From 952865a86ebb08f97263cfdbfe38b7adc20e4560 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Mon, 19 Jul 2021 00:01:24 +0200 Subject: Replace contents with redirect message The default development branch is now `main`. This commit only exists on `master` to point people towards that. See https://gitlab.gnome.org/GNOME/glib/-/issues/2348 for details. --- src/backends/edid-parse.c | 542 -- src/backends/edid.h | 193 - src/backends/gsm-inhibitor-flag.h | 36 - src/backends/meta-backend-private.h | 203 - src/backends/meta-backend-types.h | 69 - src/backends/meta-backend.c | 1663 ---- src/backends/meta-barrier-private.h | 66 - src/backends/meta-barrier.c | 365 - src/backends/meta-crtc-mode.c | 200 - src/backends/meta-crtc-mode.h | 93 - src/backends/meta-crtc.c | 246 - src/backends/meta-crtc.h | 77 - src/backends/meta-cursor-renderer.c | 492 -- src/backends/meta-cursor-renderer.h | 82 - src/backends/meta-cursor-sprite-xcursor.c | 371 - src/backends/meta-cursor-sprite-xcursor.h | 43 - src/backends/meta-cursor-tracker-private.h | 56 - src/backends/meta-cursor-tracker.c | 514 -- src/backends/meta-cursor.c | 240 - src/backends/meta-cursor.h | 85 - src/backends/meta-dbus-session-watcher.c | 237 - src/backends/meta-dbus-session-watcher.h | 52 - src/backends/meta-display-config-shared.h | 39 - src/backends/meta-dnd-private.h | 41 - src/backends/meta-egl-ext.h | 103 - src/backends/meta-egl.c | 1154 --- src/backends/meta-egl.h | 272 - src/backends/meta-gles3-table.h | 36 - src/backends/meta-gles3.c | 163 - src/backends/meta-gles3.h | 83 - src/backends/meta-gpu.c | 226 - src/backends/meta-gpu.h | 72 - src/backends/meta-idle-manager.c | 379 - src/backends/meta-idle-manager.h | 39 - src/backends/meta-idle-monitor-private.h | 53 - src/backends/meta-idle-monitor.c | 530 -- src/backends/meta-input-device-private.h | 48 - src/backends/meta-input-device.c | 138 - src/backends/meta-input-mapper-private.h | 52 - src/backends/meta-input-mapper.c | 986 --- src/backends/meta-input-settings-dummy.c | 295 - src/backends/meta-input-settings-dummy.h | 34 - src/backends/meta-input-settings-private.h | 204 - src/backends/meta-input-settings.c | 1762 ---- src/backends/meta-keymap-utils.c | 56 - src/backends/meta-keymap-utils.h | 28 - src/backends/meta-logical-monitor.c | 343 - src/backends/meta-logical-monitor.h | 107 - src/backends/meta-monitor-config-manager.c | 1899 ----- src/backends/meta-monitor-config-manager.h | 201 - src/backends/meta-monitor-config-migration.c | 1233 --- src/backends/meta-monitor-config-migration.h | 41 - src/backends/meta-monitor-config-store.c | 1683 ---- src/backends/meta-monitor-config-store.h | 60 - src/backends/meta-monitor-manager-dummy.c | 816 -- src/backends/meta-monitor-manager-dummy.h | 48 - src/backends/meta-monitor-manager-private.h | 439 - src/backends/meta-monitor-manager.c | 3471 -------- src/backends/meta-monitor-transform.c | 128 - src/backends/meta-monitor-transform.h | 74 - src/backends/meta-monitor.c | 1988 ----- src/backends/meta-monitor.h | 280 - src/backends/meta-orientation-manager.c | 335 - src/backends/meta-orientation-manager.h | 44 - src/backends/meta-output.c | 465 -- src/backends/meta-output.h | 192 - src/backends/meta-pointer-constraint.c | 146 - src/backends/meta-pointer-constraint.h | 77 - src/backends/meta-profiler.c | 203 - src/backends/meta-profiler.h | 41 - .../meta-remote-access-controller-private.h | 38 - src/backends/meta-remote-access-controller.c | 283 - src/backends/meta-remote-desktop-session.c | 1725 ---- src/backends/meta-remote-desktop-session.h | 60 - src/backends/meta-remote-desktop.c | 342 - src/backends/meta-remote-desktop.h | 54 - src/backends/meta-renderer-view.c | 247 - src/backends/meta-renderer-view.h | 34 - src/backends/meta-renderer.c | 405 - src/backends/meta-renderer.h | 78 - src/backends/meta-screen-cast-area-stream-src.c | 652 -- src/backends/meta-screen-cast-area-stream-src.h | 37 - src/backends/meta-screen-cast-area-stream.c | 181 - src/backends/meta-screen-cast-area-stream.h | 49 - src/backends/meta-screen-cast-monitor-stream-src.c | 793 -- src/backends/meta-screen-cast-monitor-stream-src.h | 40 - src/backends/meta-screen-cast-monitor-stream.c | 295 - src/backends/meta-screen-cast-monitor-stream.h | 50 - src/backends/meta-screen-cast-session.c | 825 -- src/backends/meta-screen-cast-session.h | 72 - src/backends/meta-screen-cast-stream-src.c | 1237 --- src/backends/meta-screen-cast-stream-src.h | 117 - src/backends/meta-screen-cast-stream.c | 383 - src/backends/meta-screen-cast-stream.h | 74 - src/backends/meta-screen-cast-virtual-stream-src.c | 612 -- src/backends/meta-screen-cast-virtual-stream-src.h | 38 - src/backends/meta-screen-cast-virtual-stream.c | 121 - src/backends/meta-screen-cast-virtual-stream.h | 40 - src/backends/meta-screen-cast-window-stream-src.c | 614 -- src/backends/meta-screen-cast-window-stream-src.h | 37 - src/backends/meta-screen-cast-window-stream.c | 285 - src/backends/meta-screen-cast-window-stream.h | 46 - src/backends/meta-screen-cast-window.c | 99 - src/backends/meta-screen-cast-window.h | 93 - src/backends/meta-screen-cast.c | 385 - src/backends/meta-screen-cast.h | 69 - src/backends/meta-settings-private.h | 81 - src/backends/meta-settings.c | 559 -- src/backends/meta-stage-impl-private.h | 76 - src/backends/meta-stage-impl.c | 756 -- src/backends/meta-stage-private.h | 79 - src/backends/meta-stage-view-private.h | 51 - src/backends/meta-stage-view.c | 204 - src/backends/meta-stage.c | 485 -- src/backends/meta-viewport-info.c | 223 - src/backends/meta-viewport-info.h | 61 - src/backends/meta-virtual-monitor.c | 238 - src/backends/meta-virtual-monitor.h | 71 - src/backends/native/dbus-utils.c | 107 - src/backends/native/dbus-utils.h | 32 - src/backends/native/gen-default-modes.py | 127 - src/backends/native/meta-backend-native-private.h | 35 - src/backends/native/meta-backend-native-types.h | 41 - src/backends/native/meta-backend-native.c | 768 -- src/backends/native/meta-backend-native.h | 55 - src/backends/native/meta-barrier-native.c | 652 -- src/backends/native/meta-barrier-native.h | 52 - src/backends/native/meta-clutter-backend-native.c | 111 - src/backends/native/meta-clutter-backend-native.h | 38 - src/backends/native/meta-cogl-utils.c | 85 - src/backends/native/meta-cogl-utils.h | 38 - src/backends/native/meta-crtc-kms.c | 386 - src/backends/native/meta-crtc-kms.h | 83 - src/backends/native/meta-crtc-mode-kms.c | 81 - src/backends/native/meta-crtc-mode-kms.h | 39 - src/backends/native/meta-crtc-mode-virtual.c | 70 - src/backends/native/meta-crtc-mode-virtual.h | 34 - src/backends/native/meta-crtc-native.c | 44 - src/backends/native/meta-crtc-native.h | 41 - src/backends/native/meta-crtc-virtual.c | 60 - src/backends/native/meta-crtc-virtual.h | 32 - src/backends/native/meta-cursor-renderer-native.c | 1878 ----- src/backends/native/meta-cursor-renderer-native.h | 42 - src/backends/native/meta-device-pool-private.h | 35 - src/backends/native/meta-device-pool.c | 390 - src/backends/native/meta-device-pool.h | 68 - src/backends/native/meta-drm-buffer-dumb.c | 287 - src/backends/native/meta-drm-buffer-dumb.h | 45 - src/backends/native/meta-drm-buffer-gbm.c | 474 -- src/backends/native/meta-drm-buffer-gbm.h | 49 - src/backends/native/meta-drm-buffer-import.c | 209 - src/backends/native/meta-drm-buffer-import.h | 55 - src/backends/native/meta-drm-buffer-private.h | 64 - src/backends/native/meta-drm-buffer.c | 296 - src/backends/native/meta-drm-buffer.h | 53 - src/backends/native/meta-gpu-kms.c | 422 - src/backends/native/meta-gpu-kms.h | 74 - src/backends/native/meta-input-device-native.c | 1599 ---- src/backends/native/meta-input-device-native.h | 162 - .../native/meta-input-device-tool-native.c | 183 - .../native/meta-input-device-tool-native.h | 90 - src/backends/native/meta-input-settings-native.c | 876 -- src/backends/native/meta-input-settings-native.h | 56 - src/backends/native/meta-input-thread.h | 33 - src/backends/native/meta-keymap-native.c | 152 - src/backends/native/meta-keymap-native.h | 43 - src/backends/native/meta-kms-connector-private.h | 54 - src/backends/native/meta-kms-connector.c | 700 -- src/backends/native/meta-kms-connector.h | 77 - src/backends/native/meta-kms-crtc-private.h | 51 - src/backends/native/meta-kms-crtc.c | 399 - src/backends/native/meta-kms-crtc.h | 79 - src/backends/native/meta-kms-device-private.h | 36 - src/backends/native/meta-kms-device.c | 439 - src/backends/native/meta-kms-device.h | 69 - src/backends/native/meta-kms-impl-device-atomic.c | 1202 --- src/backends/native/meta-kms-impl-device-atomic.h | 29 - src/backends/native/meta-kms-impl-device-dummy.c | 127 - src/backends/native/meta-kms-impl-device-dummy.h | 30 - src/backends/native/meta-kms-impl-device-simple.c | 1678 ---- src/backends/native/meta-kms-impl-device-simple.h | 29 - src/backends/native/meta-kms-impl-device.c | 1070 --- src/backends/native/meta-kms-impl-device.h | 178 - src/backends/native/meta-kms-impl.c | 204 - src/backends/native/meta-kms-impl.h | 52 - src/backends/native/meta-kms-mode-private.h | 34 - src/backends/native/meta-kms-mode.c | 143 - src/backends/native/meta-kms-mode.h | 47 - src/backends/native/meta-kms-page-flip-private.h | 65 - src/backends/native/meta-kms-page-flip.c | 288 - src/backends/native/meta-kms-plane-private.h | 64 - src/backends/native/meta-kms-plane.c | 537 -- src/backends/native/meta-kms-plane.h | 65 - src/backends/native/meta-kms-private.h | 65 - src/backends/native/meta-kms-types.h | 75 - src/backends/native/meta-kms-update-private.h | 157 - src/backends/native/meta-kms-update.c | 645 -- src/backends/native/meta-kms-update.h | 181 - src/backends/native/meta-kms-utils.c | 103 - src/backends/native/meta-kms-utils.h | 43 - src/backends/native/meta-kms.c | 754 -- src/backends/native/meta-kms.h | 74 - src/backends/native/meta-launcher.c | 410 - src/backends/native/meta-launcher.h | 40 - src/backends/native/meta-monitor-manager-native.c | 825 -- src/backends/native/meta-monitor-manager-native.h | 49 - src/backends/native/meta-onscreen-native.c | 2137 ----- src/backends/native/meta-onscreen-native.h | 59 - src/backends/native/meta-output-kms.c | 414 - src/backends/native/meta-output-kms.h | 55 - src/backends/native/meta-output-native.c | 43 - src/backends/native/meta-output-native.h | 39 - src/backends/native/meta-output-virtual.c | 80 - src/backends/native/meta-output-virtual.h | 36 - .../native/meta-pointer-constraint-native.c | 694 -- .../native/meta-pointer-constraint-native.h | 46 - src/backends/native/meta-renderer-native-gles3.c | 160 - src/backends/native/meta-renderer-native-gles3.h | 40 - src/backends/native/meta-renderer-native-private.h | 115 - src/backends/native/meta-renderer-native.c | 2264 ----- src/backends/native/meta-renderer-native.h | 71 - src/backends/native/meta-seat-impl.c | 3542 -------- src/backends/native/meta-seat-impl.h | 254 - src/backends/native/meta-seat-native.c | 634 -- src/backends/native/meta-seat-native.h | 133 - src/backends/native/meta-stage-native.c | 191 - src/backends/native/meta-stage-native.h | 37 - src/backends/native/meta-udev.c | 274 - src/backends/native/meta-udev.h | 49 - .../native/meta-virtual-input-device-native.c | 1110 --- .../native/meta-virtual-input-device-native.h | 31 - src/backends/native/meta-virtual-monitor-native.c | 80 - src/backends/native/meta-virtual-monitor-native.h | 45 - src/backends/native/meta-xkb-utils.c | 137 - src/backends/native/meta-xkb-utils.h | 43 - src/backends/x11/cm/meta-backend-x11-cm.c | 550 -- src/backends/x11/cm/meta-backend-x11-cm.h | 31 - src/backends/x11/cm/meta-cursor-sprite-xfixes.c | 231 - src/backends/x11/cm/meta-cursor-sprite-xfixes.h | 36 - src/backends/x11/cm/meta-renderer-x11-cm.c | 113 - src/backends/x11/cm/meta-renderer-x11-cm.h | 42 - src/backends/x11/meta-backend-x11.c | 996 --- src/backends/x11/meta-backend-x11.h | 63 - src/backends/x11/meta-barrier-x11.c | 212 - src/backends/x11/meta-barrier-x11.h | 42 - src/backends/x11/meta-clutter-backend-x11.c | 745 -- src/backends/x11/meta-clutter-backend-x11.h | 96 - src/backends/x11/meta-crtc-xrandr.c | 308 - src/backends/x11/meta-crtc-xrandr.h | 57 - src/backends/x11/meta-cursor-renderer-x11.c | 114 - src/backends/x11/meta-cursor-renderer-x11.h | 52 - src/backends/x11/meta-cursor-tracker-x11.c | 186 - src/backends/x11/meta-cursor-tracker-x11.h | 34 - src/backends/x11/meta-event-x11.c | 114 - src/backends/x11/meta-event-x11.h | 33 - src/backends/x11/meta-gpu-xrandr.c | 277 - src/backends/x11/meta-gpu-xrandr.h | 42 - src/backends/x11/meta-input-device-tool-x11.c | 56 - src/backends/x11/meta-input-device-tool-x11.h | 51 - src/backends/x11/meta-input-device-x11.c | 795 -- src/backends/x11/meta-input-device-x11.h | 102 - src/backends/x11/meta-input-settings-x11.c | 948 --- src/backends/x11/meta-input-settings-x11.h | 49 - src/backends/x11/meta-keymap-x11.c | 949 --- src/backends/x11/meta-keymap-x11.h | 61 - src/backends/x11/meta-monitor-manager-xrandr.c | 1151 --- src/backends/x11/meta-monitor-manager-xrandr.h | 41 - src/backends/x11/meta-output-xrandr.c | 987 --- src/backends/x11/meta-output-xrandr.h | 52 - src/backends/x11/meta-renderer-x11.c | 107 - src/backends/x11/meta-renderer-x11.h | 42 - src/backends/x11/meta-seat-x11.c | 2422 ------ src/backends/x11/meta-seat-x11.h | 44 - src/backends/x11/meta-stage-x11.c | 853 -- src/backends/x11/meta-stage-x11.h | 96 - src/backends/x11/meta-virtual-input-device-x11.c | 253 - src/backends/x11/meta-virtual-input-device-x11.h | 31 - src/backends/x11/meta-xkb-a11y-x11.c | 339 - src/backends/x11/meta-xkb-a11y-x11.h | 39 - src/backends/x11/nested/meta-backend-x11-nested.c | 320 - src/backends/x11/nested/meta-backend-x11-nested.h | 40 - .../x11/nested/meta-cursor-renderer-x11-nested.c | 91 - .../x11/nested/meta-cursor-renderer-x11-nested.h | 38 - src/backends/x11/nested/meta-renderer-x11-nested.c | 248 - src/backends/x11/nested/meta-renderer-x11-nested.h | 37 - src/backends/x11/nested/meta-stage-x11-nested.c | 236 - src/backends/x11/nested/meta-stage-x11-nested.h | 35 - src/compositor/README | 70 - src/compositor/clutter-utils.c | 188 - src/compositor/clutter-utils.h | 40 - src/compositor/cogl-utils.c | 114 - src/compositor/cogl-utils.h | 39 - src/compositor/compositor-private.h | 101 - src/compositor/compositor.c | 1581 ---- src/compositor/meta-background-actor-private.h | 10 - src/compositor/meta-background-actor.c | 218 - src/compositor/meta-background-content-private.h | 16 - src/compositor/meta-background-content.c | 1312 --- src/compositor/meta-background-group.c | 66 - src/compositor/meta-background-image.c | 370 - src/compositor/meta-background-private.h | 14 - src/compositor/meta-background.c | 1018 --- src/compositor/meta-compositor-native.c | 151 - src/compositor/meta-compositor-native.h | 33 - src/compositor/meta-compositor-server.c | 100 - src/compositor/meta-compositor-server.h | 38 - src/compositor/meta-compositor-x11.c | 530 -- src/compositor/meta-compositor-x11.h | 39 - src/compositor/meta-cullable.c | 245 - src/compositor/meta-cullable.h | 61 - src/compositor/meta-dnd-actor-private.h | 48 - src/compositor/meta-dnd-actor.c | 242 - src/compositor/meta-dnd.c | 336 - src/compositor/meta-feedback-actor-private.h | 70 - src/compositor/meta-feedback-actor.c | 285 - src/compositor/meta-later-private.h | 28 - src/compositor/meta-later.c | 352 - src/compositor/meta-module.c | 193 - src/compositor/meta-module.h | 55 - src/compositor/meta-plugin-manager.c | 419 - src/compositor/meta-plugin-manager.h | 105 - src/compositor/meta-plugin.c | 223 - src/compositor/meta-shadow-factory.c | 1066 --- src/compositor/meta-shaped-texture-private.h | 76 - src/compositor/meta-shaped-texture.c | 1676 ---- src/compositor/meta-surface-actor-wayland.c | 198 - src/compositor/meta-surface-actor-wayland.h | 63 - src/compositor/meta-surface-actor-x11.c | 422 - src/compositor/meta-surface-actor-x11.h | 62 - src/compositor/meta-surface-actor.c | 698 -- src/compositor/meta-surface-actor.h | 72 - src/compositor/meta-sync-ring.c | 592 -- src/compositor/meta-sync-ring.h | 13 - src/compositor/meta-texture-tower.c | 484 -- src/compositor/meta-texture-tower.h | 68 - src/compositor/meta-window-actor-private.h | 102 - src/compositor/meta-window-actor-wayland.c | 171 - src/compositor/meta-window-actor-wayland.h | 37 - src/compositor/meta-window-actor-x11.c | 1693 ---- src/compositor/meta-window-actor-x11.h | 47 - src/compositor/meta-window-actor.c | 1559 ---- src/compositor/meta-window-group-private.h | 23 - src/compositor/meta-window-group.c | 222 - src/compositor/meta-window-shape.c | 259 - src/compositor/plugins/default.c | 923 --- src/compositor/plugins/meson.build | 20 - src/compositor/region-utils.c | 458 -- src/compositor/region-utils.h | 119 - src/core/bell.c | 209 - src/core/bell.h | 43 - src/core/boxes-private.h | 288 - src/core/boxes.c | 2183 ----- src/core/constraints.c | 1878 ----- src/core/constraints.h | 39 - src/core/delete.c | 124 - src/core/display-private.h | 434 - src/core/display.c | 3852 --------- src/core/edge-resistance.c | 1310 --- src/core/edge-resistance.h | 40 - src/core/events.c | 509 -- src/core/events.h | 31 - src/core/frame.c | 427 - src/core/frame.h | 85 - src/core/keybindings-private.h | 160 - src/core/keybindings.c | 4578 ----------- src/core/meta-accel-parse.c | 358 - src/core/meta-accel-parse.h | 44 - src/core/meta-anonymous-file.c | 368 - src/core/meta-anonymous-file.h | 53 - src/core/meta-border.c | 154 - src/core/meta-border.h | 84 - src/core/meta-clipboard-manager.c | 179 - src/core/meta-clipboard-manager.h | 30 - src/core/meta-close-dialog-default-private.h | 37 - src/core/meta-close-dialog-default.c | 281 - src/core/meta-close-dialog.c | 144 - src/core/meta-context-main.c | 702 -- src/core/meta-context-main.h | 31 - src/core/meta-context-private.h | 63 - src/core/meta-context.c | 568 -- src/core/meta-fraction.c | 134 - src/core/meta-fraction.h | 31 - src/core/meta-gesture-tracker-private.h | 70 - src/core/meta-gesture-tracker.c | 581 -- ...meta-inhibit-shortcuts-dialog-default-private.h | 34 - src/core/meta-inhibit-shortcuts-dialog-default.c | 132 - src/core/meta-inhibit-shortcuts-dialog.c | 103 - src/core/meta-launch-context.c | 269 - src/core/meta-pad-action-mapper.c | 860 -- src/core/meta-pad-action-mapper.h | 46 - src/core/meta-private-enums.h | 31 - src/core/meta-selection-private.h | 32 - src/core/meta-selection-source-memory.c | 128 - src/core/meta-selection-source-remote.c | 144 - src/core/meta-selection-source-remote.h | 43 - src/core/meta-selection-source.c | 166 - src/core/meta-selection.c | 415 - src/core/meta-sound-player.c | 296 - src/core/meta-workspace-manager-private.h | 96 - src/core/meta-workspace-manager.c | 1060 --- src/core/mutter.c | 97 - src/core/place.c | 942 --- src/core/place.h | 39 - src/core/prefs-private.h | 26 - src/core/prefs.c | 2229 ----- src/core/restart-helper.c | 84 - src/core/restart.c | 201 - src/core/stack-tracker.c | 1293 --- src/core/stack-tracker.h | 87 - src/core/stack.c | 1340 --- src/core/stack.h | 406 - src/core/startup-notification-private.h | 52 - src/core/startup-notification.c | 696 -- src/core/util-private.h | 61 - src/core/util.c | 796 -- src/core/window-private.h | 888 -- src/core/window.c | 8665 -------------------- src/core/workspace-private.h | 103 - src/core/workspace.c | 1477 ---- src/libmutter.pc.in | 14 - src/meson.build | 1102 --- src/meta-private-enum-types.c.in | 39 - src/meta-private-enum-types.h.in | 25 - src/meta/barrier.h | 124 - src/meta/boxes.h | 159 - src/meta/common.h | 553 -- src/meta/compositor-mutter.h | 60 - src/meta/compositor.h | 165 - src/meta/display.h | 315 - src/meta/group.h | 65 - src/meta/keybindings.h | 46 - src/meta/main.h | 50 - src/meta/meson.build | 75 - src/meta/meta-backend.h | 76 - src/meta/meta-background-actor.h | 50 - src/meta/meta-background-content.h | 74 - src/meta/meta-background-group.h | 26 - src/meta/meta-background-image.h | 69 - src/meta/meta-background.h | 74 - src/meta/meta-close-dialog.h | 65 - src/meta/meta-context.h | 101 - src/meta/meta-cursor-tracker.h | 63 - src/meta/meta-dnd.h | 34 - src/meta/meta-enum-types.c.in | 39 - src/meta/meta-enum-types.h.in | 27 - src/meta/meta-enums.h | 30 - src/meta/meta-idle-monitor.h | 56 - src/meta/meta-inhibit-shortcuts-dialog.h | 55 - src/meta/meta-later.h | 53 - src/meta/meta-launch-context.h | 39 - src/meta/meta-monitor-manager.h | 68 - src/meta/meta-plugin.h | 370 - src/meta/meta-remote-access-controller.h | 63 - src/meta/meta-selection-source-memory.h | 39 - src/meta/meta-selection-source.h | 85 - src/meta/meta-selection.h | 70 - src/meta/meta-settings.h | 34 - src/meta/meta-shadow-factory.h | 135 - src/meta/meta-shaped-texture.h | 60 - src/meta/meta-sound-player.h | 46 - src/meta/meta-stage.h | 34 - src/meta/meta-startup-notification.h | 76 - src/meta/meta-wayland-client.h | 67 - src/meta/meta-window-actor.h | 67 - src/meta/meta-window-group.h | 16 - src/meta/meta-window-shape.h | 76 - src/meta/meta-workspace-manager.h | 78 - src/meta/meta-x11-display.h | 73 - src/meta/meta-x11-errors.h | 41 - src/meta/prefs.h | 485 -- src/meta/theme.h | 41 - src/meta/types.h | 49 - src/meta/util.h | 236 - src/meta/window.h | 449 - src/meta/workspace.h | 73 - src/org.freedesktop.login1.xml | 46 - src/org.gnome.Mutter.DisplayConfig.xml | 473 -- src/org.gnome.Mutter.IdleMonitor.xml | 37 - src/org.gnome.Mutter.RemoteDesktop.xml | 351 - src/org.gnome.Mutter.ScreenCast.xml | 220 - src/tests/README | 93 - src/tests/anonymous-file.c | 282 - src/tests/boxes-tests.c | 1389 ---- src/tests/boxes-tests.h | 23 - src/tests/clutter-test-utils.c | 473 -- src/tests/clutter-test-utils.h | 174 - src/tests/clutter/README | 38 - .../accessibility/cally-atkcomponent-example.c | 95 - .../accessibility/cally-atkeditabletext-example.c | 266 - .../accessibility/cally-atkevents-example.c | 194 - .../clutter/accessibility/cally-atktext-example.c | 253 - .../clutter/accessibility/cally-clone-example.c | 112 - .../clutter/accessibility/cally-examples-util.c | 148 - .../clutter/accessibility/cally-examples-util.h | 26 - src/tests/clutter/accessibility/meson.build | 39 - src/tests/clutter/clutter-1.0.suppressions | 165 - src/tests/clutter/conform/actor-clone.c | 68 - src/tests/clutter/conform/actor-destroy.c | 200 - src/tests/clutter/conform/actor-graph.c | 552 -- src/tests/clutter/conform/actor-invariants.c | 368 - src/tests/clutter/conform/actor-iter.c | 220 - src/tests/clutter/conform/actor-layout.c | 98 - src/tests/clutter/conform/actor-meta.c | 42 - .../clutter/conform/actor-offscreen-redirect.c | 452 - src/tests/clutter/conform/actor-paint-opacity.c | 151 - src/tests/clutter/conform/actor-pick.c | 231 - src/tests/clutter/conform/actor-pivot-point.c | 52 - src/tests/clutter/conform/actor-shader-effect.c | 301 - src/tests/clutter/conform/actor-size.c | 218 - src/tests/clutter/conform/binding-pool.c | 311 - src/tests/clutter/conform/cally-text.c | 338 - src/tests/clutter/conform/color.c | 321 - src/tests/clutter/conform/frame-clock-timeline.c | 209 - src/tests/clutter/conform/frame-clock.c | 846 -- src/tests/clutter/conform/interval.c | 119 - src/tests/clutter/conform/meson.build | 79 - src/tests/clutter/conform/path.c | 740 -- src/tests/clutter/conform/script-parser.c | 303 - .../clutter/conform/scripts/test-script-child.json | 21 - .../conform/scripts/test-script-interval.json | 16 - .../conform/scripts/test-script-margin.json | 22 - .../clutter/conform/scripts/test-script-model.json | 17 - .../conform/scripts/test-script-named-object.json | 44 - .../scripts/test-script-object-property.json | 13 - .../conform/scripts/test-script-single.json | 10 - .../scripts/test-script-timeline-markers.json | 16 - src/tests/clutter/conform/text-cache.c | 299 - src/tests/clutter/conform/text.c | 564 -- src/tests/clutter/conform/texture-fbo.c | 227 - src/tests/clutter/conform/timeline-interpolate.c | 211 - src/tests/clutter/conform/timeline-progress.c | 117 - src/tests/clutter/conform/timeline-rewind.c | 102 - src/tests/clutter/conform/timeline.c | 365 - src/tests/clutter/conform/units.c | 133 - src/tests/clutter/interactive/light0.png | Bin 1559 -> 0 bytes src/tests/clutter/interactive/meson.build | 74 - .../interactive/meson/gen-test-unit-names.sh | 14 - src/tests/clutter/interactive/redhand.png | Bin 8250 -> 0 bytes src/tests/clutter/interactive/redhand_alpha.png | Bin 2360 -> 0 bytes src/tests/clutter/interactive/test-actors.c | 264 - src/tests/clutter/interactive/test-animation.c | 131 - .../clutter/interactive/test-bind-constraint.c | 258 - src/tests/clutter/interactive/test-binding-pool.c | 326 - src/tests/clutter/interactive/test-cairo-clock.c | 125 - src/tests/clutter/interactive/test-cairo-flowers.c | 261 - .../clutter/interactive/test-cogl-multitexture.c | 254 - .../clutter/interactive/test-cogl-offscreen.c | 353 - .../clutter/interactive/test-cogl-point-sprites.c | 282 - .../clutter/interactive/test-cogl-shader-glsl.c | 350 - .../clutter/interactive/test-cogl-tex-convert.c | 245 - .../clutter/interactive/test-cogl-tex-polygon.c | 455 - src/tests/clutter/interactive/test-cogl-tex-tile.c | 235 - src/tests/clutter/interactive/test-content.c | 242 - src/tests/clutter/interactive/test-devices.c | 234 - src/tests/clutter/interactive/test-easing.c | 252 - src/tests/clutter/interactive/test-events.c | 477 -- src/tests/clutter/interactive/test-grab.c | 283 - src/tests/clutter/interactive/test-image.c | 261 - .../clutter/interactive/test-keyframe-transition.c | 115 - src/tests/clutter/interactive/test-layout.c | 684 -- src/tests/clutter/interactive/test-main.c | 227 - .../clutter/interactive/test-path-constraint.c | 138 - src/tests/clutter/interactive/test-rotate-zoom.c | 100 - src/tests/clutter/interactive/test-script.c | 154 - src/tests/clutter/interactive/test-script.json | 54 - .../clutter/interactive/test-shader-effects.c | 88 - src/tests/clutter/interactive/test-stage-sizing.c | 89 - src/tests/clutter/interactive/test-state-script.c | 46 - src/tests/clutter/interactive/test-swipe-action.c | 199 - src/tests/clutter/interactive/test-text-field.c | 339 - src/tests/clutter/interactive/test-text.c | 102 - src/tests/clutter/interactive/test-touch-events.c | 185 - src/tests/clutter/interactive/wrapper.sh.in | 15 - src/tests/clutter/meson.build | 11 - src/tests/clutter/micro-bench/meson.build | 31 - src/tests/clutter/micro-bench/test-cogl-perf.c | 150 - src/tests/clutter/micro-bench/test-picking.c | 119 - src/tests/clutter/micro-bench/test-random-text.c | 106 - src/tests/clutter/micro-bench/test-text-perf.c | 190 - src/tests/clutter/micro-bench/test-text.c | 123 - src/tests/clutter/performance/create-report.rb | 179 - src/tests/clutter/performance/joblist | 27 - src/tests/clutter/performance/makejobs.rb | 24 - src/tests/clutter/performance/meson.build | 34 - src/tests/clutter/performance/test-common.h | 144 - src/tests/clutter/performance/test-picking.c | 109 - src/tests/clutter/performance/test-text-perf.c | 166 - src/tests/clutter/test-utils.h | 30 - src/tests/headless-start-test.c | 180 - src/tests/kms-utils-unit-tests.c | 267 - src/tests/meson.build | 351 - src/tests/meta-backend-test.c | 95 - src/tests/meta-backend-test.h | 37 - src/tests/meta-context-test.c | 333 - src/tests/meta-gpu-test.c | 55 - src/tests/meta-gpu-test.h | 26 - src/tests/meta-monitor-manager-test.c | 490 -- src/tests/meta-monitor-manager-test.h | 81 - src/tests/meta-ref-test.c | 610 -- src/tests/meta-ref-test.h | 39 - src/tests/meta-test-utils-private.h | 26 - src/tests/meta-test-utils.c | 567 -- src/tests/meta-test-utils.h | 100 - src/tests/meta-test/meson.build | 9 - src/tests/meta-test/meta-context-test.h | 56 - src/tests/meta-wayland-test-driver.c | 160 - src/tests/meta-wayland-test-driver.h | 30 - src/tests/migration/basic-new.xml | 78 - src/tests/migration/basic-old.xml | 72 - src/tests/migration/first-rotated-new.xml | 44 - src/tests/migration/first-rotated-old.xml | 37 - src/tests/migration/oneoff-new-finished.xml | 31 - src/tests/migration/oneoff-new.xml | 31 - src/tests/migration/oneoff-old.xml | 26 - src/tests/migration/rotated-new-finished.xml | 27 - src/tests/migration/rotated-new.xml | 27 - src/tests/migration/rotated-old.xml | 21 - src/tests/migration/tiled-new.xml | 23 - src/tests/migration/tiled-old.xml | 37 - src/tests/migration/wiggle-new-discarded.xml | 2 - src/tests/migration/wiggle-new-finished.xml | 27 - src/tests/migration/wiggle-new.xml | 27 - src/tests/migration/wiggle-old.xml | 21 - src/tests/monitor-config-migration-unit-tests.c | 136 - src/tests/monitor-config-migration-unit-tests.h | 25 - src/tests/monitor-configs/first-rotated.xml | 47 - src/tests/monitor-configs/fractional-scale.xml | 23 - .../high-precision-fractional-scale.xml | 23 - src/tests/monitor-configs/interlaced.xml | 23 - src/tests/monitor-configs/lid-scale.xml | 23 - src/tests/monitor-configs/lid-switch.xml | 91 - src/tests/monitor-configs/mirrored.xml | 35 - .../non-preferred-tiled-custom-resolution.xml | 22 - src/tests/monitor-configs/oneoff.xml | 31 - src/tests/monitor-configs/primary.xml | 40 - src/tests/monitor-configs/scale.xml | 23 - src/tests/monitor-configs/second-rotated-tiled.xml | 43 - src/tests/monitor-configs/second-rotated.xml | 43 - src/tests/monitor-configs/single.xml | 22 - .../monitor-configs/tiled-custom-resolution.xml | 23 - src/tests/monitor-configs/tiled.xml | 23 - src/tests/monitor-configs/underscanning.xml | 23 - src/tests/monitor-configs/vertical.xml | 39 - src/tests/monitor-store-unit-tests.c | 864 -- src/tests/monitor-store-unit-tests.h | 25 - src/tests/monitor-test-utils.c | 780 -- src/tests/monitor-test-utils.h | 206 - src/tests/monitor-transform-tests.c | 101 - src/tests/monitor-transform-tests.h | 23 - src/tests/monitor-unit-tests.c | 5868 ------------- src/tests/monitor-unit-tests.h | 36 - src/tests/mutter-all.test.in | 6 - src/tests/native-headless.c | 47 - src/tests/native-persistent-virtual-monitor.c | 100 - src/tests/native-screen-cast.c | 86 - src/tests/native-screen-cast.h | 26 - src/tests/native-virtual-monitor.c | 135 - src/tests/native-virtual-monitor.h | 26 - src/tests/ref-test-sanity.c | 148 - ...ackends_native_virtual-monitor_create_0.ref.png | Bin 3509 -> 0 bytes ...ackends_native_virtual-monitor_create_1.ref.png | Bin 2610 -> 0 bytes .../ref-tests/tests_ref-test_sanity_0.ref.png | Bin 6749 -> 0 bytes .../ref-tests/tests_ref-test_sanity_1.ref.png | Bin 5402 -> 0 bytes src/tests/screen-cast-client.c | 572 -- src/tests/stacking/basic-wayland.metatest | 22 - src/tests/stacking/basic-x11.metatest | 19 - src/tests/stacking/client-side-decorated.metatest | 22 - .../closed-transient-no-default-focus.metatest | 29 - ...ransient-no-input-no-take-focus-parent.metatest | 23 - ...ansient-no-input-no-take-focus-parents.metatest | 30 - ...parent-delayed-focus-default-cancelled.metatest | 37 - .../closed-transient-no-input-parent.metatest | 31 - ...parents-queued-default-focus-destroyed.metatest | 44 - .../closed-transient-no-input-parents.metatest | 47 - ...osed-transient-only-take-focus-parents.metatest | 36 - src/tests/stacking/closed-transient.metatest | 19 - src/tests/stacking/default-size.metatest | 36 - src/tests/stacking/fullscreen-maximize.metatest | 73 - src/tests/stacking/map-fixed-size.metatest | 75 - src/tests/stacking/minimized.metatest | 18 - src/tests/stacking/mixed-windows.metatest | 26 - src/tests/stacking/modals.metatest | 32 - src/tests/stacking/override-redirect.metatest | 19 - src/tests/stacking/restore-position.metatest | 73 - src/tests/stacking/restore-size.metatest | 95 - .../stacking/set-override-redirect-parent.metatest | 37 - src/tests/stacking/set-parent-exported.metatest | 15 - src/tests/stacking/set-parent.metatest | 14 - src/tests/stacking/unmaximize-new-size.metatest | 22 - src/tests/stage-view-tests.c | 1171 --- src/tests/test-client.c | 944 --- src/tests/test-runner.c | 1202 --- src/tests/unit-tests.c | 258 - src/tests/unit-tests.h | 25 - .../wayland-test-clients/invalid-subsurfaces.c | 165 - .../invalid-xdg-shell-actions.c | 280 - src/tests/wayland-test-clients/meson.build | 70 - .../subsurface-remap-toplevel.c | 397 - src/tests/wayland-test-clients/test-driver.xml | 13 - .../wayland-test-client-utils.c | 88 - .../wayland-test-client-utils.h | 8 - src/tests/wayland-test-clients/xdg-apply-limits.c | 408 - src/tests/wayland-unit-tests.c | 264 - src/tests/wayland-unit-tests.h | 25 - src/ui/frames.c | 1869 ----- src/ui/frames.h | 148 - src/ui/theme-private.h | 281 - src/ui/theme.c | 1397 ---- src/ui/ui.c | 281 - src/ui/ui.h | 79 - src/wayland/meta-cursor-sprite-wayland.c | 75 - src/wayland/meta-cursor-sprite-wayland.h | 35 - src/wayland/meta-pointer-confinement-wayland.c | 267 - src/wayland/meta-pointer-confinement-wayland.h | 56 - src/wayland/meta-pointer-lock-wayland.c | 104 - src/wayland/meta-pointer-lock-wayland.h | 42 - .../meta-selection-source-wayland-private.h | 39 - src/wayland/meta-selection-source-wayland.c | 170 - src/wayland/meta-wayland-activation.c | 333 - src/wayland/meta-wayland-activation.h | 32 - src/wayland/meta-wayland-actor-surface.c | 460 -- src/wayland/meta-wayland-actor-surface.h | 54 - src/wayland/meta-wayland-buffer.c | 852 -- src/wayland/meta-wayland-buffer.h | 96 - src/wayland/meta-wayland-client.c | 335 - src/wayland/meta-wayland-cursor-surface.c | 401 - src/wayland/meta-wayland-cursor-surface.h | 52 - .../meta-wayland-data-device-primary-legacy.c | 359 - .../meta-wayland-data-device-primary-legacy.h | 55 - src/wayland/meta-wayland-data-device-primary.c | 358 - src/wayland/meta-wayland-data-device-primary.h | 55 - src/wayland/meta-wayland-data-device.c | 1147 --- src/wayland/meta-wayland-data-device.h | 91 - .../meta-wayland-data-offer-primary-legacy.c | 139 - .../meta-wayland-data-offer-primary-legacy.h | 31 - src/wayland/meta-wayland-data-offer-primary.c | 139 - src/wayland/meta-wayland-data-offer-primary.h | 31 - src/wayland/meta-wayland-data-offer.c | 327 - src/wayland/meta-wayland-data-offer.h | 51 - .../meta-wayland-data-source-primary-legacy.c | 117 - .../meta-wayland-data-source-primary-legacy.h | 37 - src/wayland/meta-wayland-data-source-primary.c | 117 - src/wayland/meta-wayland-data-source-primary.h | 37 - src/wayland/meta-wayland-data-source.c | 523 -- src/wayland/meta-wayland-data-source.h | 112 - src/wayland/meta-wayland-dma-buf.c | 784 -- src/wayland/meta-wayland-dma-buf.h | 56 - src/wayland/meta-wayland-dnd-surface.c | 152 - src/wayland/meta-wayland-dnd-surface.h | 31 - src/wayland/meta-wayland-egl-stream.c | 367 - src/wayland/meta-wayland-egl-stream.h | 54 - src/wayland/meta-wayland-gtk-shell.c | 565 -- src/wayland/meta-wayland-gtk-shell.h | 31 - .../meta-wayland-inhibit-shortcuts-dialog.c | 187 - .../meta-wayland-inhibit-shortcuts-dialog.h | 31 - src/wayland/meta-wayland-inhibit-shortcuts.c | 188 - src/wayland/meta-wayland-inhibit-shortcuts.h | 39 - src/wayland/meta-wayland-input-device.c | 129 - src/wayland/meta-wayland-input-device.h | 48 - src/wayland/meta-wayland-keyboard.c | 873 -- src/wayland/meta-wayland-keyboard.h | 140 - src/wayland/meta-wayland-legacy-xdg-shell.c | 2105 ----- src/wayland/meta-wayland-legacy-xdg-shell.h | 53 - src/wayland/meta-wayland-outputs.c | 750 -- src/wayland/meta-wayland-outputs.h | 55 - src/wayland/meta-wayland-pointer-constraints.c | 1201 --- src/wayland/meta-wayland-pointer-constraints.h | 47 - src/wayland/meta-wayland-pointer-gesture-pinch.c | 166 - src/wayland/meta-wayland-pointer-gesture-pinch.h | 39 - src/wayland/meta-wayland-pointer-gesture-swipe.c | 162 - src/wayland/meta-wayland-pointer-gesture-swipe.h | 39 - src/wayland/meta-wayland-pointer-gestures.c | 83 - src/wayland/meta-wayland-pointer-gestures.h | 32 - src/wayland/meta-wayland-pointer.c | 1370 ---- src/wayland/meta-wayland-pointer.h | 158 - src/wayland/meta-wayland-popup.c | 308 - src/wayland/meta-wayland-popup.h | 62 - .../meta-wayland-presentation-time-private.h | 67 - src/wayland/meta-wayland-presentation-time.c | 417 - src/wayland/meta-wayland-private.h | 107 - src/wayland/meta-wayland-region.c | 105 - src/wayland/meta-wayland-region.h | 41 - src/wayland/meta-wayland-seat.c | 556 -- src/wayland/meta-wayland-seat.h | 87 - src/wayland/meta-wayland-shell-surface.c | 380 - src/wayland/meta-wayland-shell-surface.h | 68 - src/wayland/meta-wayland-subsurface.c | 612 -- src/wayland/meta-wayland-subsurface.h | 58 - src/wayland/meta-wayland-surface.c | 2133 ----- src/wayland/meta-wayland-surface.h | 399 - src/wayland/meta-wayland-tablet-cursor-surface.c | 43 - src/wayland/meta-wayland-tablet-cursor-surface.h | 33 - src/wayland/meta-wayland-tablet-manager.c | 244 - src/wayland/meta-wayland-tablet-manager.h | 53 - src/wayland/meta-wayland-tablet-pad-group.c | 385 - src/wayland/meta-wayland-tablet-pad-group.h | 73 - src/wayland/meta-wayland-tablet-pad-ring.c | 206 - src/wayland/meta-wayland-tablet-pad-ring.h | 59 - src/wayland/meta-wayland-tablet-pad-strip.c | 205 - src/wayland/meta-wayland-tablet-pad-strip.h | 59 - src/wayland/meta-wayland-tablet-pad.c | 563 -- src/wayland/meta-wayland-tablet-pad.h | 81 - src/wayland/meta-wayland-tablet-seat.c | 571 -- src/wayland/meta-wayland-tablet-seat.h | 81 - src/wayland/meta-wayland-tablet-tool.c | 912 -- src/wayland/meta-wayland-tablet-tool.h | 87 - src/wayland/meta-wayland-tablet.c | 129 - src/wayland/meta-wayland-tablet.h | 58 - src/wayland/meta-wayland-text-input-legacy.c | 633 -- src/wayland/meta-wayland-text-input-legacy.h | 43 - src/wayland/meta-wayland-text-input.c | 766 -- src/wayland/meta-wayland-text-input.h | 47 - src/wayland/meta-wayland-touch.c | 616 -- src/wayland/meta-wayland-touch.h | 78 - src/wayland/meta-wayland-types.h | 66 - src/wayland/meta-wayland-versions.h | 63 - src/wayland/meta-wayland-viewporter.c | 237 - src/wayland/meta-wayland-viewporter.h | 30 - src/wayland/meta-wayland-window-configuration.c | 131 - src/wayland/meta-wayland-window-configuration.h | 70 - src/wayland/meta-wayland-wl-shell.c | 777 -- src/wayland/meta-wayland-wl-shell.h | 33 - src/wayland/meta-wayland-xdg-foreign.c | 462 -- src/wayland/meta-wayland-xdg-foreign.h | 34 - src/wayland/meta-wayland-xdg-shell.c | 2437 ------ src/wayland/meta-wayland-xdg-shell.h | 53 - src/wayland/meta-wayland.c | 741 -- src/wayland/meta-wayland.h | 95 - src/wayland/meta-window-wayland.c | 1195 --- src/wayland/meta-window-wayland.h | 80 - src/wayland/meta-window-xwayland.c | 305 - src/wayland/meta-window-xwayland.h | 34 - src/wayland/meta-xwayland-dnd-private.h | 34 - src/wayland/meta-xwayland-dnd.c | 991 --- src/wayland/meta-xwayland-grab-keyboard.c | 346 - src/wayland/meta-xwayland-grab-keyboard.h | 41 - src/wayland/meta-xwayland-private.h | 59 - src/wayland/meta-xwayland-surface.c | 257 - src/wayland/meta-xwayland-surface.h | 38 - src/wayland/meta-xwayland.c | 1417 ---- src/wayland/meta-xwayland.h | 53 - src/wayland/protocol/gtk-primary-selection.xml | 225 - src/wayland/protocol/gtk-shell.xml | 90 - src/wayland/protocol/gtk-text-input.xml | 302 - src/x11/atomnames.h | 186 - src/x11/events.c | 1936 ----- src/x11/events.h | 31 - src/x11/group-private.h | 41 - src/x11/group-props.c | 235 - src/x11/group-props.h | 37 - src/x11/group.c | 332 - src/x11/iconcache.c | 575 -- src/x11/iconcache.h | 75 - src/x11/meta-selection-source-x11-private.h | 44 - src/x11/meta-selection-source-x11.c | 275 - src/x11/meta-startup-notification-x11.c | 377 - src/x11/meta-startup-notification-x11.h | 44 - src/x11/meta-x11-display-private.h | 261 - src/x11/meta-x11-display.c | 2320 ------ src/x11/meta-x11-errors.c | 65 - src/x11/meta-x11-selection-input-stream-private.h | 54 - src/x11/meta-x11-selection-input-stream.c | 572 -- src/x11/meta-x11-selection-output-stream-private.h | 47 - src/x11/meta-x11-selection-output-stream.c | 686 -- src/x11/meta-x11-selection-private.h | 34 - src/x11/meta-x11-selection.c | 551 -- src/x11/meta-x11-stack-private.h | 33 - src/x11/meta-x11-stack.c | 355 - src/x11/meta-x11-window-control.c | 265 - src/x11/meta-x11-window-control.h | 81 - src/x11/mutter-Xatomtype.h | 136 - src/x11/session.c | 1860 ----- src/x11/session.h | 90 - src/x11/window-props.c | 2012 ----- src/x11/window-props.h | 95 - src/x11/window-x11-private.h | 89 - src/x11/window-x11.c | 4223 ---------- src/x11/window-x11.h | 103 - src/x11/xprops.c | 1126 --- src/x11/xprops.h | 196 - 880 files changed, 265156 deletions(-) delete mode 100644 src/backends/edid-parse.c delete mode 100644 src/backends/edid.h delete mode 100644 src/backends/gsm-inhibitor-flag.h delete mode 100644 src/backends/meta-backend-private.h delete mode 100644 src/backends/meta-backend-types.h delete mode 100644 src/backends/meta-backend.c delete mode 100644 src/backends/meta-barrier-private.h delete mode 100644 src/backends/meta-barrier.c delete mode 100644 src/backends/meta-crtc-mode.c delete mode 100644 src/backends/meta-crtc-mode.h delete mode 100644 src/backends/meta-crtc.c delete mode 100644 src/backends/meta-crtc.h delete mode 100644 src/backends/meta-cursor-renderer.c delete mode 100644 src/backends/meta-cursor-renderer.h delete mode 100644 src/backends/meta-cursor-sprite-xcursor.c delete mode 100644 src/backends/meta-cursor-sprite-xcursor.h delete mode 100644 src/backends/meta-cursor-tracker-private.h delete mode 100644 src/backends/meta-cursor-tracker.c delete mode 100644 src/backends/meta-cursor.c delete mode 100644 src/backends/meta-cursor.h delete mode 100644 src/backends/meta-dbus-session-watcher.c delete mode 100644 src/backends/meta-dbus-session-watcher.h delete mode 100644 src/backends/meta-display-config-shared.h delete mode 100644 src/backends/meta-dnd-private.h delete mode 100644 src/backends/meta-egl-ext.h delete mode 100644 src/backends/meta-egl.c delete mode 100644 src/backends/meta-egl.h delete mode 100644 src/backends/meta-gles3-table.h delete mode 100644 src/backends/meta-gles3.c delete mode 100644 src/backends/meta-gles3.h delete mode 100644 src/backends/meta-gpu.c delete mode 100644 src/backends/meta-gpu.h delete mode 100644 src/backends/meta-idle-manager.c delete mode 100644 src/backends/meta-idle-manager.h delete mode 100644 src/backends/meta-idle-monitor-private.h delete mode 100644 src/backends/meta-idle-monitor.c delete mode 100644 src/backends/meta-input-device-private.h delete mode 100644 src/backends/meta-input-device.c delete mode 100644 src/backends/meta-input-mapper-private.h delete mode 100644 src/backends/meta-input-mapper.c delete mode 100644 src/backends/meta-input-settings-dummy.c delete mode 100644 src/backends/meta-input-settings-dummy.h delete mode 100644 src/backends/meta-input-settings-private.h delete mode 100644 src/backends/meta-input-settings.c delete mode 100644 src/backends/meta-keymap-utils.c delete mode 100644 src/backends/meta-keymap-utils.h delete mode 100644 src/backends/meta-logical-monitor.c delete mode 100644 src/backends/meta-logical-monitor.h delete mode 100644 src/backends/meta-monitor-config-manager.c delete mode 100644 src/backends/meta-monitor-config-manager.h delete mode 100644 src/backends/meta-monitor-config-migration.c delete mode 100644 src/backends/meta-monitor-config-migration.h delete mode 100644 src/backends/meta-monitor-config-store.c delete mode 100644 src/backends/meta-monitor-config-store.h delete mode 100644 src/backends/meta-monitor-manager-dummy.c delete mode 100644 src/backends/meta-monitor-manager-dummy.h delete mode 100644 src/backends/meta-monitor-manager-private.h delete mode 100644 src/backends/meta-monitor-manager.c delete mode 100644 src/backends/meta-monitor-transform.c delete mode 100644 src/backends/meta-monitor-transform.h delete mode 100644 src/backends/meta-monitor.c delete mode 100644 src/backends/meta-monitor.h delete mode 100644 src/backends/meta-orientation-manager.c delete mode 100644 src/backends/meta-orientation-manager.h delete mode 100644 src/backends/meta-output.c delete mode 100644 src/backends/meta-output.h delete mode 100644 src/backends/meta-pointer-constraint.c delete mode 100644 src/backends/meta-pointer-constraint.h delete mode 100644 src/backends/meta-profiler.c delete mode 100644 src/backends/meta-profiler.h delete mode 100644 src/backends/meta-remote-access-controller-private.h delete mode 100644 src/backends/meta-remote-access-controller.c delete mode 100644 src/backends/meta-remote-desktop-session.c delete mode 100644 src/backends/meta-remote-desktop-session.h delete mode 100644 src/backends/meta-remote-desktop.c delete mode 100644 src/backends/meta-remote-desktop.h delete mode 100644 src/backends/meta-renderer-view.c delete mode 100644 src/backends/meta-renderer-view.h delete mode 100644 src/backends/meta-renderer.c delete mode 100644 src/backends/meta-renderer.h delete mode 100644 src/backends/meta-screen-cast-area-stream-src.c delete mode 100644 src/backends/meta-screen-cast-area-stream-src.h delete mode 100644 src/backends/meta-screen-cast-area-stream.c delete mode 100644 src/backends/meta-screen-cast-area-stream.h delete mode 100644 src/backends/meta-screen-cast-monitor-stream-src.c delete mode 100644 src/backends/meta-screen-cast-monitor-stream-src.h delete mode 100644 src/backends/meta-screen-cast-monitor-stream.c delete mode 100644 src/backends/meta-screen-cast-monitor-stream.h delete mode 100644 src/backends/meta-screen-cast-session.c delete mode 100644 src/backends/meta-screen-cast-session.h delete mode 100644 src/backends/meta-screen-cast-stream-src.c delete mode 100644 src/backends/meta-screen-cast-stream-src.h delete mode 100644 src/backends/meta-screen-cast-stream.c delete mode 100644 src/backends/meta-screen-cast-stream.h delete mode 100644 src/backends/meta-screen-cast-virtual-stream-src.c delete mode 100644 src/backends/meta-screen-cast-virtual-stream-src.h delete mode 100644 src/backends/meta-screen-cast-virtual-stream.c delete mode 100644 src/backends/meta-screen-cast-virtual-stream.h delete mode 100644 src/backends/meta-screen-cast-window-stream-src.c delete mode 100644 src/backends/meta-screen-cast-window-stream-src.h delete mode 100644 src/backends/meta-screen-cast-window-stream.c delete mode 100644 src/backends/meta-screen-cast-window-stream.h delete mode 100644 src/backends/meta-screen-cast-window.c delete mode 100644 src/backends/meta-screen-cast-window.h delete mode 100644 src/backends/meta-screen-cast.c delete mode 100644 src/backends/meta-screen-cast.h delete mode 100644 src/backends/meta-settings-private.h delete mode 100644 src/backends/meta-settings.c delete mode 100644 src/backends/meta-stage-impl-private.h delete mode 100644 src/backends/meta-stage-impl.c delete mode 100644 src/backends/meta-stage-private.h delete mode 100644 src/backends/meta-stage-view-private.h delete mode 100644 src/backends/meta-stage-view.c delete mode 100644 src/backends/meta-stage.c delete mode 100644 src/backends/meta-viewport-info.c delete mode 100644 src/backends/meta-viewport-info.h delete mode 100644 src/backends/meta-virtual-monitor.c delete mode 100644 src/backends/meta-virtual-monitor.h delete mode 100644 src/backends/native/dbus-utils.c delete mode 100644 src/backends/native/dbus-utils.h delete mode 100755 src/backends/native/gen-default-modes.py delete mode 100644 src/backends/native/meta-backend-native-private.h delete mode 100644 src/backends/native/meta-backend-native-types.h delete mode 100644 src/backends/native/meta-backend-native.c delete mode 100644 src/backends/native/meta-backend-native.h delete mode 100644 src/backends/native/meta-barrier-native.c delete mode 100644 src/backends/native/meta-barrier-native.h delete mode 100644 src/backends/native/meta-clutter-backend-native.c delete mode 100644 src/backends/native/meta-clutter-backend-native.h delete mode 100644 src/backends/native/meta-cogl-utils.c delete mode 100644 src/backends/native/meta-cogl-utils.h delete mode 100644 src/backends/native/meta-crtc-kms.c delete mode 100644 src/backends/native/meta-crtc-kms.h delete mode 100644 src/backends/native/meta-crtc-mode-kms.c delete mode 100644 src/backends/native/meta-crtc-mode-kms.h delete mode 100644 src/backends/native/meta-crtc-mode-virtual.c delete mode 100644 src/backends/native/meta-crtc-mode-virtual.h delete mode 100644 src/backends/native/meta-crtc-native.c delete mode 100644 src/backends/native/meta-crtc-native.h delete mode 100644 src/backends/native/meta-crtc-virtual.c delete mode 100644 src/backends/native/meta-crtc-virtual.h delete mode 100644 src/backends/native/meta-cursor-renderer-native.c delete mode 100644 src/backends/native/meta-cursor-renderer-native.h delete mode 100644 src/backends/native/meta-device-pool-private.h delete mode 100644 src/backends/native/meta-device-pool.c delete mode 100644 src/backends/native/meta-device-pool.h delete mode 100644 src/backends/native/meta-drm-buffer-dumb.c delete mode 100644 src/backends/native/meta-drm-buffer-dumb.h delete mode 100644 src/backends/native/meta-drm-buffer-gbm.c delete mode 100644 src/backends/native/meta-drm-buffer-gbm.h delete mode 100644 src/backends/native/meta-drm-buffer-import.c delete mode 100644 src/backends/native/meta-drm-buffer-import.h delete mode 100644 src/backends/native/meta-drm-buffer-private.h delete mode 100644 src/backends/native/meta-drm-buffer.c delete mode 100644 src/backends/native/meta-drm-buffer.h delete mode 100644 src/backends/native/meta-gpu-kms.c delete mode 100644 src/backends/native/meta-gpu-kms.h delete mode 100644 src/backends/native/meta-input-device-native.c delete mode 100644 src/backends/native/meta-input-device-native.h delete mode 100644 src/backends/native/meta-input-device-tool-native.c delete mode 100644 src/backends/native/meta-input-device-tool-native.h delete mode 100644 src/backends/native/meta-input-settings-native.c delete mode 100644 src/backends/native/meta-input-settings-native.h delete mode 100644 src/backends/native/meta-input-thread.h delete mode 100644 src/backends/native/meta-keymap-native.c delete mode 100644 src/backends/native/meta-keymap-native.h delete mode 100644 src/backends/native/meta-kms-connector-private.h delete mode 100644 src/backends/native/meta-kms-connector.c delete mode 100644 src/backends/native/meta-kms-connector.h delete mode 100644 src/backends/native/meta-kms-crtc-private.h delete mode 100644 src/backends/native/meta-kms-crtc.c delete mode 100644 src/backends/native/meta-kms-crtc.h delete mode 100644 src/backends/native/meta-kms-device-private.h delete mode 100644 src/backends/native/meta-kms-device.c delete mode 100644 src/backends/native/meta-kms-device.h delete mode 100644 src/backends/native/meta-kms-impl-device-atomic.c delete mode 100644 src/backends/native/meta-kms-impl-device-atomic.h delete mode 100644 src/backends/native/meta-kms-impl-device-dummy.c delete mode 100644 src/backends/native/meta-kms-impl-device-dummy.h delete mode 100644 src/backends/native/meta-kms-impl-device-simple.c delete mode 100644 src/backends/native/meta-kms-impl-device-simple.h delete mode 100644 src/backends/native/meta-kms-impl-device.c delete mode 100644 src/backends/native/meta-kms-impl-device.h delete mode 100644 src/backends/native/meta-kms-impl.c delete mode 100644 src/backends/native/meta-kms-impl.h delete mode 100644 src/backends/native/meta-kms-mode-private.h delete mode 100644 src/backends/native/meta-kms-mode.c delete mode 100644 src/backends/native/meta-kms-mode.h delete mode 100644 src/backends/native/meta-kms-page-flip-private.h delete mode 100644 src/backends/native/meta-kms-page-flip.c delete mode 100644 src/backends/native/meta-kms-plane-private.h delete mode 100644 src/backends/native/meta-kms-plane.c delete mode 100644 src/backends/native/meta-kms-plane.h delete mode 100644 src/backends/native/meta-kms-private.h delete mode 100644 src/backends/native/meta-kms-types.h delete mode 100644 src/backends/native/meta-kms-update-private.h delete mode 100644 src/backends/native/meta-kms-update.c delete mode 100644 src/backends/native/meta-kms-update.h delete mode 100644 src/backends/native/meta-kms-utils.c delete mode 100644 src/backends/native/meta-kms-utils.h delete mode 100644 src/backends/native/meta-kms.c delete mode 100644 src/backends/native/meta-kms.h delete mode 100644 src/backends/native/meta-launcher.c delete mode 100644 src/backends/native/meta-launcher.h delete mode 100644 src/backends/native/meta-monitor-manager-native.c delete mode 100644 src/backends/native/meta-monitor-manager-native.h delete mode 100644 src/backends/native/meta-onscreen-native.c delete mode 100644 src/backends/native/meta-onscreen-native.h delete mode 100644 src/backends/native/meta-output-kms.c delete mode 100644 src/backends/native/meta-output-kms.h delete mode 100644 src/backends/native/meta-output-native.c delete mode 100644 src/backends/native/meta-output-native.h delete mode 100644 src/backends/native/meta-output-virtual.c delete mode 100644 src/backends/native/meta-output-virtual.h delete mode 100644 src/backends/native/meta-pointer-constraint-native.c delete mode 100644 src/backends/native/meta-pointer-constraint-native.h delete mode 100644 src/backends/native/meta-renderer-native-gles3.c delete mode 100644 src/backends/native/meta-renderer-native-gles3.h delete mode 100644 src/backends/native/meta-renderer-native-private.h delete mode 100644 src/backends/native/meta-renderer-native.c delete mode 100644 src/backends/native/meta-renderer-native.h delete mode 100644 src/backends/native/meta-seat-impl.c delete mode 100644 src/backends/native/meta-seat-impl.h delete mode 100644 src/backends/native/meta-seat-native.c delete mode 100644 src/backends/native/meta-seat-native.h delete mode 100644 src/backends/native/meta-stage-native.c delete mode 100644 src/backends/native/meta-stage-native.h delete mode 100644 src/backends/native/meta-udev.c delete mode 100644 src/backends/native/meta-udev.h delete mode 100644 src/backends/native/meta-virtual-input-device-native.c delete mode 100644 src/backends/native/meta-virtual-input-device-native.h delete mode 100644 src/backends/native/meta-virtual-monitor-native.c delete mode 100644 src/backends/native/meta-virtual-monitor-native.h delete mode 100644 src/backends/native/meta-xkb-utils.c delete mode 100644 src/backends/native/meta-xkb-utils.h delete mode 100644 src/backends/x11/cm/meta-backend-x11-cm.c delete mode 100644 src/backends/x11/cm/meta-backend-x11-cm.h delete mode 100644 src/backends/x11/cm/meta-cursor-sprite-xfixes.c delete mode 100644 src/backends/x11/cm/meta-cursor-sprite-xfixes.h delete mode 100644 src/backends/x11/cm/meta-renderer-x11-cm.c delete mode 100644 src/backends/x11/cm/meta-renderer-x11-cm.h delete mode 100644 src/backends/x11/meta-backend-x11.c delete mode 100644 src/backends/x11/meta-backend-x11.h delete mode 100644 src/backends/x11/meta-barrier-x11.c delete mode 100644 src/backends/x11/meta-barrier-x11.h delete mode 100644 src/backends/x11/meta-clutter-backend-x11.c delete mode 100644 src/backends/x11/meta-clutter-backend-x11.h delete mode 100644 src/backends/x11/meta-crtc-xrandr.c delete mode 100644 src/backends/x11/meta-crtc-xrandr.h delete mode 100644 src/backends/x11/meta-cursor-renderer-x11.c delete mode 100644 src/backends/x11/meta-cursor-renderer-x11.h delete mode 100644 src/backends/x11/meta-cursor-tracker-x11.c delete mode 100644 src/backends/x11/meta-cursor-tracker-x11.h delete mode 100644 src/backends/x11/meta-event-x11.c delete mode 100644 src/backends/x11/meta-event-x11.h delete mode 100644 src/backends/x11/meta-gpu-xrandr.c delete mode 100644 src/backends/x11/meta-gpu-xrandr.h delete mode 100644 src/backends/x11/meta-input-device-tool-x11.c delete mode 100644 src/backends/x11/meta-input-device-tool-x11.h delete mode 100644 src/backends/x11/meta-input-device-x11.c delete mode 100644 src/backends/x11/meta-input-device-x11.h delete mode 100644 src/backends/x11/meta-input-settings-x11.c delete mode 100644 src/backends/x11/meta-input-settings-x11.h delete mode 100644 src/backends/x11/meta-keymap-x11.c delete mode 100644 src/backends/x11/meta-keymap-x11.h delete mode 100644 src/backends/x11/meta-monitor-manager-xrandr.c delete mode 100644 src/backends/x11/meta-monitor-manager-xrandr.h delete mode 100644 src/backends/x11/meta-output-xrandr.c delete mode 100644 src/backends/x11/meta-output-xrandr.h delete mode 100644 src/backends/x11/meta-renderer-x11.c delete mode 100644 src/backends/x11/meta-renderer-x11.h delete mode 100644 src/backends/x11/meta-seat-x11.c delete mode 100644 src/backends/x11/meta-seat-x11.h delete mode 100644 src/backends/x11/meta-stage-x11.c delete mode 100644 src/backends/x11/meta-stage-x11.h delete mode 100644 src/backends/x11/meta-virtual-input-device-x11.c delete mode 100644 src/backends/x11/meta-virtual-input-device-x11.h delete mode 100644 src/backends/x11/meta-xkb-a11y-x11.c delete mode 100644 src/backends/x11/meta-xkb-a11y-x11.h delete mode 100644 src/backends/x11/nested/meta-backend-x11-nested.c delete mode 100644 src/backends/x11/nested/meta-backend-x11-nested.h delete mode 100644 src/backends/x11/nested/meta-cursor-renderer-x11-nested.c delete mode 100644 src/backends/x11/nested/meta-cursor-renderer-x11-nested.h delete mode 100644 src/backends/x11/nested/meta-renderer-x11-nested.c delete mode 100644 src/backends/x11/nested/meta-renderer-x11-nested.h delete mode 100644 src/backends/x11/nested/meta-stage-x11-nested.c delete mode 100644 src/backends/x11/nested/meta-stage-x11-nested.h delete mode 100644 src/compositor/README delete mode 100644 src/compositor/clutter-utils.c delete mode 100644 src/compositor/clutter-utils.h delete mode 100644 src/compositor/cogl-utils.c delete mode 100644 src/compositor/cogl-utils.h delete mode 100644 src/compositor/compositor-private.h delete mode 100644 src/compositor/compositor.c delete mode 100644 src/compositor/meta-background-actor-private.h delete mode 100644 src/compositor/meta-background-actor.c delete mode 100644 src/compositor/meta-background-content-private.h delete mode 100644 src/compositor/meta-background-content.c delete mode 100644 src/compositor/meta-background-group.c delete mode 100644 src/compositor/meta-background-image.c delete mode 100644 src/compositor/meta-background-private.h delete mode 100644 src/compositor/meta-background.c delete mode 100644 src/compositor/meta-compositor-native.c delete mode 100644 src/compositor/meta-compositor-native.h delete mode 100644 src/compositor/meta-compositor-server.c delete mode 100644 src/compositor/meta-compositor-server.h delete mode 100644 src/compositor/meta-compositor-x11.c delete mode 100644 src/compositor/meta-compositor-x11.h delete mode 100644 src/compositor/meta-cullable.c delete mode 100644 src/compositor/meta-cullable.h delete mode 100644 src/compositor/meta-dnd-actor-private.h delete mode 100644 src/compositor/meta-dnd-actor.c delete mode 100644 src/compositor/meta-dnd.c delete mode 100644 src/compositor/meta-feedback-actor-private.h delete mode 100644 src/compositor/meta-feedback-actor.c delete mode 100644 src/compositor/meta-later-private.h delete mode 100644 src/compositor/meta-later.c delete mode 100644 src/compositor/meta-module.c delete mode 100644 src/compositor/meta-module.h delete mode 100644 src/compositor/meta-plugin-manager.c delete mode 100644 src/compositor/meta-plugin-manager.h delete mode 100644 src/compositor/meta-plugin.c delete mode 100644 src/compositor/meta-shadow-factory.c delete mode 100644 src/compositor/meta-shaped-texture-private.h delete mode 100644 src/compositor/meta-shaped-texture.c delete mode 100644 src/compositor/meta-surface-actor-wayland.c delete mode 100644 src/compositor/meta-surface-actor-wayland.h delete mode 100644 src/compositor/meta-surface-actor-x11.c delete mode 100644 src/compositor/meta-surface-actor-x11.h delete mode 100644 src/compositor/meta-surface-actor.c delete mode 100644 src/compositor/meta-surface-actor.h delete mode 100644 src/compositor/meta-sync-ring.c delete mode 100644 src/compositor/meta-sync-ring.h delete mode 100644 src/compositor/meta-texture-tower.c delete mode 100644 src/compositor/meta-texture-tower.h delete mode 100644 src/compositor/meta-window-actor-private.h delete mode 100644 src/compositor/meta-window-actor-wayland.c delete mode 100644 src/compositor/meta-window-actor-wayland.h delete mode 100644 src/compositor/meta-window-actor-x11.c delete mode 100644 src/compositor/meta-window-actor-x11.h delete mode 100644 src/compositor/meta-window-actor.c delete mode 100644 src/compositor/meta-window-group-private.h delete mode 100644 src/compositor/meta-window-group.c delete mode 100644 src/compositor/meta-window-shape.c delete mode 100644 src/compositor/plugins/default.c delete mode 100644 src/compositor/plugins/meson.build delete mode 100644 src/compositor/region-utils.c delete mode 100644 src/compositor/region-utils.h delete mode 100644 src/core/bell.c delete mode 100644 src/core/bell.h delete mode 100644 src/core/boxes-private.h delete mode 100644 src/core/boxes.c delete mode 100644 src/core/constraints.c delete mode 100644 src/core/constraints.h delete mode 100644 src/core/delete.c delete mode 100644 src/core/display-private.h delete mode 100644 src/core/display.c delete mode 100644 src/core/edge-resistance.c delete mode 100644 src/core/edge-resistance.h delete mode 100644 src/core/events.c delete mode 100644 src/core/events.h delete mode 100644 src/core/frame.c delete mode 100644 src/core/frame.h delete mode 100644 src/core/keybindings-private.h delete mode 100644 src/core/keybindings.c delete mode 100644 src/core/meta-accel-parse.c delete mode 100644 src/core/meta-accel-parse.h delete mode 100644 src/core/meta-anonymous-file.c delete mode 100644 src/core/meta-anonymous-file.h delete mode 100644 src/core/meta-border.c delete mode 100644 src/core/meta-border.h delete mode 100644 src/core/meta-clipboard-manager.c delete mode 100644 src/core/meta-clipboard-manager.h delete mode 100644 src/core/meta-close-dialog-default-private.h delete mode 100644 src/core/meta-close-dialog-default.c delete mode 100644 src/core/meta-close-dialog.c delete mode 100644 src/core/meta-context-main.c delete mode 100644 src/core/meta-context-main.h delete mode 100644 src/core/meta-context-private.h delete mode 100644 src/core/meta-context.c delete mode 100644 src/core/meta-fraction.c delete mode 100644 src/core/meta-fraction.h delete mode 100644 src/core/meta-gesture-tracker-private.h delete mode 100644 src/core/meta-gesture-tracker.c delete mode 100644 src/core/meta-inhibit-shortcuts-dialog-default-private.h delete mode 100644 src/core/meta-inhibit-shortcuts-dialog-default.c delete mode 100644 src/core/meta-inhibit-shortcuts-dialog.c delete mode 100644 src/core/meta-launch-context.c delete mode 100644 src/core/meta-pad-action-mapper.c delete mode 100644 src/core/meta-pad-action-mapper.h delete mode 100644 src/core/meta-private-enums.h delete mode 100644 src/core/meta-selection-private.h delete mode 100644 src/core/meta-selection-source-memory.c delete mode 100644 src/core/meta-selection-source-remote.c delete mode 100644 src/core/meta-selection-source-remote.h delete mode 100644 src/core/meta-selection-source.c delete mode 100644 src/core/meta-selection.c delete mode 100644 src/core/meta-sound-player.c delete mode 100644 src/core/meta-workspace-manager-private.h delete mode 100644 src/core/meta-workspace-manager.c delete mode 100644 src/core/mutter.c delete mode 100644 src/core/place.c delete mode 100644 src/core/place.h delete mode 100644 src/core/prefs-private.h delete mode 100644 src/core/prefs.c delete mode 100644 src/core/restart-helper.c delete mode 100644 src/core/restart.c delete mode 100644 src/core/stack-tracker.c delete mode 100644 src/core/stack-tracker.h delete mode 100644 src/core/stack.c delete mode 100644 src/core/stack.h delete mode 100644 src/core/startup-notification-private.h delete mode 100644 src/core/startup-notification.c delete mode 100644 src/core/util-private.h delete mode 100644 src/core/util.c delete mode 100644 src/core/window-private.h delete mode 100644 src/core/window.c delete mode 100644 src/core/workspace-private.h delete mode 100644 src/core/workspace.c delete mode 100644 src/libmutter.pc.in delete mode 100644 src/meson.build delete mode 100644 src/meta-private-enum-types.c.in delete mode 100644 src/meta-private-enum-types.h.in delete mode 100644 src/meta/barrier.h delete mode 100644 src/meta/boxes.h delete mode 100644 src/meta/common.h delete mode 100644 src/meta/compositor-mutter.h delete mode 100644 src/meta/compositor.h delete mode 100644 src/meta/display.h delete mode 100644 src/meta/group.h delete mode 100644 src/meta/keybindings.h delete mode 100644 src/meta/main.h delete mode 100644 src/meta/meson.build delete mode 100644 src/meta/meta-backend.h delete mode 100644 src/meta/meta-background-actor.h delete mode 100644 src/meta/meta-background-content.h delete mode 100644 src/meta/meta-background-group.h delete mode 100644 src/meta/meta-background-image.h delete mode 100644 src/meta/meta-background.h delete mode 100644 src/meta/meta-close-dialog.h delete mode 100644 src/meta/meta-context.h delete mode 100644 src/meta/meta-cursor-tracker.h delete mode 100644 src/meta/meta-dnd.h delete mode 100644 src/meta/meta-enum-types.c.in delete mode 100644 src/meta/meta-enum-types.h.in delete mode 100644 src/meta/meta-enums.h delete mode 100644 src/meta/meta-idle-monitor.h delete mode 100644 src/meta/meta-inhibit-shortcuts-dialog.h delete mode 100644 src/meta/meta-later.h delete mode 100644 src/meta/meta-launch-context.h delete mode 100644 src/meta/meta-monitor-manager.h delete mode 100644 src/meta/meta-plugin.h delete mode 100644 src/meta/meta-remote-access-controller.h delete mode 100644 src/meta/meta-selection-source-memory.h delete mode 100644 src/meta/meta-selection-source.h delete mode 100644 src/meta/meta-selection.h delete mode 100644 src/meta/meta-settings.h delete mode 100644 src/meta/meta-shadow-factory.h delete mode 100644 src/meta/meta-shaped-texture.h delete mode 100644 src/meta/meta-sound-player.h delete mode 100644 src/meta/meta-stage.h delete mode 100644 src/meta/meta-startup-notification.h delete mode 100644 src/meta/meta-wayland-client.h delete mode 100644 src/meta/meta-window-actor.h delete mode 100644 src/meta/meta-window-group.h delete mode 100644 src/meta/meta-window-shape.h delete mode 100644 src/meta/meta-workspace-manager.h delete mode 100644 src/meta/meta-x11-display.h delete mode 100644 src/meta/meta-x11-errors.h delete mode 100644 src/meta/prefs.h delete mode 100644 src/meta/theme.h delete mode 100644 src/meta/types.h delete mode 100644 src/meta/util.h delete mode 100644 src/meta/window.h delete mode 100644 src/meta/workspace.h delete mode 100644 src/org.freedesktop.login1.xml delete mode 100644 src/org.gnome.Mutter.DisplayConfig.xml delete mode 100644 src/org.gnome.Mutter.IdleMonitor.xml delete mode 100644 src/org.gnome.Mutter.RemoteDesktop.xml delete mode 100644 src/org.gnome.Mutter.ScreenCast.xml delete mode 100644 src/tests/README delete mode 100644 src/tests/anonymous-file.c delete mode 100644 src/tests/boxes-tests.c delete mode 100644 src/tests/boxes-tests.h delete mode 100644 src/tests/clutter-test-utils.c delete mode 100644 src/tests/clutter-test-utils.h delete mode 100644 src/tests/clutter/README delete mode 100644 src/tests/clutter/accessibility/cally-atkcomponent-example.c delete mode 100644 src/tests/clutter/accessibility/cally-atkeditabletext-example.c delete mode 100644 src/tests/clutter/accessibility/cally-atkevents-example.c delete mode 100644 src/tests/clutter/accessibility/cally-atktext-example.c delete mode 100644 src/tests/clutter/accessibility/cally-clone-example.c delete mode 100644 src/tests/clutter/accessibility/cally-examples-util.c delete mode 100644 src/tests/clutter/accessibility/cally-examples-util.h delete mode 100644 src/tests/clutter/accessibility/meson.build delete mode 100644 src/tests/clutter/clutter-1.0.suppressions delete mode 100644 src/tests/clutter/conform/actor-clone.c delete mode 100644 src/tests/clutter/conform/actor-destroy.c delete mode 100644 src/tests/clutter/conform/actor-graph.c delete mode 100644 src/tests/clutter/conform/actor-invariants.c delete mode 100644 src/tests/clutter/conform/actor-iter.c delete mode 100644 src/tests/clutter/conform/actor-layout.c delete mode 100644 src/tests/clutter/conform/actor-meta.c delete mode 100644 src/tests/clutter/conform/actor-offscreen-redirect.c delete mode 100644 src/tests/clutter/conform/actor-paint-opacity.c delete mode 100644 src/tests/clutter/conform/actor-pick.c delete mode 100644 src/tests/clutter/conform/actor-pivot-point.c delete mode 100644 src/tests/clutter/conform/actor-shader-effect.c delete mode 100644 src/tests/clutter/conform/actor-size.c delete mode 100644 src/tests/clutter/conform/binding-pool.c delete mode 100644 src/tests/clutter/conform/cally-text.c delete mode 100644 src/tests/clutter/conform/color.c delete mode 100644 src/tests/clutter/conform/frame-clock-timeline.c delete mode 100644 src/tests/clutter/conform/frame-clock.c delete mode 100644 src/tests/clutter/conform/interval.c delete mode 100644 src/tests/clutter/conform/meson.build delete mode 100644 src/tests/clutter/conform/path.c delete mode 100644 src/tests/clutter/conform/script-parser.c delete mode 100644 src/tests/clutter/conform/scripts/test-script-child.json delete mode 100644 src/tests/clutter/conform/scripts/test-script-interval.json delete mode 100644 src/tests/clutter/conform/scripts/test-script-margin.json delete mode 100644 src/tests/clutter/conform/scripts/test-script-model.json delete mode 100644 src/tests/clutter/conform/scripts/test-script-named-object.json delete mode 100644 src/tests/clutter/conform/scripts/test-script-object-property.json delete mode 100644 src/tests/clutter/conform/scripts/test-script-single.json delete mode 100644 src/tests/clutter/conform/scripts/test-script-timeline-markers.json delete mode 100644 src/tests/clutter/conform/text-cache.c delete mode 100644 src/tests/clutter/conform/text.c delete mode 100644 src/tests/clutter/conform/texture-fbo.c delete mode 100644 src/tests/clutter/conform/timeline-interpolate.c delete mode 100644 src/tests/clutter/conform/timeline-progress.c delete mode 100644 src/tests/clutter/conform/timeline-rewind.c delete mode 100644 src/tests/clutter/conform/timeline.c delete mode 100644 src/tests/clutter/conform/units.c delete mode 100644 src/tests/clutter/interactive/light0.png delete mode 100644 src/tests/clutter/interactive/meson.build delete mode 100755 src/tests/clutter/interactive/meson/gen-test-unit-names.sh delete mode 100644 src/tests/clutter/interactive/redhand.png delete mode 100644 src/tests/clutter/interactive/redhand_alpha.png delete mode 100644 src/tests/clutter/interactive/test-actors.c delete mode 100644 src/tests/clutter/interactive/test-animation.c delete mode 100644 src/tests/clutter/interactive/test-bind-constraint.c delete mode 100644 src/tests/clutter/interactive/test-binding-pool.c delete mode 100644 src/tests/clutter/interactive/test-cairo-clock.c delete mode 100644 src/tests/clutter/interactive/test-cairo-flowers.c delete mode 100644 src/tests/clutter/interactive/test-cogl-multitexture.c delete mode 100644 src/tests/clutter/interactive/test-cogl-offscreen.c delete mode 100644 src/tests/clutter/interactive/test-cogl-point-sprites.c delete mode 100644 src/tests/clutter/interactive/test-cogl-shader-glsl.c delete mode 100644 src/tests/clutter/interactive/test-cogl-tex-convert.c delete mode 100644 src/tests/clutter/interactive/test-cogl-tex-polygon.c delete mode 100644 src/tests/clutter/interactive/test-cogl-tex-tile.c delete mode 100644 src/tests/clutter/interactive/test-content.c delete mode 100644 src/tests/clutter/interactive/test-devices.c delete mode 100644 src/tests/clutter/interactive/test-easing.c delete mode 100644 src/tests/clutter/interactive/test-events.c delete mode 100644 src/tests/clutter/interactive/test-grab.c delete mode 100644 src/tests/clutter/interactive/test-image.c delete mode 100644 src/tests/clutter/interactive/test-keyframe-transition.c delete mode 100644 src/tests/clutter/interactive/test-layout.c delete mode 100644 src/tests/clutter/interactive/test-main.c delete mode 100644 src/tests/clutter/interactive/test-path-constraint.c delete mode 100644 src/tests/clutter/interactive/test-rotate-zoom.c delete mode 100644 src/tests/clutter/interactive/test-script.c delete mode 100644 src/tests/clutter/interactive/test-script.json delete mode 100644 src/tests/clutter/interactive/test-shader-effects.c delete mode 100644 src/tests/clutter/interactive/test-stage-sizing.c delete mode 100644 src/tests/clutter/interactive/test-state-script.c delete mode 100644 src/tests/clutter/interactive/test-swipe-action.c delete mode 100644 src/tests/clutter/interactive/test-text-field.c delete mode 100644 src/tests/clutter/interactive/test-text.c delete mode 100644 src/tests/clutter/interactive/test-touch-events.c delete mode 100755 src/tests/clutter/interactive/wrapper.sh.in delete mode 100644 src/tests/clutter/meson.build delete mode 100644 src/tests/clutter/micro-bench/meson.build delete mode 100644 src/tests/clutter/micro-bench/test-cogl-perf.c delete mode 100644 src/tests/clutter/micro-bench/test-picking.c delete mode 100644 src/tests/clutter/micro-bench/test-random-text.c delete mode 100644 src/tests/clutter/micro-bench/test-text-perf.c delete mode 100644 src/tests/clutter/micro-bench/test-text.c delete mode 100755 src/tests/clutter/performance/create-report.rb delete mode 100644 src/tests/clutter/performance/joblist delete mode 100755 src/tests/clutter/performance/makejobs.rb delete mode 100644 src/tests/clutter/performance/meson.build delete mode 100644 src/tests/clutter/performance/test-common.h delete mode 100644 src/tests/clutter/performance/test-picking.c delete mode 100644 src/tests/clutter/performance/test-text-perf.c delete mode 100644 src/tests/clutter/test-utils.h delete mode 100644 src/tests/headless-start-test.c delete mode 100644 src/tests/kms-utils-unit-tests.c delete mode 100644 src/tests/meson.build delete mode 100644 src/tests/meta-backend-test.c delete mode 100644 src/tests/meta-backend-test.h delete mode 100644 src/tests/meta-context-test.c delete mode 100644 src/tests/meta-gpu-test.c delete mode 100644 src/tests/meta-gpu-test.h delete mode 100644 src/tests/meta-monitor-manager-test.c delete mode 100644 src/tests/meta-monitor-manager-test.h delete mode 100644 src/tests/meta-ref-test.c delete mode 100644 src/tests/meta-ref-test.h delete mode 100644 src/tests/meta-test-utils-private.h delete mode 100644 src/tests/meta-test-utils.c delete mode 100644 src/tests/meta-test-utils.h delete mode 100644 src/tests/meta-test/meson.build delete mode 100644 src/tests/meta-test/meta-context-test.h delete mode 100644 src/tests/meta-wayland-test-driver.c delete mode 100644 src/tests/meta-wayland-test-driver.h delete mode 100644 src/tests/migration/basic-new.xml delete mode 100644 src/tests/migration/basic-old.xml delete mode 100644 src/tests/migration/first-rotated-new.xml delete mode 100644 src/tests/migration/first-rotated-old.xml delete mode 100644 src/tests/migration/oneoff-new-finished.xml delete mode 100644 src/tests/migration/oneoff-new.xml delete mode 100644 src/tests/migration/oneoff-old.xml delete mode 100644 src/tests/migration/rotated-new-finished.xml delete mode 100644 src/tests/migration/rotated-new.xml delete mode 100644 src/tests/migration/rotated-old.xml delete mode 100644 src/tests/migration/tiled-new.xml delete mode 100644 src/tests/migration/tiled-old.xml delete mode 100644 src/tests/migration/wiggle-new-discarded.xml delete mode 100644 src/tests/migration/wiggle-new-finished.xml delete mode 100644 src/tests/migration/wiggle-new.xml delete mode 100644 src/tests/migration/wiggle-old.xml delete mode 100644 src/tests/monitor-config-migration-unit-tests.c delete mode 100644 src/tests/monitor-config-migration-unit-tests.h delete mode 100644 src/tests/monitor-configs/first-rotated.xml delete mode 100644 src/tests/monitor-configs/fractional-scale.xml delete mode 100644 src/tests/monitor-configs/high-precision-fractional-scale.xml delete mode 100644 src/tests/monitor-configs/interlaced.xml delete mode 100644 src/tests/monitor-configs/lid-scale.xml delete mode 100644 src/tests/monitor-configs/lid-switch.xml delete mode 100644 src/tests/monitor-configs/mirrored.xml delete mode 100644 src/tests/monitor-configs/non-preferred-tiled-custom-resolution.xml delete mode 100644 src/tests/monitor-configs/oneoff.xml delete mode 100644 src/tests/monitor-configs/primary.xml delete mode 100644 src/tests/monitor-configs/scale.xml delete mode 100644 src/tests/monitor-configs/second-rotated-tiled.xml delete mode 100644 src/tests/monitor-configs/second-rotated.xml delete mode 100644 src/tests/monitor-configs/single.xml delete mode 100644 src/tests/monitor-configs/tiled-custom-resolution.xml delete mode 100644 src/tests/monitor-configs/tiled.xml delete mode 100644 src/tests/monitor-configs/underscanning.xml delete mode 100644 src/tests/monitor-configs/vertical.xml delete mode 100644 src/tests/monitor-store-unit-tests.c delete mode 100644 src/tests/monitor-store-unit-tests.h delete mode 100644 src/tests/monitor-test-utils.c delete mode 100644 src/tests/monitor-test-utils.h delete mode 100644 src/tests/monitor-transform-tests.c delete mode 100644 src/tests/monitor-transform-tests.h delete mode 100644 src/tests/monitor-unit-tests.c delete mode 100644 src/tests/monitor-unit-tests.h delete mode 100644 src/tests/mutter-all.test.in delete mode 100644 src/tests/native-headless.c delete mode 100644 src/tests/native-persistent-virtual-monitor.c delete mode 100644 src/tests/native-screen-cast.c delete mode 100644 src/tests/native-screen-cast.h delete mode 100644 src/tests/native-virtual-monitor.c delete mode 100644 src/tests/native-virtual-monitor.h delete mode 100644 src/tests/ref-test-sanity.c delete mode 100644 src/tests/ref-tests/backends_native_virtual-monitor_create_0.ref.png delete mode 100644 src/tests/ref-tests/backends_native_virtual-monitor_create_1.ref.png delete mode 100644 src/tests/ref-tests/tests_ref-test_sanity_0.ref.png delete mode 100644 src/tests/ref-tests/tests_ref-test_sanity_1.ref.png delete mode 100644 src/tests/screen-cast-client.c delete mode 100644 src/tests/stacking/basic-wayland.metatest delete mode 100644 src/tests/stacking/basic-x11.metatest delete mode 100644 src/tests/stacking/client-side-decorated.metatest delete mode 100644 src/tests/stacking/closed-transient-no-default-focus.metatest delete mode 100644 src/tests/stacking/closed-transient-no-input-no-take-focus-parent.metatest delete mode 100644 src/tests/stacking/closed-transient-no-input-no-take-focus-parents.metatest delete mode 100644 src/tests/stacking/closed-transient-no-input-parent-delayed-focus-default-cancelled.metatest delete mode 100644 src/tests/stacking/closed-transient-no-input-parent.metatest delete mode 100644 src/tests/stacking/closed-transient-no-input-parents-queued-default-focus-destroyed.metatest delete mode 100644 src/tests/stacking/closed-transient-no-input-parents.metatest delete mode 100644 src/tests/stacking/closed-transient-only-take-focus-parents.metatest delete mode 100644 src/tests/stacking/closed-transient.metatest delete mode 100644 src/tests/stacking/default-size.metatest delete mode 100644 src/tests/stacking/fullscreen-maximize.metatest delete mode 100644 src/tests/stacking/map-fixed-size.metatest delete mode 100644 src/tests/stacking/minimized.metatest delete mode 100644 src/tests/stacking/mixed-windows.metatest delete mode 100644 src/tests/stacking/modals.metatest delete mode 100644 src/tests/stacking/override-redirect.metatest delete mode 100644 src/tests/stacking/restore-position.metatest delete mode 100644 src/tests/stacking/restore-size.metatest delete mode 100644 src/tests/stacking/set-override-redirect-parent.metatest delete mode 100644 src/tests/stacking/set-parent-exported.metatest delete mode 100644 src/tests/stacking/set-parent.metatest delete mode 100644 src/tests/stacking/unmaximize-new-size.metatest delete mode 100644 src/tests/stage-view-tests.c delete mode 100644 src/tests/test-client.c delete mode 100644 src/tests/test-runner.c delete mode 100644 src/tests/unit-tests.c delete mode 100644 src/tests/unit-tests.h delete mode 100644 src/tests/wayland-test-clients/invalid-subsurfaces.c delete mode 100644 src/tests/wayland-test-clients/invalid-xdg-shell-actions.c delete mode 100644 src/tests/wayland-test-clients/meson.build delete mode 100644 src/tests/wayland-test-clients/subsurface-remap-toplevel.c delete mode 100644 src/tests/wayland-test-clients/test-driver.xml delete mode 100644 src/tests/wayland-test-clients/wayland-test-client-utils.c delete mode 100644 src/tests/wayland-test-clients/wayland-test-client-utils.h delete mode 100644 src/tests/wayland-test-clients/xdg-apply-limits.c delete mode 100644 src/tests/wayland-unit-tests.c delete mode 100644 src/tests/wayland-unit-tests.h delete mode 100644 src/ui/frames.c delete mode 100644 src/ui/frames.h delete mode 100644 src/ui/theme-private.h delete mode 100644 src/ui/theme.c delete mode 100644 src/ui/ui.c delete mode 100644 src/ui/ui.h delete mode 100644 src/wayland/meta-cursor-sprite-wayland.c delete mode 100644 src/wayland/meta-cursor-sprite-wayland.h delete mode 100644 src/wayland/meta-pointer-confinement-wayland.c delete mode 100644 src/wayland/meta-pointer-confinement-wayland.h delete mode 100644 src/wayland/meta-pointer-lock-wayland.c delete mode 100644 src/wayland/meta-pointer-lock-wayland.h delete mode 100644 src/wayland/meta-selection-source-wayland-private.h delete mode 100644 src/wayland/meta-selection-source-wayland.c delete mode 100644 src/wayland/meta-wayland-activation.c delete mode 100644 src/wayland/meta-wayland-activation.h delete mode 100644 src/wayland/meta-wayland-actor-surface.c delete mode 100644 src/wayland/meta-wayland-actor-surface.h delete mode 100644 src/wayland/meta-wayland-buffer.c delete mode 100644 src/wayland/meta-wayland-buffer.h delete mode 100644 src/wayland/meta-wayland-client.c delete mode 100644 src/wayland/meta-wayland-cursor-surface.c delete mode 100644 src/wayland/meta-wayland-cursor-surface.h delete mode 100644 src/wayland/meta-wayland-data-device-primary-legacy.c delete mode 100644 src/wayland/meta-wayland-data-device-primary-legacy.h delete mode 100644 src/wayland/meta-wayland-data-device-primary.c delete mode 100644 src/wayland/meta-wayland-data-device-primary.h delete mode 100644 src/wayland/meta-wayland-data-device.c delete mode 100644 src/wayland/meta-wayland-data-device.h delete mode 100644 src/wayland/meta-wayland-data-offer-primary-legacy.c delete mode 100644 src/wayland/meta-wayland-data-offer-primary-legacy.h delete mode 100644 src/wayland/meta-wayland-data-offer-primary.c delete mode 100644 src/wayland/meta-wayland-data-offer-primary.h delete mode 100644 src/wayland/meta-wayland-data-offer.c delete mode 100644 src/wayland/meta-wayland-data-offer.h delete mode 100644 src/wayland/meta-wayland-data-source-primary-legacy.c delete mode 100644 src/wayland/meta-wayland-data-source-primary-legacy.h delete mode 100644 src/wayland/meta-wayland-data-source-primary.c delete mode 100644 src/wayland/meta-wayland-data-source-primary.h delete mode 100644 src/wayland/meta-wayland-data-source.c delete mode 100644 src/wayland/meta-wayland-data-source.h delete mode 100644 src/wayland/meta-wayland-dma-buf.c delete mode 100644 src/wayland/meta-wayland-dma-buf.h delete mode 100644 src/wayland/meta-wayland-dnd-surface.c delete mode 100644 src/wayland/meta-wayland-dnd-surface.h delete mode 100644 src/wayland/meta-wayland-egl-stream.c delete mode 100644 src/wayland/meta-wayland-egl-stream.h delete mode 100644 src/wayland/meta-wayland-gtk-shell.c delete mode 100644 src/wayland/meta-wayland-gtk-shell.h delete mode 100644 src/wayland/meta-wayland-inhibit-shortcuts-dialog.c delete mode 100644 src/wayland/meta-wayland-inhibit-shortcuts-dialog.h delete mode 100644 src/wayland/meta-wayland-inhibit-shortcuts.c delete mode 100644 src/wayland/meta-wayland-inhibit-shortcuts.h delete mode 100644 src/wayland/meta-wayland-input-device.c delete mode 100644 src/wayland/meta-wayland-input-device.h delete mode 100644 src/wayland/meta-wayland-keyboard.c delete mode 100644 src/wayland/meta-wayland-keyboard.h delete mode 100644 src/wayland/meta-wayland-legacy-xdg-shell.c delete mode 100644 src/wayland/meta-wayland-legacy-xdg-shell.h delete mode 100644 src/wayland/meta-wayland-outputs.c delete mode 100644 src/wayland/meta-wayland-outputs.h delete mode 100644 src/wayland/meta-wayland-pointer-constraints.c delete mode 100644 src/wayland/meta-wayland-pointer-constraints.h delete mode 100644 src/wayland/meta-wayland-pointer-gesture-pinch.c delete mode 100644 src/wayland/meta-wayland-pointer-gesture-pinch.h delete mode 100644 src/wayland/meta-wayland-pointer-gesture-swipe.c delete mode 100644 src/wayland/meta-wayland-pointer-gesture-swipe.h delete mode 100644 src/wayland/meta-wayland-pointer-gestures.c delete mode 100644 src/wayland/meta-wayland-pointer-gestures.h delete mode 100644 src/wayland/meta-wayland-pointer.c delete mode 100644 src/wayland/meta-wayland-pointer.h delete mode 100644 src/wayland/meta-wayland-popup.c delete mode 100644 src/wayland/meta-wayland-popup.h delete mode 100644 src/wayland/meta-wayland-presentation-time-private.h delete mode 100644 src/wayland/meta-wayland-presentation-time.c delete mode 100644 src/wayland/meta-wayland-private.h delete mode 100644 src/wayland/meta-wayland-region.c delete mode 100644 src/wayland/meta-wayland-region.h delete mode 100644 src/wayland/meta-wayland-seat.c delete mode 100644 src/wayland/meta-wayland-seat.h delete mode 100644 src/wayland/meta-wayland-shell-surface.c delete mode 100644 src/wayland/meta-wayland-shell-surface.h delete mode 100644 src/wayland/meta-wayland-subsurface.c delete mode 100644 src/wayland/meta-wayland-subsurface.h delete mode 100644 src/wayland/meta-wayland-surface.c delete mode 100644 src/wayland/meta-wayland-surface.h delete mode 100644 src/wayland/meta-wayland-tablet-cursor-surface.c delete mode 100644 src/wayland/meta-wayland-tablet-cursor-surface.h delete mode 100644 src/wayland/meta-wayland-tablet-manager.c delete mode 100644 src/wayland/meta-wayland-tablet-manager.h delete mode 100644 src/wayland/meta-wayland-tablet-pad-group.c delete mode 100644 src/wayland/meta-wayland-tablet-pad-group.h delete mode 100644 src/wayland/meta-wayland-tablet-pad-ring.c delete mode 100644 src/wayland/meta-wayland-tablet-pad-ring.h delete mode 100644 src/wayland/meta-wayland-tablet-pad-strip.c delete mode 100644 src/wayland/meta-wayland-tablet-pad-strip.h delete mode 100644 src/wayland/meta-wayland-tablet-pad.c delete mode 100644 src/wayland/meta-wayland-tablet-pad.h delete mode 100644 src/wayland/meta-wayland-tablet-seat.c delete mode 100644 src/wayland/meta-wayland-tablet-seat.h delete mode 100644 src/wayland/meta-wayland-tablet-tool.c delete mode 100644 src/wayland/meta-wayland-tablet-tool.h delete mode 100644 src/wayland/meta-wayland-tablet.c delete mode 100644 src/wayland/meta-wayland-tablet.h delete mode 100644 src/wayland/meta-wayland-text-input-legacy.c delete mode 100644 src/wayland/meta-wayland-text-input-legacy.h delete mode 100644 src/wayland/meta-wayland-text-input.c delete mode 100644 src/wayland/meta-wayland-text-input.h delete mode 100644 src/wayland/meta-wayland-touch.c delete mode 100644 src/wayland/meta-wayland-touch.h delete mode 100644 src/wayland/meta-wayland-types.h delete mode 100644 src/wayland/meta-wayland-versions.h delete mode 100644 src/wayland/meta-wayland-viewporter.c delete mode 100644 src/wayland/meta-wayland-viewporter.h delete mode 100644 src/wayland/meta-wayland-window-configuration.c delete mode 100644 src/wayland/meta-wayland-window-configuration.h delete mode 100644 src/wayland/meta-wayland-wl-shell.c delete mode 100644 src/wayland/meta-wayland-wl-shell.h delete mode 100644 src/wayland/meta-wayland-xdg-foreign.c delete mode 100644 src/wayland/meta-wayland-xdg-foreign.h delete mode 100644 src/wayland/meta-wayland-xdg-shell.c delete mode 100644 src/wayland/meta-wayland-xdg-shell.h delete mode 100644 src/wayland/meta-wayland.c delete mode 100644 src/wayland/meta-wayland.h delete mode 100644 src/wayland/meta-window-wayland.c delete mode 100644 src/wayland/meta-window-wayland.h delete mode 100644 src/wayland/meta-window-xwayland.c delete mode 100644 src/wayland/meta-window-xwayland.h delete mode 100644 src/wayland/meta-xwayland-dnd-private.h delete mode 100644 src/wayland/meta-xwayland-dnd.c delete mode 100644 src/wayland/meta-xwayland-grab-keyboard.c delete mode 100644 src/wayland/meta-xwayland-grab-keyboard.h delete mode 100644 src/wayland/meta-xwayland-private.h delete mode 100644 src/wayland/meta-xwayland-surface.c delete mode 100644 src/wayland/meta-xwayland-surface.h delete mode 100644 src/wayland/meta-xwayland.c delete mode 100644 src/wayland/meta-xwayland.h delete mode 100644 src/wayland/protocol/gtk-primary-selection.xml delete mode 100644 src/wayland/protocol/gtk-shell.xml delete mode 100644 src/wayland/protocol/gtk-text-input.xml delete mode 100644 src/x11/atomnames.h delete mode 100644 src/x11/events.c delete mode 100644 src/x11/events.h delete mode 100644 src/x11/group-private.h delete mode 100644 src/x11/group-props.c delete mode 100644 src/x11/group-props.h delete mode 100644 src/x11/group.c delete mode 100644 src/x11/iconcache.c delete mode 100644 src/x11/iconcache.h delete mode 100644 src/x11/meta-selection-source-x11-private.h delete mode 100644 src/x11/meta-selection-source-x11.c delete mode 100644 src/x11/meta-startup-notification-x11.c delete mode 100644 src/x11/meta-startup-notification-x11.h delete mode 100644 src/x11/meta-x11-display-private.h delete mode 100644 src/x11/meta-x11-display.c delete mode 100644 src/x11/meta-x11-errors.c delete mode 100644 src/x11/meta-x11-selection-input-stream-private.h delete mode 100644 src/x11/meta-x11-selection-input-stream.c delete mode 100644 src/x11/meta-x11-selection-output-stream-private.h delete mode 100644 src/x11/meta-x11-selection-output-stream.c delete mode 100644 src/x11/meta-x11-selection-private.h delete mode 100644 src/x11/meta-x11-selection.c delete mode 100644 src/x11/meta-x11-stack-private.h delete mode 100644 src/x11/meta-x11-stack.c delete mode 100644 src/x11/meta-x11-window-control.c delete mode 100644 src/x11/meta-x11-window-control.h delete mode 100644 src/x11/mutter-Xatomtype.h delete mode 100644 src/x11/session.c delete mode 100644 src/x11/session.h delete mode 100644 src/x11/window-props.c delete mode 100644 src/x11/window-props.h delete mode 100644 src/x11/window-x11-private.h delete mode 100644 src/x11/window-x11.c delete mode 100644 src/x11/window-x11.h delete mode 100644 src/x11/xprops.c delete mode 100644 src/x11/xprops.h (limited to 'src') diff --git a/src/backends/edid-parse.c b/src/backends/edid-parse.c deleted file mode 100644 index a7b9fd225..000000000 --- a/src/backends/edid-parse.c +++ /dev/null @@ -1,542 +0,0 @@ -/* - * Copyright 2007 Red Hat, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* Author: Soren Sandmann */ - -#include "config.h" - -#include -#include -#include -#include - -#include "backends/edid.h" - -static int -get_bit (int in, int bit) -{ - return (in & (1 << bit)) >> bit; -} - -static int -get_bits (int in, int begin, int end) -{ - int mask = (1 << (end - begin + 1)) - 1; - - return (in >> begin) & mask; -} - -static int -decode_header (const uchar *edid) -{ - if (memcmp (edid, "\x00\xff\xff\xff\xff\xff\xff\x00", 8) == 0) - return TRUE; - return FALSE; -} - -static int -decode_vendor_and_product_identification (const uchar *edid, MonitorInfo *info) -{ - int is_model_year; - - /* Manufacturer Code */ - info->manufacturer_code[0] = get_bits (edid[0x08], 2, 6); - info->manufacturer_code[1] = get_bits (edid[0x08], 0, 1) << 3; - info->manufacturer_code[1] |= get_bits (edid[0x09], 5, 7); - info->manufacturer_code[2] = get_bits (edid[0x09], 0, 4); - info->manufacturer_code[3] = '\0'; - - info->manufacturer_code[0] += 'A' - 1; - info->manufacturer_code[1] += 'A' - 1; - info->manufacturer_code[2] += 'A' - 1; - - /* Product Code */ - info->product_code = edid[0x0b] << 8 | edid[0x0a]; - - /* Serial Number */ - info->serial_number = - edid[0x0c] | edid[0x0d] << 8 | edid[0x0e] << 16 | edid[0x0f] << 24; - - /* Week and Year */ - is_model_year = FALSE; - switch (edid[0x10]) - { - case 0x00: - info->production_week = -1; - break; - - case 0xff: - info->production_week = -1; - is_model_year = TRUE; - break; - - default: - info->production_week = edid[0x10]; - break; - } - - if (is_model_year) - { - info->production_year = -1; - info->model_year = 1990 + edid[0x11]; - } - else - { - info->production_year = 1990 + edid[0x11]; - info->model_year = -1; - } - - return TRUE; -} - -static int -decode_edid_version (const uchar *edid, MonitorInfo *info) -{ - info->major_version = edid[0x12]; - info->minor_version = edid[0x13]; - - return TRUE; -} - -static int -decode_display_parameters (const uchar *edid, MonitorInfo *info) -{ - /* Digital vs Analog */ - info->is_digital = get_bit (edid[0x14], 7); - - if (info->is_digital) - { - int bits; - - static const int bit_depth[8] = - { - -1, 6, 8, 10, 12, 14, 16, -1 - }; - - static const Interface interfaces[6] = - { - UNDEFINED, DVI, HDMI_A, HDMI_B, MDDI, DISPLAY_PORT - }; - - bits = get_bits (edid[0x14], 4, 6); - info->connector.digital.bits_per_primary = bit_depth[bits]; - - bits = get_bits (edid[0x14], 0, 3); - - if (bits <= 5) - info->connector.digital.interface = interfaces[bits]; - else - info->connector.digital.interface = UNDEFINED; - } - else - { - int bits = get_bits (edid[0x14], 5, 6); - - static const double levels[][3] = - { - { 0.7, 0.3, 1.0 }, - { 0.714, 0.286, 1.0 }, - { 1.0, 0.4, 1.4 }, - { 0.7, 0.0, 0.7 }, - }; - - info->connector.analog.video_signal_level = levels[bits][0]; - info->connector.analog.sync_signal_level = levels[bits][1]; - info->connector.analog.total_signal_level = levels[bits][2]; - - info->connector.analog.blank_to_black = get_bit (edid[0x14], 4); - - info->connector.analog.separate_hv_sync = get_bit (edid[0x14], 3); - info->connector.analog.composite_sync_on_h = get_bit (edid[0x14], 2); - info->connector.analog.composite_sync_on_green = get_bit (edid[0x14], 1); - - info->connector.analog.serration_on_vsync = get_bit (edid[0x14], 0); - } - - /* Screen Size / Aspect Ratio */ - if (edid[0x15] == 0 && edid[0x16] == 0) - { - info->width_mm = -1; - info->height_mm = -1; - info->aspect_ratio = -1.0; - } - else if (edid[0x16] == 0) - { - info->width_mm = -1; - info->height_mm = -1; - info->aspect_ratio = 100.0 / (edid[0x15] + 99); - } - else if (edid[0x15] == 0) - { - info->width_mm = -1; - info->height_mm = -1; - info->aspect_ratio = 100.0 / (edid[0x16] + 99); - info->aspect_ratio = 1/info->aspect_ratio; /* portrait */ - } - else - { - info->width_mm = 10 * edid[0x15]; - info->height_mm = 10 * edid[0x16]; - } - - /* Gamma */ - if (edid[0x17] == 0xFF) - info->gamma = -1.0; - else - info->gamma = (edid[0x17] + 100.0) / 100.0; - - /* Features */ - info->standby = get_bit (edid[0x18], 7); - info->suspend = get_bit (edid[0x18], 6); - info->active_off = get_bit (edid[0x18], 5); - - if (info->is_digital) - { - info->connector.digital.rgb444 = TRUE; - if (get_bit (edid[0x18], 3)) - info->connector.digital.ycrcb444 = 1; - if (get_bit (edid[0x18], 4)) - info->connector.digital.ycrcb422 = 1; - } - else - { - int bits = get_bits (edid[0x18], 3, 4); - ColorType color_type[4] = - { - MONOCHROME, RGB, OTHER_COLOR, UNDEFINED_COLOR - }; - - info->connector.analog.color_type = color_type[bits]; - } - - info->srgb_is_standard = get_bit (edid[0x18], 2); - - /* In 1.3 this is called "has preferred timing" */ - info->preferred_timing_includes_native = get_bit (edid[0x18], 1); - - /* FIXME: In 1.3 this indicates whether the monitor accepts GTF */ - info->continuous_frequency = get_bit (edid[0x18], 0); - return TRUE; -} - -static double -decode_fraction (int high, int low) -{ - double result = 0.0; - int i; - - high = (high << 2) | low; - - for (i = 0; i < 10; ++i) - result += get_bit (high, i) * pow (2, i - 10); - - return result; -} - -static int -decode_color_characteristics (const uchar *edid, MonitorInfo *info) -{ - info->red_x = decode_fraction (edid[0x1b], get_bits (edid[0x19], 6, 7)); - info->red_y = decode_fraction (edid[0x1c], get_bits (edid[0x19], 5, 4)); - info->green_x = decode_fraction (edid[0x1d], get_bits (edid[0x19], 2, 3)); - info->green_y = decode_fraction (edid[0x1e], get_bits (edid[0x19], 0, 1)); - info->blue_x = decode_fraction (edid[0x1f], get_bits (edid[0x1a], 6, 7)); - info->blue_y = decode_fraction (edid[0x20], get_bits (edid[0x1a], 4, 5)); - info->white_x = decode_fraction (edid[0x21], get_bits (edid[0x1a], 2, 3)); - info->white_y = decode_fraction (edid[0x22], get_bits (edid[0x1a], 0, 1)); - - return TRUE; -} - -static int -decode_established_timings (const uchar *edid, MonitorInfo *info) -{ - static const Timing established[][8] = - { - { - { 800, 600, 60 }, - { 800, 600, 56 }, - { 640, 480, 75 }, - { 640, 480, 72 }, - { 640, 480, 67 }, - { 640, 480, 60 }, - { 720, 400, 88 }, - { 720, 400, 70 } - }, - { - { 1280, 1024, 75 }, - { 1024, 768, 75 }, - { 1024, 768, 70 }, - { 1024, 768, 60 }, - { 1024, 768, 87 }, - { 832, 624, 75 }, - { 800, 600, 75 }, - { 800, 600, 72 } - }, - { - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 }, - { 0, 0, 0 }, - { 1152, 870, 75 } - }, - }; - - int i, j, idx; - - idx = 0; - for (i = 0; i < 3; ++i) - { - for (j = 0; j < 8; ++j) - { - int byte = edid[0x23 + i]; - - if (get_bit (byte, j) && established[i][j].frequency != 0) - info->established[idx++] = established[i][j]; - } - } - return TRUE; -} - -static int -decode_standard_timings (const uchar *edid, MonitorInfo *info) -{ - int i; - - for (i = 0; i < 8; i++) - { - int first = edid[0x26 + 2 * i]; - int second = edid[0x27 + 2 * i]; - - if (first != 0x01 && second != 0x01) - { - int w = 8 * (first + 31); - int h = 0; - - switch (get_bits (second, 6, 7)) - { - case 0x00: h = (w / 16) * 10; break; - case 0x01: h = (w / 4) * 3; break; - case 0x02: h = (w / 5) * 4; break; - case 0x03: h = (w / 16) * 9; break; - } - - info->standard[i].width = w; - info->standard[i].height = h; - info->standard[i].frequency = get_bits (second, 0, 5) + 60; - } - } - - return TRUE; -} - -static void -decode_lf_string (const uchar *s, int n_chars, char *result) -{ - int i; - for (i = 0; i < n_chars; ++i) - { - if (s[i] == 0x0a) - { - *result++ = '\0'; - break; - } - else if (s[i] == 0x00) - { - /* Convert embedded 0's to spaces */ - *result++ = ' '; - } - else - { - *result++ = s[i]; - } - } -} - -static void -decode_display_descriptor (const uchar *desc, - MonitorInfo *info) -{ - switch (desc[0x03]) - { - case 0xFC: - decode_lf_string (desc + 5, 13, info->dsc_product_name); - break; - case 0xFF: - decode_lf_string (desc + 5, 13, info->dsc_serial_number); - break; - case 0xFE: - decode_lf_string (desc + 5, 13, info->dsc_string); - break; - case 0xFD: - /* Range Limits */ - break; - case 0xFB: - /* Color Point */ - break; - case 0xFA: - /* Timing Identifications */ - break; - case 0xF9: - /* Color Management */ - break; - case 0xF8: - /* Timing Codes */ - break; - case 0xF7: - /* Established Timings */ - break; - case 0x10: - break; - } -} - -static void -decode_detailed_timing (const uchar *timing, - DetailedTiming *detailed) -{ - int bits; - StereoType stereo[] = - { - NO_STEREO, NO_STEREO, FIELD_RIGHT, FIELD_LEFT, - TWO_WAY_RIGHT_ON_EVEN, TWO_WAY_LEFT_ON_EVEN, - FOUR_WAY_INTERLEAVED, SIDE_BY_SIDE - }; - - detailed->pixel_clock = (timing[0x00] | timing[0x01] << 8) * 10000; - detailed->h_addr = timing[0x02] | ((timing[0x04] & 0xf0) << 4); - detailed->h_blank = timing[0x03] | ((timing[0x04] & 0x0f) << 8); - detailed->v_addr = timing[0x05] | ((timing[0x07] & 0xf0) << 4); - detailed->v_blank = timing[0x06] | ((timing[0x07] & 0x0f) << 8); - detailed->h_front_porch = timing[0x08] | get_bits (timing[0x0b], 6, 7) << 8; - detailed->h_sync = timing[0x09] | get_bits (timing[0x0b], 4, 5) << 8; - detailed->v_front_porch = - get_bits (timing[0x0a], 4, 7) | get_bits (timing[0x0b], 2, 3) << 4; - detailed->v_sync = - get_bits (timing[0x0a], 0, 3) | get_bits (timing[0x0b], 0, 1) << 4; - detailed->width_mm = timing[0x0c] | get_bits (timing[0x0e], 4, 7) << 8; - detailed->height_mm = timing[0x0d] | get_bits (timing[0x0e], 0, 3) << 8; - detailed->right_border = timing[0x0f]; - detailed->top_border = timing[0x10]; - - detailed->interlaced = get_bit (timing[0x11], 7); - - /* Stereo */ - bits = get_bits (timing[0x11], 5, 6) << 1 | get_bit (timing[0x11], 0); - detailed->stereo = stereo[bits]; - - /* Sync */ - bits = timing[0x11]; - - detailed->digital_sync = get_bit (bits, 4); - if (detailed->digital_sync) - { - detailed->connector.digital.composite = !get_bit (bits, 3); - - if (detailed->connector.digital.composite) - { - detailed->connector.digital.serrations = get_bit (bits, 2); - detailed->connector.digital.negative_vsync = FALSE; - } - else - { - detailed->connector.digital.serrations = FALSE; - detailed->connector.digital.negative_vsync = !get_bit (bits, 2); - } - - detailed->connector.digital.negative_hsync = !get_bit (bits, 0); - } - else - { - detailed->connector.analog.bipolar = get_bit (bits, 3); - detailed->connector.analog.serrations = get_bit (bits, 2); - detailed->connector.analog.sync_on_green = !get_bit (bits, 1); - } -} - -static int -decode_descriptors (const uchar *edid, MonitorInfo *info) -{ - int i; - int timing_idx; - - timing_idx = 0; - - for (i = 0; i < 4; ++i) - { - int index = 0x36 + i * 18; - - if (edid[index + 0] == 0x00 && edid[index + 1] == 0x00) - { - decode_display_descriptor (edid + index, info); - } - else - { - decode_detailed_timing (edid + index, &(info->detailed_timings[timing_idx++])); - } - } - - info->n_detailed_timings = timing_idx; - - return TRUE; -} - -static void -decode_check_sum (const uchar *edid, - MonitorInfo *info) -{ - int i; - uchar check = 0; - - for (i = 0; i < 128; ++i) - check += edid[i]; - - info->checksum = check; -} - -MonitorInfo * -decode_edid (const uchar *edid) -{ - MonitorInfo *info = g_new0 (MonitorInfo, 1); - - decode_check_sum (edid, info); - - if (decode_header (edid) - && decode_vendor_and_product_identification (edid, info) - && decode_edid_version (edid, info) - && decode_display_parameters (edid, info) - && decode_color_characteristics (edid, info) - && decode_established_timings (edid, info) - && decode_standard_timings (edid, info) - && decode_descriptors (edid, info)) - { - return info; - } - else - { - g_free (info); - return NULL; - } -} diff --git a/src/backends/edid.h b/src/backends/edid.h deleted file mode 100644 index f07fd9e55..000000000 --- a/src/backends/edid.h +++ /dev/null @@ -1,193 +0,0 @@ -/* edid.h - * - * Copyright 2007, 2008, Red Hat, Inc. - * - * This file is part of the Gnome Library. - * - * The Gnome Library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * The Gnome 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with the Gnome Library; see the file COPYING.LIB. If not, - * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - * Author: Soren Sandmann - */ - -#ifndef EDID_H -#define EDID_H - -typedef unsigned char uchar; -typedef struct MonitorInfo MonitorInfo; -typedef struct Timing Timing; -typedef struct DetailedTiming DetailedTiming; - -typedef enum -{ - UNDEFINED, - DVI, - HDMI_A, - HDMI_B, - MDDI, - DISPLAY_PORT -} Interface; - -typedef enum -{ - UNDEFINED_COLOR, - MONOCHROME, - RGB, - OTHER_COLOR -} ColorType; - -typedef enum -{ - NO_STEREO, - FIELD_RIGHT, - FIELD_LEFT, - TWO_WAY_RIGHT_ON_EVEN, - TWO_WAY_LEFT_ON_EVEN, - FOUR_WAY_INTERLEAVED, - SIDE_BY_SIDE -} StereoType; - -struct Timing -{ - int width; - int height; - int frequency; -}; - -struct DetailedTiming -{ - int pixel_clock; - int h_addr; - int h_blank; - int h_sync; - int h_front_porch; - int v_addr; - int v_blank; - int v_sync; - int v_front_porch; - int width_mm; - int height_mm; - int right_border; - int top_border; - int interlaced; - StereoType stereo; - - int digital_sync; - union - { - struct - { - int bipolar; - int serrations; - int sync_on_green; - } analog; - - struct - { - int composite; - int serrations; - int negative_vsync; - int negative_hsync; - } digital; - } connector; -}; - -struct MonitorInfo -{ - int checksum; - char manufacturer_code[4]; - int product_code; - unsigned int serial_number; - - int production_week; /* -1 if not specified */ - int production_year; /* -1 if not specified */ - int model_year; /* -1 if not specified */ - - int major_version; - int minor_version; - - int is_digital; - - union - { - struct - { - int bits_per_primary; - Interface interface; - int rgb444; - int ycrcb444; - int ycrcb422; - } digital; - - struct - { - double video_signal_level; - double sync_signal_level; - double total_signal_level; - - int blank_to_black; - - int separate_hv_sync; - int composite_sync_on_h; - int composite_sync_on_green; - int serration_on_vsync; - ColorType color_type; - } analog; - } connector; - - int width_mm; /* -1 if not specified */ - int height_mm; /* -1 if not specified */ - double aspect_ratio; /* -1.0 if not specififed */ - - double gamma; /* -1.0 if not specified */ - - int standby; - int suspend; - int active_off; - - int srgb_is_standard; - int preferred_timing_includes_native; - int continuous_frequency; - - double red_x; - double red_y; - double green_x; - double green_y; - double blue_x; - double blue_y; - double white_x; - double white_y; - - Timing established[24]; /* Terminated by 0x0x0 */ - Timing standard[8]; - - int n_detailed_timings; - DetailedTiming detailed_timings[4]; /* If monitor has a preferred - * mode, it is the first one - * (whether it has, is - * determined by the - * preferred_timing_includes - * bit. - */ - - /* Optional product description */ - char dsc_serial_number[14]; - char dsc_product_name[14]; - char dsc_string[14]; /* Unspecified ASCII data */ -}; - -MonitorInfo *decode_edid (const uchar *data); - -#endif diff --git a/src/backends/gsm-inhibitor-flag.h b/src/backends/gsm-inhibitor-flag.h deleted file mode 100644 index 40698f96a..000000000 --- a/src/backends/gsm-inhibitor-flag.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * Copyright (C) 2008 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 - * Lesser 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 . - */ - -#ifndef __GSM_INHIBITOR_FLAG_H__ -#define __GSM_INHIBITOR_FLAG_H__ - -#include - -G_BEGIN_DECLS - -typedef enum { - GSM_INHIBITOR_FLAG_LOGOUT = 1 << 0, - GSM_INHIBITOR_FLAG_SWITCH_USER = 1 << 1, - GSM_INHIBITOR_FLAG_SUSPEND = 1 << 2, - GSM_INHIBITOR_FLAG_IDLE = 1 << 3, - GSM_INHIBITOR_FLAG_AUTOMOUNT = 1 << 4 -} GsmInhibitorFlag; - -G_END_DECLS - -#endif /* __GSM_INHIBITOR_FLAG_H__ */ diff --git a/src/backends/meta-backend-private.h b/src/backends/meta-backend-private.h deleted file mode 100644 index 81104e2d0..000000000 --- a/src/backends/meta-backend-private.h +++ /dev/null @@ -1,203 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - - -#ifndef META_BACKEND_PRIVATE_H -#define META_BACKEND_PRIVATE_H - -#include -#include - -#include "meta/meta-backend.h" -#include "meta/meta-idle-monitor.h" -#include "backends/meta-backend-types.h" -#include "backends/meta-cursor-renderer.h" -#include "backends/meta-egl.h" -#include "backends/meta-input-mapper-private.h" -#include "backends/meta-input-settings-private.h" -#include "backends/meta-monitor-manager-private.h" -#include "backends/meta-orientation-manager.h" -#include "backends/meta-pointer-constraint.h" -#include "backends/meta-renderer.h" -#include "backends/meta-settings-private.h" -#include "core/meta-context-private.h" -#include "core/util-private.h" - -#define DEFAULT_XKB_RULES_FILE "evdev" -#define DEFAULT_XKB_MODEL "pc105+inet" - -typedef enum -{ - META_SEQUENCE_NONE, - META_SEQUENCE_ACCEPTED, - META_SEQUENCE_REJECTED, - META_SEQUENCE_PENDING_END -} MetaSequenceState; - -struct _MetaBackendClass -{ - GObjectClass parent_class; - - ClutterBackend * (* create_clutter_backend) (MetaBackend *backend); - - void (* post_init) (MetaBackend *backend); - - MetaMonitorManager * (* create_monitor_manager) (MetaBackend *backend, - GError **error); - MetaCursorRenderer * (* get_cursor_renderer) (MetaBackend *backend, - ClutterInputDevice *device); - MetaCursorTracker * (* create_cursor_tracker) (MetaBackend *backend); - MetaRenderer * (* create_renderer) (MetaBackend *backend, - GError **error); - MetaInputSettings * (* get_input_settings) (MetaBackend *backend); - - ClutterSeat * (* create_default_seat) (MetaBackend *backend, - GError **error); - - gboolean (* grab_device) (MetaBackend *backend, - int device_id, - uint32_t timestamp); - gboolean (* ungrab_device) (MetaBackend *backend, - int device_id, - uint32_t timestamp); - - void (* finish_touch_sequence) (MetaBackend *backend, - ClutterEventSequence *sequence, - MetaSequenceState state); - MetaLogicalMonitor * (* get_current_logical_monitor) (MetaBackend *backend); - - void (* set_keymap) (MetaBackend *backend, - const char *layouts, - const char *variants, - const char *options); - - gboolean (* is_lid_closed) (MetaBackend *backend); - - struct xkb_keymap * (* get_keymap) (MetaBackend *backend); - - xkb_layout_index_t (* get_keymap_layout_group) (MetaBackend *backend); - - void (* lock_layout_group) (MetaBackend *backend, - guint idx); - - void (* update_screen_size) (MetaBackend *backend, int width, int height); - void (* select_stage_events) (MetaBackend *backend); - - void (* set_pointer_constraint) (MetaBackend *backend, - MetaPointerConstraint *constraint); -}; - -void meta_backend_destroy (MetaBackend *backend); - -void meta_backend_prepare_shutdown (MetaBackend *backend); - -ClutterBackend * meta_backend_get_clutter_backend (MetaBackend *backend); - -ClutterSeat * meta_backend_get_default_seat (MetaBackend *bakcend); - -MetaIdleMonitor * meta_backend_get_idle_monitor (MetaBackend *backend, - ClutterInputDevice *device); - -MetaIdleManager * meta_backend_get_idle_manager (MetaBackend *backend); - -META_EXPORT_TEST -MetaMonitorManager * meta_backend_get_monitor_manager (MetaBackend *backend); -MetaOrientationManager * meta_backend_get_orientation_manager (MetaBackend *backend); -MetaCursorTracker * meta_backend_get_cursor_tracker (MetaBackend *backend); -MetaCursorRenderer * meta_backend_get_cursor_renderer_for_device (MetaBackend *backend, - ClutterInputDevice *device); -MetaCursorRenderer * meta_backend_get_cursor_renderer (MetaBackend *backend); -META_EXPORT_TEST -MetaRenderer * meta_backend_get_renderer (MetaBackend *backend); -MetaEgl * meta_backend_get_egl (MetaBackend *backend); - -#ifdef HAVE_REMOTE_DESKTOP -MetaRemoteDesktop * meta_backend_get_remote_desktop (MetaBackend *backend); - -MetaScreenCast * meta_backend_get_screen_cast (MetaBackend *backend); -#endif - -gboolean meta_backend_grab_device (MetaBackend *backend, - int device_id, - uint32_t timestamp); -gboolean meta_backend_ungrab_device (MetaBackend *backend, - int device_id, - uint32_t timestamp); - -void meta_backend_finish_touch_sequence (MetaBackend *backend, - ClutterEventSequence *sequence, - MetaSequenceState state); - -MetaLogicalMonitor * meta_backend_get_current_logical_monitor (MetaBackend *backend); - -struct xkb_keymap * meta_backend_get_keymap (MetaBackend *backend); - -xkb_layout_index_t meta_backend_get_keymap_layout_group (MetaBackend *backend); - -gboolean meta_backend_is_lid_closed (MetaBackend *backend); - -void meta_backend_update_last_device (MetaBackend *backend, - ClutterInputDevice *device); - -MetaPointerConstraint * meta_backend_get_client_pointer_constraint (MetaBackend *backend); -void meta_backend_set_client_pointer_constraint (MetaBackend *backend, - MetaPointerConstraint *constraint); - -void meta_backend_monitors_changed (MetaBackend *backend); - -META_EXPORT_TEST -gboolean meta_is_stage_views_enabled (void); - -gboolean meta_is_stage_views_scaled (void); - -MetaInputMapper *meta_backend_get_input_mapper (MetaBackend *backend); -MetaInputSettings *meta_backend_get_input_settings (MetaBackend *backend); - -void meta_backend_notify_keymap_changed (MetaBackend *backend); - -void meta_backend_notify_keymap_layout_group_changed (MetaBackend *backend, - unsigned int locked_group); - -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); - -#ifdef HAVE_LIBWACOM -WacomDeviceDatabase * meta_backend_get_wacom_database (MetaBackend *backend); -#endif - -void meta_backend_add_hw_cursor_inhibitor (MetaBackend *backend, - MetaHwCursorInhibitor *inhibitor); - -void meta_backend_remove_hw_cursor_inhibitor (MetaBackend *backend, - MetaHwCursorInhibitor *inhibitor); - -gboolean meta_backend_is_hw_cursors_inhibited (MetaBackend *backend); - -#endif /* META_BACKEND_PRIVATE_H */ diff --git a/src/backends/meta-backend-types.h b/src/backends/meta-backend-types.h deleted file mode 100644 index c5e46d87a..000000000 --- a/src/backends/meta-backend-types.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * Copyright (C) 2013-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 . - */ - -#ifndef META_BACKEND_TYPE_H -#define META_BACKEND_TYPE_H - -typedef struct _MetaBackend MetaBackend; - -typedef struct _MetaMonitorManager MetaMonitorManager; - -typedef struct _MetaMonitorConfigManager MetaMonitorConfigManager; -typedef struct _MetaMonitorConfigStore MetaMonitorConfigStore; -typedef struct _MetaMonitorsConfig MetaMonitorsConfig; - -typedef struct _MetaMonitor MetaMonitor; -typedef struct _MetaMonitorNormal MetaMonitorNormal; -typedef struct _MetaMonitorTiled MetaMonitorTiled; -typedef struct _MetaMonitorSpec MetaMonitorSpec; -typedef struct _MetaLogicalMonitor MetaLogicalMonitor; - -typedef enum _MetaMonitorTransform MetaMonitorTransform; - -typedef struct _MetaMonitorMode MetaMonitorMode; - -typedef struct _MetaGpu MetaGpu; - -typedef struct _MetaCrtc MetaCrtc; -typedef struct _MetaOutput MetaOutput; -typedef struct _MetaCrtcMode MetaCrtcMode; -typedef struct _MetaCrtcAssignment MetaCrtcAssignment; -typedef struct _MetaOutputAssignment MetaOutputAssignment; - -typedef struct _MetaTileInfo MetaTileInfo; - -typedef struct _MetaRenderer MetaRenderer; -typedef struct _MetaRendererView MetaRendererView; - -typedef struct _MetaRemoteDesktop MetaRemoteDesktop; -typedef struct _MetaScreenCast MetaScreenCast; -typedef struct _MetaScreenCastSession MetaScreenCastSession; -typedef struct _MetaScreenCastStream MetaScreenCastStream; - -typedef struct _MetaVirtualMonitor MetaVirtualMonitor; -typedef struct _MetaVirtualMonitorInfo MetaVirtualMonitorInfo; - -typedef struct _MetaIdleManager MetaIdleManager; - -#ifdef HAVE_REMOTE_DESKTOP -typedef struct _MetaRemoteDesktop MetaRemoteDesktop; -#endif - -#endif /* META_BACKEND_TYPE_H */ diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c deleted file mode 100644 index d4cd5d10f..000000000 --- a/src/backends/meta-backend.c +++ /dev/null @@ -1,1663 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -/** - * SECTION:meta-backend - * @title: MetaBackend - * @short_description: Handles monitor config, modesetting, cursor sprites, ... - * - * MetaBackend is the abstraction that deals with several things like: - * - Modesetting (depending on the backend, this can be done either by X or KMS) - * - Initializing the #MetaSettings - * - Setting up Monitor configuration - * - Input device configuration (using the #ClutterDeviceManager) - * - Creating the #MetaRenderer - * - Setting up the stage of the scene graph (using #MetaStage) - * - Creating the object that deals with the cursor (using #MetaCursorTracker) - * and its possible pointer constraint (using #MetaPointerConstraint) - * - Setting the cursor sprite (using #MetaCursorRenderer) - * - Interacting with logind (using the appropriate D-Bus interface) - * - Querying UPower (over D-Bus) to know when the lid is closed - * - Setup Remote Desktop / Screencasting (#MetaRemoteDesktop) - * - Setup the #MetaEgl object - * - * Note that the #MetaBackend is not a subclass of #ClutterBackend. It is - * responsible for creating the correct one, based on the backend that is - * used (#MetaBackendNative or #MetaBackendX11). - */ - -#include "config.h" - -#include "backends/meta-backend-private.h" - -#include - -#include "backends/meta-cursor-renderer.h" -#include "backends/meta-cursor-tracker-private.h" -#include "backends/meta-idle-manager.h" -#include "backends/meta-idle-monitor-private.h" -#include "backends/meta-input-mapper-private.h" -#include "backends/meta-input-settings-private.h" -#include "backends/meta-logical-monitor.h" -#include "backends/meta-monitor-manager-dummy.h" -#include "backends/meta-settings-private.h" -#include "backends/meta-stage-private.h" -#include "backends/x11/meta-backend-x11.h" -#include "clutter/clutter-mutter.h" -#include "clutter/clutter-seat-private.h" -#include "core/meta-context-private.h" -#include "meta/main.h" -#include "meta/meta-backend.h" -#include "meta/meta-context.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" -#include "backends/meta-remote-desktop.h" -#include "backends/meta-screen-cast.h" -#endif - -#ifdef HAVE_NATIVE_BACKEND -#include "backends/native/meta-backend-native.h" -#endif - -#ifdef HAVE_WAYLAND -#include "wayland/meta-wayland.h" -#endif - -enum -{ - PROP_0, - - PROP_CONTEXT, - - N_PROPS -}; - -static GParamSpec *obj_props[N_PROPS]; - -enum -{ - KEYMAP_CHANGED, - KEYMAP_LAYOUT_GROUP_CHANGED, - LAST_DEVICE_CHANGED, - LID_IS_CLOSED_CHANGED, - GPU_ADDED, - PREPARE_SHUTDOWN, - - N_SIGNALS -}; - -static guint signals[N_SIGNALS]; - -static MetaBackend *_backend; - -static gboolean stage_views_disabled = FALSE; - -/** - * meta_get_backend: - * - * Accessor for the singleton MetaBackend. - * - * Returns: (transfer none): The only #MetaBackend there is. - */ -MetaBackend * -meta_get_backend (void) -{ - return _backend; -} - -struct _MetaBackendPrivate -{ - MetaContext *context; - - MetaMonitorManager *monitor_manager; - MetaOrientationManager *orientation_manager; - MetaCursorTracker *cursor_tracker; - MetaInputMapper *input_mapper; - MetaIdleManager *idle_manager; - MetaRenderer *renderer; -#ifdef HAVE_EGL - MetaEgl *egl; -#endif - MetaSettings *settings; -#ifdef HAVE_REMOTE_DESKTOP - MetaRemoteAccessController *remote_access_controller; - MetaDbusSessionWatcher *dbus_session_watcher; - MetaScreenCast *screen_cast; - MetaRemoteDesktop *remote_desktop; -#endif - -#ifdef HAVE_PROFILER - MetaProfiler *profiler; -#endif - -#ifdef HAVE_LIBWACOM - WacomDeviceDatabase *wacom_db; -#endif - - ClutterBackend *clutter_backend; - ClutterSeat *default_seat; - ClutterActor *stage; - - GList *gpus; - GList *hw_cursor_inhibitors; - - gboolean is_pointer_position_initialized; - - guint device_update_idle_id; - - ClutterInputDevice *current_device; - - MetaPointerConstraint *client_pointer_constraint; - MetaDnd *dnd; - - guint upower_watch_id; - GDBusProxy *upower_proxy; - gboolean lid_is_closed; - - guint sleep_signal_id; - GCancellable *cancellable; - GDBusConnection *system_bus; -}; -typedef struct _MetaBackendPrivate MetaBackendPrivate; - -typedef struct _MetaBackendSource MetaBackendSource; - -struct _MetaBackendSource -{ - GSource parent; - MetaBackend *backend; -}; - -static void -initable_iface_init (GInitableIface *initable_iface); - -G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaBackend, meta_backend, G_TYPE_OBJECT, - G_ADD_PRIVATE (MetaBackend) - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - initable_iface_init)); - -static void -meta_backend_dispose (GObject *object) -{ - MetaBackend *backend = META_BACKEND (object); - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - _backend = NULL; - - g_clear_pointer (&priv->cursor_tracker, meta_cursor_tracker_destroy); - g_clear_object (&priv->current_device); - g_clear_object (&priv->monitor_manager); - g_clear_object (&priv->orientation_manager); -#ifdef HAVE_REMOTE_DESKTOP - g_clear_object (&priv->remote_desktop); - g_clear_object (&priv->screen_cast); - g_clear_object (&priv->dbus_session_watcher); - g_clear_object (&priv->remote_access_controller); -#endif - -#ifdef HAVE_LIBWACOM - g_clear_pointer (&priv->wacom_db, libwacom_database_destroy); -#endif - - if (priv->sleep_signal_id) - { - g_dbus_connection_signal_unsubscribe (priv->system_bus, priv->sleep_signal_id); - priv->sleep_signal_id = 0; - } - - if (priv->upower_watch_id) - { - g_bus_unwatch_name (priv->upower_watch_id); - priv->upower_watch_id = 0; - } - - g_cancellable_cancel (priv->cancellable); - g_clear_object (&priv->cancellable); - g_clear_object (&priv->system_bus); - g_clear_object (&priv->upower_proxy); - - g_clear_handle_id (&priv->device_update_idle_id, g_source_remove); - - g_clear_object (&priv->settings); - -#ifdef HAVE_PROFILER - g_clear_object (&priv->profiler); -#endif - - g_clear_pointer (&priv->default_seat, clutter_seat_destroy); - g_clear_pointer (&priv->stage, clutter_actor_destroy); - g_clear_pointer (&priv->clutter_backend, clutter_backend_destroy); - g_clear_pointer (&priv->idle_manager, meta_idle_manager_free); - g_clear_object (&priv->renderer); - g_clear_list (&priv->gpus, g_object_unref); - - G_OBJECT_CLASS (meta_backend_parent_class)->dispose (object); -} - -void -meta_backend_destroy (MetaBackend *backend) -{ - g_object_run_dispose (G_OBJECT (backend)); - g_object_unref (backend); -} - -static void -meta_backend_sync_screen_size (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - int width, height; - - meta_monitor_manager_get_screen_size (priv->monitor_manager, &width, &height); - - META_BACKEND_GET_CLASS (backend)->update_screen_size (backend, width, height); -} - -static void -reset_pointer_position (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - MetaMonitorManager *monitor_manager = priv->monitor_manager; - ClutterSeat *seat = clutter_backend_get_default_seat (priv->clutter_backend); - MetaLogicalMonitor *primary; - - primary = - meta_monitor_manager_get_primary_logical_monitor (monitor_manager); - - /* Move the pointer out of the way to avoid hovering over reactive - * elements (e.g. users list at login) causing undesired behaviour. */ - clutter_seat_warp_pointer (seat, - primary->rect.x + primary->rect.width * 0.9, - primary->rect.y + primary->rect.height * 0.9); -} - -static gboolean -should_have_cursor_renderer (ClutterInputDevice *device) -{ - switch (clutter_input_device_get_device_type (device)) - { - case CLUTTER_POINTER_DEVICE: - if (clutter_input_device_get_device_mode (device) == - CLUTTER_INPUT_MODE_LOGICAL) - return TRUE; - - return FALSE; - case CLUTTER_TABLET_DEVICE: - return TRUE; - default: - return FALSE; - } -} - -static void -update_cursors (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - ClutterSeat *seat = clutter_backend_get_default_seat (priv->clutter_backend); - MetaCursorRenderer *cursor_renderer; - ClutterInputDevice *pointer, *device; - GList *devices, *l; - - pointer = clutter_seat_get_pointer (seat); - devices = clutter_seat_list_devices (seat); - devices = g_list_prepend (devices, pointer); - - for (l = devices; l; l = l->next) - { - device = l->data; - - if (!should_have_cursor_renderer (device)) - continue; - - cursor_renderer = meta_backend_get_cursor_renderer_for_device (backend, - device); - if (cursor_renderer) - meta_cursor_renderer_force_update (cursor_renderer); - } - - g_list_free (devices); -} - -void -meta_backend_monitors_changed (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - ClutterSeat *seat = clutter_backend_get_default_seat (priv->clutter_backend); - ClutterInputDevice *device = clutter_seat_get_pointer (seat); - graphene_point_t point; - - meta_backend_sync_screen_size (backend); - - if (clutter_seat_query_state (seat, device, NULL, &point, NULL)) - { - /* If we're outside all monitors, warp the pointer back inside */ - if ((!meta_monitor_manager_get_logical_monitor_at (monitor_manager, - point.x, point.y) || - !priv->is_pointer_position_initialized) && - !meta_monitor_manager_is_headless (monitor_manager)) - { - reset_pointer_position (backend); - priv->is_pointer_position_initialized = TRUE; - } - } - - update_cursors (backend); -} - -static inline gboolean -check_has_pointing_device (ClutterSeat *seat) -{ - GList *l, *devices; - gboolean found = FALSE; - - devices = clutter_seat_list_devices (seat); - - for (l = devices; l; l = l->next) - { - ClutterInputDevice *device = l->data; - - if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_LOGICAL) - continue; - if (clutter_input_device_get_device_type (device) == CLUTTER_TOUCHSCREEN_DEVICE || - clutter_input_device_get_device_type (device) == CLUTTER_KEYBOARD_DEVICE) - continue; - - found = TRUE; - break; - } - - g_list_free (devices); - - return found; -} - -static void -on_device_added (ClutterSeat *seat, - ClutterInputDevice *device, - gpointer user_data) -{ - MetaBackend *backend = META_BACKEND (user_data); - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - ClutterInputDeviceType device_type; - - if (clutter_input_device_get_device_mode (device) == - CLUTTER_INPUT_MODE_LOGICAL) - return; - - device_type = clutter_input_device_get_device_type (device); - - if (device_type == CLUTTER_TOUCHSCREEN_DEVICE) - meta_cursor_tracker_set_pointer_visible (priv->cursor_tracker, FALSE); - else if (device_type == CLUTTER_POINTER_DEVICE && - !clutter_seat_has_touchscreen (seat)) - meta_cursor_tracker_set_pointer_visible (priv->cursor_tracker, TRUE); - - if (device_type == CLUTTER_TOUCHSCREEN_DEVICE || - device_type == CLUTTER_TABLET_DEVICE || - device_type == CLUTTER_PEN_DEVICE || - device_type == CLUTTER_ERASER_DEVICE || - device_type == CLUTTER_CURSOR_DEVICE || - device_type == CLUTTER_PAD_DEVICE) - meta_input_mapper_add_device (priv->input_mapper, device); -} - -static void -on_device_removed (ClutterSeat *seat, - ClutterInputDevice *device, - gpointer user_data) -{ - MetaBackend *backend = META_BACKEND (user_data); - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - if (clutter_input_device_get_device_mode (device) == - CLUTTER_INPUT_MODE_LOGICAL) - return; - - meta_input_mapper_remove_device (priv->input_mapper, device); - - /* If the device the user last interacted goes away, check again pointer - * visibility. - */ - if (priv->current_device == device) - { - MetaCursorTracker *cursor_tracker = priv->cursor_tracker; - gboolean has_touchscreen, has_pointing_device; - ClutterInputDeviceType device_type; - - g_clear_object (&priv->current_device); - g_clear_handle_id (&priv->device_update_idle_id, g_source_remove); - - device_type = clutter_input_device_get_device_type (device); - has_touchscreen = clutter_seat_has_touchscreen (seat); - - if (device_type == CLUTTER_TOUCHSCREEN_DEVICE && has_touchscreen) - { - /* There's more touchscreens left, keep the pointer hidden */ - meta_cursor_tracker_set_pointer_visible (cursor_tracker, FALSE); - } - else if (device_type != CLUTTER_KEYBOARD_DEVICE) - { - has_pointing_device = check_has_pointing_device (seat); - meta_cursor_tracker_set_pointer_visible (cursor_tracker, - has_pointing_device && - !has_touchscreen); - } - } - - if (priv->current_device == device) - meta_backend_update_last_device (backend, NULL); -} - -static void -input_mapper_device_mapped_cb (MetaInputMapper *mapper, - ClutterInputDevice *device, - float matrix[6], - MetaInputSettings *input_settings) -{ - meta_input_settings_set_device_matrix (input_settings, device, matrix); -} - -static void -input_mapper_device_enabled_cb (MetaInputMapper *mapper, - ClutterInputDevice *device, - gboolean enabled, - MetaInputSettings *input_settings) -{ - meta_input_settings_set_device_enabled (input_settings, device, enabled); -} - -static void -input_mapper_device_aspect_ratio_cb (MetaInputMapper *mapper, - ClutterInputDevice *device, - double aspect_ratio, - MetaInputSettings *input_settings) -{ - meta_input_settings_set_device_aspect_ratio (input_settings, device, aspect_ratio); -} - -static void -on_stage_shown_cb (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - ClutterSeat *seat = clutter_backend_get_default_seat (priv->clutter_backend); - g_autoptr (GList) devices = NULL; - const GList *l; - - devices = clutter_seat_list_devices (seat); - for (l = devices; l; l = l->next) - { - ClutterInputDevice *device = l->data; - - if (clutter_input_device_get_device_mode (device) == - CLUTTER_INPUT_MODE_LOGICAL) - continue; - - if (clutter_input_device_get_device_type (device) != - CLUTTER_POINTER_DEVICE) - continue; - - meta_cursor_tracker_set_pointer_visible (priv->cursor_tracker, TRUE); - break; - } -} - -static void -meta_backend_real_post_init (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - ClutterSeat *seat = clutter_backend_get_default_seat (priv->clutter_backend); - MetaInputSettings *input_settings; - - priv->stage = meta_stage_new (backend); - clutter_actor_realize (priv->stage); - META_BACKEND_GET_CLASS (backend)->select_stage_events (backend); - g_signal_connect_object (priv->stage, "show", - G_CALLBACK (on_stage_shown_cb), backend, - G_CONNECT_SWAPPED); - - meta_monitor_manager_setup (priv->monitor_manager); - - meta_backend_sync_screen_size (backend); - - priv->idle_manager = meta_idle_manager_new (backend); - - g_signal_connect_object (seat, "device-added", - G_CALLBACK (on_device_added), backend, 0); - g_signal_connect_object (seat, "device-removed", - G_CALLBACK (on_device_removed), backend, - G_CONNECT_AFTER); - - priv->input_mapper = meta_input_mapper_new (); - - input_settings = meta_backend_get_input_settings (backend); - - if (input_settings) - { - g_signal_connect (priv->input_mapper, "device-mapped", - G_CALLBACK (input_mapper_device_mapped_cb), - input_settings); - g_signal_connect (priv->input_mapper, "device-enabled", - G_CALLBACK (input_mapper_device_enabled_cb), - input_settings); - g_signal_connect (priv->input_mapper, "device-aspect-ratio", - G_CALLBACK (input_mapper_device_aspect_ratio_cb), - input_settings); - } - -#ifdef HAVE_REMOTE_DESKTOP - priv->dbus_session_watcher = g_object_new (META_TYPE_DBUS_SESSION_WATCHER, NULL); - priv->screen_cast = meta_screen_cast_new (backend, - priv->dbus_session_watcher); - priv->remote_desktop = meta_remote_desktop_new (backend, - priv->dbus_session_watcher); - priv->remote_access_controller = - meta_remote_access_controller_new (priv->remote_desktop, priv->screen_cast); -#endif /* HAVE_REMOTE_DESKTOP */ - - if (!meta_monitor_manager_is_headless (priv->monitor_manager)) - { - reset_pointer_position (backend); - priv->is_pointer_position_initialized = TRUE; - } - - meta_monitor_manager_post_init (priv->monitor_manager); -} - -static gboolean -meta_backend_real_grab_device (MetaBackend *backend, - int device_id, - uint32_t timestamp) -{ - /* Do nothing */ - return TRUE; -} - -static gboolean -meta_backend_real_ungrab_device (MetaBackend *backend, - int device_id, - uint32_t timestamp) -{ - /* Do nothing */ - return TRUE; -} - -static void -meta_backend_real_select_stage_events (MetaBackend *backend) -{ - /* Do nothing */ -} - -static gboolean -meta_backend_real_is_lid_closed (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - return priv->lid_is_closed; -} - -static MetaCursorTracker * -meta_backend_real_create_cursor_tracker (MetaBackend *backend) -{ - return g_object_new (META_TYPE_CURSOR_TRACKER, - "backend", backend, - NULL); -} - -gboolean -meta_backend_is_lid_closed (MetaBackend *backend) -{ - return META_BACKEND_GET_CLASS (backend)->is_lid_closed (backend); -} - -static void -upower_properties_changed (GDBusProxy *proxy, - GVariant *changed_properties, - GStrv invalidated_properties, - gpointer user_data) -{ - MetaBackend *backend = user_data; - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - GVariant *v; - gboolean lid_is_closed; - - v = g_variant_lookup_value (changed_properties, - "LidIsClosed", - G_VARIANT_TYPE_BOOLEAN); - if (!v) - return; - - lid_is_closed = g_variant_get_boolean (v); - g_variant_unref (v); - - if (lid_is_closed == priv->lid_is_closed) - return; - - priv->lid_is_closed = lid_is_closed; - g_signal_emit (backend, signals[LID_IS_CLOSED_CHANGED], 0, - priv->lid_is_closed); - - if (lid_is_closed) - return; - - meta_idle_manager_reset_idle_time (priv->idle_manager); -} - -static void -upower_ready_cb (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - MetaBackend *backend; - MetaBackendPrivate *priv; - GDBusProxy *proxy; - GError *error = NULL; - GVariant *v; - - proxy = g_dbus_proxy_new_finish (res, &error); - if (!proxy) - { - if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - g_warning ("Failed to create UPower proxy: %s", error->message); - g_error_free (error); - return; - } - - backend = META_BACKEND (user_data); - priv = meta_backend_get_instance_private (backend); - - priv->upower_proxy = proxy; - g_signal_connect (proxy, "g-properties-changed", - G_CALLBACK (upower_properties_changed), backend); - - v = g_dbus_proxy_get_cached_property (proxy, "LidIsClosed"); - if (!v) - return; - priv->lid_is_closed = g_variant_get_boolean (v); - g_variant_unref (v); - - if (priv->lid_is_closed) - { - g_signal_emit (backend, signals[LID_IS_CLOSED_CHANGED], 0, - priv->lid_is_closed); - } -} - -static void -upower_appeared (GDBusConnection *connection, - const gchar *name, - const gchar *name_owner, - gpointer user_data) -{ - MetaBackend *backend = META_BACKEND (user_data); - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - g_dbus_proxy_new (connection, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.freedesktop.UPower", - "/org/freedesktop/UPower", - "org.freedesktop.UPower", - priv->cancellable, - upower_ready_cb, - backend); -} - -static void -upower_vanished (GDBusConnection *connection, - const gchar *name, - gpointer user_data) -{ - MetaBackend *backend = META_BACKEND (user_data); - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - g_clear_object (&priv->upower_proxy); -} - -static void -meta_backend_constructed (GObject *object) -{ - MetaBackend *backend = META_BACKEND (object); - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - MetaBackendClass *backend_class = - META_BACKEND_GET_CLASS (backend); - - g_assert (priv->context); - -#ifdef HAVE_LIBWACOM - priv->wacom_db = libwacom_database_new (); - if (!priv->wacom_db) - { - g_warning ("Could not create database of Wacom devices, " - "expect tablets to misbehave"); - } -#endif - - if (backend_class->is_lid_closed != meta_backend_real_is_lid_closed) - return; - - priv->upower_watch_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM, - "org.freedesktop.UPower", - G_BUS_NAME_WATCHER_FLAGS_NONE, - upower_appeared, - upower_vanished, - backend, - NULL); -} - -static void -meta_backend_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaBackend *backend = META_BACKEND (object); - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - switch (prop_id) - { - case PROP_CONTEXT: - priv->context = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_backend_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaBackend *backend = META_BACKEND (object); - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - switch (prop_id) - { - case PROP_CONTEXT: - g_value_set_object (value, priv->context); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_backend_class_init (MetaBackendClass *klass) -{ - const gchar *mutter_stage_views; - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = meta_backend_dispose; - object_class->constructed = meta_backend_constructed; - object_class->set_property = meta_backend_set_property; - object_class->get_property = meta_backend_get_property; - - klass->post_init = meta_backend_real_post_init; - klass->grab_device = meta_backend_real_grab_device; - klass->ungrab_device = meta_backend_real_ungrab_device; - klass->select_stage_events = meta_backend_real_select_stage_events; - klass->is_lid_closed = meta_backend_real_is_lid_closed; - klass->create_cursor_tracker = meta_backend_real_create_cursor_tracker; - - obj_props[PROP_CONTEXT] = - g_param_spec_object ("context", - "context", - "MetaContext", - META_TYPE_CONTEXT, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, N_PROPS, obj_props); - - signals[KEYMAP_CHANGED] = - g_signal_new ("keymap-changed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - signals[KEYMAP_LAYOUT_GROUP_CHANGED] = - g_signal_new ("keymap-layout-group-changed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 1, G_TYPE_UINT); - signals[LAST_DEVICE_CHANGED] = - g_signal_new ("last-device-changed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 1, CLUTTER_TYPE_INPUT_DEVICE); - signals[LID_IS_CLOSED_CHANGED] = - g_signal_new ("lid-is-closed-changed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 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); - signals[PREPARE_SHUTDOWN] = - g_signal_new ("prepare-shutdown", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - mutter_stage_views = g_getenv ("MUTTER_STAGE_VIEWS"); - stage_views_disabled = g_strcmp0 (mutter_stage_views, "0") == 0; -} - -static MetaMonitorManager * -meta_backend_create_monitor_manager (MetaBackend *backend, - GError **error) -{ - return META_BACKEND_GET_CLASS (backend)->create_monitor_manager (backend, - error); -} - -static MetaRenderer * -meta_backend_create_renderer (MetaBackend *backend, - GError **error) -{ - return META_BACKEND_GET_CLASS (backend)->create_renderer (backend, error); -} - -static void -prepare_for_sleep_cb (GDBusConnection *connection, - const gchar *sender_name, - const gchar *object_path, - const gchar *interface_name, - const gchar *signal_name, - GVariant *parameters, - gpointer user_data) -{ - MetaBackend *backend = user_data; - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - gboolean suspending; - - g_variant_get (parameters, "(b)", &suspending); - if (suspending) - return; - - meta_idle_manager_reset_idle_time (priv->idle_manager); -} - -static void -system_bus_gotten_cb (GObject *object, - GAsyncResult *res, - gpointer user_data) -{ - MetaBackend *backend = user_data; - MetaBackendPrivate *priv; - GDBusConnection *bus; - - bus = g_bus_get_finish (res, NULL); - if (!bus) - return; - - priv = meta_backend_get_instance_private (backend); - priv->system_bus = bus; - priv->sleep_signal_id = - g_dbus_connection_signal_subscribe (priv->system_bus, - "org.freedesktop.login1", - "org.freedesktop.login1.Manager", - "PrepareForSleep", - "/org/freedesktop/login1", - NULL, - G_DBUS_SIGNAL_FLAGS_NONE, - prepare_for_sleep_cb, - backend, - NULL); -} - -/* Mutter is responsible for pulling events off the X queue, so Clutter - * doesn't need (and shouldn't) run its normal event source which polls - * the X fd, but we do have to deal with dispatching events that accumulate - * in the clutter queue. This happens, for example, when clutter generate - * enter/leave events on mouse motion - several events are queued in the - * clutter queue but only one dispatched. It could also happen because of - * explicit calls to clutter_event_put(). We add a very simple custom - * event loop source which is simply responsible for pulling events off - * of the queue and dispatching them before we block for new events. - */ - -static gboolean -clutter_source_prepare (GSource *source, - int *timeout) -{ - *timeout = -1; - - return clutter_events_pending (); -} - -static gboolean -clutter_source_check (GSource *source) -{ - return clutter_events_pending (); -} - -static gboolean -clutter_source_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data) -{ - MetaBackendSource *backend_source = (MetaBackendSource *) source; - ClutterEvent *event = clutter_event_get (); - - if (event) - { - event->any.stage = - CLUTTER_STAGE (meta_backend_get_stage (backend_source->backend)); - clutter_do_event (event); - clutter_event_free (event); - } - - return TRUE; -} - -static GSourceFuncs clutter_source_funcs = { - clutter_source_prepare, - clutter_source_check, - clutter_source_dispatch -}; - -static ClutterBackend * -meta_get_clutter_backend (void) -{ - MetaBackend *backend = meta_get_backend (); - - return meta_backend_get_clutter_backend (backend); -} - -static ClutterSeat * -meta_backend_create_default_seat (MetaBackend *backend, - GError **error) -{ - return META_BACKEND_GET_CLASS (backend)->create_default_seat (backend, error); -} - -static gboolean -init_clutter (MetaBackend *backend, - GError **error) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - MetaBackendSource *backend_source; - GSource *source; - - clutter_set_custom_backend_func (meta_get_clutter_backend); - - if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Unable to initialize Clutter"); - return FALSE; - } - - priv->default_seat = meta_backend_create_default_seat (backend, error); - if (!priv->default_seat) - return FALSE; - - source = g_source_new (&clutter_source_funcs, sizeof (MetaBackendSource)); - backend_source = (MetaBackendSource *) source; - backend_source->backend = backend; - g_source_attach (source, NULL); - g_source_unref (source); - - return TRUE; -} - -static void -meta_backend_post_init (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - META_BACKEND_GET_CLASS (backend)->post_init (backend); - - meta_settings_post_init (priv->settings); -} - -static gboolean -meta_backend_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - MetaBackend *backend = META_BACKEND (initable); - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - priv->settings = meta_settings_new (backend); - -#ifdef HAVE_EGL - priv->egl = g_object_new (META_TYPE_EGL, NULL); -#endif - - priv->orientation_manager = g_object_new (META_TYPE_ORIENTATION_MANAGER, NULL); - - priv->monitor_manager = meta_backend_create_monitor_manager (backend, error); - if (!priv->monitor_manager) - return FALSE; - - priv->renderer = meta_backend_create_renderer (backend, error); - if (!priv->renderer) - return FALSE; - - priv->cursor_tracker = - META_BACKEND_GET_CLASS (backend)->create_cursor_tracker (backend); - - priv->dnd = g_object_new (META_TYPE_DND, NULL); - - priv->cancellable = g_cancellable_new (); - g_bus_get (G_BUS_TYPE_SYSTEM, - priv->cancellable, - system_bus_gotten_cb, - backend); - -#ifdef HAVE_PROFILER - priv->profiler = meta_profiler_new (); -#endif - - if (!init_clutter (backend, error)) - return FALSE; - - meta_backend_post_init (backend); - - return TRUE; -} - -static void -initable_iface_init (GInitableIface *initable_iface) -{ - initable_iface->init = meta_backend_initable_init; -} - -static void -meta_backend_init (MetaBackend *backend) -{ - _backend = backend; -} - -/** - * meta_backend_get_idle_monitor: (skip) - */ -MetaIdleMonitor * -meta_backend_get_idle_monitor (MetaBackend *backend, - ClutterInputDevice *device) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - return meta_idle_manager_get_monitor (priv->idle_manager, device); -} - -/** - * meta_backend_get_core_idle_monitor: - * - * Returns: (transfer none): the #MetaIdleMonitor that tracks server-global - * idle time for all devices. - */ -MetaIdleMonitor * -meta_backend_get_core_idle_monitor (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - return meta_idle_manager_get_core_monitor (priv->idle_manager); -} - -/** - * meta_backend_get_idle_manager: (skip) - */ -MetaIdleManager * -meta_backend_get_idle_manager (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - return priv->idle_manager; -} - -/** - * meta_backend_get_monitor_manager: (skip) - */ -MetaMonitorManager * -meta_backend_get_monitor_manager (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - return priv->monitor_manager; -} - -/** - * meta_backend_get_orientation_manager: (skip) - */ -MetaOrientationManager * -meta_backend_get_orientation_manager (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - return priv->orientation_manager; -} - -MetaCursorTracker * -meta_backend_get_cursor_tracker (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - return priv->cursor_tracker; -} - -/** - * meta_backend_get_cursor_renderer: (skip) - */ -MetaCursorRenderer * -meta_backend_get_cursor_renderer (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - ClutterInputDevice *pointer; - ClutterSeat *seat; - - seat = clutter_backend_get_default_seat (priv->clutter_backend); - pointer = clutter_seat_get_pointer (seat); - - return meta_backend_get_cursor_renderer_for_device (backend, pointer); -} - -MetaCursorRenderer * -meta_backend_get_cursor_renderer_for_device (MetaBackend *backend, - ClutterInputDevice *device) -{ - g_return_val_if_fail (META_IS_BACKEND (backend), NULL); - g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL); - g_return_val_if_fail (clutter_input_device_get_device_type (device) != - CLUTTER_KEYBOARD_DEVICE, NULL); - - return META_BACKEND_GET_CLASS (backend)->get_cursor_renderer (backend, - device); -} - -/** - * meta_backend_get_renderer: (skip) - */ -MetaRenderer * -meta_backend_get_renderer (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - return priv->renderer; -} - -#ifdef HAVE_EGL -/** - * meta_backend_get_egl: (skip) - */ -MetaEgl * -meta_backend_get_egl (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - return priv->egl; -} -#endif /* HAVE_EGL */ - -/** - * meta_backend_get_settings: (skip) - */ -MetaSettings * -meta_backend_get_settings (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - return priv->settings; -} - -#ifdef HAVE_REMOTE_DESKTOP -/** - * meta_backend_get_remote_desktop: (skip) - */ -MetaRemoteDesktop * -meta_backend_get_remote_desktop (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - return priv->remote_desktop; -} - -/** - * meta_backend_get_screen_cast: (skip) - */ -MetaScreenCast * -meta_backend_get_screen_cast (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - return priv->screen_cast; -} -#endif /* HAVE_REMOTE_DESKTOP */ - -/** - * meta_backend_get_remote_access_controller: - * @backend: A #MetaBackend - * - * Return Value: (transfer none): The #MetaRemoteAccessController - */ -MetaRemoteAccessController * -meta_backend_get_remote_access_controller (MetaBackend *backend) -{ -#ifdef HAVE_REMOTE_DESKTOP - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - return priv->remote_access_controller; -#else - return NULL; -#endif -} - -/** - * meta_backend_is_rendering_hardware_accelerated: - * @backend: A #MetaBackend - * - * Returns: %TRUE if the rendering is hardware accelerated, otherwise - * %FALSE. - */ -gboolean -meta_backend_is_rendering_hardware_accelerated (MetaBackend *backend) -{ - MetaRenderer *renderer = meta_backend_get_renderer (backend); - - return meta_renderer_is_hardware_accelerated (renderer); -} - -/** - * meta_backend_grab_device: (skip) - */ -gboolean -meta_backend_grab_device (MetaBackend *backend, - int device_id, - uint32_t timestamp) -{ - return META_BACKEND_GET_CLASS (backend)->grab_device (backend, device_id, timestamp); -} - -/** - * meta_backend_get_context: - * @backend: the #MetaBackend - * - * Returns: (transfer none): The #MetaContext - */ -MetaContext * -meta_backend_get_context (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - return priv->context; -} - -/** - * meta_backend_ungrab_device: (skip) - */ -gboolean -meta_backend_ungrab_device (MetaBackend *backend, - int device_id, - uint32_t timestamp) -{ - return META_BACKEND_GET_CLASS (backend)->ungrab_device (backend, device_id, timestamp); -} - -/** - * meta_backend_finish_touch_sequence: (skip) - */ -void -meta_backend_finish_touch_sequence (MetaBackend *backend, - ClutterEventSequence *sequence, - MetaSequenceState state) -{ - if (META_BACKEND_GET_CLASS (backend)->finish_touch_sequence) - META_BACKEND_GET_CLASS (backend)->finish_touch_sequence (backend, - sequence, - state); -} - -MetaLogicalMonitor * -meta_backend_get_current_logical_monitor (MetaBackend *backend) -{ - return META_BACKEND_GET_CLASS (backend)->get_current_logical_monitor (backend); -} - -void -meta_backend_set_keymap (MetaBackend *backend, - const char *layouts, - const char *variants, - const char *options) -{ - META_BACKEND_GET_CLASS (backend)->set_keymap (backend, layouts, variants, options); -} - -/** - * meta_backend_get_keymap: (skip) - */ -struct xkb_keymap * -meta_backend_get_keymap (MetaBackend *backend) - -{ - return META_BACKEND_GET_CLASS (backend)->get_keymap (backend); -} - -xkb_layout_index_t -meta_backend_get_keymap_layout_group (MetaBackend *backend) -{ - return META_BACKEND_GET_CLASS (backend)->get_keymap_layout_group (backend); -} - -void -meta_backend_lock_layout_group (MetaBackend *backend, - guint idx) -{ - META_BACKEND_GET_CLASS (backend)->lock_layout_group (backend, idx); -} - -/** - * meta_backend_get_stage: - * @backend: A #MetaBackend - * - * Gets the global #ClutterStage that's managed by this backend. - * - * Returns: (transfer none): the #ClutterStage - */ -ClutterActor * -meta_backend_get_stage (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - return priv->stage; -} - -ClutterSeat * -meta_backend_get_default_seat (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - return priv->default_seat; -} - -static gboolean -update_last_device (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - MetaCursorTracker *cursor_tracker = priv->cursor_tracker; - ClutterInputDeviceType device_type; - - priv->device_update_idle_id = 0; - device_type = clutter_input_device_get_device_type (priv->current_device); - - g_signal_emit (backend, signals[LAST_DEVICE_CHANGED], 0, - priv->current_device); - - switch (device_type) - { - case CLUTTER_KEYBOARD_DEVICE: - break; - case CLUTTER_TOUCHSCREEN_DEVICE: - meta_cursor_tracker_set_pointer_visible (cursor_tracker, FALSE); - break; - default: - meta_cursor_tracker_set_pointer_visible (cursor_tracker, TRUE); - break; - } - - return G_SOURCE_REMOVE; -} - -void -meta_backend_update_last_device (MetaBackend *backend, - ClutterInputDevice *device) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - if (priv->current_device == device) - return; - - if (!device || - clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_LOGICAL) - return; - - g_set_object (&priv->current_device, device); - - if (priv->device_update_idle_id == 0) - { - priv->device_update_idle_id = - g_idle_add ((GSourceFunc) update_last_device, backend); - g_source_set_name_by_id (priv->device_update_idle_id, - "[mutter] update_last_device"); - } -} - -MetaPointerConstraint * -meta_backend_get_client_pointer_constraint (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - return priv->client_pointer_constraint; -} - -/** - * meta_backend_set_client_pointer_constraint: - * @backend: a #MetaBackend object. - * @constraint: (nullable): the client constraint to follow. - * - * Sets the current pointer constraint and removes (and unrefs) the previous - * one. If @constraint is %NULL, this means that there is no - * #MetaPointerConstraint active. - */ -void -meta_backend_set_client_pointer_constraint (MetaBackend *backend, - MetaPointerConstraint *constraint) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - META_BACKEND_GET_CLASS (backend)->set_pointer_constraint (backend, constraint); - g_set_object (&priv->client_pointer_constraint, constraint); -} - -ClutterBackend * -meta_backend_get_clutter_backend (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - if (!priv->clutter_backend) - { - priv->clutter_backend = - META_BACKEND_GET_CLASS (backend)->create_clutter_backend (backend); - } - - return priv->clutter_backend; -} - -void -meta_backend_prepare_shutdown (MetaBackend *backend) -{ - g_signal_emit (backend, signals[PREPARE_SHUTDOWN], 0); -} - -/** - * meta_is_stage_views_enabled: - * - * Returns whether the #ClutterStage can be rendered using multiple stage views. - * In practice, this means we can define a separate framebuffer for each - * #MetaLogicalMonitor, rather than rendering everything into a single - * framebuffer. For example: in X11, onle one single framebuffer is allowed. - */ -gboolean -meta_is_stage_views_enabled (void) -{ - if (!meta_is_wayland_compositor ()) - return FALSE; - - return !stage_views_disabled; -} - -gboolean -meta_is_stage_views_scaled (void) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaLogicalMonitorLayoutMode layout_mode; - - if (!meta_is_stage_views_enabled ()) - return FALSE; - - layout_mode = monitor_manager->layout_mode; - - return layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL; -} - -MetaInputMapper * -meta_backend_get_input_mapper (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - return priv->input_mapper; -} - -MetaInputSettings * -meta_backend_get_input_settings (MetaBackend *backend) -{ - return META_BACKEND_GET_CLASS (backend)->get_input_settings (backend); -} - -/** - * meta_backend_get_dnd: - * @backend: A #MetaDnd - * - * Gets the global #MetaDnd that's managed by this backend. - * - * Returns: (transfer none): the #MetaDnd - */ -MetaDnd * -meta_backend_get_dnd (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - return priv->dnd; -} - -void -meta_backend_notify_keymap_changed (MetaBackend *backend) -{ - g_signal_emit (backend, signals[KEYMAP_CHANGED], 0); -} - -void -meta_backend_notify_keymap_layout_group_changed (MetaBackend *backend, - unsigned int locked_group) -{ - 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; -} - -#ifdef HAVE_LIBWACOM -WacomDeviceDatabase * -meta_backend_get_wacom_database (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - return priv->wacom_db; -} -#endif - -void -meta_backend_add_hw_cursor_inhibitor (MetaBackend *backend, - MetaHwCursorInhibitor *inhibitor) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - priv->hw_cursor_inhibitors = g_list_prepend (priv->hw_cursor_inhibitors, - inhibitor); -} - -void -meta_backend_remove_hw_cursor_inhibitor (MetaBackend *backend, - MetaHwCursorInhibitor *inhibitor) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - priv->hw_cursor_inhibitors = g_list_remove (priv->hw_cursor_inhibitors, - inhibitor); -} - -gboolean -meta_backend_is_hw_cursors_inhibited (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - GList *l; - - for (l = priv->hw_cursor_inhibitors; l; l = l->next) - { - MetaHwCursorInhibitor *inhibitor = l->data; - - if (meta_hw_cursor_inhibitor_is_cursor_inhibited (inhibitor)) - return TRUE; - } - - return FALSE; -} diff --git a/src/backends/meta-barrier-private.h b/src/backends/meta-barrier-private.h deleted file mode 100644 index d0483e43c..000000000 --- a/src/backends/meta-barrier-private.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014-2015 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - * Jonas Ådahl - */ - -#ifndef META_BARRIER_PRIVATE_H -#define META_BARRIER_PRIVATE_H - -#include "core/meta-border.h" -#include "meta/barrier.h" - -G_BEGIN_DECLS - -#define META_TYPE_BARRIER_IMPL (meta_barrier_impl_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaBarrierImpl, - meta_barrier_impl, - META, BARRIER_IMPL, - GObject) - -struct _MetaBarrierImplClass -{ - GObjectClass parent_class; - - gboolean (*is_active) (MetaBarrierImpl *barrier); - void (*release) (MetaBarrierImpl *barrier, - MetaBarrierEvent *event); - void (*destroy) (MetaBarrierImpl *barrier); -}; - -void _meta_barrier_emit_hit_signal (MetaBarrier *barrier, - MetaBarrierEvent *event); -void _meta_barrier_emit_left_signal (MetaBarrier *barrier, - MetaBarrierEvent *event); - -void meta_barrier_event_unref (MetaBarrierEvent *event); - -G_END_DECLS - -struct _MetaBarrierPrivate -{ - MetaDisplay *display; - MetaBorder border; - MetaBarrierImpl *impl; -}; - -#endif /* META_BARRIER_PRIVATE_H */ diff --git a/src/backends/meta-barrier.c b/src/backends/meta-barrier.c deleted file mode 100644 index d924d0ab3..000000000 --- a/src/backends/meta-barrier.c +++ /dev/null @@ -1,365 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; c-basic-offset: 2; -*- */ - -/** - * SECTION:barrier - * @Title: MetaBarrier - * @Short_Description: Pointer barriers - */ - -#include "config.h" - -#include "meta/barrier.h" -#include "backends/meta-barrier-private.h" - -#include - -#include "backends/x11/meta-backend-x11.h" -#include "backends/x11/meta-barrier-x11.h" -#include "meta/meta-enum-types.h" -#include "meta/util.h" - -#ifdef HAVE_NATIVE_BACKEND -#include "backends/native/meta-backend-native.h" -#include "backends/native/meta-barrier-native.h" -#endif - -G_DEFINE_TYPE_WITH_PRIVATE (MetaBarrier, meta_barrier, G_TYPE_OBJECT) -G_DEFINE_TYPE (MetaBarrierImpl, meta_barrier_impl, G_TYPE_OBJECT) - -enum -{ - PROP_0, - - PROP_DISPLAY, - - PROP_X1, - PROP_Y1, - PROP_X2, - PROP_Y2, - PROP_DIRECTIONS, - - PROP_LAST, -}; - -static GParamSpec *obj_props[PROP_LAST]; - -enum -{ - HIT, - LEFT, - - LAST_SIGNAL, -}; - -static guint obj_signals[LAST_SIGNAL]; - - -static void -meta_barrier_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaBarrier *barrier = META_BARRIER (object); - MetaBarrierPrivate *priv = barrier->priv; - switch (prop_id) - { - case PROP_DISPLAY: - g_value_set_object (value, priv->display); - break; - case PROP_X1: - g_value_set_int (value, priv->border.line.a.x); - break; - case PROP_Y1: - g_value_set_int (value, priv->border.line.a.y); - break; - case PROP_X2: - g_value_set_int (value, priv->border.line.b.x); - break; - case PROP_Y2: - g_value_set_int (value, priv->border.line.b.y); - break; - case PROP_DIRECTIONS: - g_value_set_flags (value, - meta_border_get_allows_directions (&priv->border)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_barrier_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaBarrier *barrier = META_BARRIER (object); - MetaBarrierPrivate *priv = barrier->priv; - switch (prop_id) - { - case PROP_DISPLAY: - priv->display = g_value_get_object (value); - break; - case PROP_X1: - priv->border.line.a.x = g_value_get_int (value); - break; - case PROP_Y1: - priv->border.line.a.y = g_value_get_int (value); - break; - case PROP_X2: - priv->border.line.b.x = g_value_get_int (value); - break; - case PROP_Y2: - priv->border.line.b.y = g_value_get_int (value); - break; - case PROP_DIRECTIONS: - meta_border_set_allows_directions (&priv->border, - g_value_get_flags (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_barrier_dispose (GObject *object) -{ - MetaBarrier *barrier = META_BARRIER (object); - MetaBarrierPrivate *priv = barrier->priv; - - if (meta_barrier_is_active (barrier)) - { - meta_bug ("MetaBarrier %p was destroyed while it was still active.", - barrier); - } - - g_clear_object (&priv->impl); - - G_OBJECT_CLASS (meta_barrier_parent_class)->dispose (object); -} - -gboolean -meta_barrier_is_active (MetaBarrier *barrier) -{ - MetaBarrierImpl *impl = barrier->priv->impl; - - if (impl) - return META_BARRIER_IMPL_GET_CLASS (impl)->is_active (impl); - else - return FALSE; -} - -/** - * meta_barrier_release: - * @barrier: The barrier to release - * @event: The event to release the pointer for - * - * In XI2.3, pointer barriers provide a feature where they can - * be temporarily released so that the pointer goes through - * them. Pass a #MetaBarrierEvent to release the barrier for - * this event sequence. - */ -void -meta_barrier_release (MetaBarrier *barrier, - MetaBarrierEvent *event) -{ - MetaBarrierImpl *impl = barrier->priv->impl; - - if (impl) - META_BARRIER_IMPL_GET_CLASS (impl)->release (impl, event); -} - -static void -meta_barrier_constructed (GObject *object) -{ - MetaBarrier *barrier = META_BARRIER (object); - MetaBarrierPrivate *priv = barrier->priv; - - g_return_if_fail (priv->border.line.a.x == priv->border.line.b.x || - priv->border.line.a.y == priv->border.line.b.y); - g_return_if_fail (priv->border.line.a.x >= 0); - g_return_if_fail (priv->border.line.a.y >= 0); - g_return_if_fail (priv->border.line.b.x >= 0); - g_return_if_fail (priv->border.line.b.y >= 0); - -#if defined(HAVE_NATIVE_BACKEND) - if (META_IS_BACKEND_NATIVE (meta_get_backend ())) - priv->impl = meta_barrier_impl_native_new (barrier); -#endif - if (META_IS_BACKEND_X11 (meta_get_backend ()) && - !meta_is_wayland_compositor ()) - priv->impl = meta_barrier_impl_x11_new (barrier); - - if (priv->impl == NULL) - g_warning ("Created a non-working barrier"); - - /* Take a ref that we'll release in destroy() so that the object stays - * alive while active. */ - g_object_ref (barrier); - - G_OBJECT_CLASS (meta_barrier_parent_class)->constructed (object); -} - -static void -meta_barrier_class_init (MetaBarrierClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->get_property = meta_barrier_get_property; - object_class->set_property = meta_barrier_set_property; - object_class->dispose = meta_barrier_dispose; - object_class->constructed = meta_barrier_constructed; - - obj_props[PROP_DISPLAY] = - g_param_spec_object ("display", - "Display", - "The display to construct the pointer barrier on", - META_TYPE_DISPLAY, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - obj_props[PROP_X1] = - g_param_spec_int ("x1", - "X1", - "The first X coordinate of the barrier", - 0, G_MAXSHORT, 0, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - obj_props[PROP_Y1] = - g_param_spec_int ("y1", - "Y1", - "The first Y coordinate of the barrier", - 0, G_MAXSHORT, 0, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - obj_props[PROP_X2] = - g_param_spec_int ("x2", - "X2", - "The second X coordinate of the barrier", - 0, G_MAXSHORT, G_MAXSHORT, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - obj_props[PROP_Y2] = - g_param_spec_int ("y2", - "Y2", - "The second Y coordinate of the barrier", - 0, G_MAXSHORT, G_MAXSHORT, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - obj_props[PROP_DIRECTIONS] = - g_param_spec_flags ("directions", - "Directions", - "A set of directions to let the pointer through", - META_TYPE_BARRIER_DIRECTION, - 0, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties (object_class, PROP_LAST, obj_props); - - /** - * MetaBarrier::hit: - * @barrier: The #MetaBarrier that was hit - * @event: A #MetaBarrierEvent that has the details of how - * the barrier was hit. - * - * When a pointer barrier is hit, this will trigger. This - * requires an XI2-enabled server. - */ - obj_signals[HIT] = - g_signal_new ("hit", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 1, - META_TYPE_BARRIER_EVENT); - - /** - * MetaBarrier::left: - * @barrier: The #MetaBarrier that was left - * @event: A #MetaBarrierEvent that has the details of how - * the barrier was left. - * - * When a pointer barrier hitbox was left, this will trigger. - * This requires an XI2-enabled server. - */ - obj_signals[LEFT] = - g_signal_new ("left", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 1, - META_TYPE_BARRIER_EVENT); -} - -void -meta_barrier_destroy (MetaBarrier *barrier) -{ - MetaBarrierImpl *impl = barrier->priv->impl; - - if (impl) - META_BARRIER_IMPL_GET_CLASS (impl)->destroy (impl); - - g_object_unref (barrier); -} - -static void -meta_barrier_init (MetaBarrier *barrier) -{ - barrier->priv = meta_barrier_get_instance_private (barrier); -} - -void -_meta_barrier_emit_hit_signal (MetaBarrier *barrier, - MetaBarrierEvent *event) -{ - g_signal_emit (barrier, obj_signals[HIT], 0, event); -} - -void -_meta_barrier_emit_left_signal (MetaBarrier *barrier, - MetaBarrierEvent *event) -{ - g_signal_emit (barrier, obj_signals[LEFT], 0, event); -} - -static void -meta_barrier_impl_class_init (MetaBarrierImplClass *klass) -{ - klass->is_active = NULL; - klass->release = NULL; - klass->destroy = NULL; -} - -static void -meta_barrier_impl_init (MetaBarrierImpl *impl) -{ -} - -static MetaBarrierEvent * -meta_barrier_event_ref (MetaBarrierEvent *event) -{ - g_return_val_if_fail (event != NULL, NULL); - g_return_val_if_fail (event->ref_count > 0, NULL); - - g_atomic_int_inc ((volatile int *)&event->ref_count); - return event; -} - -void -meta_barrier_event_unref (MetaBarrierEvent *event) -{ - g_return_if_fail (event != NULL); - g_return_if_fail (event->ref_count > 0); - - if (g_atomic_int_dec_and_test ((volatile int *)&event->ref_count)) - g_free (event); -} - -G_DEFINE_BOXED_TYPE (MetaBarrierEvent, - meta_barrier_event, - meta_barrier_event_ref, - meta_barrier_event_unref) diff --git a/src/backends/meta-crtc-mode.c b/src/backends/meta-crtc-mode.c deleted file mode 100644 index 6d2de4b74..000000000 --- a/src/backends/meta-crtc-mode.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 2017-2020 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. - */ - -#include "config.h" - -#include "backends/meta-crtc-mode.h" - -enum -{ - PROP_0, - - PROP_ID, - PROP_NAME, - PROP_INFO, - - N_PROPS -}; - -static GParamSpec *obj_props[N_PROPS]; - -typedef struct _MetaCrtcModePrivate -{ - uint64_t id; - char *name; - MetaCrtcModeInfo *info; -} MetaCrtcModePrivate; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaCrtcMode, meta_crtc_mode, G_TYPE_OBJECT) - -G_DEFINE_BOXED_TYPE (MetaCrtcModeInfo, meta_crtc_mode_info, - meta_crtc_mode_info_ref, - meta_crtc_mode_info_unref) - -MetaCrtcModeInfo * -meta_crtc_mode_info_new (void) -{ - MetaCrtcModeInfo *crtc_mode_info; - - crtc_mode_info = g_new0 (MetaCrtcModeInfo, 1); - g_ref_count_init (&crtc_mode_info->ref_count); - - return crtc_mode_info; -} - -MetaCrtcModeInfo * -meta_crtc_mode_info_ref (MetaCrtcModeInfo *crtc_mode_info) -{ - g_ref_count_inc (&crtc_mode_info->ref_count); - return crtc_mode_info; -} - -void -meta_crtc_mode_info_unref (MetaCrtcModeInfo *crtc_mode_info) -{ - if (g_ref_count_dec (&crtc_mode_info->ref_count)) - g_free (crtc_mode_info); -} - -uint64_t -meta_crtc_mode_get_id (MetaCrtcMode *crtc_mode) -{ - MetaCrtcModePrivate *priv = meta_crtc_mode_get_instance_private (crtc_mode); - - return priv->id; -} - -const char * -meta_crtc_mode_get_name (MetaCrtcMode *crtc_mode) -{ - MetaCrtcModePrivate *priv = meta_crtc_mode_get_instance_private (crtc_mode); - - return priv->name; -} - -const MetaCrtcModeInfo * -meta_crtc_mode_get_info (MetaCrtcMode *crtc_mode) -{ - MetaCrtcModePrivate *priv = meta_crtc_mode_get_instance_private (crtc_mode); - - return priv->info; -} - -static void -meta_crtc_mode_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaCrtcMode *crtc_mode = META_CRTC_MODE (object); - MetaCrtcModePrivate *priv = meta_crtc_mode_get_instance_private (crtc_mode); - - switch (prop_id) - { - case PROP_ID: - priv->id = g_value_get_uint64 (value); - break; - case PROP_NAME: - priv->name = g_value_dup_string (value); - break; - case PROP_INFO: - priv->info = meta_crtc_mode_info_ref (g_value_get_boxed (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_crtc_mode_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaCrtcMode *crtc_mode = META_CRTC_MODE (object); - MetaCrtcModePrivate *priv = meta_crtc_mode_get_instance_private (crtc_mode); - - switch (prop_id) - { - case PROP_ID: - g_value_set_uint64 (value, priv->id); - break; - case PROP_NAME: - g_value_set_string (value, priv->name); - break; - case PROP_INFO: - g_value_set_boxed (value, priv->info); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_crtc_mode_finalize (GObject *object) -{ - MetaCrtcMode *crtc_mode = META_CRTC_MODE (object); - MetaCrtcModePrivate *priv = meta_crtc_mode_get_instance_private (crtc_mode); - - g_clear_pointer (&priv->name, g_free); - g_clear_pointer (&priv->info, meta_crtc_mode_info_unref); - - G_OBJECT_CLASS (meta_crtc_mode_parent_class)->finalize (object); -} - -static void -meta_crtc_mode_init (MetaCrtcMode *crtc_mode) -{ -} - -static void -meta_crtc_mode_class_init (MetaCrtcModeClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->set_property = meta_crtc_mode_set_property; - object_class->get_property = meta_crtc_mode_get_property; - object_class->finalize = meta_crtc_mode_finalize; - - obj_props[PROP_ID] = - g_param_spec_uint64 ("id", - "id", - "CRTC mode id", - 0, UINT64_MAX, 0, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - obj_props[PROP_NAME] = - g_param_spec_string ("name", - "name", - "Name of CRTC mode", - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - obj_props[PROP_INFO] = - g_param_spec_boxed ("info", - "info", - "MetaOutputInfo", - META_TYPE_CRTC_MODE_INFO, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, N_PROPS, obj_props); -} diff --git a/src/backends/meta-crtc-mode.h b/src/backends/meta-crtc-mode.h deleted file mode 100644 index 2ac90e408..000000000 --- a/src/backends/meta-crtc-mode.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2017-2020 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_CRTC_MODE_H -#define META_CRTC_MODE_H - -#include -#include - -#include "core/util-private.h" - -/* Same as KMS mode flags and X11 randr flags */ -typedef enum _MetaCrtcModeFlag -{ - META_CRTC_MODE_FLAG_NONE = 0, - META_CRTC_MODE_FLAG_PHSYNC = (1 << 0), - META_CRTC_MODE_FLAG_NHSYNC = (1 << 1), - META_CRTC_MODE_FLAG_PVSYNC = (1 << 2), - META_CRTC_MODE_FLAG_NVSYNC = (1 << 3), - META_CRTC_MODE_FLAG_INTERLACE = (1 << 4), - META_CRTC_MODE_FLAG_DBLSCAN = (1 << 5), - META_CRTC_MODE_FLAG_CSYNC = (1 << 6), - META_CRTC_MODE_FLAG_PCSYNC = (1 << 7), - META_CRTC_MODE_FLAG_NCSYNC = (1 << 8), - META_CRTC_MODE_FLAG_HSKEW = (1 << 9), - META_CRTC_MODE_FLAG_BCAST = (1 << 10), - META_CRTC_MODE_FLAG_PIXMUX = (1 << 11), - META_CRTC_MODE_FLAG_DBLCLK = (1 << 12), - META_CRTC_MODE_FLAG_CLKDIV2 = (1 << 13), - - META_CRTC_MODE_FLAG_MASK = 0x3fff -} MetaCrtcModeFlag; - -typedef struct _MetaCrtcModeInfo -{ - grefcount ref_count; - - int width; - int height; - float refresh_rate; - int64_t vblank_duration_us; - MetaCrtcModeFlag flags; -} MetaCrtcModeInfo; - -#define META_TYPE_CRTC_MODE (meta_crtc_mode_get_type ()) -META_EXPORT_TEST -G_DECLARE_DERIVABLE_TYPE (MetaCrtcMode, meta_crtc_mode, - META, CRTC_MODE, - GObject) - -struct _MetaCrtcModeClass -{ - GObjectClass parent_class; -}; - -#define META_TYPE_CRTC_MODE_INFO (meta_crtc_mode_info_get_type ()) -GType meta_crtc_mode_info_get_type (void); - -META_EXPORT_TEST -MetaCrtcModeInfo * meta_crtc_mode_info_new (void); - -META_EXPORT_TEST -MetaCrtcModeInfo * meta_crtc_mode_info_ref (MetaCrtcModeInfo *crtc_mode_info); - -META_EXPORT_TEST -void meta_crtc_mode_info_unref (MetaCrtcModeInfo *crtc_mode_info); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaCrtcModeInfo, meta_crtc_mode_info_unref) - -uint64_t meta_crtc_mode_get_id (MetaCrtcMode *crtc_mode); - -const char * meta_crtc_mode_get_name (MetaCrtcMode *crtc_mode); - -META_EXPORT_TEST -const MetaCrtcModeInfo * meta_crtc_mode_get_info (MetaCrtcMode *crtc_mode); - -#endif /* META_CRTC_MODE_H */ diff --git a/src/backends/meta-crtc.c b/src/backends/meta-crtc.c deleted file mode 100644 index 09f9199d5..000000000 --- a/src/backends/meta-crtc.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (C) 2017 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. - */ - -#include "config.h" - -#include "backends/meta-crtc.h" - -#include "backends/meta-gpu.h" - -enum -{ - PROP_0, - - PROP_ID, - PROP_GPU, - PROP_ALL_TRANSFORMS, - - N_PROPS -}; - -static GParamSpec *obj_props[N_PROPS]; - -typedef struct _MetaCrtcPrivate -{ - uint64_t id; - - MetaGpu *gpu; - - MetaMonitorTransform all_transforms; - - GList *outputs; - MetaCrtcConfig *config; -} MetaCrtcPrivate; - -G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaCrtc, meta_crtc, G_TYPE_OBJECT) - -uint64_t -meta_crtc_get_id (MetaCrtc *crtc) -{ - MetaCrtcPrivate *priv = meta_crtc_get_instance_private (crtc); - - return priv->id; -} - -MetaGpu * -meta_crtc_get_gpu (MetaCrtc *crtc) -{ - MetaCrtcPrivate *priv = meta_crtc_get_instance_private (crtc); - - return priv->gpu; -} - -const GList * -meta_crtc_get_outputs (MetaCrtc *crtc) -{ - MetaCrtcPrivate *priv = meta_crtc_get_instance_private (crtc); - - return priv->outputs; -} - -void -meta_crtc_assign_output (MetaCrtc *crtc, - MetaOutput *output) -{ - MetaCrtcPrivate *priv = meta_crtc_get_instance_private (crtc); - - priv->outputs = g_list_append (priv->outputs, output); -} - -void -meta_crtc_unassign_output (MetaCrtc *crtc, - MetaOutput *output) -{ - MetaCrtcPrivate *priv = meta_crtc_get_instance_private (crtc); - - g_return_if_fail (g_list_find (priv->outputs, output)); - - priv->outputs = g_list_remove (priv->outputs, output); -} - -MetaMonitorTransform -meta_crtc_get_all_transforms (MetaCrtc *crtc) -{ - MetaCrtcPrivate *priv = meta_crtc_get_instance_private (crtc); - - return priv->all_transforms; -} - -void -meta_crtc_set_config (MetaCrtc *crtc, - graphene_rect_t *layout, - MetaCrtcMode *mode, - MetaMonitorTransform transform) -{ - MetaCrtcPrivate *priv = meta_crtc_get_instance_private (crtc); - MetaCrtcConfig *config; - - meta_crtc_unset_config (crtc); - - config = g_new0 (MetaCrtcConfig, 1); - config->layout = *layout; - config->mode = mode; - config->transform = transform; - - priv->config = config; -} - -void -meta_crtc_unset_config (MetaCrtc *crtc) -{ - MetaCrtcPrivate *priv = meta_crtc_get_instance_private (crtc); - - g_clear_pointer (&priv->config, g_free); -} - -const MetaCrtcConfig * -meta_crtc_get_config (MetaCrtc *crtc) -{ - MetaCrtcPrivate *priv = meta_crtc_get_instance_private (crtc); - - return priv->config; -} - -static void -meta_crtc_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaCrtc *crtc = META_CRTC (object); - MetaCrtcPrivate *priv = meta_crtc_get_instance_private (crtc); - - switch (prop_id) - { - case PROP_ID: - priv->id = g_value_get_uint64 (value); - break; - case PROP_GPU: - priv->gpu = g_value_get_object (value); - break; - case PROP_ALL_TRANSFORMS: - priv->all_transforms = g_value_get_uint (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_crtc_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaCrtc *crtc = META_CRTC (object); - MetaCrtcPrivate *priv = meta_crtc_get_instance_private (crtc); - - switch (prop_id) - { - case PROP_ID: - g_value_set_uint64 (value, priv->id); - break; - case PROP_GPU: - g_value_set_object (value, priv->gpu); - break; - case PROP_ALL_TRANSFORMS: - g_value_set_uint (value, priv->all_transforms); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_crtc_finalize (GObject *object) -{ - MetaCrtc *crtc = META_CRTC (object); - MetaCrtcPrivate *priv = meta_crtc_get_instance_private (crtc); - - g_clear_pointer (&priv->config, g_free); - g_clear_pointer (&priv->outputs, g_list_free); - - G_OBJECT_CLASS (meta_crtc_parent_class)->finalize (object); -} - -static void -meta_crtc_init (MetaCrtc *crtc) -{ - MetaCrtcPrivate *priv = meta_crtc_get_instance_private (crtc); - - priv->all_transforms = META_MONITOR_ALL_TRANSFORMS; -} - -static void -meta_crtc_class_init (MetaCrtcClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->set_property = meta_crtc_set_property; - object_class->get_property = meta_crtc_get_property; - object_class->finalize = meta_crtc_finalize; - - obj_props[PROP_ID] = - g_param_spec_uint64 ("id", - "id", - "CRTC id", - 0, UINT64_MAX, 0, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - obj_props[PROP_GPU] = - g_param_spec_object ("gpu", - "gpu", - "MetaGpu", - META_TYPE_GPU, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - obj_props[PROP_ALL_TRANSFORMS] = - g_param_spec_uint ("all-transforms", - "all-transforms", - "All transforms", - 0, - META_MONITOR_ALL_TRANSFORMS, - META_MONITOR_ALL_TRANSFORMS, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, N_PROPS, obj_props); -} diff --git a/src/backends/meta-crtc.h b/src/backends/meta-crtc.h deleted file mode 100644 index f6a3bc136..000000000 --- a/src/backends/meta-crtc.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2017 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_CRTC_H -#define META_CRTC_H - -#include - -#include "backends/meta-backend-types.h" -#include "backends/meta-crtc-mode.h" -#include "backends/meta-monitor-transform.h" -#include "core/util-private.h" -#include "meta/boxes.h" - -typedef struct _MetaCrtcConfig -{ - graphene_rect_t layout; - MetaMonitorTransform transform; - MetaCrtcMode *mode; -} MetaCrtcConfig; - -#define META_TYPE_CRTC (meta_crtc_get_type ()) -META_EXPORT_TEST -G_DECLARE_DERIVABLE_TYPE (MetaCrtc, meta_crtc, META, CRTC, GObject) - -struct _MetaCrtcClass -{ - GObjectClass parent_class; -}; - -META_EXPORT_TEST -uint64_t meta_crtc_get_id (MetaCrtc *crtc); - -META_EXPORT_TEST -MetaGpu * meta_crtc_get_gpu (MetaCrtc *crtc); - -META_EXPORT_TEST -const GList * meta_crtc_get_outputs (MetaCrtc *crtc); - -void meta_crtc_assign_output (MetaCrtc *crtc, - MetaOutput *output); - -META_EXPORT_TEST -void meta_crtc_unassign_output (MetaCrtc *crtc, - MetaOutput *output); - -MetaMonitorTransform meta_crtc_get_all_transforms (MetaCrtc *crtc); - -META_EXPORT_TEST -void meta_crtc_set_config (MetaCrtc *crtc, - graphene_rect_t *layout, - MetaCrtcMode *mode, - MetaMonitorTransform transform); - -META_EXPORT_TEST -void meta_crtc_unset_config (MetaCrtc *crtc); - -META_EXPORT_TEST -const MetaCrtcConfig * meta_crtc_get_config (MetaCrtc *crtc); - -#endif /* META_CRTC_H */ diff --git a/src/backends/meta-cursor-renderer.c b/src/backends/meta-cursor-renderer.c deleted file mode 100644 index 3353b17d3..000000000 --- a/src/backends/meta-cursor-renderer.c +++ /dev/null @@ -1,492 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -#include "config.h" - -#include "backends/meta-cursor-renderer.h" - -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-logical-monitor.h" -#include "backends/meta-stage-private.h" -#include "clutter/clutter.h" -#include "clutter/clutter-mutter.h" -#include "cogl/cogl.h" -#include "core/boxes-private.h" -#include "meta/meta-backend.h" -#include "meta/util.h" - -G_DEFINE_INTERFACE (MetaHwCursorInhibitor, meta_hw_cursor_inhibitor, - G_TYPE_OBJECT) - -enum -{ - PROP_0, - - PROP_BACKEND, - PROP_DEVICE, - - N_PROPS -}; - -static GParamSpec *obj_props[N_PROPS]; - -struct _MetaCursorRendererPrivate -{ - MetaBackend *backend; - - float current_x; - float current_y; - - ClutterInputDevice *device; - MetaCursorSprite *displayed_cursor; - MetaCursorSprite *overlay_cursor; - - MetaOverlay *stage_overlay; - gboolean handled_by_backend; - gulong after_paint_handler_id; - - GList *hw_cursor_inhibitors; -}; -typedef struct _MetaCursorRendererPrivate MetaCursorRendererPrivate; - -enum -{ - CURSOR_PAINTED, - LAST_SIGNAL -}; -static guint signals[LAST_SIGNAL]; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRenderer, meta_cursor_renderer, G_TYPE_OBJECT); - -gboolean -meta_hw_cursor_inhibitor_is_cursor_inhibited (MetaHwCursorInhibitor *inhibitor) -{ - MetaHwCursorInhibitorInterface *iface = - META_HW_CURSOR_INHIBITOR_GET_IFACE (inhibitor); - - return iface->is_cursor_inhibited (inhibitor); -} - -static void -meta_hw_cursor_inhibitor_default_init (MetaHwCursorInhibitorInterface *iface) -{ -} - -void -meta_cursor_renderer_emit_painted (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite, - ClutterStageView *stage_view) -{ - g_signal_emit (renderer, signals[CURSOR_PAINTED], 0, cursor_sprite, stage_view); -} - -static void -align_cursor_position (MetaCursorRenderer *renderer, - graphene_rect_t *rect) -{ - MetaCursorRendererPrivate *priv = - meta_cursor_renderer_get_instance_private (renderer); - ClutterActor *stage = meta_backend_get_stage (priv->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); - - graphene_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; - graphene_rect_offset (rect, view_layout.x, view_layout.y); -} - -void -meta_cursor_renderer_update_stage_overlay (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite) -{ - MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); - ClutterActor *stage = meta_backend_get_stage (priv->backend); - CoglTexture *texture; - graphene_rect_t rect = GRAPHENE_RECT_INIT_ZERO; - - g_set_object (&priv->overlay_cursor, cursor_sprite); - - 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)); - - if (cursor_sprite) - texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); - else - texture = NULL; - - meta_overlay_set_visible (priv->stage_overlay, !priv->handled_by_backend); - meta_stage_update_cursor_overlay (META_STAGE (stage), priv->stage_overlay, - texture, &rect); -} - -static void -meta_cursor_renderer_after_paint (ClutterStage *stage, - ClutterStageView *stage_view, - MetaCursorRenderer *renderer) -{ - MetaCursorRendererPrivate *priv = - meta_cursor_renderer_get_instance_private (renderer); - - if (priv->displayed_cursor && !priv->handled_by_backend) - { - graphene_rect_t rect; - MetaRectangle view_layout; - graphene_rect_t view_rect; - - rect = meta_cursor_renderer_calculate_rect (renderer, - priv->displayed_cursor); - clutter_stage_view_get_layout (stage_view, &view_layout); - view_rect = meta_rectangle_to_graphene_rect (&view_layout); - if (graphene_rect_intersection (&rect, &view_rect, NULL)) - { - meta_cursor_renderer_emit_painted (renderer, - priv->displayed_cursor, - stage_view); - } - } -} - -static gboolean -meta_cursor_renderer_real_update_cursor (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite) -{ - if (cursor_sprite) - meta_cursor_sprite_realize_texture (cursor_sprite); - - return FALSE; -} - -static void -meta_cursor_renderer_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaCursorRenderer *renderer = META_CURSOR_RENDERER (object); - MetaCursorRendererPrivate *priv = - meta_cursor_renderer_get_instance_private (renderer); - - switch (prop_id) - { - case PROP_BACKEND: - g_value_set_object (value, priv->backend); - break; - case PROP_DEVICE: - g_value_set_object (value, priv->device); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_cursor_renderer_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaCursorRenderer *renderer = META_CURSOR_RENDERER (object); - MetaCursorRendererPrivate *priv = - meta_cursor_renderer_get_instance_private (renderer); - - switch (prop_id) - { - case PROP_BACKEND: - priv->backend = g_value_get_object (value); - break; - case PROP_DEVICE: - priv->device = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_cursor_renderer_finalize (GObject *object) -{ - MetaCursorRenderer *renderer = META_CURSOR_RENDERER (object); - MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); - ClutterActor *stage = meta_backend_get_stage (priv->backend); - - if (priv->stage_overlay) - meta_stage_remove_cursor_overlay (META_STAGE (stage), priv->stage_overlay); - - g_clear_signal_handler (&priv->after_paint_handler_id, stage); - - g_clear_object (&priv->displayed_cursor); - g_clear_object (&priv->overlay_cursor); - - G_OBJECT_CLASS (meta_cursor_renderer_parent_class)->finalize (object); -} - -static void -meta_cursor_renderer_constructed (GObject *object) -{ - MetaCursorRenderer *renderer = META_CURSOR_RENDERER (object); - MetaCursorRendererPrivate *priv = - meta_cursor_renderer_get_instance_private (renderer); - ClutterActor *stage; - - stage = meta_backend_get_stage (priv->backend); - priv->after_paint_handler_id = - g_signal_connect (stage, "after-paint", - G_CALLBACK (meta_cursor_renderer_after_paint), - renderer); - - G_OBJECT_CLASS (meta_cursor_renderer_parent_class)->constructed (object); -} - -static void -meta_cursor_renderer_class_init (MetaCursorRendererClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->get_property = meta_cursor_renderer_get_property; - object_class->set_property = meta_cursor_renderer_set_property; - object_class->finalize = meta_cursor_renderer_finalize; - object_class->constructed = meta_cursor_renderer_constructed; - klass->update_cursor = meta_cursor_renderer_real_update_cursor; - - 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); - obj_props[PROP_DEVICE] = - g_param_spec_object ("device", - "device", - "Input device", - CLUTTER_TYPE_INPUT_DEVICE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, N_PROPS, obj_props); - - signals[CURSOR_PAINTED] = g_signal_new ("cursor-painted", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 2, - G_TYPE_POINTER, - CLUTTER_TYPE_STAGE_VIEW); -} - -static void -meta_cursor_renderer_init (MetaCursorRenderer *renderer) -{ -} - -graphene_rect_t -meta_cursor_renderer_calculate_rect (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite) -{ - MetaCursorRendererPrivate *priv = - meta_cursor_renderer_get_instance_private (renderer); - CoglTexture *texture; - int hot_x, hot_y; - int width, height; - float texture_scale; - - texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); - if (!texture) - return (graphene_rect_t) GRAPHENE_RECT_INIT_ZERO; - - meta_cursor_sprite_get_hotspot (cursor_sprite, &hot_x, &hot_y); - texture_scale = meta_cursor_sprite_get_texture_scale (cursor_sprite); - width = cogl_texture_get_width (texture); - height = cogl_texture_get_height (texture); - - return (graphene_rect_t) { - .origin = { - .x = priv->current_x - (hot_x * texture_scale), - .y = priv->current_y - (hot_y * texture_scale) - }, - .size = { - .width = width * texture_scale, - .height = height * texture_scale - } - }; -} - -static float -find_highest_logical_monitor_scale (MetaBackend *backend, - MetaCursorSprite *cursor_sprite) -{ - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaCursorRenderer *cursor_renderer = - meta_backend_get_cursor_renderer (backend); - graphene_rect_t cursor_rect; - GList *logical_monitors; - GList *l; - float highest_scale = 0.0f; - - cursor_rect = meta_cursor_renderer_calculate_rect (cursor_renderer, - cursor_sprite); - - logical_monitors = - meta_monitor_manager_get_logical_monitors (monitor_manager); - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - graphene_rect_t logical_monitor_rect = - meta_rectangle_to_graphene_rect (&logical_monitor->rect); - - if (!graphene_rect_intersection (&cursor_rect, - &logical_monitor_rect, - NULL)) - continue; - - highest_scale = MAX (highest_scale, logical_monitor->scale); - } - - return highest_scale; -} - -static void -meta_cursor_renderer_update_cursor (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite) -{ - MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); - gboolean handled_by_backend; - - if (cursor_sprite) - { - float scale = find_highest_logical_monitor_scale (priv->backend, - cursor_sprite); - meta_cursor_sprite_prepare_at (cursor_sprite, - MAX (1, scale), - (int) priv->current_x, - (int) priv->current_y); - } - - handled_by_backend = - META_CURSOR_RENDERER_GET_CLASS (renderer)->update_cursor (renderer, - cursor_sprite); - if (handled_by_backend != priv->handled_by_backend) - priv->handled_by_backend = handled_by_backend; - - meta_cursor_renderer_update_stage_overlay (renderer, cursor_sprite); -} - -MetaCursorRenderer * -meta_cursor_renderer_new (MetaBackend *backend, - ClutterInputDevice *device) -{ - return g_object_new (META_TYPE_CURSOR_RENDERER, - "backend", backend, - "device", device, - NULL); -} - -void -meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite) -{ - MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); - - if (priv->displayed_cursor == cursor_sprite) - return; - g_set_object (&priv->displayed_cursor, cursor_sprite); - - meta_cursor_renderer_update_cursor (renderer, cursor_sprite); -} - -void -meta_cursor_renderer_force_update (MetaCursorRenderer *renderer) -{ - MetaCursorRendererPrivate *priv = - meta_cursor_renderer_get_instance_private (renderer); - - meta_cursor_renderer_update_cursor (renderer, priv->displayed_cursor); -} - -void -meta_cursor_renderer_update_position (MetaCursorRenderer *renderer) -{ - MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); - graphene_point_t pos; - - clutter_seat_query_state (clutter_input_device_get_seat (priv->device), - priv->device, NULL, &pos, NULL); - priv->current_x = pos.x; - priv->current_y = pos.y; - - meta_cursor_renderer_update_cursor (renderer, priv->displayed_cursor); -} - -MetaCursorSprite * -meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer) -{ - MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); - - return priv->overlay_cursor; -} - -gboolean -meta_cursor_renderer_is_overlay_visible (MetaCursorRenderer *renderer) -{ - MetaCursorRendererPrivate *priv = - meta_cursor_renderer_get_instance_private (renderer); - - if (!priv->stage_overlay) - return FALSE; - - return meta_overlay_is_visible (priv->stage_overlay); -} - -ClutterInputDevice * -meta_cursor_renderer_get_input_device (MetaCursorRenderer *renderer) -{ - MetaCursorRendererPrivate *priv = - meta_cursor_renderer_get_instance_private (renderer); - - return priv->device; -} diff --git a/src/backends/meta-cursor-renderer.h b/src/backends/meta-cursor-renderer.h deleted file mode 100644 index f6de01bfb..000000000 --- a/src/backends/meta-cursor-renderer.h +++ /dev/null @@ -1,82 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -#ifndef META_CURSOR_RENDERER_H -#define META_CURSOR_RENDERER_H - -#include - -#include "backends/meta-backend-types.h" -#include "backends/meta-cursor.h" - -#define META_TYPE_HW_CURSOR_INHIBITOR (meta_hw_cursor_inhibitor_get_type ()) -G_DECLARE_INTERFACE (MetaHwCursorInhibitor, meta_hw_cursor_inhibitor, - META, HW_CURSOR_INHIBITOR, GObject) - -struct _MetaHwCursorInhibitorInterface -{ - GTypeInterface parent_iface; - - gboolean (* is_cursor_inhibited) (MetaHwCursorInhibitor *inhibitor); -}; - -gboolean meta_hw_cursor_inhibitor_is_cursor_inhibited (MetaHwCursorInhibitor *inhibitor); - -#define META_TYPE_CURSOR_RENDERER (meta_cursor_renderer_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaCursorRenderer, meta_cursor_renderer, - META, CURSOR_RENDERER, GObject); - -struct _MetaCursorRendererClass -{ - GObjectClass parent_class; - - gboolean (* update_cursor) (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite); -}; - -MetaCursorRenderer * meta_cursor_renderer_new (MetaBackend *backend, - ClutterInputDevice *device); - -void meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite); - -void meta_cursor_renderer_update_position (MetaCursorRenderer *renderer); -void meta_cursor_renderer_force_update (MetaCursorRenderer *renderer); - -MetaCursorSprite * meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer); - -gboolean meta_cursor_renderer_is_overlay_visible (MetaCursorRenderer *renderer); - -graphene_rect_t meta_cursor_renderer_calculate_rect (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite); - -void meta_cursor_renderer_emit_painted (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite, - ClutterStageView *stage_view); -ClutterInputDevice * meta_cursor_renderer_get_input_device (MetaCursorRenderer *renderer); - -void meta_cursor_renderer_update_stage_overlay (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite); - -#endif /* META_CURSOR_RENDERER_H */ diff --git a/src/backends/meta-cursor-sprite-xcursor.c b/src/backends/meta-cursor-sprite-xcursor.c deleted file mode 100644 index 5284f28ea..000000000 --- a/src/backends/meta-cursor-sprite-xcursor.c +++ /dev/null @@ -1,371 +0,0 @@ -/* - * Copyright 2013, 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 . - * - */ - -#include "config.h" - -#include "backends/meta-cursor-sprite-xcursor.h" - -#include "backends/meta-cursor.h" -#include "backends/meta-cursor-renderer.h" -#include "clutter/clutter.h" -#include "cogl/cogl.h" -#include "meta/prefs.h" -#include "meta/util.h" - -struct _MetaCursorSpriteXcursor -{ - MetaCursorSprite parent; - - MetaCursor cursor; - - int current_frame; - XcursorImages *xcursor_images; - - int theme_scale; - gboolean theme_dirty; -}; - -G_DEFINE_TYPE (MetaCursorSpriteXcursor, meta_cursor_sprite_xcursor, - META_TYPE_CURSOR_SPRITE) - -static const char * -translate_meta_cursor (MetaCursor cursor) -{ - switch (cursor) - { - case META_CURSOR_DEFAULT: - return "left_ptr"; - case META_CURSOR_NORTH_RESIZE: - return "top_side"; - case META_CURSOR_SOUTH_RESIZE: - return "bottom_side"; - case META_CURSOR_WEST_RESIZE: - return "left_side"; - case META_CURSOR_EAST_RESIZE: - return "right_side"; - case META_CURSOR_SE_RESIZE: - return "bottom_right_corner"; - case META_CURSOR_SW_RESIZE: - return "bottom_left_corner"; - case META_CURSOR_NE_RESIZE: - return "top_right_corner"; - case META_CURSOR_NW_RESIZE: - return "top_left_corner"; - case META_CURSOR_MOVE_OR_RESIZE_WINDOW: - return "fleur"; - case META_CURSOR_BUSY: - return "watch"; - case META_CURSOR_DND_IN_DRAG: - return "dnd-none"; - case META_CURSOR_DND_MOVE: - return "dnd-move"; - case META_CURSOR_DND_COPY: - return "dnd-copy"; - case META_CURSOR_DND_UNSUPPORTED_TARGET: - return "dnd-none"; - case META_CURSOR_POINTING_HAND: - return "hand2"; - case META_CURSOR_CROSSHAIR: - return "crosshair"; - case META_CURSOR_IBEAM: - return "xterm"; - case META_CURSOR_BLANK: - case META_CURSOR_NONE: - case META_CURSOR_LAST: - break; - } - - g_assert_not_reached (); - return NULL; -} - -static Cursor -create_blank_cursor (Display *xdisplay) -{ - Pixmap pixmap; - XColor color; - Cursor cursor; - XGCValues gc_values; - GC gc; - - pixmap = XCreatePixmap (xdisplay, DefaultRootWindow (xdisplay), 1, 1, 1); - - gc_values.foreground = BlackPixel (xdisplay, DefaultScreen (xdisplay)); - gc = XCreateGC (xdisplay, pixmap, GCForeground, &gc_values); - - XFillRectangle (xdisplay, pixmap, gc, 0, 0, 1, 1); - - color.pixel = 0; - color.red = color.blue = color.green = 0; - - cursor = XCreatePixmapCursor (xdisplay, pixmap, pixmap, &color, &color, 1, 1); - - XFreeGC (xdisplay, gc); - XFreePixmap (xdisplay, pixmap); - - return cursor; -} - -static XcursorImages * -create_blank_cursor_images (void) -{ - XcursorImages *images; - - images = XcursorImagesCreate (1); - images->images[0] = XcursorImageCreate (1, 1); - - images->images[0]->xhot = 0; - images->images[0]->yhot = 0; - memset (images->images[0]->pixels, 0, sizeof(int32_t)); - - return images; -} - -MetaCursor -meta_cursor_sprite_xcursor_get_cursor (MetaCursorSpriteXcursor *sprite_xcursor) -{ - return sprite_xcursor->cursor; -} - -Cursor -meta_create_x_cursor (Display *xdisplay, - MetaCursor cursor) -{ - if (cursor == META_CURSOR_BLANK) - return create_blank_cursor (xdisplay); - - return XcursorLibraryLoadCursor (xdisplay, translate_meta_cursor (cursor)); -} - -static XcursorImages * -load_cursor_on_client (MetaCursor cursor, int scale) -{ - XcursorImages *xcursor_images; - int fallback_size; - - if (cursor == META_CURSOR_BLANK) - return create_blank_cursor_images (); - - xcursor_images = - XcursorLibraryLoadImages (translate_meta_cursor (cursor), - meta_prefs_get_cursor_theme (), - meta_prefs_get_cursor_size () * scale); - if (xcursor_images) - return xcursor_images; - - g_warning_once ("No cursor theme available, please install a cursor theme"); - - fallback_size = 24 * scale; - xcursor_images = XcursorImagesCreate (1); - xcursor_images->images[0] = XcursorImageCreate (fallback_size, fallback_size); - xcursor_images->images[0]->xhot = 0; - xcursor_images->images[0]->yhot = 0; - memset (xcursor_images->images[0]->pixels, 0xc0, - fallback_size * fallback_size * sizeof (int32_t)); - return xcursor_images; -} - -static void -load_from_current_xcursor_image (MetaCursorSpriteXcursor *sprite_xcursor) -{ - MetaCursorSprite *sprite = META_CURSOR_SPRITE (sprite_xcursor); - XcursorImage *xc_image; - int width, height, rowstride; - CoglPixelFormat cogl_format; - ClutterBackend *clutter_backend; - CoglContext *cogl_context; - CoglTexture2D *texture; - GError *error = NULL; - int hotspot_x, hotspot_y; - - g_assert (!meta_cursor_sprite_get_cogl_texture (sprite)); - - xc_image = meta_cursor_sprite_xcursor_get_current_image (sprite_xcursor); - width = (int) xc_image->width; - height = (int) xc_image->height; - rowstride = width * 4; - -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - cogl_format = COGL_PIXEL_FORMAT_BGRA_8888; -#else - cogl_format = COGL_PIXEL_FORMAT_ARGB_8888; -#endif - - clutter_backend = clutter_get_default_backend (); - cogl_context = clutter_backend_get_cogl_context (clutter_backend); - texture = cogl_texture_2d_new_from_data (cogl_context, - width, height, - cogl_format, - rowstride, - (uint8_t *) xc_image->pixels, - &error); - if (!texture) - { - g_warning ("Failed to allocate cursor texture: %s", error->message); - g_error_free (error); - } - - if (meta_is_wayland_compositor ()) - { - hotspot_x = ((int) (xc_image->xhot / sprite_xcursor->theme_scale) * - sprite_xcursor->theme_scale); - hotspot_y = ((int) (xc_image->yhot / sprite_xcursor->theme_scale) * - sprite_xcursor->theme_scale); - } - else - { - hotspot_x = xc_image->xhot; - hotspot_y = xc_image->yhot; - } - meta_cursor_sprite_set_texture (sprite, - COGL_TEXTURE (texture), - hotspot_x, hotspot_y); - - g_clear_pointer (&texture, cogl_object_unref); -} - -void -meta_cursor_sprite_xcursor_set_theme_scale (MetaCursorSpriteXcursor *sprite_xcursor, - int theme_scale) -{ - if (sprite_xcursor->theme_scale != theme_scale) - sprite_xcursor->theme_dirty = TRUE; - sprite_xcursor->theme_scale = theme_scale; -} - -static gboolean -meta_cursor_sprite_xcursor_is_animated (MetaCursorSprite *sprite) -{ - MetaCursorSpriteXcursor *sprite_xcursor = META_CURSOR_SPRITE_XCURSOR (sprite); - - return (sprite_xcursor->xcursor_images && - sprite_xcursor->xcursor_images->nimage > 1); -} - -XcursorImage * -meta_cursor_sprite_xcursor_get_current_image (MetaCursorSpriteXcursor *sprite_xcursor) -{ - return sprite_xcursor->xcursor_images->images[sprite_xcursor->current_frame]; -} - -static void -meta_cursor_sprite_xcursor_tick_frame (MetaCursorSprite *sprite) -{ - MetaCursorSpriteXcursor *sprite_xcursor = META_CURSOR_SPRITE_XCURSOR (sprite); - - if (!meta_cursor_sprite_is_animated (sprite)) - return; - - sprite_xcursor->current_frame++; - - if (sprite_xcursor->current_frame >= sprite_xcursor->xcursor_images->nimage) - sprite_xcursor->current_frame = 0; - - meta_cursor_sprite_clear_texture (sprite); - load_from_current_xcursor_image (sprite_xcursor); -} - -static unsigned int -meta_cursor_sprite_xcursor_get_current_frame_time (MetaCursorSprite *sprite) -{ - MetaCursorSpriteXcursor *sprite_xcursor = META_CURSOR_SPRITE_XCURSOR (sprite); - XcursorImages *xcursor_images; - - g_return_val_if_fail (meta_cursor_sprite_is_animated (sprite), 0); - - xcursor_images = sprite_xcursor->xcursor_images; - return xcursor_images->images[sprite_xcursor->current_frame]->delay; -} - -static void -load_cursor_from_theme (MetaCursorSprite *sprite) -{ - MetaCursorSpriteXcursor *sprite_xcursor = META_CURSOR_SPRITE_XCURSOR (sprite); - - g_assert (sprite_xcursor->cursor != META_CURSOR_NONE); - - sprite_xcursor->theme_dirty = FALSE; - - /* We might be reloading with a different scale. If so clear the old data. */ - if (sprite_xcursor->xcursor_images) - { - meta_cursor_sprite_clear_texture (sprite); - XcursorImagesDestroy (sprite_xcursor->xcursor_images); - } - - sprite_xcursor->current_frame = 0; - sprite_xcursor->xcursor_images = - load_cursor_on_client (sprite_xcursor->cursor, - sprite_xcursor->theme_scale); - - load_from_current_xcursor_image (sprite_xcursor); -} - -static void -meta_cursor_sprite_xcursor_realize_texture (MetaCursorSprite *sprite) -{ - MetaCursorSpriteXcursor *sprite_xcursor = META_CURSOR_SPRITE_XCURSOR (sprite); - - if (sprite_xcursor->theme_dirty) - load_cursor_from_theme (sprite); -} - -MetaCursorSpriteXcursor * -meta_cursor_sprite_xcursor_new (MetaCursor cursor) -{ - MetaCursorSpriteXcursor *sprite_xcursor; - - sprite_xcursor = g_object_new (META_TYPE_CURSOR_SPRITE_XCURSOR, NULL); - sprite_xcursor->cursor = cursor; - - return sprite_xcursor; -} - -static void -meta_cursor_sprite_xcursor_finalize (GObject *object) -{ - MetaCursorSpriteXcursor *sprite_xcursor = META_CURSOR_SPRITE_XCURSOR (object); - - g_clear_pointer (&sprite_xcursor->xcursor_images, - XcursorImagesDestroy); - - G_OBJECT_CLASS (meta_cursor_sprite_xcursor_parent_class)->finalize (object); -} - -static void -meta_cursor_sprite_xcursor_init (MetaCursorSpriteXcursor *sprite_xcursor) -{ - sprite_xcursor->theme_scale = 1; - sprite_xcursor->theme_dirty = TRUE; -} - -static void -meta_cursor_sprite_xcursor_class_init (MetaCursorSpriteXcursorClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaCursorSpriteClass *cursor_sprite_class = META_CURSOR_SPRITE_CLASS (klass); - - object_class->finalize = meta_cursor_sprite_xcursor_finalize; - - cursor_sprite_class->realize_texture = - meta_cursor_sprite_xcursor_realize_texture; - cursor_sprite_class->is_animated = meta_cursor_sprite_xcursor_is_animated; - cursor_sprite_class->tick_frame = meta_cursor_sprite_xcursor_tick_frame; - cursor_sprite_class->get_current_frame_time = - meta_cursor_sprite_xcursor_get_current_frame_time; -} diff --git a/src/backends/meta-cursor-sprite-xcursor.h b/src/backends/meta-cursor-sprite-xcursor.h deleted file mode 100644 index dbc927484..000000000 --- a/src/backends/meta-cursor-sprite-xcursor.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2013, 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 . - * - */ - -#ifndef META_CURSOR_SPRITE_XCURSOR_H -#define META_CURSOR_SPRITE_XCURSOR_H - -#include -#include - -#include "backends/meta-cursor.h" - -#define META_TYPE_CURSOR_SPRITE_XCURSOR meta_cursor_sprite_xcursor_get_type () -G_DECLARE_FINAL_TYPE (MetaCursorSpriteXcursor, meta_cursor_sprite_xcursor, - META, CURSOR_SPRITE_XCURSOR, MetaCursorSprite) - -MetaCursorSpriteXcursor * meta_cursor_sprite_xcursor_new (MetaCursor cursor); - -void meta_cursor_sprite_xcursor_set_theme_scale (MetaCursorSpriteXcursor *sprite_xcursor, - int scale); - -MetaCursor meta_cursor_sprite_xcursor_get_cursor (MetaCursorSpriteXcursor *sprite_xcusror); - -XcursorImage * meta_cursor_sprite_xcursor_get_current_image (MetaCursorSpriteXcursor *sprite_xcursor); - -Cursor meta_create_x_cursor (Display *xdisplay, - MetaCursor cursor); - -#endif /* META_CURSOR_SPRITE_XCURSOR_H */ diff --git a/src/backends/meta-cursor-tracker-private.h b/src/backends/meta-cursor-tracker-private.h deleted file mode 100644 index 2d8d38042..000000000 --- a/src/backends/meta-cursor-tracker-private.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright 2013 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - * - * Author: Giovanni Campagna - */ - -#ifndef META_CURSOR_TRACKER_PRIVATE_H -#define META_CURSOR_TRACKER_PRIVATE_H - -#include "backends/meta-cursor.h" -#include "backends/meta-cursor-renderer.h" -#include "meta/meta-cursor-tracker.h" - -struct _MetaCursorTrackerClass -{ - GObjectClass parent_class; - - void (* set_force_track_position) (MetaCursorTracker *tracker, - gboolean is_enabled); - MetaCursorSprite * (* get_sprite) (MetaCursorTracker *tracker); -}; - -void meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker, - MetaCursorSprite *cursor_sprite); -void meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker); -void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker, - MetaCursorSprite *cursor_sprite); - -void meta_cursor_tracker_invalidate_position (MetaCursorTracker *tracker); - -void meta_cursor_tracker_track_position (MetaCursorTracker *tracker); - -void meta_cursor_tracker_untrack_position (MetaCursorTracker *tracker); - -MetaBackend * meta_cursor_tracker_get_backend (MetaCursorTracker *tracker); - -void meta_cursor_tracker_notify_cursor_changed (MetaCursorTracker *tracker); - -void meta_cursor_tracker_destroy (MetaCursorTracker *tracker); - -#endif diff --git a/src/backends/meta-cursor-tracker.c b/src/backends/meta-cursor-tracker.c deleted file mode 100644 index 24776e266..000000000 --- a/src/backends/meta-cursor-tracker.c +++ /dev/null @@ -1,514 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright 2013 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - * - * Author: Giovanni Campagna - */ - -/** - * SECTION:cursor-tracker - * @title: MetaCursorTracker - * @short_description: Mutter cursor tracking helper. Originally only - * tracking the cursor image, now more of a "core - * pointer abstraction" - */ - -#include "config.h" - -#include "backends/meta-cursor-tracker-private.h" - -#include - -#include "backends/meta-backend-private.h" -#include "cogl/cogl.h" -#include "core/display-private.h" -#include "clutter/clutter.h" -#include "meta/main.h" -#include "meta/util.h" - -enum -{ - PROP_0, - - PROP_BACKEND, - - N_PROPS -}; - -static GParamSpec *obj_props[N_PROPS]; - -typedef struct _MetaCursorTrackerPrivate -{ - MetaBackend *backend; - - gboolean is_showing; - - int track_position_count; - - float x; - float y; - - MetaCursorSprite *effective_cursor; /* May be NULL when hidden */ - MetaCursorSprite *displayed_cursor; - - /* Wayland clients can set a NULL buffer as their cursor - * explicitly, which means that we shouldn't display anything. - * So, we can't simply store a NULL in window_cursor to - * determine an unset window cursor; we need an extra boolean. - */ - gboolean has_window_cursor; - MetaCursorSprite *window_cursor; - - MetaCursorSprite *root_cursor; -} MetaCursorTrackerPrivate; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorTracker, meta_cursor_tracker, - G_TYPE_OBJECT) - -enum -{ - CURSOR_CHANGED, - POSITION_INVALIDATED, - VISIBILITY_CHANGED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL]; - -void -meta_cursor_tracker_notify_cursor_changed (MetaCursorTracker *tracker) -{ - g_signal_emit (tracker, signals[CURSOR_CHANGED], 0); -} - -static void -cursor_texture_updated (MetaCursorSprite *cursor, - MetaCursorTracker *tracker) -{ - g_signal_emit (tracker, signals[CURSOR_CHANGED], 0); -} - -static gboolean -update_displayed_cursor (MetaCursorTracker *tracker) -{ - MetaCursorTrackerPrivate *priv = - meta_cursor_tracker_get_instance_private (tracker); - MetaDisplay *display = meta_get_display (); - MetaCursorSprite *cursor = NULL; - - if (display && meta_display_windows_are_interactable (display) && - priv->has_window_cursor) - cursor = priv->window_cursor; - else - cursor = priv->root_cursor; - - if (priv->displayed_cursor == cursor) - return FALSE; - - if (priv->displayed_cursor) - { - g_signal_handlers_disconnect_by_func (priv->displayed_cursor, - cursor_texture_updated, - tracker); - } - - g_set_object (&priv->displayed_cursor, cursor); - - if (cursor) - { - g_signal_connect (cursor, "texture-changed", - G_CALLBACK (cursor_texture_updated), tracker); - } - - return TRUE; -} - -static gboolean -update_effective_cursor (MetaCursorTracker *tracker) -{ - MetaCursorTrackerPrivate *priv = - meta_cursor_tracker_get_instance_private (tracker); - MetaCursorSprite *cursor = NULL; - - if (priv->is_showing) - cursor = priv->displayed_cursor; - - return g_set_object (&priv->effective_cursor, cursor); -} - -static void -change_cursor_renderer (MetaCursorTracker *tracker) -{ - MetaCursorTrackerPrivate *priv = - meta_cursor_tracker_get_instance_private (tracker); - MetaCursorRenderer *cursor_renderer = - meta_backend_get_cursor_renderer (priv->backend); - - meta_cursor_renderer_set_cursor (cursor_renderer, priv->effective_cursor); -} - -static void -sync_cursor (MetaCursorTracker *tracker) -{ - gboolean cursor_changed = FALSE; - - cursor_changed = update_displayed_cursor (tracker); - - if (update_effective_cursor (tracker)) - change_cursor_renderer (tracker); - - if (cursor_changed) - g_signal_emit (tracker, signals[CURSOR_CHANGED], 0); -} - -static void -meta_cursor_tracker_real_set_force_track_position (MetaCursorTracker *tracker, - gboolean is_enabled) -{ -} - -static MetaCursorSprite * -meta_cursor_tracker_real_get_sprite (MetaCursorTracker *tracker) -{ - MetaCursorTrackerPrivate *priv = - meta_cursor_tracker_get_instance_private (tracker); - - return priv->displayed_cursor; -} - -void -meta_cursor_tracker_destroy (MetaCursorTracker *tracker) -{ - g_object_run_dispose (G_OBJECT (tracker)); - g_object_unref (tracker); -} - -static void -meta_cursor_tracker_init (MetaCursorTracker *tracker) -{ - MetaCursorTrackerPrivate *priv = - meta_cursor_tracker_get_instance_private (tracker); - - priv->is_showing = FALSE; - priv->x = -1.0; - priv->y = -1.0; -} - -static void -meta_cursor_tracker_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaCursorTracker *tracker = META_CURSOR_TRACKER (object); - MetaCursorTrackerPrivate *priv = - meta_cursor_tracker_get_instance_private (tracker); - - switch (prop_id) - { - case PROP_BACKEND: - g_value_set_object (value, priv->backend); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_cursor_tracker_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaCursorTracker *tracker = META_CURSOR_TRACKER (object); - MetaCursorTrackerPrivate *priv = - meta_cursor_tracker_get_instance_private (tracker); - - switch (prop_id) - { - case PROP_BACKEND: - priv->backend = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_cursor_tracker_dispose (GObject *object) -{ - MetaCursorTracker *tracker = META_CURSOR_TRACKER (object); - MetaCursorTrackerPrivate *priv = - meta_cursor_tracker_get_instance_private (tracker); - - g_clear_object (&priv->effective_cursor); - g_clear_object (&priv->displayed_cursor); - g_clear_object (&priv->root_cursor); - - G_OBJECT_CLASS (meta_cursor_tracker_parent_class)->dispose (object); -} - -static void -meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->get_property = meta_cursor_tracker_get_property; - object_class->set_property = meta_cursor_tracker_set_property; - object_class->dispose = meta_cursor_tracker_dispose; - - klass->set_force_track_position = - meta_cursor_tracker_real_set_force_track_position; - klass->get_sprite = - meta_cursor_tracker_real_get_sprite; - - 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); - g_object_class_install_properties (object_class, N_PROPS, obj_props); - - signals[CURSOR_CHANGED] = g_signal_new ("cursor-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - signals[POSITION_INVALIDATED] = g_signal_new ("position-invalidated", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - signals[VISIBILITY_CHANGED] = g_signal_new ("visibility-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); -} - -/** - * meta_cursor_tracker_get_for_display: - * @display: the #MetaDisplay - * - * Retrieves the cursor tracker object for @display. - * - * Returns: (transfer none): - */ -MetaCursorTracker * -meta_cursor_tracker_get_for_display (MetaDisplay *display) -{ - MetaBackend *backend = meta_get_backend (); - MetaCursorTracker *tracker = meta_backend_get_cursor_tracker (backend); - - g_assert (tracker); - - return tracker; -} - -static void -set_window_cursor (MetaCursorTracker *tracker, - gboolean has_cursor, - MetaCursorSprite *cursor_sprite) -{ - MetaCursorTrackerPrivate *priv = - meta_cursor_tracker_get_instance_private (tracker); - - g_clear_object (&priv->window_cursor); - if (cursor_sprite) - priv->window_cursor = g_object_ref (cursor_sprite); - priv->has_window_cursor = has_cursor; - sync_cursor (tracker); -} - -/** - * meta_cursor_tracker_get_sprite: - * - * Returns: (transfer none): - */ -CoglTexture * -meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker) -{ - MetaCursorSprite *cursor_sprite; - - cursor_sprite = META_CURSOR_TRACKER_GET_CLASS (tracker)->get_sprite (tracker); - - if (!cursor_sprite) - return NULL; - - meta_cursor_sprite_realize_texture (cursor_sprite); - return meta_cursor_sprite_get_cogl_texture (cursor_sprite); -} - -/** - * meta_cursor_tracker_get_hot: - * @tracker: - * @x: (out): - * @y: (out): - * - */ -void -meta_cursor_tracker_get_hot (MetaCursorTracker *tracker, - int *x, - int *y) -{ - MetaCursorSprite *cursor_sprite; - - g_return_if_fail (META_IS_CURSOR_TRACKER (tracker)); - - cursor_sprite = META_CURSOR_TRACKER_GET_CLASS (tracker)->get_sprite (tracker); - - if (cursor_sprite) - meta_cursor_sprite_get_hotspot (cursor_sprite, x, y); - else - { - if (x) - *x = 0; - if (y) - *y = 0; - } -} - -void -meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker, - MetaCursorSprite *cursor_sprite) -{ - set_window_cursor (tracker, TRUE, cursor_sprite); -} - -void -meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker) -{ - set_window_cursor (tracker, FALSE, NULL); -} - -/** - * meta_cursor_tracker_set_root_cursor: - * @tracker: a #MetaCursorTracker object. - * @cursor_sprite: (transfer none): the new root cursor - * - * Sets the root cursor (the cursor that is shown if not modified by a window). - * The #MetaCursorTracker will take a strong reference to the sprite. - */ -void -meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker, - MetaCursorSprite *cursor_sprite) -{ - MetaCursorTrackerPrivate *priv = - meta_cursor_tracker_get_instance_private (tracker); - - g_clear_object (&priv->root_cursor); - if (cursor_sprite) - priv->root_cursor = g_object_ref (cursor_sprite); - - sync_cursor (tracker); -} - -void -meta_cursor_tracker_invalidate_position (MetaCursorTracker *tracker) -{ - g_signal_emit (tracker, signals[POSITION_INVALIDATED], 0); -} - -void -meta_cursor_tracker_get_pointer (MetaCursorTracker *tracker, - graphene_point_t *coords, - ClutterModifierType *mods) -{ - ClutterSeat *seat; - ClutterInputDevice *cdevice; - - seat = clutter_backend_get_default_seat (clutter_get_default_backend ()); - cdevice = clutter_seat_get_pointer (seat); - - clutter_seat_query_state (seat, cdevice, NULL, coords, mods); -} - -void -meta_cursor_tracker_track_position (MetaCursorTracker *tracker) -{ - MetaCursorTrackerPrivate *priv = - meta_cursor_tracker_get_instance_private (tracker); - - priv->track_position_count++; - if (priv->track_position_count == 1) - { - MetaCursorTrackerClass *klass = - META_CURSOR_TRACKER_GET_CLASS (tracker); - - klass->set_force_track_position (tracker, TRUE); - } -} - -void -meta_cursor_tracker_untrack_position (MetaCursorTracker *tracker) -{ - MetaCursorTrackerPrivate *priv = - meta_cursor_tracker_get_instance_private (tracker); - - g_return_if_fail (priv->track_position_count > 0); - - priv->track_position_count--; - if (priv->track_position_count == 0) - { - MetaCursorTrackerClass *klass = - META_CURSOR_TRACKER_GET_CLASS (tracker); - - klass->set_force_track_position (tracker, FALSE); - } -} - -gboolean -meta_cursor_tracker_get_pointer_visible (MetaCursorTracker *tracker) -{ - MetaCursorTrackerPrivate *priv = - meta_cursor_tracker_get_instance_private (tracker); - - return priv->is_showing; -} - -void -meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker, - gboolean visible) -{ - MetaCursorTrackerPrivate *priv = - meta_cursor_tracker_get_instance_private (tracker); - - if (visible == priv->is_showing) - return; - priv->is_showing = visible; - - sync_cursor (tracker); - - g_signal_emit (tracker, signals[VISIBILITY_CHANGED], 0); -} -MetaBackend * -meta_cursor_tracker_get_backend (MetaCursorTracker *tracker) -{ - MetaCursorTrackerPrivate *priv = - meta_cursor_tracker_get_instance_private (tracker); - - return priv->backend; -} diff --git a/src/backends/meta-cursor.c b/src/backends/meta-cursor.c deleted file mode 100644 index d0fb2ba68..000000000 --- a/src/backends/meta-cursor.c +++ /dev/null @@ -1,240 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright 2013 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - * - * Author: Giovanni Campagna - */ - -#include "config.h" - -#include "backends/meta-cursor.h" - -#include "backends/meta-backend-private.h" -#include "cogl/cogl.h" -#include "meta/common.h" - -enum -{ - PREPARE_AT, - TEXTURE_CHANGED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL]; - -typedef struct _MetaCursorSpritePrivate -{ - GObject parent; - - CoglTexture2D *texture; - float texture_scale; - MetaMonitorTransform texture_transform; - int hot_x, hot_y; -} MetaCursorSpritePrivate; - -G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaCursorSprite, - meta_cursor_sprite, - G_TYPE_OBJECT) - -gboolean -meta_cursor_sprite_is_animated (MetaCursorSprite *sprite) -{ - MetaCursorSpriteClass *klass = META_CURSOR_SPRITE_GET_CLASS (sprite); - - if (klass->is_animated) - return klass->is_animated (sprite); - else - return FALSE; -} - -void -meta_cursor_sprite_tick_frame (MetaCursorSprite *sprite) -{ - return META_CURSOR_SPRITE_GET_CLASS (sprite)->tick_frame (sprite); -} - -unsigned int -meta_cursor_sprite_get_current_frame_time (MetaCursorSprite *sprite) -{ - return META_CURSOR_SPRITE_GET_CLASS (sprite)->get_current_frame_time (sprite); -} - -void -meta_cursor_sprite_clear_texture (MetaCursorSprite *sprite) -{ - MetaCursorSpritePrivate *priv = - meta_cursor_sprite_get_instance_private (sprite); - - g_clear_pointer (&priv->texture, cogl_object_unref); -} - -void -meta_cursor_sprite_set_texture (MetaCursorSprite *sprite, - CoglTexture *texture, - int hot_x, - int hot_y) -{ - MetaCursorSpritePrivate *priv = - meta_cursor_sprite_get_instance_private (sprite); - - g_clear_pointer (&priv->texture, cogl_object_unref); - if (texture) - priv->texture = cogl_object_ref (texture); - priv->hot_x = hot_x; - priv->hot_y = hot_y; - - g_signal_emit (sprite, signals[TEXTURE_CHANGED], 0); -} - -void -meta_cursor_sprite_set_texture_scale (MetaCursorSprite *sprite, - float scale) -{ - MetaCursorSpritePrivate *priv = - meta_cursor_sprite_get_instance_private (sprite); - - priv->texture_scale = scale; -} - -void -meta_cursor_sprite_set_texture_transform (MetaCursorSprite *sprite, - MetaMonitorTransform transform) -{ - MetaCursorSpritePrivate *priv = - meta_cursor_sprite_get_instance_private (sprite); - - priv->texture_transform = transform; -} - -CoglTexture * -meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *sprite) -{ - MetaCursorSpritePrivate *priv = - meta_cursor_sprite_get_instance_private (sprite); - - return COGL_TEXTURE (priv->texture); -} - -void -meta_cursor_sprite_get_hotspot (MetaCursorSprite *sprite, - int *hot_x, - int *hot_y) -{ - MetaCursorSpritePrivate *priv = - meta_cursor_sprite_get_instance_private (sprite); - - *hot_x = priv->hot_x; - *hot_y = priv->hot_y; -} - -int -meta_cursor_sprite_get_width (MetaCursorSprite *sprite) -{ - CoglTexture *texture; - - texture = meta_cursor_sprite_get_cogl_texture (sprite); - return cogl_texture_get_width (texture); -} - -int -meta_cursor_sprite_get_height (MetaCursorSprite *sprite) -{ - CoglTexture *texture; - - texture = meta_cursor_sprite_get_cogl_texture (sprite); - return cogl_texture_get_height (texture); -} - -float -meta_cursor_sprite_get_texture_scale (MetaCursorSprite *sprite) -{ - MetaCursorSpritePrivate *priv = - meta_cursor_sprite_get_instance_private (sprite); - - return priv->texture_scale; -} - -MetaMonitorTransform -meta_cursor_sprite_get_texture_transform (MetaCursorSprite *sprite) -{ - MetaCursorSpritePrivate *priv = - meta_cursor_sprite_get_instance_private (sprite); - - return priv->texture_transform; -} - -void -meta_cursor_sprite_prepare_at (MetaCursorSprite *sprite, - float best_scale, - int x, - int y) -{ - g_signal_emit (sprite, signals[PREPARE_AT], 0, best_scale, x, y); -} - -void -meta_cursor_sprite_realize_texture (MetaCursorSprite *sprite) -{ - META_CURSOR_SPRITE_GET_CLASS (sprite)->realize_texture (sprite); -} - -static void -meta_cursor_sprite_init (MetaCursorSprite *sprite) -{ - MetaCursorSpritePrivate *priv = - meta_cursor_sprite_get_instance_private (sprite); - - priv->texture_scale = 1.0f; - priv->texture_transform = META_MONITOR_TRANSFORM_NORMAL; -} - -static void -meta_cursor_sprite_finalize (GObject *object) -{ - MetaCursorSprite *sprite = META_CURSOR_SPRITE (object); - MetaCursorSpritePrivate *priv = - meta_cursor_sprite_get_instance_private (sprite); - - g_clear_pointer (&priv->texture, cogl_object_unref); - - G_OBJECT_CLASS (meta_cursor_sprite_parent_class)->finalize (object); -} - -static void -meta_cursor_sprite_class_init (MetaCursorSpriteClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_cursor_sprite_finalize; - - signals[PREPARE_AT] = g_signal_new ("prepare-at", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 3, - G_TYPE_FLOAT, - G_TYPE_INT, - G_TYPE_INT); - signals[TEXTURE_CHANGED] = g_signal_new ("texture-changed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); -} diff --git a/src/backends/meta-cursor.h b/src/backends/meta-cursor.h deleted file mode 100644 index a65e128c4..000000000 --- a/src/backends/meta-cursor.h +++ /dev/null @@ -1,85 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright 2013 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - * - * Author: Giovanni Campagna - */ - -#ifndef META_CURSOR_H -#define META_CURSOR_H - -#include "backends/meta-backend-types.h" -#include "meta/common.h" -#include "meta/boxes.h" - -#define META_TYPE_CURSOR_SPRITE (meta_cursor_sprite_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaCursorSprite, - meta_cursor_sprite, - META, CURSOR_SPRITE, - GObject) - -struct _MetaCursorSpriteClass -{ - GObjectClass parent_class; - - void (* realize_texture) (MetaCursorSprite *sprite); - gboolean (* is_animated) (MetaCursorSprite *sprite); - void (* tick_frame) (MetaCursorSprite *sprite); - unsigned int (* get_current_frame_time) (MetaCursorSprite *sprite); -}; - -void meta_cursor_sprite_prepare_at (MetaCursorSprite *sprite, - float best_scale, - int x, - int y); - -void meta_cursor_sprite_realize_texture (MetaCursorSprite *sprite); - -void meta_cursor_sprite_clear_texture (MetaCursorSprite *sprite); - -void meta_cursor_sprite_set_texture (MetaCursorSprite *sprite, - CoglTexture *texture, - int hot_x, - int hot_y); - -void meta_cursor_sprite_set_texture_scale (MetaCursorSprite *sprite, - float scale); - -void meta_cursor_sprite_set_texture_transform (MetaCursorSprite *sprite, - MetaMonitorTransform transform); - -CoglTexture *meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *sprite); - -void meta_cursor_sprite_get_hotspot (MetaCursorSprite *sprite, - int *hot_x, - int *hot_y); - -int meta_cursor_sprite_get_width (MetaCursorSprite *sprite); - -int meta_cursor_sprite_get_height (MetaCursorSprite *sprite); - -float meta_cursor_sprite_get_texture_scale (MetaCursorSprite *sprite); - -MetaMonitorTransform meta_cursor_sprite_get_texture_transform (MetaCursorSprite *sprite); - -gboolean meta_cursor_sprite_is_animated (MetaCursorSprite *sprite); - -void meta_cursor_sprite_tick_frame (MetaCursorSprite *sprite); - -unsigned int meta_cursor_sprite_get_current_frame_time (MetaCursorSprite *sprite); - -#endif /* META_CURSOR_H */ diff --git a/src/backends/meta-dbus-session-watcher.c b/src/backends/meta-dbus-session-watcher.c deleted file mode 100644 index a885b423b..000000000 --- a/src/backends/meta-dbus-session-watcher.c +++ /dev/null @@ -1,237 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015-2017 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "backends/meta-dbus-session-watcher.h" - -#include - -enum -{ - SESSION_SIGNAL_SESSION_CLOSED, - - N_SESSION_SIGNALS -}; - -static guint session_signals[N_SESSION_SIGNALS]; - -G_DEFINE_INTERFACE (MetaDbusSession, meta_dbus_session, G_TYPE_OBJECT) - -struct _MetaDbusSessionWatcher -{ - GObject parent; - - GHashTable *clients; -}; - -G_DEFINE_TYPE (MetaDbusSessionWatcher, - meta_dbus_session_watcher, - G_TYPE_OBJECT) - -typedef struct _MetaDbusSessionClient -{ - MetaDbusSessionWatcher *session_watcher; - MetaDbusSession *session; - char *dbus_name; - guint name_watcher_id; - GList *sessions; -} MetaDbusSessionClient; - -static void -meta_dbus_session_client_vanished (MetaDbusSession *session) -{ - META_DBUS_SESSION_GET_IFACE (session)->client_vanished (session); -} - -static void -meta_dbus_session_client_destroy (MetaDbusSessionClient *client) -{ - while (TRUE) - { - GList *l; - MetaDbusSession *session; - - l = client->sessions; - if (!l) - break; - - session = l->data; - - /* - * This will invoke on_session_closed which removes the session from the - * list. - */ - meta_dbus_session_client_vanished (session); - } - - if (client->name_watcher_id) - g_bus_unwatch_name (client->name_watcher_id); - - g_free (client->dbus_name); - g_free (client); -} - -static void -meta_dbus_session_watcher_destroy_client (MetaDbusSessionWatcher *session_watcher, - MetaDbusSessionClient *client) -{ - g_hash_table_remove (session_watcher->clients, client->dbus_name); -} - -static void -name_vanished_callback (GDBusConnection *connection, - const char *name, - gpointer user_data) -{ - MetaDbusSessionClient *client = user_data; - - g_warning ("D-Bus client with active sessions vanished"); - - client->name_watcher_id = 0; - - meta_dbus_session_watcher_destroy_client (client->session_watcher, client); -} - -static MetaDbusSessionClient * -meta_dbus_session_client_new (MetaDbusSessionWatcher *session_watcher, - MetaDbusSession *session, - const char *dbus_name) -{ - GDBusInterfaceSkeleton *interface_skeleton = - G_DBUS_INTERFACE_SKELETON (session); - GDBusConnection *connection = - g_dbus_interface_skeleton_get_connection (interface_skeleton); - MetaDbusSessionClient *client; - - client = g_new0 (MetaDbusSessionClient, 1); - client->session_watcher = session_watcher; - client->session = session; - client->dbus_name = g_strdup (dbus_name); - - client->name_watcher_id = - g_bus_watch_name_on_connection (connection, - dbus_name, - G_BUS_NAME_WATCHER_FLAGS_NONE, - NULL, - name_vanished_callback, - client, - NULL); - - return client; -} - -static void -on_session_closed (MetaDbusSession *session, - MetaDbusSessionClient *client) -{ - client->sessions = g_list_remove (client->sessions, session); - - if (!client->sessions) - meta_dbus_session_watcher_destroy_client (client->session_watcher, client); -} - -static void -meta_dbus_session_client_add_session (MetaDbusSessionClient *client, - MetaDbusSession *session) -{ - client->sessions = g_list_append (client->sessions, session); - - g_signal_connect (session, "session-closed", - G_CALLBACK (on_session_closed), - client); -} - -static MetaDbusSessionClient * -meta_dbus_session_watcher_get_client (MetaDbusSessionWatcher *session_watcher, - const char *dbus_name) -{ - return g_hash_table_lookup (session_watcher->clients, dbus_name); -} - -void -meta_dbus_session_watcher_watch_session (MetaDbusSessionWatcher *session_watcher, - const char *client_dbus_name, - MetaDbusSession *session) -{ - MetaDbusSessionClient *client; - - client = meta_dbus_session_watcher_get_client (session_watcher, - client_dbus_name); - if (!client) - { - client = meta_dbus_session_client_new (session_watcher, - session, - client_dbus_name); - g_hash_table_insert (session_watcher->clients, - g_strdup (client_dbus_name), - client); - } - - meta_dbus_session_client_add_session (client, session); -} - -void -meta_dbus_session_notify_closed (MetaDbusSession *session) -{ - g_signal_emit (session, session_signals[SESSION_SIGNAL_SESSION_CLOSED], 0); -} - -static void -meta_dbus_session_default_init (MetaDbusSessionInterface *iface) -{ - session_signals[SESSION_SIGNAL_SESSION_CLOSED] = - g_signal_new ("session-closed", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); -} - -static void -meta_dbus_session_watcher_finalize (GObject *object) -{ - MetaDbusSessionWatcher *session_watcher = META_DBUS_SESSION_WATCHER (object); - - g_hash_table_destroy (session_watcher->clients); - - G_OBJECT_CLASS (meta_dbus_session_watcher_parent_class)->finalize (object); -} - -static void -meta_dbus_session_watcher_init (MetaDbusSessionWatcher *session_watcher) -{ - session_watcher->clients = - g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - (GDestroyNotify) meta_dbus_session_client_destroy); -} - -static void -meta_dbus_session_watcher_class_init (MetaDbusSessionWatcherClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_dbus_session_watcher_finalize; -} diff --git a/src/backends/meta-dbus-session-watcher.h b/src/backends/meta-dbus-session-watcher.h deleted file mode 100644 index 06d3e1ff9..000000000 --- a/src/backends/meta-dbus-session-watcher.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_DBUS_SESSION_WATCHER_H -#define META_DBUS_SESSION_WATCHER_H - -#include - -#define META_TYPE_DBUS_SESSION (meta_dbus_session_get_type ()) -G_DECLARE_INTERFACE (MetaDbusSession, meta_dbus_session, - META, DBUS_SESSION, - GObject) - -struct _MetaDbusSessionInterface -{ - GTypeInterface parent_iface; - - void (* client_vanished) (MetaDbusSession *session); -}; - -#define META_TYPE_DBUS_SESSION_WATCHER (meta_dbus_session_watcher_get_type ()) -G_DECLARE_FINAL_TYPE (MetaDbusSessionWatcher, - meta_dbus_session_watcher, - META, DBUS_SESSION_WATCHER, - GObject) - -void meta_dbus_session_watcher_watch_session (MetaDbusSessionWatcher *session_watcher, - const char *client_dbus_name, - MetaDbusSession *session); - -void meta_dbus_session_notify_closed (MetaDbusSession *session); - -#endif /* META_DBUS_SESSION_WATCHER_H */ diff --git a/src/backends/meta-display-config-shared.h b/src/backends/meta-display-config-shared.h deleted file mode 100644 index f037dac83..000000000 --- a/src/backends/meta-display-config-shared.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * Copyright (C) 2013 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -/* This file is shared between mutter (src/core/meta-display-config-shared.h) - and gnome-desktop (libgnome-desktop/meta-xrandr-shared.h). - - The canonical place for all changes is mutter. - - There should be no includes in this file. -*/ - -#ifndef META_DISPLAY_CONFIG_SHARED_H -#define META_DISPLAY_CONFIG_SHARED_H - -typedef enum -{ - META_POWER_SAVE_UNSUPPORTED = -1, - META_POWER_SAVE_ON = 0, - META_POWER_SAVE_STANDBY, - META_POWER_SAVE_SUSPEND, - META_POWER_SAVE_OFF, -} MetaPowerSave; - -#endif /* META_DISPLAY_CONFIG_SHARED_H */ diff --git a/src/backends/meta-dnd-private.h b/src/backends/meta-dnd-private.h deleted file mode 100644 index 0cfb3d788..000000000 --- a/src/backends/meta-dnd-private.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 Hyungwon Hwang - * - * 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 . - */ - -#ifndef META_DND_PRIVATE__H -#define META_DND_PRIVATE__H - -#include -#include - -#include "backends/meta-backend-private.h" -#include "compositor/meta-compositor-x11.h" - -gboolean meta_dnd_handle_xdnd_event (MetaBackend *backend, - MetaCompositorX11 *compositor_x11, - Display *xdisplay, - XEvent *xev); - -void meta_dnd_init_xdnd (MetaX11Display *x11_display); - -#ifdef HAVE_WAYLAND -void meta_dnd_wayland_handle_begin_modal (MetaCompositor *compositor); -void meta_dnd_wayland_handle_end_modal (MetaCompositor *compositor); -#endif - -#endif /* META_DND_PRIVATE_H */ diff --git a/src/backends/meta-egl-ext.h b/src/backends/meta-egl-ext.h deleted file mode 100644 index db0b74f76..000000000 --- a/src/backends/meta-egl-ext.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef META_EGL_EXT_H -#define META_EGL_EXT_H - -#include -#include -#include - -/* - * This is a little different to the tests shipped with EGL implementations, - * which wrap the entire thing in #ifndef EGL_WL_bind_wayland_display, then go - * on to define both BindWaylandDisplay and QueryWaylandBuffer. - * - * Unfortunately, some implementations (particularly the version of Mesa shipped - * in Ubuntu 12.04) define EGL_WL_bind_wayland_display, but then only provide - * prototypes for (Un)BindWaylandDisplay, completely omitting - * QueryWaylandBuffer. - * - * Detect this, and provide our own definitions if necessary. - */ -#ifndef EGL_WAYLAND_BUFFER_WL -#define EGL_WAYLAND_BUFFER_WL 0x31D5 /* eglCreateImageKHR target */ -#define EGL_WAYLAND_PLANE_WL 0x31D6 /* eglCreateImageKHR target */ - -#define EGL_TEXTURE_Y_U_V_WL 0x31D7 -#define EGL_TEXTURE_Y_UV_WL 0x31D8 -#define EGL_TEXTURE_Y_XUXV_WL 0x31D9 -#define EGL_TEXTURE_EXTERNAL_WL 0x31DA - -struct wl_resource; -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLBoolean EGLAPIENTRY eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value); -#endif -typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYWAYLANDBUFFERWL) (EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value); -#endif - -/* - * FIXME: Remove both EGL_EXT_stream_acquire_mode and - * EGL_NV_output_drm_flip_event definitions below once both extensions - * get published by Khronos and incorportated into Khronos' header files - */ -#ifndef EGL_EXT_stream_acquire_mode -#define EGL_EXT_stream_acquire_mode 1 -#define EGL_CONSUMER_AUTO_ACQUIRE_EXT 0x332B -#define EGL_RESOURCE_BUSY_EXT 0x3353 -typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREATTRIBEXTPROC) (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list); -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireAttribEXT (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list); -#endif -#endif /* EGL_EXT_stream_acquire_mode */ - -#ifndef EGL_NV_output_drm_flip_event -#define EGL_NV_output_drm_flip_event 1 -#define EGL_DRM_FLIP_EVENT_DATA_NV 0x333E -#endif /* EGL_NV_output_drm_flip_event */ - -#ifndef EGL_NV_stream_attrib -#define EGL_NV_stream_attrib 1 -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamAttribNV(EGLDisplay dpy, const EGLAttrib *attrib_list); -EGLAPI EGLBoolean EGLAPIENTRY eglSetStreamAttribNV(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib value); -EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamAttribNV(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib *value); -EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireAttribNV(EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list); -EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerReleaseAttribNV(EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list); -#endif -typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMATTRIBNVPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETSTREAMATTRIBNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib value); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMATTRIBNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLAttrib *value); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREATTRIBNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEATTRIBNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list); -#endif /* EGL_NV_stream_attrib */ - -#ifndef EGL_WL_wayland_eglstream -#define EGL_WL_wayland_eglstream 1 -#define EGL_WAYLAND_EGLSTREAM_WL 0x334B -#endif /* EGL_WL_wayland_eglstream */ - -#endif /* META_EGL_EXT_H */ diff --git a/src/backends/meta-egl.c b/src/backends/meta-egl.c deleted file mode 100644 index 0d3f8c95d..000000000 --- a/src/backends/meta-egl.c +++ /dev/null @@ -1,1154 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016, 2017 Red Hat Inc. - * Copyright (C) 2018, 2019 DisplayLink (UK) Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-egl.h" -#include "backends/meta-egl-ext.h" -#include "meta/util.h" - -struct _MetaEgl -{ - GObject parent; - - PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT; - - PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; - PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; - - PFNEGLBINDWAYLANDDISPLAYWL eglBindWaylandDisplayWL; - PFNEGLQUERYWAYLANDBUFFERWL eglQueryWaylandBufferWL; - - PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT; - PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT; - - PFNEGLGETOUTPUTLAYERSEXTPROC eglGetOutputLayersEXT; - PFNEGLQUERYOUTPUTLAYERATTRIBEXTPROC eglQueryOutputLayerAttribEXT; - - PFNEGLCREATESTREAMKHRPROC eglCreateStreamKHR; - PFNEGLDESTROYSTREAMKHRPROC eglDestroyStreamKHR; - PFNEGLQUERYSTREAMKHRPROC eglQueryStreamKHR; - - PFNEGLCREATESTREAMATTRIBNVPROC eglCreateStreamAttribNV; - - PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC eglCreateStreamProducerSurfaceKHR; - - PFNEGLSTREAMCONSUMEROUTPUTEXTPROC eglStreamConsumerOutputEXT; - - PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC eglStreamConsumerGLTextureExternalKHR; - - PFNEGLSTREAMCONSUMERACQUIREKHRPROC eglStreamConsumerAcquireKHR; - PFNEGLSTREAMCONSUMERACQUIREATTRIBNVPROC eglStreamConsumerAcquireAttribNV; - - PFNEGLQUERYDMABUFFORMATSEXTPROC eglQueryDmaBufFormatsEXT; - PFNEGLQUERYDMABUFMODIFIERSEXTPROC eglQueryDmaBufModifiersEXT; -}; - -G_DEFINE_TYPE (MetaEgl, meta_egl, G_TYPE_OBJECT) - -G_DEFINE_QUARK (-meta-egl-error-quark, meta_egl_error) - -static const char * -get_egl_error_str (EGLint error_number) -{ - switch (error_number) - { - case EGL_SUCCESS: - return "The last function succeeded without error."; - break; - case EGL_NOT_INITIALIZED: - return "EGL is not initialized, or could not be initialized, for the specified EGL display connection."; - break; - case EGL_BAD_ACCESS: - return "EGL cannot access a requested resource (for example a context is bound in another thread)."; - break; - case EGL_BAD_ALLOC: - return "EGL failed to allocate resources for the requested operation."; - break; - case EGL_BAD_ATTRIBUTE: - return "An unrecognized attribute or attribute value was passed in the attribute list."; - break; - case EGL_BAD_CONTEXT: - return "An EGLContext argument does not name a valid EGL rendering context."; - break; - case EGL_BAD_CONFIG: - return "An EGLConfig argument does not name a valid EGL frame buffer configuration."; - break; - case EGL_BAD_CURRENT_SURFACE: - return "The current surface of the calling thread is a window, pixel buffer or pixmap that is no longer valid."; - break; - case EGL_BAD_DISPLAY: - return "An EGLDisplay argument does not name a valid EGL display connection."; - break; - case EGL_BAD_SURFACE: - return "An EGLSurface argument does not name a valid surface (window, pixel buffer or pixmap) configured for GL rendering."; - break; - case EGL_BAD_MATCH: - return "Arguments are inconsistent (for example, a valid context requires buffers not supplied by a valid surface)."; - break; - case EGL_BAD_PARAMETER: - return "One or more argument values are invalid."; - break; - case EGL_BAD_NATIVE_PIXMAP: - return "A NativePixmapType argument does not refer to a valid native pixmap."; - break; - case EGL_BAD_NATIVE_WINDOW: - return "A NativeWindowType argument does not refer to a valid native window."; - break; - case EGL_CONTEXT_LOST: - return "A power management event has occurred. The application must destroy all contexts and reinitialise OpenGL ES state and objects to continue rendering. "; - break; - case EGL_BAD_STREAM_KHR: - return "An EGLStreamKHR argument does not name a valid EGL stream."; - break; - case EGL_BAD_STATE_KHR: - return "An EGLStreamKHR argument is not in a valid state"; - break; - case EGL_BAD_DEVICE_EXT: - return "An EGLDeviceEXT argument does not name a valid EGL device."; - break; - case EGL_BAD_OUTPUT_LAYER_EXT: - return "An EGLOutputLayerEXT argument does not name a valid EGL output layer."; - case EGL_RESOURCE_BUSY_EXT: - return "The operation could not be completed on the requested resource because it is temporary unavailable."; - default: - return "Unknown error"; - break; - } -} - -static void -set_egl_error (GError **error) -{ - EGLint error_number; - const char *error_str; - - if (!error) - return; - - error_number = eglGetError (); - error_str = get_egl_error_str (error_number); - g_set_error_literal (error, META_EGL_ERROR, - error_number, - error_str); -} - -gboolean -meta_extensions_string_has_extensions_valist (const char *extensions_str, - const char ***missing_extensions, - const char *first_extension, - va_list var_args) -{ - char **extensions; - const char *extension; - size_t num_missing_extensions = 0; - - if (missing_extensions) - *missing_extensions = NULL; - - extensions = g_strsplit (extensions_str, " ", -1); - - extension = first_extension; - while (extension) - { - if (!g_strv_contains ((const char * const *) extensions, extension)) - { - num_missing_extensions++; - if (missing_extensions) - { - *missing_extensions = g_realloc_n (*missing_extensions, - num_missing_extensions + 1, - sizeof (const char *)); - (*missing_extensions)[num_missing_extensions - 1] = extension; - (*missing_extensions)[num_missing_extensions] = NULL; - } - else - { - break; - } - } - extension = va_arg (var_args, char *); - } - - g_strfreev (extensions); - - return num_missing_extensions == 0; -} - -gboolean -meta_egl_has_extensions (MetaEgl *egl, - EGLDisplay display, - const char ***missing_extensions, - const char *first_extension, - ...) -{ - va_list var_args; - const char *extensions_str; - gboolean has_extensions; - - extensions_str = (const char *) eglQueryString (display, EGL_EXTENSIONS); - if (!extensions_str) - { - g_warning ("Failed to query string: %s", - get_egl_error_str (eglGetError ())); - return FALSE; - } - - va_start (var_args, first_extension); - has_extensions = - meta_extensions_string_has_extensions_valist (extensions_str, - missing_extensions, - first_extension, - var_args); - va_end (var_args); - - return has_extensions; -} - -gboolean -meta_egl_initialize (MetaEgl *egl, - EGLDisplay display, - GError **error) -{ - if (!eglInitialize (display, NULL, NULL)) - { - set_egl_error (error); - return FALSE; - } - - return TRUE; -} - -gboolean -meta_egl_bind_api (MetaEgl *egl, - EGLenum api, - GError **error) -{ - if (!eglBindAPI (api)) - { - set_egl_error (error); - return FALSE; - } - - return TRUE; -} - -gpointer -meta_egl_get_proc_address (MetaEgl *egl, - const char *procname, - GError **error) -{ - gpointer func; - - func = (gpointer) eglGetProcAddress (procname); - if (!func) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Could not load symbol '%s': Not found", - procname); - return NULL; - } - - return func; -} - -gboolean -meta_egl_get_config_attrib (MetaEgl *egl, - EGLDisplay display, - EGLConfig config, - EGLint attribute, - EGLint *value, - GError **error) -{ - if (!eglGetConfigAttrib (display, - config, - attribute, - value)) - { - set_egl_error (error); - return FALSE; - } - - return TRUE; -} - -EGLConfig * -meta_egl_choose_all_configs (MetaEgl *egl, - EGLDisplay display, - const EGLint *attrib_list, - EGLint *out_num_configs, - GError **error) -{ - EGLint num_configs; - EGLConfig *configs; - EGLint num_matches; - - if (!eglGetConfigs (display, NULL, 0, &num_configs)) - { - set_egl_error (error); - return FALSE; - } - - if (num_configs < 1) - { - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "No EGL configurations available"); - return FALSE; - } - - configs = g_new0 (EGLConfig, num_configs); - - if (!eglChooseConfig (display, attrib_list, configs, num_configs, &num_matches)) - { - g_free (configs); - set_egl_error (error); - return FALSE; - } - - if (num_matches == 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "No matching EGL configs"); - g_free (configs); - return NULL; - } - - *out_num_configs = num_configs; - return configs; -} - -gboolean -meta_egl_choose_first_config (MetaEgl *egl, - EGLDisplay display, - const EGLint *attrib_list, - EGLConfig *chosen_config, - GError **error) -{ - EGLint num_configs; - EGLConfig *configs; - EGLint num_matches; - - if (!eglGetConfigs (display, NULL, 0, &num_configs)) - { - set_egl_error (error); - return FALSE; - } - - if (num_configs < 1) - { - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "No EGL configurations available"); - return FALSE; - } - - configs = g_new0 (EGLConfig, num_configs); - - if (!eglChooseConfig (display, attrib_list, configs, num_configs, &num_matches)) - { - g_free (configs); - set_egl_error (error); - return FALSE; - } - - if (num_matches == 0) - { - g_free (configs); - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "No matching EGLConfig found"); - return FALSE; - } - - /* - * We don't have any preference specified yet, so lets choose the first one. - */ - *chosen_config = configs[0]; - - g_free (configs); - - return TRUE; -} - -EGLSurface -meta_egl_create_window_surface (MetaEgl *egl, - EGLDisplay display, - EGLConfig config, - EGLNativeWindowType native_window_type, - const EGLint *attrib_list, - GError **error) -{ - EGLSurface surface; - - surface = eglCreateWindowSurface (display, config, - native_window_type, attrib_list); - if (surface == EGL_NO_SURFACE) - { - set_egl_error (error); - return EGL_NO_SURFACE; - } - - return surface; -} - -EGLSurface -meta_egl_create_pbuffer_surface (MetaEgl *egl, - EGLDisplay display, - EGLConfig config, - const EGLint *attrib_list, - GError **error) -{ - EGLSurface surface; - - surface = eglCreatePbufferSurface (display, config, attrib_list); - if (surface == EGL_NO_SURFACE) - { - set_egl_error (error); - return EGL_NO_SURFACE; - } - - return surface; -} - -gboolean -meta_egl_destroy_surface (MetaEgl *egl, - EGLDisplay display, - EGLSurface surface, - GError **error) -{ - if (!eglDestroySurface (display, surface)) - { - set_egl_error (error); - return FALSE; - } - - return TRUE; -} - -static gboolean -is_egl_proc_valid_real (void *proc, - const char *proc_name, - GError **error) -{ - if (!proc) - { - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "EGL proc '%s' not resolved", - proc_name); - return FALSE; - } - - return TRUE; -} - -#define is_egl_proc_valid(proc, error) \ - is_egl_proc_valid_real (proc, #proc, error) - -EGLDisplay -meta_egl_get_platform_display (MetaEgl *egl, - EGLenum platform, - void *native_display, - const EGLint *attrib_list, - GError **error) -{ - EGLDisplay display; - - if (!is_egl_proc_valid (egl->eglGetPlatformDisplayEXT, error)) - return EGL_NO_DISPLAY; - - display = egl->eglGetPlatformDisplayEXT (platform, - native_display, - attrib_list); - if (display == EGL_NO_DISPLAY) - { - set_egl_error (error); - return EGL_NO_DISPLAY; - } - - return display; -} - -gboolean -meta_egl_terminate (MetaEgl *egl, - EGLDisplay display, - GError **error) -{ - if (!eglTerminate (display)) - { - set_egl_error (error); - return FALSE; - } - - return TRUE; -} - -EGLContext -meta_egl_create_context (MetaEgl *egl, - EGLDisplay display, - EGLConfig config, - EGLContext share_context, - const EGLint *attrib_list, - GError **error) -{ - EGLContext context; - - context = eglCreateContext (display, config, share_context, attrib_list); - if (context == EGL_NO_CONTEXT) - { - set_egl_error (error); - return EGL_NO_CONTEXT; - } - - return context; -} - -gboolean -meta_egl_destroy_context (MetaEgl *egl, - EGLDisplay display, - EGLContext context, - GError **error) -{ - if (!eglDestroyContext (display, context)) - { - set_egl_error (error); - return FALSE; - } - - return TRUE; -} - -EGLImageKHR -meta_egl_create_image (MetaEgl *egl, - EGLDisplay display, - EGLContext context, - EGLenum target, - EGLClientBuffer buffer, - const EGLint *attrib_list, - GError **error) -{ - EGLImageKHR image; - - if (!is_egl_proc_valid (egl->eglCreateImageKHR, error)) - return EGL_NO_IMAGE_KHR; - - image = egl->eglCreateImageKHR (display, context, - target, buffer, attrib_list); - if (image == EGL_NO_IMAGE_KHR) - { - set_egl_error (error); - return EGL_NO_IMAGE_KHR; - } - - return image; -} - -gboolean -meta_egl_destroy_image (MetaEgl *egl, - EGLDisplay display, - EGLImageKHR image, - GError **error) -{ - if (!is_egl_proc_valid (egl->eglDestroyImageKHR, error)) - return FALSE; - - if (!egl->eglDestroyImageKHR (display, image)) - { - set_egl_error (error); - return FALSE; - } - - return TRUE; -} - -EGLImageKHR -meta_egl_create_dmabuf_image (MetaEgl *egl, - EGLDisplay egl_display, - unsigned int width, - unsigned int height, - uint32_t drm_format, - uint32_t n_planes, - const int *fds, - const uint32_t *strides, - const uint32_t *offsets, - const uint64_t *modifiers, - GError **error) -{ - EGLint attribs[37]; - int atti = 0; - - /* This requires the Mesa commit in - * Mesa 10.3 (08264e5dad4df448e7718e782ad9077902089a07) or - * Mesa 10.2.7 (55d28925e6109a4afd61f109e845a8a51bd17652). - * Otherwise Mesa closes the fd behind our back and re-importing - * will fail. - * https://bugs.freedesktop.org/show_bug.cgi?id=76188 - */ - - attribs[atti++] = EGL_WIDTH; - attribs[atti++] = width; - attribs[atti++] = EGL_HEIGHT; - attribs[atti++] = height; - attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT; - attribs[atti++] = drm_format; - - if (n_planes > 0) - { - attribs[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT; - attribs[atti++] = fds[0]; - attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT; - attribs[atti++] = offsets[0]; - attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT; - attribs[atti++] = strides[0]; - if (modifiers) - { - attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT; - attribs[atti++] = modifiers[0] & 0xFFFFFFFF; - attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT; - attribs[atti++] = modifiers[0] >> 32; - } - } - - if (n_planes > 1) - { - attribs[atti++] = EGL_DMA_BUF_PLANE1_FD_EXT; - attribs[atti++] = fds[1]; - attribs[atti++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT; - attribs[atti++] = offsets[1]; - attribs[atti++] = EGL_DMA_BUF_PLANE1_PITCH_EXT; - attribs[atti++] = strides[1]; - if (modifiers) - { - attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT; - attribs[atti++] = modifiers[1] & 0xFFFFFFFF; - attribs[atti++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT; - attribs[atti++] = modifiers[1] >> 32; - } - } - - if (n_planes > 2) - { - attribs[atti++] = EGL_DMA_BUF_PLANE2_FD_EXT; - attribs[atti++] = fds[2]; - attribs[atti++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT; - attribs[atti++] = offsets[2]; - attribs[atti++] = EGL_DMA_BUF_PLANE2_PITCH_EXT; - attribs[atti++] = strides[2]; - if (modifiers) - { - attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT; - attribs[atti++] = modifiers[2] & 0xFFFFFFFF; - attribs[atti++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT; - attribs[atti++] = modifiers[2] >> 32; - } - } - - attribs[atti++] = EGL_NONE; - g_assert (atti <= G_N_ELEMENTS (attribs)); - - return meta_egl_create_image (egl, egl_display, EGL_NO_CONTEXT, - EGL_LINUX_DMA_BUF_EXT, NULL, - attribs, - error); -} - -gboolean -meta_egl_make_current (MetaEgl *egl, - EGLDisplay display, - EGLSurface draw, - EGLSurface read, - EGLContext context, - GError **error) -{ - if (!eglMakeCurrent (display, draw, read, context)) - { - set_egl_error (error); - return FALSE; - } - - return TRUE; -} - -gboolean -meta_egl_swap_buffers (MetaEgl *egl, - EGLDisplay display, - EGLSurface surface, - GError **error) -{ - if (!eglSwapBuffers (display, surface)) - { - set_egl_error (error); - return FALSE; - } - - return TRUE; -} - -gboolean -meta_egl_bind_wayland_display (MetaEgl *egl, - EGLDisplay display, - struct wl_display *wayland_display, - GError **error) -{ - if (!is_egl_proc_valid (egl->eglBindWaylandDisplayWL, error)) - return FALSE; - - if (!egl->eglBindWaylandDisplayWL (display, wayland_display)) - { - set_egl_error (error); - return FALSE; - } - - return TRUE; -} - -gboolean -meta_egl_query_wayland_buffer (MetaEgl *egl, - EGLDisplay display, - struct wl_resource *buffer, - EGLint attribute, - EGLint *value, - GError **error) -{ - if (!is_egl_proc_valid (egl->eglQueryWaylandBufferWL, error)) - return FALSE; - - if (!egl->eglQueryWaylandBufferWL (display, buffer, attribute, value)) - { - set_egl_error (error); - return FALSE; - } - - return TRUE; -} - -gboolean -meta_egl_query_devices (MetaEgl *egl, - EGLint max_devices, - EGLDeviceEXT *devices, - EGLint *num_devices, - GError **error) -{ - if (!is_egl_proc_valid (egl->eglQueryDevicesEXT, error)) - return FALSE; - - if (!egl->eglQueryDevicesEXT (max_devices, - devices, - num_devices)) - { - set_egl_error (error); - return FALSE; - } - - return TRUE; -} - -const char * -meta_egl_query_device_string (MetaEgl *egl, - EGLDeviceEXT device, - EGLint name, - GError **error) -{ - const char *device_string; - - if (!is_egl_proc_valid (egl->eglQueryDeviceStringEXT, error)) - return NULL; - - device_string = egl->eglQueryDeviceStringEXT (device, name); - if (!device_string) - { - set_egl_error (error); - return NULL; - } - - return device_string; -} - -gboolean -meta_egl_egl_device_has_extensions (MetaEgl *egl, - EGLDeviceEXT device, - const char ***missing_extensions, - const char *first_extension, - ...) -{ - va_list var_args; - const char *extensions_str; - gboolean has_extensions; - GError *error = NULL; - - extensions_str = meta_egl_query_device_string (egl, device, EGL_EXTENSIONS, - &error); - if (!extensions_str) - { - g_warning ("Failed to query device string: %s", error->message); - g_error_free (error); - return FALSE; - } - - va_start (var_args, first_extension); - has_extensions = - meta_extensions_string_has_extensions_valist (extensions_str, - missing_extensions, - first_extension, - var_args); - va_end (var_args); - - return has_extensions; -} - -gboolean -meta_egl_get_output_layers (MetaEgl *egl, - EGLDisplay display, - const EGLAttrib *attrib_list, - EGLOutputLayerEXT *layers, - EGLint max_layers, - EGLint *num_layers, - GError **error) -{ - if (!is_egl_proc_valid (egl->eglGetOutputLayersEXT, error)) - return FALSE; - - if (!egl->eglGetOutputLayersEXT (display, - attrib_list, - layers, - max_layers, - num_layers)) - { - set_egl_error (error); - return FALSE; - } - - return TRUE; -} - -gboolean -meta_egl_query_output_layer_attrib (MetaEgl *egl, - EGLDisplay display, - EGLOutputLayerEXT layer, - EGLint attribute, - EGLAttrib *value, - GError **error) -{ - if (!is_egl_proc_valid (egl->eglQueryOutputLayerAttribEXT, error)) - return FALSE; - - if (!egl->eglQueryOutputLayerAttribEXT (display, layer, - attribute, value)) - { - set_egl_error (error); - return FALSE; - } - - return TRUE; -} - -EGLStreamKHR -meta_egl_create_stream (MetaEgl *egl, - EGLDisplay display, - const EGLint *attrib_list, - GError **error) -{ - EGLStreamKHR stream; - - if (!is_egl_proc_valid (egl->eglCreateStreamKHR, error)) - return EGL_NO_STREAM_KHR; - - stream = egl->eglCreateStreamKHR (display, attrib_list); - if (stream == EGL_NO_STREAM_KHR) - { - set_egl_error (error); - return EGL_NO_STREAM_KHR; - } - - return stream; -} - -gboolean -meta_egl_destroy_stream (MetaEgl *egl, - EGLDisplay display, - EGLStreamKHR stream, - GError **error) -{ - if (!is_egl_proc_valid (egl->eglDestroyStreamKHR, error)) - return FALSE; - - if (!egl->eglDestroyStreamKHR (display, stream)) - { - set_egl_error (error); - return FALSE; - } - - return TRUE; -} - -gboolean -meta_egl_query_stream (MetaEgl *egl, - EGLDisplay display, - EGLStreamKHR stream, - EGLenum attribute, - EGLint *value, - GError **error) -{ - if (!is_egl_proc_valid (egl->eglQueryStreamKHR, error)) - return FALSE; - - if (!egl->eglQueryStreamKHR (display, stream, attribute, value)) - { - set_egl_error (error); - return FALSE; - } - - return TRUE; -} - -EGLStreamKHR -meta_egl_create_stream_attrib (MetaEgl *egl, - EGLDisplay display, - const EGLAttrib *attrib_list, - GError **error) -{ - EGLStreamKHR stream; - - if (!is_egl_proc_valid (egl->eglCreateStreamAttribNV, error)) - return FALSE; - - stream = egl->eglCreateStreamAttribNV (display, attrib_list); - if (stream == EGL_NO_STREAM_KHR) - { - set_egl_error (error); - return EGL_NO_STREAM_KHR; - } - - return stream; -} - -EGLSurface -meta_egl_create_stream_producer_surface (MetaEgl *egl, - EGLDisplay display, - EGLConfig config, - EGLStreamKHR stream, - const EGLint *attrib_list, - GError **error) -{ - EGLSurface surface; - - if (!is_egl_proc_valid (egl->eglCreateStreamProducerSurfaceKHR, error)) - return EGL_NO_SURFACE; - - surface = egl->eglCreateStreamProducerSurfaceKHR (display, - config, - stream, - attrib_list); - if (surface == EGL_NO_SURFACE) - { - set_egl_error (error); - return EGL_NO_SURFACE; - } - - return surface; -} - -gboolean -meta_egl_stream_consumer_output (MetaEgl *egl, - EGLDisplay display, - EGLStreamKHR stream, - EGLOutputLayerEXT layer, - GError **error) -{ - if (!is_egl_proc_valid (egl->eglStreamConsumerOutputEXT, error)) - return FALSE; - - if (!egl->eglStreamConsumerOutputEXT (display, stream, layer)) - { - set_egl_error (error); - return FALSE; - } - - return TRUE; -} - -gboolean -meta_egl_stream_consumer_acquire_attrib (MetaEgl *egl, - EGLDisplay display, - EGLStreamKHR stream, - EGLAttrib *attrib_list, - GError **error) -{ - if (!is_egl_proc_valid (egl->eglStreamConsumerAcquireAttribNV, error)) - return FALSE; - - if (!egl->eglStreamConsumerAcquireAttribNV (display, stream, attrib_list)) - { - set_egl_error (error); - return FALSE; - } - - return TRUE; -} - -gboolean -meta_egl_stream_consumer_gl_texture_external (MetaEgl *egl, - EGLDisplay display, - EGLStreamKHR stream, - GError **error) -{ - if (!is_egl_proc_valid (egl->eglStreamConsumerGLTextureExternalKHR, error)) - return FALSE; - - if (!egl->eglStreamConsumerGLTextureExternalKHR (display, stream)) - { - set_egl_error (error); - return FALSE; - } - - return TRUE; -} - -gboolean -meta_egl_stream_consumer_acquire (MetaEgl *egl, - EGLDisplay display, - EGLStreamKHR stream, - GError **error) -{ - if (!is_egl_proc_valid (egl->eglStreamConsumerAcquireKHR, error)) - return FALSE; - - if (!egl->eglStreamConsumerAcquireKHR (display, stream)) - { - set_egl_error (error); - return FALSE; - } - - return TRUE; -} - -gboolean -meta_egl_query_dma_buf_formats (MetaEgl *egl, - EGLDisplay display, - EGLint max_formats, - EGLint *formats, - EGLint *num_formats, - GError **error) -{ - if (!is_egl_proc_valid (egl->eglQueryDmaBufFormatsEXT, error)) - return FALSE; - - if (!egl->eglQueryDmaBufFormatsEXT (display, max_formats, formats, - num_formats)) - { - set_egl_error (error); - return FALSE; - } - - return TRUE; -} - -gboolean -meta_egl_query_dma_buf_modifiers (MetaEgl *egl, - EGLDisplay display, - EGLint format, - EGLint max_modifiers, - EGLuint64KHR *modifiers, - EGLBoolean *external_only, - EGLint *num_modifiers, - GError **error) -{ - if (!is_egl_proc_valid (egl->eglQueryDmaBufModifiersEXT, error)) - return FALSE; - - if (!egl->eglQueryDmaBufModifiersEXT (display, format, max_modifiers, - modifiers, external_only, - num_modifiers)) - { - set_egl_error (error); - return FALSE; - } - - return TRUE; -} - -#define GET_EGL_PROC_ADDR(proc) \ - egl->proc = (void *) eglGetProcAddress (#proc); - -static void -meta_egl_constructed (GObject *object) -{ - MetaEgl *egl = META_EGL (object); - - GET_EGL_PROC_ADDR (eglGetPlatformDisplayEXT); - - GET_EGL_PROC_ADDR (eglCreateImageKHR); - GET_EGL_PROC_ADDR (eglDestroyImageKHR); - - GET_EGL_PROC_ADDR (eglBindWaylandDisplayWL); - GET_EGL_PROC_ADDR (eglQueryWaylandBufferWL); - - GET_EGL_PROC_ADDR (eglQueryDevicesEXT); - GET_EGL_PROC_ADDR (eglQueryDeviceStringEXT); - - GET_EGL_PROC_ADDR (eglGetOutputLayersEXT); - GET_EGL_PROC_ADDR (eglQueryOutputLayerAttribEXT); - - GET_EGL_PROC_ADDR (eglCreateStreamKHR); - GET_EGL_PROC_ADDR (eglDestroyStreamKHR); - GET_EGL_PROC_ADDR (eglQueryStreamKHR); - - GET_EGL_PROC_ADDR (eglCreateStreamAttribNV); - - GET_EGL_PROC_ADDR (eglCreateStreamProducerSurfaceKHR); - - GET_EGL_PROC_ADDR (eglStreamConsumerOutputEXT); - - GET_EGL_PROC_ADDR (eglStreamConsumerGLTextureExternalKHR); - - GET_EGL_PROC_ADDR (eglStreamConsumerAcquireKHR); - GET_EGL_PROC_ADDR (eglStreamConsumerAcquireAttribNV); - - GET_EGL_PROC_ADDR (eglQueryDmaBufFormatsEXT); - GET_EGL_PROC_ADDR (eglQueryDmaBufModifiersEXT); -} - -#undef GET_EGL_PROC_ADDR - -static void -meta_egl_init (MetaEgl *egl) -{ -} - -static void -meta_egl_class_init (MetaEglClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->constructed = meta_egl_constructed; -} diff --git a/src/backends/meta-egl.h b/src/backends/meta-egl.h deleted file mode 100644 index e108e714a..000000000 --- a/src/backends/meta-egl.h +++ /dev/null @@ -1,272 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 Red Hat Inc. - * Copyright (C) 2019 DisplayLink (UK) Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#ifndef META_EGL_H -#define META_EGL_H - -#include -#include -#include -#include - -#define META_EGL_ERROR meta_egl_error_quark () - -#define META_TYPE_EGL (meta_egl_get_type ()) -G_DECLARE_FINAL_TYPE (MetaEgl, meta_egl, META, EGL, GObject) - -GQuark meta_egl_error_quark (void); - -gboolean -meta_extensions_string_has_extensions_valist (const char *extensions_str, - const char ***missing_extensions, - const char *first_extension, - va_list var_args); - -gboolean meta_egl_has_extensions (MetaEgl *egl, - EGLDisplay display, - const char ***missing_extensions, - const char *first_extension, - ...); - -gboolean meta_egl_initialize (MetaEgl *egl, - EGLDisplay display, - GError **error); - -gboolean meta_egl_bind_api (MetaEgl *egl, - EGLenum api, - GError **error); - -gpointer meta_egl_get_proc_address (MetaEgl *egl, - const char *procname, - GError **error); - -gboolean meta_egl_choose_first_config (MetaEgl *egl, - EGLDisplay display, - const EGLint *attrib_list, - EGLConfig *chosen_config, - GError **error); - -gboolean meta_egl_get_config_attrib (MetaEgl *egl, - EGLDisplay display, - EGLConfig config, - EGLint attribute, - EGLint *value, - GError **error); - -EGLConfig * meta_egl_choose_all_configs (MetaEgl *egl, - EGLDisplay display, - const EGLint *attrib_list, - EGLint *out_num_configs, - GError **error); - -EGLContext meta_egl_create_context (MetaEgl *egl, - EGLDisplay display, - EGLConfig config, - EGLContext share_context, - const EGLint *attrib_list, - GError **error); - -gboolean meta_egl_destroy_context (MetaEgl *egl, - EGLDisplay display, - EGLContext context, - GError **error); - -EGLImageKHR meta_egl_create_image (MetaEgl *egl, - EGLDisplay display, - EGLContext context, - EGLenum target, - EGLClientBuffer buffer, - const EGLint *attrib_list, - GError **error); - -gboolean meta_egl_destroy_image (MetaEgl *egl, - EGLDisplay display, - EGLImageKHR image, - GError **error); - -EGLImageKHR meta_egl_create_dmabuf_image (MetaEgl *egl, - EGLDisplay egl_display, - unsigned int width, - unsigned int height, - uint32_t drm_format, - uint32_t n_planes, - const int *fds, - const uint32_t *strides, - const uint32_t *offsets, - const uint64_t *modifiers, - GError **error); - -EGLSurface meta_egl_create_window_surface (MetaEgl *egl, - EGLDisplay display, - EGLConfig config, - EGLNativeWindowType native_window_type, - const EGLint *attrib_list, - GError **error); - -EGLSurface meta_egl_create_pbuffer_surface (MetaEgl *egl, - EGLDisplay display, - EGLConfig config, - const EGLint *attrib_list, - GError **error); - -gboolean meta_egl_destroy_surface (MetaEgl *egl, - EGLDisplay display, - EGLSurface surface, - GError **error); - -EGLDisplay meta_egl_get_platform_display (MetaEgl *egl, - EGLenum platform, - void *native_display, - const EGLint *attrib_list, - GError **error); - -gboolean meta_egl_terminate (MetaEgl *egl, - EGLDisplay display, - GError **error); - -gboolean meta_egl_make_current (MetaEgl *egl, - EGLDisplay display, - EGLSurface draw, - EGLSurface read, - EGLContext context, - GError **error); - -gboolean meta_egl_swap_buffers (MetaEgl *egl, - EGLDisplay display, - EGLSurface surface, - GError **error); - -gboolean meta_egl_bind_wayland_display (MetaEgl *egl, - EGLDisplay display, - struct wl_display *wayland_display, - GError **error); - -gboolean meta_egl_query_wayland_buffer (MetaEgl *egl, - EGLDisplay display, - struct wl_resource *buffer, - EGLint attribute, - EGLint *value, - GError **error); - -gboolean meta_egl_query_devices (MetaEgl *egl, - EGLint max_devices, - EGLDeviceEXT *devices, - EGLint *num_devices, - GError **error); - -const char * meta_egl_query_device_string (MetaEgl *egl, - EGLDeviceEXT device, - EGLint name, - GError **error); - -gboolean meta_egl_egl_device_has_extensions (MetaEgl *egl, - EGLDeviceEXT device, - const char ***missing_extensions, - const char *first_extension, - ...); - -gboolean meta_egl_get_output_layers (MetaEgl *egl, - EGLDisplay display, - const EGLAttrib *attrib_list, - EGLOutputLayerEXT *layers, - EGLint max_layers, - EGLint *num_layers, - GError **error); - -gboolean meta_egl_query_output_layer_attrib (MetaEgl *egl, - EGLDisplay display, - EGLOutputLayerEXT layer, - EGLint attribute, - EGLAttrib *value, - GError **error); - -EGLStreamKHR meta_egl_create_stream (MetaEgl *egl, - EGLDisplay display, - const EGLint *attrib_list, - GError **error); - -gboolean meta_egl_destroy_stream (MetaEgl *egl, - EGLDisplay display, - EGLStreamKHR stream, - GError **error); - -gboolean meta_egl_query_stream (MetaEgl *egl, - EGLDisplay display, - EGLStreamKHR stream, - EGLenum attribute, - EGLint *value, - GError **error); - -EGLStreamKHR meta_egl_create_stream_attrib (MetaEgl *egl, - EGLDisplay display, - const EGLAttrib *attrib_list, - GError **error); - -EGLSurface meta_egl_create_stream_producer_surface (MetaEgl *egl, - EGLDisplay display, - EGLConfig config, - EGLStreamKHR stream, - const EGLint *attrib_list, - GError **error); - -gboolean meta_egl_stream_consumer_output (MetaEgl *egl, - EGLDisplay display, - EGLStreamKHR stream, - EGLOutputLayerEXT layer, - GError **error); - -gboolean meta_egl_stream_consumer_acquire_attrib (MetaEgl *egl, - EGLDisplay display, - EGLStreamKHR stream, - EGLAttrib *attrib_list, - GError **error); - -gboolean meta_egl_stream_consumer_acquire (MetaEgl *egl, - EGLDisplay display, - EGLStreamKHR stream, - GError **error); - -gboolean meta_egl_stream_consumer_gl_texture_external (MetaEgl *egl, - EGLDisplay display, - EGLStreamKHR stream, - GError **error); - -gboolean meta_egl_query_dma_buf_formats (MetaEgl *egl, - EGLDisplay display, - EGLint max_formats, - EGLint *formats, - EGLint *num_formats, - GError **error); - -gboolean meta_egl_query_dma_buf_modifiers (MetaEgl *egl, - EGLDisplay display, - EGLint format, - EGLint max_modifiers, - EGLuint64KHR *modifiers, - EGLBoolean *external_only, - EGLint *num_formats, - GError **error); - -#endif /* META_EGL_H */ diff --git a/src/backends/meta-gles3-table.h b/src/backends/meta-gles3-table.h deleted file mode 100644 index 4cc866060..000000000 --- a/src/backends/meta-gles3-table.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 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_GLES3_TABLE_H -#define META_GLES3_TABLE_H - -#include -#include -#include - -typedef struct _MetaGles3Table -{ - void (* glEGLImageTargetTexture2DOES) (GLenum target, - GLeglImageOES image); -} MetaGles3Table; - -#endif /* META_GLES3_TABLE */ diff --git a/src/backends/meta-gles3.c b/src/backends/meta-gles3.c deleted file mode 100644 index 727b3c125..000000000 --- a/src/backends/meta-gles3.c +++ /dev/null @@ -1,163 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 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. - * - */ -#include - -#include "config.h" - -#include "backends/meta-gles3.h" - -#include -#include - -#include "backends/meta-gles3-table.h" - -struct _MetaGles3 -{ - GObject parent; - - MetaEgl *egl; - - MetaGles3Table table; -}; - -G_DEFINE_TYPE (MetaGles3, meta_gles3, G_TYPE_OBJECT) - -MetaGles3Table * -meta_gles3_get_table (MetaGles3 *gles3) -{ - return &gles3->table; -} - -void -meta_gles3_ensure_loaded (MetaGles3 *gles3, - gpointer *func, - const char *name) -{ - GError *error = NULL; - - if (*func) - return; - - *func = meta_egl_get_proc_address (gles3->egl, name, &error); - if (!*func) - g_error ("Failed to load GLES3 symbol: %s", error->message); -} - -static const char * -get_gl_error_str (GLenum gl_error) -{ - switch (gl_error) - { - case GL_NO_ERROR: - return "No error has been recorded."; - case GL_INVALID_ENUM: - return "An unacceptable value is specified for an enumerated argument."; - case GL_INVALID_VALUE: - return "A numeric argument is out of range."; - case GL_INVALID_OPERATION: - return "The specified operation is not allowed in the current state."; - case GL_INVALID_FRAMEBUFFER_OPERATION: - return "The framebuffer object is not complete."; - case GL_OUT_OF_MEMORY: - return "There is not enough memory left to execute the command."; - default: - return "Unknown error"; - } -} - -void -meta_gles3_clear_error (MetaGles3 *gles3) -{ - while (TRUE) - { - GLenum gl_error = glGetError (); - - if (gl_error == GL_NO_ERROR) - break; - } -} - -gboolean -meta_gles3_validate (MetaGles3 *gles3, - GError **error) -{ - GLenum gl_error; - - gl_error = glGetError (); - if (gl_error != GL_NO_ERROR) - { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, - get_gl_error_str (gl_error)); - return FALSE; - } - - return TRUE; -} - -gboolean -meta_gles3_has_extensions (MetaGles3 *gles3, - const char ***missing_extensions, - const char *first_extension, - ...) -{ - va_list var_args; - const char *extensions_str; - gboolean has_extensions; - - extensions_str = (const char *) glGetString (GL_EXTENSIONS); - if (!extensions_str) - { - g_warning ("Failed to get string: %s", get_gl_error_str (glGetError ())); - return FALSE; - } - - va_start (var_args, first_extension); - has_extensions = - meta_extensions_string_has_extensions_valist (extensions_str, - missing_extensions, - first_extension, - var_args); - va_end (var_args); - - return has_extensions; -} - -MetaGles3 * -meta_gles3_new (MetaEgl *egl) -{ - MetaGles3 *gles3; - - gles3 = g_object_new (META_TYPE_GLES3, NULL); - gles3->egl = egl; - - return gles3; -} - -static void -meta_gles3_init (MetaGles3 *gles3) -{ -} - -static void -meta_gles3_class_init (MetaGles3Class *klass) -{ -} diff --git a/src/backends/meta-gles3.h b/src/backends/meta-gles3.h deleted file mode 100644 index 89206cc8f..000000000 --- a/src/backends/meta-gles3.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 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_GLES3_H -#define META_GLES3_H - -#include - -#include "backends/meta-egl.h" - -typedef struct _MetaGles3Table MetaGles3Table; - -#define META_TYPE_GLES3 (meta_gles3_get_type ()) -G_DECLARE_FINAL_TYPE (MetaGles3, meta_gles3, META, GLES3, GObject) - -MetaGles3Table * meta_gles3_get_table (MetaGles3 *gles3); - -void meta_gles3_clear_error (MetaGles3 *gles3); - -gboolean meta_gles3_validate (MetaGles3 *gles3, - GError **error); - -void meta_gles3_ensure_loaded (MetaGles3 *gles, - gpointer *func, - const char *name); - -gboolean meta_gles3_has_extensions (MetaGles3 *gles3, - const char ***missing_extensions, - const char *first_extension, - ...); - -MetaGles3 * meta_gles3_new (MetaEgl *egl); - -#define GLBAS(gles3, func, args) \ -{ \ - GError *_error = NULL; \ - \ - func args; \ - \ - if (!meta_gles3_validate (gles3, &_error)) \ - { \ - g_warning ("%s %s failed: %s", #func, #args, _error->message); \ - g_error_free (_error); \ - } \ -} - -#define GLEXT(gles3, func, args) \ -{ \ - GError *_error = NULL; \ - MetaGles3Table *table; \ - \ - table = meta_gles3_get_table (gles3); \ - meta_gles3_ensure_loaded (gles3, (gpointer *) &table->func, #func); \ - \ - table->func args; \ - \ - if (!meta_gles3_validate (gles3, &_error)) \ - { \ - g_warning ("%s %s failed: %s", #func, #args, _error->message); \ - g_error_free (_error); \ - } \ -} - -#endif /* META_GLES3_H */ diff --git a/src/backends/meta-gpu.c b/src/backends/meta-gpu.c deleted file mode 100644 index ce4353bf0..000000000 --- a/src/backends/meta-gpu.c +++ /dev/null @@ -1,226 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 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. - */ - -#include "config.h" - -#include "backends/meta-gpu.h" - -#include "backends/meta-backend-private.h" -#include "backends/meta-output.h" - -enum -{ - PROP_0, - - PROP_BACKEND, - - PROP_LAST -}; - -static GParamSpec *obj_props[PROP_LAST]; - -typedef struct _MetaGpuPrivate -{ - MetaBackend *backend; - - GList *outputs; - GList *crtcs; - GList *modes; -} MetaGpuPrivate; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaGpu, meta_gpu, G_TYPE_OBJECT) - -gboolean -meta_gpu_has_hotplug_mode_update (MetaGpu *gpu) -{ - MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); - GList *l; - - for (l = priv->outputs; l; l = l->next) - { - MetaOutput *output = l->data; - const MetaOutputInfo *output_info = meta_output_get_info (output); - - if (output_info->hotplug_mode_update) - return TRUE; - } - - return FALSE; -} - -gboolean -meta_gpu_read_current (MetaGpu *gpu, - GError **error) -{ - MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); - gboolean ret; - GList *old_outputs; - GList *old_crtcs; - GList *old_modes; - - /* TODO: Get rid of this when objects incref:s what they need instead */ - old_outputs = priv->outputs; - old_crtcs = priv->crtcs; - old_modes = priv->modes; - - ret = META_GPU_GET_CLASS (gpu)->read_current (gpu, error); - - g_list_free_full (old_outputs, g_object_unref); - g_list_free_full (old_modes, g_object_unref); - g_list_free_full (old_crtcs, g_object_unref); - - return ret; -} - -MetaBackend * -meta_gpu_get_backend (MetaGpu *gpu) -{ - MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); - - return priv->backend; -} - -GList * -meta_gpu_get_outputs (MetaGpu *gpu) -{ - MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); - - return priv->outputs; -} - -GList * -meta_gpu_get_crtcs (MetaGpu *gpu) -{ - MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); - - return priv->crtcs; -} - -GList * -meta_gpu_get_modes (MetaGpu *gpu) -{ - MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); - - return priv->modes; -} - -void -meta_gpu_take_outputs (MetaGpu *gpu, - GList *outputs) -{ - MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); - - priv->outputs = outputs; -} - -void -meta_gpu_take_crtcs (MetaGpu *gpu, - GList *crtcs) -{ - MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); - - priv->crtcs = crtcs; -} - -void -meta_gpu_take_modes (MetaGpu *gpu, - GList *modes) -{ - MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); - - priv->modes = modes; -} - -static void -meta_gpu_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaGpu *gpu = META_GPU (object); - MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); - - switch (prop_id) - { - case PROP_BACKEND: - priv->backend = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_gpu_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaGpu *gpu = META_GPU (object); - MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); - - switch (prop_id) - { - case PROP_BACKEND: - g_value_set_object (value, priv->backend); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_gpu_finalize (GObject *object) -{ - MetaGpu *gpu = META_GPU (object); - MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); - - g_list_free_full (priv->outputs, g_object_unref); - g_list_free_full (priv->modes, g_object_unref); - g_list_free_full (priv->crtcs, g_object_unref); - - G_OBJECT_CLASS (meta_gpu_parent_class)->finalize (object); -} - -static void -meta_gpu_init (MetaGpu *gpu) -{ -} - -static void -meta_gpu_class_init (MetaGpuClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->set_property = meta_gpu_set_property; - object_class->get_property = meta_gpu_get_property; - object_class->finalize = meta_gpu_finalize; - - 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); - g_object_class_install_properties (object_class, PROP_LAST, obj_props); -} diff --git a/src/backends/meta-gpu.h b/src/backends/meta-gpu.h deleted file mode 100644 index 9d12f95a7..000000000 --- a/src/backends/meta-gpu.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 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_GPU_H -#define META_GPU_H - -#include - -#include "backends/meta-monitor-manager-private.h" - -#define META_TYPE_GPU (meta_gpu_get_type ()) -META_EXPORT_TEST -G_DECLARE_DERIVABLE_TYPE (MetaGpu, meta_gpu, META, GPU, GObject) - -struct _MetaGpuClass -{ - GObjectClass parent_class; - - gboolean (* read_current) (MetaGpu *gpu, - GError **error); -}; - -META_EXPORT_TEST -gboolean meta_gpu_read_current (MetaGpu *gpu, - GError **error); - -META_EXPORT_TEST -gboolean meta_gpu_has_hotplug_mode_update (MetaGpu *gpu); - -META_EXPORT_TEST -MetaBackend * meta_gpu_get_backend (MetaGpu *gpu); - -META_EXPORT_TEST -GList * meta_gpu_get_outputs (MetaGpu *gpu); - -META_EXPORT_TEST -GList * meta_gpu_get_crtcs (MetaGpu *gpu); - -META_EXPORT_TEST -GList * meta_gpu_get_modes (MetaGpu *gpu); - -META_EXPORT_TEST -void meta_gpu_take_outputs (MetaGpu *gpu, - GList *outputs); - -META_EXPORT_TEST -void meta_gpu_take_crtcs (MetaGpu *gpu, - GList *crtcs); - -META_EXPORT_TEST -void meta_gpu_take_modes (MetaGpu *gpu, - GList *modes); - -#endif /* META_GPU_H */ diff --git a/src/backends/meta-idle-manager.c b/src/backends/meta-idle-manager.c deleted file mode 100644 index 92ba0a237..000000000 --- a/src/backends/meta-idle-manager.c +++ /dev/null @@ -1,379 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright 2013-2021 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 . - * - * Adapted from gnome-session/gnome-session/gs-idle-monitor.c and - * from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c - */ - -#include "config.h" - -#include "backends/meta-idle-manager.h" - -#include "backends/meta-idle-monitor-private.h" -#include "clutter/clutter.h" -#include "meta/main.h" -#include "meta/meta-context.h" -#include "meta/meta-idle-monitor.h" -#include "meta/util.h" - -#include "meta-dbus-idle-monitor.h" - -typedef struct _MetaIdleManager -{ - MetaBackend *backend; - guint dbus_name_id; - - GHashTable *device_monitors; -} MetaIdleManager; - -static gboolean -handle_get_idletime (MetaDBusIdleMonitor *skeleton, - GDBusMethodInvocation *invocation, - MetaIdleMonitor *monitor) -{ - guint64 idletime; - - idletime = meta_idle_monitor_get_idletime (monitor); - meta_dbus_idle_monitor_complete_get_idletime (skeleton, invocation, idletime); - - return TRUE; -} - -static gboolean -handle_reset_idletime (MetaDBusIdleMonitor *skeleton, - GDBusMethodInvocation *invocation, - MetaIdleMonitor *monitor) -{ - if (!g_getenv ("MUTTER_DEBUG_RESET_IDLETIME")) - { - g_dbus_method_invocation_return_error_literal (invocation, - G_DBUS_ERROR, - G_DBUS_ERROR_UNKNOWN_METHOD, - "This method is for testing purposes only. MUTTER_DEBUG_RESET_IDLETIME must be set to use it"); - return TRUE; - } - - meta_idle_manager_reset_idle_time (meta_idle_monitor_get_manager (monitor)); - meta_dbus_idle_monitor_complete_reset_idletime (skeleton, invocation); - - return TRUE; -} - -typedef struct { - MetaDBusIdleMonitor *dbus_monitor; - MetaIdleMonitor *monitor; - char *dbus_name; - guint watch_id; - guint name_watcher_id; -} DBusWatch; - -static void -destroy_dbus_watch (gpointer data) -{ - DBusWatch *watch = data; - - g_object_unref (watch->dbus_monitor); - g_object_unref (watch->monitor); - g_free (watch->dbus_name); - g_bus_unwatch_name (watch->name_watcher_id); - - g_free (watch); -} - -static void -dbus_idle_callback (MetaIdleMonitor *monitor, - guint watch_id, - gpointer user_data) -{ - DBusWatch *watch = user_data; - GDBusInterfaceSkeleton *skeleton = G_DBUS_INTERFACE_SKELETON (watch->dbus_monitor); - - g_dbus_connection_emit_signal (g_dbus_interface_skeleton_get_connection (skeleton), - watch->dbus_name, - g_dbus_interface_skeleton_get_object_path (skeleton), - "org.gnome.Mutter.IdleMonitor", - "WatchFired", - g_variant_new ("(u)", watch_id), - NULL); -} - -static void -name_vanished_callback (GDBusConnection *connection, - const char *name, - gpointer user_data) -{ - DBusWatch *watch = user_data; - - meta_idle_monitor_remove_watch (watch->monitor, watch->watch_id); -} - -static DBusWatch * -make_dbus_watch (MetaDBusIdleMonitor *skeleton, - GDBusMethodInvocation *invocation, - MetaIdleMonitor *monitor) -{ - DBusWatch *watch; - - watch = g_new0 (DBusWatch, 1); - watch->dbus_monitor = g_object_ref (skeleton); - watch->monitor = g_object_ref (monitor); - watch->dbus_name = g_strdup (g_dbus_method_invocation_get_sender (invocation)); - watch->name_watcher_id = g_bus_watch_name_on_connection (g_dbus_method_invocation_get_connection (invocation), - watch->dbus_name, - G_BUS_NAME_WATCHER_FLAGS_NONE, - NULL, /* appeared */ - name_vanished_callback, - watch, NULL); - - return watch; -} - -static gboolean -handle_add_idle_watch (MetaDBusIdleMonitor *skeleton, - GDBusMethodInvocation *invocation, - guint64 interval, - MetaIdleMonitor *monitor) -{ - DBusWatch *watch; - - watch = make_dbus_watch (skeleton, invocation, monitor); - watch->watch_id = meta_idle_monitor_add_idle_watch (monitor, interval, - dbus_idle_callback, watch, destroy_dbus_watch); - - meta_dbus_idle_monitor_complete_add_idle_watch (skeleton, invocation, watch->watch_id); - - return TRUE; -} - -static gboolean -handle_add_user_active_watch (MetaDBusIdleMonitor *skeleton, - GDBusMethodInvocation *invocation, - MetaIdleMonitor *monitor) -{ - DBusWatch *watch; - - watch = make_dbus_watch (skeleton, invocation, monitor); - watch->watch_id = meta_idle_monitor_add_user_active_watch (monitor, - dbus_idle_callback, watch, - destroy_dbus_watch); - - meta_dbus_idle_monitor_complete_add_user_active_watch (skeleton, invocation, watch->watch_id); - - return TRUE; -} - -static gboolean -handle_remove_watch (MetaDBusIdleMonitor *skeleton, - GDBusMethodInvocation *invocation, - guint id, - MetaIdleMonitor *monitor) -{ - meta_idle_monitor_remove_watch (monitor, id); - meta_dbus_idle_monitor_complete_remove_watch (skeleton, invocation); - - return TRUE; -} - -static void -create_monitor_skeleton (GDBusObjectManagerServer *manager, - MetaIdleMonitor *monitor, - const char *path) -{ - MetaDBusIdleMonitor *skeleton; - MetaDBusObjectSkeleton *object; - - skeleton = meta_dbus_idle_monitor_skeleton_new (); - g_signal_connect (skeleton, "handle-add-idle-watch", - G_CALLBACK (handle_add_idle_watch), monitor); - g_signal_connect (skeleton, "handle-add-user-active-watch", - G_CALLBACK (handle_add_user_active_watch), monitor); - g_signal_connect (skeleton, "handle-remove-watch", - G_CALLBACK (handle_remove_watch), monitor); - g_signal_connect (skeleton, "handle-reset-idletime", - G_CALLBACK (handle_reset_idletime), monitor); - g_signal_connect (skeleton, "handle-get-idletime", - G_CALLBACK (handle_get_idletime), monitor); - - object = meta_dbus_object_skeleton_new (path); - meta_dbus_object_skeleton_set_idle_monitor (object, skeleton); - - g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object)); - - g_object_unref (skeleton); - g_object_unref (object); -} - -static void -on_bus_acquired (GDBusConnection *connection, - const char *name, - gpointer user_data) -{ - MetaIdleManager *manager = user_data; - GDBusObjectManagerServer *object_manager; - MetaIdleMonitor *monitor; - char *path; - - object_manager = g_dbus_object_manager_server_new ("/org/gnome/Mutter/IdleMonitor"); - - /* We never clear the core monitor, as that's supposed to cumulate idle times from - all devices */ - monitor = meta_idle_manager_get_core_monitor (manager); - path = g_strdup ("/org/gnome/Mutter/IdleMonitor/Core"); - create_monitor_skeleton (object_manager, monitor, path); - g_free (path); - - g_dbus_object_manager_server_set_connection (object_manager, connection); -} - -static void -on_name_acquired (GDBusConnection *connection, - const char *name, - gpointer user_data) -{ - meta_verbose ("Acquired name %s", name); -} - -static void -on_name_lost (GDBusConnection *connection, - const char *name, - gpointer user_data) -{ - meta_verbose ("Lost or failed to acquire name %s", name); -} - -MetaIdleMonitor * -meta_idle_manager_get_monitor (MetaIdleManager *idle_manager, - ClutterInputDevice *device) -{ - return g_hash_table_lookup (idle_manager->device_monitors, device); -} - -MetaIdleMonitor * -meta_idle_manager_get_core_monitor (MetaIdleManager *idle_manager) -{ - MetaBackend *backend = meta_get_backend (); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - ClutterSeat *seat = clutter_backend_get_default_seat (clutter_backend); - - return meta_backend_get_idle_monitor (backend, - clutter_seat_get_pointer (seat)); -} - -void -meta_idle_manager_reset_idle_time (MetaIdleManager *idle_manager) -{ - MetaIdleMonitor *core_monitor; - - core_monitor = meta_idle_manager_get_core_monitor (idle_manager); - meta_idle_monitor_reset_idletime (core_monitor); -} - -static void -create_device_monitor (MetaIdleManager *idle_manager, - ClutterInputDevice *device) -{ - MetaIdleMonitor *idle_monitor; - - if (g_hash_table_contains (idle_manager->device_monitors, device)) - return; - - idle_monitor = meta_idle_monitor_new (idle_manager, device); - g_hash_table_insert (idle_manager->device_monitors, device, idle_monitor); -} - -static void -on_device_added (ClutterSeat *seat, - ClutterInputDevice *device, - gpointer user_data) -{ - MetaIdleManager *idle_manager = user_data; - - create_device_monitor (idle_manager, device); -} - -static void -on_device_removed (ClutterSeat *seat, - ClutterInputDevice *device, - gpointer user_data) -{ - MetaIdleManager *idle_manager = user_data; - - g_hash_table_remove (idle_manager->device_monitors, device); -} - -static void -create_device_monitors (MetaIdleManager *idle_manager, - ClutterSeat *seat) -{ - GList *l, *devices; - - create_device_monitor (idle_manager, clutter_seat_get_pointer (seat)); - create_device_monitor (idle_manager, clutter_seat_get_keyboard (seat)); - - devices = clutter_seat_list_devices (seat); - for (l = devices; l; l = l->next) - { - ClutterInputDevice *device = l->data; - - create_device_monitor (idle_manager, device); - } - - g_list_free (devices); -} - -MetaIdleManager * -meta_idle_manager_new (MetaBackend *backend) -{ - MetaContext *context = meta_backend_get_context (backend); - ClutterSeat *seat = meta_backend_get_default_seat (backend); - MetaIdleManager *idle_manager; - - idle_manager = g_new0 (MetaIdleManager, 1); - idle_manager->backend = backend; - - idle_manager->dbus_name_id = - g_bus_own_name (G_BUS_TYPE_SESSION, - "org.gnome.Mutter.IdleMonitor", - G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | - (meta_context_is_replacing (context) ? - G_BUS_NAME_OWNER_FLAGS_REPLACE : - G_BUS_NAME_OWNER_FLAGS_NONE), - on_bus_acquired, - on_name_acquired, - on_name_lost, - idle_manager, - NULL); - - idle_manager->device_monitors = - g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) g_object_unref); - g_signal_connect (seat, "device-added", - G_CALLBACK (on_device_added), idle_manager); - g_signal_connect_after (seat, "device-removed", - G_CALLBACK (on_device_removed), idle_manager); - create_device_monitors (idle_manager, seat); - - return idle_manager; -} - -void -meta_idle_manager_free (MetaIdleManager *idle_manager) -{ - g_clear_pointer (&idle_manager->device_monitors, g_hash_table_destroy); - g_bus_unown_name (idle_manager->dbus_name_id); - g_free (idle_manager); -} diff --git a/src/backends/meta-idle-manager.h b/src/backends/meta-idle-manager.h deleted file mode 100644 index c2a998feb..000000000 --- a/src/backends/meta-idle-manager.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2021 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 . - * - */ - -#ifndef META_IDLE_MANAGER_H -#define META_IDLE_MANAGER_H - -#include "backends/meta-backend-types.h" -#include "clutter/clutter.h" - -typedef struct _MetaIdleMonitor MetaIdleMonitor; -typedef struct _MetaIdleManager MetaIdleManager; - -MetaIdleMonitor * meta_idle_manager_get_monitor (MetaIdleManager *idle_manager, - ClutterInputDevice *device); - -MetaIdleMonitor * meta_idle_manager_get_core_monitor (MetaIdleManager *idle_manager); - -void meta_idle_manager_reset_idle_time (MetaIdleManager *idle_manager); - -MetaIdleManager * meta_idle_manager_new (MetaBackend *backend); - -void meta_idle_manager_free (MetaIdleManager *idle_manager); - -#endif /* META_IDLE_MANAGER_H */ diff --git a/src/backends/meta-idle-monitor-private.h b/src/backends/meta-idle-monitor-private.h deleted file mode 100644 index 6d4387876..000000000 --- a/src/backends/meta-idle-monitor-private.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright 2013 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - * - * Adapted from gnome-session/gnome-session/gs-idle-monitor.c and - * from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c - */ - -#ifndef META_IDLE_MONITOR_PRIVATE_H -#define META_IDLE_MONITOR_PRIVATE_H - -#include "core/display-private.h" -#include "meta/meta-idle-monitor.h" - -typedef struct -{ - MetaIdleMonitor *monitor; - guint id; - MetaIdleMonitorWatchFunc callback; - gpointer user_data; - GDestroyNotify notify; - guint64 timeout_msec; - int idle_source_id; - GSource *timeout_source; -} MetaIdleMonitorWatch; - -struct _MetaIdleMonitorClass -{ - GObjectClass parent_class; -}; - -void meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor); - -MetaIdleManager * meta_idle_monitor_get_manager (MetaIdleMonitor *monitor); - -MetaIdleMonitor * meta_idle_monitor_new (MetaIdleManager *idle_manager, - ClutterInputDevice *device); - -#endif /* META_IDLE_MONITOR_PRIVATE_H */ diff --git a/src/backends/meta-idle-monitor.c b/src/backends/meta-idle-monitor.c deleted file mode 100644 index df924d4dd..000000000 --- a/src/backends/meta-idle-monitor.c +++ /dev/null @@ -1,530 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright 2013 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - * - * Adapted from gnome-session/gnome-session/gs-idle-monitor.c and - * from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c - */ - -/** - * SECTION:idle-monitor - * @title: MetaIdleMonitor - * @short_description: Mutter idle counter (similar to X's IDLETIME) - */ - -#include "config.h" - -#include -#include -#include - -#include "backends/gsm-inhibitor-flag.h" -#include "backends/meta-backend-private.h" -#include "backends/meta-idle-monitor-private.h" -#include "clutter/clutter.h" -#include "meta/main.h" -#include "meta/meta-idle-monitor.h" -#include "meta/util.h" - -G_STATIC_ASSERT(sizeof(unsigned long) == sizeof(gpointer)); - -enum -{ - PROP_0, - PROP_DEVICE, - PROP_LAST, -}; - -static GParamSpec *obj_props[PROP_LAST]; - -struct _MetaIdleMonitor -{ - GObject parent; - - MetaIdleManager *idle_manager; - GDBusProxy *session_proxy; - gboolean inhibited; - GHashTable *watches; - ClutterInputDevice *device; - int64_t last_event_time; -}; - -G_DEFINE_TYPE (MetaIdleMonitor, meta_idle_monitor, G_TYPE_OBJECT) - -static void -meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch) -{ - MetaIdleMonitor *monitor; - guint id; - gboolean is_user_active_watch; - - monitor = watch->monitor; - g_object_ref (monitor); - - g_clear_handle_id (&watch->idle_source_id, g_source_remove); - - id = watch->id; - is_user_active_watch = (watch->timeout_msec == 0); - - if (watch->callback) - watch->callback (monitor, id, watch->user_data); - - if (is_user_active_watch) - meta_idle_monitor_remove_watch (monitor, id); - - g_object_unref (monitor); -} - -static void -meta_idle_monitor_dispose (GObject *object) -{ - MetaIdleMonitor *monitor = META_IDLE_MONITOR (object); - - g_clear_pointer (&monitor->watches, g_hash_table_destroy); - g_clear_object (&monitor->session_proxy); - - G_OBJECT_CLASS (meta_idle_monitor_parent_class)->dispose (object); -} - -static void -meta_idle_monitor_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaIdleMonitor *monitor = META_IDLE_MONITOR (object); - - switch (prop_id) - { - case PROP_DEVICE: - g_value_set_object (value, monitor->device); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_idle_monitor_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaIdleMonitor *monitor = META_IDLE_MONITOR (object); - switch (prop_id) - { - case PROP_DEVICE: - monitor->device = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_idle_monitor_class_init (MetaIdleMonitorClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = meta_idle_monitor_dispose; - object_class->get_property = meta_idle_monitor_get_property; - object_class->set_property = meta_idle_monitor_set_property; - - /** - * MetaIdleMonitor:device: - * - * The device to listen to idletime on. - */ - obj_props[PROP_DEVICE] = - g_param_spec_object ("device", - "Device", - "The device to listen to idletime on", - CLUTTER_TYPE_INPUT_DEVICE, - G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - - g_object_class_install_property (object_class, PROP_DEVICE, obj_props[PROP_DEVICE]); -} - -static void -free_watch (gpointer data) -{ - MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) data; - MetaIdleMonitor *monitor = watch->monitor; - - g_object_ref (monitor); - - g_clear_handle_id (&watch->idle_source_id, g_source_remove); - - if (watch->notify != NULL) - watch->notify (watch->user_data); - - if (watch->timeout_source != NULL) - g_source_destroy (watch->timeout_source); - - g_object_unref (monitor); - g_free (watch); -} - -static void -update_inhibited_watch (gpointer key, - gpointer value, - gpointer user_data) -{ - MetaIdleMonitor *monitor = user_data; - MetaIdleMonitorWatch *watch = value; - - if (!watch->timeout_source) - return; - - if (monitor->inhibited) - { - g_source_set_ready_time (watch->timeout_source, -1); - } - else - { - g_source_set_ready_time (watch->timeout_source, - monitor->last_event_time + - watch->timeout_msec * 1000); - } -} - -static void -update_inhibited (MetaIdleMonitor *monitor, - gboolean inhibited) -{ - if (inhibited == monitor->inhibited) - return; - - monitor->inhibited = inhibited; - - g_hash_table_foreach (monitor->watches, - update_inhibited_watch, - monitor); -} - -static void -meta_idle_monitor_inhibited_actions_changed (GDBusProxy *session, - GVariant *changed, - char **invalidated, - gpointer user_data) -{ - MetaIdleMonitor *monitor = user_data; - GVariant *v; - - v = g_variant_lookup_value (changed, "InhibitedActions", G_VARIANT_TYPE_UINT32); - if (v) - { - gboolean inhibited; - - inhibited = !!(g_variant_get_uint32 (v) & GSM_INHIBITOR_FLAG_IDLE); - g_variant_unref (v); - - if (!inhibited) - monitor->last_event_time = g_get_monotonic_time (); - update_inhibited (monitor, inhibited); - } -} - -static void -meta_idle_monitor_init (MetaIdleMonitor *monitor) -{ - GVariant *v; - - monitor->watches = g_hash_table_new_full (NULL, NULL, NULL, free_watch); - monitor->last_event_time = g_get_monotonic_time (); - - /* Monitor inhibitors */ - monitor->session_proxy = - g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | - G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, - NULL, - "org.gnome.SessionManager", - "/org/gnome/SessionManager", - "org.gnome.SessionManager", - NULL, - NULL); - if (!monitor->session_proxy) - return; - - g_signal_connect (monitor->session_proxy, "g-properties-changed", - G_CALLBACK (meta_idle_monitor_inhibited_actions_changed), - monitor); - - v = g_dbus_proxy_get_cached_property (monitor->session_proxy, - "InhibitedActions"); - if (v) - { - monitor->inhibited = !!(g_variant_get_uint32 (v) & - GSM_INHIBITOR_FLAG_IDLE); - g_variant_unref (v); - } -} - -static guint32 -get_next_watch_serial (void) -{ - static guint32 serial = 0; - - g_atomic_int_inc (&serial); - - return serial; -} - -static gboolean -idle_monitor_dispatch_timeout (GSource *source, - GSourceFunc callback, - gpointer user_data) -{ - MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) user_data; - int64_t now; - int64_t ready_time; - - now = g_source_get_time (source); - ready_time = g_source_get_ready_time (source); - if (ready_time > now) - return G_SOURCE_CONTINUE; - - g_source_set_ready_time (watch->timeout_source, -1); - - meta_idle_monitor_watch_fire (watch); - - return G_SOURCE_CONTINUE; -} - -static GSourceFuncs idle_monitor_source_funcs = { - .prepare = NULL, - .check = NULL, - .dispatch = idle_monitor_dispatch_timeout, - .finalize = NULL, -}; - -static MetaIdleMonitorWatch * -make_watch (MetaIdleMonitor *monitor, - guint64 timeout_msec, - MetaIdleMonitorWatchFunc callback, - gpointer user_data, - GDestroyNotify notify) -{ - MetaIdleMonitorWatch *watch; - - watch = g_new0 (MetaIdleMonitorWatch, 1); - - watch->monitor = monitor; - watch->id = get_next_watch_serial (); - watch->callback = callback; - watch->user_data = user_data; - watch->notify = notify; - watch->timeout_msec = timeout_msec; - - if (timeout_msec != 0) - { - GSource *source = g_source_new (&idle_monitor_source_funcs, - sizeof (GSource)); - - g_source_set_callback (source, NULL, watch, NULL); - if (!monitor->inhibited) - { - g_source_set_ready_time (source, - monitor->last_event_time + - timeout_msec * 1000); - } - g_source_attach (source, NULL); - g_source_unref (source); - - watch->timeout_source = source; - } - - g_hash_table_insert (monitor->watches, - GUINT_TO_POINTER (watch->id), - watch); - return watch; -} - -/** - * meta_idle_monitor_add_idle_watch: - * @monitor: A #MetaIdleMonitor - * @interval_msec: The idletime interval, in milliseconds - * @callback: (nullable): The callback to call when the user has - * accumulated @interval_msec milliseconds of idle time. - * @user_data: (nullable): The user data to pass to the callback - * @notify: A #GDestroyNotify - * - * Returns: a watch id - * - * Adds a watch for a specific idle time. The callback will be called - * when the user has accumulated @interval_msec milliseconds of idle time. - * This function will return an ID that can either be passed to - * meta_idle_monitor_remove_watch(), or can be used to tell idle time - * watches apart if you have more than one. - * - * Also note that this function will only care about positive transitions - * (user's idle time exceeding a certain time). If you want to know about - * when the user has become active, use - * meta_idle_monitor_add_user_active_watch(). - */ -guint -meta_idle_monitor_add_idle_watch (MetaIdleMonitor *monitor, - guint64 interval_msec, - MetaIdleMonitorWatchFunc callback, - gpointer user_data, - GDestroyNotify notify) -{ - MetaIdleMonitorWatch *watch; - - g_return_val_if_fail (META_IS_IDLE_MONITOR (monitor), 0); - g_return_val_if_fail (interval_msec > 0, 0); - - watch = make_watch (monitor, - interval_msec, - callback, - user_data, - notify); - - return watch->id; -} - -/** - * meta_idle_monitor_add_user_active_watch: - * @monitor: A #MetaIdleMonitor - * @callback: (nullable): The callback to call when the user is - * active again. - * @user_data: (nullable): The user data to pass to the callback - * @notify: A #GDestroyNotify - * - * Returns: a watch id - * - * Add a one-time watch to know when the user is active again. - * Note that this watch is one-time and will de-activate after the - * function is called, for efficiency purposes. It's most convenient - * to call this when an idle watch, as added by - * meta_idle_monitor_add_idle_watch(), has triggered. - */ -guint -meta_idle_monitor_add_user_active_watch (MetaIdleMonitor *monitor, - MetaIdleMonitorWatchFunc callback, - gpointer user_data, - GDestroyNotify notify) -{ - MetaIdleMonitorWatch *watch; - - g_return_val_if_fail (META_IS_IDLE_MONITOR (monitor), 0); - - watch = make_watch (monitor, - 0, - callback, - user_data, - notify); - - return watch->id; -} - -/** - * meta_idle_monitor_remove_watch: - * @monitor: A #MetaIdleMonitor - * @id: A watch ID - * - * Removes an idle time watcher, previously added by - * meta_idle_monitor_add_idle_watch() or - * meta_idle_monitor_add_user_active_watch(). - */ -void -meta_idle_monitor_remove_watch (MetaIdleMonitor *monitor, - guint id) -{ - g_return_if_fail (META_IS_IDLE_MONITOR (monitor)); - - g_object_ref (monitor); - g_hash_table_remove (monitor->watches, - GUINT_TO_POINTER (id)); - g_object_unref (monitor); -} - -/** - * meta_idle_monitor_get_idletime: - * @monitor: A #MetaIdleMonitor - * - * Returns: The current idle time, in milliseconds, or -1 for not supported - */ -gint64 -meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor) -{ - return (g_get_monotonic_time () - monitor->last_event_time) / 1000; -} - -void -meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor) -{ - GList *node, *watch_ids; - - monitor->last_event_time = g_get_monotonic_time (); - - watch_ids = g_hash_table_get_keys (monitor->watches); - - for (node = watch_ids; node != NULL; node = node->next) - { - guint watch_id = GPOINTER_TO_UINT (node->data); - MetaIdleMonitorWatch *watch; - - watch = g_hash_table_lookup (monitor->watches, - GUINT_TO_POINTER (watch_id)); - if (!watch) - continue; - - if (watch->timeout_msec == 0) - { - meta_idle_monitor_watch_fire (watch); - } - else - { - if (monitor->inhibited) - { - g_source_set_ready_time (watch->timeout_source, -1); - } - else - { - g_source_set_ready_time (watch->timeout_source, - monitor->last_event_time + - watch->timeout_msec * 1000); - } - } - } - - g_list_free (watch_ids); -} - -MetaIdleManager * -meta_idle_monitor_get_manager (MetaIdleMonitor *monitor) -{ - return monitor->idle_manager; -} - -MetaIdleMonitor * -meta_idle_monitor_new (MetaIdleManager *idle_manager, - ClutterInputDevice *device) -{ - MetaIdleMonitor *monitor; - - monitor = g_object_new (META_TYPE_IDLE_MONITOR, - "device", device, - NULL); - monitor->idle_manager = idle_manager; - - return monitor; -} diff --git a/src/backends/meta-input-device-private.h b/src/backends/meta-input-device-private.h deleted file mode 100644 index a2cbd4864..000000000 --- a/src/backends/meta-input-device-private.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright © 2020 Red Hat Ltd. - * - * 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 . - * - * Author: Carlos Garnacho - */ -#ifndef META_INPUT_DEVICE_H -#define META_INPUT_DEVICE_H - -#include - -#ifdef HAVE_LIBWACOM -#include -#endif - -#include "clutter/clutter-mutter.h" - -typedef struct _MetaInputDeviceClass MetaInputDeviceClass; -typedef struct _MetaInputDevice MetaInputDevice; - -struct _MetaInputDeviceClass -{ - ClutterInputDeviceClass parent_class; -}; - -#define META_TYPE_INPUT_DEVICE (meta_input_device_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaInputDevice, - meta_input_device, - META, INPUT_DEVICE, - ClutterInputDevice) - -#ifdef HAVE_LIBWACOM -WacomDevice * meta_input_device_get_wacom_device (MetaInputDevice *input_device); -#endif - -#endif /* META_INPUT_DEVICE_H */ diff --git a/src/backends/meta-input-device.c b/src/backends/meta-input-device.c deleted file mode 100644 index 24f6ef9ae..000000000 --- a/src/backends/meta-input-device.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright © 2020 Red Hat Ltd. - * - * 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 . - * - * Author: Carlos Garnacho - */ - -#include "config.h" - -#include "backends/meta-backend-private.h" -#include "meta-input-device-private.h" - -typedef struct _MetaInputDevicePrivate MetaInputDevicePrivate; - -struct _MetaInputDevicePrivate -{ -#ifdef HAVE_LIBWACOM - WacomDevice *wacom_device; -#else - /* Just something to have non-zero sized struct otherwise */ - gpointer wacom_device; -#endif -}; - -enum -{ - PROP_WACOM_DEVICE = 1, - N_PROPS -}; - -static GParamSpec *props[N_PROPS] = { 0 }; - -G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaInputDevice, - meta_input_device, - CLUTTER_TYPE_INPUT_DEVICE) - -static void -meta_input_device_init (MetaInputDevice *input_device) -{ -} - -static void -meta_input_device_constructed (GObject *object) -{ -#ifdef HAVE_LIBWACOM - MetaInputDevice *input_device; - WacomDeviceDatabase *wacom_db; - MetaInputDevicePrivate *priv; - const char *node; -#endif - - G_OBJECT_CLASS (meta_input_device_parent_class)->constructed (object); - -#ifdef HAVE_LIBWACOM - input_device = META_INPUT_DEVICE (object); - priv = meta_input_device_get_instance_private (input_device); - wacom_db = meta_backend_get_wacom_database (meta_get_backend ()); - node = clutter_input_device_get_device_node (CLUTTER_INPUT_DEVICE (input_device)); - priv->wacom_device = libwacom_new_from_path (wacom_db, node, - WFALLBACK_NONE, NULL); -#endif /* HAVE_LIBWACOM */ -} - -static void -meta_input_device_finalize (GObject *object) -{ -#ifdef HAVE_LIBWACOM - MetaInputDevicePrivate *priv; - - priv = meta_input_device_get_instance_private (META_INPUT_DEVICE (object)); - - g_clear_pointer (&priv->wacom_device, libwacom_destroy); -#endif /* HAVE_LIBWACOM */ - - G_OBJECT_CLASS (meta_input_device_parent_class)->finalize (object); -} - -static void -meta_input_device_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaInputDevicePrivate *priv; - - priv = meta_input_device_get_instance_private (META_INPUT_DEVICE (object)); - - switch (prop_id) - { - case PROP_WACOM_DEVICE: - g_value_set_pointer (value, priv->wacom_device); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_input_device_class_init (MetaInputDeviceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->constructed = meta_input_device_constructed; - object_class->finalize = meta_input_device_finalize; - object_class->get_property = meta_input_device_get_property; - - props[PROP_WACOM_DEVICE] = - g_param_spec_pointer ("wacom-device", - "Wacom device", - "Wacom device", - G_PARAM_READABLE); - - g_object_class_install_properties (object_class, N_PROPS, props); -} - -#ifdef HAVE_LIBWACOM -WacomDevice * -meta_input_device_get_wacom_device (MetaInputDevice *input_device) -{ - MetaInputDevicePrivate *priv; - - priv = meta_input_device_get_instance_private (input_device); - - return priv->wacom_device; -} -#endif /* HAVE_LIBWACOM */ diff --git a/src/backends/meta-input-mapper-private.h b/src/backends/meta-input-mapper-private.h deleted file mode 100644 index 63d480dba..000000000 --- a/src/backends/meta-input-mapper-private.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * 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 . - * - * Author: Carlos Garnacho - */ - -#ifndef META_INPUT_MAPPER_H -#define META_INPUT_MAPPER_H - -#include - -#include "backends/meta-backend-types.h" - -#define META_TYPE_INPUT_MAPPER (meta_input_mapper_get_type ()) - -G_DECLARE_FINAL_TYPE (MetaInputMapper, meta_input_mapper, - META, INPUT_MAPPER, GObject) - -MetaInputMapper * meta_input_mapper_new (void); - -void meta_input_mapper_add_device (MetaInputMapper *mapper, - ClutterInputDevice *device); -void meta_input_mapper_remove_device (MetaInputMapper *mapper, - ClutterInputDevice *device); - -ClutterInputDevice * -meta_input_mapper_get_logical_monitor_device (MetaInputMapper *mapper, - MetaLogicalMonitor *logical_monitor, - ClutterInputDeviceType device_type); -MetaLogicalMonitor * -meta_input_mapper_get_device_logical_monitor (MetaInputMapper *mapper, - ClutterInputDevice *device); - -GSettings * meta_input_mapper_get_tablet_settings (MetaInputMapper *mapper, - ClutterInputDevice *device); - -#endif /* META_INPUT_MAPPER_H */ diff --git a/src/backends/meta-input-mapper.c b/src/backends/meta-input-mapper.c deleted file mode 100644 index ffbe2dd37..000000000 --- a/src/backends/meta-input-mapper.c +++ /dev/null @@ -1,986 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * 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 . - * - * Author: Carlos Garnacho - */ - -#include "config.h" - -#ifdef HAVE_LIBGUDEV -#include -#endif - -#include "backends/meta-input-device-private.h" -#include "meta-input-mapper-private.h" -#include "meta-monitor-manager-private.h" -#include "meta-logical-monitor.h" -#include "meta-backend-private.h" - -#define MAX_SIZE_MATCH_DIFF 0.05 - -typedef struct _MetaMapperInputInfo MetaMapperInputInfo; -typedef struct _MetaMapperOutputInfo MetaMapperOutputInfo; -typedef struct _MappingHelper MappingHelper; -typedef struct _DeviceCandidates DeviceCandidates; -typedef struct _DeviceMatch DeviceMatch; - -struct _MetaInputMapper -{ - GObject parent_instance; - MetaMonitorManager *monitor_manager; - ClutterSeat *seat; - GHashTable *input_devices; /* ClutterInputDevice -> MetaMapperInputInfo */ - GHashTable *output_devices; /* MetaLogicalMonitor -> MetaMapperOutputInfo */ -#ifdef HAVE_LIBGUDEV - GUdevClient *udev_client; -#endif -}; - -typedef enum -{ - META_INPUT_CAP_TOUCH = 1 << 0, /* touch device, either touchscreen or tablet */ - META_INPUT_CAP_STYLUS = 1 << 1, /* tablet pen */ - META_INPUT_CAP_ERASER = 1 << 2, /* tablet eraser */ - META_INPUT_CAP_PAD = 1 << 3, /* pad device, most usually in tablets */ - META_INPUT_CAP_CURSOR = 1 << 4 /* pointer-like device in tablets */ -} MetaInputCapabilityFlags; - -typedef enum -{ - META_MATCH_EDID_VENDOR, /* EDID vendor match, eg. "WAC" for Wacom */ - META_MATCH_EDID_PARTIAL, /* Partial EDID model match, eg. "Cintiq" */ - META_MATCH_EDID_FULL, /* Full EDID model match, eg. "Cintiq 12WX" */ - META_MATCH_SIZE, /* Size from input device and output match */ - META_MATCH_IS_BUILTIN, /* Output is builtin, applies mainly to system-integrated devices */ - META_MATCH_CONFIG, /* Specified by config */ - N_OUTPUT_MATCHES -} MetaOutputMatchType; - -struct _MetaMapperInputInfo -{ - ClutterInputDevice *device; - MetaInputMapper *mapper; - MetaMapperOutputInfo *output; - GSettings *settings; - guint builtin : 1; -}; - -struct _MetaMapperOutputInfo -{ - MetaLogicalMonitor *logical_monitor; - GList *input_devices; - MetaInputCapabilityFlags attached_caps; -}; - -struct _MappingHelper -{ - GArray *device_maps; -}; - -struct _DeviceMatch -{ - MetaMonitor *monitor; - uint32_t score; -}; - -struct _DeviceCandidates -{ - MetaMapperInputInfo *input; - - GArray *matches; /* Array of DeviceMatch */ - - int best; -}; - -enum -{ - DEVICE_MAPPED, - DEVICE_ENABLED, - DEVICE_ASPECT_RATIO, - N_SIGNALS -}; - -static guint signals[N_SIGNALS] = { 0, }; - -static void mapper_output_info_remove_input (MetaMapperOutputInfo *output, - MetaMapperInputInfo *input); - -static void mapper_recalculate_input (MetaInputMapper *mapper, - MetaMapperInputInfo *input); - -G_DEFINE_TYPE (MetaInputMapper, meta_input_mapper, G_TYPE_OBJECT) - -static GSettings * -get_device_settings (ClutterInputDevice *device) -{ - const char *group, *schema, *vendor, *product; - ClutterInputDeviceType type; - GSettings *settings; - char *path; - - type = clutter_input_device_get_device_type (device); - - if (type == CLUTTER_TOUCHSCREEN_DEVICE) - { - group = "touchscreens"; - schema = "org.gnome.desktop.peripherals.touchscreen"; - } - else if (type == CLUTTER_TABLET_DEVICE || - type == CLUTTER_PEN_DEVICE || - type == CLUTTER_ERASER_DEVICE || - type == CLUTTER_CURSOR_DEVICE || - type == CLUTTER_PAD_DEVICE) - { - group = "tablets"; - schema = "org.gnome.desktop.peripherals.tablet"; - } - else - { - return NULL; - } - - vendor = clutter_input_device_get_vendor_id (device); - product = clutter_input_device_get_product_id (device); - path = g_strdup_printf ("/org/gnome/desktop/peripherals/%s/%s:%s/", - group, vendor, product); - - settings = g_settings_new_with_path (schema, path); - g_free (path); - - return settings; -} - -static void -settings_output_changed_cb (GSettings *settings, - const char *key, - MetaMapperInputInfo *info) -{ - if (info->output != NULL) - mapper_output_info_remove_input (info->output, info); - - mapper_recalculate_input (info->mapper, info); -} - -static MetaMapperInputInfo * -mapper_input_info_new (ClutterInputDevice *device, - MetaInputMapper *mapper) -{ - MetaMapperInputInfo *info; - - info = g_new0 (MetaMapperInputInfo, 1); - info->mapper = mapper; - info->device = device; - info->settings = get_device_settings (device); - - g_signal_connect (info->settings, "changed::output", - G_CALLBACK (settings_output_changed_cb), info); - - return info; -} - -static void -mapper_input_info_free (MetaMapperInputInfo *info) -{ - g_signal_handlers_disconnect_by_func (info->settings, settings_output_changed_cb, info); - g_object_unref (info->settings); - g_free (info); -} - -static MetaMapperOutputInfo * -mapper_output_info_new (MetaLogicalMonitor *logical_monitor) -{ - MetaMapperOutputInfo *info; - - info = g_new0 (MetaMapperOutputInfo, 1); - info->logical_monitor = logical_monitor; - - return info; -} - -static void -mapper_output_info_free (MetaMapperOutputInfo *info) -{ - g_free (info); -} - -static MetaInputCapabilityFlags -mapper_input_info_get_caps (MetaMapperInputInfo *info) -{ - ClutterInputDeviceType type; - - type = clutter_input_device_get_device_type (info->device); - - switch (type) - { - case CLUTTER_TOUCHSCREEN_DEVICE: - return META_INPUT_CAP_TOUCH; - case CLUTTER_TABLET_DEVICE: - case CLUTTER_PEN_DEVICE: - return META_INPUT_CAP_STYLUS; - case CLUTTER_ERASER_DEVICE: - return META_INPUT_CAP_ERASER; - case CLUTTER_CURSOR_DEVICE: - return META_INPUT_CAP_CURSOR; - case CLUTTER_PAD_DEVICE: - return META_INPUT_CAP_PAD; - default: - return 0; - } -} - -static void -mapper_input_info_set_output (MetaMapperInputInfo *input, - MetaMapperOutputInfo *output, - MetaMonitor *monitor) -{ - MetaInputMapper *mapper = input->mapper; - float matrix[6] = { 1, 0, 0, 0, 1, 0 }; - double aspect_ratio; - int width, height; - - if (input->output == output) - return; - - input->output = output; - - if (output && monitor) - { - meta_monitor_manager_get_monitor_matrix (mapper->monitor_manager, - monitor, - output->logical_monitor, - matrix); - meta_monitor_get_current_resolution (monitor, &width, &height); - } - else - { - meta_monitor_manager_get_screen_size (mapper->monitor_manager, - &width, &height); - } - - aspect_ratio = (double) width / height; - - g_signal_emit (input->mapper, signals[DEVICE_MAPPED], 0, - input->device, matrix); - g_signal_emit (input->mapper, signals[DEVICE_ASPECT_RATIO], 0, - input->device, aspect_ratio); -} - -static void -mapper_output_info_add_input (MetaMapperOutputInfo *output, - MetaMapperInputInfo *input, - MetaMonitor *monitor) -{ - g_assert (input->output == NULL); - - output->input_devices = g_list_prepend (output->input_devices, input); - output->attached_caps |= mapper_input_info_get_caps (input); - - mapper_input_info_set_output (input, output, monitor); -} - -static void -mapper_output_info_remove_input (MetaMapperOutputInfo *output, - MetaMapperInputInfo *input) -{ - GList *l; - - g_assert (input->output == output); - - output->input_devices = g_list_remove (output->input_devices, input); - output->attached_caps = 0; - - for (l = output->input_devices; l; l = l->next) - output->attached_caps |= mapper_input_info_get_caps (l->data); - - mapper_input_info_set_output (input, NULL, NULL); -} - -static void -mapper_output_info_clear_inputs (MetaMapperOutputInfo *output) -{ - while (output->input_devices) - { - MetaMapperInputInfo *input = output->input_devices->data; - - mapper_input_info_set_output (input, NULL, NULL); - output->input_devices = g_list_remove (output->input_devices, input); - } - - output->attached_caps = 0; -} - -static void -clear_candidates (DeviceCandidates *candidates) -{ - g_clear_pointer (&candidates->matches, g_array_unref); -} - -static void -mapping_helper_init (MappingHelper *helper) -{ - helper->device_maps = g_array_new (FALSE, FALSE, sizeof (DeviceCandidates)); - g_array_set_clear_func (helper->device_maps, - (GDestroyNotify) clear_candidates); -} - -static void -mapping_helper_release (MappingHelper *helper) -{ - g_array_unref (helper->device_maps); -} - -static gboolean -match_edid (MetaMapperInputInfo *input, - MetaMonitor *monitor, - MetaOutputMatchType *match_type) -{ - const gchar *dev_name; - - dev_name = clutter_input_device_get_device_name (input->device); - - if (strcasestr (dev_name, meta_monitor_get_vendor (monitor)) == NULL) - return FALSE; - - *match_type = META_MATCH_EDID_VENDOR; - - if (strcasestr (dev_name, meta_monitor_get_product (monitor)) != NULL) - { - *match_type = META_MATCH_EDID_FULL; - } - else - { - int i; - g_auto (GStrv) split = NULL; - - split = g_strsplit (meta_monitor_get_product (monitor), " ", -1); - - for (i = 0; split[i]; i++) - { - if (strcasestr (dev_name, split[i]) != NULL) - { - *match_type = META_MATCH_EDID_PARTIAL; - break; - } - } - } - - return TRUE; -} - -static gboolean -input_device_get_physical_size (MetaInputMapper *mapper, - ClutterInputDevice *device, - double *width, - double *height) -{ -#ifdef HAVE_LIBGUDEV - g_autoptr (GUdevDevice) udev_device = NULL; - const char *node; - - node = clutter_input_device_get_device_node (device); - if (!node) - return FALSE; - - udev_device = g_udev_client_query_by_device_file (mapper->udev_client, node); - - if (udev_device && - g_udev_device_has_property (udev_device, "ID_INPUT_WIDTH_MM")) - { - *width = g_udev_device_get_property_as_double (udev_device, - "ID_INPUT_WIDTH_MM"); - *height = g_udev_device_get_property_as_double (udev_device, - "ID_INPUT_HEIGHT_MM"); - return TRUE; - } -#endif - - return FALSE; -} - -static gboolean -match_size (MetaMapperInputInfo *input, - MetaMonitor *monitor) -{ - double w_diff, h_diff; - int o_width, o_height; - double i_width, i_height; - - if (!input_device_get_physical_size (input->mapper, input->device, - &i_width, &i_height)) - return FALSE; - - meta_monitor_get_physical_dimensions (monitor, &o_width, &o_height); - w_diff = ABS (1 - ((double) o_width / i_width)); - h_diff = ABS (1 - ((double) o_height / i_height)); - - return w_diff < MAX_SIZE_MATCH_DIFF && h_diff < MAX_SIZE_MATCH_DIFF; -} - -static gboolean -match_builtin (MetaInputMapper *mapper, - MetaMonitor *monitor) -{ - return monitor == meta_monitor_manager_get_laptop_panel (mapper->monitor_manager); -} - -static gboolean -match_config (MetaMapperInputInfo *info, - MetaMonitor *monitor) -{ - gboolean match = FALSE; - char **edid; - guint n_values; - - edid = g_settings_get_strv (info->settings, "output"); - n_values = g_strv_length (edid); - - if (n_values != 3) - { - g_warning ("EDID configuration for device '%s' " - "is incorrect, must have 3 values", - clutter_input_device_get_device_name (info->device)); - goto out; - } - - if (!*edid[0] && !*edid[1] && !*edid[2]) - goto out; - - match = (g_strcmp0 (meta_monitor_get_vendor (monitor), edid[0]) == 0 && - g_strcmp0 (meta_monitor_get_product (monitor), edid[1]) == 0 && - g_strcmp0 (meta_monitor_get_serial (monitor), edid[2]) == 0); - - out: - g_strfreev (edid); - - return match; -} - -static int -sort_by_score (DeviceMatch *match1, - DeviceMatch *match2) -{ - return (int) match1->score - match2->score; -} - -static void -guess_candidates (MetaInputMapper *mapper, - MetaMapperInputInfo *input, - DeviceCandidates *info) -{ - GList *monitors, *l; - gboolean builtin = FALSE; - gboolean integrated = TRUE; - -#ifdef HAVE_LIBWACOM - if (clutter_input_device_get_device_type (input->device) != CLUTTER_TOUCHSCREEN_DEVICE) - { - WacomDevice *wacom_device; - WacomIntegrationFlags flags = 0; - - wacom_device = - meta_input_device_get_wacom_device (META_INPUT_DEVICE (input->device)); - - if (wacom_device) - { - flags = libwacom_get_integration_flags (wacom_device); - - integrated = (flags & (WACOM_DEVICE_INTEGRATED_SYSTEM | - WACOM_DEVICE_INTEGRATED_DISPLAY)) != 0; - builtin = (flags & WACOM_DEVICE_INTEGRATED_SYSTEM) != 0; - } - } -#endif - - monitors = meta_monitor_manager_get_monitors (mapper->monitor_manager); - - for (l = monitors; l; l = l->next) - { - MetaOutputMatchType edid_match; - DeviceMatch match = { l->data, 0 }; - - g_assert (META_IS_MONITOR (l->data)); - - if (match_edid (input, l->data, &edid_match)) - match.score |= 1 << edid_match; - - if (integrated && match_size (input, l->data)) - match.score |= 1 << META_MATCH_SIZE; - - if (builtin && match_builtin (mapper, l->data)) - match.score |= 1 << META_MATCH_IS_BUILTIN; - - if (match_config (input, l->data)) - match.score |= 1 << META_MATCH_CONFIG; - - if (match.score > 0) - g_array_append_val (info->matches, match); - } - - if (info->matches->len == 0) - { - DeviceMatch match = { 0 }; - - match.monitor = - meta_monitor_manager_get_laptop_panel (mapper->monitor_manager); - - if (match.monitor != NULL) - g_array_append_val (info->matches, match); - - info->best = 0; - } - else - { - DeviceMatch *best; - - g_array_sort (info->matches, (GCompareFunc) sort_by_score); - best = &g_array_index (info->matches, DeviceMatch, 0); - info->best = best->score; - } -} - -static void -mapping_helper_add (MappingHelper *helper, - MetaMapperInputInfo *input, - MetaInputMapper *mapper) -{ - DeviceCandidates info = { 0, }; - guint i, pos = 0; - - info.input = input; - info.matches = g_array_new (FALSE, TRUE, sizeof (DeviceMatch)); - - guess_candidates (mapper, input, &info); - - for (i = 0; i < helper->device_maps->len; i++) - { - DeviceCandidates *elem; - - elem = &g_array_index (helper->device_maps, DeviceCandidates, i); - - if (elem->best > info.best) - pos = i; - } - - if (pos >= helper->device_maps->len) - g_array_append_val (helper->device_maps, info); - else - g_array_insert_val (helper->device_maps, pos, info); -} - -static void -mapping_helper_apply (MappingHelper *helper, - MetaInputMapper *mapper) -{ - guint i, j; - - /* Now, decide which input claims which output */ - for (i = 0; i < helper->device_maps->len; i++) - { - DeviceCandidates *info; - - info = &g_array_index (helper->device_maps, DeviceCandidates, i); - g_debug ("Applying mapping %d to input device '%s', capabilities %x", i, - clutter_input_device_get_device_name (info->input->device), - mapper_input_info_get_caps (info->input)); - - for (j = 0; j < info->matches->len; j++) - { - MetaLogicalMonitor *logical_monitor; - MetaMapperOutputInfo *output; - MetaMonitor *monitor; - DeviceMatch *match; - - match = &g_array_index (info->matches, DeviceMatch, j); - g_debug ("Output candidate '%s', score %x", - meta_monitor_get_display_name (match->monitor), - match->score); - - monitor = match->monitor; - logical_monitor = meta_monitor_get_logical_monitor (monitor); - output = g_hash_table_lookup (mapper->output_devices, - logical_monitor); - - if (!output) - continue; - - if (output->attached_caps & mapper_input_info_get_caps (info->input)) - continue; - - g_debug ("Matched input '%s' with output '%s'", - clutter_input_device_get_device_name (info->input->device), - meta_monitor_get_display_name (match->monitor)); - mapper_output_info_add_input (output, info->input, monitor); - break; - } - } -} - -static void -mapper_recalculate_candidates (MetaInputMapper *mapper) -{ - MetaMapperInputInfo *input; - MappingHelper helper; - GHashTableIter iter; - - mapping_helper_init (&helper); - g_hash_table_iter_init (&iter, mapper->input_devices); - - while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &input)) - mapping_helper_add (&helper, input, mapper); - - mapping_helper_apply (&helper, mapper); - mapping_helper_release (&helper); -} - -static void -mapper_recalculate_input (MetaInputMapper *mapper, - MetaMapperInputInfo *input) -{ - MappingHelper helper; - - mapping_helper_init (&helper); - mapping_helper_add (&helper, input, mapper); - mapping_helper_apply (&helper, mapper); - mapping_helper_release (&helper); -} - -static void -mapper_update_outputs (MetaInputMapper *mapper) -{ - MetaMapperOutputInfo *output; - GList *logical_monitors, *l; - GHashTableIter iter; - - g_hash_table_iter_init (&iter, mapper->output_devices); - - while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &output)) - { - mapper_output_info_clear_inputs (output); - g_hash_table_iter_remove (&iter); - } - - logical_monitors = - meta_monitor_manager_get_logical_monitors (mapper->monitor_manager); - - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - MetaMapperOutputInfo *info; - - info = mapper_output_info_new (logical_monitor); - g_hash_table_insert (mapper->output_devices, logical_monitor, info); - } - - mapper_recalculate_candidates (mapper); -} - -static void -input_mapper_monitors_changed_cb (MetaMonitorManager *monitor_manager, - MetaInputMapper *mapper) -{ - mapper_update_outputs (mapper); -} - -static void -input_mapper_power_save_mode_changed_cb (MetaMonitorManager *monitor_manager, - MetaInputMapper *mapper) -{ - ClutterInputDevice *device; - MetaLogicalMonitor *logical_monitor; - MetaMonitor *builtin; - MetaPowerSave power_save_mode; - gboolean on; - - power_save_mode = - meta_monitor_manager_get_power_save_mode (mapper->monitor_manager); - on = power_save_mode == META_POWER_SAVE_ON; - - builtin = meta_monitor_manager_get_laptop_panel (monitor_manager); - if (!builtin) - return; - - logical_monitor = meta_monitor_get_logical_monitor (builtin); - if (!logical_monitor) - return; - - device = - meta_input_mapper_get_logical_monitor_device (mapper, - logical_monitor, - CLUTTER_TOUCHSCREEN_DEVICE); - if (!device) - return; - - g_signal_emit (mapper, signals[DEVICE_ENABLED], 0, device, on); -} - -static void -input_mapper_device_removed_cb (ClutterSeat *seat, - ClutterInputDevice *device, - MetaInputMapper *mapper) -{ - meta_input_mapper_remove_device (mapper, device); -} - -static void -meta_input_mapper_finalize (GObject *object) -{ - MetaInputMapper *mapper = META_INPUT_MAPPER (object); - - g_signal_handlers_disconnect_by_func (mapper->monitor_manager, - input_mapper_monitors_changed_cb, - mapper); - g_signal_handlers_disconnect_by_func (mapper->seat, - input_mapper_device_removed_cb, - mapper); - - g_hash_table_unref (mapper->input_devices); - g_hash_table_unref (mapper->output_devices); -#ifdef HAVE_LIBGUDEV - g_clear_object (&mapper->udev_client); -#endif - - G_OBJECT_CLASS (meta_input_mapper_parent_class)->finalize (object); -} - -static void -meta_input_mapper_constructed (GObject *object) -{ -#ifdef HAVE_LIBGUDEV - const char *udev_subsystems[] = { "input", NULL }; -#endif - MetaInputMapper *mapper = META_INPUT_MAPPER (object); - MetaBackend *backend; - - G_OBJECT_CLASS (meta_input_mapper_parent_class)->constructed (object); - -#ifdef HAVE_LIBGUDEV - mapper->udev_client = g_udev_client_new (udev_subsystems); -#endif - - mapper->seat = clutter_backend_get_default_seat (clutter_get_default_backend ()); - g_signal_connect (mapper->seat, "device-removed", - G_CALLBACK (input_mapper_device_removed_cb), mapper); - - backend = meta_get_backend (); - mapper->monitor_manager = meta_backend_get_monitor_manager (backend); - g_signal_connect (mapper->monitor_manager, "monitors-changed-internal", - G_CALLBACK (input_mapper_monitors_changed_cb), mapper); - g_signal_connect (mapper->monitor_manager, "power-save-mode-changed", - G_CALLBACK (input_mapper_power_save_mode_changed_cb), - mapper); - - mapper_update_outputs (mapper); -} - -static void -meta_input_mapper_class_init (MetaInputMapperClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->constructed = meta_input_mapper_constructed; - object_class->finalize = meta_input_mapper_finalize; - - signals[DEVICE_MAPPED] = - g_signal_new ("device-mapped", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 2, - CLUTTER_TYPE_INPUT_DEVICE, - G_TYPE_POINTER); - signals[DEVICE_ENABLED] = - g_signal_new ("device-enabled", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 2, - CLUTTER_TYPE_INPUT_DEVICE, - G_TYPE_BOOLEAN); - signals[DEVICE_ASPECT_RATIO] = - g_signal_new ("device-aspect-ratio", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 2, - CLUTTER_TYPE_INPUT_DEVICE, - G_TYPE_DOUBLE); -} - -static void -meta_input_mapper_init (MetaInputMapper *mapper) -{ - mapper->input_devices = - g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) mapper_input_info_free); - mapper->output_devices = - g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) mapper_output_info_free); -} - -MetaInputMapper * -meta_input_mapper_new (void) -{ - return g_object_new (META_TYPE_INPUT_MAPPER, NULL); -} - -void -meta_input_mapper_add_device (MetaInputMapper *mapper, - ClutterInputDevice *device) -{ - MetaMapperInputInfo *info; - - g_return_if_fail (mapper != NULL); - g_return_if_fail (device != NULL); - - if (g_hash_table_contains (mapper->input_devices, device)) - return; - - info = mapper_input_info_new (device, mapper); - g_hash_table_insert (mapper->input_devices, device, info); - mapper_recalculate_input (mapper, info); -} - -void -meta_input_mapper_remove_device (MetaInputMapper *mapper, - ClutterInputDevice *device) -{ - MetaMapperInputInfo *input; - - g_return_if_fail (mapper != NULL); - g_return_if_fail (device != NULL); - - input = g_hash_table_lookup (mapper->input_devices, device); - - if (input) - { - if (input->output) - mapper_output_info_remove_input (input->output, input); - g_hash_table_remove (mapper->input_devices, device); - } -} - -ClutterInputDevice * -meta_input_mapper_get_logical_monitor_device (MetaInputMapper *mapper, - MetaLogicalMonitor *logical_monitor, - ClutterInputDeviceType device_type) -{ - MetaMapperOutputInfo *output; - GList *l; - - output = g_hash_table_lookup (mapper->output_devices, logical_monitor); - if (!output) - return NULL; - - for (l = output->input_devices; l; l = l->next) - { - MetaMapperInputInfo *input = l->data; - - if (clutter_input_device_get_device_type (input->device) == device_type) - return input->device; - } - - return NULL; -} - -static ClutterInputDevice * -find_grouped_pen (ClutterInputDevice *device) -{ - GList *l, *devices; - ClutterInputDeviceType device_type; - ClutterInputDevice *pen = NULL; - ClutterSeat *seat; - - device_type = clutter_input_device_get_device_type (device); - - if (device_type == CLUTTER_TABLET_DEVICE || - device_type == CLUTTER_PEN_DEVICE) - return device; - - seat = clutter_input_device_get_seat (device); - devices = clutter_seat_list_devices (seat); - - for (l = devices; l; l = l->next) - { - ClutterInputDevice *other_device = l->data; - - device_type = clutter_input_device_get_device_type (other_device); - - if ((device_type == CLUTTER_TABLET_DEVICE || - device_type == CLUTTER_PEN_DEVICE) && - clutter_input_device_is_grouped (device, other_device)) - { - pen = other_device; - break; - } - } - - g_list_free (devices); - - return pen; -} - -MetaLogicalMonitor * -meta_input_mapper_get_device_logical_monitor (MetaInputMapper *mapper, - ClutterInputDevice *device) -{ - MetaMapperOutputInfo *output; - MetaLogicalMonitor *logical_monitor; - GHashTableIter iter; - GList *l; - - if (clutter_input_device_get_device_type (device) == CLUTTER_PAD_DEVICE) - { - device = find_grouped_pen (device); - if (!device) - return NULL; - } - - g_hash_table_iter_init (&iter, mapper->output_devices); - - while (g_hash_table_iter_next (&iter, (gpointer *) &logical_monitor, - (gpointer *) &output)) - { - for (l = output->input_devices; l; l = l->next) - { - MetaMapperInputInfo *input = l->data; - - if (input->device == device) - return logical_monitor; - } - } - - return NULL; -} - -GSettings * -meta_input_mapper_get_tablet_settings (MetaInputMapper *mapper, - ClutterInputDevice *device) -{ - MetaMapperInputInfo *input; - - g_return_val_if_fail (META_IS_INPUT_MAPPER (mapper), NULL); - g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL); - - input = g_hash_table_lookup (mapper->input_devices, device); - if (!input) - return NULL; - - return input->settings; -} diff --git a/src/backends/meta-input-settings-dummy.c b/src/backends/meta-input-settings-dummy.c deleted file mode 100644 index 74e6f429c..000000000 --- a/src/backends/meta-input-settings-dummy.c +++ /dev/null @@ -1,295 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright 2021 Canonical, Ltd. - * - * 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 . - * - * Author: Marco Trevisan - */ - -#include "backends/meta-input-settings-dummy.h" - -G_DEFINE_TYPE (MetaInputSettingsDummy, - meta_input_settings_dummy, - META_TYPE_INPUT_SETTINGS) - -static void -meta_input_settings_dummy_set_send_events (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopDeviceSendEvents mode) -{ -} - -static void -meta_input_settings_dummy_set_matrix (MetaInputSettings *settings, - ClutterInputDevice *device, - const float matrix[6]) -{ -} - -static void -meta_input_settings_dummy_set_speed (MetaInputSettings *settings, - ClutterInputDevice *device, - gdouble speed) -{ -} - -static void -meta_input_settings_dummy_set_left_handed (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ -} - -static void -meta_input_settings_dummy_set_tap_enabled (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ -} - -static void -meta_input_settings_dummy_set_tap_button_map (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopTouchpadTapButtonMap mode) -{ -} - -static void -meta_input_settings_dummy_set_tap_and_drag_enabled (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ -} - -static void -meta_input_settings_dummy_set_tap_and_drag_lock_enabled (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ -} - -static void -meta_input_settings_dummy_set_disable_while_typing (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ -} - -static void -meta_input_settings_dummy_set_invert_scroll (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean inverted) -{ -} - -static void -meta_input_settings_dummy_set_edge_scroll (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ -} - -static void -meta_input_settings_dummy_set_two_finger_scroll (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ -} - -static void -meta_input_settings_dummy_set_scroll_button (MetaInputSettings *settings, - ClutterInputDevice *device, - guint button, - gboolean button_lock) -{ -} - - -static void -meta_input_settings_dummy_set_click_method (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopTouchpadClickMethod mode) -{ -} - - -static void -meta_input_settings_dummy_set_keyboard_repeat (MetaInputSettings *settings, - gboolean repeat, - guint delay, - guint interval) -{ -} - - -static void -meta_input_settings_dummy_set_tablet_mapping (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopTabletMapping mapping) -{ -} - -static void -meta_input_settings_dummy_set_tablet_aspect_ratio (MetaInputSettings *settings, - ClutterInputDevice *device, - double ratio) -{ -} - -static void -meta_input_settings_dummy_set_tablet_area (MetaInputSettings *settings, - ClutterInputDevice *device, - gdouble padding_left, - gdouble padding_right, - gdouble padding_top, - gdouble padding_bottom) -{ -} - - -static void -meta_input_settings_dummy_set_mouse_accel_profile (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopPointerAccelProfile profile) -{ -} - -static void -meta_input_settings_dummy_set_trackball_accel_profile (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopPointerAccelProfile profile) -{ -} - - -static void -meta_input_settings_dummy_set_stylus_pressure (MetaInputSettings *settings, - ClutterInputDevice *device, - ClutterInputDeviceTool *tool, - const gint32 curve[4]) -{ -} - -static void -meta_input_settings_dummy_set_stylus_button_map (MetaInputSettings *settings, - ClutterInputDevice *device, - ClutterInputDeviceTool *tool, - GDesktopStylusButtonAction primary, - GDesktopStylusButtonAction secondary, - GDesktopStylusButtonAction tertiary) -{ -} - - -static void -meta_input_settings_dummy_set_mouse_middle_click_emulation (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ -} - -static void -meta_input_settings_dummy_set_touchpad_middle_click_emulation (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ -} - -static void -meta_input_settings_dummy_set_trackball_middle_click_emulation (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ -} - -static gboolean -meta_input_settings_dummy_has_two_finger_scroll (MetaInputSettings *settings, - ClutterInputDevice *device) -{ - return FALSE; -} -static gboolean -meta_input_settings_dummy_is_trackball_device (MetaInputSettings *settings, - ClutterInputDevice *device) -{ - return FALSE; -} - -static void -meta_input_settings_dummy_init (MetaInputSettingsDummy *input_settings) -{ -} - -static void -meta_input_settings_dummy_class_init (MetaInputSettingsDummyClass *klass) -{ - MetaInputSettingsClass *input_settings_class = META_INPUT_SETTINGS_CLASS (klass); - - input_settings_class->set_send_events = - meta_input_settings_dummy_set_send_events; - input_settings_class->set_matrix = - meta_input_settings_dummy_set_matrix; - input_settings_class->set_speed = - meta_input_settings_dummy_set_speed; - input_settings_class->set_left_handed = - meta_input_settings_dummy_set_left_handed; - input_settings_class->set_tap_enabled = - meta_input_settings_dummy_set_tap_enabled; - input_settings_class->set_tap_button_map = - meta_input_settings_dummy_set_tap_button_map; - input_settings_class->set_tap_and_drag_enabled = - meta_input_settings_dummy_set_tap_and_drag_enabled; - input_settings_class->set_tap_and_drag_lock_enabled = - meta_input_settings_dummy_set_tap_and_drag_lock_enabled; - input_settings_class->set_disable_while_typing = - meta_input_settings_dummy_set_disable_while_typing; - input_settings_class->set_invert_scroll = - meta_input_settings_dummy_set_invert_scroll; - input_settings_class->set_edge_scroll = - meta_input_settings_dummy_set_edge_scroll; - input_settings_class->set_two_finger_scroll = - meta_input_settings_dummy_set_two_finger_scroll; - input_settings_class->set_scroll_button = - meta_input_settings_dummy_set_scroll_button; - input_settings_class->set_click_method = - meta_input_settings_dummy_set_click_method; - input_settings_class->set_keyboard_repeat = - meta_input_settings_dummy_set_keyboard_repeat; - input_settings_class->set_tablet_mapping = - meta_input_settings_dummy_set_tablet_mapping; - input_settings_class->set_tablet_aspect_ratio = - meta_input_settings_dummy_set_tablet_aspect_ratio; - input_settings_class->set_tablet_area = - meta_input_settings_dummy_set_tablet_area; - input_settings_class->set_mouse_accel_profile = - meta_input_settings_dummy_set_mouse_accel_profile; - input_settings_class->set_trackball_accel_profile = - meta_input_settings_dummy_set_trackball_accel_profile; - input_settings_class->set_stylus_pressure = - meta_input_settings_dummy_set_stylus_pressure; - input_settings_class->set_stylus_button_map = - meta_input_settings_dummy_set_stylus_button_map; - input_settings_class->set_mouse_middle_click_emulation = - meta_input_settings_dummy_set_mouse_middle_click_emulation; - input_settings_class->set_touchpad_middle_click_emulation = - meta_input_settings_dummy_set_touchpad_middle_click_emulation; - input_settings_class->set_trackball_middle_click_emulation = - meta_input_settings_dummy_set_trackball_middle_click_emulation; - input_settings_class->has_two_finger_scroll = - meta_input_settings_dummy_has_two_finger_scroll; - input_settings_class->is_trackball_device = - meta_input_settings_dummy_is_trackball_device; -} diff --git a/src/backends/meta-input-settings-dummy.h b/src/backends/meta-input-settings-dummy.h deleted file mode 100644 index 9d91dc15d..000000000 --- a/src/backends/meta-input-settings-dummy.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright 2021 Canonical, Ltd. - * - * 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 . - * - * Author: Marco Trevisan - */ - -#pragma once - -#include "backends/meta-input-settings-private.h" - -#define META_TYPE_INPUT_SETTINGS_DUMMY (meta_input_settings_dummy_get_type ()) - -G_DECLARE_DERIVABLE_TYPE (MetaInputSettingsDummy, meta_input_settings_dummy, - META, INPUT_SETTINGS_DUMMY, MetaInputSettings); - -struct _MetaInputSettingsDummyClass -{ - MetaInputSettingsClass parent_class; -}; diff --git a/src/backends/meta-input-settings-private.h b/src/backends/meta-input-settings-private.h deleted file mode 100644 index 42ee0e0e6..000000000 --- a/src/backends/meta-input-settings-private.h +++ /dev/null @@ -1,204 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright 2014 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 . - * - * Author: Carlos Garnacho - */ - -#ifndef META_INPUT_SETTINGS_PRIVATE_H -#define META_INPUT_SETTINGS_PRIVATE_H - -#include - -#ifdef HAVE_LIBWACOM -#include -#endif - -#include "backends/meta-backend-types.h" -#include "clutter/clutter.h" -#include "meta/display.h" - -#define META_TYPE_INPUT_SETTINGS (meta_input_settings_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaInputSettings, meta_input_settings, - META, INPUT_SETTINGS, GObject) - -typedef enum -{ - META_A11Y_KEYBOARD_ENABLED = 1 << 0, - META_A11Y_TIMEOUT_ENABLED = 1 << 1, - META_A11Y_MOUSE_KEYS_ENABLED = 1 << 2, - META_A11Y_SLOW_KEYS_ENABLED = 1 << 3, - META_A11Y_SLOW_KEYS_BEEP_PRESS = 1 << 4, - META_A11Y_SLOW_KEYS_BEEP_ACCEPT = 1 << 5, - META_A11Y_SLOW_KEYS_BEEP_REJECT = 1 << 6, - META_A11Y_BOUNCE_KEYS_ENABLED = 1 << 7, - META_A11Y_BOUNCE_KEYS_BEEP_REJECT = 1 << 8, - META_A11Y_TOGGLE_KEYS_ENABLED = 1 << 9, - META_A11Y_STICKY_KEYS_ENABLED = 1 << 10, - META_A11Y_STICKY_KEYS_TWO_KEY_OFF = 1 << 11, - META_A11Y_STICKY_KEYS_BEEP = 1 << 12, - META_A11Y_FEATURE_STATE_CHANGE_BEEP = 1 << 13, -} MetaKeyboardA11yFlags; - -/** - * MetaKbdA11ySettings: - * - * The #MetaKbdA11ySettings structure contains keyboard accessibility - * settings - * - */ -typedef struct _MetaKbdA11ySettings -{ - MetaKeyboardA11yFlags controls; - int slowkeys_delay; - int debounce_delay; - int timeout_delay; - int mousekeys_init_delay; - int mousekeys_max_speed; - int mousekeys_accel_time; -} MetaKbdA11ySettings; - -struct _MetaInputSettingsClass -{ - GObjectClass parent_class; - - void (* set_send_events) (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopDeviceSendEvents mode); - void (* set_matrix) (MetaInputSettings *settings, - ClutterInputDevice *device, - const float matrix[6]); - void (* set_speed) (MetaInputSettings *settings, - ClutterInputDevice *device, - gdouble speed); - void (* set_left_handed) (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled); - void (* set_tap_enabled) (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled); - void (* set_tap_button_map) (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopTouchpadTapButtonMap mode); - void (* set_tap_and_drag_enabled) (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled); - void (* set_tap_and_drag_lock_enabled) (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled); - void (* set_disable_while_typing) (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled); - void (* set_invert_scroll) (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean inverted); - void (* set_edge_scroll) (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled); - void (* set_two_finger_scroll) (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled); - void (* set_scroll_button) (MetaInputSettings *settings, - ClutterInputDevice *device, - guint button, - gboolean button_lock); - - void (* set_click_method) (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopTouchpadClickMethod mode); - - void (* set_keyboard_repeat) (MetaInputSettings *settings, - gboolean repeat, - guint delay, - guint interval); - - void (* set_tablet_mapping) (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopTabletMapping mapping); - void (* set_tablet_aspect_ratio) (MetaInputSettings *settings, - ClutterInputDevice *device, - double ratio); - void (* set_tablet_area) (MetaInputSettings *settings, - ClutterInputDevice *device, - gdouble padding_left, - gdouble padding_right, - gdouble padding_top, - gdouble padding_bottom); - - void (* set_mouse_accel_profile) (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopPointerAccelProfile profile); - void (* set_trackball_accel_profile) (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopPointerAccelProfile profile); - - void (* set_stylus_pressure) (MetaInputSettings *settings, - ClutterInputDevice *device, - ClutterInputDeviceTool *tool, - const gint32 curve[4]); - void (* set_stylus_button_map) (MetaInputSettings *settings, - ClutterInputDevice *device, - ClutterInputDeviceTool *tool, - GDesktopStylusButtonAction primary, - GDesktopStylusButtonAction secondary, - GDesktopStylusButtonAction tertiary); - - void (* set_mouse_middle_click_emulation) (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled); - void (* set_touchpad_middle_click_emulation) (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled); - void (* set_trackball_middle_click_emulation) (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled); - - gboolean (* has_two_finger_scroll) (MetaInputSettings *settings, - ClutterInputDevice *device); - gboolean (* is_trackball_device) (MetaInputSettings *settings, - ClutterInputDevice *device); -}; - -void meta_input_settings_maybe_save_numlock_state (MetaInputSettings *input_settings, - gboolean numlock_state); -gboolean meta_input_settings_maybe_restore_numlock_state (MetaInputSettings *input_settings); - -void meta_input_settings_set_device_matrix (MetaInputSettings *input_settings, - ClutterInputDevice *device, - float matrix[6]); -void meta_input_settings_set_device_enabled (MetaInputSettings *input_settings, - ClutterInputDevice *device, - gboolean enabled); -void meta_input_settings_set_device_aspect_ratio (MetaInputSettings *input_settings, - ClutterInputDevice *device, - double aspect_ratio); - -void meta_input_settings_get_kbd_a11y_settings (MetaInputSettings *input_settings, - MetaKbdA11ySettings *a11y_settings); - -void meta_input_settings_add_device (MetaInputSettings *input_settings, - ClutterInputDevice *device); -void meta_input_settings_remove_device (MetaInputSettings *input_settings, - ClutterInputDevice *device); -void meta_input_settings_notify_tool_change (MetaInputSettings *input_settings, - ClutterInputDevice *device, - ClutterInputDeviceTool *tool); -void meta_input_settings_notify_kbd_a11y_change (MetaInputSettings *input_settings, - MetaKeyboardA11yFlags new_flags, - MetaKeyboardA11yFlags what_changed); - -#endif /* META_INPUT_SETTINGS_PRIVATE_H */ diff --git a/src/backends/meta-input-settings.c b/src/backends/meta-input-settings.c deleted file mode 100644 index 16618608b..000000000 --- a/src/backends/meta-input-settings.c +++ /dev/null @@ -1,1762 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright 2014 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 . - * - * Author: Carlos Garnacho - */ - -/** - * SECTION:input-settings - * @title: MetaInputSettings - * @short_description: Mutter input device configuration - */ - -#include "config.h" - -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-input-device-private.h" -#include "backends/meta-input-settings-private.h" -#include "backends/meta-input-mapper-private.h" -#include "backends/meta-logical-monitor.h" -#include "backends/meta-monitor.h" -#include "core/display-private.h" -#include "meta/util.h" - -static GQuark quark_tool_settings = 0; - -typedef struct _MetaInputSettingsPrivate MetaInputSettingsPrivate; -typedef struct _DeviceMappingInfo DeviceMappingInfo; -typedef struct _CurrentToolInfo CurrentToolInfo; - -struct _CurrentToolInfo -{ - MetaInputSettings *input_settings; - ClutterInputDevice *device; - ClutterInputDeviceTool *tool; - GSettings *settings; - gulong changed_id; -}; - -struct _DeviceMappingInfo -{ - MetaInputSettings *input_settings; - ClutterInputDevice *device; - GSettings *settings; - gulong changed_id; - guint *group_modes; - double aspect_ratio; -}; - -struct _MetaInputSettingsPrivate -{ - ClutterSeat *seat; - gulong monitors_changed_id; - - GSettings *mouse_settings; - GSettings *touchpad_settings; - GSettings *trackball_settings; - GSettings *keyboard_settings; - GSettings *keyboard_a11y_settings; - - GList *devices; - GHashTable *mappable_devices; - - GHashTable *current_tools; - - GHashTable *two_finger_devices; - - MetaKbdA11ySettings kbd_a11y_settings; -}; - -typedef gboolean (* ConfigBoolMappingFunc) (MetaInputSettings *input_settings, - ClutterInputDevice *device, - gboolean value); - -typedef void (*ConfigBoolFunc) (MetaInputSettings *input_settings, - ClutterInputDevice *device, - gboolean setting); -typedef void (*ConfigDoubleFunc) (MetaInputSettings *input_settings, - ClutterInputDevice *device, - gdouble value); -typedef void (*ConfigUintFunc) (MetaInputSettings *input_settings, - ClutterInputDevice *device, - guint value); - -G_DEFINE_TYPE_WITH_PRIVATE (MetaInputSettings, meta_input_settings, G_TYPE_OBJECT) - -enum -{ - KBD_A11Y_CHANGED, - N_SIGNALS -}; - -static guint signals[N_SIGNALS] = { 0 }; - -static GSList * -meta_input_settings_get_devices (MetaInputSettings *settings, - ClutterInputDeviceType type) -{ - MetaInputSettingsPrivate *priv; - GList *l; - GSList *list = NULL; - - priv = meta_input_settings_get_instance_private (settings); - - for (l = priv->devices; l; l = l->next) - { - ClutterInputDevice *device = l->data; - - if (clutter_input_device_get_device_type (device) == type && - clutter_input_device_get_device_mode (device) != CLUTTER_INPUT_MODE_LOGICAL) - list = g_slist_prepend (list, device); - } - - return list; -} - -static void -meta_input_settings_dispose (GObject *object) -{ - MetaInputSettings *settings = META_INPUT_SETTINGS (object); - MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (settings); - - g_clear_object (&priv->mouse_settings); - g_clear_object (&priv->touchpad_settings); - g_clear_object (&priv->trackball_settings); - g_clear_object (&priv->keyboard_settings); - g_clear_object (&priv->keyboard_a11y_settings); - g_clear_pointer (&priv->mappable_devices, g_hash_table_unref); - g_clear_pointer (&priv->current_tools, g_hash_table_unref); - - g_clear_pointer (&priv->two_finger_devices, g_hash_table_destroy); - - G_OBJECT_CLASS (meta_input_settings_parent_class)->dispose (object); -} - -static void -settings_device_set_bool_setting (MetaInputSettings *input_settings, - ClutterInputDevice *device, - ConfigBoolFunc func, - gboolean enabled) -{ - func (input_settings, device, enabled); -} - -static void -settings_set_bool_setting (MetaInputSettings *input_settings, - ClutterInputDeviceType type, - ConfigBoolMappingFunc mapping_func, - ConfigBoolFunc func, - gboolean enabled) -{ - GSList *devices, *l; - - devices = meta_input_settings_get_devices (input_settings, type); - - for (l = devices; l; l = l->next) - { - gboolean value = enabled; - - if (mapping_func) - value = mapping_func (input_settings, l->data, value); - settings_device_set_bool_setting (input_settings, l->data, func, value); - } - - g_slist_free (devices); -} - -static void -settings_device_set_double_setting (MetaInputSettings *input_settings, - ClutterInputDevice *device, - ConfigDoubleFunc func, - gdouble value) -{ - func (input_settings, device, value); -} - -static void -settings_set_double_setting (MetaInputSettings *input_settings, - ClutterInputDeviceType type, - ConfigDoubleFunc func, - gdouble value) -{ - GSList *devices, *d; - - devices = meta_input_settings_get_devices (input_settings, type); - - for (d = devices; d; d = d->next) - settings_device_set_double_setting (input_settings, d->data, func, value); - - g_slist_free (devices); -} - -static void -settings_device_set_uint_setting (MetaInputSettings *input_settings, - ClutterInputDevice *device, - ConfigUintFunc func, - guint value) -{ - (func) (input_settings, device, value); -} - -static void -settings_set_uint_setting (MetaInputSettings *input_settings, - ClutterInputDeviceType type, - ConfigUintFunc func, - guint value) -{ - GSList *devices, *d; - - devices = meta_input_settings_get_devices (input_settings, type); - - for (d = devices; d; d = d->next) - settings_device_set_uint_setting (input_settings, d->data, func, value); - - g_slist_free (devices); -} - -static void -update_touchpad_left_handed (MetaInputSettings *input_settings, - ClutterInputDevice *device) -{ - MetaInputSettingsClass *input_settings_class; - GDesktopTouchpadHandedness handedness; - MetaInputSettingsPrivate *priv; - gboolean enabled = FALSE; - - if (device && - clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE) - return; - - priv = meta_input_settings_get_instance_private (input_settings); - input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); - handedness = g_settings_get_enum (priv->touchpad_settings, "left-handed"); - - switch (handedness) - { - case G_DESKTOP_TOUCHPAD_HANDEDNESS_RIGHT: - enabled = FALSE; - break; - case G_DESKTOP_TOUCHPAD_HANDEDNESS_LEFT: - enabled = TRUE; - break; - case G_DESKTOP_TOUCHPAD_HANDEDNESS_MOUSE: - enabled = g_settings_get_boolean (priv->mouse_settings, "left-handed"); - break; - default: - g_assert_not_reached (); - } - - if (device) - { - settings_device_set_bool_setting (input_settings, device, - input_settings_class->set_left_handed, - enabled); - } - else - { - settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, NULL, - input_settings_class->set_left_handed, - enabled); - } -} - -static void -update_mouse_left_handed (MetaInputSettings *input_settings, - ClutterInputDevice *device) -{ - MetaInputSettingsClass *input_settings_class; - MetaInputSettingsPrivate *priv; - gboolean enabled; - - if (device && - clutter_input_device_get_device_type (device) != CLUTTER_POINTER_DEVICE) - return; - - priv = meta_input_settings_get_instance_private (input_settings); - input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); - enabled = g_settings_get_boolean (priv->mouse_settings, "left-handed"); - - if (device) - { - settings_device_set_bool_setting (input_settings, device, - input_settings_class->set_left_handed, - enabled); - } - else - { - GDesktopTouchpadHandedness touchpad_handedness; - - settings_set_bool_setting (input_settings, CLUTTER_POINTER_DEVICE, NULL, - input_settings_class->set_left_handed, - enabled); - - touchpad_handedness = g_settings_get_enum (priv->touchpad_settings, - "left-handed"); - - /* Also update touchpads if they're following mouse settings */ - if (touchpad_handedness == G_DESKTOP_TOUCHPAD_HANDEDNESS_MOUSE) - update_touchpad_left_handed (input_settings, NULL); - } -} - -static void -do_update_pointer_accel_profile (MetaInputSettings *input_settings, - GSettings *settings, - ClutterInputDevice *device, - GDesktopPointerAccelProfile profile) -{ - MetaInputSettingsPrivate *priv = - meta_input_settings_get_instance_private (input_settings); - MetaInputSettingsClass *input_settings_class = - META_INPUT_SETTINGS_GET_CLASS (input_settings); - - if (settings == priv->mouse_settings) - input_settings_class->set_mouse_accel_profile (input_settings, - device, - profile); - else if (settings == priv->trackball_settings) - input_settings_class->set_trackball_accel_profile (input_settings, - device, - profile); -} - -static void -update_pointer_accel_profile (MetaInputSettings *input_settings, - GSettings *settings, - ClutterInputDevice *device) -{ - GDesktopPointerAccelProfile profile; - - profile = g_settings_get_enum (settings, "accel-profile"); - - if (device) - { - do_update_pointer_accel_profile (input_settings, settings, - device, profile); - } - else - { - MetaInputSettingsPrivate *priv = - meta_input_settings_get_instance_private (input_settings); - GList *l; - - for (l = priv->devices; l; l = l->next) - { - device = l->data; - - if (clutter_input_device_get_device_mode (device) == - CLUTTER_INPUT_MODE_LOGICAL) - continue; - - do_update_pointer_accel_profile (input_settings, settings, - device, profile); - } - } -} - -static GSettings * -get_settings_for_device_type (MetaInputSettings *input_settings, - ClutterInputDeviceType type) -{ - MetaInputSettingsPrivate *priv; - priv = meta_input_settings_get_instance_private (input_settings); - switch (type) - { - case CLUTTER_POINTER_DEVICE: - return priv->mouse_settings; - case CLUTTER_TOUCHPAD_DEVICE: - return priv->touchpad_settings; - default: - return NULL; - } -} - -static void -update_middle_click_emulation (MetaInputSettings *input_settings, - GSettings *settings, - ClutterInputDevice *device) -{ - ConfigBoolFunc func; - const gchar *key = "middle-click-emulation"; - MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (input_settings); - - if (!settings) - return; - - if (settings == priv->mouse_settings) - func = META_INPUT_SETTINGS_GET_CLASS (input_settings)->set_mouse_middle_click_emulation; - else if (settings == priv->touchpad_settings) - func = META_INPUT_SETTINGS_GET_CLASS (input_settings)->set_touchpad_middle_click_emulation; - else if (settings == priv->trackball_settings) - func = META_INPUT_SETTINGS_GET_CLASS (input_settings)->set_trackball_middle_click_emulation; - else - return; - - if (device) - { - settings_device_set_bool_setting (input_settings, device, func, - g_settings_get_boolean (settings, key)); - } - else - { - settings_set_bool_setting (input_settings, CLUTTER_POINTER_DEVICE, - NULL, func, - g_settings_get_boolean (settings, key)); - } -} - -static void -update_device_speed (MetaInputSettings *input_settings, - ClutterInputDevice *device) -{ - GSettings *settings; - ConfigDoubleFunc func; - const gchar *key = "speed"; - - func = META_INPUT_SETTINGS_GET_CLASS (input_settings)->set_speed; - - if (device) - { - settings = get_settings_for_device_type (input_settings, - clutter_input_device_get_device_type (device)); - if (!settings) - return; - - settings_device_set_double_setting (input_settings, device, func, - g_settings_get_double (settings, key)); - } - else - { - settings = get_settings_for_device_type (input_settings, CLUTTER_POINTER_DEVICE); - settings_set_double_setting (input_settings, CLUTTER_POINTER_DEVICE, func, - g_settings_get_double (settings, key)); - settings = get_settings_for_device_type (input_settings, CLUTTER_TOUCHPAD_DEVICE); - settings_set_double_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, func, - g_settings_get_double (settings, key)); - } -} - -static void -update_device_natural_scroll (MetaInputSettings *input_settings, - ClutterInputDevice *device) -{ - GSettings *settings; - ConfigBoolFunc func; - const gchar *key = "natural-scroll"; - - func = META_INPUT_SETTINGS_GET_CLASS (input_settings)->set_invert_scroll; - - if (device) - { - settings = get_settings_for_device_type (input_settings, - clutter_input_device_get_device_type (device)); - if (!settings) - return; - - settings_device_set_bool_setting (input_settings, device, func, - g_settings_get_boolean (settings, key)); - } - else - { - settings = get_settings_for_device_type (input_settings, CLUTTER_POINTER_DEVICE); - settings_set_bool_setting (input_settings, CLUTTER_POINTER_DEVICE, - NULL, func, - g_settings_get_boolean (settings, key)); - settings = get_settings_for_device_type (input_settings, CLUTTER_TOUCHPAD_DEVICE); - settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, - NULL, func, - g_settings_get_boolean (settings, key)); - } -} - -static void -update_touchpad_disable_while_typing (MetaInputSettings *input_settings, - ClutterInputDevice *device) -{ - GSettings *settings; - MetaInputSettingsClass *input_settings_class; - MetaInputSettingsPrivate *priv; - gboolean enabled; - const gchar *key = "disable-while-typing"; - - if (device && - clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE) - return; - - priv = meta_input_settings_get_instance_private (input_settings); - input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); - enabled = g_settings_get_boolean (priv->touchpad_settings, key); - - if (device) - { - settings = get_settings_for_device_type (input_settings, - clutter_input_device_get_device_type (device)); - - if (!settings) - return; - - settings_device_set_bool_setting (input_settings, device, - input_settings_class->set_disable_while_typing, - enabled); - } - else - { - settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, NULL, - input_settings_class->set_disable_while_typing, - enabled); - } -} - -static gboolean -device_is_tablet_touchpad (MetaInputSettings *input_settings, - ClutterInputDevice *device) -{ -#ifdef HAVE_LIBWACOM - WacomIntegrationFlags flags = 0; - WacomDevice *wacom_device; - - if (clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE) - return FALSE; - - wacom_device = meta_input_device_get_wacom_device (META_INPUT_DEVICE (device)); - - if (wacom_device) - { - flags = libwacom_get_integration_flags (wacom_device); - - if ((flags & (WACOM_DEVICE_INTEGRATED_SYSTEM | - WACOM_DEVICE_INTEGRATED_DISPLAY)) == 0) - return TRUE; - } -#endif - - return FALSE; -} - -static gboolean -force_enable_on_tablet (MetaInputSettings *input_settings, - ClutterInputDevice *device, - gboolean value) -{ - return device_is_tablet_touchpad (input_settings, device) || value; -} - -static void -update_touchpad_tap_enabled (MetaInputSettings *input_settings, - ClutterInputDevice *device) -{ - MetaInputSettingsClass *input_settings_class; - MetaInputSettingsPrivate *priv; - gboolean enabled; - - if (device && - clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE) - return; - - priv = meta_input_settings_get_instance_private (input_settings); - input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); - enabled = g_settings_get_boolean (priv->touchpad_settings, "tap-to-click"); - - if (device) - { - enabled = force_enable_on_tablet (input_settings, device, enabled); - settings_device_set_bool_setting (input_settings, device, - input_settings_class->set_tap_enabled, - enabled); - } - else - { - settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, - force_enable_on_tablet, - input_settings_class->set_tap_enabled, - enabled); - } -} - -static void -update_touchpad_tap_button_map (MetaInputSettings *input_settings, - ClutterInputDevice *device) -{ - MetaInputSettingsClass *input_settings_class; - GDesktopTouchpadTapButtonMap method; - MetaInputSettingsPrivate *priv; - - if (device && - clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE) - return; - - priv = meta_input_settings_get_instance_private (input_settings); - input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); - method = g_settings_get_enum (priv->touchpad_settings, "tap-button-map"); - - if (device) - { - settings_device_set_uint_setting (input_settings, device, - input_settings_class->set_tap_button_map, - method); - } - else - { - settings_set_uint_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, - (ConfigUintFunc) input_settings_class->set_tap_button_map, - method); - } -} - -static void -update_touchpad_tap_and_drag_enabled (MetaInputSettings *input_settings, - ClutterInputDevice *device) -{ - MetaInputSettingsClass *input_settings_class; - MetaInputSettingsPrivate *priv; - gboolean enabled; - - if (device && - clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE) - return; - - priv = meta_input_settings_get_instance_private (input_settings); - input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); - enabled = g_settings_get_boolean (priv->touchpad_settings, "tap-and-drag"); - - if (device) - { - enabled = force_enable_on_tablet (input_settings, device, enabled); - settings_device_set_bool_setting (input_settings, device, - input_settings_class->set_tap_and_drag_enabled, - enabled); - } - else - { - settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, - force_enable_on_tablet, - input_settings_class->set_tap_and_drag_enabled, - enabled); - } -} - -static void -update_touchpad_tap_and_drag_lock_enabled (MetaInputSettings *input_settings, - ClutterInputDevice *device) -{ - MetaInputSettingsClass *input_settings_class; - MetaInputSettingsPrivate *priv; - gboolean enabled; - - if (device && - clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE) - return; - - priv = meta_input_settings_get_instance_private (input_settings); - input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); - enabled = g_settings_get_boolean (priv->touchpad_settings, "tap-and-drag-lock"); - - if (device) - { - settings_device_set_bool_setting (input_settings, device, - input_settings_class->set_tap_and_drag_lock_enabled, - enabled); - } - else - { - settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, - NULL, - input_settings_class->set_tap_and_drag_lock_enabled, - enabled); - } -} - -static void -update_touchpad_edge_scroll (MetaInputSettings *input_settings, - ClutterInputDevice *device) -{ - MetaInputSettingsClass *input_settings_class; - gboolean edge_scroll_enabled; - gboolean two_finger_scroll_enabled; - gboolean two_finger_scroll_available; - MetaInputSettingsPrivate *priv; - - if (device && - clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE) - return; - - priv = meta_input_settings_get_instance_private (input_settings); - input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); - edge_scroll_enabled = g_settings_get_boolean (priv->touchpad_settings, "edge-scrolling-enabled"); - two_finger_scroll_enabled = g_settings_get_boolean (priv->touchpad_settings, "two-finger-scrolling-enabled"); - two_finger_scroll_available = g_hash_table_size (priv->two_finger_devices) > 0; - - /* If both are enabled we prefer two finger. */ - if (edge_scroll_enabled && two_finger_scroll_enabled && two_finger_scroll_available) - edge_scroll_enabled = FALSE; - - if (device) - { - settings_device_set_bool_setting (input_settings, device, - input_settings_class->set_edge_scroll, - edge_scroll_enabled); - } - else - { - settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, NULL, - (ConfigBoolFunc) input_settings_class->set_edge_scroll, - edge_scroll_enabled); - } -} - -static void -update_touchpad_two_finger_scroll (MetaInputSettings *input_settings, - ClutterInputDevice *device) -{ - MetaInputSettingsClass *input_settings_class; - gboolean two_finger_scroll_enabled; - MetaInputSettingsPrivate *priv; - - if (device && - clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE) - return; - - priv = meta_input_settings_get_instance_private (input_settings); - input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); - two_finger_scroll_enabled = g_settings_get_boolean (priv->touchpad_settings, "two-finger-scrolling-enabled"); - - /* Disable edge since they can't both be set. */ - if (two_finger_scroll_enabled) - update_touchpad_edge_scroll (input_settings, device); - - if (device) - { - settings_device_set_bool_setting (input_settings, device, - input_settings_class->set_two_finger_scroll, - two_finger_scroll_enabled); - } - else - { - settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, NULL, - (ConfigBoolFunc) input_settings_class->set_two_finger_scroll, - two_finger_scroll_enabled); - } - - /* Edge might have been disabled because two finger was on. */ - if (!two_finger_scroll_enabled) - update_touchpad_edge_scroll (input_settings, device); -} - -static void -update_touchpad_click_method (MetaInputSettings *input_settings, - ClutterInputDevice *device) -{ - MetaInputSettingsClass *input_settings_class; - GDesktopTouchpadClickMethod method; - MetaInputSettingsPrivate *priv; - - if (device && - clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE) - return; - - priv = meta_input_settings_get_instance_private (input_settings); - input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); - method = g_settings_get_enum (priv->touchpad_settings, "click-method"); - - if (device) - { - settings_device_set_uint_setting (input_settings, device, - input_settings_class->set_click_method, - method); - } - else - { - settings_set_uint_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, - (ConfigUintFunc) input_settings_class->set_click_method, - method); - } -} - -static void -update_touchpad_send_events (MetaInputSettings *input_settings, - ClutterInputDevice *device) -{ - MetaInputSettingsClass *input_settings_class; - MetaInputSettingsPrivate *priv; - GDesktopDeviceSendEvents mode; - - if (device && - clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE) - return; - - priv = meta_input_settings_get_instance_private (input_settings); - input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); - mode = g_settings_get_enum (priv->touchpad_settings, "send-events"); - - if (device) - { - settings_device_set_uint_setting (input_settings, device, - input_settings_class->set_send_events, - mode); - } - else - { - settings_set_uint_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, - input_settings_class->set_send_events, - mode); - } -} - -static void -update_trackball_scroll_button (MetaInputSettings *input_settings, - ClutterInputDevice *device) -{ - MetaInputSettingsClass *input_settings_class; - MetaInputSettingsPrivate *priv; - guint button; - gboolean button_lock; - - priv = meta_input_settings_get_instance_private (input_settings); - input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); - - if (device && !input_settings_class->is_trackball_device (input_settings, device)) - return; - - /* This key is 'i' in the schema but it also specifies a minimum - * range of 0 so the cast here is safe. */ - button = (guint) g_settings_get_int (priv->trackball_settings, "scroll-wheel-emulation-button"); - button_lock = g_settings_get_boolean (priv->trackball_settings, "scroll-wheel-emulation-button-lock"); - - if (device) - { - input_settings_class->set_scroll_button (input_settings, device, button, button_lock); - } - else if (!device) - { - GList *l; - - for (l = priv->devices; l; l = l->next) - { - device = l->data; - - if (input_settings_class->is_trackball_device (input_settings, device)) - input_settings_class->set_scroll_button (input_settings, device, button, button_lock); - } - } -} - -static void -update_keyboard_repeat (MetaInputSettings *input_settings) -{ - MetaInputSettingsClass *input_settings_class; - MetaInputSettingsPrivate *priv; - guint delay, interval; - gboolean repeat; - - priv = meta_input_settings_get_instance_private (input_settings); - repeat = g_settings_get_boolean (priv->keyboard_settings, "repeat"); - delay = g_settings_get_uint (priv->keyboard_settings, "delay"); - interval = g_settings_get_uint (priv->keyboard_settings, "repeat-interval"); - - delay = MAX (1, delay); - interval = MAX (1, interval); - - input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); - input_settings_class->set_keyboard_repeat (input_settings, - repeat, delay, interval); -} - -static void -update_tablet_keep_aspect (MetaInputSettings *input_settings, - GSettings *settings, - ClutterInputDevice *device) -{ - MetaInputSettingsPrivate *priv; - MetaInputSettingsClass *input_settings_class; - DeviceMappingInfo *info; - gboolean keep_aspect; - double aspect_ratio; - - if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE && - clutter_input_device_get_device_type (device) != CLUTTER_PEN_DEVICE && - clutter_input_device_get_device_type (device) != CLUTTER_ERASER_DEVICE) - return; - - priv = meta_input_settings_get_instance_private (input_settings); - - info = g_hash_table_lookup (priv->mappable_devices, device); - if (!info) - return; - -#ifdef HAVE_LIBWACOM - { - WacomDevice *wacom_device; - - wacom_device = meta_input_device_get_wacom_device (META_INPUT_DEVICE (device)); - - /* Keep aspect only makes sense in external tablets */ - if (wacom_device && - libwacom_get_integration_flags (wacom_device) != WACOM_DEVICE_INTEGRATED_NONE) - return; - } -#endif - - keep_aspect = g_settings_get_boolean (settings, "keep-aspect"); - - if (keep_aspect) - aspect_ratio = info->aspect_ratio; - else - aspect_ratio = 0; - - input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); - input_settings_class->set_tablet_aspect_ratio (input_settings, device, aspect_ratio); -} - -static void -update_tablet_mapping (MetaInputSettings *input_settings, - GSettings *settings, - ClutterInputDevice *device) -{ - MetaInputSettingsClass *input_settings_class; - GDesktopTabletMapping mapping; - - if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE && - clutter_input_device_get_device_type (device) != CLUTTER_PEN_DEVICE && - clutter_input_device_get_device_type (device) != CLUTTER_ERASER_DEVICE) - return; - -#ifdef HAVE_LIBWACOM - { - WacomDevice *wacom_device; - - wacom_device = meta_input_device_get_wacom_device (META_INPUT_DEVICE (device)); - - /* Tablet mapping only makes sense on external tablets */ - if (wacom_device && - (libwacom_get_integration_flags (wacom_device) != WACOM_DEVICE_INTEGRATED_NONE)) - return; - } -#endif - - input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); - mapping = g_settings_get_enum (settings, "mapping"); - - settings_device_set_uint_setting (input_settings, device, - input_settings_class->set_tablet_mapping, - mapping); -} - -static void -update_tablet_area (MetaInputSettings *input_settings, - GSettings *settings, - ClutterInputDevice *device) -{ - MetaInputSettingsClass *input_settings_class; - GVariant *variant; - const gdouble *area; - gsize n_elems; - - if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE && - clutter_input_device_get_device_type (device) != CLUTTER_PEN_DEVICE && - clutter_input_device_get_device_type (device) != CLUTTER_ERASER_DEVICE) - return; - -#ifdef HAVE_LIBWACOM - { - WacomDevice *wacom_device; - - wacom_device = meta_input_device_get_wacom_device (META_INPUT_DEVICE (device)); - - /* Tablet area only makes sense on system/display integrated tablets */ - if (wacom_device && - (libwacom_get_integration_flags (wacom_device) & - (WACOM_DEVICE_INTEGRATED_SYSTEM | WACOM_DEVICE_INTEGRATED_DISPLAY)) == 0) - return; - } -#endif - - input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); - variant = g_settings_get_value (settings, "area"); - - area = g_variant_get_fixed_array (variant, &n_elems, sizeof (gdouble)); - if (n_elems == 4) - { - input_settings_class->set_tablet_area (input_settings, device, - area[0], area[1], - area[2], area[3]); - } - - g_variant_unref (variant); -} - -static void -update_tablet_left_handed (MetaInputSettings *input_settings, - GSettings *settings, - ClutterInputDevice *device) -{ - MetaInputSettingsClass *input_settings_class; - gboolean enabled; - - if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE && - clutter_input_device_get_device_type (device) != CLUTTER_PEN_DEVICE && - clutter_input_device_get_device_type (device) != CLUTTER_ERASER_DEVICE && - clutter_input_device_get_device_type (device) != CLUTTER_PAD_DEVICE) - return; - -#ifdef HAVE_LIBWACOM - { - WacomDevice *wacom_device; - - wacom_device = meta_input_device_get_wacom_device (META_INPUT_DEVICE (device)); - - /* Left handed mode only makes sense on external tablets */ - if (wacom_device && - (libwacom_get_integration_flags (wacom_device) != WACOM_DEVICE_INTEGRATED_NONE)) - return; - } -#endif - - input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); - enabled = g_settings_get_boolean (settings, "left-handed"); - - settings_device_set_bool_setting (input_settings, device, - input_settings_class->set_left_handed, - enabled); -} - -static void -meta_input_settings_changed_cb (GSettings *settings, - const char *key, - gpointer user_data) -{ - MetaInputSettings *input_settings = META_INPUT_SETTINGS (user_data); - MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (input_settings); - - if (settings == priv->mouse_settings) - { - if (strcmp (key, "left-handed") == 0) - update_mouse_left_handed (input_settings, NULL); - else if (strcmp (key, "speed") == 0) - update_device_speed (input_settings, NULL); - else if (strcmp (key, "natural-scroll") == 0) - update_device_natural_scroll (input_settings, NULL); - else if (strcmp (key, "accel-profile") == 0) - update_pointer_accel_profile (input_settings, settings, NULL); - else if (strcmp (key, "middle-click-emulation") == 0) - update_middle_click_emulation (input_settings, settings, NULL); - } - else if (settings == priv->touchpad_settings) - { - if (strcmp (key, "left-handed") == 0) - update_touchpad_left_handed (input_settings, NULL); - else if (strcmp (key, "speed") == 0) - update_device_speed (input_settings, NULL); - else if (strcmp (key, "natural-scroll") == 0) - update_device_natural_scroll (input_settings, NULL); - else if (strcmp (key, "tap-to-click") == 0) - update_touchpad_tap_enabled (input_settings, NULL); - else if (strcmp (key, "tap-button-map") == 0) - update_touchpad_tap_button_map (input_settings, NULL); - else if (strcmp (key, "tap-and-drag") == 0) - update_touchpad_tap_and_drag_enabled (input_settings, NULL); - else if (strcmp (key, "tap-and-drag-lock") == 0) - update_touchpad_tap_and_drag_lock_enabled (input_settings, NULL); - else if (strcmp(key, "disable-while-typing") == 0) - update_touchpad_disable_while_typing (input_settings, NULL); - else if (strcmp (key, "send-events") == 0) - update_touchpad_send_events (input_settings, NULL); - else if (strcmp (key, "edge-scrolling-enabled") == 0) - update_touchpad_edge_scroll (input_settings, NULL); - else if (strcmp (key, "two-finger-scrolling-enabled") == 0) - update_touchpad_two_finger_scroll (input_settings, NULL); - else if (strcmp (key, "click-method") == 0) - update_touchpad_click_method (input_settings, NULL); - else if (strcmp (key, "middle-click-emulation") == 0) - update_middle_click_emulation (input_settings, settings, NULL); - } - else if (settings == priv->trackball_settings) - { - if (strcmp (key, "scroll-wheel-emulation-button") == 0 || - strcmp (key, "scroll-wheel-emulation-button-lock") == 0) - update_trackball_scroll_button (input_settings, NULL); - else if (strcmp (key, "accel-profile") == 0) - update_pointer_accel_profile (input_settings, settings, NULL); - else if (strcmp (key, "middle-click-emulation") == 0) - update_middle_click_emulation (input_settings, settings, NULL); - } - else if (settings == priv->keyboard_settings) - { - if (strcmp (key, "repeat") == 0 || - strcmp (key, "repeat-interval") == 0 || - strcmp (key, "delay") == 0) - update_keyboard_repeat (input_settings); - } -} - -static void -mapped_device_changed_cb (GSettings *settings, - const gchar *key, - DeviceMappingInfo *info) -{ - if (strcmp (key, "mapping") == 0) - update_tablet_mapping (info->input_settings, settings, info->device); - else if (strcmp (key, "area") == 0) - update_tablet_area (info->input_settings, settings, info->device); - else if (strcmp (key, "keep-aspect") == 0) - update_tablet_keep_aspect (info->input_settings, settings, info->device); - else if (strcmp (key, "left-handed") == 0) - update_tablet_left_handed (info->input_settings, settings, info->device); -} - -static void -apply_mappable_device_settings (MetaInputSettings *input_settings, - DeviceMappingInfo *info) -{ - ClutterInputDeviceType device_type; - - device_type = clutter_input_device_get_device_type (info->device); - - if (device_type == CLUTTER_TABLET_DEVICE || - device_type == CLUTTER_PEN_DEVICE || - device_type == CLUTTER_ERASER_DEVICE || - device_type == CLUTTER_PAD_DEVICE) - { - update_tablet_mapping (input_settings, info->settings, info->device); - update_tablet_area (input_settings, info->settings, info->device); - update_tablet_keep_aspect (input_settings, info->settings, info->device); - update_tablet_left_handed (input_settings, info->settings, info->device); - } -} - -struct _keyboard_a11y_settings_flags_pair { - const char *name; - MetaKeyboardA11yFlags flag; -} keyboard_a11y_settings_flags_pair[] = { - { "enable", META_A11Y_KEYBOARD_ENABLED }, - { "timeout-enable", META_A11Y_TIMEOUT_ENABLED }, - { "mousekeys-enable", META_A11Y_MOUSE_KEYS_ENABLED }, - { "slowkeys-enable", META_A11Y_SLOW_KEYS_ENABLED }, - { "slowkeys-beep-press", META_A11Y_SLOW_KEYS_BEEP_PRESS }, - { "slowkeys-beep-accept", META_A11Y_SLOW_KEYS_BEEP_ACCEPT }, - { "slowkeys-beep-reject", META_A11Y_SLOW_KEYS_BEEP_REJECT }, - { "bouncekeys-enable", META_A11Y_BOUNCE_KEYS_ENABLED }, - { "bouncekeys-beep-reject", META_A11Y_BOUNCE_KEYS_BEEP_REJECT }, - { "togglekeys-enable", META_A11Y_TOGGLE_KEYS_ENABLED }, - { "stickykeys-enable", META_A11Y_STICKY_KEYS_ENABLED }, - { "stickykeys-modifier-beep", META_A11Y_STICKY_KEYS_BEEP }, - { "stickykeys-two-key-off", META_A11Y_STICKY_KEYS_TWO_KEY_OFF }, - { "feature-state-change-beep", META_A11Y_FEATURE_STATE_CHANGE_BEEP }, -}; - -static void -load_keyboard_a11y_settings (MetaInputSettings *input_settings) -{ - MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (input_settings); - MetaKbdA11ySettings kbd_a11y_settings = { 0 }; - guint i; - - kbd_a11y_settings.controls = 0; - for (i = 0; i < G_N_ELEMENTS (keyboard_a11y_settings_flags_pair); i++) - { - 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->keyboard_a11y_settings, - "disable-timeout"); - 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->keyboard_a11y_settings, - "bouncekeys-delay"); - 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->keyboard_a11y_settings, - "mousekeys-max-speed"); - kbd_a11y_settings.mousekeys_accel_time = g_settings_get_int (priv->keyboard_a11y_settings, - "mousekeys-accel-time"); - - priv->kbd_a11y_settings = kbd_a11y_settings; - g_signal_emit (input_settings, signals[KBD_A11Y_CHANGED], 0, &priv->kbd_a11y_settings); -} - -void -meta_input_settings_notify_kbd_a11y_change (MetaInputSettings *input_settings, - MetaKeyboardA11yFlags new_flags, - MetaKeyboardA11yFlags what_changed) -{ - MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (input_settings); - guint i; - - for (i = 0; i < G_N_ELEMENTS (keyboard_a11y_settings_flags_pair); i++) - { - 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_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); -} - -static GSettings * -lookup_device_settings (ClutterInputDevice *device) -{ - const gchar *group, *schema, *vendor, *product; - ClutterInputDeviceType type; - GSettings *settings; - gchar *path; - - type = clutter_input_device_get_device_type (device); - - if (type == CLUTTER_TOUCHSCREEN_DEVICE) - { - group = "touchscreens"; - schema = "org.gnome.desktop.peripherals.touchscreen"; - } - else if (type == CLUTTER_TABLET_DEVICE || - type == CLUTTER_PEN_DEVICE || - type == CLUTTER_ERASER_DEVICE || - type == CLUTTER_CURSOR_DEVICE || - type == CLUTTER_PAD_DEVICE) - { - group = "tablets"; - schema = "org.gnome.desktop.peripherals.tablet"; - } - else - return NULL; - - vendor = clutter_input_device_get_vendor_id (device); - product = clutter_input_device_get_product_id (device); - path = g_strdup_printf ("/org/gnome/desktop/peripherals/%s/%s:%s/", - group, vendor, product); - - settings = g_settings_new_with_path (schema, path); - g_free (path); - - return settings; -} - -static GSettings * -lookup_tool_settings (ClutterInputDeviceTool *tool, - ClutterInputDevice *device) -{ - GSettings *tool_settings; - guint64 serial; - gchar *path; - - tool_settings = g_object_get_qdata (G_OBJECT (tool), quark_tool_settings); - if (tool_settings) - return tool_settings; - - serial = clutter_input_device_tool_get_serial (tool); - - /* The Wacom driver uses serial 1 for serial-less devices but 1 is not a - * real serial, so let's custom-case this */ - if (serial == 0 || serial == 1) - { - path = g_strdup_printf ("/org/gnome/desktop/peripherals/stylus/default-%s:%s/", - clutter_input_device_get_vendor_id (device), - clutter_input_device_get_product_id (device)); - } - else - { - path = g_strdup_printf ("/org/gnome/desktop/peripherals/stylus/%" G_GINT64_MODIFIER "x/", - serial); - } - - tool_settings = - g_settings_new_with_path ("org.gnome.desktop.peripherals.tablet.stylus", - path); - g_object_set_qdata_full (G_OBJECT (tool), quark_tool_settings, tool_settings, - (GDestroyNotify) g_object_unref); - g_free (path); - - return tool_settings; -} - -static void -device_mapping_info_free (DeviceMappingInfo *info) -{ - g_clear_signal_handler (&info->changed_id, info->settings); - g_object_unref (info->settings); - g_free (info->group_modes); - g_free (info); -} - -static gboolean -check_add_mappable_device (MetaInputSettings *input_settings, - ClutterInputDevice *device) -{ - MetaInputSettingsPrivate *priv; - DeviceMappingInfo *info; - ClutterInputDeviceType device_type; - GSettings *settings; - - device_type = clutter_input_device_get_device_type (device); - - if ((device_type == CLUTTER_TABLET_DEVICE || - device_type == CLUTTER_PEN_DEVICE || - device_type == CLUTTER_ERASER_DEVICE || - device_type == CLUTTER_PAD_DEVICE) && - g_getenv ("MUTTER_DISABLE_WACOM_CONFIGURATION") != NULL) - return FALSE; - - settings = lookup_device_settings (device); - - if (!settings) - return FALSE; - - priv = meta_input_settings_get_instance_private (input_settings); - - info = g_new0 (DeviceMappingInfo, 1); - info->input_settings = input_settings; - info->device = device; - info->settings = settings; - - if (device_type == CLUTTER_PAD_DEVICE) - { - info->group_modes = - g_new0 (guint, clutter_input_device_get_n_mode_groups (device)); - } - - info->changed_id = g_signal_connect (settings, "changed", - G_CALLBACK (mapped_device_changed_cb), - info); - - g_hash_table_insert (priv->mappable_devices, device, info); - - apply_mappable_device_settings (input_settings, info); - - return TRUE; -} - -static void -apply_device_settings (MetaInputSettings *input_settings, - ClutterInputDevice *device) -{ - MetaInputSettingsPrivate *priv = - meta_input_settings_get_instance_private (input_settings); - - update_device_speed (input_settings, device); - update_device_natural_scroll (input_settings, device); - - update_mouse_left_handed (input_settings, device); - update_pointer_accel_profile (input_settings, - priv->mouse_settings, - device); - - update_touchpad_left_handed (input_settings, device); - update_touchpad_tap_enabled (input_settings, device); - update_touchpad_tap_button_map (input_settings, device); - update_touchpad_tap_and_drag_enabled (input_settings, device); - update_touchpad_tap_and_drag_lock_enabled (input_settings, device); - update_touchpad_disable_while_typing (input_settings, device); - update_touchpad_send_events (input_settings, device); - update_touchpad_two_finger_scroll (input_settings, device); - update_touchpad_edge_scroll (input_settings, device); - update_touchpad_click_method (input_settings, device); - - update_trackball_scroll_button (input_settings, device); - update_pointer_accel_profile (input_settings, - priv->trackball_settings, - device); - - update_middle_click_emulation (input_settings, priv->mouse_settings, device); - update_middle_click_emulation (input_settings, priv->touchpad_settings, device); - update_middle_click_emulation (input_settings, priv->trackball_settings, device); -} - -static void -update_stylus_pressure (MetaInputSettings *input_settings, - ClutterInputDevice *device, - ClutterInputDeviceTool *tool) -{ - MetaInputSettingsClass *input_settings_class; - GSettings *tool_settings; - const gint32 *curve; - GVariant *variant; - gsize n_elems; - - if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE && - clutter_input_device_get_device_type (device) != CLUTTER_PEN_DEVICE && - clutter_input_device_get_device_type (device) != CLUTTER_ERASER_DEVICE) - return; - - if (!tool) - return; - - tool_settings = lookup_tool_settings (tool, device); - - if (clutter_input_device_tool_get_tool_type (tool) == - CLUTTER_INPUT_DEVICE_TOOL_ERASER) - variant = g_settings_get_value (tool_settings, "eraser-pressure-curve"); - else - variant = g_settings_get_value (tool_settings, "pressure-curve"); - - curve = g_variant_get_fixed_array (variant, &n_elems, sizeof (gint32)); - if (n_elems != 4) - return; - - input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); - input_settings_class->set_stylus_pressure (input_settings, device, tool, curve); -} - -static void -update_stylus_buttonmap (MetaInputSettings *input_settings, - ClutterInputDevice *device, - ClutterInputDeviceTool *tool) -{ - MetaInputSettingsClass *input_settings_class; - GDesktopStylusButtonAction primary, secondary, tertiary; - GSettings *tool_settings; - - if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE && - clutter_input_device_get_device_type (device) != CLUTTER_PEN_DEVICE && - clutter_input_device_get_device_type (device) != CLUTTER_ERASER_DEVICE) - return; - - if (!tool) - return; - - tool_settings = lookup_tool_settings (tool, device); - - primary = g_settings_get_enum (tool_settings, "button-action"); - secondary = g_settings_get_enum (tool_settings, "secondary-button-action"); - tertiary = g_settings_get_enum (tool_settings, "tertiary-button-action"); - - input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); - input_settings_class->set_stylus_button_map (input_settings, device, tool, - primary, secondary, tertiary); -} - -static void -apply_stylus_settings (MetaInputSettings *input_settings, - ClutterInputDevice *device, - ClutterInputDeviceTool *tool) -{ - update_stylus_pressure (input_settings, device, tool); - update_stylus_buttonmap (input_settings, device, tool); -} - -static void -evaluate_two_finger_scrolling (MetaInputSettings *input_settings, - ClutterInputDevice *device) -{ - MetaInputSettingsClass *klass; - MetaInputSettingsPrivate *priv; - - if (clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE) - return; - - klass = META_INPUT_SETTINGS_GET_CLASS (input_settings); - priv = meta_input_settings_get_instance_private (input_settings); - - if (klass->has_two_finger_scroll (input_settings, device)) - g_hash_table_add (priv->two_finger_devices, device); -} - -void -meta_input_settings_add_device (MetaInputSettings *input_settings, - ClutterInputDevice *device) -{ - MetaInputSettingsPrivate *priv = - meta_input_settings_get_instance_private (input_settings); - - if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_LOGICAL) - return; - - priv->devices = g_list_prepend (priv->devices, device); - evaluate_two_finger_scrolling (input_settings, device); - - apply_device_settings (input_settings, device); - check_add_mappable_device (input_settings, device); -} - -void -meta_input_settings_remove_device (MetaInputSettings *input_settings, - ClutterInputDevice *device) -{ - MetaInputSettingsPrivate *priv; - - priv = meta_input_settings_get_instance_private (input_settings); - g_hash_table_remove (priv->mappable_devices, device); - g_hash_table_remove (priv->current_tools, device); - - if (g_hash_table_remove (priv->two_finger_devices, device) && - g_hash_table_size (priv->two_finger_devices) == 0) - apply_device_settings (input_settings, NULL); - - priv->devices = g_list_remove (priv->devices, device); -} - -static void -current_tool_changed_cb (GSettings *settings, - const char *key, - gpointer user_data) -{ - CurrentToolInfo *info = user_data; - - apply_stylus_settings (info->input_settings, info->device, info->tool); -} - -static CurrentToolInfo * -current_tool_info_new (MetaInputSettings *input_settings, - ClutterInputDevice *device, - ClutterInputDeviceTool *tool) -{ - CurrentToolInfo *info; - - info = g_new0 (CurrentToolInfo, 1); - info->input_settings = input_settings; - info->device = device; - info->tool = tool; - info->settings = lookup_tool_settings (tool, device); - info->changed_id = - g_signal_connect (info->settings, "changed", - G_CALLBACK (current_tool_changed_cb), - info); - return info; -} - -static void -current_tool_info_free (CurrentToolInfo *info) -{ - g_clear_signal_handler (&info->changed_id, info->settings); - g_free (info); -} - -void -meta_input_settings_notify_tool_change (MetaInputSettings *input_settings, - ClutterInputDevice *device, - ClutterInputDeviceTool *tool) -{ - MetaInputSettingsPrivate *priv; - - priv = meta_input_settings_get_instance_private (input_settings); - - if (tool) - { - CurrentToolInfo *current_tool; - - current_tool = current_tool_info_new (input_settings, device, tool); - g_hash_table_insert (priv->current_tools, device, current_tool); - apply_stylus_settings (input_settings, device, tool); - } - else - { - g_hash_table_remove (priv->current_tools, device); - } -} - -static void -check_mappable_devices (MetaInputSettings *input_settings) -{ - MetaInputSettingsPrivate *priv; - GList *l; - - priv = meta_input_settings_get_instance_private (input_settings); - - for (l = priv->devices; l; l = l->next) - { - ClutterInputDevice *device = l->data; - - if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_LOGICAL) - continue; - - check_add_mappable_device (input_settings, device); - } -} - -static void -meta_input_settings_constructed (GObject *object) -{ - MetaInputSettings *input_settings = META_INPUT_SETTINGS (object); - GSList *devices, *d; - - devices = meta_input_settings_get_devices (input_settings, CLUTTER_TOUCHPAD_DEVICE); - for (d = devices; d; d = d->next) - evaluate_two_finger_scrolling (input_settings, d->data); - - g_slist_free (devices); - - apply_device_settings (input_settings, NULL); - update_keyboard_repeat (input_settings); - check_mappable_devices (input_settings); - - load_keyboard_a11y_settings (input_settings); -} - -static void -meta_input_settings_class_init (MetaInputSettingsClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = meta_input_settings_dispose; - object_class->constructed = meta_input_settings_constructed; - - quark_tool_settings = - g_quark_from_static_string ("meta-input-settings-tool-settings"); - - signals[KBD_A11Y_CHANGED] = - g_signal_new ("kbd-a11y-changed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 1, - G_TYPE_POINTER); - -} - -static void -meta_input_settings_init (MetaInputSettings *settings) -{ - MetaInputSettingsPrivate *priv; - - priv = meta_input_settings_get_instance_private (settings); - - priv->mouse_settings = g_settings_new ("org.gnome.desktop.peripherals.mouse"); - g_signal_connect (priv->mouse_settings, "changed", - G_CALLBACK (meta_input_settings_changed_cb), settings); - - priv->touchpad_settings = g_settings_new ("org.gnome.desktop.peripherals.touchpad"); - g_signal_connect (priv->touchpad_settings, "changed", - G_CALLBACK (meta_input_settings_changed_cb), settings); - - priv->trackball_settings = g_settings_new ("org.gnome.desktop.peripherals.trackball"); - g_signal_connect (priv->trackball_settings, "changed", - G_CALLBACK (meta_input_settings_changed_cb), settings); - - priv->keyboard_settings = g_settings_new ("org.gnome.desktop.peripherals.keyboard"); - g_signal_connect (priv->keyboard_settings, "changed", - G_CALLBACK (meta_input_settings_changed_cb), 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); - - priv->mappable_devices = - g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) device_mapping_info_free); - - priv->current_tools = - g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) current_tool_info_free); - - priv->two_finger_devices = g_hash_table_new (NULL, NULL); -} - -void -meta_input_settings_maybe_save_numlock_state (MetaInputSettings *input_settings, - gboolean numlock_state) -{ - MetaInputSettingsPrivate *priv; - - priv = meta_input_settings_get_instance_private (input_settings); - - if (!g_settings_get_boolean (priv->keyboard_settings, "remember-numlock-state")) - return; - - if (numlock_state == g_settings_get_boolean (priv->keyboard_settings, "numlock-state")) - return; - - g_settings_set_boolean (priv->keyboard_settings, "numlock-state", numlock_state); -} - -gboolean -meta_input_settings_maybe_restore_numlock_state (MetaInputSettings *input_settings) -{ - MetaInputSettingsPrivate *priv; - gboolean numlock_state = FALSE; - - priv = meta_input_settings_get_instance_private (input_settings); - - if (g_settings_get_boolean (priv->keyboard_settings, "remember-numlock-state")) - numlock_state = g_settings_get_boolean (priv->keyboard_settings, "numlock-state"); - - return numlock_state; -} - -void -meta_input_settings_set_device_matrix (MetaInputSettings *input_settings, - ClutterInputDevice *device, - float matrix[6]) -{ - g_return_if_fail (META_IS_INPUT_SETTINGS (input_settings)); - g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); - - META_INPUT_SETTINGS_GET_CLASS (input_settings)->set_matrix (input_settings, - device, - matrix); -} - -void -meta_input_settings_set_device_enabled (MetaInputSettings *input_settings, - ClutterInputDevice *device, - gboolean enabled) -{ - GDesktopDeviceSendEvents mode; - - g_return_if_fail (META_IS_INPUT_SETTINGS (input_settings)); - g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); - - mode = enabled ? - G_DESKTOP_DEVICE_SEND_EVENTS_ENABLED : - G_DESKTOP_DEVICE_SEND_EVENTS_DISABLED; - - META_INPUT_SETTINGS_GET_CLASS (input_settings)->set_send_events (input_settings, - device, - mode); -} - -void -meta_input_settings_set_device_aspect_ratio (MetaInputSettings *input_settings, - ClutterInputDevice *device, - double aspect_ratio) -{ - MetaInputSettingsPrivate *priv; - DeviceMappingInfo *info; - - g_return_if_fail (META_IS_INPUT_SETTINGS (input_settings)); - g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); - - priv = meta_input_settings_get_instance_private (input_settings); - - info = g_hash_table_lookup (priv->mappable_devices, device); - if (!info) - return; - - info->aspect_ratio = aspect_ratio; - update_tablet_keep_aspect (input_settings, info->settings, device); -} - -void -meta_input_settings_get_kbd_a11y_settings (MetaInputSettings *input_settings, - MetaKbdA11ySettings *a11y_settings) -{ - MetaInputSettingsPrivate *priv; - - g_return_if_fail (META_IS_INPUT_SETTINGS (input_settings)); - - priv = meta_input_settings_get_instance_private (input_settings); - - *a11y_settings = priv->kbd_a11y_settings; -} diff --git a/src/backends/meta-keymap-utils.c b/src/backends/meta-keymap-utils.c deleted file mode 100644 index 123eb2303..000000000 --- a/src/backends/meta-keymap-utils.c +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * Utilities for use with libxkbcommon - * - * Copyright 2019 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 . - */ - -#include "config.h" - -#include "backends/meta-keymap-utils.h" - -#include -#include - -struct xkb_context * -meta_create_xkb_context (void) -{ - struct xkb_context *ctx; - char xdg[PATH_MAX] = {0}; - const char *env; - - /* - * We can only append search paths in libxkbcommon, so we start with an - * empty set, then add the XDG dir, then add the default search paths. - */ - ctx = xkb_context_new (XKB_CONTEXT_NO_DEFAULT_INCLUDES); - - env = g_getenv ("XDG_CONFIG_HOME"); - if (env) - { - g_snprintf (xdg, sizeof xdg, "%s/xkb", env); - } - else if ((env = g_getenv ("HOME"))) - { - g_snprintf (xdg, sizeof xdg, "%s/.config/xkb", env); - } - - if (env) - xkb_context_include_path_append (ctx, xdg); - xkb_context_include_path_append_default (ctx); - - return ctx; -} diff --git a/src/backends/meta-keymap-utils.h b/src/backends/meta-keymap-utils.h deleted file mode 100644 index 3806824e4..000000000 --- a/src/backends/meta-keymap-utils.h +++ /dev/null @@ -1,28 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * Utilities for use with libxkbcommon - * - * Copyright 2020 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 . - */ - -#ifndef META_KEYMAP_UTILS_H -#define META_KEYMAP_UTILS_H - -#include - -struct xkb_context * meta_create_xkb_context (void); - -#endif /* META_KEYMAP_UTILS_H */ diff --git a/src/backends/meta-logical-monitor.c b/src/backends/meta-logical-monitor.c deleted file mode 100644 index b562e5acb..000000000 --- a/src/backends/meta-logical-monitor.c +++ /dev/null @@ -1,343 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 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. - */ - -/** - * SECTION:meta-logical-monitor - * @title: MetaLogicalMonitor - * @short_description: An abstraction for a monitor(set) and its configuration. - * - * A logical monitor is a group of one or more physical monitors that - * must behave and be treated as single one. This happens, for example, - * when 2 monitors are mirrored. Each physical monitor is represented - * by a #MetaMonitor. - * - * #MetaLogicalMonitor has a single viewport, with its owns transformations - * (such as scaling), that are applied to all the #MetaMonitors that - * are grouped by it. - * - * #MetaLogicalMonitor provides an abstraction that makes it easy to handle - * the specifics of setting up different #MetaMonitors. It then can - * be used more easily by #MetaRendererView. - */ - -#include "config.h" - -#include "backends/meta-logical-monitor.h" - -#include "backends/meta-backend-private.h" -#include "backends/meta-crtc.h" -#include "backends/meta-output.h" - -G_DEFINE_TYPE (MetaLogicalMonitor, meta_logical_monitor, G_TYPE_OBJECT) - -static MetaMonitor * -get_first_monitor (MetaMonitorManager *monitor_manager, - GList *monitor_configs) -{ - MetaMonitorConfig *first_monitor_config; - MetaMonitorSpec *first_monitor_spec; - - first_monitor_config = g_list_first (monitor_configs)->data; - first_monitor_spec = first_monitor_config->monitor_spec; - - return meta_monitor_manager_get_monitor_from_spec (monitor_manager, - first_monitor_spec); -} - -typedef struct -{ - MetaMonitorManager *monitor_manager; - MetaLogicalMonitor *logical_monitor; -} AddMonitorFromConfigData; - -static void -add_monitor_from_config (MetaMonitorConfig *monitor_config, - AddMonitorFromConfigData *data) -{ - MetaMonitorSpec *monitor_spec; - MetaMonitor *monitor; - - monitor_spec = monitor_config->monitor_spec; - monitor = meta_monitor_manager_get_monitor_from_spec (data->monitor_manager, - monitor_spec); - - meta_logical_monitor_add_monitor (data->logical_monitor, monitor); -} - -MetaLogicalMonitor * -meta_logical_monitor_new (MetaMonitorManager *monitor_manager, - MetaLogicalMonitorConfig *logical_monitor_config, - int monitor_number) -{ - MetaLogicalMonitor *logical_monitor; - GList *monitor_configs; - MetaMonitor *first_monitor; - MetaOutput *main_output; - - logical_monitor = g_object_new (META_TYPE_LOGICAL_MONITOR, NULL); - - monitor_configs = logical_monitor_config->monitor_configs; - first_monitor = get_first_monitor (monitor_manager, monitor_configs); - main_output = meta_monitor_get_main_output (first_monitor); - - logical_monitor->number = monitor_number; - logical_monitor->winsys_id = meta_output_get_id (main_output); - logical_monitor->scale = logical_monitor_config->scale; - logical_monitor->transform = logical_monitor_config->transform; - logical_monitor->in_fullscreen = -1; - logical_monitor->rect = logical_monitor_config->layout; - - logical_monitor->is_presentation = TRUE; - g_list_foreach (monitor_configs, (GFunc) add_monitor_from_config, - &(AddMonitorFromConfigData) { - .monitor_manager = monitor_manager, - .logical_monitor = logical_monitor - }); - - return logical_monitor; -} - -static MetaMonitorTransform -derive_monitor_transform (MetaMonitor *monitor) -{ - MetaOutput *main_output; - MetaCrtc *crtc; - const MetaCrtcConfig *crtc_config; - MetaMonitorTransform transform; - - main_output = meta_monitor_get_main_output (monitor); - crtc = meta_output_get_assigned_crtc (main_output); - crtc_config = meta_crtc_get_config (crtc); - transform = crtc_config->transform; - - return meta_monitor_crtc_to_logical_transform (monitor, transform); -} - -MetaLogicalMonitor * -meta_logical_monitor_new_derived (MetaMonitorManager *monitor_manager, - MetaMonitor *monitor, - MetaRectangle *layout, - float scale, - int monitor_number) -{ - MetaLogicalMonitor *logical_monitor; - MetaOutput *main_output; - MetaMonitorTransform transform; - - logical_monitor = g_object_new (META_TYPE_LOGICAL_MONITOR, NULL); - - transform = derive_monitor_transform (monitor); - - main_output = meta_monitor_get_main_output (monitor); - logical_monitor->number = monitor_number; - logical_monitor->winsys_id = meta_output_get_id (main_output); - logical_monitor->scale = scale; - logical_monitor->transform = transform; - logical_monitor->in_fullscreen = -1; - logical_monitor->rect = *layout; - - logical_monitor->is_presentation = TRUE; - meta_logical_monitor_add_monitor (logical_monitor, monitor); - - return logical_monitor; -} - -void -meta_logical_monitor_add_monitor (MetaLogicalMonitor *logical_monitor, - MetaMonitor *monitor) -{ - GList *l; - gboolean is_presentation; - - is_presentation = logical_monitor->is_presentation; - logical_monitor->monitors = g_list_append (logical_monitor->monitors, - g_object_ref (monitor)); - - for (l = logical_monitor->monitors; l; l = l->next) - { - MetaMonitor *monitor = l->data; - GList *outputs; - GList *l_output; - - outputs = meta_monitor_get_outputs (monitor); - for (l_output = outputs; l_output; l_output = l_output->next) - { - MetaOutput *output = l_output->data; - - is_presentation = (is_presentation && - meta_output_is_presentation (output)); - } - } - - logical_monitor->is_presentation = is_presentation; - - meta_monitor_set_logical_monitor (monitor, logical_monitor); -} - -gboolean -meta_logical_monitor_is_primary (MetaLogicalMonitor *logical_monitor) -{ - return logical_monitor->is_primary; -} - -void -meta_logical_monitor_make_primary (MetaLogicalMonitor *logical_monitor) -{ - logical_monitor->is_primary = TRUE; -} - -float -meta_logical_monitor_get_scale (MetaLogicalMonitor *logical_monitor) -{ - return logical_monitor->scale; -} - -MetaMonitorTransform -meta_logical_monitor_get_transform (MetaLogicalMonitor *logical_monitor) -{ - return logical_monitor->transform; -} - -MetaRectangle -meta_logical_monitor_get_layout (MetaLogicalMonitor *logical_monitor) -{ - return logical_monitor->rect; -} - -GList * -meta_logical_monitor_get_monitors (MetaLogicalMonitor *logical_monitor) -{ - return logical_monitor->monitors; -} - -typedef struct _ForeachCrtcData -{ - MetaLogicalMonitor *logical_monitor; - MetaLogicalMonitorCrtcFunc func; - gpointer user_data; -} ForeachCrtcData; - -static gboolean -foreach_crtc (MetaMonitor *monitor, - MetaMonitorMode *mode, - MetaMonitorCrtcMode *monitor_crtc_mode, - gpointer user_data, - GError **error) -{ - ForeachCrtcData *data = user_data; - - data->func (data->logical_monitor, - monitor, - monitor_crtc_mode->output, - meta_output_get_assigned_crtc (monitor_crtc_mode->output), - data->user_data); - - return TRUE; -} - -void -meta_logical_monitor_foreach_crtc (MetaLogicalMonitor *logical_monitor, - MetaLogicalMonitorCrtcFunc func, - gpointer user_data) -{ - GList *l; - - for (l = logical_monitor->monitors; l; l = l->next) - { - MetaMonitor *monitor = l->data; - MetaMonitorMode *mode; - ForeachCrtcData data = { - .logical_monitor = logical_monitor, - .func = func, - .user_data = user_data - }; - - mode = meta_monitor_get_current_mode (monitor); - meta_monitor_mode_foreach_crtc (monitor, mode, foreach_crtc, &data, NULL); - } -} - -static void -meta_logical_monitor_init (MetaLogicalMonitor *logical_monitor) -{ -} - -static void -meta_logical_monitor_dispose (GObject *object) -{ - MetaLogicalMonitor *logical_monitor = META_LOGICAL_MONITOR (object); - - if (logical_monitor->monitors) - { - g_list_free_full (logical_monitor->monitors, g_object_unref); - logical_monitor->monitors = NULL; - } - - G_OBJECT_CLASS (meta_logical_monitor_parent_class)->dispose (object); -} - -static void -meta_logical_monitor_class_init (MetaLogicalMonitorClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = meta_logical_monitor_dispose; -} - -gboolean -meta_logical_monitor_has_neighbor (MetaLogicalMonitor *logical_monitor, - MetaLogicalMonitor *neighbor, - MetaDisplayDirection neighbor_direction) -{ - switch (neighbor_direction) - { - case META_DISPLAY_RIGHT: - if (neighbor->rect.x == (logical_monitor->rect.x + - logical_monitor->rect.width) && - meta_rectangle_vert_overlap (&neighbor->rect, - &logical_monitor->rect)) - return TRUE; - break; - case META_DISPLAY_LEFT: - if (logical_monitor->rect.x == (neighbor->rect.x + - neighbor->rect.width) && - meta_rectangle_vert_overlap (&neighbor->rect, - &logical_monitor->rect)) - return TRUE; - break; - case META_DISPLAY_UP: - if (logical_monitor->rect.y == (neighbor->rect.y + - neighbor->rect.height) && - meta_rectangle_horiz_overlap (&neighbor->rect, - &logical_monitor->rect)) - return TRUE; - break; - case META_DISPLAY_DOWN: - if (neighbor->rect.y == (logical_monitor->rect.y + - logical_monitor->rect.height) && - meta_rectangle_horiz_overlap (&neighbor->rect, - &logical_monitor->rect)) - return TRUE; - break; - } - - return FALSE; -} diff --git a/src/backends/meta-logical-monitor.h b/src/backends/meta-logical-monitor.h deleted file mode 100644 index d5ef1da83..000000000 --- a/src/backends/meta-logical-monitor.h +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 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_LOGICAL_MONITOR_H -#define META_LOGICAL_MONITOR_H - -#include - -#include "backends/meta-monitor.h" -#include "backends/meta-monitor-config-manager.h" -#include "backends/meta-monitor-manager-private.h" -#include "core/util-private.h" -#include "meta/boxes.h" - -#define META_MAX_OUTPUTS_PER_MONITOR 4 - -struct _MetaLogicalMonitor -{ - GObject parent; - - int number; - MetaRectangle rect; - gboolean is_primary; - gboolean is_presentation; /* XXX: not yet used */ - gboolean in_fullscreen; - float scale; - MetaMonitorTransform transform; - - /* The primary or first output for this monitor, 0 if we can't figure out. - It can be matched to a winsys_id of a MetaOutput. - - This is used as an opaque token on reconfiguration when switching from - clone to extended, to decide on what output the windows should go next - (it's an attempt to keep windows on the same monitor, and preferably on - the primary one). - */ - uint64_t winsys_id; - - GList *monitors; -}; - -#define META_TYPE_LOGICAL_MONITOR (meta_logical_monitor_get_type ()) -G_DECLARE_FINAL_TYPE (MetaLogicalMonitor, meta_logical_monitor, - META, LOGICAL_MONITOR, - GObject) - -typedef void (* MetaLogicalMonitorCrtcFunc) (MetaLogicalMonitor *logical_monitor, - MetaMonitor *monitor, - MetaOutput *output, - MetaCrtc *crtc, - gpointer user_data); - -MetaLogicalMonitor * meta_logical_monitor_new (MetaMonitorManager *monitor_manager, - MetaLogicalMonitorConfig *logical_monitor_config, - int monitor_number); - -MetaLogicalMonitor * meta_logical_monitor_new_derived (MetaMonitorManager *monitor_manager, - MetaMonitor *monitor, - MetaRectangle *layout, - float scale, - int monitor_number); - -void meta_logical_monitor_add_monitor (MetaLogicalMonitor *logical_monitor, - MetaMonitor *monitor); - -META_EXPORT_TEST -gboolean meta_logical_monitor_is_primary (MetaLogicalMonitor *logical_monitor); - -void meta_logical_monitor_make_primary (MetaLogicalMonitor *logical_monitor); - -float meta_logical_monitor_get_scale (MetaLogicalMonitor *logical_monitor); - -MetaMonitorTransform meta_logical_monitor_get_transform (MetaLogicalMonitor *logical_monitor); - -META_EXPORT_TEST -MetaRectangle meta_logical_monitor_get_layout (MetaLogicalMonitor *logical_monitor); - -META_EXPORT_TEST -GList * meta_logical_monitor_get_monitors (MetaLogicalMonitor *logical_monitor); - -gboolean meta_logical_monitor_has_neighbor (MetaLogicalMonitor *logical_monitor, - MetaLogicalMonitor *neighbor, - MetaDisplayDirection neighbor_dir); - -void meta_logical_monitor_foreach_crtc (MetaLogicalMonitor *logical_monitor, - MetaLogicalMonitorCrtcFunc func, - gpointer user_data); - -#endif /* META_LOGICAL_MONITOR_H */ diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c deleted file mode 100644 index 0253e072f..000000000 --- a/src/backends/meta-monitor-config-manager.c +++ /dev/null @@ -1,1899 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 Red Hat - * Copyright (c) 2018 DisplayLink (UK) Ltd. - * - * 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 "backends/meta-monitor-config-manager.h" - -#include "backends/meta-backend-private.h" -#include "backends/meta-monitor-config-migration.h" -#include "backends/meta-monitor-config-store.h" -#include "backends/meta-monitor-manager-private.h" -#include "backends/meta-output.h" -#include "core/boxes-private.h" - -#define CONFIG_HISTORY_MAX_SIZE 3 - -struct _MetaMonitorConfigManager -{ - GObject parent; - - MetaMonitorManager *monitor_manager; - - MetaMonitorConfigStore *config_store; - - MetaMonitorsConfig *current_config; - GQueue config_history; -}; - -G_DEFINE_TYPE (MetaMonitorConfigManager, meta_monitor_config_manager, - G_TYPE_OBJECT) - -G_DEFINE_TYPE (MetaMonitorsConfig, meta_monitors_config, - G_TYPE_OBJECT) - -static void -meta_crtc_assignment_free (MetaCrtcAssignment *assignment); - -static void -meta_output_assignment_free (MetaOutputAssignment *assignment); - -MetaMonitorConfigManager * -meta_monitor_config_manager_new (MetaMonitorManager *monitor_manager) -{ - MetaMonitorConfigManager *config_manager; - - config_manager = g_object_new (META_TYPE_MONITOR_CONFIG_MANAGER, NULL); - config_manager->monitor_manager = monitor_manager; - config_manager->config_store = - meta_monitor_config_store_new (monitor_manager); - - return config_manager; -} - -MetaMonitorConfigStore * -meta_monitor_config_manager_get_store (MetaMonitorConfigManager *config_manager) -{ - return config_manager->config_store; -} - -static gboolean -is_crtc_reserved (MetaCrtc *crtc, - GArray *reserved_crtcs) -{ - unsigned int i; - - for (i = 0; i < reserved_crtcs->len; i++) - { - uint64_t id; - - id = g_array_index (reserved_crtcs, uint64_t, i); - if (id == meta_crtc_get_id (crtc)) - return TRUE; - } - - return FALSE; -} - -static gboolean -is_crtc_assigned (MetaCrtc *crtc, - GPtrArray *crtc_assignments) -{ - unsigned int i; - - for (i = 0; i < crtc_assignments->len; i++) - { - MetaCrtcAssignment *assigned_crtc_assignment = - g_ptr_array_index (crtc_assignments, i); - - if (assigned_crtc_assignment->crtc == crtc) - return TRUE; - } - - return FALSE; -} - -static MetaCrtc * -find_unassigned_crtc (MetaOutput *output, - GPtrArray *crtc_assignments, - GArray *reserved_crtcs) -{ - MetaCrtc *crtc; - const MetaOutputInfo *output_info; - unsigned int i; - - crtc = meta_output_get_assigned_crtc (output); - if (crtc && !is_crtc_assigned (crtc, crtc_assignments)) - return crtc; - - output_info = meta_output_get_info (output); - - /* then try to assign a CRTC that wasn't used */ - for (i = 0; i < output_info->n_possible_crtcs; i++) - { - crtc = output_info->possible_crtcs[i]; - - if (is_crtc_assigned (crtc, crtc_assignments)) - continue; - - if (is_crtc_reserved (crtc, reserved_crtcs)) - continue; - - return crtc; - } - - /* finally just give a CRTC that we haven't assigned */ - for (i = 0; i < output_info->n_possible_crtcs; i++) - { - crtc = output_info->possible_crtcs[i]; - - if (is_crtc_assigned (crtc, crtc_assignments)) - continue; - - return crtc; - } - - return NULL; -} - -typedef struct -{ - MetaMonitorManager *monitor_manager; - MetaMonitorsConfig *config; - MetaLogicalMonitorConfig *logical_monitor_config; - MetaMonitorConfig *monitor_config; - GPtrArray *crtc_assignments; - GPtrArray *output_assignments; - GArray *reserved_crtcs; -} MonitorAssignmentData; - -static gboolean -assign_monitor_crtc (MetaMonitor *monitor, - MetaMonitorMode *mode, - MetaMonitorCrtcMode *monitor_crtc_mode, - gpointer user_data, - GError **error) -{ - MonitorAssignmentData *data = user_data; - MetaOutput *output; - MetaCrtc *crtc; - MetaMonitorTransform transform; - MetaMonitorTransform crtc_transform; - MetaMonitorTransform crtc_hw_transform; - int crtc_x, crtc_y; - float x_offset, y_offset; - float scale = 0.0; - float width, height; - MetaCrtcMode *crtc_mode; - const MetaCrtcModeInfo *crtc_mode_info; - graphene_rect_t crtc_layout; - MetaCrtcAssignment *crtc_assignment; - MetaOutputAssignment *output_assignment; - MetaMonitorConfig *first_monitor_config; - gboolean assign_output_as_primary; - gboolean assign_output_as_presentation; - - output = monitor_crtc_mode->output; - - crtc = find_unassigned_crtc (output, - data->crtc_assignments, - data->reserved_crtcs); - - if (!crtc) - { - MetaMonitorSpec *monitor_spec = meta_monitor_get_spec (monitor); - - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "No available CRTC for monitor '%s %s' not found", - monitor_spec->vendor, monitor_spec->product); - return FALSE; - } - - transform = data->logical_monitor_config->transform; - crtc_transform = meta_monitor_logical_to_crtc_transform (monitor, transform); - if (meta_monitor_manager_is_transform_handled (data->monitor_manager, - crtc, - crtc_transform)) - crtc_hw_transform = crtc_transform; - else - crtc_hw_transform = META_MONITOR_TRANSFORM_NORMAL; - - meta_monitor_calculate_crtc_pos (monitor, mode, output, crtc_transform, - &crtc_x, &crtc_y); - - x_offset = data->logical_monitor_config->layout.x; - y_offset = data->logical_monitor_config->layout.y; - - switch (data->config->layout_mode) - { - case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL: - scale = data->logical_monitor_config->scale; - break; - case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL: - scale = 1.0; - break; - } - - crtc_mode = monitor_crtc_mode->crtc_mode; - crtc_mode_info = meta_crtc_mode_get_info (monitor_crtc_mode->crtc_mode); - - if (meta_monitor_transform_is_rotated (crtc_transform)) - { - width = crtc_mode_info->height / scale; - height = crtc_mode_info->width / scale; - } - else - { - width = crtc_mode_info->width / scale; - height = crtc_mode_info->height / scale; - } - - crtc_layout = GRAPHENE_RECT_INIT (x_offset + (crtc_x / scale), - y_offset + (crtc_y / scale), - width, - height); - - crtc_assignment = g_new0 (MetaCrtcAssignment, 1); - *crtc_assignment = (MetaCrtcAssignment) { - .crtc = crtc, - .mode = crtc_mode, - .layout = crtc_layout, - .transform = crtc_hw_transform, - .outputs = g_ptr_array_new () - }; - g_ptr_array_add (crtc_assignment->outputs, output); - - /* - * Only one output can be marked as primary (due to Xrandr limitation), - * so only mark the main output of the first monitor in the logical monitor - * as such. - */ - first_monitor_config = data->logical_monitor_config->monitor_configs->data; - if (data->logical_monitor_config->is_primary && - data->monitor_config == first_monitor_config && - meta_monitor_get_main_output (monitor) == output) - assign_output_as_primary = TRUE; - else - assign_output_as_primary = FALSE; - - if (data->logical_monitor_config->is_presentation) - assign_output_as_presentation = TRUE; - else - assign_output_as_presentation = FALSE; - - output_assignment = g_new0 (MetaOutputAssignment, 1); - *output_assignment = (MetaOutputAssignment) { - .output = output, - .is_primary = assign_output_as_primary, - .is_presentation = assign_output_as_presentation, - .is_underscanning = data->monitor_config->enable_underscanning - }; - - g_ptr_array_add (data->crtc_assignments, crtc_assignment); - g_ptr_array_add (data->output_assignments, output_assignment); - - return TRUE; -} - -static gboolean -assign_monitor_crtcs (MetaMonitorManager *manager, - MetaMonitorsConfig *config, - MetaLogicalMonitorConfig *logical_monitor_config, - MetaMonitorConfig *monitor_config, - GPtrArray *crtc_assignments, - GPtrArray *output_assignments, - GArray *reserved_crtcs, - GError **error) -{ - MetaMonitorSpec *monitor_spec = monitor_config->monitor_spec; - MetaMonitorModeSpec *monitor_mode_spec = monitor_config->mode_spec; - MetaMonitor *monitor; - MetaMonitorMode *monitor_mode; - MonitorAssignmentData data; - - monitor = meta_monitor_manager_get_monitor_from_spec (manager, monitor_spec); - if (!monitor) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Configured monitor '%s %s' not found", - monitor_spec->vendor, monitor_spec->product); - return FALSE; - } - - monitor_mode = meta_monitor_get_mode_from_spec (monitor, monitor_mode_spec); - if (!monitor_mode) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Invalid mode %dx%d (%f) for monitor '%s %s'", - monitor_mode_spec->width, monitor_mode_spec->height, - monitor_mode_spec->refresh_rate, - monitor_spec->vendor, monitor_spec->product); - return FALSE; - } - - data = (MonitorAssignmentData) { - .monitor_manager = manager, - .config = config, - .logical_monitor_config = logical_monitor_config, - .monitor_config = monitor_config, - .crtc_assignments = crtc_assignments, - .output_assignments = output_assignments, - .reserved_crtcs = reserved_crtcs - }; - if (!meta_monitor_mode_foreach_crtc (monitor, monitor_mode, - assign_monitor_crtc, - &data, - error)) - return FALSE; - - return TRUE; -} - -static gboolean -assign_logical_monitor_crtcs (MetaMonitorManager *manager, - MetaMonitorsConfig *config, - MetaLogicalMonitorConfig *logical_monitor_config, - GPtrArray *crtc_assignments, - GPtrArray *output_assignments, - GArray *reserved_crtcs, - GError **error) -{ - GList *l; - - for (l = logical_monitor_config->monitor_configs; l; l = l->next) - { - MetaMonitorConfig *monitor_config = l->data; - - if (!assign_monitor_crtcs (manager, - config, - logical_monitor_config, - monitor_config, - crtc_assignments, output_assignments, - reserved_crtcs, error)) - return FALSE; - } - - return TRUE; -} - -gboolean -meta_monitor_config_manager_assign (MetaMonitorManager *manager, - MetaMonitorsConfig *config, - GPtrArray **out_crtc_assignments, - GPtrArray **out_output_assignments, - GError **error) -{ - GPtrArray *crtc_assignments; - GPtrArray *output_assignments; - GArray *reserved_crtcs; - GList *l; - - crtc_assignments = - g_ptr_array_new_with_free_func ((GDestroyNotify) meta_crtc_assignment_free); - output_assignments = - g_ptr_array_new_with_free_func ((GDestroyNotify) meta_output_assignment_free); - reserved_crtcs = g_array_new (FALSE, FALSE, sizeof (uint64_t)); - - for (l = config->logical_monitor_configs; l; l = l->next) - { - MetaLogicalMonitorConfig *logical_monitor_config = l->data; - GList *k; - - for (k = logical_monitor_config->monitor_configs; k; k = k->next) - { - MetaMonitorConfig *monitor_config = k->data; - MetaMonitorSpec *monitor_spec = monitor_config->monitor_spec; - MetaMonitor *monitor; - GList *o; - - monitor = meta_monitor_manager_get_monitor_from_spec (manager, monitor_spec); - - for (o = meta_monitor_get_outputs (monitor); o; o = o->next) - { - MetaOutput *output = o->data; - MetaCrtc *crtc; - - crtc = meta_output_get_assigned_crtc (output); - if (crtc) - { - uint64_t crtc_id = meta_crtc_get_id (crtc); - - g_array_append_val (reserved_crtcs, crtc_id); - } - } - } - } - - for (l = config->logical_monitor_configs; l; l = l->next) - { - MetaLogicalMonitorConfig *logical_monitor_config = l->data; - - if (!assign_logical_monitor_crtcs (manager, - config, logical_monitor_config, - crtc_assignments, output_assignments, - reserved_crtcs, error)) - { - g_ptr_array_free (crtc_assignments, TRUE); - g_ptr_array_free (output_assignments, TRUE); - g_array_free (reserved_crtcs, TRUE); - return FALSE; - } - } - - g_array_free (reserved_crtcs, TRUE); - - *out_crtc_assignments = crtc_assignments; - *out_output_assignments = output_assignments; - - return TRUE; -} - -static gboolean -is_lid_closed (MetaMonitorManager *monitor_manager) -{ - MetaBackend *backend; - - backend = meta_monitor_manager_get_backend (monitor_manager); - return meta_backend_is_lid_closed (backend); -} - -MetaMonitorsConfigKey * -meta_create_monitors_config_key_for_current_state (MetaMonitorManager *monitor_manager) -{ - MetaMonitorsConfigKey *config_key; - MetaMonitorSpec *laptop_monitor_spec; - GList *l; - GList *monitor_specs; - - laptop_monitor_spec = NULL; - monitor_specs = NULL; - for (l = monitor_manager->monitors; l; l = l->next) - { - MetaMonitor *monitor = l->data; - MetaMonitorSpec *monitor_spec; - - if (meta_monitor_is_laptop_panel (monitor)) - { - laptop_monitor_spec = meta_monitor_get_spec (monitor); - - if (is_lid_closed (monitor_manager)) - continue; - } - - monitor_spec = meta_monitor_spec_clone (meta_monitor_get_spec (monitor)); - monitor_specs = g_list_prepend (monitor_specs, monitor_spec); - } - - if (!monitor_specs && laptop_monitor_spec) - { - monitor_specs = - g_list_prepend (NULL, meta_monitor_spec_clone (laptop_monitor_spec)); - } - - if (!monitor_specs) - return NULL; - - monitor_specs = g_list_sort (monitor_specs, - (GCompareFunc) meta_monitor_spec_compare); - - config_key = g_new0 (MetaMonitorsConfigKey, 1); - *config_key = (MetaMonitorsConfigKey) { - .monitor_specs = monitor_specs - }; - - return config_key; -} - -MetaMonitorsConfig * -meta_monitor_config_manager_get_stored (MetaMonitorConfigManager *config_manager) -{ - MetaMonitorManager *monitor_manager = config_manager->monitor_manager; - MetaMonitorsConfigKey *config_key; - MetaMonitorsConfig *config; - GError *error = NULL; - - config_key = - meta_create_monitors_config_key_for_current_state (monitor_manager); - if (!config_key) - return NULL; - - config = meta_monitor_config_store_lookup (config_manager->config_store, - config_key); - meta_monitors_config_key_free (config_key); - - if (!config) - return NULL; - - if (config->flags & META_MONITORS_CONFIG_FLAG_MIGRATED) - { - if (!meta_finish_monitors_config_migration (monitor_manager, config, - &error)) - { - g_warning ("Failed to finish monitors config migration: %s", - error->message); - g_error_free (error); - meta_monitor_config_store_remove (config_manager->config_store, config); - return NULL; - } - } - - return config; -} - -typedef enum _MonitorMatchRule -{ - MONITOR_MATCH_ALL = 0, - MONITOR_MATCH_EXTERNAL = (1 << 0) -} MonitorMatchRule; - -static MetaMonitor * -find_monitor_with_highest_preferred_resolution (MetaMonitorManager *monitor_manager, - MonitorMatchRule match_rule) -{ - GList *monitors; - GList *l; - int largest_area = 0; - MetaMonitor *largest_monitor = NULL; - - monitors = meta_monitor_manager_get_monitors (monitor_manager); - for (l = monitors; l; l = l->next) - { - MetaMonitor *monitor = l->data; - MetaMonitorMode *mode; - int width, height; - int area; - - if (match_rule & MONITOR_MATCH_EXTERNAL) - { - if (meta_monitor_is_laptop_panel (monitor)) - continue; - } - - mode = meta_monitor_get_preferred_mode (monitor); - meta_monitor_mode_get_resolution (mode, &width, &height); - area = width * height; - - if (area > largest_area) - { - largest_area = area; - largest_monitor = monitor; - } - } - - return largest_monitor; -} - -/* - * Try to find the primary monitor. The priority of classification is: - * - * 1. Find the primary monitor as reported by the underlying system, - * 2. Find the laptop panel - * 3. Find the external monitor with highest resolution - * - * If the laptop lid is closed, exclude the laptop panel from possible - * alternatives, except if no other alternatives exist. - */ -static MetaMonitor * -find_primary_monitor (MetaMonitorManager *monitor_manager) -{ - MetaMonitor *monitor; - - if (is_lid_closed (monitor_manager)) - { - monitor = meta_monitor_manager_get_primary_monitor (monitor_manager); - if (monitor && !meta_monitor_is_laptop_panel (monitor)) - return monitor; - - monitor = - find_monitor_with_highest_preferred_resolution (monitor_manager, - MONITOR_MATCH_EXTERNAL); - if (monitor) - return monitor; - - return find_monitor_with_highest_preferred_resolution (monitor_manager, - MONITOR_MATCH_ALL); - } - else - { - monitor = meta_monitor_manager_get_primary_monitor (monitor_manager); - if (monitor) - return monitor; - - monitor = meta_monitor_manager_get_laptop_panel (monitor_manager); - if (monitor) - return monitor; - - return find_monitor_with_highest_preferred_resolution (monitor_manager, - MONITOR_MATCH_ALL); - } -} - -static MetaMonitorConfig * -create_monitor_config (MetaMonitor *monitor, - MetaMonitorMode *mode) -{ - MetaMonitorSpec *monitor_spec; - MetaMonitorModeSpec *mode_spec; - MetaMonitorConfig *monitor_config; - - monitor_spec = meta_monitor_get_spec (monitor); - mode_spec = meta_monitor_mode_get_spec (mode); - - monitor_config = g_new0 (MetaMonitorConfig, 1); - *monitor_config = (MetaMonitorConfig) { - .monitor_spec = meta_monitor_spec_clone (monitor_spec), - .mode_spec = g_memdup2 (mode_spec, sizeof (MetaMonitorModeSpec)), - .enable_underscanning = meta_monitor_is_underscanning (monitor) - }; - - return monitor_config; -} - -static MetaMonitorTransform -get_monitor_transform (MetaMonitorManager *monitor_manager, - MetaMonitor *monitor) -{ - MetaOrientationManager *orientation_manager; - MetaBackend *backend; - - if (!meta_monitor_is_laptop_panel (monitor)) - return META_MONITOR_TRANSFORM_NORMAL; - - backend = meta_monitor_manager_get_backend (monitor_manager); - orientation_manager = meta_backend_get_orientation_manager (backend); - - switch (meta_orientation_manager_get_orientation (orientation_manager)) - { - case META_ORIENTATION_BOTTOM_UP: - return META_MONITOR_TRANSFORM_180; - case META_ORIENTATION_LEFT_UP: - return META_MONITOR_TRANSFORM_90; - case META_ORIENTATION_RIGHT_UP: - return META_MONITOR_TRANSFORM_270; - case META_ORIENTATION_UNDEFINED: - case META_ORIENTATION_NORMAL: - default: - return META_MONITOR_TRANSFORM_NORMAL; - } -} - -static MetaLogicalMonitorConfig * -create_preferred_logical_monitor_config (MetaMonitorManager *monitor_manager, - MetaMonitor *monitor, - int x, - int y, - MetaLogicalMonitorConfig *primary_logical_monitor_config, - MetaLogicalMonitorLayoutMode layout_mode) -{ - MetaMonitorMode *mode; - int width, height; - float scale; - MetaMonitorTransform transform; - MetaMonitorConfig *monitor_config; - MetaLogicalMonitorConfig *logical_monitor_config; - - mode = meta_monitor_get_preferred_mode (monitor); - meta_monitor_mode_get_resolution (mode, &width, &height); - - if ((meta_monitor_manager_get_capabilities (monitor_manager) & - META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED) && - primary_logical_monitor_config) - scale = primary_logical_monitor_config->scale; - else - scale = meta_monitor_manager_calculate_monitor_mode_scale (monitor_manager, - monitor, - mode); - - switch (layout_mode) - { - case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL: - width = (int) roundf (width / scale); - height = (int) roundf (height / scale); - break; - case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL: - break; - } - - monitor_config = create_monitor_config (monitor, mode); - - transform = get_monitor_transform (monitor_manager, monitor); - if (meta_monitor_transform_is_rotated (transform)) - { - int temp = width; - width = height; - height = temp; - } - - logical_monitor_config = g_new0 (MetaLogicalMonitorConfig, 1); - *logical_monitor_config = (MetaLogicalMonitorConfig) { - .layout = (MetaRectangle) { - .x = x, - .y = y, - .width = width, - .height = height - }, - .transform = transform, - .scale = scale, - .monitor_configs = g_list_append (NULL, monitor_config) - }; - - return logical_monitor_config; -} - -MetaMonitorsConfig * -meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_manager) -{ - MetaMonitorManager *monitor_manager = config_manager->monitor_manager; - GList *logical_monitor_configs; - MetaMonitor *primary_monitor; - MetaLogicalMonitorLayoutMode layout_mode; - MetaLogicalMonitorConfig *primary_logical_monitor_config; - int x; - GList *monitors; - GList *l; - MetaMonitorsConfig *monitors_config; - - primary_monitor = find_primary_monitor (monitor_manager); - if (!primary_monitor) - return NULL; - - layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager); - - primary_logical_monitor_config = - create_preferred_logical_monitor_config (monitor_manager, - primary_monitor, - 0, 0, - NULL, - layout_mode); - primary_logical_monitor_config->is_primary = TRUE; - logical_monitor_configs = g_list_append (NULL, - primary_logical_monitor_config); - - x = primary_logical_monitor_config->layout.width; - monitors = meta_monitor_manager_get_monitors (monitor_manager); - for (l = monitors; l; l = l->next) - { - MetaMonitor *monitor = l->data; - MetaLogicalMonitorConfig *logical_monitor_config; - - if (monitor == primary_monitor) - continue; - - if (meta_monitor_is_laptop_panel (monitor) && - is_lid_closed (monitor_manager)) - continue; - - logical_monitor_config = - create_preferred_logical_monitor_config (monitor_manager, - monitor, - x, 0, - primary_logical_monitor_config, - layout_mode); - logical_monitor_configs = g_list_append (logical_monitor_configs, - logical_monitor_config); - - x += logical_monitor_config->layout.width; - } - - monitors_config = meta_monitors_config_new (monitor_manager, - logical_monitor_configs, - layout_mode, - META_MONITORS_CONFIG_FLAG_NONE); - - if (monitors_config) - meta_monitors_config_set_switch_config (monitors_config, META_MONITOR_SWITCH_CONFIG_ALL_LINEAR); - - return monitors_config; -} - -MetaMonitorsConfig * -meta_monitor_config_manager_create_fallback (MetaMonitorConfigManager *config_manager) -{ - MetaMonitorManager *monitor_manager = config_manager->monitor_manager; - MetaMonitor *primary_monitor; - GList *logical_monitor_configs; - MetaLogicalMonitorLayoutMode layout_mode; - MetaLogicalMonitorConfig *primary_logical_monitor_config; - - primary_monitor = find_primary_monitor (monitor_manager); - if (!primary_monitor) - return NULL; - - layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager); - - primary_logical_monitor_config = - create_preferred_logical_monitor_config (monitor_manager, - primary_monitor, - 0, 0, - NULL, - layout_mode); - primary_logical_monitor_config->is_primary = TRUE; - logical_monitor_configs = g_list_append (NULL, - primary_logical_monitor_config); - - return meta_monitors_config_new (monitor_manager, - logical_monitor_configs, - layout_mode, - META_MONITORS_CONFIG_FLAG_NONE); -} - -MetaMonitorsConfig * -meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_manager) -{ - MetaMonitorManager *monitor_manager = config_manager->monitor_manager; - MetaLogicalMonitorConfig *primary_logical_monitor_config = NULL; - MetaMonitor *primary_monitor; - MetaLogicalMonitorLayoutMode layout_mode; - GList *logical_monitor_configs; - GList *region; - int x, y; - GList *monitors; - GList *l; - - primary_monitor = find_primary_monitor (monitor_manager); - if (!primary_monitor) - return NULL; - - if (!meta_monitor_get_suggested_position (primary_monitor, &x, &y)) - return NULL; - - layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager); - - primary_logical_monitor_config = - create_preferred_logical_monitor_config (monitor_manager, - primary_monitor, - x, y, - NULL, - layout_mode); - primary_logical_monitor_config->is_primary = TRUE; - logical_monitor_configs = g_list_append (NULL, - primary_logical_monitor_config); - region = g_list_prepend (NULL, &primary_logical_monitor_config->layout); - - monitors = meta_monitor_manager_get_monitors (monitor_manager); - for (l = monitors; l; l = l->next) - { - MetaMonitor *monitor = l->data; - MetaLogicalMonitorConfig *logical_monitor_config; - - if (monitor == primary_monitor) - continue; - - if (!meta_monitor_get_suggested_position (monitor, &x, &y)) - continue; - - logical_monitor_config = - create_preferred_logical_monitor_config (monitor_manager, - monitor, - x, y, - primary_logical_monitor_config, - layout_mode); - logical_monitor_configs = g_list_append (logical_monitor_configs, - logical_monitor_config); - - if (meta_rectangle_overlaps_with_region (region, - &logical_monitor_config->layout)) - { - g_warning ("Suggested monitor config has overlapping region, rejecting"); - g_list_free (region); - g_list_free_full (logical_monitor_configs, - (GDestroyNotify) meta_logical_monitor_config_free); - return NULL; - } - - region = g_list_prepend (region, &logical_monitor_config->layout); - } - - g_list_free (region); - - if (!logical_monitor_configs) - return NULL; - - return meta_monitors_config_new (monitor_manager, - logical_monitor_configs, - layout_mode, - META_MONITORS_CONFIG_FLAG_NONE); -} - -static GList * -clone_monitor_config_list (GList *monitor_configs_in) -{ - MetaMonitorConfig *monitor_config_in; - MetaMonitorConfig *monitor_config_out; - GList *monitor_configs_out = NULL; - GList *l; - - for (l = monitor_configs_in; l; l = l->next) - { - monitor_config_in = l->data; - monitor_config_out = g_new0 (MetaMonitorConfig, 1); - *monitor_config_out = (MetaMonitorConfig) { - .monitor_spec = meta_monitor_spec_clone (monitor_config_in->monitor_spec), - .mode_spec = g_memdup2 (monitor_config_in->mode_spec, - sizeof (MetaMonitorModeSpec)), - .enable_underscanning = monitor_config_in->enable_underscanning - }; - monitor_configs_out = - g_list_append (monitor_configs_out, monitor_config_out); - } - - return monitor_configs_out; -} - -static GList * -clone_logical_monitor_config_list (GList *logical_monitor_configs_in) -{ - MetaLogicalMonitorConfig *logical_monitor_config_in; - MetaLogicalMonitorConfig *logical_monitor_config_out; - GList *logical_monitor_configs_out = NULL; - GList *l; - - for (l = logical_monitor_configs_in; l; l = l->next) - { - logical_monitor_config_in = l->data; - - logical_monitor_config_out = - g_memdup2 (logical_monitor_config_in, - sizeof (MetaLogicalMonitorConfig)); - logical_monitor_config_out->monitor_configs = - clone_monitor_config_list (logical_monitor_config_in->monitor_configs); - - logical_monitor_configs_out = - g_list_append (logical_monitor_configs_out, logical_monitor_config_out); - } - - return logical_monitor_configs_out; -} - -static MetaLogicalMonitorConfig * -find_logical_config_for_builtin_display_rotation (MetaMonitorConfigManager *config_manager, - GList *logical_monitor_configs) -{ - MetaLogicalMonitorConfig *logical_monitor_config; - MetaMonitorConfig *monitor_config; - MetaMonitor *panel; - GList *l; - - panel = meta_monitor_manager_get_laptop_panel (config_manager->monitor_manager); - if (panel && meta_monitor_is_active (panel)) - { - for (l = logical_monitor_configs; l; l = l->next) - { - logical_monitor_config = l->data; - /* - * We only want to return the config for the panel if it is - * configured on its own, so we skip configs which contain clones. - */ - if (g_list_length (logical_monitor_config->monitor_configs) != 1) - continue; - - monitor_config = logical_monitor_config->monitor_configs->data; - if (meta_monitor_spec_equals (meta_monitor_get_spec (panel), - monitor_config->monitor_spec)) - return logical_monitor_config; - } - } - - return NULL; -} - -static MetaMonitorsConfig * -create_for_builtin_display_rotation (MetaMonitorConfigManager *config_manager, - gboolean rotate, - MetaMonitorTransform transform) -{ - MetaMonitorManager *monitor_manager = config_manager->monitor_manager; - MetaLogicalMonitorConfig *logical_monitor_config; - MetaLogicalMonitorConfig *current_logical_monitor_config; - GList *logical_monitor_configs, *current_configs; - MetaLogicalMonitorLayoutMode layout_mode; - - if (!config_manager->current_config) - return NULL; - - current_configs = config_manager->current_config->logical_monitor_configs; - current_logical_monitor_config = - find_logical_config_for_builtin_display_rotation (config_manager, - current_configs); - if (!current_logical_monitor_config) - return NULL; - - if (rotate) - transform = (current_logical_monitor_config->transform + 1) % META_MONITOR_TRANSFORM_FLIPPED; - else - { - /* - * The transform coming from the accelerometer should be applied to - * the crtc as is, without taking panel-orientation into account, this - * is done so that non panel-orientation aware desktop environments do the - * right thing. Mutter corrects for panel-orientation when applying the - * transform from a logical-monitor-config, so we must convert here. - */ - MetaMonitor *panel = - meta_monitor_manager_get_laptop_panel (config_manager->monitor_manager); - - transform = meta_monitor_crtc_to_logical_transform (panel, transform); - } - - if (current_logical_monitor_config->transform == transform) - return NULL; - - logical_monitor_configs = - clone_logical_monitor_config_list (config_manager->current_config->logical_monitor_configs); - logical_monitor_config = - find_logical_config_for_builtin_display_rotation (config_manager, logical_monitor_configs); - logical_monitor_config->transform = transform; - - if (meta_monitor_transform_is_rotated (current_logical_monitor_config->transform) != - meta_monitor_transform_is_rotated (logical_monitor_config->transform)) - { - int temp = logical_monitor_config->layout.width; - logical_monitor_config->layout.width = logical_monitor_config->layout.height; - logical_monitor_config->layout.height = temp; - } - - layout_mode = config_manager->current_config->layout_mode; - return meta_monitors_config_new (monitor_manager, - logical_monitor_configs, - layout_mode, - META_MONITORS_CONFIG_FLAG_NONE); -} - -MetaMonitorsConfig * -meta_monitor_config_manager_create_for_orientation (MetaMonitorConfigManager *config_manager, - MetaMonitorTransform transform) -{ - return create_for_builtin_display_rotation (config_manager, FALSE, transform); -} - -MetaMonitorsConfig * -meta_monitor_config_manager_create_for_rotate_monitor (MetaMonitorConfigManager *config_manager) -{ - return create_for_builtin_display_rotation (config_manager, TRUE, META_MONITOR_TRANSFORM_NORMAL); -} - -static MetaMonitorsConfig * -create_for_switch_config_all_mirror (MetaMonitorConfigManager *config_manager) -{ - MetaMonitorManager *monitor_manager = config_manager->monitor_manager; - MetaLogicalMonitorLayoutMode layout_mode; - MetaLogicalMonitorConfig *logical_monitor_config = NULL; - GList *logical_monitor_configs; - GList *monitor_configs = NULL; - gint common_mode_w = 0, common_mode_h = 0; - float best_scale = 1.0; - MetaMonitor *monitor; - GList *modes; - GList *monitors; - GList *l; - MetaMonitorsConfig *monitors_config; - - monitors = meta_monitor_manager_get_monitors (monitor_manager); - monitor = monitors->data; - modes = meta_monitor_get_modes (monitor); - for (l = modes; l; l = l->next) - { - MetaMonitorMode *mode = l->data; - gboolean common_mode_size = TRUE; - gint mode_w, mode_h; - GList *ll; - - meta_monitor_mode_get_resolution (mode, &mode_w, &mode_h); - - for (ll = monitors->next; ll; ll = ll->next) - { - MetaMonitor *monitor_b = ll->data; - gboolean have_same_mode_size = FALSE; - GList *mm; - - for (mm = meta_monitor_get_modes (monitor_b); mm; mm = mm->next) - { - MetaMonitorMode *mode_b = mm->data; - gint mode_b_w, mode_b_h; - - meta_monitor_mode_get_resolution (mode_b, &mode_b_w, &mode_b_h); - - if (mode_w == mode_b_w && - mode_h == mode_b_h) - { - have_same_mode_size = TRUE; - break; - } - } - - if (!have_same_mode_size) - { - common_mode_size = FALSE; - break; - } - } - - if (common_mode_size && - common_mode_w * common_mode_h < mode_w * mode_h) - { - common_mode_w = mode_w; - common_mode_h = mode_h; - } - } - - if (common_mode_w == 0 || common_mode_h == 0) - return NULL; - - for (l = monitors; l; l = l->next) - { - MetaMonitor *monitor = l->data; - MetaMonitorMode *mode = NULL; - GList *ll; - float scale; - - for (ll = meta_monitor_get_modes (monitor); ll; ll = ll->next) - { - gint mode_w, mode_h; - - mode = ll->data; - meta_monitor_mode_get_resolution (mode, &mode_w, &mode_h); - - if (mode_w == common_mode_w && mode_h == common_mode_h) - break; - } - - if (!mode) - continue; - - scale = meta_monitor_manager_calculate_monitor_mode_scale (monitor_manager, monitor, mode); - best_scale = MAX (best_scale, scale); - monitor_configs = g_list_prepend (monitor_configs, create_monitor_config (monitor, mode)); - } - - logical_monitor_config = g_new0 (MetaLogicalMonitorConfig, 1); - *logical_monitor_config = (MetaLogicalMonitorConfig) { - .layout = (MetaRectangle) { - .x = 0, - .y = 0, - .width = common_mode_w, - .height = common_mode_h - }, - .scale = best_scale, - .monitor_configs = monitor_configs - }; - - logical_monitor_configs = g_list_append (NULL, logical_monitor_config); - layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager); - monitors_config = meta_monitors_config_new (monitor_manager, - logical_monitor_configs, - layout_mode, - META_MONITORS_CONFIG_FLAG_NONE); - - if (monitors_config) - meta_monitors_config_set_switch_config (monitors_config, META_MONITOR_SWITCH_CONFIG_ALL_MIRROR); - - return monitors_config; -} - -static MetaMonitorsConfig * -create_for_switch_config_external (MetaMonitorConfigManager *config_manager) -{ - MetaMonitorManager *monitor_manager = config_manager->monitor_manager; - GList *logical_monitor_configs = NULL; - int x = 0; - MetaLogicalMonitorLayoutMode layout_mode; - GList *monitors; - GList *l; - MetaMonitorsConfig *monitors_config; - - layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager); - - monitors = meta_monitor_manager_get_monitors (monitor_manager); - for (l = monitors; l; l = l->next) - { - MetaMonitor *monitor = l->data; - MetaLogicalMonitorConfig *logical_monitor_config; - - if (meta_monitor_is_laptop_panel (monitor)) - continue; - - logical_monitor_config = - create_preferred_logical_monitor_config (monitor_manager, - monitor, - x, 0, - NULL, - layout_mode); - logical_monitor_configs = g_list_append (logical_monitor_configs, - logical_monitor_config); - - if (x == 0) - logical_monitor_config->is_primary = TRUE; - - x += logical_monitor_config->layout.width; - } - - if (!logical_monitor_configs) - return NULL; - - monitors_config = meta_monitors_config_new (monitor_manager, - logical_monitor_configs, - layout_mode, - META_MONITORS_CONFIG_FLAG_NONE); - - if (monitors_config) - meta_monitors_config_set_switch_config (monitors_config, META_MONITOR_SWITCH_CONFIG_EXTERNAL); - - return monitors_config; -} - -static MetaMonitorsConfig * -create_for_switch_config_builtin (MetaMonitorConfigManager *config_manager) -{ - MetaMonitorManager *monitor_manager = config_manager->monitor_manager; - MetaLogicalMonitorLayoutMode layout_mode; - GList *logical_monitor_configs; - MetaLogicalMonitorConfig *primary_logical_monitor_config; - MetaMonitor *monitor; - MetaMonitorsConfig *monitors_config; - - monitor = meta_monitor_manager_get_laptop_panel (monitor_manager); - if (!monitor) - return NULL; - - layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager); - - primary_logical_monitor_config = - create_preferred_logical_monitor_config (monitor_manager, - monitor, - 0, 0, - NULL, - layout_mode); - primary_logical_monitor_config->is_primary = TRUE; - logical_monitor_configs = g_list_append (NULL, - primary_logical_monitor_config); - - monitors_config = meta_monitors_config_new (monitor_manager, - logical_monitor_configs, - layout_mode, - META_MONITORS_CONFIG_FLAG_NONE); - - if (monitors_config) - meta_monitors_config_set_switch_config (monitors_config, META_MONITOR_SWITCH_CONFIG_BUILTIN); - - return monitors_config; -} - -MetaMonitorsConfig * -meta_monitor_config_manager_create_for_switch_config (MetaMonitorConfigManager *config_manager, - MetaMonitorSwitchConfigType config_type) -{ - MetaMonitorManager *monitor_manager = config_manager->monitor_manager; - MetaMonitorsConfig *config; - - if (!meta_monitor_manager_can_switch_config (monitor_manager)) - return NULL; - - switch (config_type) - { - case META_MONITOR_SWITCH_CONFIG_ALL_MIRROR: - config = create_for_switch_config_all_mirror (config_manager); - break; - case META_MONITOR_SWITCH_CONFIG_ALL_LINEAR: - config = meta_monitor_config_manager_create_linear (config_manager); - break; - case META_MONITOR_SWITCH_CONFIG_EXTERNAL: - config = create_for_switch_config_external (config_manager); - break; - case META_MONITOR_SWITCH_CONFIG_BUILTIN: - config = create_for_switch_config_builtin (config_manager); - break; - case META_MONITOR_SWITCH_CONFIG_UNKNOWN: - default: - g_warn_if_reached (); - return NULL; - } - - return config; -} - -void -meta_monitor_config_manager_set_current (MetaMonitorConfigManager *config_manager, - MetaMonitorsConfig *config) -{ - if (config_manager->current_config) - { - g_queue_push_head (&config_manager->config_history, - g_object_ref (config_manager->current_config)); - if (g_queue_get_length (&config_manager->config_history) > - CONFIG_HISTORY_MAX_SIZE) - g_object_unref (g_queue_pop_tail (&config_manager->config_history)); - } - - g_set_object (&config_manager->current_config, config); -} - -void -meta_monitor_config_manager_save_current (MetaMonitorConfigManager *config_manager) -{ - g_return_if_fail (config_manager->current_config); - - meta_monitor_config_store_add (config_manager->config_store, - config_manager->current_config); -} - -MetaMonitorsConfig * -meta_monitor_config_manager_get_current (MetaMonitorConfigManager *config_manager) -{ - return config_manager->current_config; -} - -MetaMonitorsConfig * -meta_monitor_config_manager_pop_previous (MetaMonitorConfigManager *config_manager) -{ - return g_queue_pop_head (&config_manager->config_history); -} - -MetaMonitorsConfig * -meta_monitor_config_manager_get_previous (MetaMonitorConfigManager *config_manager) -{ - return g_queue_peek_head (&config_manager->config_history); -} - -void -meta_monitor_config_manager_clear_history (MetaMonitorConfigManager *config_manager) -{ - g_queue_foreach (&config_manager->config_history, (GFunc) g_object_unref, NULL); - g_queue_clear (&config_manager->config_history); -} - -static void -meta_monitor_config_manager_dispose (GObject *object) -{ - MetaMonitorConfigManager *config_manager = - META_MONITOR_CONFIG_MANAGER (object); - - g_clear_object (&config_manager->current_config); - meta_monitor_config_manager_clear_history (config_manager); - - G_OBJECT_CLASS (meta_monitor_config_manager_parent_class)->dispose (object); -} - -static void -meta_monitor_config_manager_init (MetaMonitorConfigManager *config_manager) -{ - g_queue_init (&config_manager->config_history); -} - -static void -meta_monitor_config_manager_class_init (MetaMonitorConfigManagerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = meta_monitor_config_manager_dispose; -} - -void -meta_monitor_config_free (MetaMonitorConfig *monitor_config) -{ - if (monitor_config->monitor_spec) - meta_monitor_spec_free (monitor_config->monitor_spec); - g_free (monitor_config->mode_spec); - g_free (monitor_config); -} - -void -meta_logical_monitor_config_free (MetaLogicalMonitorConfig *logical_monitor_config) -{ - g_list_free_full (logical_monitor_config->monitor_configs, - (GDestroyNotify) meta_monitor_config_free); - g_free (logical_monitor_config); -} - -static MetaMonitorsConfigKey * -meta_monitors_config_key_new (GList *logical_monitor_configs, - GList *disabled_monitor_specs) -{ - MetaMonitorsConfigKey *config_key; - GList *monitor_specs; - GList *l; - - monitor_specs = NULL; - for (l = logical_monitor_configs; l; l = l->next) - { - MetaLogicalMonitorConfig *logical_monitor_config = l->data; - GList *k; - - for (k = logical_monitor_config->monitor_configs; k; k = k->next) - { - MetaMonitorConfig *monitor_config = k->data; - MetaMonitorSpec *monitor_spec; - - monitor_spec = meta_monitor_spec_clone (monitor_config->monitor_spec); - monitor_specs = g_list_prepend (monitor_specs, monitor_spec); - } - } - - for (l = disabled_monitor_specs; l; l = l->next) - { - MetaMonitorSpec *monitor_spec = l->data; - - monitor_spec = meta_monitor_spec_clone (monitor_spec); - monitor_specs = g_list_prepend (monitor_specs, monitor_spec); - } - - monitor_specs = g_list_sort (monitor_specs, - (GCompareFunc) meta_monitor_spec_compare); - - config_key = g_new0 (MetaMonitorsConfigKey, 1); - *config_key = (MetaMonitorsConfigKey) { - .monitor_specs = monitor_specs - }; - - return config_key; -} - -void -meta_monitors_config_key_free (MetaMonitorsConfigKey *config_key) -{ - g_list_free_full (config_key->monitor_specs, - (GDestroyNotify) meta_monitor_spec_free); - g_free (config_key); -} - -unsigned int -meta_monitors_config_key_hash (gconstpointer data) -{ - const MetaMonitorsConfigKey *config_key = data; - GList *l; - unsigned long hash; - - hash = 0; - for (l = config_key->monitor_specs; l; l = l->next) - { - MetaMonitorSpec *monitor_spec = l->data; - - hash ^= (g_str_hash (monitor_spec->connector) ^ - g_str_hash (monitor_spec->vendor) ^ - g_str_hash (monitor_spec->product) ^ - g_str_hash (monitor_spec->serial)); - } - - return hash; -} - -gboolean -meta_monitors_config_key_equal (gconstpointer data_a, - gconstpointer data_b) -{ - const MetaMonitorsConfigKey *config_key_a = data_a; - const MetaMonitorsConfigKey *config_key_b = data_b; - GList *l_a, *l_b; - - for (l_a = config_key_a->monitor_specs, l_b = config_key_b->monitor_specs; - l_a && l_b; - l_a = l_a->next, l_b = l_b->next) - { - MetaMonitorSpec *monitor_spec_a = l_a->data; - MetaMonitorSpec *monitor_spec_b = l_b->data; - - if (!meta_monitor_spec_equals (monitor_spec_a, monitor_spec_b)) - return FALSE; - } - - if (l_a || l_b) - return FALSE; - - return TRUE; -} - -MetaMonitorSwitchConfigType -meta_monitors_config_get_switch_config (MetaMonitorsConfig *config) -{ - return config->switch_config; -} - -void -meta_monitors_config_set_switch_config (MetaMonitorsConfig *config, - MetaMonitorSwitchConfigType switch_config) -{ - config->switch_config = switch_config; -} - -MetaMonitorsConfig * -meta_monitors_config_new_full (GList *logical_monitor_configs, - GList *disabled_monitor_specs, - MetaLogicalMonitorLayoutMode layout_mode, - MetaMonitorsConfigFlag flags) -{ - MetaMonitorsConfig *config; - - config = g_object_new (META_TYPE_MONITORS_CONFIG, NULL); - config->logical_monitor_configs = logical_monitor_configs; - config->disabled_monitor_specs = disabled_monitor_specs; - config->key = meta_monitors_config_key_new (logical_monitor_configs, - disabled_monitor_specs); - config->layout_mode = layout_mode; - config->flags = flags; - config->switch_config = META_MONITOR_SWITCH_CONFIG_UNKNOWN; - - return config; -} - -MetaMonitorsConfig * -meta_monitors_config_new (MetaMonitorManager *monitor_manager, - GList *logical_monitor_configs, - MetaLogicalMonitorLayoutMode layout_mode, - MetaMonitorsConfigFlag flags) -{ - GList *disabled_monitor_specs = NULL; - GList *monitors; - GList *l; - - monitors = meta_monitor_manager_get_monitors (monitor_manager); - for (l = monitors; l; l = l->next) - { - MetaMonitor *monitor = l->data; - MetaMonitorSpec *monitor_spec; - - if (is_lid_closed (monitor_manager) && - meta_monitor_is_laptop_panel (monitor)) - continue; - - monitor_spec = meta_monitor_get_spec (monitor); - if (meta_logical_monitor_configs_have_monitor (logical_monitor_configs, - monitor_spec)) - continue; - - disabled_monitor_specs = - g_list_prepend (disabled_monitor_specs, - meta_monitor_spec_clone (monitor_spec)); - } - - return meta_monitors_config_new_full (logical_monitor_configs, - disabled_monitor_specs, - layout_mode, - flags); -} - -static void -meta_monitors_config_finalize (GObject *object) -{ - MetaMonitorsConfig *config = META_MONITORS_CONFIG (object); - - meta_monitors_config_key_free (config->key); - g_list_free_full (config->logical_monitor_configs, - (GDestroyNotify) meta_logical_monitor_config_free); - g_list_free_full (config->disabled_monitor_specs, - (GDestroyNotify) meta_monitor_spec_free); - - G_OBJECT_CLASS (meta_monitors_config_parent_class)->finalize (object); -} - -static void -meta_monitors_config_init (MetaMonitorsConfig *config) -{ -} - -static void -meta_monitors_config_class_init (MetaMonitorsConfigClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_monitors_config_finalize; -} - -static void -meta_crtc_assignment_free (MetaCrtcAssignment *assignment) -{ - g_ptr_array_free (assignment->outputs, TRUE); - g_free (assignment); -} - -static void -meta_output_assignment_free (MetaOutputAssignment *assignment) -{ - g_free (assignment); -} - -gboolean -meta_verify_monitor_mode_spec (MetaMonitorModeSpec *monitor_mode_spec, - GError **error) -{ - if (monitor_mode_spec->width > 0 && - monitor_mode_spec->height > 0 && - monitor_mode_spec->refresh_rate > 0.0f) - { - return TRUE; - } - else - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Monitor mode invalid"); - return FALSE; - } -} - -gboolean -meta_verify_monitor_spec (MetaMonitorSpec *monitor_spec, - GError **error) -{ - if (monitor_spec->connector && - monitor_spec->vendor && - monitor_spec->product && - monitor_spec->serial) - { - return TRUE; - } - else - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Monitor spec incomplete"); - return FALSE; - } -} - -gboolean -meta_verify_monitor_config (MetaMonitorConfig *monitor_config, - GError **error) -{ - if (monitor_config->monitor_spec && monitor_config->mode_spec) - { - return TRUE; - } - else - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Monitor config incomplete"); - return FALSE; - } -} - -gboolean -meta_verify_logical_monitor_config (MetaLogicalMonitorConfig *logical_monitor_config, - MetaLogicalMonitorLayoutMode layout_mode, - MetaMonitorManager *monitor_manager, - GError **error) -{ - GList *l; - int expected_mode_width = 0; - int expected_mode_height = 0; - - if (logical_monitor_config->layout.x < 0 || - logical_monitor_config->layout.y < 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Invalid logical monitor position (%d, %d)", - logical_monitor_config->layout.x, - logical_monitor_config->layout.y); - return FALSE; - } - - if (!logical_monitor_config->monitor_configs) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Logical monitor is empty"); - return FALSE; - } - - if (meta_monitor_transform_is_rotated (logical_monitor_config->transform)) - { - expected_mode_width = logical_monitor_config->layout.height; - expected_mode_height = logical_monitor_config->layout.width; - } - else - { - expected_mode_width = logical_monitor_config->layout.width; - expected_mode_height = logical_monitor_config->layout.height; - } - - switch (layout_mode) - { - case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL: - expected_mode_width = roundf (expected_mode_width * - logical_monitor_config->scale); - expected_mode_height = roundf (expected_mode_height * - logical_monitor_config->scale); - break; - case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL: - break; - } - - for (l = logical_monitor_config->monitor_configs; l; l = l->next) - { - MetaMonitorConfig *monitor_config = l->data; - - if (monitor_config->mode_spec->width != expected_mode_width || - monitor_config->mode_spec->height != expected_mode_height) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Monitor modes in logical monitor conflict"); - return FALSE; - } - } - - return TRUE; -} - -static gboolean -has_adjacent_neighbour (MetaMonitorsConfig *config, - MetaLogicalMonitorConfig *logical_monitor_config) -{ - GList *l; - - if (!config->logical_monitor_configs->next) - { - g_assert (config->logical_monitor_configs->data == - logical_monitor_config); - return TRUE; - } - - for (l = config->logical_monitor_configs; l; l = l->next) - { - MetaLogicalMonitorConfig *other_logical_monitor_config = l->data; - - if (logical_monitor_config == other_logical_monitor_config) - continue; - - if (meta_rectangle_is_adjacent_to (&logical_monitor_config->layout, - &other_logical_monitor_config->layout)) - return TRUE; - } - - return FALSE; -} - -gboolean -meta_logical_monitor_configs_have_monitor (GList *logical_monitor_configs, - MetaMonitorSpec *monitor_spec) -{ - GList *l; - - for (l = logical_monitor_configs; l; l = l->next) - { - MetaLogicalMonitorConfig *logical_monitor_config = l->data; - GList *k; - - for (k = logical_monitor_config->monitor_configs; k; k = k->next) - { - MetaMonitorConfig *monitor_config = k->data; - - if (meta_monitor_spec_equals (monitor_spec, - monitor_config->monitor_spec)) - return TRUE; - } - } - - return FALSE; -} - -static gboolean -meta_monitors_config_is_monitor_enabled (MetaMonitorsConfig *config, - MetaMonitorSpec *monitor_spec) -{ - return meta_logical_monitor_configs_have_monitor (config->logical_monitor_configs, - monitor_spec); -} - -gboolean -meta_verify_monitors_config (MetaMonitorsConfig *config, - MetaMonitorManager *monitor_manager, - GError **error) -{ - int min_x, min_y; - gboolean has_primary; - GList *region; - GList *l; - gboolean global_scale_required; - - if (!config->logical_monitor_configs) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Monitors config incomplete"); - return FALSE; - } - - global_scale_required = - !!(meta_monitor_manager_get_capabilities (monitor_manager) & - META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED); - - min_x = INT_MAX; - min_y = INT_MAX; - region = NULL; - has_primary = FALSE; - for (l = config->logical_monitor_configs; l; l = l->next) - { - MetaLogicalMonitorConfig *logical_monitor_config = l->data; - - if (global_scale_required) - { - MetaLogicalMonitorConfig *prev_logical_monitor_config = - l->prev ? l->prev->data : NULL; - - if (prev_logical_monitor_config && - (prev_logical_monitor_config->scale != - logical_monitor_config->scale)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Logical monitor scales must be identical"); - return FALSE; - } - } - - if (meta_rectangle_overlaps_with_region (region, - &logical_monitor_config->layout)) - { - g_list_free (region); - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Logical monitors overlap"); - return FALSE; - } - - if (has_primary && logical_monitor_config->is_primary) - { - g_list_free (region); - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Config contains multiple primary logical monitors"); - return FALSE; - } - else if (logical_monitor_config->is_primary) - { - has_primary = TRUE; - } - - if (!has_adjacent_neighbour (config, logical_monitor_config)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Logical monitors not adjacent"); - return FALSE; - } - - min_x = MIN (logical_monitor_config->layout.x, min_x); - min_y = MIN (logical_monitor_config->layout.y, min_y); - - region = g_list_prepend (region, &logical_monitor_config->layout); - } - - g_list_free (region); - - for (l = config->disabled_monitor_specs; l; l = l->next) - { - MetaMonitorSpec *monitor_spec = l->data; - - if (meta_monitors_config_is_monitor_enabled (config, monitor_spec)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Assigned monitor explicitly disabled"); - return FALSE; - } - } - - if (min_x != 0 || min_y != 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Logical monitors positions are offset"); - return FALSE; - } - - if (!has_primary) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Config is missing primary logical"); - return FALSE; - } - - return TRUE; -} diff --git a/src/backends/meta-monitor-config-manager.h b/src/backends/meta-monitor-config-manager.h deleted file mode 100644 index 86756a7e3..000000000 --- a/src/backends/meta-monitor-config-manager.h +++ /dev/null @@ -1,201 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 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_MONITOR_CONFIG_MANAGER_H -#define META_MONITOR_CONFIG_MANAGER_H - -#include "backends/meta-monitor.h" -#include "backends/meta-monitor-manager-private.h" - -#define META_TYPE_MONITOR_CONFIG_MANAGER (meta_monitor_config_manager_get_type ()) -G_DECLARE_FINAL_TYPE (MetaMonitorConfigManager, meta_monitor_config_manager, - META, MONITOR_CONFIG_MANAGER, GObject) - -typedef struct _MetaMonitorConfig -{ - MetaMonitorSpec *monitor_spec; - MetaMonitorModeSpec *mode_spec; - gboolean enable_underscanning; -} MetaMonitorConfig; - -typedef struct _MetaLogicalMonitorConfig -{ - MetaRectangle layout; - GList *monitor_configs; - MetaMonitorTransform transform; - float scale; - gboolean is_primary; - gboolean is_presentation; -} MetaLogicalMonitorConfig; - -typedef struct _MetaMonitorsConfigKey -{ - GList *monitor_specs; -} MetaMonitorsConfigKey; - -typedef enum _MetaMonitorsConfigFlag -{ - META_MONITORS_CONFIG_FLAG_NONE = 0, - META_MONITORS_CONFIG_FLAG_MIGRATED = (1 << 0), - META_MONITORS_CONFIG_FLAG_SYSTEM_CONFIG = (1 << 1), -} MetaMonitorsConfigFlag; - -struct _MetaMonitorsConfig -{ - GObject parent; - - MetaMonitorsConfigKey *key; - GList *logical_monitor_configs; - - GList *disabled_monitor_specs; - - MetaMonitorsConfigFlag flags; - - MetaLogicalMonitorLayoutMode layout_mode; - - MetaMonitorSwitchConfigType switch_config; -}; - -#define META_TYPE_MONITORS_CONFIG (meta_monitors_config_get_type ()) -G_DECLARE_FINAL_TYPE (MetaMonitorsConfig, meta_monitors_config, - META, MONITORS_CONFIG, GObject) - -META_EXPORT_TEST -MetaMonitorConfigManager * meta_monitor_config_manager_new (MetaMonitorManager *monitor_manager); - -META_EXPORT_TEST -MetaMonitorConfigStore * meta_monitor_config_manager_get_store (MetaMonitorConfigManager *config_manager); - -META_EXPORT_TEST -gboolean meta_monitor_config_manager_assign (MetaMonitorManager *manager, - MetaMonitorsConfig *config, - GPtrArray **crtc_assignments, - GPtrArray **output_assignments, - GError **error); - -META_EXPORT_TEST -MetaMonitorsConfig * meta_monitor_config_manager_get_stored (MetaMonitorConfigManager *config_manager); - -META_EXPORT_TEST -MetaMonitorsConfig * meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_manager); - -META_EXPORT_TEST -MetaMonitorsConfig * meta_monitor_config_manager_create_fallback (MetaMonitorConfigManager *config_manager); - -META_EXPORT_TEST -MetaMonitorsConfig * meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_manager); - -META_EXPORT_TEST -MetaMonitorsConfig * meta_monitor_config_manager_create_for_orientation (MetaMonitorConfigManager *config_manager, - MetaMonitorTransform transform); - -META_EXPORT_TEST -MetaMonitorsConfig * meta_monitor_config_manager_create_for_rotate_monitor (MetaMonitorConfigManager *config_manager); - -META_EXPORT_TEST -MetaMonitorsConfig * meta_monitor_config_manager_create_for_switch_config (MetaMonitorConfigManager *config_manager, - MetaMonitorSwitchConfigType config_type); - -META_EXPORT_TEST -void meta_monitor_config_manager_set_current (MetaMonitorConfigManager *config_manager, - MetaMonitorsConfig *config); - -META_EXPORT_TEST -MetaMonitorsConfig * meta_monitor_config_manager_get_current (MetaMonitorConfigManager *config_manager); - -META_EXPORT_TEST -MetaMonitorsConfig * meta_monitor_config_manager_pop_previous (MetaMonitorConfigManager *config_manager); - -META_EXPORT_TEST -MetaMonitorsConfig * meta_monitor_config_manager_get_previous (MetaMonitorConfigManager *config_manager); - -META_EXPORT_TEST -void meta_monitor_config_manager_clear_history (MetaMonitorConfigManager *config_manager); - -META_EXPORT_TEST -void meta_monitor_config_manager_save_current (MetaMonitorConfigManager *config_manager); - -META_EXPORT_TEST -MetaMonitorsConfig * meta_monitors_config_new_full (GList *logical_monitor_configs, - GList *disabled_monitors, - MetaLogicalMonitorLayoutMode layout_mode, - MetaMonitorsConfigFlag flags); - -META_EXPORT_TEST -MetaMonitorsConfig * meta_monitors_config_new (MetaMonitorManager *monitor_manager, - GList *logical_monitor_configs, - MetaLogicalMonitorLayoutMode layout_mode, - MetaMonitorsConfigFlag flags); - -META_EXPORT_TEST -MetaMonitorSwitchConfigType meta_monitors_config_get_switch_config (MetaMonitorsConfig *config); - -META_EXPORT_TEST -void meta_monitors_config_set_switch_config (MetaMonitorsConfig *config, - MetaMonitorSwitchConfigType switch_config); - -META_EXPORT_TEST -unsigned int meta_monitors_config_key_hash (gconstpointer config_key); - -META_EXPORT_TEST -gboolean meta_monitors_config_key_equal (gconstpointer config_key_a, - gconstpointer config_key_b); - -META_EXPORT_TEST -void meta_monitors_config_key_free (MetaMonitorsConfigKey *config_key); - -META_EXPORT_TEST -void meta_logical_monitor_config_free (MetaLogicalMonitorConfig *logical_monitor_config); - -META_EXPORT_TEST -void meta_monitor_config_free (MetaMonitorConfig *monitor_config); - -META_EXPORT_TEST -MetaMonitorsConfigKey * meta_create_monitors_config_key_for_current_state (MetaMonitorManager *monitor_manager); - -META_EXPORT_TEST -gboolean meta_logical_monitor_configs_have_monitor (GList *logical_monitor_configs, - MetaMonitorSpec *monitor_spec); - -META_EXPORT_TEST -gboolean meta_verify_monitor_mode_spec (MetaMonitorModeSpec *monitor_mode_spec, - GError **error); - -META_EXPORT_TEST -gboolean meta_verify_monitor_spec (MetaMonitorSpec *monitor_spec, - GError **error); - -META_EXPORT_TEST -gboolean meta_verify_monitor_config (MetaMonitorConfig *monitor_config, - GError **error); - -META_EXPORT_TEST -gboolean meta_verify_logical_monitor_config (MetaLogicalMonitorConfig *logical_monitor_config, - MetaLogicalMonitorLayoutMode layout_mode, - MetaMonitorManager *monitor_manager, - GError **error); - -META_EXPORT_TEST -gboolean meta_verify_monitors_config (MetaMonitorsConfig *config, - MetaMonitorManager *monitor_manager, - GError **error); - -#endif /* META_MONITOR_CONFIG_MANAGER_H */ diff --git a/src/backends/meta-monitor-config-migration.c b/src/backends/meta-monitor-config-migration.c deleted file mode 100644 index d619dc433..000000000 --- a/src/backends/meta-monitor-config-migration.c +++ /dev/null @@ -1,1233 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001, 2002 Havoc Pennington - * Copyright (C) 2002, 2003 Red Hat Inc. - * Some ICCCM manager selection code derived from fvwm2, - * Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * Copyright (C) 2013, 2017 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 . - */ - -/* - * Portions of this file are derived from gnome-desktop/libgnome-desktop/gnome-rr-config.c - * - * Copyright 2007, 2008, Red Hat, Inc. - * Copyright 2010 Giovanni Campagna - * - * Author: Soren Sandmann - */ - -#include "config.h" - -#include "backends/meta-monitor-config-migration.h" - -#include -#include - -#include "backends/meta-monitor-config-manager.h" -#include "backends/meta-monitor-config-store.h" -#include "backends/meta-monitor-manager-private.h" -#include "meta/boxes.h" - -#define META_MONITORS_CONFIG_MIGRATION_ERROR (meta_monitors_config_migration_error_quark ()) -static GQuark meta_monitors_config_migration_error_quark (void); - -G_DEFINE_QUARK (meta-monitors-config-migration-error-quark, - meta_monitors_config_migration_error) - -enum _MetaConfigMigrationError -{ - META_MONITORS_CONFIG_MIGRATION_ERROR_NOT_TILED, - META_MONITORS_CONFIG_MIGRATION_ERROR_NOT_MAIN_TILE -} MetaConfigMigrationError; - -typedef struct -{ - char *connector; - char *vendor; - char *product; - char *serial; -} MetaOutputKey; - -typedef struct -{ - gboolean enabled; - MetaRectangle rect; - float refresh_rate; - MetaMonitorTransform transform; - - gboolean is_primary; - gboolean is_presentation; - gboolean is_underscanning; -} MetaOutputConfig; - -typedef struct _MetaLegacyMonitorsConfig -{ - MetaOutputKey *keys; - MetaOutputConfig *outputs; - unsigned int n_outputs; -} MetaLegacyMonitorsConfig; - -typedef enum -{ - STATE_INITIAL, - STATE_MONITORS, - STATE_CONFIGURATION, - STATE_OUTPUT, - STATE_OUTPUT_FIELD, - STATE_CLONE -} ParserState; - -typedef struct -{ - ParserState state; - int unknown_count; - - GArray *key_array; - GArray *output_array; - MetaOutputKey key; - MetaOutputConfig output; - - char *output_field; - - GHashTable *configs; -} ConfigParser; - -static MetaLegacyMonitorsConfig * -legacy_config_new (void) -{ - return g_new0 (MetaLegacyMonitorsConfig, 1); -} - -static void -legacy_config_free (gpointer data) -{ - MetaLegacyMonitorsConfig *config = data; - - g_free (config->keys); - g_free (config->outputs); - g_free (config); -} - -static unsigned long -output_key_hash (const MetaOutputKey *key) -{ - return (g_str_hash (key->connector) ^ - g_str_hash (key->vendor) ^ - g_str_hash (key->product) ^ - g_str_hash (key->serial)); -} - -static gboolean -output_key_equal (const MetaOutputKey *one, - const MetaOutputKey *two) -{ - return (strcmp (one->connector, two->connector) == 0 && - strcmp (one->vendor, two->vendor) == 0 && - strcmp (one->product, two->product) == 0 && - strcmp (one->serial, two->serial) == 0); -} - -static unsigned int -legacy_config_hash (gconstpointer data) -{ - const MetaLegacyMonitorsConfig *config = data; - unsigned int i, hash; - - hash = 0; - for (i = 0; i < config->n_outputs; i++) - hash ^= output_key_hash (&config->keys[i]); - - return hash; -} - -static gboolean -legacy_config_equal (gconstpointer one, - gconstpointer two) -{ - const MetaLegacyMonitorsConfig *c_one = one; - const MetaLegacyMonitorsConfig *c_two = two; - unsigned int i; - gboolean ok; - - if (c_one->n_outputs != c_two->n_outputs) - return FALSE; - - ok = TRUE; - for (i = 0; i < c_one->n_outputs && ok; i++) - ok = output_key_equal (&c_one->keys[i], - &c_two->keys[i]); - - return ok; -} - -static void -free_output_key (MetaOutputKey *key) -{ - g_free (key->connector); - g_free (key->vendor); - g_free (key->product); - g_free (key->serial); -} - -static void -handle_start_element (GMarkupParseContext *context, - const char *element_name, - const char **attribute_names, - const char **attribute_values, - gpointer user_data, - GError **error) -{ - ConfigParser *parser = user_data; - - switch (parser->state) - { - case STATE_INITIAL: - { - char *version; - - if (strcmp (element_name, "monitors") != 0) - { - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, - "Invalid document element %s", element_name); - return; - } - - if (!g_markup_collect_attributes (element_name, - attribute_names, - attribute_values, - error, - G_MARKUP_COLLECT_STRING, - "version", &version, - G_MARKUP_COLLECT_INVALID)) - return; - - if (strcmp (version, "1") != 0) - { - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - "Invalid or unsupported version %s", version); - return; - } - - parser->state = STATE_MONITORS; - return; - } - - case STATE_MONITORS: - { - if (strcmp (element_name, "configuration") != 0) - { - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, - "Invalid toplevel element %s", element_name); - return; - } - - parser->key_array = g_array_new (FALSE, FALSE, - sizeof (MetaOutputKey)); - parser->output_array = g_array_new (FALSE, FALSE, - sizeof (MetaOutputConfig)); - parser->state = STATE_CONFIGURATION; - return; - } - - case STATE_CONFIGURATION: - { - if (strcmp (element_name, "clone") == 0 && - parser->unknown_count == 0) - { - parser->state = STATE_CLONE; - } - else if (strcmp (element_name, "output") == 0 && - parser->unknown_count == 0) - { - char *name; - - if (!g_markup_collect_attributes (element_name, - attribute_names, - attribute_values, - error, - G_MARKUP_COLLECT_STRING, - "name", &name, - G_MARKUP_COLLECT_INVALID)) - return; - - memset (&parser->key, 0, sizeof (MetaOutputKey)); - memset (&parser->output, 0, sizeof (MetaOutputConfig)); - - parser->key.connector = g_strdup (name); - parser->state = STATE_OUTPUT; - } - else - { - parser->unknown_count++; - } - - return; - } - - case STATE_OUTPUT: - { - if ((strcmp (element_name, "vendor") == 0 || - strcmp (element_name, "product") == 0 || - strcmp (element_name, "serial") == 0 || - strcmp (element_name, "width") == 0 || - strcmp (element_name, "height") == 0 || - strcmp (element_name, "rate") == 0 || - strcmp (element_name, "x") == 0 || - strcmp (element_name, "y") == 0 || - strcmp (element_name, "rotation") == 0 || - strcmp (element_name, "reflect_x") == 0 || - strcmp (element_name, "reflect_y") == 0 || - strcmp (element_name, "primary") == 0 || - strcmp (element_name, "presentation") == 0 || - strcmp (element_name, "underscanning") == 0) && - parser->unknown_count == 0) - { - parser->state = STATE_OUTPUT_FIELD; - - parser->output_field = g_strdup (element_name); - } - else - { - parser->unknown_count++; - } - - return; - } - - case STATE_CLONE: - case STATE_OUTPUT_FIELD: - { - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - "Unexpected element %s", element_name); - return; - } - - default: - g_assert_not_reached (); - } -} - -static void -handle_end_element (GMarkupParseContext *context, - const char *element_name, - gpointer user_data, - GError **error) -{ - ConfigParser *parser = user_data; - - switch (parser->state) - { - case STATE_MONITORS: - { - parser->state = STATE_INITIAL; - return; - } - - case STATE_CONFIGURATION: - { - if (strcmp (element_name, "configuration") == 0 && - parser->unknown_count == 0) - { - MetaLegacyMonitorsConfig *config = legacy_config_new (); - - g_assert (parser->key_array->len == parser->output_array->len); - - config->n_outputs = parser->key_array->len; - config->keys = (void*)g_array_free (parser->key_array, FALSE); - config->outputs = (void*)g_array_free (parser->output_array, FALSE); - - g_hash_table_replace (parser->configs, config, config); - - parser->key_array = NULL; - parser->output_array = NULL; - parser->state = STATE_MONITORS; - } - else - { - parser->unknown_count--; - - g_assert (parser->unknown_count >= 0); - } - - return; - } - - case STATE_OUTPUT: - { - if (strcmp (element_name, "output") == 0 && parser->unknown_count == 0) - { - if (parser->key.vendor == NULL || - parser->key.product == NULL || - parser->key.serial == NULL) - { - /* Disconnected output, ignore */ - free_output_key (&parser->key); - } - else - { - if (parser->output.rect.width == 0 || - parser->output.rect.height == 0) - parser->output.enabled = FALSE; - else - parser->output.enabled = TRUE; - - g_array_append_val (parser->key_array, parser->key); - g_array_append_val (parser->output_array, parser->output); - } - - memset (&parser->key, 0, sizeof (MetaOutputKey)); - memset (&parser->output, 0, sizeof (MetaOutputConfig)); - - parser->state = STATE_CONFIGURATION; - } - else - { - parser->unknown_count--; - - g_assert (parser->unknown_count >= 0); - } - - return; - } - - case STATE_CLONE: - { - parser->state = STATE_CONFIGURATION; - return; - } - - case STATE_OUTPUT_FIELD: - { - g_free (parser->output_field); - parser->output_field = NULL; - - parser->state = STATE_OUTPUT; - return; - } - - case STATE_INITIAL: - default: - g_assert_not_reached (); - } -} - -static void -read_int (const char *text, - gsize text_len, - gint *field, - GError **error) -{ - char buf[64]; - gint64 v; - char *end; - - strncpy (buf, text, text_len); - buf[MIN (63, text_len)] = 0; - - v = g_ascii_strtoll (buf, &end, 10); - - /* Limit reasonable values (actual limits are a lot smaller that these) */ - if (*end || v < 0 || v > G_MAXINT16) - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - "Expected a number, got %s", buf); - else - *field = v; -} - -static void -read_float (const char *text, - gsize text_len, - gfloat *field, - GError **error) -{ - char buf[64]; - gfloat v; - char *end; - - strncpy (buf, text, text_len); - buf[MIN (63, text_len)] = 0; - - v = g_ascii_strtod (buf, &end); - - /* Limit reasonable values (actual limits are a lot smaller that these) */ - if (*end) - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - "Expected a number, got %s", buf); - else - *field = v; -} - -static gboolean -read_bool (const char *text, - gsize text_len, - GError **error) -{ - if (strncmp (text, "no", text_len) == 0) - return FALSE; - else if (strncmp (text, "yes", text_len) == 0) - return TRUE; - else - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - "Invalid boolean value %.*s", (int)text_len, text); - - return FALSE; -} - -static gboolean -is_all_whitespace (const char *text, - gsize text_len) -{ - gsize i; - - for (i = 0; i < text_len; i++) - if (!g_ascii_isspace (text[i])) - return FALSE; - - return TRUE; -} - -static void -handle_text (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error) -{ - ConfigParser *parser = user_data; - - switch (parser->state) - { - case STATE_MONITORS: - { - if (!is_all_whitespace (text, text_len)) - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - "Unexpected content at this point"); - return; - } - - case STATE_CONFIGURATION: - { - if (parser->unknown_count == 0) - { - if (!is_all_whitespace (text, text_len)) - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - "Unexpected content at this point"); - } - else - { - /* Handling unknown element, ignore */ - } - - return; - } - - case STATE_OUTPUT: - { - if (parser->unknown_count == 0) - { - if (!is_all_whitespace (text, text_len)) - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - "Unexpected content at this point"); - } - else - { - /* Handling unknown element, ignore */ - } - return; - } - - case STATE_CLONE: - { - /* Ignore the clone flag */ - return; - } - - case STATE_OUTPUT_FIELD: - { - if (strcmp (parser->output_field, "vendor") == 0) - parser->key.vendor = g_strndup (text, text_len); - else if (strcmp (parser->output_field, "product") == 0) - parser->key.product = g_strndup (text, text_len); - else if (strcmp (parser->output_field, "serial") == 0) - parser->key.serial = g_strndup (text, text_len); - else if (strcmp (parser->output_field, "width") == 0) - read_int (text, text_len, &parser->output.rect.width, error); - else if (strcmp (parser->output_field, "height") == 0) - read_int (text, text_len, &parser->output.rect.height, error); - else if (strcmp (parser->output_field, "rate") == 0) - read_float (text, text_len, &parser->output.refresh_rate, error); - else if (strcmp (parser->output_field, "x") == 0) - read_int (text, text_len, &parser->output.rect.x, error); - else if (strcmp (parser->output_field, "y") == 0) - read_int (text, text_len, &parser->output.rect.y, error); - else if (strcmp (parser->output_field, "rotation") == 0) - { - if (strncmp (text, "normal", text_len) == 0) - parser->output.transform = META_MONITOR_TRANSFORM_NORMAL; - else if (strncmp (text, "left", text_len) == 0) - parser->output.transform = META_MONITOR_TRANSFORM_90; - else if (strncmp (text, "upside_down", text_len) == 0) - parser->output.transform = META_MONITOR_TRANSFORM_180; - else if (strncmp (text, "right", text_len) == 0) - parser->output.transform = META_MONITOR_TRANSFORM_270; - else - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - "Invalid rotation type %.*s", (int)text_len, text); - } - else if (strcmp (parser->output_field, "reflect_x") == 0) - parser->output.transform += read_bool (text, text_len, error) ? - META_MONITOR_TRANSFORM_FLIPPED : 0; - else if (strcmp (parser->output_field, "reflect_y") == 0) - { - if (read_bool (text, text_len, error)) - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - "Y reflection is not supported"); - } - else if (strcmp (parser->output_field, "primary") == 0) - parser->output.is_primary = read_bool (text, text_len, error); - else if (strcmp (parser->output_field, "presentation") == 0) - parser->output.is_presentation = read_bool (text, text_len, error); - else if (strcmp (parser->output_field, "underscanning") == 0) - parser->output.is_underscanning = read_bool (text, text_len, error); - else - g_assert_not_reached (); - return; - } - - case STATE_INITIAL: - default: - g_assert_not_reached (); - } -} - -static const GMarkupParser config_parser = { - .start_element = handle_start_element, - .end_element = handle_end_element, - .text = handle_text, -}; - -static GHashTable * -load_config_file (GFile *file, - GError **error) -{ - g_autofree char *contents = NULL; - gsize size; - g_autoptr (GMarkupParseContext) context = NULL; - ConfigParser parser = { 0 }; - - if (!g_file_load_contents (file, NULL, &contents, &size, NULL, error)) - return FALSE; - - parser.configs = g_hash_table_new_full (legacy_config_hash, - legacy_config_equal, - legacy_config_free, - NULL); - parser.state = STATE_INITIAL; - - context = g_markup_parse_context_new (&config_parser, - G_MARKUP_TREAT_CDATA_AS_TEXT | - G_MARKUP_PREFIX_ERROR_POSITION, - &parser, NULL); - if (!g_markup_parse_context_parse (context, contents, size, error)) - { - if (parser.key_array) - g_array_free (parser.key_array, TRUE); - if (parser.output_array) - g_array_free (parser.output_array, TRUE); - - free_output_key (&parser.key); - g_free (parser.output_field); - g_hash_table_destroy (parser.configs); - - return NULL; - } - - return parser.configs; -} - -static MetaMonitorConfig * -create_monitor_config (MetaOutputKey *output_key, - MetaOutputConfig *output_config, - int mode_width, - int mode_height, - GError **error) -{ - MetaMonitorModeSpec *mode_spec; - MetaMonitorSpec *monitor_spec; - MetaMonitorConfig *monitor_config; - - mode_spec = g_new0 (MetaMonitorModeSpec, 1); - *mode_spec = (MetaMonitorModeSpec) { - .width = mode_width, - .height = mode_height, - .refresh_rate = output_config->refresh_rate - }; - - if (!meta_verify_monitor_mode_spec (mode_spec, error)) - { - g_free (mode_spec); - return NULL; - } - - monitor_spec = g_new0 (MetaMonitorSpec, 1); - *monitor_spec = (MetaMonitorSpec) { - .connector = output_key->connector, - .vendor = output_key->vendor, - .product = output_key->product, - .serial = output_key->serial - }; - - monitor_config = g_new0 (MetaMonitorConfig, 1); - *monitor_config = (MetaMonitorConfig) { - .monitor_spec = monitor_spec, - .mode_spec = mode_spec, - .enable_underscanning = output_config->is_underscanning - }; - - if (!meta_verify_monitor_config (monitor_config, error)) - { - meta_monitor_config_free (monitor_config); - return NULL; - } - - return monitor_config; -} - -typedef struct _MonitorTile -{ - MetaOutputKey *output_key; - MetaOutputConfig *output_config; -} MonitorTile; - -static MetaMonitorConfig * -try_derive_tiled_monitor_config (MetaLegacyMonitorsConfig *config, - MetaOutputKey *output_key, - MetaOutputConfig *output_config, - MetaMonitorConfigStore *config_store, - MetaRectangle *out_layout, - GError **error) -{ - MonitorTile top_left_tile = { 0 }; - MonitorTile top_right_tile = { 0 }; - MonitorTile bottom_left_tile = { 0 }; - MonitorTile bottom_right_tile = { 0 }; - MonitorTile origin_tile = { 0 }; - MetaMonitorTransform transform = output_config->transform; - unsigned int i; - int max_x = 0; - int min_x = INT_MAX; - int max_y = 0; - int min_y = INT_MAX; - int mode_width = 0; - int mode_height = 0; - MetaMonitorConfig *monitor_config; - - /* - * In order to derive a monitor configuration for a tiled monitor, - * try to find the origin tile, then combine the discovered output - * tiles to given the configured transform a monitor mode. - * - * If the origin tile is not the main tile (tile always enabled - * even for non-tiled modes), this will fail, but since infermation - * about tiling is lost, there is no way to discover it. - */ - - for (i = 0; i < config->n_outputs; i++) - { - MetaOutputKey *other_output_key = &config->keys[i]; - MetaOutputConfig *other_output_config = &config->outputs[i]; - MetaRectangle *rect; - - if (strcmp (output_key->vendor, other_output_key->vendor) != 0 || - strcmp (output_key->product, other_output_key->product) != 0 || - strcmp (output_key->serial, other_output_key->serial) != 0) - continue; - - rect = &other_output_config->rect; - min_x = MIN (min_x, rect->x); - min_y = MIN (min_y, rect->y); - max_x = MAX (max_x, rect->x + rect->width); - max_y = MAX (max_y, rect->y + rect->height); - - if (min_x == rect->x && - min_y == rect->y) - { - top_left_tile = (MonitorTile) { - .output_key = other_output_key, - .output_config = other_output_config - }; - } - if (max_x == rect->x + rect->width && - min_y == rect->y) - { - top_right_tile = (MonitorTile) { - .output_key = other_output_key, - .output_config = other_output_config - }; - } - if (min_x == rect->x && - max_y == rect->y + rect->height) - { - bottom_left_tile = (MonitorTile) { - .output_key = other_output_key, - .output_config = other_output_config - }; - } - if (max_x == rect->x + rect->width && - max_y == rect->y + rect->height) - { - bottom_right_tile = (MonitorTile) { - .output_key = other_output_key, - .output_config = other_output_config - }; - } - } - - if (top_left_tile.output_key == bottom_right_tile.output_key) - { - g_set_error_literal (error, - META_MONITORS_CONFIG_MIGRATION_ERROR, - META_MONITORS_CONFIG_MIGRATION_ERROR_NOT_TILED, - "Not a tiled monitor"); - return NULL; - } - - switch (transform) - { - case META_MONITOR_TRANSFORM_NORMAL: - origin_tile = top_left_tile; - mode_width = max_x - min_x; - mode_height = max_y - min_y; - break; - case META_MONITOR_TRANSFORM_90: - origin_tile = bottom_left_tile; - mode_width = max_y - min_y; - mode_height = max_x - min_x; - break; - case META_MONITOR_TRANSFORM_180: - origin_tile = bottom_right_tile; - mode_width = max_x - min_x; - mode_height = max_y - min_y; - break; - case META_MONITOR_TRANSFORM_270: - origin_tile = top_right_tile; - mode_width = max_y - min_y; - mode_height = max_x - min_x; - break; - case META_MONITOR_TRANSFORM_FLIPPED: - origin_tile = bottom_left_tile; - mode_width = max_x - min_x; - mode_height = max_y - min_y; - break; - case META_MONITOR_TRANSFORM_FLIPPED_90: - origin_tile = bottom_right_tile; - mode_width = max_y - min_y; - mode_height = max_x - min_x; - break; - case META_MONITOR_TRANSFORM_FLIPPED_180: - origin_tile = top_right_tile; - mode_width = max_x - min_x; - mode_height = max_y - min_y; - break; - case META_MONITOR_TRANSFORM_FLIPPED_270: - origin_tile = top_left_tile; - mode_width = max_y - min_y; - mode_height = max_x - min_x; - break; - } - - g_assert (origin_tile.output_key); - g_assert (origin_tile.output_config); - - if (origin_tile.output_key != output_key) - { - g_set_error_literal (error, - META_MONITORS_CONFIG_MIGRATION_ERROR, - META_MONITORS_CONFIG_MIGRATION_ERROR_NOT_MAIN_TILE, - "Not the main tile"); - return NULL; - } - - monitor_config = create_monitor_config (origin_tile.output_key, - origin_tile.output_config, - mode_width, mode_height, - error); - if (!monitor_config) - return NULL; - - *out_layout = (MetaRectangle) { - .x = min_x, - .y = min_y, - .width = max_x - min_x, - .height = max_y - min_y - }; - - return monitor_config; -} - -static MetaMonitorConfig * -derive_monitor_config (MetaOutputKey *output_key, - MetaOutputConfig *output_config, - MetaRectangle *out_layout, - GError **error) -{ - int mode_width; - int mode_height; - MetaMonitorConfig *monitor_config; - - if (meta_monitor_transform_is_rotated (output_config->transform)) - { - mode_width = output_config->rect.height; - mode_height = output_config->rect.width; - } - else - { - mode_width = output_config->rect.width; - mode_height = output_config->rect.height; - } - - monitor_config = create_monitor_config (output_key, output_config, - mode_width, mode_height, - error); - if (!monitor_config) - return NULL; - - *out_layout = output_config->rect; - - return monitor_config; -} - -static MetaLogicalMonitorConfig * -ensure_logical_monitor (GList **logical_monitor_configs, - MetaOutputConfig *output_config, - MetaRectangle *layout) -{ - MetaLogicalMonitorConfig *new_logical_monitor_config; - GList *l; - - for (l = *logical_monitor_configs; l; l = l->next) - { - MetaLogicalMonitorConfig *logical_monitor_config = l->data; - - if (meta_rectangle_equal (&logical_monitor_config->layout, layout)) - return logical_monitor_config; - } - - new_logical_monitor_config = g_new0 (MetaLogicalMonitorConfig, 1); - *new_logical_monitor_config = (MetaLogicalMonitorConfig) { - .layout = *layout, - .is_primary = output_config->is_primary, - .is_presentation = output_config->is_presentation, - .transform = output_config->transform, - .scale = -1.0, - }; - - *logical_monitor_configs = g_list_append (*logical_monitor_configs, - new_logical_monitor_config); - - return new_logical_monitor_config; -} - -static GList * -derive_logical_monitor_configs (MetaLegacyMonitorsConfig *config, - MetaMonitorConfigStore *config_store, - GError **error) -{ - GList *logical_monitor_configs = NULL; - unsigned int i; - - for (i = 0; i < config->n_outputs; i++) - { - MetaOutputKey *output_key = &config->keys[i]; - MetaOutputConfig *output_config = &config->outputs[i]; - MetaMonitorConfig *monitor_config = NULL; - MetaRectangle layout; - MetaLogicalMonitorConfig *logical_monitor_config; - - if (!output_config->enabled) - continue; - - if (output_key->vendor && - g_strcmp0 (output_key->vendor, "unknown") != 0 && - output_key->product && - g_strcmp0 (output_key->product, "unknown") != 0 && - output_key->serial && - g_strcmp0 (output_key->serial, "unknown") != 0) - { - monitor_config = try_derive_tiled_monitor_config (config, - output_key, - output_config, - config_store, - &layout, - error); - if (!monitor_config) - { - if ((*error)->domain == META_MONITORS_CONFIG_MIGRATION_ERROR) - { - int error_code = (*error)->code; - - g_clear_error (error); - - switch (error_code) - { - case META_MONITORS_CONFIG_MIGRATION_ERROR_NOT_TILED: - break; - case META_MONITORS_CONFIG_MIGRATION_ERROR_NOT_MAIN_TILE: - continue; - } - } - else - { - g_list_free_full (logical_monitor_configs, - (GDestroyNotify) meta_logical_monitor_config_free); - return NULL; - } - } - } - - if (!monitor_config) - monitor_config = derive_monitor_config (output_key, output_config, - &layout, - error); - - if (!monitor_config) - { - g_list_free_full (logical_monitor_configs, - (GDestroyNotify) meta_logical_monitor_config_free); - return NULL; - } - - logical_monitor_config = - ensure_logical_monitor (&logical_monitor_configs, - output_config, &layout); - - logical_monitor_config->monitor_configs = - g_list_append (logical_monitor_config->monitor_configs, monitor_config); - } - - if (!logical_monitor_configs) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Empty configuration"); - return NULL; - } - - return logical_monitor_configs; -} - -static char * -generate_config_name (MetaLegacyMonitorsConfig *config) -{ - char **output_strings; - unsigned int i; - char *key_name; - - output_strings = g_new0 (char *, config->n_outputs + 1); - for (i = 0; i < config->n_outputs; i++) - { - MetaOutputKey *output_key = &config->keys[i]; - - output_strings[i] = g_strdup_printf ("%s:%s:%s:%s", - output_key->connector, - output_key->vendor, - output_key->product, - output_key->serial); - } - - key_name = g_strjoinv (", ", output_strings); - - g_strfreev (output_strings); - - return key_name; -} - -static GList * -find_disabled_monitor_specs (MetaLegacyMonitorsConfig *legacy_config) -{ - GList *disabled_monitors = NULL; - unsigned int i; - - for (i = 0; i < legacy_config->n_outputs; i++) - { - MetaOutputKey *output_key = &legacy_config->keys[i]; - MetaOutputConfig *output_config = &legacy_config->outputs[i]; - MetaMonitorSpec *monitor_spec; - - if (output_config->enabled) - continue; - - monitor_spec = g_new0 (MetaMonitorSpec, 1); - *monitor_spec = (MetaMonitorSpec) { - .connector = output_key->connector, - .vendor = output_key->vendor, - .product = output_key->product, - .serial = output_key->serial - }; - - disabled_monitors = g_list_prepend (disabled_monitors, monitor_spec); - } - - return disabled_monitors; -} - -static void -migrate_config (gpointer key, - gpointer value, - gpointer user_data) -{ - MetaLegacyMonitorsConfig *legacy_config = key; - MetaMonitorConfigStore *config_store = user_data; - MetaMonitorManager *monitor_manager = - meta_monitor_config_store_get_monitor_manager (config_store); - GList *logical_monitor_configs; - MetaLogicalMonitorLayoutMode layout_mode; - GError *error = NULL; - GList *disabled_monitor_specs; - MetaMonitorsConfig *config; - - logical_monitor_configs = derive_logical_monitor_configs (legacy_config, - config_store, - &error); - if (!logical_monitor_configs) - { - g_autofree char *config_name = NULL; - - config_name = generate_config_name (legacy_config); - g_warning ("Failed to migrate monitor configuration for %s: %s", - config_name, error->message); - return; - } - - disabled_monitor_specs = find_disabled_monitor_specs (legacy_config); - - layout_mode = META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL; - config = meta_monitors_config_new_full (logical_monitor_configs, - disabled_monitor_specs, - layout_mode, - META_MONITORS_CONFIG_FLAG_MIGRATED); - if (!meta_verify_monitors_config (config, monitor_manager, &error)) - { - g_autofree char *config_name = NULL; - - config_name = generate_config_name (legacy_config); - g_warning ("Ignoring invalid monitor configuration for %s: %s", - config_name, error->message); - g_object_unref (config); - return; - } - - meta_monitor_config_store_add (config_store, config); -} - -gboolean -meta_migrate_old_monitors_config (MetaMonitorConfigStore *config_store, - GFile *in_file, - GError **error) -{ - g_autoptr (GHashTable) configs = NULL; - - configs = load_config_file (in_file, error); - if (!configs) - return FALSE; - - g_hash_table_foreach (configs, migrate_config, config_store); - - return TRUE; -} - -gboolean -meta_migrate_old_user_monitors_config (MetaMonitorConfigStore *config_store, - GError **error) -{ - g_autofree char *backup_path = NULL; - g_autoptr (GFile) backup_file = NULL; - g_autofree char *user_file_path = NULL; - g_autoptr (GFile) user_file = NULL; - - user_file_path = g_build_filename (g_get_user_config_dir (), - "monitors.xml", - NULL); - user_file = g_file_new_for_path (user_file_path); - backup_path = g_build_filename (g_get_user_config_dir (), - "monitors-v1-backup.xml", - NULL); - backup_file = g_file_new_for_path (backup_path); - - if (!g_file_copy (user_file, backup_file, - G_FILE_COPY_OVERWRITE | G_FILE_COPY_BACKUP, - NULL, NULL, NULL, - error)) - { - g_warning ("Failed to make a backup of monitors.xml: %s", - (*error)->message); - g_clear_error (error); - } - - return meta_migrate_old_monitors_config (config_store, user_file, error); -} - -gboolean -meta_finish_monitors_config_migration (MetaMonitorManager *monitor_manager, - MetaMonitorsConfig *config, - GError **error) -{ - MetaMonitorConfigManager *config_manager = monitor_manager->config_manager; - MetaMonitorConfigStore *config_store = - meta_monitor_config_manager_get_store (config_manager); - GList *l; - - for (l = config->logical_monitor_configs; l; l = l->next) - { - MetaLogicalMonitorConfig *logical_monitor_config = l->data; - MetaMonitorConfig *monitor_config; - MetaMonitorSpec *monitor_spec; - MetaMonitor *monitor; - MetaMonitorModeSpec *monitor_mode_spec; - MetaMonitorMode *monitor_mode; - float scale; - - monitor_config = logical_monitor_config->monitor_configs->data; - monitor_spec = monitor_config->monitor_spec; - monitor = meta_monitor_manager_get_monitor_from_spec (monitor_manager, - monitor_spec); - monitor_mode_spec = monitor_config->mode_spec; - monitor_mode = meta_monitor_get_mode_from_spec (monitor, - monitor_mode_spec); - if (!monitor_mode) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Mode not available on monitor"); - return FALSE; - } - - scale = meta_monitor_calculate_mode_scale (monitor, monitor_mode); - - logical_monitor_config->scale = scale; - } - - config->layout_mode = - meta_monitor_manager_get_default_layout_mode (monitor_manager); - config->flags &= ~META_MONITORS_CONFIG_FLAG_MIGRATED; - - if (!meta_verify_monitors_config (config, monitor_manager, error)) - return FALSE; - - meta_monitor_config_store_add (config_store, config); - - return TRUE; -} diff --git a/src/backends/meta-monitor-config-migration.h b/src/backends/meta-monitor-config-migration.h deleted file mode 100644 index 7b338ace2..000000000 --- a/src/backends/meta-monitor-config-migration.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 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_MONITOR_CONFIG_MIGRATION_H -#define META_MONITOR_CONFIG_MIGRATION_H - -#include "backends/meta-monitor-manager-private.h" - -META_EXPORT_TEST -gboolean meta_migrate_old_monitors_config (MetaMonitorConfigStore *config_store, - GFile *in_file, - GError **error); - -META_EXPORT_TEST -gboolean meta_migrate_old_user_monitors_config (MetaMonitorConfigStore *config_store, - GError **error); - -META_EXPORT_TEST -gboolean meta_finish_monitors_config_migration (MetaMonitorManager *monitor_manager, - MetaMonitorsConfig *config, - GError **error); - -#endif /* META_MONITOR_CONFIG_MIGRATION_H */ diff --git a/src/backends/meta-monitor-config-store.c b/src/backends/meta-monitor-config-store.c deleted file mode 100644 index 4dd357a15..000000000 --- a/src/backends/meta-monitor-config-store.c +++ /dev/null @@ -1,1683 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 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. - */ - -#include "config.h" - -#include "backends/meta-monitor-config-store.h" - -#include -#include - -#include "backends/meta-monitor-config-manager.h" -#include "backends/meta-monitor-config-migration.h" - -#define MONITORS_CONFIG_XML_FORMAT_VERSION 2 - -#define QUOTE1(a) #a -#define QUOTE(a) QUOTE1(a) - -/* - * Example configuration: - * - * - * - * - * 0 - * 0 - * 1 - * - * - * LVDS1 - * Vendor A - * Product A - * Serial A - * - * - * 1920 - * 1080 - * 60.049972534179688 - * interlace - * - * - * - * right - * no - * - * yes - * no - * - * - * 1920 - * 1080 - * - * - * LVDS2 - * Vendor B - * Product B - * Serial B - * - * - * 1920 - * 1080 - * 60.049972534179688 - * - * yes - * - * yes - * - * - * - * LVDS3 - * Vendor C - * Product C - * Serial C - * - * - * - * - * - */ - -enum -{ - PROP_0, - - PROP_MONITOR_MANAGER, - - PROP_LAST -}; - -static GParamSpec *obj_props[PROP_LAST]; - -struct _MetaMonitorConfigStore -{ - GObject parent; - - MetaMonitorManager *monitor_manager; - - GHashTable *configs; - - GCancellable *save_cancellable; - - GFile *user_file; - GFile *custom_read_file; - GFile *custom_write_file; -}; - -#define META_MONITOR_CONFIG_STORE_ERROR (meta_monitor_config_store_error_quark ()) -static GQuark meta_monitor_config_store_error_quark (void); - -enum -{ - META_MONITOR_CONFIG_STORE_ERROR_NEEDS_MIGRATION -}; - -G_DEFINE_QUARK (meta-monitor-config-store-error-quark, - meta_monitor_config_store_error) - -typedef enum -{ - STATE_INITIAL, - STATE_MONITORS, - STATE_CONFIGURATION, - STATE_MIGRATED, - STATE_LOGICAL_MONITOR, - STATE_LOGICAL_MONITOR_X, - STATE_LOGICAL_MONITOR_Y, - STATE_LOGICAL_MONITOR_PRIMARY, - STATE_LOGICAL_MONITOR_PRESENTATION, - STATE_LOGICAL_MONITOR_SCALE, - STATE_TRANSFORM, - STATE_TRANSFORM_ROTATION, - STATE_TRANSFORM_FLIPPED, - STATE_MONITOR, - STATE_MONITOR_SPEC, - STATE_MONITOR_SPEC_CONNECTOR, - STATE_MONITOR_SPEC_VENDOR, - STATE_MONITOR_SPEC_PRODUCT, - STATE_MONITOR_SPEC_SERIAL, - STATE_MONITOR_MODE, - STATE_MONITOR_MODE_WIDTH, - STATE_MONITOR_MODE_HEIGHT, - STATE_MONITOR_MODE_RATE, - STATE_MONITOR_MODE_FLAG, - STATE_MONITOR_UNDERSCANNING, - STATE_DISABLED, -} ParserState; - -typedef struct -{ - ParserState state; - MetaMonitorConfigStore *config_store; - - ParserState monitor_spec_parent_state; - - gboolean current_was_migrated; - GList *current_logical_monitor_configs; - MetaMonitorSpec *current_monitor_spec; - gboolean current_transform_flipped; - MetaMonitorTransform current_transform; - MetaMonitorModeSpec *current_monitor_mode_spec; - MetaMonitorConfig *current_monitor_config; - MetaLogicalMonitorConfig *current_logical_monitor_config; - GList *current_disabled_monitor_specs; - - MetaMonitorsConfigFlag extra_config_flags; -} ConfigParser; - -G_DEFINE_TYPE (MetaMonitorConfigStore, meta_monitor_config_store, - G_TYPE_OBJECT) - -static void -handle_start_element (GMarkupParseContext *context, - const char *element_name, - const char **attribute_names, - const char **attribute_values, - gpointer user_data, - GError **error) -{ - ConfigParser *parser = user_data; - - switch (parser->state) - { - case STATE_INITIAL: - { - char *version; - - if (!g_str_equal (element_name, "monitors")) - { - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, - "Invalid document element '%s'", element_name); - return; - } - - if (!g_markup_collect_attributes (element_name, attribute_names, attribute_values, - error, - G_MARKUP_COLLECT_STRING, "version", &version, - G_MARKUP_COLLECT_INVALID)) - { - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - "Missing config file format version"); - } - - if (g_str_equal (version, "1")) - { - g_set_error_literal (error, - META_MONITOR_CONFIG_STORE_ERROR, - META_MONITOR_CONFIG_STORE_ERROR_NEEDS_MIGRATION, - "monitors.xml has the old format"); - return; - } - - if (!g_str_equal (version, QUOTE (MONITORS_CONFIG_XML_FORMAT_VERSION))) - { - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - "Invalid or unsupported version '%s'", version); - return; - } - - parser->state = STATE_MONITORS; - return; - } - - case STATE_MONITORS: - { - if (!g_str_equal (element_name, "configuration")) - { - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, - "Invalid toplevel element '%s'", element_name); - return; - } - - parser->state = STATE_CONFIGURATION; - parser->current_was_migrated = FALSE; - - return; - } - - case STATE_CONFIGURATION: - { - if (g_str_equal (element_name, "logicalmonitor")) - { - parser->current_logical_monitor_config = - g_new0 (MetaLogicalMonitorConfig, 1); - - parser->state = STATE_LOGICAL_MONITOR; - } - else if (g_str_equal (element_name, "migrated")) - { - parser->current_was_migrated = TRUE; - - parser->state = STATE_MIGRATED; - } - else if (g_str_equal (element_name, "disabled")) - { - parser->state = STATE_DISABLED; - } - else - { - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, - "Invalid configuration element '%s'", element_name); - return; - } - - return; - } - - case STATE_MIGRATED: - { - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, - "Unexpected element '%s'", element_name); - return; - } - - case STATE_LOGICAL_MONITOR: - { - if (g_str_equal (element_name, "x")) - { - parser->state = STATE_LOGICAL_MONITOR_X; - } - else if (g_str_equal (element_name, "y")) - { - parser->state = STATE_LOGICAL_MONITOR_Y; - } - else if (g_str_equal (element_name, "scale")) - { - parser->state = STATE_LOGICAL_MONITOR_SCALE; - } - else if (g_str_equal (element_name, "primary")) - { - parser->state = STATE_LOGICAL_MONITOR_PRIMARY; - } - else if (g_str_equal (element_name, "presentation")) - { - parser->state = STATE_LOGICAL_MONITOR_PRESENTATION; - } - else if (g_str_equal (element_name, "transform")) - { - parser->state = STATE_TRANSFORM; - } - else if (g_str_equal (element_name, "monitor")) - { - parser->current_monitor_config = g_new0 (MetaMonitorConfig, 1); - - parser->state = STATE_MONITOR; - } - else - { - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, - "Invalid monitor logicalmonitor element '%s'", element_name); - return; - } - - return; - } - - case STATE_LOGICAL_MONITOR_X: - case STATE_LOGICAL_MONITOR_Y: - case STATE_LOGICAL_MONITOR_SCALE: - case STATE_LOGICAL_MONITOR_PRIMARY: - case STATE_LOGICAL_MONITOR_PRESENTATION: - { - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, - "Invalid logical monitor element '%s'", element_name); - return; - } - - case STATE_TRANSFORM: - { - if (g_str_equal (element_name, "rotation")) - { - parser->state = STATE_TRANSFORM_ROTATION; - } - else if (g_str_equal (element_name, "flipped")) - { - parser->state = STATE_TRANSFORM_FLIPPED; - } - - return; - } - - case STATE_TRANSFORM_ROTATION: - case STATE_TRANSFORM_FLIPPED: - { - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, - "Invalid transform element '%s'", element_name); - return; - } - - case STATE_MONITOR: - { - if (g_str_equal (element_name, "monitorspec")) - { - parser->current_monitor_spec = g_new0 (MetaMonitorSpec, 1); - parser->monitor_spec_parent_state = STATE_MONITOR; - parser->state = STATE_MONITOR_SPEC; - } - else if (g_str_equal (element_name, "mode")) - { - parser->current_monitor_mode_spec = g_new0 (MetaMonitorModeSpec, 1); - - parser->state = STATE_MONITOR_MODE; - } - else if (g_str_equal (element_name, "underscanning")) - { - parser->state = STATE_MONITOR_UNDERSCANNING; - } - else - { - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, - "Invalid monitor element '%s'", element_name); - return; - } - - return; - } - - case STATE_MONITOR_SPEC: - { - if (g_str_equal (element_name, "connector")) - { - parser->state = STATE_MONITOR_SPEC_CONNECTOR; - } - else if (g_str_equal (element_name, "vendor")) - { - parser->state = STATE_MONITOR_SPEC_VENDOR; - } - else if (g_str_equal (element_name, "product")) - { - parser->state = STATE_MONITOR_SPEC_PRODUCT; - } - else if (g_str_equal (element_name, "serial")) - { - parser->state = STATE_MONITOR_SPEC_SERIAL; - } - else - { - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, - "Invalid monitor spec element '%s'", element_name); - return; - } - - return; - } - - case STATE_MONITOR_SPEC_CONNECTOR: - case STATE_MONITOR_SPEC_VENDOR: - case STATE_MONITOR_SPEC_PRODUCT: - case STATE_MONITOR_SPEC_SERIAL: - { - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, - "Invalid monitor spec element '%s'", element_name); - return; - } - - case STATE_MONITOR_MODE: - { - if (g_str_equal (element_name, "width")) - { - parser->state = STATE_MONITOR_MODE_WIDTH; - } - else if (g_str_equal (element_name, "height")) - { - parser->state = STATE_MONITOR_MODE_HEIGHT; - } - else if (g_str_equal (element_name, "rate")) - { - parser->state = STATE_MONITOR_MODE_RATE; - } - else if (g_str_equal (element_name, "flag")) - { - parser->state = STATE_MONITOR_MODE_FLAG; - } - else - { - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, - "Invalid mode element '%s'", element_name); - return; - } - - return; - } - - case STATE_MONITOR_MODE_WIDTH: - case STATE_MONITOR_MODE_HEIGHT: - case STATE_MONITOR_MODE_RATE: - case STATE_MONITOR_MODE_FLAG: - { - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, - "Invalid mode sub element '%s'", element_name); - return; - } - - case STATE_MONITOR_UNDERSCANNING: - { - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, - "Invalid element '%s' under underscanning", element_name); - return; - } - - case STATE_DISABLED: - { - if (!g_str_equal (element_name, "monitorspec")) - { - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, - "Invalid element '%s' under disabled", element_name); - return; - } - - parser->current_monitor_spec = g_new0 (MetaMonitorSpec, 1); - parser->monitor_spec_parent_state = STATE_DISABLED; - parser->state = STATE_MONITOR_SPEC; - - return; - } - } -} - -static gboolean -derive_logical_monitor_layout (MetaLogicalMonitorConfig *logical_monitor_config, - MetaLogicalMonitorLayoutMode layout_mode, - GError **error) -{ - MetaMonitorConfig *monitor_config; - int mode_width, mode_height; - int width = 0, height = 0; - GList *l; - - monitor_config = logical_monitor_config->monitor_configs->data; - mode_width = monitor_config->mode_spec->width; - mode_height = monitor_config->mode_spec->height; - - for (l = logical_monitor_config->monitor_configs->next; l; l = l->next) - { - monitor_config = l->data; - - if (monitor_config->mode_spec->width != mode_width || - monitor_config->mode_spec->height != mode_height) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Monitors in logical monitor incompatible"); - return FALSE; - } - } - - if (meta_monitor_transform_is_rotated (logical_monitor_config->transform)) - { - width = mode_height; - height = mode_width; - } - else - { - width = mode_width; - height = mode_height; - } - - switch (layout_mode) - { - case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL: - width = roundf (width / logical_monitor_config->scale); - height = roundf (height / logical_monitor_config->scale); - break; - case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL: - break; - } - - logical_monitor_config->layout.width = width; - logical_monitor_config->layout.height = height; - - return TRUE; -} - -static void -finish_monitor_spec (ConfigParser *parser) -{ - switch (parser->monitor_spec_parent_state) - { - case STATE_MONITOR: - { - parser->current_monitor_config->monitor_spec = - parser->current_monitor_spec; - parser->current_monitor_spec = NULL; - - return; - } - case STATE_DISABLED: - { - parser->current_disabled_monitor_specs = - g_list_prepend (parser->current_disabled_monitor_specs, - parser->current_monitor_spec); - parser->current_monitor_spec = NULL; - - return; - } - - default: - g_assert_not_reached (); - } -} - -static void -handle_end_element (GMarkupParseContext *context, - const char *element_name, - gpointer user_data, - GError **error) -{ - ConfigParser *parser = user_data; - - switch (parser->state) - { - case STATE_LOGICAL_MONITOR_X: - case STATE_LOGICAL_MONITOR_Y: - case STATE_LOGICAL_MONITOR_SCALE: - case STATE_LOGICAL_MONITOR_PRIMARY: - case STATE_LOGICAL_MONITOR_PRESENTATION: - { - parser->state = STATE_LOGICAL_MONITOR; - return; - } - - case STATE_TRANSFORM: - { - g_assert (g_str_equal (element_name, "transform")); - - parser->current_logical_monitor_config->transform = - parser->current_transform; - if (parser->current_transform_flipped) - { - parser->current_logical_monitor_config->transform += - META_MONITOR_TRANSFORM_FLIPPED; - } - - parser->current_transform = META_MONITOR_TRANSFORM_NORMAL; - parser->current_transform_flipped = FALSE; - - parser->state = STATE_LOGICAL_MONITOR; - return; - } - - case STATE_TRANSFORM_ROTATION: - case STATE_TRANSFORM_FLIPPED: - { - parser->state = STATE_TRANSFORM; - return; - } - - case STATE_MONITOR_SPEC_CONNECTOR: - case STATE_MONITOR_SPEC_VENDOR: - case STATE_MONITOR_SPEC_PRODUCT: - case STATE_MONITOR_SPEC_SERIAL: - { - parser->state = STATE_MONITOR_SPEC; - return; - } - - case STATE_MONITOR_SPEC: - { - g_assert (g_str_equal (element_name, "monitorspec")); - - if (!meta_verify_monitor_spec (parser->current_monitor_spec, error)) - return; - - finish_monitor_spec (parser); - - parser->state = parser->monitor_spec_parent_state; - return; - } - - case STATE_MONITOR_MODE_WIDTH: - case STATE_MONITOR_MODE_HEIGHT: - case STATE_MONITOR_MODE_RATE: - case STATE_MONITOR_MODE_FLAG: - { - parser->state = STATE_MONITOR_MODE; - return; - } - - case STATE_MONITOR_MODE: - { - g_assert (g_str_equal (element_name, "mode")); - - if (!meta_verify_monitor_mode_spec (parser->current_monitor_mode_spec, - error)) - return; - - parser->current_monitor_config->mode_spec = - parser->current_monitor_mode_spec; - parser->current_monitor_mode_spec = NULL; - - parser->state = STATE_MONITOR; - return; - } - - case STATE_MONITOR_UNDERSCANNING: - { - g_assert (g_str_equal (element_name, "underscanning")); - - parser->state = STATE_MONITOR; - return; - } - - case STATE_MONITOR: - { - MetaLogicalMonitorConfig *logical_monitor_config; - - g_assert (g_str_equal (element_name, "monitor")); - - if (!meta_verify_monitor_config (parser->current_monitor_config, error)) - return; - - logical_monitor_config = parser->current_logical_monitor_config; - - logical_monitor_config->monitor_configs = - g_list_append (logical_monitor_config->monitor_configs, - parser->current_monitor_config); - parser->current_monitor_config = NULL; - - parser->state = STATE_LOGICAL_MONITOR; - return; - } - - case STATE_LOGICAL_MONITOR: - { - MetaLogicalMonitorConfig *logical_monitor_config = - parser->current_logical_monitor_config; - - g_assert (g_str_equal (element_name, "logicalmonitor")); - - if (parser->current_was_migrated) - logical_monitor_config->scale = -1; - else if (logical_monitor_config->scale == 0) - logical_monitor_config->scale = 1; - - parser->current_logical_monitor_configs = - g_list_append (parser->current_logical_monitor_configs, - logical_monitor_config); - parser->current_logical_monitor_config = NULL; - - parser->state = STATE_CONFIGURATION; - return; - } - - case STATE_MIGRATED: - { - g_assert (g_str_equal (element_name, "migrated")); - - parser->state = STATE_CONFIGURATION; - return; - } - - case STATE_DISABLED: - { - g_assert (g_str_equal (element_name, "disabled")); - - parser->state = STATE_CONFIGURATION; - return; - } - - case STATE_CONFIGURATION: - { - MetaMonitorConfigStore *store = parser->config_store; - MetaMonitorsConfig *config; - GList *l; - MetaLogicalMonitorLayoutMode layout_mode; - MetaMonitorsConfigFlag config_flags = META_MONITORS_CONFIG_FLAG_NONE; - - g_assert (g_str_equal (element_name, "configuration")); - - if (parser->current_was_migrated) - layout_mode = META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL; - else - layout_mode = - meta_monitor_manager_get_default_layout_mode (store->monitor_manager); - - for (l = parser->current_logical_monitor_configs; l; l = l->next) - { - MetaLogicalMonitorConfig *logical_monitor_config = l->data; - - if (!derive_logical_monitor_layout (logical_monitor_config, - layout_mode, - error)) - return; - - if (!meta_verify_logical_monitor_config (logical_monitor_config, - layout_mode, - store->monitor_manager, - error)) - return; - } - - if (parser->current_was_migrated) - config_flags |= META_MONITORS_CONFIG_FLAG_MIGRATED; - - config_flags |= parser->extra_config_flags; - - config = - meta_monitors_config_new_full (parser->current_logical_monitor_configs, - parser->current_disabled_monitor_specs, - layout_mode, - config_flags); - - parser->current_logical_monitor_configs = NULL; - parser->current_disabled_monitor_specs = NULL; - - if (!meta_verify_monitors_config (config, store->monitor_manager, - error)) - { - g_object_unref (config); - return; - } - - g_hash_table_replace (parser->config_store->configs, - config->key, config); - - parser->state = STATE_MONITORS; - return; - } - - case STATE_MONITORS: - { - g_assert (g_str_equal (element_name, "monitors")); - - parser->state = STATE_INITIAL; - return; - } - - case STATE_INITIAL: - { - g_assert_not_reached (); - } - } -} - -static gboolean -read_int (const char *text, - gsize text_len, - gint *out_value, - GError **error) -{ - char buf[64]; - int64_t value; - char *end; - - strncpy (buf, text, text_len); - buf[MIN (63, text_len)] = 0; - - value = g_ascii_strtoll (buf, &end, 10); - - if (*end || value < 0 || value > G_MAXINT16) - { - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - "Expected a number, got %s", buf); - return FALSE; - } - else - { - *out_value = value; - return TRUE; - } -} - -static gboolean -read_float (const char *text, - gsize text_len, - float *out_value, - GError **error) -{ - char buf[64]; - float value; - char *end; - - strncpy (buf, text, text_len); - buf[MIN (63, text_len)] = 0; - - value = g_ascii_strtod (buf, &end); - - if (*end) - { - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - "Expected a number, got %s", buf); - return FALSE; - } - else - { - *out_value = value; - return TRUE; - } -} - -static gboolean -read_bool (const char *text, - gsize text_len, - gboolean *out_value, - GError **error) -{ - if (strncmp (text, "no", text_len) == 0) - { - *out_value = FALSE; - return TRUE; - } - else if (strncmp (text, "yes", text_len) == 0) - { - *out_value = TRUE; - return TRUE; - } - else - { - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - "Invalid boolean value '%.*s'", (int) text_len, text); - return FALSE; - } -} - -static gboolean -is_all_whitespace (const char *text, - gsize text_len) -{ - gsize i; - - for (i = 0; i < text_len; i++) - if (!g_ascii_isspace (text[i])) - return FALSE; - - return TRUE; -} - -static void -handle_text (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error) -{ - ConfigParser *parser = user_data; - - switch (parser->state) - { - case STATE_INITIAL: - case STATE_MONITORS: - case STATE_CONFIGURATION: - case STATE_MIGRATED: - case STATE_LOGICAL_MONITOR: - case STATE_MONITOR: - case STATE_MONITOR_SPEC: - case STATE_MONITOR_MODE: - case STATE_TRANSFORM: - case STATE_DISABLED: - { - if (!is_all_whitespace (text, text_len)) - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - "Unexpected content at this point"); - return; - } - - case STATE_MONITOR_SPEC_CONNECTOR: - { - parser->current_monitor_spec->connector = g_strndup (text, text_len); - return; - } - - case STATE_MONITOR_SPEC_VENDOR: - { - parser->current_monitor_spec->vendor = g_strndup (text, text_len); - return; - } - - case STATE_MONITOR_SPEC_PRODUCT: - { - parser->current_monitor_spec->product = g_strndup (text, text_len); - return; - } - - case STATE_MONITOR_SPEC_SERIAL: - { - parser->current_monitor_spec->serial = g_strndup (text, text_len); - return; - } - - case STATE_LOGICAL_MONITOR_X: - { - read_int (text, text_len, - &parser->current_logical_monitor_config->layout.x, error); - return; - } - - case STATE_LOGICAL_MONITOR_Y: - { - read_int (text, text_len, - &parser->current_logical_monitor_config->layout.y, error); - return; - } - - case STATE_LOGICAL_MONITOR_SCALE: - { - if (!read_float (text, text_len, - &parser->current_logical_monitor_config->scale, error)) - return; - - if (parser->current_logical_monitor_config->scale <= 0.0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Logical monitor scale '%g' invalid", - parser->current_logical_monitor_config->scale); - return; - } - - return; - } - - case STATE_LOGICAL_MONITOR_PRIMARY: - { - read_bool (text, text_len, - &parser->current_logical_monitor_config->is_primary, - error); - return; - } - - case STATE_LOGICAL_MONITOR_PRESENTATION: - { - read_bool (text, text_len, - &parser->current_logical_monitor_config->is_presentation, - error); - return; - } - - case STATE_TRANSFORM_ROTATION: - { - if (strncmp (text, "normal", text_len) == 0) - parser->current_transform = META_MONITOR_TRANSFORM_NORMAL; - else if (strncmp (text, "left", text_len) == 0) - parser->current_transform = META_MONITOR_TRANSFORM_90; - else if (strncmp (text, "upside_down", text_len) == 0) - parser->current_transform = META_MONITOR_TRANSFORM_180; - else if (strncmp (text, "right", text_len) == 0) - parser->current_transform = META_MONITOR_TRANSFORM_270; - else - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - "Invalid rotation type %.*s", (int)text_len, text); - - return; - } - - case STATE_TRANSFORM_FLIPPED: - { - read_bool (text, text_len, - &parser->current_transform_flipped, - error); - return; - } - - case STATE_MONITOR_MODE_WIDTH: - { - read_int (text, text_len, - &parser->current_monitor_mode_spec->width, - error); - return; - } - - case STATE_MONITOR_MODE_HEIGHT: - { - read_int (text, text_len, - &parser->current_monitor_mode_spec->height, - error); - return; - } - - case STATE_MONITOR_MODE_RATE: - { - read_float (text, text_len, - &parser->current_monitor_mode_spec->refresh_rate, - error); - return; - } - - case STATE_MONITOR_MODE_FLAG: - { - if (strncmp (text, "interlace", text_len) == 0) - { - parser->current_monitor_mode_spec->flags |= - META_CRTC_MODE_FLAG_INTERLACE; - } - else - { - g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, - "Invalid mode flag %.*s", (int) text_len, text); - } - - return; - } - - case STATE_MONITOR_UNDERSCANNING: - { - read_bool (text, text_len, - &parser->current_monitor_config->enable_underscanning, - error); - return; - } - } -} - -static const GMarkupParser config_parser = { - .start_element = handle_start_element, - .end_element = handle_end_element, - .text = handle_text -}; - -static gboolean -read_config_file (MetaMonitorConfigStore *config_store, - GFile *file, - MetaMonitorsConfigFlag extra_config_flags, - GError **error) -{ - char *buffer; - gsize size; - ConfigParser parser; - GMarkupParseContext *parse_context; - - if (!g_file_load_contents (file, NULL, &buffer, &size, NULL, error)) - return FALSE; - - parser = (ConfigParser) { - .state = STATE_INITIAL, - .config_store = config_store, - .extra_config_flags = extra_config_flags, - }; - - parse_context = g_markup_parse_context_new (&config_parser, - G_MARKUP_TREAT_CDATA_AS_TEXT | - G_MARKUP_PREFIX_ERROR_POSITION, - &parser, NULL); - if (!g_markup_parse_context_parse (parse_context, buffer, size, error)) - { - g_list_free_full (parser.current_logical_monitor_configs, - (GDestroyNotify) meta_logical_monitor_config_free); - g_clear_pointer (&parser.current_monitor_spec, - meta_monitor_spec_free); - g_free (parser.current_monitor_mode_spec); - g_clear_pointer (&parser.current_monitor_config, - meta_monitor_config_free); - g_clear_pointer (&parser.current_logical_monitor_config, - meta_logical_monitor_config_free); - return FALSE; - } - - g_markup_parse_context_free (parse_context); - g_free (buffer); - - return TRUE; -} - -MetaMonitorsConfig * -meta_monitor_config_store_lookup (MetaMonitorConfigStore *config_store, - MetaMonitorsConfigKey *key) -{ - return META_MONITORS_CONFIG (g_hash_table_lookup (config_store->configs, - key)); -} - -static void -append_monitor_spec (GString *buffer, - MetaMonitorSpec *monitor_spec, - const char *indentation) -{ - char *escaped; - - g_string_append_printf (buffer, "%s\n", indentation); - - escaped = g_markup_escape_text (monitor_spec->connector, -1); - g_string_append_printf (buffer, "%s %s\n", - indentation, - escaped); - g_free (escaped); - - escaped = g_markup_escape_text (monitor_spec->vendor, -1); - g_string_append_printf (buffer, "%s %s\n", - indentation, - escaped); - g_free (escaped); - - escaped = g_markup_escape_text (monitor_spec->product, -1); - g_string_append_printf (buffer, "%s %s\n", - indentation, - escaped); - g_free (escaped); - - escaped = g_markup_escape_text (monitor_spec->serial, -1); - g_string_append_printf (buffer, "%s %s\n", - indentation, - escaped); - g_free (escaped); - - g_string_append_printf (buffer, "%s\n", indentation); -} - -static void -append_monitors (GString *buffer, - GList *monitor_configs) -{ - GList *l; - - for (l = monitor_configs; l; l = l->next) - { - MetaMonitorConfig *monitor_config = l->data; - char rate_str[G_ASCII_DTOSTR_BUF_SIZE]; - - g_ascii_dtostr (rate_str, sizeof (rate_str), - monitor_config->mode_spec->refresh_rate); - - g_string_append (buffer, " \n"); - append_monitor_spec (buffer, monitor_config->monitor_spec, " "); - g_string_append (buffer, " \n"); - g_string_append_printf (buffer, " %d\n", - monitor_config->mode_spec->width); - g_string_append_printf (buffer, " %d\n", - monitor_config->mode_spec->height); - g_string_append_printf (buffer, " %s\n", - rate_str); - if (monitor_config->mode_spec->flags & META_CRTC_MODE_FLAG_INTERLACE) - g_string_append_printf (buffer, " interlace\n"); - g_string_append (buffer, " \n"); - if (monitor_config->enable_underscanning) - g_string_append (buffer, " yes\n"); - g_string_append (buffer, " \n"); - } -} - -static const char * -bool_to_string (gboolean value) -{ - return value ? "yes" : "no"; -} - -static void -append_transform (GString *buffer, - MetaMonitorTransform transform) -{ - const char *rotation = NULL; - gboolean flipped = FALSE; - - switch (transform) - { - case META_MONITOR_TRANSFORM_NORMAL: - return; - case META_MONITOR_TRANSFORM_90: - rotation = "left"; - break; - case META_MONITOR_TRANSFORM_180: - rotation = "upside_down"; - break; - case META_MONITOR_TRANSFORM_270: - rotation = "right"; - break; - case META_MONITOR_TRANSFORM_FLIPPED: - rotation = "normal"; - flipped = TRUE; - break; - case META_MONITOR_TRANSFORM_FLIPPED_90: - rotation = "left"; - flipped = TRUE; - break; - case META_MONITOR_TRANSFORM_FLIPPED_180: - rotation = "upside_down"; - flipped = TRUE; - break; - case META_MONITOR_TRANSFORM_FLIPPED_270: - rotation = "right"; - flipped = TRUE; - break; - } - - g_string_append (buffer, " \n"); - g_string_append_printf (buffer, " %s\n", - rotation); - g_string_append_printf (buffer, " %s\n", - bool_to_string (flipped)); - g_string_append (buffer, " \n"); -} - -static void -append_logical_monitor_xml (GString *buffer, - MetaMonitorsConfig *config, - MetaLogicalMonitorConfig *logical_monitor_config) -{ - char scale_str[G_ASCII_DTOSTR_BUF_SIZE]; - - g_string_append (buffer, " \n"); - g_string_append_printf (buffer, " %d\n", - logical_monitor_config->layout.x); - g_string_append_printf (buffer, " %d\n", - logical_monitor_config->layout.y); - g_ascii_dtostr (scale_str, G_ASCII_DTOSTR_BUF_SIZE, - logical_monitor_config->scale); - if ((config->flags & META_MONITORS_CONFIG_FLAG_MIGRATED) == 0) - g_string_append_printf (buffer, " %s\n", - scale_str); - if (logical_monitor_config->is_primary) - g_string_append (buffer, " yes\n"); - if (logical_monitor_config->is_presentation) - g_string_append (buffer, " yes\n"); - append_transform (buffer, logical_monitor_config->transform); - append_monitors (buffer, logical_monitor_config->monitor_configs); - g_string_append (buffer, " \n"); -} - -static GString * -generate_config_xml (MetaMonitorConfigStore *config_store) -{ - GString *buffer; - GHashTableIter iter; - MetaMonitorsConfig *config; - - buffer = g_string_new (""); - g_string_append_printf (buffer, "\n", - MONITORS_CONFIG_XML_FORMAT_VERSION); - - g_hash_table_iter_init (&iter, config_store->configs); - while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &config)) - { - GList *l; - - if (config->flags & META_MONITORS_CONFIG_FLAG_SYSTEM_CONFIG) - continue; - - g_string_append (buffer, " \n"); - - if (config->flags & META_MONITORS_CONFIG_FLAG_MIGRATED) - g_string_append (buffer, " \n"); - - for (l = config->logical_monitor_configs; l; l = l->next) - { - MetaLogicalMonitorConfig *logical_monitor_config = l->data; - - append_logical_monitor_xml (buffer, config, logical_monitor_config); - } - - if (config->disabled_monitor_specs) - { - g_string_append (buffer, " \n"); - for (l = config->disabled_monitor_specs; l; l = l->next) - { - MetaMonitorSpec *monitor_spec = l->data; - - append_monitor_spec (buffer, monitor_spec, " "); - } - g_string_append (buffer, " \n"); - } - - g_string_append (buffer, " \n"); - } - - g_string_append (buffer, "\n"); - - return buffer; -} - -typedef struct _SaveData -{ - MetaMonitorConfigStore *config_store; - GString *buffer; -} SaveData; - -static void -saved_cb (GObject *object, - GAsyncResult *result, - gpointer user_data) -{ - SaveData *data = user_data; - GError *error = NULL; - - if (!g_file_replace_contents_finish (G_FILE (object), result, NULL, &error)) - { - if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - { - g_warning ("Saving monitor configuration failed: %s", error->message); - g_clear_object (&data->config_store->save_cancellable); - } - - g_error_free (error); - } - else - { - g_clear_object (&data->config_store->save_cancellable); - } - - g_clear_object (&data->config_store); - g_string_free (data->buffer, TRUE); - g_free (data); -} - -static void -meta_monitor_config_store_save_sync (MetaMonitorConfigStore *config_store) -{ - GError *error = NULL; - GFile *file; - GString *buffer; - - if (config_store->custom_write_file) - file = config_store->custom_write_file; - else - file = config_store->user_file; - - buffer = generate_config_xml (config_store); - - if (!g_file_replace_contents (file, - buffer->str, buffer->len, - NULL, - FALSE, - G_FILE_CREATE_REPLACE_DESTINATION, - NULL, - NULL, - &error)) - { - g_warning ("Saving monitor configuration failed: %s", - error->message); - g_error_free (error); - } - - g_string_free (buffer, TRUE); -} - -static void -meta_monitor_config_store_save (MetaMonitorConfigStore *config_store) -{ - GString *buffer; - SaveData *data; - - if (config_store->save_cancellable) - { - g_cancellable_cancel (config_store->save_cancellable); - g_clear_object (&config_store->save_cancellable); - } - - /* - * Custom write file is only ever used by the test suite, and the test suite - * will want to have be able to read back the content immediately, so for - * custom write files, do the content replacement synchronously. - */ - if (config_store->custom_write_file) - { - meta_monitor_config_store_save_sync (config_store); - return; - } - - config_store->save_cancellable = g_cancellable_new (); - - buffer = generate_config_xml (config_store); - - data = g_new0 (SaveData, 1); - *data = (SaveData) { - .config_store = g_object_ref (config_store), - .buffer = buffer - }; - - g_file_replace_contents_async (config_store->user_file, - buffer->str, buffer->len, - NULL, - TRUE, - G_FILE_CREATE_REPLACE_DESTINATION, - config_store->save_cancellable, - saved_cb, data); -} - -static void -maybe_save_configs (MetaMonitorConfigStore *config_store) -{ - /* - * If a custom file is used, it means we are run by the test suite. When this - * is done, avoid replacing the user configuration file with test data, - * except if a custom write file is set as well. - */ - if (!config_store->custom_read_file || config_store->custom_write_file) - meta_monitor_config_store_save (config_store); -} - -static gboolean -is_system_config (MetaMonitorsConfig *config) -{ - return !!(config->flags & META_MONITORS_CONFIG_FLAG_SYSTEM_CONFIG); -} - -void -meta_monitor_config_store_add (MetaMonitorConfigStore *config_store, - MetaMonitorsConfig *config) -{ - g_hash_table_replace (config_store->configs, - config->key, g_object_ref (config)); - - if (!is_system_config (config)) - maybe_save_configs (config_store); -} - -void -meta_monitor_config_store_remove (MetaMonitorConfigStore *config_store, - MetaMonitorsConfig *config) -{ - g_hash_table_remove (config_store->configs, config->key); - - if (!is_system_config (config)) - maybe_save_configs (config_store); -} - -gboolean -meta_monitor_config_store_set_custom (MetaMonitorConfigStore *config_store, - const char *read_path, - const char *write_path, - GError **error) -{ - g_clear_object (&config_store->custom_read_file); - g_clear_object (&config_store->custom_write_file); - g_hash_table_remove_all (config_store->configs); - - config_store->custom_read_file = g_file_new_for_path (read_path); - if (write_path) - config_store->custom_write_file = g_file_new_for_path (write_path); - - return read_config_file (config_store, - config_store->custom_read_file, - META_MONITORS_CONFIG_FLAG_NONE, - error); -} - -int -meta_monitor_config_store_get_config_count (MetaMonitorConfigStore *config_store) -{ - return (int) g_hash_table_size (config_store->configs); -} - -MetaMonitorManager * -meta_monitor_config_store_get_monitor_manager (MetaMonitorConfigStore *config_store) -{ - return config_store->monitor_manager; -} - -MetaMonitorConfigStore * -meta_monitor_config_store_new (MetaMonitorManager *monitor_manager) -{ - return g_object_new (META_TYPE_MONITOR_CONFIG_STORE, - "monitor-manager", monitor_manager, - NULL); -} - -static void -meta_monitor_config_store_constructed (GObject *object) -{ - MetaMonitorConfigStore *config_store = META_MONITOR_CONFIG_STORE (object); - const char * const *system_dirs; - char *user_file_path; - GError *error = NULL; - - for (system_dirs = g_get_system_config_dirs (); - system_dirs && *system_dirs; - system_dirs++) - { - g_autofree char *system_file_path = NULL; - - system_file_path = g_build_filename (*system_dirs, "monitors.xml", NULL); - if (g_file_test (system_file_path, G_FILE_TEST_EXISTS)) - { - g_autoptr (GFile) system_file = NULL; - - system_file = g_file_new_for_path (system_file_path); - if (!read_config_file (config_store, - system_file, - META_MONITORS_CONFIG_FLAG_SYSTEM_CONFIG, - &error)) - { - if (g_error_matches (error, - META_MONITOR_CONFIG_STORE_ERROR, - META_MONITOR_CONFIG_STORE_ERROR_NEEDS_MIGRATION)) - g_warning ("System monitor configuration file (%s) is " - "incompatible; ask your administrator to migrate " - "the system monitor configuration.", - system_file_path); - else - g_warning ("Failed to read monitors config file '%s': %s", - system_file_path, error->message); - g_clear_error (&error); - } - } - } - - user_file_path = g_build_filename (g_get_user_config_dir (), - "monitors.xml", - NULL); - config_store->user_file = g_file_new_for_path (user_file_path); - - if (g_file_test (user_file_path, G_FILE_TEST_EXISTS)) - { - if (!read_config_file (config_store, - config_store->user_file, - META_MONITORS_CONFIG_FLAG_NONE, - &error)) - { - if (error->domain == META_MONITOR_CONFIG_STORE_ERROR && - error->code == META_MONITOR_CONFIG_STORE_ERROR_NEEDS_MIGRATION) - { - g_clear_error (&error); - if (!meta_migrate_old_user_monitors_config (config_store, &error)) - { - g_warning ("Failed to migrate old monitors config file: %s", - error->message); - g_error_free (error); - } - } - else - { - g_warning ("Failed to read monitors config file '%s': %s", - user_file_path, error->message); - g_error_free (error); - } - } - } - - g_free (user_file_path); - - G_OBJECT_CLASS (meta_monitor_config_store_parent_class)->constructed (object); -} - -static void -meta_monitor_config_store_dispose (GObject *object) -{ - MetaMonitorConfigStore *config_store = META_MONITOR_CONFIG_STORE (object); - - if (config_store->save_cancellable) - { - g_cancellable_cancel (config_store->save_cancellable); - g_clear_object (&config_store->save_cancellable); - - meta_monitor_config_store_save_sync (config_store); - } - - g_clear_pointer (&config_store->configs, g_hash_table_destroy); - - g_clear_object (&config_store->user_file); - g_clear_object (&config_store->custom_read_file); - g_clear_object (&config_store->custom_write_file); - - G_OBJECT_CLASS (meta_monitor_config_store_parent_class)->dispose (object); -} - -static void -meta_monitor_config_store_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaMonitorConfigStore *config_store = META_MONITOR_CONFIG_STORE (object); - - switch (prop_id) - { - case PROP_MONITOR_MANAGER: - g_value_set_object (value, &config_store->monitor_manager); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_monitor_config_store_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaMonitorConfigStore *config_store = META_MONITOR_CONFIG_STORE (object); - - switch (prop_id) - { - case PROP_MONITOR_MANAGER: - config_store->monitor_manager = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_monitor_config_store_init (MetaMonitorConfigStore *config_store) -{ - config_store->configs = g_hash_table_new_full (meta_monitors_config_key_hash, - meta_monitors_config_key_equal, - NULL, - g_object_unref); -} - -static void -meta_monitor_config_store_class_init (MetaMonitorConfigStoreClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->constructed = meta_monitor_config_store_constructed; - object_class->dispose = meta_monitor_config_store_dispose; - object_class->get_property = meta_monitor_config_store_get_property; - object_class->set_property = meta_monitor_config_store_set_property; - - obj_props[PROP_MONITOR_MANAGER] = - g_param_spec_object ("monitor-manager", - "MetaMonitorManager", - "MetaMonitorManager", - META_TYPE_MONITOR_MANAGER, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS | - G_PARAM_CONSTRUCT_ONLY); - - g_object_class_install_properties (object_class, PROP_LAST, obj_props); -} diff --git a/src/backends/meta-monitor-config-store.h b/src/backends/meta-monitor-config-store.h deleted file mode 100644 index 92c24ecaa..000000000 --- a/src/backends/meta-monitor-config-store.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 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_MONITOR_CONFIG_STORE_H -#define META_MONITOR_CONFIG_STORE_H - -#include - -#include "backends/meta-monitor-config-manager.h" - -#define META_TYPE_MONITOR_CONFIG_STORE (meta_monitor_config_store_get_type ()) -G_DECLARE_FINAL_TYPE (MetaMonitorConfigStore, meta_monitor_config_store, - META, MONITOR_CONFIG_STORE, GObject) - -META_EXPORT_TEST -MetaMonitorConfigStore * meta_monitor_config_store_new (MetaMonitorManager *monitor_manager); - -META_EXPORT_TEST -MetaMonitorsConfig * meta_monitor_config_store_lookup (MetaMonitorConfigStore *config_store, - MetaMonitorsConfigKey *key); - -META_EXPORT_TEST -void meta_monitor_config_store_add (MetaMonitorConfigStore *config_store, - MetaMonitorsConfig *config); - -META_EXPORT_TEST -void meta_monitor_config_store_remove (MetaMonitorConfigStore *config_store, - MetaMonitorsConfig *config); - -META_EXPORT_TEST -gboolean meta_monitor_config_store_set_custom (MetaMonitorConfigStore *config_store, - const char *read_path, - const char *write_path, - GError **error); - -META_EXPORT_TEST -int meta_monitor_config_store_get_config_count (MetaMonitorConfigStore *config_store); - -META_EXPORT_TEST -MetaMonitorManager * meta_monitor_config_store_get_monitor_manager (MetaMonitorConfigStore *config_store); - -#endif /* META_MONITOR_CONFIG_STORE_H */ diff --git a/src/backends/meta-monitor-manager-dummy.c b/src/backends/meta-monitor-manager-dummy.c deleted file mode 100644 index d08fb022b..000000000 --- a/src/backends/meta-monitor-manager-dummy.c +++ /dev/null @@ -1,816 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001, 2002 Havoc Pennington - * Copyright (C) 2002, 2003 Red Hat Inc. - * Some ICCCM manager selection code derived from fvwm2, - * Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * Copyright (C) 2013 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#include "config.h" - -#include "backends/meta-monitor-manager-dummy.h" - -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-crtc.h" -#include "backends/meta-monitor.h" -#include "backends/meta-monitor-config-manager.h" -#include "backends/meta-output.h" -#include "meta/main.h" -#include "meta/util.h" - -#define MAX_MONITORS 5 -#define MAX_OUTPUTS (MAX_MONITORS * 2) -#define MAX_CRTCS (MAX_MONITORS * 2) -#define MAX_MODES (MAX_MONITORS * 4) - -struct _MetaMonitorManagerDummy -{ - MetaMonitorManager parent_instance; - - gboolean is_transform_handled; -}; - -struct _MetaMonitorManagerDummyClass -{ - MetaMonitorManagerClass parent_class; -}; - -struct _MetaOutputDummy -{ - MetaOutput parent; - - float scale; -}; - -struct _MetaCrtcDummy -{ - MetaCrtc parent; -}; - -G_DEFINE_TYPE (MetaOutputDummy, meta_output_dummy, META_TYPE_OUTPUT) -G_DEFINE_TYPE (MetaCrtcDummy, meta_crtc_dummy, META_TYPE_CRTC) -G_DEFINE_TYPE (MetaMonitorManagerDummy, meta_monitor_manager_dummy, META_TYPE_MONITOR_MANAGER); - -struct _MetaGpuDummy -{ - MetaGpu parent; -}; - -G_DEFINE_TYPE (MetaGpuDummy, meta_gpu_dummy, META_TYPE_GPU) - -typedef struct _CrtcModeSpec -{ - int width; - int height; - float refresh_rate; -} CrtcModeSpec; -G_DEFINE_AUTOPTR_CLEANUP_FUNC(CrtcModeSpec, g_free); - -static MetaCrtcMode * -create_mode (CrtcModeSpec *spec, - long mode_id) -{ - g_autoptr (MetaCrtcModeInfo) crtc_mode_info = NULL; - - crtc_mode_info = meta_crtc_mode_info_new (); - crtc_mode_info->width = spec->width; - crtc_mode_info->height = spec->height; - crtc_mode_info->refresh_rate = spec->refresh_rate; - - return g_object_new (META_TYPE_CRTC_MODE, - "id", (uint64_t) mode_id, - "info", crtc_mode_info, - NULL); -} - -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, - GList **crtcs, - GList **outputs, - float scale) -{ - MetaGpu *gpu = get_gpu (manager); - CrtcModeSpec default_specs[] = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.0 - }, - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0 - }, - { - .width = 1440, - .height = 900, - .refresh_rate = 60.0 - }, - { - .width = 1600, - .height = 920, - .refresh_rate = 60.0 - }, - }; - g_autolist (CrtcModeSpec) mode_specs = NULL; - unsigned int n_mode_specs = 0; - GList *new_modes = NULL; - MetaCrtc *crtc; - MetaOutputDummy *output_dummy; - MetaOutput *output; - unsigned int i; - unsigned int number; - g_autoptr (MetaOutputInfo) output_info = NULL; - const char *mode_specs_str; - GList *l; - - mode_specs_str = getenv ("MUTTER_DEBUG_DUMMY_MODE_SPECS"); - if (mode_specs_str && *mode_specs_str != '\0') - { - g_auto (GStrv) specs = g_strsplit (mode_specs_str, ":", -1); - for (i = 0; specs[i]; ++i) - { - int width, height; - float refresh_rate = 60.0; - - if (sscanf (specs[i], "%dx%d@%f", - &width, &height, &refresh_rate) == 3 || - sscanf (specs[i], "%dx%d", - &width, &height) == 2) - { - CrtcModeSpec *spec; - - spec = g_new0 (CrtcModeSpec, 1); - spec->width = width; - spec->height = height; - spec->refresh_rate = refresh_rate; - mode_specs = g_list_prepend (mode_specs, spec); - } - } - } - else - { - for (i = 0; i < G_N_ELEMENTS (default_specs); i++) - { - CrtcModeSpec *spec; - - spec = g_memdup2 (&default_specs[i], sizeof (CrtcModeSpec)); - mode_specs = g_list_prepend (mode_specs, spec); - } - } - - if (!mode_specs) - { - g_warning ("Cannot create dummy output: No valid mode specs."); - meta_exit (META_EXIT_ERROR); - } - - for (l = mode_specs; l; l = l->next) - { - CrtcModeSpec *spec = l->data; - long mode_id; - MetaCrtcMode *mode; - - mode_id = g_list_length (*modes) + n_mode_specs + 1; - mode = create_mode (spec, mode_id); - - new_modes = g_list_append (new_modes, mode); - n_mode_specs++; - } - *modes = g_list_concat (*modes, new_modes); - - crtc = g_object_new (META_TYPE_CRTC_DUMMY, - "id", (uint64_t) g_list_length (*crtcs) + 1, - "gpu", gpu, - NULL); - *crtcs = g_list_append (*crtcs, crtc); - - number = g_list_length (*outputs) + 1; - - output_info = meta_output_info_new (); - output_info->name = g_strdup_printf ("LVDS%d", number); - output_info->vendor = g_strdup ("MetaProducts Inc."); - output_info->product = g_strdup ("MetaMonitor"); - output_info->serial = g_strdup_printf ("0xC0FFEE-%d", number); - output_info->width_mm = 222; - output_info->height_mm = 125; - output_info->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN; - output_info->preferred_mode = g_list_last (*modes)->data; - output_info->n_possible_clones = 0; - output_info->connector_type = META_CONNECTOR_TYPE_LVDS; - - output_info->modes = g_new0 (MetaCrtcMode *, n_mode_specs); - for (l = new_modes, i = 0; l; l = l->next, i++) - { - MetaCrtcMode *mode = l->data; - - output_info->modes[i] = mode; - } - output_info->n_modes = n_mode_specs; - output_info->possible_crtcs = g_new0 (MetaCrtc *, 1); - output_info->possible_crtcs[0] = g_list_last (*crtcs)->data; - output_info->n_possible_crtcs = 1; - - output = g_object_new (META_TYPE_OUTPUT_DUMMY, - "id", (uint64_t) number, - "gpu", gpu, - "info", output_info, - NULL); - output_dummy = META_OUTPUT_DUMMY (output); - output_dummy->scale = scale; - - *outputs = g_list_append (*outputs, output); -} - -static void -append_tiled_monitor (MetaMonitorManager *manager, - GList **modes, - GList **crtcs, - GList **outputs, - int scale) -{ - MetaGpu *gpu = get_gpu (manager); - CrtcModeSpec mode_specs[] = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.0 - }, - { - .width = 512, - .height = 768, - .refresh_rate = 60.0 - } - }; - unsigned int n_tiles = 2; - GList *new_modes = NULL; - GList *new_crtcs = NULL; - MetaOutput *output; - unsigned int i; - uint32_t tile_group_id; - - for (i = 0; i < G_N_ELEMENTS (mode_specs); i++) - { - long mode_id; - MetaCrtcMode *mode; - - mode_id = g_list_length (*modes) + i + 1; - mode = create_mode (&mode_specs[i], mode_id); - - new_modes = g_list_append (new_modes, mode); - } - *modes = g_list_concat (*modes, new_modes); - - for (i = 0; i < n_tiles; i++) - { - MetaCrtc *crtc; - - crtc = g_object_new (META_TYPE_CRTC_DUMMY, - "id", (uint64_t) g_list_length (*crtcs) + i + 1, - "gpu", gpu, - NULL); - new_crtcs = g_list_append (new_crtcs, crtc); - } - *crtcs = g_list_concat (*crtcs, new_crtcs); - - tile_group_id = g_list_length (*outputs) + 1; - for (i = 0; i < n_tiles; i++) - { - MetaOutputDummy *output_dummy; - MetaCrtcMode *preferred_mode; - const MetaCrtcModeInfo *preferred_mode_info; - unsigned int j; - unsigned int number; - g_autoptr (MetaOutputInfo) output_info = NULL; - GList *l; - - /* Arbitrary ID unique for this output */ - number = g_list_length (*outputs) + 1; - - preferred_mode = g_list_last (*modes)->data; - preferred_mode_info = meta_crtc_mode_get_info (preferred_mode); - - output_info = meta_output_info_new (); - - output_info->name = g_strdup_printf ("LVDS%d", number); - output_info->vendor = g_strdup ("MetaProducts Inc."); - output_info->product = g_strdup ("MetaMonitor"); - output_info->serial = g_strdup_printf ("0xC0FFEE-%d", number); - output_info->suggested_x = -1; - output_info->suggested_y = -1; - output_info->width_mm = 222; - output_info->height_mm = 125; - output_info->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN; - output_info->preferred_mode = preferred_mode; - output_info->n_possible_clones = 0; - output_info->connector_type = META_CONNECTOR_TYPE_LVDS; - output_info->tile_info = (MetaTileInfo) { - .group_id = tile_group_id, - .max_h_tiles = n_tiles, - .max_v_tiles = 1, - .loc_h_tile = i, - .loc_v_tile = 0, - .tile_w = preferred_mode_info->width, - .tile_h = preferred_mode_info->height - }, - - output_info->modes = g_new0 (MetaCrtcMode *, G_N_ELEMENTS (mode_specs)); - for (l = new_modes, j = 0; l; l = l->next, j++) - { - MetaCrtcMode *mode = l->data; - - output_info->modes[j] = mode; - } - output_info->n_modes = G_N_ELEMENTS (mode_specs); - - output_info->possible_crtcs = g_new0 (MetaCrtc *, n_tiles); - for (l = new_crtcs, j = 0; l; l = l->next, j++) - { - MetaCrtc *crtc = l->data; - - output_info->possible_crtcs[j] = crtc; - } - output_info->n_possible_crtcs = n_tiles; - - output = g_object_new (META_TYPE_OUTPUT_DUMMY, - "id", (uint64_t) number, - "gpu", gpu, - "info", output_info, - NULL); - output_dummy = META_OUTPUT_DUMMY (output); - output_dummy->scale = scale; - - *outputs = g_list_append (*outputs, output); - } -} - -static void -meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager) -{ - MetaGpu *gpu = get_gpu (manager); - unsigned int num_monitors = 1; - float *monitor_scales = NULL; - const char *num_monitors_str; - const char *monitor_scales_str; - const char *tiled_monitors_str; - gboolean tiled_monitors; - unsigned int i; - GList *outputs; - GList *crtcs; - GList *modes; - - /* To control what monitor configuration is generated, there are two available - * environmental variables that can be used: - * - * MUTTER_DEBUG_NUM_DUMMY_MONITORS - * - * Specifies the number of dummy monitors to include in the stage. Every - * monitor is 1024x786 pixels and they are placed on a horizontal row. - * - * MUTTER_DEBUG_DUMMY_MODE_SPECS - * - * A colon separated list of mode specifications that can be used to - * configure the monitor via dbus API. Setting this environment variable - * overrides the default set of modes available. - * Format should be WWxHH:WWxHH@RR - * - * MUTTER_DEBUG_DUMMY_MONITOR_SCALES - * - * A comma separated list that specifies the scales of the dummy monitors. - * - * MUTTER_DEBUG_TILED_DUMMY_MONITORS - * - * If set to "1" the dummy monitors will emulate being tiled, i.e. each have a - * unique tile group id, made up of multiple outputs and CRTCs. - * - * For example the following configuration results in two monitors, where the - * first one has the monitor scale 1, and the other the monitor scale 2. - * - * MUTTER_DEBUG_NUM_DUMMY_MONITORS=2 - * MUTTER_DEBUG_DUMMY_MONITOR_SCALES=1,2 - * MUTTER_DEBUG_TILED_DUMMY_MONITORS=1 - */ - num_monitors_str = getenv ("MUTTER_DEBUG_NUM_DUMMY_MONITORS"); - if (num_monitors_str) - { - num_monitors = g_ascii_strtoll (num_monitors_str, NULL, 10); - if (num_monitors <= 0) - { - meta_warning ("Invalid number of dummy monitors"); - num_monitors = 1; - } - - if (num_monitors > MAX_MONITORS) - { - meta_warning ("Clamping monitor count to max (%d)", - MAX_MONITORS); - num_monitors = MAX_MONITORS; - } - } - - monitor_scales = g_newa (typeof (*monitor_scales), num_monitors); - for (i = 0; i < num_monitors; i++) - monitor_scales[i] = 1.0; - - monitor_scales_str = getenv ("MUTTER_DEBUG_DUMMY_MONITOR_SCALES"); - if (monitor_scales_str) - { - gchar **scales_str_list; - - scales_str_list = g_strsplit (monitor_scales_str, ",", -1); - if (g_strv_length (scales_str_list) != num_monitors) - meta_warning ("Number of specified monitor scales differ from number " - "of monitors (defaults to 1)."); - for (i = 0; i < num_monitors && scales_str_list[i]; i++) - { - float scale = g_ascii_strtod (scales_str_list[i], NULL); - - monitor_scales[i] = scale; - } - g_strfreev (scales_str_list); - } - - tiled_monitors_str = g_getenv ("MUTTER_DEBUG_TILED_DUMMY_MONITORS"); - tiled_monitors = g_strcmp0 (tiled_monitors_str, "1") == 0; - - modes = NULL; - crtcs = NULL; - outputs = NULL; - - for (i = 0; i < num_monitors; i++) - { - if (tiled_monitors) - append_tiled_monitor (manager, - &modes, &crtcs, &outputs, monitor_scales[i]); - else - append_monitor (manager, &modes, &crtcs, &outputs, monitor_scales[i]); - } - - meta_gpu_take_modes (gpu, modes); - meta_gpu_take_crtcs (gpu, crtcs); - meta_gpu_take_outputs (gpu, outputs); -} - -static void -meta_monitor_manager_dummy_ensure_initial_config (MetaMonitorManager *manager) -{ - MetaMonitorsConfig *config; - - config = meta_monitor_manager_ensure_configured (manager); - - if (meta_is_stage_views_enabled ()) - meta_monitor_manager_update_logical_state (manager, config); - else - meta_monitor_manager_update_logical_state_derived (manager, NULL); -} - -static void -apply_crtc_assignments (MetaMonitorManager *manager, - MetaCrtcAssignment **crtcs, - unsigned int n_crtcs, - MetaOutputAssignment **outputs, - unsigned int n_outputs) -{ - g_autoptr (GList) to_configure_outputs = NULL; - g_autoptr (GList) to_configure_crtcs = NULL; - unsigned i; - - to_configure_outputs = g_list_copy (meta_gpu_get_outputs (get_gpu (manager))); - to_configure_crtcs = g_list_copy (meta_gpu_get_crtcs (get_gpu (manager))); - - for (i = 0; i < n_crtcs; i++) - { - MetaCrtcAssignment *crtc_assignment = crtcs[i]; - MetaCrtc *crtc = crtc_assignment->crtc; - - to_configure_crtcs = g_list_remove (to_configure_crtcs, crtc); - - if (crtc_assignment->mode == NULL) - { - meta_crtc_unset_config (crtc); - } - else - { - unsigned int j; - - meta_crtc_set_config (crtc, - &crtc_assignment->layout, - crtc_assignment->mode, - crtc_assignment->transform); - - for (j = 0; j < crtc_assignment->outputs->len; j++) - { - MetaOutput *output; - MetaOutputAssignment *output_assignment; - - output = ((MetaOutput**) crtc_assignment->outputs->pdata)[j]; - - to_configure_outputs = g_list_remove (to_configure_outputs, - output); - - output_assignment = meta_find_output_assignment (outputs, - n_outputs, - output); - meta_output_assign_crtc (output, crtc, output_assignment); - } - } - } - - g_list_foreach (to_configure_crtcs, - (GFunc) meta_crtc_unset_config, - NULL); - g_list_foreach (to_configure_outputs, - (GFunc) meta_output_unassign_crtc, - NULL); -} - -static void -update_screen_size (MetaMonitorManager *manager, - MetaMonitorsConfig *config) -{ - GList *l; - int screen_width = 0; - int screen_height = 0; - - for (l = config->logical_monitor_configs; l; l = l->next) - { - MetaLogicalMonitorConfig *logical_monitor_config = l->data; - int right_edge; - int bottom_edge; - - right_edge = (logical_monitor_config->layout.width + - logical_monitor_config->layout.x); - if (right_edge > screen_width) - screen_width = right_edge; - - bottom_edge = (logical_monitor_config->layout.height + - logical_monitor_config->layout.y); - if (bottom_edge > screen_height) - screen_height = bottom_edge; - } - - manager->screen_width = screen_width; - manager->screen_height = screen_height; -} - -static gboolean -meta_monitor_manager_dummy_apply_monitors_config (MetaMonitorManager *manager, - MetaMonitorsConfig *config, - MetaMonitorsConfigMethod method, - GError **error) -{ - GPtrArray *crtc_assignments; - GPtrArray *output_assignments; - - if (!config) - { - manager->screen_width = META_MONITOR_MANAGER_MIN_SCREEN_WIDTH; - manager->screen_height = META_MONITOR_MANAGER_MIN_SCREEN_HEIGHT; - - meta_monitor_manager_rebuild (manager, NULL); - return TRUE; - } - - if (!meta_monitor_config_manager_assign (manager, config, - &crtc_assignments, - &output_assignments, - error)) - return FALSE; - - if (method == META_MONITORS_CONFIG_METHOD_VERIFY) - { - g_ptr_array_free (crtc_assignments, TRUE); - g_ptr_array_free (output_assignments, TRUE); - return TRUE; - } - - apply_crtc_assignments (manager, - (MetaCrtcAssignment **) crtc_assignments->pdata, - crtc_assignments->len, - (MetaOutputAssignment **) output_assignments->pdata, - output_assignments->len); - - g_ptr_array_free (crtc_assignments, TRUE); - g_ptr_array_free (output_assignments, TRUE); - - update_screen_size (manager, config); - meta_monitor_manager_rebuild (manager, config); - - return TRUE; -} - -static gboolean -meta_monitor_manager_dummy_is_transform_handled (MetaMonitorManager *manager, - MetaCrtc *crtc, - MetaMonitorTransform transform) -{ - MetaMonitorManagerDummy *manager_dummy = META_MONITOR_MANAGER_DUMMY (manager); - - return manager_dummy->is_transform_handled; -} - -static float -meta_monitor_manager_dummy_calculate_monitor_mode_scale (MetaMonitorManager *manager, - MetaMonitor *monitor, - MetaMonitorMode *monitor_mode) -{ - MetaOutput *output; - MetaOutputDummy *output_dummy; - - output = meta_monitor_get_main_output (monitor); - output_dummy = META_OUTPUT_DUMMY (output); - - return output_dummy->scale; -} - -static float * -meta_monitor_manager_dummy_calculate_supported_scales (MetaMonitorManager *manager, - MetaLogicalMonitorLayoutMode layout_mode, - MetaMonitor *monitor, - MetaMonitorMode *monitor_mode, - int *n_supported_scales) -{ - MetaMonitorScalesConstraint constraints = - META_MONITOR_SCALES_CONSTRAINT_NONE; - - switch (layout_mode) - { - case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL: - break; - case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL: - constraints |= META_MONITOR_SCALES_CONSTRAINT_NO_FRAC; - break; - } - - return meta_monitor_calculate_supported_scales (monitor, monitor_mode, - constraints, - n_supported_scales); -} - -static gboolean -is_monitor_framebuffers_scaled (void) -{ - MetaBackend *backend = meta_get_backend (); - MetaSettings *settings = meta_backend_get_settings (backend); - - return meta_settings_is_experimental_feature_enabled ( - settings, - META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER); -} - -static MetaMonitorManagerCapability -meta_monitor_manager_dummy_get_capabilities (MetaMonitorManager *manager) -{ - MetaBackend *backend = meta_get_backend (); - MetaSettings *settings = meta_backend_get_settings (backend); - MetaMonitorManagerCapability capabilities = - META_MONITOR_MANAGER_CAPABILITY_NONE; - - if (meta_settings_is_experimental_feature_enabled ( - settings, - META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER)) - capabilities |= META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE; - - return capabilities; -} - -static gboolean -meta_monitor_manager_dummy_get_max_screen_size (MetaMonitorManager *manager, - int *max_width, - int *max_height) -{ - if (meta_is_stage_views_enabled ()) - return FALSE; - - *max_width = 65535; - *max_height = 65535; - - return TRUE; -} - -static MetaLogicalMonitorLayoutMode -meta_monitor_manager_dummy_get_default_layout_mode (MetaMonitorManager *manager) -{ - if (!meta_is_stage_views_enabled ()) - return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL; - - if (is_monitor_framebuffers_scaled ()) - return META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL; - else - 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; - manager_class->calculate_monitor_mode_scale = meta_monitor_manager_dummy_calculate_monitor_mode_scale; - manager_class->calculate_supported_scales = meta_monitor_manager_dummy_calculate_supported_scales; - manager_class->get_capabilities = meta_monitor_manager_dummy_get_capabilities; - manager_class->get_max_screen_size = meta_monitor_manager_dummy_get_max_screen_size; - manager_class->get_default_layout_mode = meta_monitor_manager_dummy_get_default_layout_mode; -} - -static void -meta_monitor_manager_dummy_init (MetaMonitorManagerDummy *manager_dummy) -{ -} - -static gboolean -meta_gpu_dummy_read_current (MetaGpu *gpu, - GError **error) -{ - MetaBackend *backend = meta_gpu_get_backend (gpu); - MetaMonitorManager *manager = meta_backend_get_monitor_manager (backend); - - meta_monitor_manager_dummy_read_current (manager); - - return TRUE; -} - -static void -meta_gpu_dummy_init (MetaGpuDummy *gpu_dummy) -{ -} - -static void -meta_gpu_dummy_class_init (MetaGpuDummyClass *klass) -{ - MetaGpuClass *gpu_class = META_GPU_CLASS (klass); - - gpu_class->read_current = meta_gpu_dummy_read_current; -} - -static void -meta_output_dummy_init (MetaOutputDummy *output_dummy) -{ - output_dummy->scale = 1; -} - -static void -meta_output_dummy_class_init (MetaOutputDummyClass *klass) -{ -} - -static void -meta_crtc_dummy_init (MetaCrtcDummy *crtc_dummy) -{ -} - -static void -meta_crtc_dummy_class_init (MetaCrtcDummyClass *klass) -{ -} diff --git a/src/backends/meta-monitor-manager-dummy.h b/src/backends/meta-monitor-manager-dummy.h deleted file mode 100644 index 72244166e..000000000 --- a/src/backends/meta-monitor-manager-dummy.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * Copyright (C) 2013 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#ifndef META_MONITOR_MANAGER_DUMMY_H -#define META_MONITOR_MANAGER_DUMMY_H - -#include "backends/meta-crtc.h" -#include "backends/meta-gpu.h" -#include "backends/meta-monitor-manager-private.h" -#include "backends/meta-output.h" - -#define META_TYPE_OUTPUT_DUMMY (meta_output_dummy_get_type ()) -G_DECLARE_FINAL_TYPE (MetaOutputDummy, meta_output_dummy, - META, OUTPUT_DUMMY, - MetaOutput) - -#define META_TYPE_CRTC_DUMMY (meta_crtc_dummy_get_type ()) -G_DECLARE_FINAL_TYPE (MetaCrtcDummy, meta_crtc_dummy, - META, CRTC_DUMMY, - MetaCrtc) - -#define META_TYPE_MONITOR_MANAGER_DUMMY (meta_monitor_manager_dummy_get_type ()) -G_DECLARE_FINAL_TYPE (MetaMonitorManagerDummy, meta_monitor_manager_dummy, - META, MONITOR_MANAGER_DUMMY, MetaMonitorManager) - -#define META_TYPE_GPU_DUMMY (meta_gpu_dummy_get_type ()) -G_DECLARE_FINAL_TYPE (MetaGpuDummy, meta_gpu_dummy, META, GPU_DUMMY, MetaGpu) - -#endif /* META_MONITOR_MANAGER_DUMMY_H */ diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h deleted file mode 100644 index 60c1e9082..000000000 --- a/src/backends/meta-monitor-manager-private.h +++ /dev/null @@ -1,439 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * Copyright (C) 2013 Red Hat Inc. - * Copyright (C) 2020 NVIDIA CORPORATION - * - * 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 . - */ - -#ifndef META_MONITOR_MANAGER_PRIVATE_H -#define META_MONITOR_MANAGER_PRIVATE_H - -#include -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-cursor.h" -#include "backends/meta-display-config-shared.h" -#include "backends/meta-monitor-transform.h" -#include "backends/meta-viewport-info.h" -#include "core/util-private.h" -#include "meta/display.h" -#include "meta/meta-monitor-manager.h" - -#define META_MONITOR_MANAGER_MIN_SCREEN_WIDTH 640 -#define META_MONITOR_MANAGER_MIN_SCREEN_HEIGHT 480 - -typedef enum _MetaMonitorManagerCapability -{ - META_MONITOR_MANAGER_CAPABILITY_NONE = 0, - META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE = (1 << 0), - META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED = (1 << 1) -} MetaMonitorManagerCapability; - -/* Equivalent to the 'method' enum in org.gnome.Mutter.DisplayConfig */ -typedef enum _MetaMonitorsConfigMethod -{ - META_MONITORS_CONFIG_METHOD_VERIFY = 0, - META_MONITORS_CONFIG_METHOD_TEMPORARY = 1, - META_MONITORS_CONFIG_METHOD_PERSISTENT = 2 -} MetaMonitorsConfigMethod; - -/* Equivalent to the 'layout-mode' enum in org.gnome.Mutter.DisplayConfig */ -typedef enum _MetaLogicalMonitorLayoutMode -{ - META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL = 1, - META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL = 2 -} MetaLogicalMonitorLayoutMode; - -/* - * MetaCrtcAssignment: - * - * A representation of a CRTC configuration, generated by - * MetaMonitorConfigManager. - */ -struct _MetaCrtcAssignment -{ - MetaCrtc *crtc; - MetaCrtcMode *mode; - graphene_rect_t layout; - MetaMonitorTransform transform; - GPtrArray *outputs; -}; - -/* - * MetaOutputAssignment: - * - * A representation of a connector configuration, generated by - * MetaMonitorConfigManager. - */ -struct _MetaOutputAssignment -{ - MetaOutput *output; - gboolean is_primary; - gboolean is_presentation; - gboolean is_underscanning; -}; - -/* - * MetaOutputCtm: - * - * A 3x3 color transform matrix in the fixed-point S31.32 sign-magnitude format - * used by DRM. - */ -typedef struct _MetaOutputCtm -{ - uint64_t matrix[9]; -} MetaOutputCtm; - -#define META_TYPE_MONITOR_MANAGER (meta_monitor_manager_get_type ()) -#define META_MONITOR_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER, MetaMonitorManager)) -#define META_MONITOR_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER, MetaMonitorManagerClass)) -#define META_IS_MONITOR_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER)) -#define META_IS_MONITOR_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_MANAGER)) -#define META_MONITOR_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_MANAGER, MetaMonitorManagerClass)) - -typedef struct _MetaDBusDisplayConfig MetaDBusDisplayConfig; - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaMonitorManager, g_object_unref) - -struct _MetaMonitorManager -{ - GObject parent_instance; - - MetaDBusDisplayConfig *display_config; - - MetaBackend *backend; - - /* XXX: this structure is very badly - packed, but I like the logical organization - of fields */ - - gboolean in_init; - unsigned int serial; - - MetaLogicalMonitorLayoutMode layout_mode; - - int screen_width; - int screen_height; - - GList *monitors; - - GList *logical_monitors; - MetaLogicalMonitor *primary_logical_monitor; - - int dbus_name_id; - - int persistent_timeout_id; - - guint panel_orientation_managed : 1; - - MetaMonitorConfigManager *config_manager; - - GnomePnpIds *pnp_ids; - - gulong experimental_features_changed_handler_id; - - MetaMonitorSwitchConfigType current_switch_config; -}; - -/** - * MetaMonitorManagerClass: - * - * @read_edid: Returns the raw Extended Display Identification Data (EDID) - * for the given #MetaOutput object. - * - * @ensure_initial_config: Called on setup. Makes sure an initial config - * is loaded. - * - * @apply_monitors_config: Tries to apply the given config using the given - * method. Throws an error if something went wrong. - * - * @set_power_save_mode: Sets the #MetaPowerSave mode (for all displays). - * - * @change_backlight: Changes the backlight intensity to the given value (in - * percent). - * - * @get_crtc_gamma: Queries and returns the gamma rampQueries and returns the - * gamma ramp. - * - * @set_crtc_gamma: Sets custom display LUT (look up table) for each primary - * color. Each table is indexed by a value that represents input intensity, - * and yields a value that represents output intensity. - * - * @tiled_monitor_added: Should be called by a #MetaMonitor when it is created. - * - * @tiled_monitor_removed: Should be called by a #MetaMonitor when it is - * destroyed. - * - * @is_transform_handled: vfunc for - * meta_monitor_manager_is_transform_handled(). - * @calculate_monitor_mode_scale: vfunc for - * meta_monitor_manager_calculate_monitor_mode_scale(). - * @calculate_supported_scales: vfunc for - * meta_monitor_manager_calculate_supported_scales(). - * @get_capabilities: vfunc for meta_monitor_manager_get_capabilities(). - * @get_max_screen_size: vfunc for meta_monitor_manager_get_max_screen_size(). - * @get_default_layout_mode: vfunc for meta_monitor_manager_get_default_layout_mode(). - * @set_output_ctm: vfunc for meta_monitor_manager_output_set_ctm() - * - * The base class for a #MetaMonitorManager. - */ -struct _MetaMonitorManagerClass -{ - GObjectClass parent_class; - - GBytes * (* read_edid) (MetaMonitorManager *manager, - MetaOutput *output); - - void (* read_current_state) (MetaMonitorManager *manager); - - void (* ensure_initial_config) (MetaMonitorManager *manager); - - gboolean (* apply_monitors_config) (MetaMonitorManager *manager, - MetaMonitorsConfig *config, - MetaMonitorsConfigMethod method, - GError **error); - - void (* set_power_save_mode) (MetaMonitorManager *manager, - MetaPowerSave power_save); - - void (* change_backlight) (MetaMonitorManager *manager, - MetaOutput *output, - int backlight); - - void (* get_crtc_gamma) (MetaMonitorManager *manager, - MetaCrtc *crtc, - size_t *size, - unsigned short **red, - unsigned short **green, - unsigned short **blue); - void (* set_crtc_gamma) (MetaMonitorManager *manager, - MetaCrtc *crtc, - size_t size, - unsigned short *red, - unsigned short *green, - unsigned short *blue); - - void (* tiled_monitor_added) (MetaMonitorManager *manager, - MetaMonitor *monitor); - - void (* tiled_monitor_removed) (MetaMonitorManager *manager, - MetaMonitor *monitor); - - gboolean (* is_transform_handled) (MetaMonitorManager *manager, - MetaCrtc *crtc, - MetaMonitorTransform transform); - - float (* calculate_monitor_mode_scale) (MetaMonitorManager *manager, - MetaMonitor *monitor, - MetaMonitorMode *monitor_mode); - - float * (* calculate_supported_scales) (MetaMonitorManager *manager, - MetaLogicalMonitorLayoutMode layout_mode, - MetaMonitor *monitor, - MetaMonitorMode *monitor_mode, - int *n_supported_scales); - - MetaMonitorManagerCapability (* get_capabilities) (MetaMonitorManager *manager); - - gboolean (* get_max_screen_size) (MetaMonitorManager *manager, - int *width, - int *height); - - MetaLogicalMonitorLayoutMode (* get_default_layout_mode) (MetaMonitorManager *manager); - - void (* set_output_ctm) (MetaOutput *output, - const MetaOutputCtm *ctm); - - MetaVirtualMonitor * (* create_virtual_monitor) (MetaMonitorManager *manager, - const MetaVirtualMonitorInfo *info, - GError **error); -}; - -META_EXPORT_TEST -MetaBackend * meta_monitor_manager_get_backend (MetaMonitorManager *manager); - -void meta_monitor_manager_setup (MetaMonitorManager *manager); - -META_EXPORT_TEST -void meta_monitor_manager_rebuild (MetaMonitorManager *manager, - MetaMonitorsConfig *config); - -META_EXPORT_TEST -void meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager, - MetaMonitorsConfig *config); - -META_EXPORT_TEST -int meta_monitor_manager_get_num_logical_monitors (MetaMonitorManager *manager); - -META_EXPORT_TEST -GList * meta_monitor_manager_get_logical_monitors (MetaMonitorManager *manager); - -MetaLogicalMonitor *meta_monitor_manager_get_logical_monitor_from_number (MetaMonitorManager *manager, - int number); - -MetaLogicalMonitor *meta_monitor_manager_get_primary_logical_monitor (MetaMonitorManager *manager); - -MetaLogicalMonitor *meta_monitor_manager_get_logical_monitor_at (MetaMonitorManager *manager, - float x, - float y); - -MetaLogicalMonitor *meta_monitor_manager_get_logical_monitor_from_rect (MetaMonitorManager *manager, - MetaRectangle *rect); - -MetaLogicalMonitor *meta_monitor_manager_get_logical_monitor_neighbor (MetaMonitorManager *manager, - MetaLogicalMonitor *logical_monitor, - MetaDisplayDirection direction); - -MetaMonitor * meta_monitor_manager_get_primary_monitor (MetaMonitorManager *manager); - -MetaMonitor * meta_monitor_manager_get_laptop_panel (MetaMonitorManager *manager); - -MetaMonitor * meta_monitor_manager_get_monitor_from_spec (MetaMonitorManager *manager, - MetaMonitorSpec *monitor_spec); - -MetaMonitor * meta_monitor_manager_get_monitor_from_connector (MetaMonitorManager *manager, - const char *connector); - -META_EXPORT_TEST -GList * meta_monitor_manager_get_monitors (MetaMonitorManager *manager); - -void meta_monitor_manager_get_screen_size (MetaMonitorManager *manager, - int *width, - int *height); - -MetaPowerSave meta_monitor_manager_get_power_save_mode (MetaMonitorManager *manager); - -void meta_monitor_manager_power_save_mode_changed (MetaMonitorManager *manager, - MetaPowerSave mode); - -void meta_monitor_manager_confirm_configuration (MetaMonitorManager *manager, - gboolean ok); - -gboolean meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager); - -void meta_monitor_manager_read_current_state (MetaMonitorManager *manager); - -void meta_monitor_manager_reconfigure (MetaMonitorManager *manager); - -META_EXPORT_TEST -void meta_monitor_manager_reload (MetaMonitorManager *manager); - -gboolean meta_monitor_manager_get_monitor_matrix (MetaMonitorManager *manager, - MetaMonitor *monitor, - MetaLogicalMonitor *logical_monitor, - gfloat matrix[6]); - -void meta_monitor_manager_tiled_monitor_added (MetaMonitorManager *manager, - MetaMonitor *monitor); -void meta_monitor_manager_tiled_monitor_removed (MetaMonitorManager *manager, - MetaMonitor *monitor); - -gboolean meta_monitor_manager_is_transform_handled (MetaMonitorManager *manager, - MetaCrtc *crtc, - MetaMonitorTransform transform); - -META_EXPORT_TEST -MetaMonitorsConfig * meta_monitor_manager_ensure_configured (MetaMonitorManager *manager); - -META_EXPORT_TEST -void meta_monitor_manager_update_logical_state (MetaMonitorManager *manager, - MetaMonitorsConfig *config); - -META_EXPORT_TEST -void meta_monitor_manager_update_logical_state_derived (MetaMonitorManager *manager, - MetaMonitorsConfig *config); - -META_EXPORT_TEST -void meta_monitor_manager_lid_is_closed_changed (MetaMonitorManager *manager); - -gboolean meta_monitor_manager_is_headless (MetaMonitorManager *manager); - -float meta_monitor_manager_calculate_monitor_mode_scale (MetaMonitorManager *manager, - MetaMonitor *monitor, - MetaMonitorMode *monitor_mode); - -float * meta_monitor_manager_calculate_supported_scales (MetaMonitorManager *, - MetaLogicalMonitorLayoutMode , - MetaMonitor *, - MetaMonitorMode *, - int *); - -gboolean meta_monitor_manager_is_scale_supported (MetaMonitorManager *manager, - MetaLogicalMonitorLayoutMode layout_mode, - MetaMonitor *monitor, - MetaMonitorMode *monitor_mode, - float scale); - -MetaMonitorManagerCapability - meta_monitor_manager_get_capabilities (MetaMonitorManager *manager); - -gboolean meta_monitor_manager_get_max_screen_size (MetaMonitorManager *manager, - int *max_width, - int *max_height); - -MetaLogicalMonitorLayoutMode - meta_monitor_manager_get_default_layout_mode (MetaMonitorManager *manager); - -META_EXPORT_TEST -MetaVirtualMonitor * meta_monitor_manager_create_virtual_monitor (MetaMonitorManager *manager, - const MetaVirtualMonitorInfo *info, - GError **error); - -META_EXPORT_TEST -MetaMonitorConfigManager * - meta_monitor_manager_get_config_manager (MetaMonitorManager *manager); - -void meta_monitor_manager_rotate_monitor (MetaMonitorManager *manager); - -void meta_monitor_manager_clear_output (MetaOutput *output); -void meta_monitor_manager_clear_mode (MetaCrtcMode *mode); -void meta_monitor_manager_clear_crtc (MetaCrtc *crtc); - -gboolean meta_monitor_has_aspect_as_size (MetaMonitor *monitor); - -char * meta_monitor_manager_get_vendor_name (MetaMonitorManager *manager, - const char *vendor); - -static inline MetaOutputAssignment * -meta_find_output_assignment (MetaOutputAssignment **outputs, - unsigned int n_outputs, - MetaOutput *output) -{ - unsigned int i; - - for (i = 0; i < n_outputs; i++) - { - MetaOutputAssignment *output_assignment = outputs[i]; - - if (output == output_assignment->output) - return output_assignment; - } - - return NULL; -} - -void meta_monitor_manager_post_init (MetaMonitorManager *manager); - -MetaViewportInfo * meta_monitor_manager_get_viewports (MetaMonitorManager *manager); - -GList * meta_monitor_manager_get_virtual_monitors (MetaMonitorManager *manager); - -#endif /* META_MONITOR_MANAGER_PRIVATE_H */ diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c deleted file mode 100644 index e6d50bd99..000000000 --- a/src/backends/meta-monitor-manager.c +++ /dev/null @@ -1,3471 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001, 2002 Havoc Pennington - * Copyright (C) 2002, 2003 Red Hat Inc. - * Some ICCCM manager selection code derived from fvwm2, - * Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * Copyright (C) 2013 Red Hat Inc. - * Copyright (C) 2020 NVIDIA CORPORATION - * - * 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 . - */ - -/** - * SECTION:meta-monitor-manager - * @title: MetaMonitorManager - * @short_description: A manager for multiple monitors - * - * #MetaMonitorManager is an abstract class which contains methods to handle - * multiple monitors (both #MetaMonitor and #MetaLogicalMonitor) and GPU's - * (#MetaGpu). Its functions include reading and/or changing the current - * configuration and available capabiliies. - * - * The #MetaMonitorManager also provides the "org.gnome.Mutter.DisplayConfig" - * DBus service, so apps like GNOME Settings can use this functionality. - */ - -#include "config.h" - -#include "backends/meta-monitor-manager-private.h" - -#include -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-crtc.h" -#include "backends/meta-logical-monitor.h" -#include "backends/meta-monitor.h" -#include "backends/meta-monitor-config-manager.h" -#include "backends/meta-orientation-manager.h" -#include "backends/meta-output.h" -#include "backends/meta-virtual-monitor.h" -#include "backends/x11/meta-monitor-manager-xrandr.h" -#include "clutter/clutter.h" -#include "core/util-private.h" -#include "meta/main.h" -#include "meta/meta-x11-errors.h" - -#include "meta-dbus-display-config.h" - -#define DEFAULT_DISPLAY_CONFIGURATION_TIMEOUT 20 - -enum -{ - PROP_0, - - PROP_BACKEND, - PROP_PANEL_ORIENTATION_MANAGED, - - PROP_LAST -}; - -static GParamSpec *obj_props[PROP_LAST]; - -enum -{ - MONITORS_CHANGED, - MONITORS_CHANGED_INTERNAL, - POWER_SAVE_MODE_CHANGED, - CONFIRM_DISPLAY_CHANGE, - SIGNALS_LAST -}; - -/* Array index matches MetaMonitorTransform */ -static gfloat transform_matrices[][6] = { - { 1, 0, 0, 0, 1, 0 }, /* normal */ - { 0, -1, 1, 1, 0, 0 }, /* 90° */ - { -1, 0, 1, 0, -1, 1 }, /* 180° */ - { 0, 1, 0, -1, 0, 1 }, /* 270° */ - { -1, 0, 1, 0, 1, 0 }, /* normal flipped */ - { 0, 1, 0, 1, 0, 0 }, /* 90° flipped */ - { 1, 0, 0, 0, -1, 1 }, /* 180° flipped */ - { 0, -1, 1, -1, 0, 1 }, /* 270° flipped */ -}; - -static int signals[SIGNALS_LAST]; - -typedef struct _MetaMonitorManagerPrivate -{ - MetaPowerSave power_save_mode; - gboolean initial_orient_change_done; - - GList *virtual_monitors; - - gboolean shutting_down; -} MetaMonitorManagerPrivate; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaMonitorManager, meta_monitor_manager, - G_TYPE_OBJECT) - -static void initialize_dbus_interface (MetaMonitorManager *manager); -static void monitor_manager_setup_dbus_config_handlers (MetaMonitorManager *manager); - -static gboolean -meta_monitor_manager_is_config_complete (MetaMonitorManager *manager, - MetaMonitorsConfig *config); - -static MetaMonitor * -meta_monitor_manager_get_active_monitor (MetaMonitorManager *manager); - -static void -meta_monitor_manager_real_read_current_state (MetaMonitorManager *manager); - -MetaBackend * -meta_monitor_manager_get_backend (MetaMonitorManager *manager) -{ - return manager->backend; -} - -static void -meta_monitor_manager_init (MetaMonitorManager *manager) -{ -} - -static void -meta_monitor_manager_set_primary_logical_monitor (MetaMonitorManager *manager, - MetaLogicalMonitor *logical_monitor) -{ - manager->primary_logical_monitor = logical_monitor; - if (logical_monitor) - meta_logical_monitor_make_primary (logical_monitor); -} - -static gboolean -is_main_tiled_monitor_output (MetaOutput *output) -{ - const MetaOutputInfo *output_info = meta_output_get_info (output); - - return (output_info->tile_info.loc_h_tile == 0 && - output_info->tile_info.loc_v_tile == 0); -} - -static MetaLogicalMonitor * -logical_monitor_from_layout (MetaMonitorManager *manager, - GList *logical_monitors, - MetaRectangle *layout) -{ - GList *l; - - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - - if (meta_rectangle_equal (layout, &logical_monitor->rect)) - return logical_monitor; - } - - return NULL; -} - -static void -meta_monitor_manager_rebuild_logical_monitors (MetaMonitorManager *manager, - MetaMonitorsConfig *config) -{ - GList *logical_monitor_configs; - GList *logical_monitors = NULL; - GList *l; - int monitor_number = 0; - MetaLogicalMonitor *primary_logical_monitor = NULL; - - logical_monitor_configs = config ? config->logical_monitor_configs : NULL; - for (l = logical_monitor_configs; l; l = l->next) - { - MetaLogicalMonitorConfig *logical_monitor_config = l->data; - MetaLogicalMonitor *logical_monitor; - - logical_monitor = meta_logical_monitor_new (manager, - logical_monitor_config, - monitor_number); - monitor_number++; - - if (logical_monitor_config->is_primary) - primary_logical_monitor = logical_monitor; - - logical_monitors = g_list_append (logical_monitors, logical_monitor); - } - - /* - * If no monitor was marked as primary, fall back on marking the first - * logical monitor the primary one. - */ - if (!primary_logical_monitor && logical_monitors) - primary_logical_monitor = g_list_first (logical_monitors)->data; - - manager->logical_monitors = logical_monitors; - meta_monitor_manager_set_primary_logical_monitor (manager, - primary_logical_monitor); -} - -static float -derive_configured_global_scale (MetaMonitorManager *manager, - MetaMonitorsConfig *config) -{ - MetaLogicalMonitorConfig *logical_monitor_config; - - logical_monitor_config = config->logical_monitor_configs->data; - - return logical_monitor_config->scale; -} - -static float -calculate_monitor_scale (MetaMonitorManager *manager, - MetaMonitor *monitor) -{ - MetaMonitorMode *monitor_mode; - - monitor_mode = meta_monitor_get_current_mode (monitor); - return meta_monitor_manager_calculate_monitor_mode_scale (manager, - monitor, - monitor_mode); -} - -static float -derive_calculated_global_scale (MetaMonitorManager *manager) -{ - MetaMonitor *monitor = NULL; - - monitor = meta_monitor_manager_get_primary_monitor (manager); - - if (!monitor || !meta_monitor_is_active (monitor)) - monitor = meta_monitor_manager_get_active_monitor (manager); - - if (!monitor) - return 1.0; - - return calculate_monitor_scale (manager, monitor); -} - -static float -derive_scale_from_config (MetaMonitorManager *manager, - MetaMonitorsConfig *config, - MetaRectangle *layout) -{ - GList *l; - - for (l = config->logical_monitor_configs; l; l = l->next) - { - MetaLogicalMonitorConfig *logical_monitor_config = l->data; - - if (meta_rectangle_equal (layout, &logical_monitor_config->layout)) - return logical_monitor_config->scale; - } - - g_warning ("Missing logical monitor, using scale 1"); - return 1.0; -} - -static void -meta_monitor_manager_rebuild_logical_monitors_derived (MetaMonitorManager *manager, - MetaMonitorsConfig *config) -{ - GList *logical_monitors = NULL; - GList *l; - int monitor_number; - MetaLogicalMonitor *primary_logical_monitor = NULL; - gboolean use_global_scale; - float global_scale = 0.0; - MetaMonitorManagerCapability capabilities; - - monitor_number = 0; - - capabilities = meta_monitor_manager_get_capabilities (manager); - use_global_scale = - !!(capabilities & META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED); - - if (use_global_scale) - { - if (config) - global_scale = derive_configured_global_scale (manager, config); - else - global_scale = derive_calculated_global_scale (manager); - } - - for (l = manager->monitors; l; l = l->next) - { - MetaMonitor *monitor = l->data; - MetaLogicalMonitor *logical_monitor; - MetaRectangle layout; - - if (!meta_monitor_is_active (monitor)) - continue; - - meta_monitor_derive_layout (monitor, &layout); - logical_monitor = logical_monitor_from_layout (manager, logical_monitors, - &layout); - if (logical_monitor) - { - meta_logical_monitor_add_monitor (logical_monitor, monitor); - } - else - { - float scale; - - if (use_global_scale) - scale = global_scale; - else if (config) - scale = derive_scale_from_config (manager, config, &layout); - else - scale = calculate_monitor_scale (manager, monitor); - - g_assert (scale > 0); - - logical_monitor = meta_logical_monitor_new_derived (manager, - monitor, - &layout, - scale, - monitor_number); - logical_monitors = g_list_append (logical_monitors, logical_monitor); - monitor_number++; - } - - if (meta_monitor_is_primary (monitor)) - primary_logical_monitor = logical_monitor; - } - - manager->logical_monitors = logical_monitors; - - /* - * If no monitor was marked as primary, fall back on marking the first - * logical monitor the primary one. - */ - if (!primary_logical_monitor && manager->logical_monitors) - primary_logical_monitor = g_list_first (manager->logical_monitors)->data; - - meta_monitor_manager_set_primary_logical_monitor (manager, - primary_logical_monitor); -} - -void -meta_monitor_manager_power_save_mode_changed (MetaMonitorManager *manager, - MetaPowerSave mode) -{ - MetaMonitorManagerPrivate *priv = - meta_monitor_manager_get_instance_private (manager); - - if (priv->power_save_mode == mode) - return; - - priv->power_save_mode = mode; - g_signal_emit (manager, signals[POWER_SAVE_MODE_CHANGED], 0); -} - -static void -power_save_mode_changed (MetaMonitorManager *manager, - GParamSpec *pspec, - gpointer user_data) -{ - MetaMonitorManagerPrivate *priv = - meta_monitor_manager_get_instance_private (manager); - MetaMonitorManagerClass *klass; - int mode = meta_dbus_display_config_get_power_save_mode (manager->display_config); - - if (mode == META_POWER_SAVE_UNSUPPORTED) - return; - - /* If DPMS is unsupported, force the property back. */ - if (priv->power_save_mode == META_POWER_SAVE_UNSUPPORTED) - { - meta_dbus_display_config_set_power_save_mode (manager->display_config, META_POWER_SAVE_UNSUPPORTED); - return; - } - - klass = META_MONITOR_MANAGER_GET_CLASS (manager); - if (klass->set_power_save_mode) - klass->set_power_save_mode (manager, mode); - - meta_monitor_manager_power_save_mode_changed (manager, mode); -} - -void -meta_monitor_manager_lid_is_closed_changed (MetaMonitorManager *manager) -{ - meta_monitor_manager_ensure_configured (manager); -} - -static void -lid_is_closed_changed (MetaBackend *backend, - gboolean lid_is_closed, - gpointer user_data) -{ - MetaMonitorManager *manager = user_data; - meta_monitor_manager_lid_is_closed_changed (manager); -} - -static void -prepare_shutdown (MetaBackend *backend, - MetaMonitorManager *manager) -{ - MetaMonitorManagerPrivate *priv = - meta_monitor_manager_get_instance_private (manager); - - priv->shutting_down = TRUE; -} - -/** - * meta_monitor_manager_is_headless: - * @manager: A #MetaMonitorManager object - * - * Returns whether the monitor manager is headless, i.e. without - * any #MetaLogicalMonitors attached to it. - * - * Returns: %TRUE if no monitors are attached, %FALSE otherwise. - */ -gboolean -meta_monitor_manager_is_headless (MetaMonitorManager *manager) -{ - return !manager->logical_monitors; -} - -float -meta_monitor_manager_calculate_monitor_mode_scale (MetaMonitorManager *manager, - MetaMonitor *monitor, - MetaMonitorMode *monitor_mode) -{ - MetaMonitorManagerClass *manager_class = - META_MONITOR_MANAGER_GET_CLASS (manager); - - return manager_class->calculate_monitor_mode_scale (manager, - monitor, - monitor_mode); -} - -float * -meta_monitor_manager_calculate_supported_scales (MetaMonitorManager *manager, - MetaLogicalMonitorLayoutMode layout_mode, - MetaMonitor *monitor, - MetaMonitorMode *monitor_mode, - int *n_supported_scales) -{ - MetaMonitorManagerClass *manager_class = - META_MONITOR_MANAGER_GET_CLASS (manager); - - return manager_class->calculate_supported_scales (manager, - layout_mode, - monitor, - monitor_mode, - n_supported_scales); -} - -/** - * meta_monitor_manager_get_capabilities: - * @manager: A #MetaMonitorManager object - * - * Queries the capabilities of the monitor manager. - * - * Returns: #MetaMonitorManagerCapability flags representing the capabilities. - */ -MetaMonitorManagerCapability -meta_monitor_manager_get_capabilities (MetaMonitorManager *manager) -{ - MetaMonitorManagerClass *manager_class = - META_MONITOR_MANAGER_GET_CLASS (manager); - - return manager_class->get_capabilities (manager); -} - -gboolean -meta_monitor_manager_get_max_screen_size (MetaMonitorManager *manager, - int *max_width, - int *max_height) -{ - MetaMonitorManagerClass *manager_class = - META_MONITOR_MANAGER_GET_CLASS (manager); - - return manager_class->get_max_screen_size (manager, max_width, max_height); -} - - -MetaLogicalMonitorLayoutMode -meta_monitor_manager_get_default_layout_mode (MetaMonitorManager *manager) -{ - MetaMonitorManagerClass *manager_class = - META_MONITOR_MANAGER_GET_CLASS (manager); - - return manager_class->get_default_layout_mode (manager); -} - -static void -on_virtual_monitor_destroyed (MetaVirtualMonitor *virtual_monitor, - MetaMonitorManager *manager) -{ - MetaMonitorManagerPrivate *priv = - meta_monitor_manager_get_instance_private (manager); - MetaOutput *output; - - output = meta_virtual_monitor_get_output (virtual_monitor); - g_message ("Removed virtual monitor %s", meta_output_get_name (output)); - priv->virtual_monitors = g_list_remove (priv->virtual_monitors, - virtual_monitor); - - if (!priv->shutting_down) - meta_monitor_manager_reload (manager); -} - -MetaVirtualMonitor * -meta_monitor_manager_create_virtual_monitor (MetaMonitorManager *manager, - const MetaVirtualMonitorInfo *info, - GError **error) -{ - MetaMonitorManagerPrivate *priv = - meta_monitor_manager_get_instance_private (manager); - MetaMonitorManagerClass *manager_class = - META_MONITOR_MANAGER_GET_CLASS (manager); - MetaVirtualMonitor *virtual_monitor; - MetaOutput *output; - - if (!manager_class->create_virtual_monitor) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - "Backend doesn't support creating virtual monitors"); - return NULL; - } - - virtual_monitor = manager_class->create_virtual_monitor (manager, info, - error); - if (!virtual_monitor) - return NULL; - - g_signal_connect (virtual_monitor, "destroy", - G_CALLBACK (on_virtual_monitor_destroyed), - manager); - - priv->virtual_monitors = g_list_append (priv->virtual_monitors, - virtual_monitor); - - output = meta_virtual_monitor_get_output (virtual_monitor); - g_message ("Added virtual monitor %s", meta_output_get_name (output)); - - return virtual_monitor; -} - -static void -meta_monitor_manager_ensure_initial_config (MetaMonitorManager *manager) -{ - META_MONITOR_MANAGER_GET_CLASS (manager)->ensure_initial_config (manager); -} - -static gboolean -meta_monitor_manager_apply_monitors_config (MetaMonitorManager *manager, - MetaMonitorsConfig *config, - MetaMonitorsConfigMethod method, - GError **error) -{ - MetaMonitorManagerClass *manager_class = - META_MONITOR_MANAGER_GET_CLASS (manager); - - g_assert (!config || - !(config->flags & META_MONITORS_CONFIG_FLAG_MIGRATED)); - - if (!manager_class->apply_monitors_config (manager, config, method, error)) - return FALSE; - - switch (method) - { - case META_MONITORS_CONFIG_METHOD_TEMPORARY: - case META_MONITORS_CONFIG_METHOD_PERSISTENT: - meta_monitor_config_manager_set_current (manager->config_manager, config); - break; - case META_MONITORS_CONFIG_METHOD_VERIFY: - break; - } - - return TRUE; -} - -gboolean -meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager) -{ - GList *gpus; - GList *l; - - gpus = meta_backend_get_gpus (manager->backend); - for (l = gpus; l; l = l->next) - { - MetaGpu *gpu = l->data; - - if (meta_gpu_has_hotplug_mode_update (gpu)) - return TRUE; - } - - return FALSE; -} - -static gboolean -should_use_stored_config (MetaMonitorManager *manager) -{ - return (manager->in_init || - !meta_monitor_manager_has_hotplug_mode_update (manager)); -} - -MetaMonitorsConfig * -meta_monitor_manager_ensure_configured (MetaMonitorManager *manager) -{ - MetaMonitorsConfig *config = NULL; - GError *error = NULL; - gboolean use_stored_config; - MetaMonitorsConfigMethod method; - MetaMonitorsConfigMethod fallback_method = - META_MONITORS_CONFIG_METHOD_TEMPORARY; - - use_stored_config = should_use_stored_config (manager); - if (use_stored_config) - method = META_MONITORS_CONFIG_METHOD_PERSISTENT; - else - method = META_MONITORS_CONFIG_METHOD_TEMPORARY; - - if (use_stored_config) - { - config = meta_monitor_config_manager_get_stored (manager->config_manager); - if (config) - { - if (!meta_monitor_manager_apply_monitors_config (manager, - config, - method, - &error)) - { - config = NULL; - g_warning ("Failed to use stored monitor configuration: %s", - error->message); - g_clear_error (&error); - } - else - { - g_object_ref (config); - goto done; - } - } - } - - config = meta_monitor_config_manager_create_suggested (manager->config_manager); - if (config) - { - if (!meta_monitor_manager_apply_monitors_config (manager, - config, - method, - &error)) - { - g_clear_object (&config); - g_warning ("Failed to use suggested monitor configuration: %s", - error->message); - g_clear_error (&error); - } - else - { - goto done; - } - } - - config = meta_monitor_config_manager_get_previous (manager->config_manager); - if (config) - { - config = g_object_ref (config); - - if (meta_monitor_manager_is_config_complete (manager, config)) - { - if (!meta_monitor_manager_apply_monitors_config (manager, - config, - method, - &error)) - { - g_warning ("Failed to use suggested monitor configuration: %s", - error->message); - g_clear_error (&error); - } - else - { - goto done; - } - } - - g_clear_object (&config); - } - - config = meta_monitor_config_manager_create_linear (manager->config_manager); - if (config) - { - if (!meta_monitor_manager_apply_monitors_config (manager, - config, - method, - &error)) - { - g_clear_object (&config); - g_warning ("Failed to use linear monitor configuration: %s", - error->message); - g_clear_error (&error); - } - else - { - goto done; - } - } - - config = meta_monitor_config_manager_create_fallback (manager->config_manager); - if (config) - { - if (!meta_monitor_manager_apply_monitors_config (manager, - config, - fallback_method, - &error)) - { - g_clear_object (&config); - g_warning ("Failed to use fallback monitor configuration: %s", - error->message); - g_clear_error (&error); - } - else - { - goto done; - } - } - -done: - if (!config) - { - meta_monitor_manager_apply_monitors_config (manager, - NULL, - fallback_method, - &error); - return NULL; - } - - g_object_unref (config); - - return config; -} - -static void -handle_orientation_change (MetaOrientationManager *orientation_manager, - MetaMonitorManager *manager) -{ - MetaMonitorTransform transform; - GError *error = NULL; - MetaMonitorsConfig *config; - - switch (meta_orientation_manager_get_orientation (orientation_manager)) - { - case META_ORIENTATION_NORMAL: - transform = META_MONITOR_TRANSFORM_NORMAL; - break; - case META_ORIENTATION_BOTTOM_UP: - transform = META_MONITOR_TRANSFORM_180; - break; - case META_ORIENTATION_LEFT_UP: - transform = META_MONITOR_TRANSFORM_90; - break; - case META_ORIENTATION_RIGHT_UP: - transform = META_MONITOR_TRANSFORM_270; - break; - - case META_ORIENTATION_UNDEFINED: - default: - return; - } - - config = - meta_monitor_config_manager_create_for_orientation (manager->config_manager, - transform); - if (!config) - return; - - if (!meta_monitor_manager_apply_monitors_config (manager, - config, - META_MONITORS_CONFIG_METHOD_TEMPORARY, - &error)) - { - g_warning ("Failed to use orientation monitor configuration: %s", - error->message); - g_error_free (error); - } - g_object_unref (config); -} - -/* - * Special case for tablets with a native portrait mode and a keyboard dock, - * where the device gets docked in landscape mode. For this combo to work - * properly with mutter starting while the tablet is docked, we need to take - * the accelerometer reported orientation into account (at mutter startup) - * even if there is a tablet-mode-switch which indicates that the device is - * NOT in tablet-mode (because it is docked). - */ -static gboolean -handle_initial_orientation_change (MetaOrientationManager *orientation_manager, - MetaMonitorManager *manager) -{ - ClutterBackend *clutter_backend; - ClutterSeat *seat; - MetaMonitor *monitor; - MetaMonitorMode *mode; - int width, height; - - clutter_backend = meta_backend_get_clutter_backend (manager->backend); - seat = clutter_backend_get_default_seat (clutter_backend); - - /* - * This is a workaround to ignore the tablet mode switch on the initial config - * of devices with a native portrait mode panel. The touchscreen and - * accelerometer requirements for applying the orientation must still be met. - */ - if (!clutter_seat_has_touchscreen (seat) || - !meta_orientation_manager_has_accelerometer (orientation_manager)) - return FALSE; - - /* Check for a portrait mode panel */ - monitor = meta_monitor_manager_get_laptop_panel (manager); - if (!monitor) - return FALSE; - - mode = meta_monitor_get_preferred_mode (monitor); - meta_monitor_mode_get_resolution (mode, &width, &height); - if (width > height) - return FALSE; - - handle_orientation_change (orientation_manager, manager); - return TRUE; -} - -static void -orientation_changed (MetaOrientationManager *orientation_manager, - MetaMonitorManager *manager) -{ - MetaMonitorManagerPrivate *priv = - meta_monitor_manager_get_instance_private (manager); - - if (!priv->initial_orient_change_done) - { - priv->initial_orient_change_done = TRUE; - if (handle_initial_orientation_change (orientation_manager, manager)) - return; - } - - if (!manager->panel_orientation_managed) - return; - - handle_orientation_change (orientation_manager, manager); -} - -static void -experimental_features_changed (MetaSettings *settings, - MetaExperimentalFeature old_experimental_features, - MetaMonitorManager *manager) -{ - gboolean was_stage_views_scaled; - gboolean is_stage_views_scaled; - gboolean should_reconfigure = FALSE; - - was_stage_views_scaled = - !!(old_experimental_features & - META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER); - is_stage_views_scaled = - meta_settings_is_experimental_feature_enabled ( - settings, - META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER); - - if (is_stage_views_scaled != was_stage_views_scaled) - should_reconfigure = TRUE; - - if (should_reconfigure) - meta_monitor_manager_reconfigure (manager); - - meta_settings_update_ui_scaling_factor (settings); -} - -static void -update_panel_orientation_managed (MetaMonitorManager *manager) -{ - MetaOrientationManager *orientation_manager; - ClutterBackend *clutter_backend; - ClutterSeat *seat; - gboolean panel_orientation_managed; - - clutter_backend = meta_backend_get_clutter_backend (manager->backend); - seat = clutter_backend_get_default_seat (clutter_backend); - - orientation_manager = meta_backend_get_orientation_manager (manager->backend); - - panel_orientation_managed = - (clutter_seat_get_touch_mode (seat) && - meta_orientation_manager_has_accelerometer (orientation_manager)); - - if (manager->panel_orientation_managed == panel_orientation_managed) - return; - - manager->panel_orientation_managed = panel_orientation_managed; - g_object_notify_by_pspec (G_OBJECT (manager), - obj_props[PROP_PANEL_ORIENTATION_MANAGED]); - - meta_dbus_display_config_set_panel_orientation_managed (manager->display_config, - manager->panel_orientation_managed); - - /* The orientation may have changed while it was unmanaged */ - if (panel_orientation_managed) - handle_orientation_change (orientation_manager, manager); -} - -void -meta_monitor_manager_setup (MetaMonitorManager *manager) -{ - manager->in_init = TRUE; - - manager->config_manager = meta_monitor_config_manager_new (manager); - - meta_monitor_manager_read_current_state (manager); - - meta_monitor_manager_ensure_initial_config (manager); - - manager->in_init = FALSE; -} - -static void -meta_monitor_manager_constructed (GObject *object) -{ - MetaMonitorManager *manager = META_MONITOR_MANAGER (object); - MetaBackend *backend = manager->backend; - MetaSettings *settings = meta_backend_get_settings (backend); - - manager->display_config = meta_dbus_display_config_skeleton_new (); - - manager->experimental_features_changed_handler_id = - g_signal_connect (settings, - "experimental-features-changed", - G_CALLBACK (experimental_features_changed), - manager); - - monitor_manager_setup_dbus_config_handlers (manager); - - g_signal_connect_object (manager->display_config, "notify::power-save-mode", - G_CALLBACK (power_save_mode_changed), manager, - G_CONNECT_SWAPPED); - - g_signal_connect_object (meta_backend_get_orientation_manager (backend), - "orientation-changed", - G_CALLBACK (orientation_changed), - manager, 0); - - g_signal_connect_object (meta_backend_get_orientation_manager (backend), - "notify::has-accelerometer", - G_CALLBACK (update_panel_orientation_managed), manager, - G_CONNECT_SWAPPED); - - g_signal_connect_object (backend, - "lid-is-closed-changed", - G_CALLBACK (lid_is_closed_changed), - manager, 0); - - g_signal_connect (backend, "prepare-shutdown", - G_CALLBACK (prepare_shutdown), - manager); - - manager->current_switch_config = META_MONITOR_SWITCH_CONFIG_UNKNOWN; - - initialize_dbus_interface (manager); -} - -static void -meta_monitor_manager_finalize (GObject *object) -{ - MetaMonitorManager *manager = META_MONITOR_MANAGER (object); - MetaMonitorManagerPrivate *priv = - meta_monitor_manager_get_instance_private (manager); - - g_list_free_full (manager->logical_monitors, g_object_unref); - - g_warn_if_fail (!priv->virtual_monitors); - - g_clear_signal_handler (&manager->experimental_features_changed_handler_id, - manager->backend); - - G_OBJECT_CLASS (meta_monitor_manager_parent_class)->finalize (object); -} - -static void -meta_monitor_manager_dispose (GObject *object) -{ - MetaMonitorManager *manager = META_MONITOR_MANAGER (object); - - if (manager->dbus_name_id != 0) - { - g_bus_unown_name (manager->dbus_name_id); - manager->dbus_name_id = 0; - } - - g_clear_object (&manager->display_config); - g_clear_object (&manager->config_manager); - - G_OBJECT_CLASS (meta_monitor_manager_parent_class)->dispose (object); -} - -static GBytes * -meta_monitor_manager_real_read_edid (MetaMonitorManager *manager, - MetaOutput *output) -{ - return NULL; -} - -static void -meta_monitor_manager_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaMonitorManager *manager = META_MONITOR_MANAGER (object); - - switch (prop_id) - { - case PROP_BACKEND: - manager->backend = g_value_get_object (value); - break; - case PROP_PANEL_ORIENTATION_MANAGED: - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_monitor_manager_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaMonitorManager *manager = META_MONITOR_MANAGER (object); - - switch (prop_id) - { - case PROP_BACKEND: - g_value_set_object (value, manager->backend); - break; - case PROP_PANEL_ORIENTATION_MANAGED: - g_value_set_boolean (value, manager->panel_orientation_managed); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_monitor_manager_class_init (MetaMonitorManagerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->constructed = meta_monitor_manager_constructed; - object_class->dispose = meta_monitor_manager_dispose; - object_class->finalize = meta_monitor_manager_finalize; - object_class->get_property = meta_monitor_manager_get_property; - object_class->set_property = meta_monitor_manager_set_property; - - klass->read_edid = meta_monitor_manager_real_read_edid; - klass->read_current_state = meta_monitor_manager_real_read_current_state; - - signals[MONITORS_CHANGED] = - g_signal_new ("monitors-changed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - signals[MONITORS_CHANGED_INTERNAL] = - g_signal_new ("monitors-changed-internal", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - signals[POWER_SAVE_MODE_CHANGED] = - g_signal_new ("power-save-mode-changed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - signals[CONFIRM_DISPLAY_CHANGE] = - g_signal_new ("confirm-display-change", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - 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); - - obj_props[PROP_PANEL_ORIENTATION_MANAGED] = - g_param_spec_boolean ("panel-orientation-managed", - "Panel orientation managed", - "Panel orientation is managed", - FALSE, - G_PARAM_READABLE | - G_PARAM_EXPLICIT_NOTIFY | - G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, PROP_LAST, obj_props); -} - -gboolean -meta_monitor_has_aspect_as_size (MetaMonitor *monitor) -{ - int width_mm; - int height_mm; - - meta_monitor_get_physical_dimensions (monitor, &width_mm, &height_mm); - - return (width_mm == 1600 && height_mm == 900) || - (width_mm == 1600 && height_mm == 1000) || - (width_mm == 160 && height_mm == 90) || - (width_mm == 160 && height_mm == 100) || - (width_mm == 16 && height_mm == 9) || - (width_mm == 16 && height_mm == 10); -} - -static const char * -get_connector_type_name (MetaConnectorType connector_type) -{ - switch (connector_type) - { - case META_CONNECTOR_TYPE_Unknown: return "Unknown"; - case META_CONNECTOR_TYPE_VGA: return "VGA"; - case META_CONNECTOR_TYPE_DVII: return "DVII"; - case META_CONNECTOR_TYPE_DVID: return "DVID"; - case META_CONNECTOR_TYPE_DVIA: return "DVIA"; - case META_CONNECTOR_TYPE_Composite: return "Composite"; - case META_CONNECTOR_TYPE_SVIDEO: return "SVIDEO"; - case META_CONNECTOR_TYPE_LVDS: return "LVDS"; - case META_CONNECTOR_TYPE_Component: return "Component"; - case META_CONNECTOR_TYPE_9PinDIN: return "9PinDIN"; - case META_CONNECTOR_TYPE_DisplayPort: return "DisplayPort"; - case META_CONNECTOR_TYPE_HDMIA: return "HDMIA"; - case META_CONNECTOR_TYPE_HDMIB: return "HDMIB"; - case META_CONNECTOR_TYPE_TV: return "TV"; - case META_CONNECTOR_TYPE_eDP: return "eDP"; - case META_CONNECTOR_TYPE_VIRTUAL: return "VIRTUAL"; - case META_CONNECTOR_TYPE_DSI: return "DSI"; - default: g_assert_not_reached (); - } - return NULL; -} - -static GList * -combine_gpu_lists (MetaMonitorManager *manager, - GList * (*list_getter) (MetaGpu *gpu)) -{ - GList *gpus; - GList *list = NULL; - GList *l; - - gpus = meta_backend_get_gpus (manager->backend); - for (l = gpus; l; l = l->next) - { - MetaGpu *gpu = l->data; - - list = g_list_concat (list, g_list_copy (list_getter (gpu))); - } - - return list; -} - -static gboolean -meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton, - GDBusMethodInvocation *invocation, - MetaMonitorManager *manager) -{ - MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_GET_CLASS (manager); - GList *combined_modes; - GList *combined_outputs; - GList *combined_crtcs; - GVariantBuilder crtc_builder, output_builder, mode_builder; - GList *l; - unsigned int i, j; - int max_screen_width; - int max_screen_height; - - combined_modes = combine_gpu_lists (manager, meta_gpu_get_modes); - combined_outputs = combine_gpu_lists (manager, meta_gpu_get_outputs); - combined_crtcs = combine_gpu_lists (manager, meta_gpu_get_crtcs); - - g_variant_builder_init (&crtc_builder, G_VARIANT_TYPE ("a(uxiiiiiuaua{sv})")); - g_variant_builder_init (&output_builder, G_VARIANT_TYPE ("a(uxiausauaua{sv})")); - g_variant_builder_init (&mode_builder, G_VARIANT_TYPE ("a(uxuudu)")); - - for (l = combined_crtcs, i = 0; l; l = l->next, i++) - { - MetaCrtc *crtc = l->data; - GVariantBuilder transforms; - const MetaCrtcConfig *crtc_config; - - g_variant_builder_init (&transforms, G_VARIANT_TYPE ("au")); - for (j = 0; j <= META_MONITOR_TRANSFORM_FLIPPED_270; j++) - { - if (meta_crtc_get_all_transforms (crtc) & (1 << j)) - g_variant_builder_add (&transforms, "u", j); - } - - crtc_config = meta_crtc_get_config (crtc); - if (crtc_config) - { - int current_mode_index; - - current_mode_index = g_list_index (combined_modes, crtc_config->mode); - g_variant_builder_add (&crtc_builder, "(uxiiiiiuaua{sv})", - i, /* ID */ - (int64_t) meta_crtc_get_id (crtc), - (int) roundf (crtc_config->layout.origin.x), - (int) roundf (crtc_config->layout.origin.y), - (int) roundf (crtc_config->layout.size.width), - (int) roundf (crtc_config->layout.size.height), - current_mode_index, - (uint32_t) crtc_config->transform, - &transforms, - NULL /* properties */); - } - else - { - g_variant_builder_add (&crtc_builder, "(uxiiiiiuaua{sv})", - i, /* ID */ - (int64_t) meta_crtc_get_id (crtc), - 0, - 0, - 0, - 0, - -1, - (uint32_t) META_MONITOR_TRANSFORM_NORMAL, - &transforms, - NULL /* properties */); - } - } - - for (l = combined_outputs, i = 0; l; l = l->next, i++) - { - MetaOutput *output = l->data; - const MetaOutputInfo *output_info = meta_output_get_info (output); - GVariantBuilder crtcs, modes, clones, properties; - GBytes *edid; - MetaCrtc *crtc; - int crtc_index; - int backlight; - int min_backlight_step; - gboolean is_primary; - gboolean is_presentation; - const char * connector_type_name; - gboolean is_underscanning; - gboolean supports_underscanning; - gboolean supports_color_transform; - - g_variant_builder_init (&crtcs, G_VARIANT_TYPE ("au")); - for (j = 0; j < output_info->n_possible_crtcs; j++) - { - MetaCrtc *possible_crtc = output_info->possible_crtcs[j]; - unsigned possible_crtc_index; - - possible_crtc_index = g_list_index (combined_crtcs, possible_crtc); - g_variant_builder_add (&crtcs, "u", possible_crtc_index); - } - - g_variant_builder_init (&modes, G_VARIANT_TYPE ("au")); - for (j = 0; j < output_info->n_modes; j++) - { - unsigned mode_index; - - mode_index = g_list_index (combined_modes, output_info->modes[j]); - g_variant_builder_add (&modes, "u", mode_index); - } - - g_variant_builder_init (&clones, G_VARIANT_TYPE ("au")); - for (j = 0; j < output_info->n_possible_clones; j++) - { - unsigned int possible_clone_index; - - possible_clone_index = g_list_index (combined_outputs, - output_info->possible_clones[j]); - g_variant_builder_add (&clones, "u", possible_clone_index); - } - - backlight = meta_output_get_backlight (output); - min_backlight_step = - output_info->backlight_max - output_info->backlight_min - ? 100 / (output_info->backlight_max - output_info->backlight_min) - : -1; - is_primary = meta_output_is_primary (output); - is_presentation = meta_output_is_presentation (output); - is_underscanning = meta_output_is_underscanning (output); - connector_type_name = get_connector_type_name (output_info->connector_type); - supports_underscanning = output_info->supports_underscanning; - supports_color_transform = output_info->supports_color_transform; - - g_variant_builder_init (&properties, G_VARIANT_TYPE ("a{sv}")); - g_variant_builder_add (&properties, "{sv}", "vendor", - g_variant_new_string (output_info->vendor)); - g_variant_builder_add (&properties, "{sv}", "product", - g_variant_new_string (output_info->product)); - g_variant_builder_add (&properties, "{sv}", "serial", - g_variant_new_string (output_info->serial)); - g_variant_builder_add (&properties, "{sv}", "width-mm", - g_variant_new_int32 (output_info->width_mm)); - g_variant_builder_add (&properties, "{sv}", "height-mm", - g_variant_new_int32 (output_info->height_mm)); - g_variant_builder_add (&properties, "{sv}", "display-name", - g_variant_new_string (output_info->name)); - g_variant_builder_add (&properties, "{sv}", "backlight", - g_variant_new_int32 (backlight)); - g_variant_builder_add (&properties, "{sv}", "min-backlight-step", - g_variant_new_int32 (min_backlight_step)); - g_variant_builder_add (&properties, "{sv}", "primary", - g_variant_new_boolean (is_primary)); - g_variant_builder_add (&properties, "{sv}", "presentation", - g_variant_new_boolean (is_presentation)); - g_variant_builder_add (&properties, "{sv}", "connector-type", - g_variant_new_string (connector_type_name)); - g_variant_builder_add (&properties, "{sv}", "underscanning", - g_variant_new_boolean (is_underscanning)); - g_variant_builder_add (&properties, "{sv}", "supports-underscanning", - g_variant_new_boolean (supports_underscanning)); - g_variant_builder_add (&properties, "{sv}", "supports-color-transform", - g_variant_new_boolean (supports_color_transform)); - - edid = manager_class->read_edid (manager, output); - if (edid) - { - g_variant_builder_add (&properties, "{sv}", "edid", - g_variant_new_from_bytes (G_VARIANT_TYPE ("ay"), - edid, TRUE)); - g_bytes_unref (edid); - } - - if (output_info->tile_info.group_id) - { - GVariant *tile_variant; - - tile_variant = g_variant_new ("(uuuuuuuu)", - output_info->tile_info.group_id, - output_info->tile_info.flags, - output_info->tile_info.max_h_tiles, - output_info->tile_info.max_v_tiles, - output_info->tile_info.loc_h_tile, - output_info->tile_info.loc_v_tile, - output_info->tile_info.tile_w, - output_info->tile_info.tile_h); - g_variant_builder_add (&properties, "{sv}", "tile", tile_variant); - } - - crtc = meta_output_get_assigned_crtc (output); - crtc_index = crtc ? g_list_index (combined_crtcs, crtc) : -1; - g_variant_builder_add (&output_builder, "(uxiausauaua{sv})", - i, /* ID */ - meta_output_get_id (output), - crtc_index, - &crtcs, - meta_output_get_name (output), - &modes, - &clones, - &properties); - } - - for (l = combined_modes, i = 0; l; l = l->next, i++) - { - MetaCrtcMode *mode = l->data; - const MetaCrtcModeInfo *crtc_mode_info = - meta_crtc_mode_get_info (mode); - - g_variant_builder_add (&mode_builder, "(uxuudu)", - i, /* ID */ - (int64_t) meta_crtc_mode_get_id (mode), - (uint32_t) crtc_mode_info->width, - (uint32_t) crtc_mode_info->height, - (double) crtc_mode_info->refresh_rate, - (uint32_t) crtc_mode_info->flags); - } - - if (!meta_monitor_manager_get_max_screen_size (manager, - &max_screen_width, - &max_screen_height)) - { - /* No max screen size, just send something large */ - max_screen_width = 65535; - max_screen_height = 65535; - } - - meta_dbus_display_config_complete_get_resources (skeleton, - invocation, - manager->serial, - g_variant_builder_end (&crtc_builder), - g_variant_builder_end (&output_builder), - g_variant_builder_end (&mode_builder), - max_screen_width, - max_screen_height); - - g_list_free (combined_modes); - g_list_free (combined_outputs); - g_list_free (combined_crtcs); - - return TRUE; -} - -static void -restore_previous_config (MetaMonitorManager *manager) -{ - MetaMonitorsConfig *previous_config; - GError *error = NULL; - - previous_config = - meta_monitor_config_manager_pop_previous (manager->config_manager); - - if (previous_config) - { - MetaMonitorsConfigMethod method; - - method = META_MONITORS_CONFIG_METHOD_TEMPORARY; - if (meta_monitor_manager_apply_monitors_config (manager, - previous_config, - method, - &error)) - { - g_object_unref (previous_config); - return; - } - else - { - g_object_unref (previous_config); - g_warning ("Failed to restore previous configuration: %s", - error->message); - g_error_free (error); - } - } - - meta_monitor_manager_ensure_configured (manager); -} - -gint -meta_monitor_manager_get_display_configuration_timeout (void) -{ - return DEFAULT_DISPLAY_CONFIGURATION_TIMEOUT; -} - -static gboolean -save_config_timeout (gpointer user_data) -{ - MetaMonitorManager *manager = user_data; - - restore_previous_config (manager); - manager->persistent_timeout_id = 0; - - return G_SOURCE_REMOVE; -} - -static void -cancel_persistent_confirmation (MetaMonitorManager *manager) -{ - g_clear_handle_id (&manager->persistent_timeout_id, g_source_remove); -} - -static void -request_persistent_confirmation (MetaMonitorManager *manager) -{ - manager->persistent_timeout_id = g_timeout_add_seconds (meta_monitor_manager_get_display_configuration_timeout (), - save_config_timeout, - manager); - g_source_set_name_by_id (manager->persistent_timeout_id, - "[mutter] save_config_timeout"); - - g_signal_emit (manager, signals[CONFIRM_DISPLAY_CHANGE], 0); -} - -#define META_DISPLAY_CONFIG_MODE_FLAGS_PREFERRED (1 << 0) -#define META_DISPLAY_CONFIG_MODE_FLAGS_CURRENT (1 << 1) - -#define MODE_FORMAT "(siiddada{sv})" -#define MODES_FORMAT "a" MODE_FORMAT -#define MONITOR_SPEC_FORMAT "(ssss)" -#define MONITOR_FORMAT "(" MONITOR_SPEC_FORMAT MODES_FORMAT "a{sv})" -#define MONITORS_FORMAT "a" MONITOR_FORMAT - -#define LOGICAL_MONITOR_MONITORS_FORMAT "a" MONITOR_SPEC_FORMAT -#define LOGICAL_MONITOR_FORMAT "(iidub" LOGICAL_MONITOR_MONITORS_FORMAT "a{sv})" -#define LOGICAL_MONITORS_FORMAT "a" LOGICAL_MONITOR_FORMAT - -static gboolean -meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton, - GDBusMethodInvocation *invocation, - MetaMonitorManager *manager) -{ - MetaSettings *settings = meta_backend_get_settings (manager->backend); - GVariantBuilder monitors_builder; - GVariantBuilder logical_monitors_builder; - GVariantBuilder properties_builder; - GList *l; - int i; - MetaMonitorManagerCapability capabilities; - int ui_scaling_factor; - int max_screen_width, max_screen_height; - - g_variant_builder_init (&monitors_builder, - G_VARIANT_TYPE (MONITORS_FORMAT)); - g_variant_builder_init (&logical_monitors_builder, - G_VARIANT_TYPE (LOGICAL_MONITORS_FORMAT)); - - for (l = manager->monitors; l; l = l->next) - { - MetaMonitor *monitor = l->data; - MetaMonitorSpec *monitor_spec = meta_monitor_get_spec (monitor); - MetaMonitorMode *current_mode; - MetaMonitorMode *preferred_mode; - GVariantBuilder modes_builder; - GVariantBuilder monitor_properties_builder; - GList *k; - gboolean is_builtin; - const char *display_name; - - current_mode = meta_monitor_get_current_mode (monitor); - preferred_mode = meta_monitor_get_preferred_mode (monitor); - - g_variant_builder_init (&modes_builder, G_VARIANT_TYPE (MODES_FORMAT)); - for (k = meta_monitor_get_modes (monitor); k; k = k->next) - { - MetaMonitorMode *monitor_mode = k->data; - GVariantBuilder supported_scales_builder; - const char *mode_id; - int mode_width, mode_height; - float refresh_rate; - float preferred_scale; - float *supported_scales; - int n_supported_scales; - GVariantBuilder mode_properties_builder; - MetaCrtcModeFlag mode_flags; - - if (!meta_monitor_mode_should_be_advertised (monitor_mode)) - continue; - - mode_id = meta_monitor_mode_get_id (monitor_mode); - meta_monitor_mode_get_resolution (monitor_mode, - &mode_width, &mode_height); - - refresh_rate = meta_monitor_mode_get_refresh_rate (monitor_mode); - - preferred_scale = - meta_monitor_manager_calculate_monitor_mode_scale (manager, - monitor, - monitor_mode); - - g_variant_builder_init (&supported_scales_builder, - G_VARIANT_TYPE ("ad")); - supported_scales = - meta_monitor_manager_calculate_supported_scales (manager, - manager->layout_mode, - monitor, - monitor_mode, - &n_supported_scales); - for (i = 0; i < n_supported_scales; i++) - g_variant_builder_add (&supported_scales_builder, "d", - (double) supported_scales[i]); - g_free (supported_scales); - - mode_flags = meta_monitor_mode_get_flags (monitor_mode); - - g_variant_builder_init (&mode_properties_builder, - G_VARIANT_TYPE ("a{sv}")); - if (monitor_mode == current_mode) - g_variant_builder_add (&mode_properties_builder, "{sv}", - "is-current", - g_variant_new_boolean (TRUE)); - if (monitor_mode == preferred_mode) - g_variant_builder_add (&mode_properties_builder, "{sv}", - "is-preferred", - g_variant_new_boolean (TRUE)); - if (mode_flags & META_CRTC_MODE_FLAG_INTERLACE) - g_variant_builder_add (&mode_properties_builder, "{sv}", - "is-interlaced", - g_variant_new_boolean (TRUE)); - - g_variant_builder_add (&modes_builder, MODE_FORMAT, - mode_id, - mode_width, - mode_height, - refresh_rate, - (double) preferred_scale, - &supported_scales_builder, - &mode_properties_builder); - } - - g_variant_builder_init (&monitor_properties_builder, - G_VARIANT_TYPE ("a{sv}")); - if (meta_monitor_supports_underscanning (monitor)) - { - gboolean is_underscanning = meta_monitor_is_underscanning (monitor); - - g_variant_builder_add (&monitor_properties_builder, "{sv}", - "is-underscanning", - g_variant_new_boolean (is_underscanning)); - } - - is_builtin = meta_monitor_is_laptop_panel (monitor); - g_variant_builder_add (&monitor_properties_builder, "{sv}", - "is-builtin", - g_variant_new_boolean (is_builtin)); - - display_name = meta_monitor_get_display_name (monitor); - g_variant_builder_add (&monitor_properties_builder, "{sv}", - "display-name", - g_variant_new_string (display_name)); - - g_variant_builder_add (&monitors_builder, MONITOR_FORMAT, - monitor_spec->connector, - monitor_spec->vendor, - monitor_spec->product, - monitor_spec->serial, - &modes_builder, - &monitor_properties_builder); - } - - for (l = manager->logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - GVariantBuilder logical_monitor_monitors_builder; - GList *k; - - g_variant_builder_init (&logical_monitor_monitors_builder, - G_VARIANT_TYPE (LOGICAL_MONITOR_MONITORS_FORMAT)); - - for (k = logical_monitor->monitors; k; k = k->next) - { - MetaMonitor *monitor = k->data; - MetaMonitorSpec *monitor_spec = meta_monitor_get_spec (monitor); - - g_variant_builder_add (&logical_monitor_monitors_builder, - MONITOR_SPEC_FORMAT, - monitor_spec->connector, - monitor_spec->vendor, - monitor_spec->product, - monitor_spec->serial); - } - - g_variant_builder_add (&logical_monitors_builder, - LOGICAL_MONITOR_FORMAT, - logical_monitor->rect.x, - logical_monitor->rect.y, - (double) logical_monitor->scale, - logical_monitor->transform, - logical_monitor->is_primary, - &logical_monitor_monitors_builder, - NULL); - } - - g_variant_builder_init (&properties_builder, G_VARIANT_TYPE ("a{sv}")); - capabilities = meta_monitor_manager_get_capabilities (manager); - - g_variant_builder_add (&properties_builder, "{sv}", - "layout-mode", - g_variant_new_uint32 (manager->layout_mode)); - if (capabilities & META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE) - { - g_variant_builder_add (&properties_builder, "{sv}", - "supports-changing-layout-mode", - g_variant_new_boolean (TRUE)); - } - - if (capabilities & META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED) - { - g_variant_builder_add (&properties_builder, "{sv}", - "global-scale-required", - g_variant_new_boolean (TRUE)); - } - - ui_scaling_factor = meta_settings_get_ui_scaling_factor (settings); - g_variant_builder_add (&properties_builder, "{sv}", - "legacy-ui-scaling-factor", - g_variant_new_int32 (ui_scaling_factor)); - - if (meta_monitor_manager_get_max_screen_size (manager, - &max_screen_width, - &max_screen_height)) - { - GVariantBuilder max_screen_size_builder; - - g_variant_builder_init (&max_screen_size_builder, - G_VARIANT_TYPE ("(ii)")); - g_variant_builder_add (&max_screen_size_builder, "i", - max_screen_width); - g_variant_builder_add (&max_screen_size_builder, "i", - max_screen_height); - - g_variant_builder_add (&properties_builder, "{sv}", - "max-screen-size", - g_variant_builder_end (&max_screen_size_builder)); - } - - meta_dbus_display_config_complete_get_current_state ( - skeleton, - invocation, - manager->serial, - g_variant_builder_end (&monitors_builder), - g_variant_builder_end (&logical_monitors_builder), - g_variant_builder_end (&properties_builder)); - - return TRUE; -} - -#undef MODE_FORMAT -#undef MODES_FORMAT -#undef MONITOR_SPEC_FORMAT -#undef MONITOR_FORMAT -#undef MONITORS_FORMAT -#undef LOGICAL_MONITOR_MONITORS_FORMAT -#undef LOGICAL_MONITOR_FORMAT -#undef LOGICAL_MONITORS_FORMAT - -gboolean -meta_monitor_manager_is_scale_supported (MetaMonitorManager *manager, - MetaLogicalMonitorLayoutMode layout_mode, - MetaMonitor *monitor, - MetaMonitorMode *monitor_mode, - float scale) -{ - g_autofree float *supported_scales = NULL; - int n_supported_scales; - int i; - - supported_scales = - meta_monitor_manager_calculate_supported_scales (manager, - layout_mode, - monitor, - monitor_mode, - &n_supported_scales); - for (i = 0; i < n_supported_scales; i++) - { - if (supported_scales[i] == scale) - return TRUE; - } - - return FALSE; -} - -static gboolean -meta_monitor_manager_is_config_applicable (MetaMonitorManager *manager, - MetaMonitorsConfig *config, - GError **error) -{ - GList *l; - - for (l = config->logical_monitor_configs; l; l = l->next) - { - MetaLogicalMonitorConfig *logical_monitor_config = l->data; - float scale = logical_monitor_config->scale; - GList *k; - - for (k = logical_monitor_config->monitor_configs; k; k = k->next) - { - MetaMonitorConfig *monitor_config = k->data; - MetaMonitorSpec *monitor_spec = monitor_config->monitor_spec; - MetaMonitorModeSpec *mode_spec = monitor_config->mode_spec; - MetaMonitor *monitor; - MetaMonitorMode *monitor_mode; - - monitor = meta_monitor_manager_get_monitor_from_spec (manager, - monitor_spec); - if (!monitor) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Specified monitor not found"); - return FALSE; - } - - monitor_mode = meta_monitor_get_mode_from_spec (monitor, mode_spec); - if (!monitor_mode) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Specified monitor mode not available"); - return FALSE; - } - - if (!meta_monitor_manager_is_scale_supported (manager, - config->layout_mode, - monitor, - monitor_mode, - scale)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Scale not supported by backend"); - return FALSE; - } - - if (meta_monitor_is_laptop_panel (monitor) && - meta_backend_is_lid_closed (manager->backend)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Refusing to activate a closed laptop panel"); - return FALSE; - } - } - } - - return TRUE; -} - -static gboolean -meta_monitor_manager_is_config_complete (MetaMonitorManager *manager, - MetaMonitorsConfig *config) -{ - MetaMonitorsConfigKey *current_state_key; - gboolean is_config_complete; - - current_state_key = - meta_create_monitors_config_key_for_current_state (manager); - if (!current_state_key) - return FALSE; - - is_config_complete = meta_monitors_config_key_equal (current_state_key, - config->key); - meta_monitors_config_key_free (current_state_key); - - if (!is_config_complete) - return FALSE; - - return meta_monitor_manager_is_config_applicable (manager, config, NULL); -} - -static MetaMonitor * -find_monitor_from_connector (MetaMonitorManager *manager, - char *connector) -{ - GList *monitors; - GList *l; - - if (!connector) - return NULL; - - monitors = meta_monitor_manager_get_monitors (manager); - for (l = monitors; l; l = l->next) - { - MetaMonitor *monitor = l->data; - MetaMonitorSpec *monitor_spec = meta_monitor_get_spec (monitor); - - if (g_str_equal (connector, monitor_spec->connector)) - return monitor; - } - - return NULL; -} - -#define MONITOR_CONFIG_FORMAT "(ssa{sv})" -#define MONITOR_CONFIGS_FORMAT "a" MONITOR_CONFIG_FORMAT - -#define LOGICAL_MONITOR_CONFIG_FORMAT "(iidub" MONITOR_CONFIGS_FORMAT ")" - -static MetaMonitorConfig * -create_monitor_config_from_variant (MetaMonitorManager *manager, - GVariant *monitor_config_variant, - GError **error) -{ - - MetaMonitorConfig *monitor_config = NULL; - g_autofree char *connector = NULL; - g_autofree char *mode_id = NULL; - MetaMonitorMode *monitor_mode; - MetaMonitor *monitor; - MetaMonitorSpec *monitor_spec; - MetaMonitorModeSpec *monitor_mode_spec; - g_autoptr (GVariant) properties_variant = NULL; - gboolean enable_underscanning = FALSE; - gboolean set_underscanning = FALSE; - - g_variant_get (monitor_config_variant, "(ss@a{sv})", - &connector, - &mode_id, - &properties_variant); - - monitor = find_monitor_from_connector (manager, connector); - if (!monitor) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Invalid connector '%s' specified", connector); - return NULL; - } - - monitor_mode = meta_monitor_get_mode_from_id (monitor, mode_id); - if (!monitor_mode) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Invalid mode '%s' specified", mode_id); - return NULL; - } - - set_underscanning = - g_variant_lookup (properties_variant, "underscanning", "b", - &enable_underscanning); - if (set_underscanning) - { - if (enable_underscanning && !meta_monitor_supports_underscanning (monitor)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Underscanning requested but unsupported"); - return NULL; - } - } - - monitor_spec = meta_monitor_spec_clone (meta_monitor_get_spec (monitor)); - - monitor_mode_spec = g_new0 (MetaMonitorModeSpec, 1); - *monitor_mode_spec = *meta_monitor_mode_get_spec (monitor_mode); - - monitor_config = g_new0 (MetaMonitorConfig, 1); - *monitor_config = (MetaMonitorConfig) { - .monitor_spec = monitor_spec, - .mode_spec = monitor_mode_spec, - .enable_underscanning = enable_underscanning - }; - - return monitor_config; -} - -static gboolean -find_monitor_mode_scale (MetaMonitorManager *manager, - MetaLogicalMonitorLayoutMode layout_mode, - MetaMonitorConfig *monitor_config, - float scale, - float *out_scale, - GError **error) -{ - MetaMonitorSpec *monitor_spec; - MetaMonitor *monitor; - MetaMonitorModeSpec *monitor_mode_spec; - MetaMonitorMode *monitor_mode; - g_autofree float *supported_scales = NULL; - int n_supported_scales; - int i; - - monitor_spec = monitor_config->monitor_spec; - monitor = meta_monitor_manager_get_monitor_from_spec (manager, - monitor_spec); - if (!monitor) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Monitor not found"); - return FALSE; - } - - monitor_mode_spec = monitor_config->mode_spec; - monitor_mode = meta_monitor_get_mode_from_spec (monitor, - monitor_mode_spec); - if (!monitor_mode) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Monitor mode not found"); - return FALSE; - } - - supported_scales = - meta_monitor_manager_calculate_supported_scales (manager, layout_mode, - monitor, monitor_mode, - &n_supported_scales); - - for (i = 0; i < n_supported_scales; i++) - { - float supported_scale = supported_scales[i]; - - if (fabsf (supported_scale - scale) < FLT_EPSILON) - { - *out_scale = supported_scale; - return TRUE; - } - } - - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Scale %g not valid for resolution %dx%d", - scale, - monitor_mode_spec->width, - monitor_mode_spec->height); - return FALSE; -} - -static gboolean -derive_logical_monitor_size (MetaMonitorConfig *monitor_config, - int *out_width, - int *out_height, - float scale, - MetaMonitorTransform transform, - MetaLogicalMonitorLayoutMode layout_mode, - GError **error) -{ - int width, height; - - if (meta_monitor_transform_is_rotated (transform)) - { - width = monitor_config->mode_spec->height; - height = monitor_config->mode_spec->width; - } - else - { - width = monitor_config->mode_spec->width; - height = monitor_config->mode_spec->height; - } - - switch (layout_mode) - { - case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL: - width = roundf (width / scale); - height = roundf (height / scale); - break; - case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL: - break; - } - - *out_width = width; - *out_height = height; - - return TRUE; -} - -static MetaLogicalMonitorConfig * -create_logical_monitor_config_from_variant (MetaMonitorManager *manager, - GVariant *logical_monitor_config_variant, - MetaLogicalMonitorLayoutMode layout_mode, - GError **error) -{ - MetaLogicalMonitorConfig *logical_monitor_config; - int x, y, width, height; - double scale_d; - float scale; - MetaMonitorTransform transform; - gboolean is_primary; - GVariantIter *monitor_configs_iter; - GList *monitor_configs = NULL; - MetaMonitorConfig *monitor_config; - - g_variant_get (logical_monitor_config_variant, LOGICAL_MONITOR_CONFIG_FORMAT, - &x, - &y, - &scale_d, - &transform, - &is_primary, - &monitor_configs_iter); - scale = (float) scale_d; - - while (TRUE) - { - GVariant *monitor_config_variant = - g_variant_iter_next_value (monitor_configs_iter); - MetaMonitorConfig *monitor_config; - - if (!monitor_config_variant) - break; - - monitor_config = - create_monitor_config_from_variant (manager, - monitor_config_variant, error); - g_variant_unref (monitor_config_variant); - - if (!monitor_config) - goto err; - - if (!meta_verify_monitor_config (monitor_config, error)) - { - meta_monitor_config_free (monitor_config); - goto err; - } - - monitor_configs = g_list_append (monitor_configs, monitor_config); - } - g_variant_iter_free (monitor_configs_iter); - - if (!monitor_configs) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Empty logical monitor"); - goto err; - } - - monitor_config = monitor_configs->data; - if (!find_monitor_mode_scale (manager, - layout_mode, - monitor_config, - scale, - &scale, - error)) - goto err; - - if (!derive_logical_monitor_size (monitor_config, &width, &height, - scale, transform, layout_mode, error)) - goto err; - - logical_monitor_config = g_new0 (MetaLogicalMonitorConfig, 1); - *logical_monitor_config = (MetaLogicalMonitorConfig) { - .layout = { - .x = x, - .y = y, - .width = width, - .height = height - }, - .transform = transform, - .scale = scale, - .is_primary = is_primary, - .monitor_configs = monitor_configs - }; - - if (!meta_verify_logical_monitor_config (logical_monitor_config, - layout_mode, - manager, - error)) - { - meta_logical_monitor_config_free (logical_monitor_config); - return NULL; - } - - return logical_monitor_config; - -err: - g_list_free_full (monitor_configs, (GDestroyNotify) meta_monitor_config_free); - return NULL; -} - -static gboolean -is_valid_layout_mode (MetaLogicalMonitorLayoutMode layout_mode) -{ - switch (layout_mode) - { - case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL: - case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL: - return TRUE; - } - - return FALSE; -} - -static gboolean -meta_monitor_manager_handle_apply_monitors_config (MetaDBusDisplayConfig *skeleton, - GDBusMethodInvocation *invocation, - guint serial, - guint method, - GVariant *logical_monitor_configs_variant, - GVariant *properties_variant, - MetaMonitorManager *manager) -{ - MetaMonitorManagerCapability capabilities; - GVariant *layout_mode_variant = NULL; - MetaLogicalMonitorLayoutMode layout_mode; - GVariantIter logical_monitor_configs_iter; - MetaMonitorsConfig *config; - GList *logical_monitor_configs = NULL; - GError *error = NULL; - - if (serial != manager->serial) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "The requested configuration is based on stale information"); - return TRUE; - } - - capabilities = meta_monitor_manager_get_capabilities (manager); - - if (properties_variant) - layout_mode_variant = g_variant_lookup_value (properties_variant, - "layout-mode", - G_VARIANT_TYPE ("u")); - - if (layout_mode_variant && - capabilities & META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE) - { - g_variant_get (layout_mode_variant, "u", &layout_mode); - } - else if (!layout_mode_variant) - { - layout_mode = - meta_monitor_manager_get_default_layout_mode (manager); - } - else - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_INVALID_ARGS, - "Can't set layout mode"); - return TRUE; - } - - if (!is_valid_layout_mode (layout_mode)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Invalid layout mode specified"); - return TRUE; - } - - g_variant_iter_init (&logical_monitor_configs_iter, - logical_monitor_configs_variant); - while (TRUE) - { - GVariant *logical_monitor_config_variant = - g_variant_iter_next_value (&logical_monitor_configs_iter); - MetaLogicalMonitorConfig *logical_monitor_config; - - if (!logical_monitor_config_variant) - break; - - logical_monitor_config = - create_logical_monitor_config_from_variant (manager, - logical_monitor_config_variant, - layout_mode, - &error); - g_variant_unref (logical_monitor_config_variant); - - if (!logical_monitor_config) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_INVALID_ARGS, - "%s", error->message); - g_error_free (error); - g_list_free_full (logical_monitor_configs, - (GDestroyNotify) meta_logical_monitor_config_free); - return TRUE; - } - - logical_monitor_configs = g_list_append (logical_monitor_configs, - logical_monitor_config); - } - - config = meta_monitors_config_new (manager, - logical_monitor_configs, - layout_mode, - META_MONITORS_CONFIG_FLAG_NONE); - if (!meta_verify_monitors_config (config, manager, &error)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_INVALID_ARGS, - "%s", error->message); - g_error_free (error); - g_object_unref (config); - return TRUE; - } - - if (!meta_monitor_manager_is_config_applicable (manager, config, &error)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_INVALID_ARGS, - "%s", error->message); - g_error_free (error); - g_object_unref (config); - return TRUE; - } - - if (manager->persistent_timeout_id && - method != META_MONITORS_CONFIG_METHOD_VERIFY) - cancel_persistent_confirmation (manager); - - if (!meta_monitor_manager_apply_monitors_config (manager, - config, - method, - &error)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_INVALID_ARGS, - "%s", error->message); - g_error_free (error); - g_object_unref (config); - return TRUE; - } - - if (method == META_MONITORS_CONFIG_METHOD_PERSISTENT) - request_persistent_confirmation (manager); - - meta_dbus_display_config_complete_apply_monitors_config (skeleton, invocation); - - return TRUE; -} - -#undef MONITOR_MODE_SPEC_FORMAT -#undef MONITOR_CONFIG_FORMAT -#undef MONITOR_CONFIGS_FORMAT -#undef LOGICAL_MONITOR_CONFIG_FORMAT - -static void -confirm_configuration (MetaMonitorManager *manager, - gboolean confirmed) -{ - if (confirmed) - meta_monitor_config_manager_save_current (manager->config_manager); - else - restore_previous_config (manager); -} - -void -meta_monitor_manager_confirm_configuration (MetaMonitorManager *manager, - gboolean ok) -{ - if (!manager->persistent_timeout_id) - { - /* too late */ - return; - } - - cancel_persistent_confirmation (manager); - confirm_configuration (manager, ok); -} - -static gboolean -meta_monitor_manager_handle_change_backlight (MetaDBusDisplayConfig *skeleton, - GDBusMethodInvocation *invocation, - guint serial, - guint output_index, - gint value, - MetaMonitorManager *manager) -{ - GList *combined_outputs; - MetaOutput *output; - const MetaOutputInfo *output_info; - int new_backlight; - - if (serial != manager->serial) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "The requested configuration is based on stale information"); - return TRUE; - } - - combined_outputs = combine_gpu_lists (manager, meta_gpu_get_outputs); - - if (output_index >= g_list_length (combined_outputs)) - { - g_list_free (combined_outputs); - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_INVALID_ARGS, - "Invalid output id"); - return TRUE; - } - output = g_list_nth_data (combined_outputs, output_index); - g_list_free (combined_outputs); - - if (value < 0 || value > 100) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_INVALID_ARGS, - "Invalid backlight value"); - return TRUE; - } - - output_info = meta_output_get_info (output); - if (meta_output_get_backlight (output) == -1 || - (output_info->backlight_min == 0 && - output_info->backlight_max == 0)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_INVALID_ARGS, - "Output does not support changing backlight"); - return TRUE; - } - - META_MONITOR_MANAGER_GET_CLASS (manager)->change_backlight (manager, output, value); - - new_backlight = meta_output_get_backlight (output); - meta_dbus_display_config_complete_change_backlight (skeleton, - invocation, - new_backlight); - return TRUE; -} - -static gboolean -meta_monitor_manager_handle_get_crtc_gamma (MetaDBusDisplayConfig *skeleton, - GDBusMethodInvocation *invocation, - guint serial, - guint crtc_id, - MetaMonitorManager *manager) -{ - MetaMonitorManagerClass *klass; - GList *combined_crtcs; - MetaCrtc *crtc; - gsize size; - unsigned short *red; - unsigned short *green; - unsigned short *blue; - GBytes *red_bytes, *green_bytes, *blue_bytes; - GVariant *red_v, *green_v, *blue_v; - - if (serial != manager->serial) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "The requested configuration is based on stale information"); - return TRUE; - } - - combined_crtcs = combine_gpu_lists (manager, meta_gpu_get_crtcs); - if (crtc_id >= g_list_length (combined_crtcs)) - { - g_list_free (combined_crtcs); - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_INVALID_ARGS, - "Invalid crtc id"); - return TRUE; - } - - crtc = g_list_nth_data (combined_crtcs, crtc_id); - g_list_free (combined_crtcs); - - klass = META_MONITOR_MANAGER_GET_CLASS (manager); - if (klass->get_crtc_gamma) - klass->get_crtc_gamma (manager, crtc, &size, &red, &green, &blue); - else - { - size = 0; - red = green = blue = NULL; - } - - red_bytes = g_bytes_new_take (red, size * sizeof (unsigned short)); - green_bytes = g_bytes_new_take (green, size * sizeof (unsigned short)); - blue_bytes = g_bytes_new_take (blue, size * sizeof (unsigned short)); - - red_v = g_variant_new_from_bytes (G_VARIANT_TYPE ("aq"), red_bytes, TRUE); - green_v = g_variant_new_from_bytes (G_VARIANT_TYPE ("aq"), green_bytes, TRUE); - blue_v = g_variant_new_from_bytes (G_VARIANT_TYPE ("aq"), blue_bytes, TRUE); - - meta_dbus_display_config_complete_get_crtc_gamma (skeleton, invocation, - red_v, green_v, blue_v); - - g_bytes_unref (red_bytes); - g_bytes_unref (green_bytes); - g_bytes_unref (blue_bytes); - - return TRUE; -} - -static gboolean -meta_monitor_manager_handle_set_crtc_gamma (MetaDBusDisplayConfig *skeleton, - GDBusMethodInvocation *invocation, - guint serial, - guint crtc_id, - GVariant *red_v, - GVariant *green_v, - GVariant *blue_v, - MetaMonitorManager *manager) -{ - MetaMonitorManagerClass *klass; - GList *combined_crtcs; - MetaCrtc *crtc; - gsize size, dummy; - unsigned short *red; - unsigned short *green; - unsigned short *blue; - GBytes *red_bytes, *green_bytes, *blue_bytes; - - if (serial != manager->serial) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "The requested configuration is based on stale information"); - return TRUE; - } - - combined_crtcs = combine_gpu_lists (manager, meta_gpu_get_crtcs); - - if (crtc_id >= g_list_length (combined_crtcs)) - { - g_list_free (combined_crtcs); - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_INVALID_ARGS, - "Invalid crtc id"); - return TRUE; - } - - crtc = g_list_nth_data (combined_crtcs, crtc_id); - g_list_free (combined_crtcs); - - red_bytes = g_variant_get_data_as_bytes (red_v); - green_bytes = g_variant_get_data_as_bytes (green_v); - blue_bytes = g_variant_get_data_as_bytes (blue_v); - - size = g_bytes_get_size (red_bytes) / sizeof (unsigned short); - red = (unsigned short*) g_bytes_get_data (red_bytes, &dummy); - green = (unsigned short*) g_bytes_get_data (green_bytes, &dummy); - blue = (unsigned short*) g_bytes_get_data (blue_bytes, &dummy); - - klass = META_MONITOR_MANAGER_GET_CLASS (manager); - if (klass->set_crtc_gamma) - klass->set_crtc_gamma (manager, crtc, size, red, green, blue); - meta_dbus_display_config_complete_set_crtc_gamma (skeleton, invocation); - - g_bytes_unref (red_bytes); - g_bytes_unref (green_bytes); - g_bytes_unref (blue_bytes); - - return TRUE; -} - -static gboolean -meta_monitor_manager_handle_set_output_ctm (MetaDBusDisplayConfig *skeleton, - GDBusMethodInvocation *invocation, - guint serial, - guint output_id, - GVariant *ctm_var, - MetaMonitorManager *manager) -{ - MetaMonitorManagerClass *klass; - GList *combined_outputs; - MetaOutput *output; - MetaOutputCtm ctm; - int i; - - if (serial != manager->serial) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "The requested configuration is based on stale information"); - return TRUE; - } - - combined_outputs = combine_gpu_lists (manager, meta_gpu_get_outputs); - - if (output_id >= g_list_length (combined_outputs)) - { - g_list_free (combined_outputs); - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_INVALID_ARGS, - "Invalid output id"); - return TRUE; - } - - output = g_list_nth_data (combined_outputs, output_id); - g_list_free (combined_outputs); - - if (g_variant_n_children (ctm_var) != 9) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_INVALID_ARGS, - "Unexpected color transform matrix variant length"); - return TRUE; - } - - for (i = 0; i < 9; i++) - { - GVariant *tmp = g_variant_get_child_value (ctm_var, i); - ctm.matrix[i] = g_variant_get_uint64 (tmp); - g_variant_unref (tmp); - } - - klass = META_MONITOR_MANAGER_GET_CLASS (manager); - if (klass->set_output_ctm) - klass->set_output_ctm (output, &ctm); - meta_dbus_display_config_complete_set_output_ctm (skeleton, invocation); - - return TRUE; -} - -static void -monitor_manager_setup_dbus_config_handlers (MetaMonitorManager *manager) -{ - g_signal_connect_object (manager->display_config, "handle-get-resources", - G_CALLBACK (meta_monitor_manager_handle_get_resources), - manager, 0); - g_signal_connect_object (manager->display_config, "handle-change-backlight", - G_CALLBACK (meta_monitor_manager_handle_change_backlight), - manager, 0); - g_signal_connect_object (manager->display_config, "handle-get-crtc-gamma", - G_CALLBACK (meta_monitor_manager_handle_get_crtc_gamma), - manager, 0); - g_signal_connect_object (manager->display_config, "handle-set-crtc-gamma", - G_CALLBACK (meta_monitor_manager_handle_set_crtc_gamma), - manager, 0); - g_signal_connect_object (manager->display_config, "handle-get-current-state", - G_CALLBACK (meta_monitor_manager_handle_get_current_state), - manager, 0); - g_signal_connect_object (manager->display_config, "handle-apply-monitors-config", - G_CALLBACK (meta_monitor_manager_handle_apply_monitors_config), - manager, 0); - g_signal_connect_object (manager->display_config, "handle-set-output-ctm", - G_CALLBACK (meta_monitor_manager_handle_set_output_ctm), - manager, 0); -} - -static void -on_bus_acquired (GDBusConnection *connection, - const char *name, - gpointer user_data) -{ - MetaMonitorManager *manager = user_data; - - g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (manager->display_config), - connection, - "/org/gnome/Mutter/DisplayConfig", - NULL); -} - -static void -on_name_acquired (GDBusConnection *connection, - const char *name, - gpointer user_data) -{ - meta_topic (META_DEBUG_DBUS, "Acquired name %s", name); -} - -static void -on_name_lost (GDBusConnection *connection, - const char *name, - gpointer user_data) -{ - meta_topic (META_DEBUG_DBUS, "Lost or failed to acquire name %s", name); -} - -static void -initialize_dbus_interface (MetaMonitorManager *manager) -{ - MetaContext *context = meta_backend_get_context (manager->backend); - - manager->dbus_name_id = - g_bus_own_name (G_BUS_TYPE_SESSION, - "org.gnome.Mutter.DisplayConfig", - G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | - (meta_context_is_replacing (context) ? - G_BUS_NAME_OWNER_FLAGS_REPLACE : - G_BUS_NAME_OWNER_FLAGS_NONE), - on_bus_acquired, - on_name_acquired, - on_name_lost, - g_object_ref (manager), - g_object_unref); -} - -/** - * meta_monitor_manager_get: - * - * Accessor for the singleton MetaMonitorManager. - * - * Returns: (transfer none): The only #MetaMonitorManager there is. - */ -MetaMonitorManager * -meta_monitor_manager_get (void) -{ - MetaBackend *backend = meta_get_backend (); - - return meta_backend_get_monitor_manager (backend); -} - -/** - * meta_monitor_manager_get_num_logical_monitors: - * @manager: A #MetaMonitorManager object - * - * Returns the number of #MetaLogicalMonitors (can be 0 in case of a - * headless setup). - * - * Returns: the total number of #MetaLogicalMonitors. - */ -int -meta_monitor_manager_get_num_logical_monitors (MetaMonitorManager *manager) -{ - return g_list_length (manager->logical_monitors); -} - -/** - * meta_monitor_manager_get_logical_monitors: - * @manager: A #MetaMonitorManager object - * - * Returns the list of #MetaLogicalMonitors that is handled. See also - * meta_monitor_manager_get_num_logical_monitors() if you only need the size of - * the list. - * - * Returns: (transfer none) (nullable): the list of logical monitors. - */ -GList * -meta_monitor_manager_get_logical_monitors (MetaMonitorManager *manager) -{ - return manager->logical_monitors; -} - -MetaLogicalMonitor * -meta_monitor_manager_get_logical_monitor_from_number (MetaMonitorManager *manager, - int number) -{ - g_return_val_if_fail ((unsigned int) number < g_list_length (manager->logical_monitors), NULL); - - return g_list_nth (manager->logical_monitors, number)->data; -} - -MetaLogicalMonitor * -meta_monitor_manager_get_primary_logical_monitor (MetaMonitorManager *manager) -{ - return manager->primary_logical_monitor; -} - -static MetaMonitor * -find_monitor (MetaMonitorManager *monitor_manager, - gboolean (*match_func) (MetaMonitor *monitor)) -{ - GList *monitors; - GList *l; - - monitors = meta_monitor_manager_get_monitors (monitor_manager); - for (l = monitors; l; l = l->next) - { - MetaMonitor *monitor = l->data; - - if (match_func (monitor)) - return monitor; - } - - return NULL; -} - -/** - * meta_monitor_manager_get_primary_monitor: - * @manager: A #MetaMonitorManager object - * - * Returns the primary monitor. This can be %NULL (e.g. when running headless). - * - * Returns: (transfer none) (nullable): The primary #MetaMonitor, or %NULL if - * none. - */ -MetaMonitor * -meta_monitor_manager_get_primary_monitor (MetaMonitorManager *manager) -{ - return find_monitor (manager, meta_monitor_is_primary); -} - -/** - * meta_monitor_manager_get_laptop_panel: - * @manager: A #MetaMonitorManager object - * - * Returns the #MetaMonitor that represents the built-in laptop panel (if - * applicable). - * - * Returns: (transfer none) (nullable): The laptop panel, or %NULL if none. - */ -MetaMonitor * -meta_monitor_manager_get_laptop_panel (MetaMonitorManager *manager) -{ - return find_monitor (manager, meta_monitor_is_laptop_panel); -} - -static MetaMonitor * -meta_monitor_manager_get_active_monitor (MetaMonitorManager *manager) -{ - return find_monitor (manager, meta_monitor_is_active); -} - -MetaMonitor * -meta_monitor_manager_get_monitor_from_connector (MetaMonitorManager *manager, - const char *connector) -{ - GList *l; - - for (l = manager->monitors; l; l = l->next) - { - MetaMonitor *monitor = l->data; - - if (g_str_equal (meta_monitor_get_connector (monitor), - connector)) - return monitor; - } - - return NULL; -} - -MetaMonitor * -meta_monitor_manager_get_monitor_from_spec (MetaMonitorManager *manager, - MetaMonitorSpec *monitor_spec) -{ - GList *l; - - for (l = manager->monitors; l; l = l->next) - { - MetaMonitor *monitor = l->data; - - if (meta_monitor_spec_equals (meta_monitor_get_spec (monitor), - monitor_spec)) - return monitor; - } - - return NULL; -} - -/** - * meta_monitor_manager_get_logical_monitor_at: - * @manager: A #MetaMonitorManager object - * @x: The x-coordinate - * @y: The y-coordinate - * - * Finds the #MetaLogicalMonitor at the given @x and @y coordinates in the - * total layout. - * - * Returns: (transfer none) (nullable): The #MetaLogicalMonitor at the given - * point, or %NULL if none. - */ -MetaLogicalMonitor * -meta_monitor_manager_get_logical_monitor_at (MetaMonitorManager *manager, - float x, - float y) -{ - GList *l; - - for (l = manager->logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - - if (META_POINT_IN_RECT (x, y, logical_monitor->rect)) - return logical_monitor; - } - - return NULL; -} - -/** - * meta_monitor_manager_get_logical_monitor_from_rect: - * @manager: A #MetaMonitorManager object - * @rect: The rectangle - * - * Finds the #MetaLogicalMonitor which has the largest area in common with the - * given @rect in the total layout. - * - * Returns: (transfer none) (nullable): The #MetaLogicalMonitor which - * corresponds the most to the given @rect, or %NULL if none. - */ -MetaLogicalMonitor * -meta_monitor_manager_get_logical_monitor_from_rect (MetaMonitorManager *manager, - MetaRectangle *rect) -{ - MetaLogicalMonitor *best_logical_monitor; - int best_logical_monitor_area; - GList *l; - - best_logical_monitor = NULL; - best_logical_monitor_area = 0; - - for (l = manager->logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - MetaRectangle intersection; - int intersection_area; - - if (!meta_rectangle_intersect (&logical_monitor->rect, - rect, - &intersection)) - continue; - - intersection_area = meta_rectangle_area (&intersection); - - if (intersection_area > best_logical_monitor_area) - { - best_logical_monitor = logical_monitor; - best_logical_monitor_area = intersection_area; - } - } - - if (!best_logical_monitor && (rect->width == 0 || rect->height == 0)) - best_logical_monitor = - meta_monitor_manager_get_logical_monitor_at (manager, rect->x, rect->y); - - if (!best_logical_monitor) - best_logical_monitor = manager->primary_logical_monitor; - - return best_logical_monitor; -} - -MetaLogicalMonitor * -meta_monitor_manager_get_logical_monitor_neighbor (MetaMonitorManager *manager, - MetaLogicalMonitor *logical_monitor, - MetaDisplayDirection direction) -{ - GList *l; - - for (l = manager->logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *other = l->data; - - if (meta_logical_monitor_has_neighbor (logical_monitor, other, direction)) - return other; - } - - return NULL; -} - -/** - * meta_monitor_manager_get_monitors: - * @manager: A #MetaMonitorManager object - * - * Returns the list of #MetaMonitors. See also - * meta_monitor_manager_get_logical_monitors() for a list of - * #MetaLogicalMonitors. - * - * Returns: (transfer none) (nullable): the list of #MetaMonitors. - */ -GList * -meta_monitor_manager_get_monitors (MetaMonitorManager *manager) -{ - return manager->monitors; -} - -void -meta_monitor_manager_get_screen_size (MetaMonitorManager *manager, - int *width, - int *height) -{ - *width = manager->screen_width; - *height = manager->screen_height; -} - -MetaPowerSave -meta_monitor_manager_get_power_save_mode (MetaMonitorManager *manager) -{ - MetaMonitorManagerPrivate *priv = - meta_monitor_manager_get_instance_private (manager); - - return priv->power_save_mode; -} - -static void -destroy_monitor (MetaMonitor *monitor) -{ - g_object_run_dispose (G_OBJECT (monitor)); - g_object_unref (monitor); -} - -static void -rebuild_monitors (MetaMonitorManager *manager) -{ - GList *gpus; - GList *l; - - if (manager->monitors) - { - g_list_free_full (manager->monitors, (GDestroyNotify) destroy_monitor); - manager->monitors = NULL; - } - - gpus = meta_backend_get_gpus (manager->backend); - for (l = gpus; l; l = l->next) - { - MetaGpu *gpu = l->data; - GList *k; - - for (k = meta_gpu_get_outputs (gpu); k; k = k->next) - { - MetaOutput *output = k->data; - const MetaOutputInfo *output_info = meta_output_get_info (output); - - if (output_info->tile_info.group_id) - { - if (is_main_tiled_monitor_output (output)) - { - MetaMonitorTiled *monitor_tiled; - - monitor_tiled = meta_monitor_tiled_new (manager, output); - manager->monitors = g_list_append (manager->monitors, - monitor_tiled); - } - } - else - { - MetaMonitorNormal *monitor_normal; - - monitor_normal = meta_monitor_normal_new (manager, output); - manager->monitors = g_list_append (manager->monitors, - monitor_normal); - } - } - } - - for (l = meta_monitor_manager_get_virtual_monitors (manager); l; l = l->next) - { - MetaVirtualMonitor *virtual_monitor = l->data; - MetaOutput *output = meta_virtual_monitor_get_output (virtual_monitor); - MetaMonitorNormal *monitor_normal; - - monitor_normal = meta_monitor_normal_new (manager, output); - manager->monitors = g_list_append (manager->monitors, - monitor_normal); - - } -} - -void -meta_monitor_manager_tiled_monitor_added (MetaMonitorManager *manager, - MetaMonitor *monitor) -{ - MetaMonitorManagerClass *manager_class = - META_MONITOR_MANAGER_GET_CLASS (manager); - - if (manager_class->tiled_monitor_added) - manager_class->tiled_monitor_added (manager, monitor); -} - -void -meta_monitor_manager_tiled_monitor_removed (MetaMonitorManager *manager, - MetaMonitor *monitor) -{ - MetaMonitorManagerClass *manager_class = - META_MONITOR_MANAGER_GET_CLASS (manager); - - if (manager_class->tiled_monitor_removed) - manager_class->tiled_monitor_removed (manager, monitor); -} - -gboolean -meta_monitor_manager_is_transform_handled (MetaMonitorManager *manager, - MetaCrtc *crtc, - MetaMonitorTransform transform) -{ - MetaMonitorManagerClass *manager_class = - META_MONITOR_MANAGER_GET_CLASS (manager); - - return manager_class->is_transform_handled (manager, crtc, transform); -} - -static void -meta_monitor_manager_real_read_current_state (MetaMonitorManager *manager) -{ - GList *l; - - manager->serial++; - - for (l = meta_backend_get_gpus (manager->backend); l; l = l->next) - { - MetaGpu *gpu = l->data; - GError *error = NULL; - - if (!meta_gpu_read_current (gpu, &error)) - { - g_warning ("Failed to read current KMS state: %s", error->message); - g_clear_error (&error); - } - } - - rebuild_monitors (manager); -} - -void -meta_monitor_manager_read_current_state (MetaMonitorManager *manager) -{ - MetaMonitorManagerClass *manager_class = - META_MONITOR_MANAGER_GET_CLASS (manager); - - manager_class->read_current_state (manager); -} - -static void -meta_monitor_manager_notify_monitors_changed (MetaMonitorManager *manager) -{ - meta_backend_monitors_changed (manager->backend); - - g_signal_emit (manager, signals[MONITORS_CHANGED_INTERNAL], 0); - g_signal_emit (manager, signals[MONITORS_CHANGED], 0); - - meta_dbus_display_config_emit_monitors_changed (manager->display_config); -} - -static void -set_logical_monitor_modes (MetaMonitorManager *manager, - MetaLogicalMonitorConfig *logical_monitor_config) -{ - GList *l; - - for (l = logical_monitor_config->monitor_configs; l; l = l->next) - { - MetaMonitorConfig *monitor_config = l->data; - MetaMonitorSpec *monitor_spec; - MetaMonitor *monitor; - MetaMonitorModeSpec *monitor_mode_spec; - MetaMonitorMode *monitor_mode; - - monitor_spec = monitor_config->monitor_spec; - monitor = meta_monitor_manager_get_monitor_from_spec (manager, - monitor_spec); - monitor_mode_spec = monitor_config->mode_spec; - monitor_mode = meta_monitor_get_mode_from_spec (monitor, - monitor_mode_spec); - - meta_monitor_set_current_mode (monitor, monitor_mode); - } -} - -static void -meta_monitor_manager_update_monitor_modes (MetaMonitorManager *manager, - MetaMonitorsConfig *config) -{ - GList *logical_monitor_configs; - GList *l; - - g_list_foreach (manager->monitors, - (GFunc) meta_monitor_set_current_mode, - NULL); - - logical_monitor_configs = config ? config->logical_monitor_configs : NULL; - for (l = logical_monitor_configs; l; l = l->next) - { - MetaLogicalMonitorConfig *logical_monitor_config = l->data; - - set_logical_monitor_modes (manager, logical_monitor_config); - } -} - -void -meta_monitor_manager_update_logical_state (MetaMonitorManager *manager, - MetaMonitorsConfig *config) -{ - if (config) - { - manager->layout_mode = config->layout_mode; - manager->current_switch_config = - meta_monitors_config_get_switch_config (config); - } - else - { - manager->layout_mode = - meta_monitor_manager_get_default_layout_mode (manager); - manager->current_switch_config = META_MONITOR_SWITCH_CONFIG_UNKNOWN; - } - - meta_monitor_manager_rebuild_logical_monitors (manager, config); -} - -void -meta_monitor_manager_rebuild (MetaMonitorManager *manager, - MetaMonitorsConfig *config) -{ - GList *old_logical_monitors; - - meta_monitor_manager_update_monitor_modes (manager, config); - - if (manager->in_init) - return; - - old_logical_monitors = manager->logical_monitors; - - meta_monitor_manager_update_logical_state (manager, config); - - meta_monitor_manager_notify_monitors_changed (manager); - - g_list_free_full (old_logical_monitors, g_object_unref); -} - -static void -meta_monitor_manager_update_monitor_modes_derived (MetaMonitorManager *manager) -{ - GList *l; - - for (l = manager->monitors; l; l = l->next) - { - MetaMonitor *monitor = l->data; - - meta_monitor_derive_current_mode (monitor); - } -} - -void -meta_monitor_manager_update_logical_state_derived (MetaMonitorManager *manager, - MetaMonitorsConfig *config) -{ - if (config) - manager->current_switch_config = - meta_monitors_config_get_switch_config (config); - else - manager->current_switch_config = META_MONITOR_SWITCH_CONFIG_UNKNOWN; - - manager->layout_mode = META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL; - - meta_monitor_manager_rebuild_logical_monitors_derived (manager, config); -} - -void -meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager, - MetaMonitorsConfig *config) -{ - GList *old_logical_monitors; - - meta_monitor_manager_update_monitor_modes_derived (manager); - - if (manager->in_init) - return; - - old_logical_monitors = manager->logical_monitors; - - meta_monitor_manager_update_logical_state_derived (manager, config); - - meta_monitor_manager_notify_monitors_changed (manager); - - g_list_free_full (old_logical_monitors, g_object_unref); -} - -void -meta_monitor_manager_reconfigure (MetaMonitorManager *manager) -{ - meta_monitor_manager_ensure_configured (manager); -} - -void -meta_monitor_manager_reload (MetaMonitorManager *manager) -{ - meta_monitor_manager_read_current_state (manager); - meta_monitor_manager_reconfigure (manager); -} - -static gboolean -calculate_viewport_matrix (MetaMonitorManager *manager, - MetaLogicalMonitor *logical_monitor, - gfloat viewport[6]) -{ - gfloat x, y, width, height; - - x = (float) logical_monitor->rect.x / manager->screen_width; - y = (float) logical_monitor->rect.y / manager->screen_height; - width = (float) logical_monitor->rect.width / manager->screen_width; - height = (float) logical_monitor->rect.height / manager->screen_height; - - viewport[0] = width; - viewport[1] = 0.0f; - viewport[2] = x; - viewport[3] = 0.0f; - viewport[4] = height; - viewport[5] = y; - - return TRUE; -} - -static inline void -multiply_matrix (float a[6], - float b[6], - float res[6]) -{ - res[0] = a[0] * b[0] + a[1] * b[3]; - res[1] = a[0] * b[1] + a[1] * b[4]; - res[2] = a[0] * b[2] + a[1] * b[5] + a[2]; - res[3] = a[3] * b[0] + a[4] * b[3]; - res[4] = a[3] * b[1] + a[4] * b[4]; - res[5] = a[3] * b[2] + a[4] * b[5] + a[5]; -} - -gboolean -meta_monitor_manager_get_monitor_matrix (MetaMonitorManager *manager, - MetaMonitor *monitor, - MetaLogicalMonitor *logical_monitor, - gfloat matrix[6]) -{ - MetaMonitorTransform transform; - gfloat viewport[9]; - - if (!calculate_viewport_matrix (manager, logical_monitor, viewport)) - return FALSE; - - /* Get transform corrected for LCD panel-orientation. */ - transform = logical_monitor->transform; - transform = meta_monitor_logical_to_crtc_transform (monitor, transform); - multiply_matrix (viewport, transform_matrices[transform], - matrix); - return TRUE; -} - -/** - * meta_monitor_manager_get_monitor_for_connector: - * @manager: A #MetaMonitorManager - * @connector: A valid connector name - * - * Returns: The monitor index or -1 if @id isn't valid or the connector - * isn't associated with a logical monitor. - */ -gint -meta_monitor_manager_get_monitor_for_connector (MetaMonitorManager *manager, - const char *connector) -{ - GList *l; - - for (l = manager->monitors; l; l = l->next) - { - MetaMonitor *monitor = l->data; - - if (meta_monitor_is_active (monitor) && - g_str_equal (connector, meta_monitor_get_connector (monitor))) - return meta_monitor_get_logical_monitor (monitor)->number; - } - - return -1; -} - -/** - * meta_monitor_manager_get_is_builtin_display_on: - * @manager: A #MetaMonitorManager object - * - * Returns whether the built-in display (i.e. a laptop panel) is turned on. - */ -gboolean -meta_monitor_manager_get_is_builtin_display_on (MetaMonitorManager *manager) -{ - MetaMonitor *laptop_panel; - - g_return_val_if_fail (META_IS_MONITOR_MANAGER (manager), FALSE); - - laptop_panel = meta_monitor_manager_get_laptop_panel (manager); - if (!laptop_panel) - return FALSE; - - return meta_monitor_is_active (laptop_panel); -} - -void -meta_monitor_manager_rotate_monitor (MetaMonitorManager *manager) -{ - GError *error = NULL; - MetaMonitorsConfig *config = - meta_monitor_config_manager_create_for_rotate_monitor (manager->config_manager); - - if (!config) - return; - - if (!meta_monitor_manager_apply_monitors_config (manager, - config, - META_MONITORS_CONFIG_METHOD_TEMPORARY, - &error)) - { - g_warning ("Failed to use rotate monitor configuration: %s", - error->message); - g_error_free (error); - } - g_object_unref (config); -} - -void -meta_monitor_manager_switch_config (MetaMonitorManager *manager, - MetaMonitorSwitchConfigType config_type) -{ - GError *error = NULL; - MetaMonitorsConfig *config; - - g_return_if_fail (config_type != META_MONITOR_SWITCH_CONFIG_UNKNOWN); - - config = - meta_monitor_config_manager_create_for_switch_config (manager->config_manager, - config_type); - if (!config) - return; - - if (!meta_monitor_manager_apply_monitors_config (manager, - config, - META_MONITORS_CONFIG_METHOD_TEMPORARY, - &error)) - { - g_warning ("Failed to use switch monitor configuration: %s", - error->message); - g_error_free (error); - } - else - { - manager->current_switch_config = config_type; - } - g_object_unref (config); -} - -gboolean -meta_monitor_manager_can_switch_config (MetaMonitorManager *manager) -{ - return (!meta_backend_is_lid_closed (manager->backend) && - g_list_length (manager->monitors) > 1); -} - -MetaMonitorSwitchConfigType -meta_monitor_manager_get_switch_config (MetaMonitorManager *manager) -{ - return manager->current_switch_config; -} - -MetaMonitorConfigManager * -meta_monitor_manager_get_config_manager (MetaMonitorManager *manager) -{ - return manager->config_manager; -} - -/** - * meta_monitor_manager_get_vendor_name: - * @manager: A #MetaMonitorManager object - * @vendor: the PNP ID of the monitor - * - * Find the full vendor name from the given monitor PNP ID. - * - * Returns: (transfer full): A string containing the vendor name, - * or NULL when not found. - */ -char * -meta_monitor_manager_get_vendor_name (MetaMonitorManager *manager, - const char *vendor) -{ - if (!manager->pnp_ids) - manager->pnp_ids = gnome_pnp_ids_new (); - - return gnome_pnp_ids_get_pnp_id (manager->pnp_ids, vendor); -} - -gboolean -meta_monitor_manager_get_panel_orientation_managed (MetaMonitorManager *manager) -{ - g_return_val_if_fail (META_IS_MONITOR_MANAGER (manager), FALSE); - - return manager->panel_orientation_managed; -} - -void -meta_monitor_manager_post_init (MetaMonitorManager *manager) -{ - ClutterBackend *clutter_backend; - ClutterSeat *seat; - - clutter_backend = meta_backend_get_clutter_backend (manager->backend); - seat = clutter_backend_get_default_seat (clutter_backend); - - g_signal_connect_object (seat, "notify::touch-mode", - G_CALLBACK (update_panel_orientation_managed), manager, - G_CONNECT_SWAPPED); -} - -MetaViewportInfo * -meta_monitor_manager_get_viewports (MetaMonitorManager *manager) -{ - MetaViewportInfo *info; - GArray *views, *scales; - GList *logical_monitors, *l; - - views = g_array_new (FALSE, FALSE, sizeof (cairo_rectangle_int_t)); - scales = g_array_new (FALSE, FALSE, sizeof (float)); - - logical_monitors = meta_monitor_manager_get_logical_monitors (manager); - - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - cairo_rectangle_int_t rect; - float scale; - - rect = logical_monitor->rect; - g_array_append_val (views, rect); - - scale = logical_monitor->scale; - g_array_append_val (scales, scale); - } - - info = meta_viewport_info_new ((cairo_rectangle_int_t *) views->data, - (float *) scales->data, - views->len, - meta_is_stage_views_scaled ()); - g_array_unref (views); - g_array_unref (scales); - - return info; -} - -GList * -meta_monitor_manager_get_virtual_monitors (MetaMonitorManager *manager) -{ - MetaMonitorManagerPrivate *priv = - meta_monitor_manager_get_instance_private (manager); - - return priv->virtual_monitors; -} diff --git a/src/backends/meta-monitor-transform.c b/src/backends/meta-monitor-transform.c deleted file mode 100644 index d6b1f8b45..000000000 --- a/src/backends/meta-monitor-transform.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2018 Robert Mader - * - * 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 . - */ - -#include "config.h" - -#include "backends/meta-monitor-transform.h" - -MetaMonitorTransform -meta_monitor_transform_invert (MetaMonitorTransform transform) -{ - switch (transform) - { - case META_MONITOR_TRANSFORM_90: - return META_MONITOR_TRANSFORM_270; - case META_MONITOR_TRANSFORM_270: - return META_MONITOR_TRANSFORM_90; - case META_MONITOR_TRANSFORM_NORMAL: - case META_MONITOR_TRANSFORM_180: - case META_MONITOR_TRANSFORM_FLIPPED: - case META_MONITOR_TRANSFORM_FLIPPED_90: - case META_MONITOR_TRANSFORM_FLIPPED_180: - case META_MONITOR_TRANSFORM_FLIPPED_270: - return transform; - } - g_assert_not_reached (); - return 0; -} - -MetaMonitorTransform -meta_monitor_transform_transform (MetaMonitorTransform transform, - MetaMonitorTransform other) -{ - MetaMonitorTransform new_transform; - - new_transform = (transform + other) % META_MONITOR_TRANSFORM_FLIPPED; - if (meta_monitor_transform_is_flipped (transform) != - meta_monitor_transform_is_flipped (other)) - new_transform += META_MONITOR_TRANSFORM_FLIPPED; - - return new_transform; -} - -/** - * meta_monitor_transform_relative_transform: - * @transform: The transform to start from - * @other: The transform to go to - * - * Return value: a transform to get from @transform to @other - */ -MetaMonitorTransform -meta_monitor_transform_relative_transform (MetaMonitorTransform transform, - MetaMonitorTransform other) -{ - MetaMonitorTransform relative_transform; - - relative_transform = ((other % META_MONITOR_TRANSFORM_FLIPPED - - transform % META_MONITOR_TRANSFORM_FLIPPED) % - META_MONITOR_TRANSFORM_FLIPPED); - - if (meta_monitor_transform_is_flipped (transform) != - meta_monitor_transform_is_flipped (other)) - { - relative_transform = (meta_monitor_transform_invert (relative_transform) + - META_MONITOR_TRANSFORM_FLIPPED); - } - - return relative_transform; -} - -void -meta_monitor_transform_transform_point (MetaMonitorTransform transform, - int area_width, - int area_height, - int x, - int y, - int *out_x, - int *out_y) -{ - switch (transform) - { - case META_MONITOR_TRANSFORM_NORMAL: - *out_x = x; - *out_y = y; - break; - case META_MONITOR_TRANSFORM_90: - *out_x = area_width - y; - *out_y = x; - break; - case META_MONITOR_TRANSFORM_180: - *out_x = area_width - x; - *out_y = area_height - y; - break; - case META_MONITOR_TRANSFORM_270: - *out_x = y, - *out_y = area_height - x; - break; - case META_MONITOR_TRANSFORM_FLIPPED: - *out_x = area_width - x; - *out_y = y; - break; - case META_MONITOR_TRANSFORM_FLIPPED_90: - *out_x = area_width - y; - *out_y = area_height - x; - break; - case META_MONITOR_TRANSFORM_FLIPPED_180: - *out_x = x; - *out_y = area_height - y; - break; - case META_MONITOR_TRANSFORM_FLIPPED_270: - *out_x = y; - *out_y = x; - break; - } -} diff --git a/src/backends/meta-monitor-transform.h b/src/backends/meta-monitor-transform.h deleted file mode 100644 index 6113f3a5a..000000000 --- a/src/backends/meta-monitor-transform.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2013 Red Hat Inc. - * Copyright (C) 2018 Robert Mader - * - * 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 . - */ - -#ifndef META_MONITOR_TRANSFORM_H -#define META_MONITOR_TRANSFORM_H - -#include - -#include "backends/meta-backend-types.h" -#include "core/util-private.h" - -enum _MetaMonitorTransform -{ - META_MONITOR_TRANSFORM_NORMAL, - META_MONITOR_TRANSFORM_90, - META_MONITOR_TRANSFORM_180, - META_MONITOR_TRANSFORM_270, - META_MONITOR_TRANSFORM_FLIPPED, - META_MONITOR_TRANSFORM_FLIPPED_90, - META_MONITOR_TRANSFORM_FLIPPED_180, - META_MONITOR_TRANSFORM_FLIPPED_270, -}; -#define META_MONITOR_N_TRANSFORMS (META_MONITOR_TRANSFORM_FLIPPED_270 + 1) -#define META_MONITOR_ALL_TRANSFORMS ((1 << META_MONITOR_N_TRANSFORMS) - 1) - -/* Returns true if transform causes width and height to be inverted - This is true for the odd transforms in the enum */ -static inline gboolean -meta_monitor_transform_is_rotated (MetaMonitorTransform transform) -{ - return (transform % 2); -} - -/* Returns true if transform involves flipping */ -static inline gboolean -meta_monitor_transform_is_flipped (MetaMonitorTransform transform) -{ - return (transform >= META_MONITOR_TRANSFORM_FLIPPED); -} - -META_EXPORT_TEST -MetaMonitorTransform meta_monitor_transform_invert (MetaMonitorTransform transform); - -META_EXPORT_TEST -MetaMonitorTransform meta_monitor_transform_transform (MetaMonitorTransform transform, - MetaMonitorTransform other); - -MetaMonitorTransform meta_monitor_transform_relative_transform (MetaMonitorTransform transform, - MetaMonitorTransform other); - -void meta_monitor_transform_transform_point (MetaMonitorTransform transform, - int area_width, - int area_height, - int x, - int y, - int *out_x, - int *out_y); - -#endif /* META_MONITOR_TRANSFORM_H */ diff --git a/src/backends/meta-monitor.c b/src/backends/meta-monitor.c deleted file mode 100644 index e02f8ed45..000000000 --- a/src/backends/meta-monitor.c +++ /dev/null @@ -1,1988 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 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. - */ - -#include "config.h" - -#include "backends/meta-monitor.h" - -#include "backends/meta-backend-private.h" -#include "backends/meta-crtc.h" -#include "backends/meta-gpu.h" -#include "backends/meta-monitor-manager-private.h" -#include "backends/meta-settings-private.h" -#include "backends/meta-output.h" -#include "core/boxes-private.h" - -#define SCALE_FACTORS_PER_INTEGER 4 -#define SCALE_FACTORS_STEPS (1.0 / (float) SCALE_FACTORS_PER_INTEGER) -#define MINIMUM_SCALE_FACTOR 1.0f -#define MAXIMUM_SCALE_FACTOR 4.0f -#define MINIMUM_LOGICAL_AREA (800 * 480) -#define MAXIMUM_REFRESH_RATE_DIFF 0.001 - -typedef struct _MetaMonitorMode -{ - MetaMonitor *monitor; - char *id; - MetaMonitorModeSpec spec; - MetaMonitorCrtcMode *crtc_modes; -} MetaMonitorMode; - -typedef struct _MetaMonitorModeTiled -{ - MetaMonitorMode parent; - - gboolean is_tiled; -} MetaMonitorModeTiled; - -typedef struct _MetaMonitorPrivate -{ - MetaBackend *backend; - - GList *outputs; - GList *modes; - GHashTable *mode_ids; - - MetaMonitorMode *preferred_mode; - MetaMonitorMode *current_mode; - - MetaMonitorSpec *spec; - - MetaLogicalMonitor *logical_monitor; - - /* - * The primary or first output for this monitor, 0 if we can't figure out. - * It can be matched to a winsys_id of a MetaOutput. - * - * This is used as an opaque token on reconfiguration when switching from - * clone to extended, to decide on what output the windows should go next - * (it's an attempt to keep windows on the same monitor, and preferably on - * the primary one). - */ - uint64_t winsys_id; - - char *display_name; -} MetaMonitorPrivate; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaMonitor, meta_monitor, G_TYPE_OBJECT) - -struct _MetaMonitorNormal -{ - MetaMonitor parent; -}; - -G_DEFINE_TYPE (MetaMonitorNormal, meta_monitor_normal, META_TYPE_MONITOR) - -struct _MetaMonitorTiled -{ - MetaMonitor parent; - - MetaMonitorManager *monitor_manager; - - uint32_t tile_group_id; - - /* The tile (0, 0) output. */ - MetaOutput *origin_output; - - /* The output enabled even when a non-tiled mode is used. */ - MetaOutput *main_output; -}; - -G_DEFINE_TYPE (MetaMonitorTiled, meta_monitor_tiled, META_TYPE_MONITOR) - -static void -meta_monitor_mode_free (MetaMonitorMode *mode); - -MetaMonitorSpec * -meta_monitor_spec_clone (MetaMonitorSpec *monitor_spec) -{ - MetaMonitorSpec *new_monitor_spec; - - new_monitor_spec = g_new0 (MetaMonitorSpec, 1); - *new_monitor_spec = (MetaMonitorSpec) { - .connector = g_strdup (monitor_spec->connector), - .vendor = g_strdup (monitor_spec->vendor), - .product = g_strdup (monitor_spec->product), - .serial = g_strdup (monitor_spec->serial), - }; - - return new_monitor_spec; -} - -gboolean -meta_monitor_spec_equals (MetaMonitorSpec *monitor_spec, - MetaMonitorSpec *other_monitor_spec) -{ - return (g_str_equal (monitor_spec->connector, other_monitor_spec->connector) && - g_str_equal (monitor_spec->vendor, other_monitor_spec->vendor) && - g_str_equal (monitor_spec->product, other_monitor_spec->product) && - g_str_equal (monitor_spec->serial, other_monitor_spec->serial)); -} - -int -meta_monitor_spec_compare (MetaMonitorSpec *monitor_spec_a, - MetaMonitorSpec *monitor_spec_b) -{ - int ret; - - ret = strcmp (monitor_spec_a->connector, monitor_spec_b->connector); - if (ret != 0) - return ret; - - ret = strcmp (monitor_spec_a->vendor, monitor_spec_b->vendor); - if (ret != 0) - return ret; - - ret = strcmp (monitor_spec_a->product, monitor_spec_b->product); - if (ret != 0) - return ret; - - return strcmp (monitor_spec_a->serial, monitor_spec_b->serial); -} - -void -meta_monitor_spec_free (MetaMonitorSpec *monitor_spec) -{ - g_free (monitor_spec->connector); - g_free (monitor_spec->vendor); - g_free (monitor_spec->product); - g_free (monitor_spec->serial); - g_free (monitor_spec); -} - -static const MetaOutputInfo * -meta_monitor_get_main_output_info (MetaMonitor *monitor) -{ - MetaOutput *output = meta_monitor_get_main_output (monitor); - - return meta_output_get_info (output); -} - -static void -meta_monitor_generate_spec (MetaMonitor *monitor) -{ - MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor); - const MetaOutputInfo *output_info = - meta_monitor_get_main_output_info (monitor); - MetaMonitorSpec *monitor_spec; - - monitor_spec = g_new0 (MetaMonitorSpec, 1); - *monitor_spec = (MetaMonitorSpec) { - .connector = g_strdup (output_info->name), - .vendor = g_strdup (output_info->vendor), - .product = g_strdup (output_info->product), - .serial = g_strdup (output_info->serial), - }; - - priv->spec = monitor_spec; -} - -static const double known_diagonals[] = { - 12.1, - 13.3, - 15.6 -}; - -static char * -diagonal_to_str (double d) -{ - unsigned int i; - - for (i = 0; i < G_N_ELEMENTS (known_diagonals); i++) - { - double delta; - - delta = fabs(known_diagonals[i] - d); - if (delta < 0.1) - return g_strdup_printf ("%0.1lf\"", known_diagonals[i]); - } - - return g_strdup_printf ("%d\"", (int) (d + 0.5)); -} - -static char * -meta_monitor_make_display_name (MetaMonitor *monitor, - MetaMonitorManager *monitor_manager) -{ - g_autofree char *inches = NULL; - g_autofree char *vendor_name = NULL; - const char *vendor = NULL; - const char *product_name = NULL; - int width_mm; - int height_mm; - - meta_monitor_get_physical_dimensions (monitor, &width_mm, &height_mm); - - if (meta_monitor_is_laptop_panel (monitor)) - return g_strdup (_("Built-in display")); - - if (width_mm > 0 && height_mm > 0) - { - if (!meta_monitor_has_aspect_as_size (monitor)) - { - double d = sqrt (width_mm * width_mm + - height_mm * height_mm); - inches = diagonal_to_str (d / 25.4); - } - else - { - product_name = meta_monitor_get_product (monitor); - } - } - - vendor = meta_monitor_get_vendor (monitor); - - if (g_strcmp0 (vendor, "unknown") != 0) - { - vendor_name = meta_monitor_manager_get_vendor_name (monitor_manager, - vendor); - - if (!vendor_name) - vendor_name = g_strdup (vendor); - } - else - { - if (inches != NULL) - vendor_name = g_strdup (_("Unknown")); - else - vendor_name = g_strdup (_("Unknown Display")); - } - - if (inches != NULL) - { - /**/ - return g_strdup_printf (C_("This is a monitor vendor name, followed by a " - "size in inches, like 'Dell 15\"'", - "%s %s"), - vendor_name, inches); - } - else if (product_name != NULL) - { - return g_strdup_printf (C_("This is a monitor vendor name followed by " - "product/model name where size in inches " - "could not be calculated, e.g. Dell U2414H", - "%s %s"), - vendor_name, product_name); - } - else - { - return g_strdup (vendor_name); - } -} - -MetaBackend * -meta_monitor_get_backend (MetaMonitor *monitor) -{ - MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor); - - return priv->backend; -} - -GList * -meta_monitor_get_outputs (MetaMonitor *monitor) -{ - MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor); - - return priv->outputs; -} - -MetaOutput * -meta_monitor_get_main_output (MetaMonitor *monitor) -{ - return META_MONITOR_GET_CLASS (monitor)->get_main_output (monitor); -} - -gboolean -meta_monitor_is_active (MetaMonitor *monitor) -{ - MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor); - - return !!priv->current_mode; -} - -gboolean -meta_monitor_is_primary (MetaMonitor *monitor) -{ - MetaOutput *output; - - output = meta_monitor_get_main_output (monitor); - - return meta_output_is_primary (output); -} - -gboolean -meta_monitor_supports_underscanning (MetaMonitor *monitor) -{ - const MetaOutputInfo *output_info = - meta_monitor_get_main_output_info (monitor); - - return output_info->supports_underscanning; -} - -gboolean -meta_monitor_is_underscanning (MetaMonitor *monitor) -{ - MetaOutput *output; - - output = meta_monitor_get_main_output (monitor); - - return meta_output_is_underscanning (output); -} - -gboolean -meta_monitor_is_laptop_panel (MetaMonitor *monitor) -{ - const MetaOutputInfo *output_info = - meta_monitor_get_main_output_info (monitor); - - switch (output_info->connector_type) - { - case META_CONNECTOR_TYPE_eDP: - case META_CONNECTOR_TYPE_LVDS: - case META_CONNECTOR_TYPE_DSI: - return TRUE; - default: - return FALSE; - } -} - -gboolean -meta_monitor_is_same_as (MetaMonitor *monitor, - MetaMonitor *other_monitor) -{ - MetaMonitorPrivate *priv = - meta_monitor_get_instance_private (monitor); - MetaMonitorPrivate *other_priv = - meta_monitor_get_instance_private (other_monitor); - - return priv->winsys_id == other_priv->winsys_id; -} - -void -meta_monitor_get_current_resolution (MetaMonitor *monitor, - int *width, - int *height) -{ - MetaMonitorMode *mode = meta_monitor_get_current_mode (monitor); - - *width = mode->spec.width; - *height = mode->spec.height; -} - -void -meta_monitor_derive_layout (MetaMonitor *monitor, - MetaRectangle *layout) -{ - META_MONITOR_GET_CLASS (monitor)->derive_layout (monitor, layout); -} - -void -meta_monitor_get_physical_dimensions (MetaMonitor *monitor, - int *width_mm, - int *height_mm) -{ - const MetaOutputInfo *output_info = - meta_monitor_get_main_output_info (monitor); - - *width_mm = output_info->width_mm; - *height_mm = output_info->height_mm; -} - -CoglSubpixelOrder -meta_monitor_get_subpixel_order (MetaMonitor *monitor) -{ - const MetaOutputInfo *output_info = - meta_monitor_get_main_output_info (monitor); - - return output_info->subpixel_order; -} - -const char * -meta_monitor_get_connector (MetaMonitor *monitor) -{ - const MetaOutputInfo *output_info = - meta_monitor_get_main_output_info (monitor); - - return output_info->name; -} - -const char * -meta_monitor_get_vendor (MetaMonitor *monitor) -{ - const MetaOutputInfo *output_info = - meta_monitor_get_main_output_info (monitor); - - return output_info->vendor; -} - -const char * -meta_monitor_get_product (MetaMonitor *monitor) -{ - const MetaOutputInfo *output_info = - meta_monitor_get_main_output_info (monitor); - - return output_info->product; -} - -const char * -meta_monitor_get_serial (MetaMonitor *monitor) -{ - const MetaOutputInfo *output_info = - meta_monitor_get_main_output_info (monitor); - - return output_info->serial; -} - -MetaConnectorType -meta_monitor_get_connector_type (MetaMonitor *monitor) -{ - const MetaOutputInfo *output_info = - meta_monitor_get_main_output_info (monitor); - - return output_info->connector_type; -} - -MetaMonitorTransform -meta_monitor_logical_to_crtc_transform (MetaMonitor *monitor, - MetaMonitorTransform transform) -{ - MetaOutput *output = meta_monitor_get_main_output (monitor); - - return meta_output_logical_to_crtc_transform (output, transform); -} - -MetaMonitorTransform -meta_monitor_crtc_to_logical_transform (MetaMonitor *monitor, - MetaMonitorTransform transform) -{ - MetaOutput *output = meta_monitor_get_main_output (monitor); - - return meta_output_crtc_to_logical_transform (output, transform); -} - -static void -meta_monitor_dispose (GObject *object) -{ - MetaMonitor *monitor = META_MONITOR (object); - MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor); - - if (priv->outputs) - { - g_list_foreach (priv->outputs, (GFunc) meta_output_unset_monitor, NULL); - g_list_free_full (priv->outputs, g_object_unref); - priv->outputs = NULL; - } - - G_OBJECT_CLASS (meta_monitor_parent_class)->dispose (object); -} - -static void -meta_monitor_finalize (GObject *object) -{ - MetaMonitor *monitor = META_MONITOR (object); - MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor); - - g_hash_table_destroy (priv->mode_ids); - g_list_free_full (priv->modes, (GDestroyNotify) meta_monitor_mode_free); - meta_monitor_spec_free (priv->spec); - g_free (priv->display_name); - - G_OBJECT_CLASS (meta_monitor_parent_class)->finalize (object); -} - -static void -meta_monitor_init (MetaMonitor *monitor) -{ - MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor); - - priv->mode_ids = g_hash_table_new (g_str_hash, g_str_equal); -} - -static void -meta_monitor_class_init (MetaMonitorClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = meta_monitor_dispose; - object_class->finalize = meta_monitor_finalize; -} - -static char * -generate_mode_id (MetaMonitorModeSpec *monitor_mode_spec) -{ - gboolean is_interlaced; - char refresh_rate_str[G_ASCII_DTOSTR_BUF_SIZE]; - - is_interlaced = !!(monitor_mode_spec->flags & META_CRTC_MODE_FLAG_INTERLACE); - g_ascii_dtostr (refresh_rate_str, G_ASCII_DTOSTR_BUF_SIZE, - monitor_mode_spec->refresh_rate); - - return g_strdup_printf ("%dx%d%s@%s", - monitor_mode_spec->width, - monitor_mode_spec->height, - is_interlaced ? "i" : "", - refresh_rate_str); -} - -static gboolean -meta_monitor_add_mode (MetaMonitor *monitor, - MetaMonitorMode *monitor_mode, - gboolean replace) -{ - MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor); - MetaMonitorMode *existing_mode; - - existing_mode = g_hash_table_lookup (priv->mode_ids, - meta_monitor_mode_get_id (monitor_mode)); - if (existing_mode && !replace) - return FALSE; - - if (existing_mode) - priv->modes = g_list_remove (priv->modes, existing_mode); - - priv->modes = g_list_append (priv->modes, monitor_mode); - g_hash_table_replace (priv->mode_ids, monitor_mode->id, monitor_mode); - - return TRUE; -} - -static MetaMonitorModeSpec -meta_monitor_create_spec (MetaMonitor *monitor, - int width, - int height, - MetaCrtcMode *crtc_mode) -{ - const MetaOutputInfo *output_info = - meta_monitor_get_main_output_info (monitor); - const MetaCrtcModeInfo *crtc_mode_info = - meta_crtc_mode_get_info (crtc_mode); - - if (meta_monitor_transform_is_rotated (output_info->panel_orientation_transform)) - { - int temp = width; - width = height; - height = temp; - } - - return (MetaMonitorModeSpec) { - .width = width, - .height = height, - .refresh_rate = crtc_mode_info->refresh_rate, - .flags = crtc_mode_info->flags & HANDLED_CRTC_MODE_FLAGS - }; -} - -static void -meta_monitor_normal_generate_modes (MetaMonitorNormal *monitor_normal) -{ - MetaMonitor *monitor = META_MONITOR (monitor_normal); - MetaMonitorPrivate *monitor_priv = - meta_monitor_get_instance_private (monitor); - MetaOutput *output; - const MetaOutputInfo *output_info; - MetaCrtcMode *preferred_mode; - MetaCrtcModeFlag preferred_mode_flags; - unsigned int i; - - output = meta_monitor_get_main_output (monitor); - output_info = meta_output_get_info (output); - preferred_mode = output_info->preferred_mode; - preferred_mode_flags = meta_crtc_mode_get_info (preferred_mode)->flags; - - for (i = 0; i < output_info->n_modes; i++) - { - MetaCrtcMode *crtc_mode = output_info->modes[i]; - const MetaCrtcModeInfo *crtc_mode_info = - meta_crtc_mode_get_info (crtc_mode); - MetaCrtc *crtc; - MetaMonitorMode *mode; - gboolean replace; - - mode = g_new0 (MetaMonitorMode, 1); - mode->monitor = monitor; - mode->spec = meta_monitor_create_spec (monitor, - crtc_mode_info->width, - crtc_mode_info->height, - crtc_mode); - mode->id = generate_mode_id (&mode->spec); - mode->crtc_modes = g_new (MetaMonitorCrtcMode, 1); - mode->crtc_modes[0] = (MetaMonitorCrtcMode) { - .output = output, - .crtc_mode = crtc_mode - }; - - /* - * We don't distinguish between all available mode flags, just the ones - * that are configurable. We still need to pick some mode though, so - * prefer ones that has the same set of flags as the preferred mode; - * otherwise take the first one in the list. This guarantees that the - * preferred mode is always added. - */ - replace = crtc_mode_info->flags == preferred_mode_flags; - - if (!meta_monitor_add_mode (monitor, mode, replace)) - { - g_assert (crtc_mode != output_info->preferred_mode); - meta_monitor_mode_free (mode); - continue; - } - - if (crtc_mode == output_info->preferred_mode) - monitor_priv->preferred_mode = mode; - - crtc = meta_output_get_assigned_crtc (output); - if (crtc) - { - const MetaCrtcConfig *crtc_config; - - crtc_config = meta_crtc_get_config (crtc); - if (crtc_config && crtc_mode == crtc_config->mode) - monitor_priv->current_mode = mode; - } - } -} - -MetaMonitorNormal * -meta_monitor_normal_new (MetaMonitorManager *monitor_manager, - MetaOutput *output) -{ - MetaMonitorNormal *monitor_normal; - MetaMonitor *monitor; - MetaMonitorPrivate *monitor_priv; - - monitor_normal = g_object_new (META_TYPE_MONITOR_NORMAL, NULL); - monitor = META_MONITOR (monitor_normal); - monitor_priv = meta_monitor_get_instance_private (monitor); - - monitor_priv->backend = meta_monitor_manager_get_backend (monitor_manager); - - monitor_priv->outputs = g_list_append (NULL, g_object_ref (output)); - meta_output_set_monitor (output, monitor); - - monitor_priv->winsys_id = meta_output_get_id (output); - meta_monitor_generate_spec (monitor); - - meta_monitor_normal_generate_modes (monitor_normal); - - monitor_priv->display_name = meta_monitor_make_display_name (monitor, - monitor_manager); - - return monitor_normal; -} - -static MetaOutput * -meta_monitor_normal_get_main_output (MetaMonitor *monitor) -{ - MetaMonitorPrivate *monitor_priv = - meta_monitor_get_instance_private (monitor); - - return monitor_priv->outputs->data; -} - -static void -meta_monitor_normal_derive_layout (MetaMonitor *monitor, - MetaRectangle *layout) -{ - MetaOutput *output; - MetaCrtc *crtc; - const MetaCrtcConfig *crtc_config; - - output = meta_monitor_get_main_output (monitor); - crtc = meta_output_get_assigned_crtc (output); - crtc_config = meta_crtc_get_config (crtc); - - g_return_if_fail (crtc_config); - - meta_rectangle_from_graphene_rect (&crtc_config->layout, - META_ROUNDING_STRATEGY_ROUND, - layout); -} - -static gboolean -meta_monitor_normal_get_suggested_position (MetaMonitor *monitor, - int *x, - int *y) -{ - const MetaOutputInfo *output_info = - meta_monitor_get_main_output_info (monitor); - - if (!output_info->hotplug_mode_update) - return FALSE; - - if (output_info->suggested_x < 0 && output_info->suggested_y < 0) - return FALSE; - - *x = output_info->suggested_x; - *y = output_info->suggested_y; - - return TRUE; -} - -static void -meta_monitor_normal_calculate_crtc_pos (MetaMonitor *monitor, - MetaMonitorMode *monitor_mode, - MetaOutput *output, - MetaMonitorTransform crtc_transform, - int *out_x, - int *out_y) -{ - *out_x = 0; - *out_y = 0; -} - -static void -meta_monitor_normal_init (MetaMonitorNormal *monitor) -{ -} - -static void -meta_monitor_normal_class_init (MetaMonitorNormalClass *klass) -{ - MetaMonitorClass *monitor_class = META_MONITOR_CLASS (klass); - - monitor_class->get_main_output = meta_monitor_normal_get_main_output; - monitor_class->derive_layout = meta_monitor_normal_derive_layout; - monitor_class->calculate_crtc_pos = meta_monitor_normal_calculate_crtc_pos; - monitor_class->get_suggested_position = meta_monitor_normal_get_suggested_position; -} - -uint32_t -meta_monitor_tiled_get_tile_group_id (MetaMonitorTiled *monitor_tiled) -{ - return monitor_tiled->tile_group_id; -} - -gboolean -meta_monitor_get_suggested_position (MetaMonitor *monitor, - int *x, - int *y) -{ - return META_MONITOR_GET_CLASS (monitor)->get_suggested_position (monitor, - x, y); -} - -static void -add_tiled_monitor_outputs (MetaGpu *gpu, - MetaMonitorTiled *monitor_tiled) -{ - MetaMonitorPrivate *monitor_priv = - meta_monitor_get_instance_private (META_MONITOR (monitor_tiled)); - GList *outputs; - GList *l; - - outputs = meta_gpu_get_outputs (gpu); - for (l = outputs; l; l = l->next) - { - MetaOutput *output = l->data; - const MetaOutputInfo *output_info = meta_output_get_info (output); - const MetaOutputInfo *origin_output_info; - - if (output_info->tile_info.group_id != monitor_tiled->tile_group_id) - continue; - - origin_output_info = meta_output_get_info (monitor_tiled->origin_output); - g_warn_if_fail (output_info->subpixel_order == - origin_output_info->subpixel_order); - - monitor_priv->outputs = g_list_append (monitor_priv->outputs, - g_object_ref (output)); - - meta_output_set_monitor (output, META_MONITOR (monitor_tiled)); - } -} - -static void -calculate_tile_coordinate (MetaMonitor *monitor, - MetaOutput *output, - MetaMonitorTransform crtc_transform, - int *out_x, - int *out_y) -{ - MetaMonitorPrivate *monitor_priv = - meta_monitor_get_instance_private (monitor); - const MetaOutputInfo *output_info = meta_output_get_info (output); - GList *l; - int x = 0; - int y = 0; - - for (l = monitor_priv->outputs; l; l = l->next) - { - const MetaOutputInfo *other_output_info = meta_output_get_info (l->data); - - switch (crtc_transform) - { - case META_MONITOR_TRANSFORM_NORMAL: - case META_MONITOR_TRANSFORM_FLIPPED: - if ((other_output_info->tile_info.loc_v_tile == - output_info->tile_info.loc_v_tile) && - (other_output_info->tile_info.loc_h_tile < - output_info->tile_info.loc_h_tile)) - x += other_output_info->tile_info.tile_w; - if ((other_output_info->tile_info.loc_h_tile == - output_info->tile_info.loc_h_tile) && - (other_output_info->tile_info.loc_v_tile < - output_info->tile_info.loc_v_tile)) - y += other_output_info->tile_info.tile_h; - break; - case META_MONITOR_TRANSFORM_180: - case META_MONITOR_TRANSFORM_FLIPPED_180: - if ((other_output_info->tile_info.loc_v_tile == - output_info->tile_info.loc_v_tile) && - (other_output_info->tile_info.loc_h_tile > - output_info->tile_info.loc_h_tile)) - x += other_output_info->tile_info.tile_w; - if ((other_output_info->tile_info.loc_h_tile == - output_info->tile_info.loc_h_tile) && - (other_output_info->tile_info.loc_v_tile > - output_info->tile_info.loc_v_tile)) - y += other_output_info->tile_info.tile_h; - break; - case META_MONITOR_TRANSFORM_270: - case META_MONITOR_TRANSFORM_FLIPPED_270: - if ((other_output_info->tile_info.loc_v_tile == - output_info->tile_info.loc_v_tile) && - (other_output_info->tile_info.loc_h_tile > - output_info->tile_info.loc_h_tile)) - y += other_output_info->tile_info.tile_w; - if ((other_output_info->tile_info.loc_h_tile == - output_info->tile_info.loc_h_tile) && - (other_output_info->tile_info.loc_v_tile > - output_info->tile_info.loc_v_tile)) - x += other_output_info->tile_info.tile_h; - break; - case META_MONITOR_TRANSFORM_90: - case META_MONITOR_TRANSFORM_FLIPPED_90: - if ((other_output_info->tile_info.loc_v_tile == - output_info->tile_info.loc_v_tile) && - (other_output_info->tile_info.loc_h_tile < - output_info->tile_info.loc_h_tile)) - y += other_output_info->tile_info.tile_w; - if ((other_output_info->tile_info.loc_h_tile == - output_info->tile_info.loc_h_tile) && - (other_output_info->tile_info.loc_v_tile < - output_info->tile_info.loc_v_tile)) - x += other_output_info->tile_info.tile_h; - break; - } - } - - *out_x = x; - *out_y = y; -} - -static void -meta_monitor_tiled_calculate_tiled_size (MetaMonitor *monitor, - int *out_width, - int *out_height) -{ - MetaMonitorPrivate *monitor_priv = - meta_monitor_get_instance_private (monitor); - GList *l; - int width; - int height; - - width = 0; - height = 0; - for (l = monitor_priv->outputs; l; l = l->next) - { - const MetaOutputInfo *output_info = meta_output_get_info (l->data); - - if (output_info->tile_info.loc_v_tile == 0) - width += output_info->tile_info.tile_w; - - if (output_info->tile_info.loc_h_tile == 0) - height += output_info->tile_info.tile_h; - } - - *out_width = width; - *out_height = height; -} - -static gboolean -is_monitor_mode_assigned (MetaMonitor *monitor, - MetaMonitorMode *mode) -{ - MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor); - GList *l; - int i; - - for (l = priv->outputs, i = 0; l; l = l->next, i++) - { - MetaOutput *output = l->data; - MetaMonitorCrtcMode *monitor_crtc_mode = &mode->crtc_modes[i]; - MetaCrtc *crtc; - const MetaCrtcConfig *crtc_config; - - crtc = meta_output_get_assigned_crtc (output); - crtc_config = crtc ? meta_crtc_get_config (crtc) : NULL; - - if (monitor_crtc_mode->crtc_mode && - (!crtc || !crtc_config || - crtc_config->mode != monitor_crtc_mode->crtc_mode)) - return FALSE; - else if (!monitor_crtc_mode->crtc_mode && crtc) - return FALSE; - } - - return TRUE; -} - -static gboolean -is_crtc_mode_tiled (MetaOutput *output, - MetaCrtcMode *crtc_mode) -{ - const MetaOutputInfo *output_info = meta_output_get_info (output); - const MetaCrtcModeInfo *crtc_mode_info = meta_crtc_mode_get_info (crtc_mode); - - return (crtc_mode_info->width == (int) output_info->tile_info.tile_w && - crtc_mode_info->height == (int) output_info->tile_info.tile_h); -} - -static MetaCrtcMode * -find_tiled_crtc_mode (MetaOutput *output, - MetaCrtcMode *reference_crtc_mode) -{ - const MetaOutputInfo *output_info = meta_output_get_info (output); - const MetaCrtcModeInfo *reference_crtc_mode_info = - meta_crtc_mode_get_info (reference_crtc_mode); - MetaCrtcMode *crtc_mode; - unsigned int i; - - crtc_mode = output_info->preferred_mode; - if (is_crtc_mode_tiled (output, crtc_mode)) - return crtc_mode; - - for (i = 0; i < output_info->n_modes; i++) - { - const MetaCrtcModeInfo *crtc_mode_info; - - crtc_mode = output_info->modes[i]; - crtc_mode_info = meta_crtc_mode_get_info (crtc_mode); - - if (!is_crtc_mode_tiled (output, crtc_mode)) - continue; - - if (crtc_mode_info->refresh_rate != reference_crtc_mode_info->refresh_rate) - continue; - - if (crtc_mode_info->flags != reference_crtc_mode_info->flags) - continue; - - return crtc_mode; - } - - return NULL; -} - -static MetaMonitorMode * -create_tiled_monitor_mode (MetaMonitorTiled *monitor_tiled, - MetaCrtcMode *reference_crtc_mode, - gboolean *out_is_preferred) -{ - MetaMonitor *monitor = META_MONITOR (monitor_tiled); - MetaMonitorPrivate *monitor_priv = - meta_monitor_get_instance_private (monitor); - MetaMonitorModeTiled *mode; - int width, height; - GList *l; - unsigned int i; - gboolean is_preferred = TRUE; - - mode = g_new0 (MetaMonitorModeTiled, 1); - mode->is_tiled = TRUE; - meta_monitor_tiled_calculate_tiled_size (monitor, &width, &height); - mode->parent.monitor = monitor; - mode->parent.spec = - meta_monitor_create_spec (monitor, width, height, reference_crtc_mode); - mode->parent.id = generate_mode_id (&mode->parent.spec); - - mode->parent.crtc_modes = g_new0 (MetaMonitorCrtcMode, - g_list_length (monitor_priv->outputs)); - for (l = monitor_priv->outputs, i = 0; l; l = l->next, i++) - { - MetaOutput *output = l->data; - const MetaOutputInfo *output_info = meta_output_get_info (output); - MetaCrtcMode *tiled_crtc_mode; - - tiled_crtc_mode = find_tiled_crtc_mode (output, reference_crtc_mode); - if (!tiled_crtc_mode) - { - g_warning ("No tiled mode found on %s", meta_output_get_name (output)); - meta_monitor_mode_free ((MetaMonitorMode *) mode); - return NULL; - } - - mode->parent.crtc_modes[i] = (MetaMonitorCrtcMode) { - .output = output, - .crtc_mode = tiled_crtc_mode - }; - - is_preferred = (is_preferred && - tiled_crtc_mode == output_info->preferred_mode); - } - - *out_is_preferred = is_preferred; - - return (MetaMonitorMode *) mode; -} - -static void -generate_tiled_monitor_modes (MetaMonitorTiled *monitor_tiled) -{ - MetaMonitor *monitor = META_MONITOR (monitor_tiled); - MetaMonitorPrivate *monitor_priv = - meta_monitor_get_instance_private (monitor); - MetaOutput *main_output; - const MetaOutputInfo *main_output_info; - GList *tiled_modes = NULL; - unsigned int i; - MetaMonitorMode *best_mode = NULL; - GList *l; - - main_output = meta_monitor_get_main_output (META_MONITOR (monitor_tiled)); - main_output_info = meta_output_get_info (main_output); - - for (i = 0; i < main_output_info->n_modes; i++) - { - MetaCrtcMode *reference_crtc_mode = main_output_info->modes[i]; - MetaMonitorMode *mode; - gboolean is_preferred; - - if (!is_crtc_mode_tiled (main_output, reference_crtc_mode)) - continue; - - mode = create_tiled_monitor_mode (monitor_tiled, reference_crtc_mode, - &is_preferred); - if (!mode) - continue; - - tiled_modes = g_list_append (tiled_modes, mode); - - if (is_monitor_mode_assigned (monitor, mode)) - monitor_priv->current_mode = mode; - - if (is_preferred) - monitor_priv->preferred_mode = mode; - } - - while ((l = tiled_modes)) - { - MetaMonitorMode *mode = l->data; - - tiled_modes = g_list_remove_link (tiled_modes, l); - - if (!meta_monitor_add_mode (monitor, mode, FALSE)) - { - meta_monitor_mode_free (mode); - continue; - } - - if (!monitor_priv->preferred_mode) - { - if (!best_mode || - mode->spec.refresh_rate > best_mode->spec.refresh_rate) - best_mode = mode; - } - } - - if (best_mode) - monitor_priv->preferred_mode = best_mode; -} - -static MetaMonitorMode * -create_untiled_monitor_mode (MetaMonitorTiled *monitor_tiled, - MetaOutput *main_output, - MetaCrtcMode *crtc_mode) -{ - MetaMonitor *monitor = META_MONITOR (monitor_tiled); - MetaMonitorPrivate *monitor_priv = - meta_monitor_get_instance_private (monitor); - MetaMonitorModeTiled *mode; - const MetaCrtcModeInfo *crtc_mode_info; - GList *l; - int i; - - if (is_crtc_mode_tiled (main_output, crtc_mode)) - return NULL; - - mode = g_new0 (MetaMonitorModeTiled, 1); - mode->is_tiled = FALSE; - mode->parent.monitor = monitor; - - crtc_mode_info = meta_crtc_mode_get_info (crtc_mode); - mode->parent.spec = meta_monitor_create_spec (monitor, - crtc_mode_info->width, - crtc_mode_info->height, - crtc_mode); - mode->parent.id = generate_mode_id (&mode->parent.spec); - mode->parent.crtc_modes = g_new0 (MetaMonitorCrtcMode, - g_list_length (monitor_priv->outputs)); - - for (l = monitor_priv->outputs, i = 0; l; l = l->next, i++) - { - MetaOutput *output = l->data; - - if (output == main_output) - { - mode->parent.crtc_modes[i] = (MetaMonitorCrtcMode) { - .output = output, - .crtc_mode = crtc_mode - }; - } - else - { - mode->parent.crtc_modes[i] = (MetaMonitorCrtcMode) { - .output = output, - .crtc_mode = NULL - }; - } - } - - return &mode->parent; -} - -static int -count_untiled_crtc_modes (MetaOutput *output) -{ - const MetaOutputInfo *output_info = meta_output_get_info (output); - int count; - unsigned int i; - - count = 0; - for (i = 0; i < output_info->n_modes; i++) - { - MetaCrtcMode *crtc_mode = output_info->modes[i]; - - if (!is_crtc_mode_tiled (output, crtc_mode)) - count++; - } - - return count; -} - -static MetaOutput * -find_untiled_output (MetaMonitorTiled *monitor_tiled) -{ - MetaMonitor *monitor = META_MONITOR (monitor_tiled); - MetaMonitorPrivate *monitor_priv = - meta_monitor_get_instance_private (monitor); - MetaOutput *best_output; - int best_untiled_crtc_mode_count; - GList *l; - - best_output = monitor_tiled->origin_output; - best_untiled_crtc_mode_count = - count_untiled_crtc_modes (monitor_tiled->origin_output); - - for (l = monitor_priv->outputs; l; l = l->next) - { - MetaOutput *output = l->data; - int untiled_crtc_mode_count; - - if (output == monitor_tiled->origin_output) - continue; - - untiled_crtc_mode_count = count_untiled_crtc_modes (output); - if (untiled_crtc_mode_count > best_untiled_crtc_mode_count) - { - best_untiled_crtc_mode_count = untiled_crtc_mode_count; - best_output = output; - } - } - - return best_output; -} - -static void -generate_untiled_monitor_modes (MetaMonitorTiled *monitor_tiled) -{ - MetaMonitor *monitor = META_MONITOR (monitor_tiled); - MetaMonitorPrivate *monitor_priv = - meta_monitor_get_instance_private (monitor); - MetaOutput *main_output; - const MetaOutputInfo *main_output_info; - unsigned int i; - - main_output = meta_monitor_get_main_output (monitor); - main_output_info = meta_output_get_info (main_output); - - for (i = 0; i < main_output_info->n_modes; i++) - { - MetaCrtcMode *crtc_mode = main_output_info->modes[i]; - MetaMonitorMode *mode; - - mode = create_untiled_monitor_mode (monitor_tiled, - main_output, - crtc_mode); - if (!mode) - continue; - - if (!meta_monitor_add_mode (monitor, mode, FALSE)) - { - meta_monitor_mode_free (mode); - continue; - } - - if (is_monitor_mode_assigned (monitor, mode)) - { - g_assert (!monitor_priv->current_mode); - monitor_priv->current_mode = mode; - } - - if (!monitor_priv->preferred_mode && - crtc_mode == main_output_info->preferred_mode) - monitor_priv->preferred_mode = mode; - } -} - -static MetaMonitorMode * -find_best_mode (MetaMonitor *monitor) -{ - MetaMonitorPrivate *monitor_priv = - meta_monitor_get_instance_private (monitor); - MetaMonitorMode *best_mode = NULL; - GList *l; - - for (l = monitor_priv->modes; l; l = l->next) - { - MetaMonitorMode *mode = l->data; - int area, best_area; - - if (!best_mode) - { - best_mode = mode; - continue; - } - - area = mode->spec.width * mode->spec.height; - best_area = best_mode->spec.width * best_mode->spec.height; - if (area > best_area) - { - best_mode = mode; - continue; - } - - if (mode->spec.refresh_rate > best_mode->spec.refresh_rate) - { - best_mode = mode; - continue; - } - } - - return best_mode; -} - -static void -meta_monitor_tiled_generate_modes (MetaMonitorTiled *monitor_tiled) -{ - MetaMonitor *monitor = META_MONITOR (monitor_tiled); - MetaMonitorPrivate *monitor_priv = - meta_monitor_get_instance_private (monitor); - - /* - * Tiled monitors may look a bit different from each other, depending on the - * monitor itself, the driver, etc. - * - * On some, the tiled modes will be the preferred CRTC modes, and running - * untiled is done by only enabling (0, 0) tile. In this case, things are - * pretty straight forward. - * - * Other times a monitor may have some bogus mode preferred on the main tile, - * and an untiled mode preferred on the non-main tile, and there seems to be - * no guarantee that the (0, 0) tile is the one that should drive the - * non-tiled mode. - * - * To handle both these cases, the following hueristics are implemented: - * - * 1) Find all the tiled CRTC modes of the (0, 0) tile, and create tiled - * monitor modes for all tiles based on these. - * 2) If there is any tiled monitor mode combination where all CRTC modes - * are the preferred ones, that one is marked as preferred. - * 3) If there is no preferred mode determined so far, assume the tiled - * monitor mode with the highest refresh rate is preferred. - * 4) Find the tile with highest number of untiled CRTC modes available, - * assume this is the one driving the monitor in untiled mode, and - * create monitor modes for all untiled CRTC modes of that tile. If - * there is still no preferred mode, set any untiled mode as preferred - * if the CRTC mode is marked as such. - * 5) If at this point there is still no preferred mode, just pick the one - * with the highest number of pixels and highest refresh rate. - * - * Note that this ignores the preference if the preference is a non-tiled - * mode. This seems to be the case on some systems, where the user tends to - * manually set up the tiled mode anyway. - */ - - generate_tiled_monitor_modes (monitor_tiled); - - if (!monitor_priv->preferred_mode) - g_warning ("Tiled monitor on %s didn't have any tiled modes", - monitor_priv->spec->connector); - - generate_untiled_monitor_modes (monitor_tiled); - - if (!monitor_priv->preferred_mode) - { - g_warning ("Tiled monitor on %s didn't have a valid preferred mode", - monitor_priv->spec->connector); - monitor_priv->preferred_mode = find_best_mode (monitor); - } -} - -MetaMonitorTiled * -meta_monitor_tiled_new (MetaMonitorManager *monitor_manager, - MetaOutput *output) -{ - const MetaOutputInfo *output_info = meta_output_get_info (output); - MetaMonitorTiled *monitor_tiled; - MetaMonitor *monitor; - MetaMonitorPrivate *monitor_priv; - - monitor_tiled = g_object_new (META_TYPE_MONITOR_TILED, NULL); - monitor = META_MONITOR (monitor_tiled); - monitor_priv = meta_monitor_get_instance_private (monitor); - - monitor_priv->backend = meta_monitor_manager_get_backend (monitor_manager); - - monitor_tiled->tile_group_id = output_info->tile_info.group_id; - monitor_priv->winsys_id = meta_output_get_id (output); - - monitor_tiled->origin_output = output; - add_tiled_monitor_outputs (meta_output_get_gpu (output), monitor_tiled); - - monitor_tiled->main_output = find_untiled_output (monitor_tiled); - - meta_monitor_generate_spec (monitor); - - monitor_tiled->monitor_manager = monitor_manager; - meta_monitor_manager_tiled_monitor_added (monitor_manager, - META_MONITOR (monitor_tiled)); - - meta_monitor_tiled_generate_modes (monitor_tiled); - - monitor_priv->display_name = meta_monitor_make_display_name (monitor, - monitor_manager); - - return monitor_tiled; -} - -static MetaOutput * -meta_monitor_tiled_get_main_output (MetaMonitor *monitor) -{ - MetaMonitorTiled *monitor_tiled = META_MONITOR_TILED (monitor); - - return monitor_tiled->main_output; -} - -static void -meta_monitor_tiled_derive_layout (MetaMonitor *monitor, - MetaRectangle *layout) -{ - MetaMonitorPrivate *monitor_priv = - meta_monitor_get_instance_private (monitor); - GList *l; - float min_x, min_y, max_x, max_y; - - min_x = FLT_MAX; - min_y = FLT_MAX; - max_x = 0.0; - max_y = 0.0; - for (l = monitor_priv->outputs; l; l = l->next) - { - MetaOutput *output = l->data; - MetaCrtc *crtc; - const MetaCrtcConfig *crtc_config; - const graphene_rect_t *crtc_layout; - - crtc = meta_output_get_assigned_crtc (output); - if (!crtc) - continue; - - crtc_config = meta_crtc_get_config (crtc); - g_return_if_fail (crtc_config); - - crtc_layout = &crtc_config->layout; - - min_x = MIN (crtc_layout->origin.x, min_x); - min_y = MIN (crtc_layout->origin.y, min_y); - max_x = MAX (crtc_layout->origin.x + crtc_layout->size.width, max_x); - max_y = MAX (crtc_layout->origin.y + crtc_layout->size.height, max_y); - } - - *layout = (MetaRectangle) { - .x = roundf (min_x), - .y = roundf (min_y), - .width = roundf (max_x - min_x), - .height = roundf (max_y - min_y) - }; -} - -static gboolean -meta_monitor_tiled_get_suggested_position (MetaMonitor *monitor, - int *x, - int *y) -{ - return FALSE; -} - -static void -meta_monitor_tiled_calculate_crtc_pos (MetaMonitor *monitor, - MetaMonitorMode *monitor_mode, - MetaOutput *output, - MetaMonitorTransform crtc_transform, - int *out_x, - int *out_y) -{ - MetaMonitorModeTiled *mode_tiled = (MetaMonitorModeTiled *) monitor_mode; - - if (mode_tiled->is_tiled) - { - calculate_tile_coordinate (monitor, output, crtc_transform, - out_x, out_y); - } - else - { - *out_x = 0; - *out_y = 0; - } -} - -static void -meta_monitor_tiled_finalize (GObject *object) -{ - MetaMonitorTiled *monitor_tiled = META_MONITOR_TILED (object); - - meta_monitor_manager_tiled_monitor_removed (monitor_tiled->monitor_manager, - META_MONITOR (monitor_tiled)); - - G_OBJECT_CLASS (meta_monitor_tiled_parent_class)->finalize (object); -} - -static void -meta_monitor_tiled_init (MetaMonitorTiled *monitor) -{ -} - -static void -meta_monitor_tiled_class_init (MetaMonitorTiledClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaMonitorClass *monitor_class = META_MONITOR_CLASS (klass); - - object_class->finalize = meta_monitor_tiled_finalize; - - monitor_class->get_main_output = meta_monitor_tiled_get_main_output; - monitor_class->derive_layout = meta_monitor_tiled_derive_layout; - monitor_class->calculate_crtc_pos = meta_monitor_tiled_calculate_crtc_pos; - monitor_class->get_suggested_position = meta_monitor_tiled_get_suggested_position; -} - -static void -meta_monitor_mode_free (MetaMonitorMode *monitor_mode) -{ - g_free (monitor_mode->id); - g_free (monitor_mode->crtc_modes); - g_free (monitor_mode); -} - -MetaMonitorSpec * -meta_monitor_get_spec (MetaMonitor *monitor) -{ - MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor); - - return priv->spec; -} - -MetaLogicalMonitor * -meta_monitor_get_logical_monitor (MetaMonitor *monitor) -{ - MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor); - - return priv->logical_monitor; -} - -MetaMonitorMode * -meta_monitor_get_mode_from_id (MetaMonitor *monitor, - const char *monitor_mode_id) -{ - MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor); - - return g_hash_table_lookup (priv->mode_ids, monitor_mode_id); -} - -static gboolean -meta_monitor_mode_spec_equals (MetaMonitorModeSpec *monitor_mode_spec, - MetaMonitorModeSpec *other_monitor_mode_spec) -{ - return (monitor_mode_spec->width == other_monitor_mode_spec->width && - monitor_mode_spec->height == other_monitor_mode_spec->height && - ABS (monitor_mode_spec->refresh_rate - - other_monitor_mode_spec->refresh_rate) < MAXIMUM_REFRESH_RATE_DIFF && - monitor_mode_spec->flags == other_monitor_mode_spec->flags); -} - -MetaMonitorMode * -meta_monitor_get_mode_from_spec (MetaMonitor *monitor, - MetaMonitorModeSpec *monitor_mode_spec) -{ - MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor); - GList *l; - - for (l = priv->modes; l; l = l->next) - { - MetaMonitorMode *monitor_mode = l->data; - - if (meta_monitor_mode_spec_equals (monitor_mode_spec, - &monitor_mode->spec)) - return monitor_mode; - } - - return NULL; -} - -MetaMonitorMode * -meta_monitor_get_preferred_mode (MetaMonitor *monitor) -{ - MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor); - - return priv->preferred_mode; -} - -MetaMonitorMode * -meta_monitor_get_current_mode (MetaMonitor *monitor) -{ - MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor); - - return priv->current_mode; -} - -static gboolean -is_current_mode_known (MetaMonitor *monitor) -{ - MetaOutput *output; - MetaCrtc *crtc; - - output = meta_monitor_get_main_output (monitor); - crtc = meta_output_get_assigned_crtc (output); - - return (meta_monitor_is_active (monitor) == - (crtc && meta_crtc_get_config (crtc))); -} - -void -meta_monitor_derive_current_mode (MetaMonitor *monitor) -{ - MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor); - MetaMonitorMode *current_mode = NULL; - GList *l; - - for (l = priv->modes; l; l = l->next) - { - MetaMonitorMode *mode = l->data; - - if (is_monitor_mode_assigned (monitor, mode)) - { - current_mode = mode; - break; - } - } - - priv->current_mode = current_mode; - - g_warn_if_fail (is_current_mode_known (monitor)); -} - -void -meta_monitor_set_current_mode (MetaMonitor *monitor, - MetaMonitorMode *mode) -{ - MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor); - - priv->current_mode = mode; -} - -GList * -meta_monitor_get_modes (MetaMonitor *monitor) -{ - MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor); - - return priv->modes; -} - -void -meta_monitor_calculate_crtc_pos (MetaMonitor *monitor, - MetaMonitorMode *monitor_mode, - MetaOutput *output, - MetaMonitorTransform crtc_transform, - int *out_x, - int *out_y) -{ - META_MONITOR_GET_CLASS (monitor)->calculate_crtc_pos (monitor, - monitor_mode, - output, - crtc_transform, - out_x, - out_y); -} - -/* The minimum resolution at which we turn on a window-scale of 2 */ -#define HIDPI_LIMIT 192 - -/* - * The minimum screen height at which we turn on a window-scale of 2; - * below this there just isn't enough vertical real estate for GNOME - * apps to work, and it's better to just be tiny - */ -#define HIDPI_MIN_HEIGHT 1200 - -/* From http://en.wikipedia.org/wiki/4K_resolution#Resolutions_of_common_formats */ -#define SMALLEST_4K_WIDTH 3656 - -static float -calculate_scale (MetaMonitor *monitor, - MetaMonitorMode *monitor_mode) -{ - int resolution_width, resolution_height; - int width_mm, height_mm; - int scale; - - scale = 1.0; - - meta_monitor_mode_get_resolution (monitor_mode, - &resolution_width, - &resolution_height); - - if (resolution_height < HIDPI_MIN_HEIGHT) - goto out; - - /* 4K TV */ - switch (meta_monitor_get_connector_type (monitor)) - { - case META_CONNECTOR_TYPE_HDMIA: - case META_CONNECTOR_TYPE_HDMIB: - if (resolution_width < SMALLEST_4K_WIDTH) - goto out; - break; - default: - break; - } - - meta_monitor_get_physical_dimensions (monitor, &width_mm, &height_mm); - - /* - * Somebody encoded the aspect ratio (16/9 or 16/10) instead of the physical - * size. - */ - if (meta_monitor_has_aspect_as_size (monitor)) - goto out; - - if (width_mm > 0 && height_mm > 0) - { - double dpi_x, dpi_y; - - dpi_x = (double) resolution_width / (width_mm / 25.4); - dpi_y = (double) resolution_height / (height_mm / 25.4); - - /* - * We don't completely trust these values so both must be high, and never - * pick higher ratio than 2 automatically. - */ - if (dpi_x > HIDPI_LIMIT && dpi_y > HIDPI_LIMIT) - scale = 2.0; - } - -out: - return scale; -} - -float -meta_monitor_calculate_mode_scale (MetaMonitor *monitor, - MetaMonitorMode *monitor_mode) -{ - MetaBackend *backend = meta_get_backend (); - MetaSettings *settings = meta_backend_get_settings (backend); - int global_scaling_factor; - - if (meta_settings_get_global_scaling_factor (settings, - &global_scaling_factor)) - return global_scaling_factor; - - return calculate_scale (monitor, monitor_mode); -} - -static gboolean -is_logical_size_large_enough (int width, - int height) -{ - return width * height >= MINIMUM_LOGICAL_AREA; -} - -gboolean -meta_monitor_mode_should_be_advertised (MetaMonitorMode *monitor_mode) -{ - MetaMonitorMode *preferred_mode; - - g_return_val_if_fail (monitor_mode != NULL, FALSE); - - preferred_mode = meta_monitor_get_preferred_mode (monitor_mode->monitor); - if (monitor_mode->spec.width == preferred_mode->spec.width && - monitor_mode->spec.height == preferred_mode->spec.height) - return TRUE; - - return is_logical_size_large_enough (monitor_mode->spec.width, - monitor_mode->spec.height); -} - -static float -get_closest_scale_factor_for_resolution (float width, - float height, - float scale) -{ - unsigned int i, j; - float scaled_h; - float scaled_w; - float best_scale; - int base_scaled_w; - gboolean found_one; - - best_scale = 0; - scaled_w = width / scale; - scaled_h = height / scale; - - if (scale < MINIMUM_SCALE_FACTOR || - scale > MAXIMUM_SCALE_FACTOR || - !is_logical_size_large_enough (floorf (scaled_w), floorf (scaled_h))) - goto out; - - if (floorf (scaled_w) == scaled_w && floorf (scaled_h) == scaled_h) - return scale; - - i = 0; - found_one = FALSE; - base_scaled_w = floorf (scaled_w); - - do - { - for (j = 0; j < 2; j++) - { - float current_scale; - int offset = i * (j ? 1 : -1); - - scaled_w = base_scaled_w + offset; - current_scale = width / scaled_w; - scaled_h = height / current_scale; - - if (current_scale >= scale + SCALE_FACTORS_STEPS || - current_scale <= scale - SCALE_FACTORS_STEPS || - current_scale < MINIMUM_SCALE_FACTOR || - current_scale > MAXIMUM_SCALE_FACTOR) - { - goto out; - } - - if (floorf (scaled_h) == scaled_h) - { - found_one = TRUE; - - if (fabsf (current_scale - scale) < fabsf (best_scale - scale)) - best_scale = current_scale; - } - } - - i++; - } - while (!found_one); - -out: - return best_scale; -} - -float * -meta_monitor_calculate_supported_scales (MetaMonitor *monitor, - MetaMonitorMode *monitor_mode, - MetaMonitorScalesConstraint constraints, - int *n_supported_scales) -{ - unsigned int i, j; - int width, height; - GArray *supported_scales; - - supported_scales = g_array_new (FALSE, FALSE, sizeof (float)); - - meta_monitor_mode_get_resolution (monitor_mode, &width, &height); - - for (i = floorf (MINIMUM_SCALE_FACTOR); - i <= ceilf (MAXIMUM_SCALE_FACTOR); - i++) - { - for (j = 0; j < SCALE_FACTORS_PER_INTEGER; j++) - { - float scale; - float scale_value = i + j * SCALE_FACTORS_STEPS; - - if ((constraints & META_MONITOR_SCALES_CONSTRAINT_NO_FRAC) && - fmodf (scale_value, 1.0) != 0.0) - { - continue; - } - - scale = get_closest_scale_factor_for_resolution (width, - height, - scale_value); - - if (scale > 0.0f) - g_array_append_val (supported_scales, scale); - } - } - - if (supported_scales->len == 0) - { - float fallback_scale; - - fallback_scale = 1.0; - g_array_append_val (supported_scales, fallback_scale); - } - - *n_supported_scales = supported_scales->len; - return (float *) g_array_free (supported_scales, FALSE); -} - -MetaMonitorModeSpec * -meta_monitor_mode_get_spec (MetaMonitorMode *monitor_mode) -{ - return &monitor_mode->spec; -} - -const char * -meta_monitor_mode_get_id (MetaMonitorMode *monitor_mode) -{ - return monitor_mode->id; -} - -void -meta_monitor_mode_get_resolution (MetaMonitorMode *monitor_mode, - int *width, - int *height) -{ - *width = monitor_mode->spec.width; - *height = monitor_mode->spec.height; -} - -float -meta_monitor_mode_get_refresh_rate (MetaMonitorMode *monitor_mode) -{ - return monitor_mode->spec.refresh_rate; -} - -MetaCrtcModeFlag -meta_monitor_mode_get_flags (MetaMonitorMode *monitor_mode) -{ - return monitor_mode->spec.flags; -} - -gboolean -meta_monitor_mode_foreach_crtc (MetaMonitor *monitor, - MetaMonitorMode *mode, - MetaMonitorModeFunc func, - gpointer user_data, - GError **error) -{ - MetaMonitorPrivate *monitor_priv = - meta_monitor_get_instance_private (monitor); - GList *l; - int i; - - for (l = monitor_priv->outputs, i = 0; l; l = l->next, i++) - { - MetaMonitorCrtcMode *monitor_crtc_mode = &mode->crtc_modes[i]; - - if (!monitor_crtc_mode->crtc_mode) - continue; - - if (!func (monitor, mode, monitor_crtc_mode, user_data, error)) - return FALSE; - } - - return TRUE; -} - -gboolean -meta_monitor_mode_foreach_output (MetaMonitor *monitor, - MetaMonitorMode *mode, - MetaMonitorModeFunc func, - gpointer user_data, - GError **error) -{ - MetaMonitorPrivate *monitor_priv = - meta_monitor_get_instance_private (monitor); - GList *l; - int i; - - for (l = monitor_priv->outputs, i = 0; l; l = l->next, i++) - { - MetaMonitorCrtcMode *monitor_crtc_mode = &mode->crtc_modes[i]; - - if (!func (monitor, mode, monitor_crtc_mode, user_data, error)) - return FALSE; - } - - return TRUE; -} - -MetaMonitorCrtcMode * -meta_monitor_get_crtc_mode_for_output (MetaMonitor *monitor, - MetaMonitorMode *mode, - MetaOutput *output) -{ - MetaMonitorPrivate *monitor_priv = - meta_monitor_get_instance_private (monitor); - GList *l; - int i; - - for (l = monitor_priv->outputs, i = 0; l; l = l->next, i++) - { - MetaMonitorCrtcMode *monitor_crtc_mode = &mode->crtc_modes[i]; - - if (monitor_crtc_mode->output == output) - return monitor_crtc_mode; - } - - g_warn_if_reached (); - return NULL; -} - -const char * -meta_monitor_get_display_name (MetaMonitor *monitor) -{ - MetaMonitorPrivate *monitor_priv = - meta_monitor_get_instance_private (monitor); - - return monitor_priv->display_name; -} - -void -meta_monitor_set_logical_monitor (MetaMonitor *monitor, - MetaLogicalMonitor *logical_monitor) -{ - MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor); - - priv->logical_monitor = logical_monitor; -} diff --git a/src/backends/meta-monitor.h b/src/backends/meta-monitor.h deleted file mode 100644 index 341657ae3..000000000 --- a/src/backends/meta-monitor.h +++ /dev/null @@ -1,280 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 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_MONITOR_H -#define META_MONITOR_H - -#include - -#include "backends/meta-backend-types.h" -#include "backends/meta-crtc.h" -#include "backends/meta-output.h" - -typedef struct _MetaMonitorSpec -{ - char *connector; - char *vendor; - char *product; - char *serial; -} MetaMonitorSpec; - -typedef struct _MetaMonitorModeSpec -{ - int width; - int height; - float refresh_rate; - MetaCrtcModeFlag flags; -} MetaMonitorModeSpec; - -typedef struct _MetaMonitorCrtcMode -{ - MetaOutput *output; - MetaCrtcMode *crtc_mode; -} MetaMonitorCrtcMode; - -#define HANDLED_CRTC_MODE_FLAGS (META_CRTC_MODE_FLAG_INTERLACE) - -typedef gboolean (* MetaMonitorModeFunc) (MetaMonitor *monitor, - MetaMonitorMode *mode, - MetaMonitorCrtcMode *monitor_crtc_mode, - gpointer user_data, - GError **error); - -typedef enum _MetaMonitorScalesConstraint -{ - META_MONITOR_SCALES_CONSTRAINT_NONE = 0, - META_MONITOR_SCALES_CONSTRAINT_NO_FRAC = (1 << 0), -} MetaMonitorScalesConstraint; - -#define META_TYPE_MONITOR (meta_monitor_get_type ()) -META_EXPORT_TEST -G_DECLARE_DERIVABLE_TYPE (MetaMonitor, meta_monitor, META, MONITOR, GObject) - -struct _MetaMonitorClass -{ - GObjectClass parent_class; - - MetaOutput * (* get_main_output) (MetaMonitor *monitor); - void (* derive_layout) (MetaMonitor *monitor, - MetaRectangle *layout); - void (* calculate_crtc_pos) (MetaMonitor *monitor, - MetaMonitorMode *monitor_mode, - MetaOutput *output, - MetaMonitorTransform crtc_transform, - int *out_x, - int *out_y); - gboolean (* get_suggested_position) (MetaMonitor *monitor, - int *width, - int *height); -}; - -#define META_TYPE_MONITOR_NORMAL (meta_monitor_normal_get_type ()) -G_DECLARE_FINAL_TYPE (MetaMonitorNormal, meta_monitor_normal, - META, MONITOR_NORMAL, - MetaMonitor) - -#define META_TYPE_MONITOR_TILED (meta_monitor_tiled_get_type ()) -G_DECLARE_FINAL_TYPE (MetaMonitorTiled, meta_monitor_tiled, - META, MONITOR_TILED, - MetaMonitor) - -MetaMonitorTiled * meta_monitor_tiled_new (MetaMonitorManager *monitor_manager, - MetaOutput *output); - -MetaMonitorNormal * meta_monitor_normal_new (MetaMonitorManager *monitor_manager, - MetaOutput *output); - -MetaMonitorSpec * meta_monitor_get_spec (MetaMonitor *monitor); - -MetaBackend * meta_monitor_get_backend (MetaMonitor *monitor); - -META_EXPORT_TEST -gboolean meta_monitor_is_active (MetaMonitor *monitor); - -META_EXPORT_TEST -MetaOutput * meta_monitor_get_main_output (MetaMonitor *monitor); - -gboolean meta_monitor_is_primary (MetaMonitor *monitor); - -gboolean meta_monitor_supports_underscanning (MetaMonitor *monitor); - -gboolean meta_monitor_is_underscanning (MetaMonitor *monitor); - -gboolean meta_monitor_is_laptop_panel (MetaMonitor *monitor); - -gboolean meta_monitor_is_same_as (MetaMonitor *monitor, - MetaMonitor *other_monitor); - -META_EXPORT_TEST -GList * meta_monitor_get_outputs (MetaMonitor *monitor); - -void meta_monitor_get_current_resolution (MetaMonitor *monitor, - int *width, - int *height); - -void meta_monitor_derive_layout (MetaMonitor *monitor, - MetaRectangle *layout); - -META_EXPORT_TEST -void meta_monitor_get_physical_dimensions (MetaMonitor *monitor, - int *width_mm, - int *height_mm); - -CoglSubpixelOrder meta_monitor_get_subpixel_order (MetaMonitor *monitor); - -META_EXPORT_TEST -const char * meta_monitor_get_connector (MetaMonitor *monitor); - -META_EXPORT_TEST -const char * meta_monitor_get_vendor (MetaMonitor *monitor); - -META_EXPORT_TEST -const char * meta_monitor_get_product (MetaMonitor *monitor); - -META_EXPORT_TEST -const char * meta_monitor_get_serial (MetaMonitor *monitor); - -META_EXPORT_TEST -MetaConnectorType meta_monitor_get_connector_type (MetaMonitor *monitor); - -/* This function returns the transform corrected for the panel orientation */ -META_EXPORT_TEST -MetaMonitorTransform meta_monitor_logical_to_crtc_transform (MetaMonitor *monitor, - MetaMonitorTransform transform); -/* - * This function converts a transform corrected for the panel orientation - * to its logical (user-visible) transform. - */ -META_EXPORT_TEST -MetaMonitorTransform meta_monitor_crtc_to_logical_transform (MetaMonitor *monitor, - MetaMonitorTransform transform); - -META_EXPORT_TEST -uint32_t meta_monitor_tiled_get_tile_group_id (MetaMonitorTiled *monitor_tiled); - -META_EXPORT_TEST -gboolean meta_monitor_get_suggested_position (MetaMonitor *monitor, - int *x, - int *y); - -META_EXPORT_TEST -MetaLogicalMonitor * meta_monitor_get_logical_monitor (MetaMonitor *monitor); - -META_EXPORT_TEST -MetaMonitorMode * meta_monitor_get_mode_from_id (MetaMonitor *monitor, - const char *monitor_mode_id); - -META_EXPORT_TEST -MetaMonitorMode * meta_monitor_get_mode_from_spec (MetaMonitor *monitor, - MetaMonitorModeSpec *monitor_mode_spec); - -META_EXPORT_TEST -MetaMonitorMode * meta_monitor_get_preferred_mode (MetaMonitor *monitor); - -META_EXPORT_TEST -MetaMonitorMode * meta_monitor_get_current_mode (MetaMonitor *monitor); - -META_EXPORT_TEST -void meta_monitor_derive_current_mode (MetaMonitor *monitor); - -META_EXPORT_TEST -void meta_monitor_set_current_mode (MetaMonitor *monitor, - MetaMonitorMode *mode); - -META_EXPORT_TEST -GList * meta_monitor_get_modes (MetaMonitor *monitor); - -META_EXPORT_TEST -void meta_monitor_calculate_crtc_pos (MetaMonitor *monitor, - MetaMonitorMode *monitor_mode, - MetaOutput *output, - MetaMonitorTransform crtc_transform, - int *out_x, - int *out_y); - -META_EXPORT_TEST -float meta_monitor_calculate_mode_scale (MetaMonitor *monitor, - MetaMonitorMode *monitor_mode); - -META_EXPORT_TEST -float * meta_monitor_calculate_supported_scales (MetaMonitor *monitor, - MetaMonitorMode *monitor_mode, - MetaMonitorScalesConstraint constraints, - int *n_supported_scales); - -META_EXPORT_TEST -const char * meta_monitor_mode_get_id (MetaMonitorMode *monitor_mode); - -META_EXPORT_TEST -MetaMonitorModeSpec * meta_monitor_mode_get_spec (MetaMonitorMode *monitor_mode); - -META_EXPORT_TEST -void meta_monitor_mode_get_resolution (MetaMonitorMode *monitor_mode, - int *width, - int *height); - -META_EXPORT_TEST -float meta_monitor_mode_get_refresh_rate (MetaMonitorMode *monitor_mode); - -META_EXPORT_TEST -MetaCrtcModeFlag meta_monitor_mode_get_flags (MetaMonitorMode *monitor_mode); - -META_EXPORT_TEST -gboolean meta_monitor_mode_foreach_crtc (MetaMonitor *monitor, - MetaMonitorMode *mode, - MetaMonitorModeFunc func, - gpointer user_data, - GError **error); - -META_EXPORT_TEST -gboolean meta_monitor_mode_foreach_output (MetaMonitor *monitor, - MetaMonitorMode *mode, - MetaMonitorModeFunc func, - gpointer user_data, - GError **error); - -MetaMonitorCrtcMode * meta_monitor_get_crtc_mode_for_output (MetaMonitor *monitor, - MetaMonitorMode *mode, - MetaOutput *output); - -META_EXPORT_TEST -gboolean meta_monitor_mode_should_be_advertised (MetaMonitorMode *monitor_mode); - -META_EXPORT_TEST -MetaMonitorSpec * meta_monitor_spec_clone (MetaMonitorSpec *monitor_id); - -META_EXPORT_TEST -gboolean meta_monitor_spec_equals (MetaMonitorSpec *monitor_id, - MetaMonitorSpec *other_monitor_id); - -META_EXPORT_TEST -int meta_monitor_spec_compare (MetaMonitorSpec *monitor_spec_a, - MetaMonitorSpec *monitor_spec_b); - -META_EXPORT_TEST -void meta_monitor_spec_free (MetaMonitorSpec *monitor_id); - -const char * meta_monitor_get_display_name (MetaMonitor *monitor); - -void meta_monitor_set_logical_monitor (MetaMonitor *monitor, - MetaLogicalMonitor *logical_monitor); - -#endif /* META_MONITOR_H */ diff --git a/src/backends/meta-orientation-manager.c b/src/backends/meta-orientation-manager.c deleted file mode 100644 index 52a1d1de6..000000000 --- a/src/backends/meta-orientation-manager.c +++ /dev/null @@ -1,335 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 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. - */ - -#include "config.h" - -#include "backends/meta-orientation-manager.h" - -#include - -enum -{ - ORIENTATION_CHANGED, - - N_SIGNALS -}; - -static guint signals[N_SIGNALS]; - -enum -{ - PROP_0, - - PROP_HAS_ACCELEROMETER, - - PROP_LAST -}; - -static GParamSpec *props[PROP_LAST]; - -struct _MetaOrientationManager -{ - GObject parent_instance; - - GCancellable *cancellable; - - guint iio_watch_id; - GDBusProxy *iio_proxy; - MetaOrientation prev_orientation; - MetaOrientation curr_orientation; - guint has_accel : 1; - - GSettings *settings; -}; - -G_DEFINE_TYPE (MetaOrientationManager, meta_orientation_manager, G_TYPE_OBJECT) - -#define CONF_SCHEMA "org.gnome.settings-daemon.peripherals.touchscreen" -#define ORIENTATION_LOCK_KEY "orientation-lock" - -static MetaOrientation -orientation_from_string (const char *orientation) -{ - if (g_strcmp0 (orientation, "normal") == 0) - return META_ORIENTATION_NORMAL; - if (g_strcmp0 (orientation, "bottom-up") == 0) - return META_ORIENTATION_BOTTOM_UP; - if (g_strcmp0 (orientation, "left-up") == 0) - return META_ORIENTATION_LEFT_UP; - if (g_strcmp0 (orientation, "right-up") == 0) - return META_ORIENTATION_RIGHT_UP; - - return META_ORIENTATION_UNDEFINED; -} - -static void -read_iio_proxy (MetaOrientationManager *self) -{ - GVariant *v; - - self->curr_orientation = META_ORIENTATION_UNDEFINED; - - if (!self->iio_proxy) - { - self->has_accel = FALSE; - return; - } - - v = g_dbus_proxy_get_cached_property (self->iio_proxy, "HasAccelerometer"); - if (v) - { - self->has_accel = !!g_variant_get_boolean (v); - g_variant_unref (v); - } - - if (self->has_accel) - { - v = g_dbus_proxy_get_cached_property (self->iio_proxy, "AccelerometerOrientation"); - if (v) - { - self->curr_orientation = orientation_from_string (g_variant_get_string (v, NULL)); - g_variant_unref (v); - } - } -} - -static void -sync_state (MetaOrientationManager *self) -{ - gboolean had_accel = self->has_accel; - - read_iio_proxy (self); - - if (had_accel != self->has_accel) - g_object_notify_by_pspec (G_OBJECT (self), props[PROP_HAS_ACCELEROMETER]); - - if (g_settings_get_boolean (self->settings, ORIENTATION_LOCK_KEY)) - return; - - if (self->prev_orientation == self->curr_orientation) - return; - - self->prev_orientation = self->curr_orientation; - - if (self->curr_orientation == META_ORIENTATION_UNDEFINED) - return; - - g_signal_emit (self, signals[ORIENTATION_CHANGED], 0); -} - -static void -orientation_lock_changed (GSettings *settings, - gchar *key, - gpointer user_data) -{ - MetaOrientationManager *self = user_data; - sync_state (self); -} - -static void -iio_properties_changed (GDBusProxy *proxy, - GVariant *changed_properties, - GStrv invalidated_properties, - gpointer user_data) -{ - MetaOrientationManager *self = user_data; - sync_state (self); -} - -static void -accelerometer_claimed (GObject *source, - GAsyncResult *res, - gpointer user_data) -{ - MetaOrientationManager *self = user_data; - GVariant *v; - GError *error = NULL; - - v = g_dbus_proxy_call_finish (G_DBUS_PROXY (source), res, &error); - if (!v) - { - if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - g_warning ("Failed to claim accelerometer: %s", error->message); - g_error_free (error); - return; - } - - g_variant_unref (v); - - sync_state (self); -} - -static void -iio_proxy_ready (GObject *source, - GAsyncResult *res, - gpointer user_data) -{ - MetaOrientationManager *self = user_data; - GDBusProxy *proxy; - GError *error = NULL; - - proxy = g_dbus_proxy_new_finish (res, &error); - if (!proxy) - { - if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - g_warning ("Failed to obtain IIO DBus proxy: %s", error->message); - g_error_free (error); - return; - } - - self->iio_proxy = proxy; - g_signal_connect_object (self->iio_proxy, "g-properties-changed", - G_CALLBACK (iio_properties_changed), self, 0); - g_dbus_proxy_call (self->iio_proxy, - "ClaimAccelerometer", - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, - self->cancellable, - accelerometer_claimed, - self); -} - -static void -iio_sensor_appeared_cb (GDBusConnection *connection, - const gchar *name, - const gchar *name_owner, - gpointer user_data) -{ - MetaOrientationManager *self = user_data; - - self->cancellable = g_cancellable_new (); - g_dbus_proxy_new (connection, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "net.hadess.SensorProxy", - "/net/hadess/SensorProxy", - "net.hadess.SensorProxy", - self->cancellable, - iio_proxy_ready, - self); -} - -static void -iio_sensor_vanished_cb (GDBusConnection *connection, - const gchar *name, - gpointer user_data) -{ - MetaOrientationManager *self = user_data; - - g_cancellable_cancel (self->cancellable); - g_clear_object (&self->cancellable); - - g_clear_object (&self->iio_proxy); - - sync_state (self); -} - -static void -meta_orientation_manager_init (MetaOrientationManager *self) -{ - self->iio_watch_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM, - "net.hadess.SensorProxy", - G_BUS_NAME_WATCHER_FLAGS_NONE, - iio_sensor_appeared_cb, - iio_sensor_vanished_cb, - self, - NULL); - - self->settings = g_settings_new (CONF_SCHEMA); - g_signal_connect_object (self->settings, "changed::"ORIENTATION_LOCK_KEY, - G_CALLBACK (orientation_lock_changed), self, 0); - sync_state (self); -} - -static void -meta_orientation_manager_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaOrientationManager *self = META_ORIENTATION_MANAGER (object); - - switch (prop_id) - { - case PROP_HAS_ACCELEROMETER: - g_value_set_boolean (value, self->has_accel); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_orientation_manager_finalize (GObject *object) -{ - MetaOrientationManager *self = META_ORIENTATION_MANAGER (object); - - g_cancellable_cancel (self->cancellable); - g_clear_object (&self->cancellable); - - g_bus_unwatch_name (self->iio_watch_id); - g_clear_object (&self->iio_proxy); - - g_clear_object (&self->settings); - - G_OBJECT_CLASS (meta_orientation_manager_parent_class)->finalize (object); -} - -static void -meta_orientation_manager_class_init (MetaOrientationManagerClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - gobject_class->finalize = meta_orientation_manager_finalize; - gobject_class->get_property = meta_orientation_manager_get_property; - - signals[ORIENTATION_CHANGED] = - g_signal_new ("orientation-changed", - G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - props[PROP_HAS_ACCELEROMETER] = - g_param_spec_boolean ("has-accelerometer", - "Has accelerometer", - "Has accelerometer", - FALSE, - G_PARAM_READABLE | - G_PARAM_EXPLICIT_NOTIFY | - G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (gobject_class, PROP_LAST, props); -} - -MetaOrientation -meta_orientation_manager_get_orientation (MetaOrientationManager *self) -{ - return self->curr_orientation; -} - -gboolean -meta_orientation_manager_has_accelerometer (MetaOrientationManager *self) -{ - return self->has_accel; -} diff --git a/src/backends/meta-orientation-manager.h b/src/backends/meta-orientation-manager.h deleted file mode 100644 index 9ae87957d..000000000 --- a/src/backends/meta-orientation-manager.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 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_ORIENTATION_MANAGER_H -#define META_ORIENTATION_MANAGER_H - -#include - -typedef enum -{ - META_ORIENTATION_UNDEFINED, - META_ORIENTATION_NORMAL, - META_ORIENTATION_BOTTOM_UP, - META_ORIENTATION_LEFT_UP, - META_ORIENTATION_RIGHT_UP -} MetaOrientation; - -#define META_TYPE_ORIENTATION_MANAGER (meta_orientation_manager_get_type ()) -G_DECLARE_FINAL_TYPE (MetaOrientationManager, meta_orientation_manager, - META, ORIENTATION_MANAGER, GObject) - -MetaOrientation meta_orientation_manager_get_orientation (MetaOrientationManager *self); - -gboolean meta_orientation_manager_has_accelerometer (MetaOrientationManager *self); - -#endif /* META_ORIENTATION_MANAGER_H */ diff --git a/src/backends/meta-output.c b/src/backends/meta-output.c deleted file mode 100644 index 432697d6d..000000000 --- a/src/backends/meta-output.c +++ /dev/null @@ -1,465 +0,0 @@ -/* - * Copyright (C) 2017 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. - */ - -#include "config.h" - -#include "backends/edid.h" -#include "backends/meta-output.h" - -#include "backends/meta-crtc.h" - -enum -{ - PROP_0, - - PROP_ID, - PROP_GPU, - PROP_INFO, - - N_PROPS -}; - -static GParamSpec *obj_props[N_PROPS]; - -typedef struct _MetaOutputPrivate -{ - uint64_t id; - - MetaGpu *gpu; - - MetaOutputInfo *info; - - MetaMonitor *monitor; - - /* The CRTC driving this output, NULL if the output is not enabled */ - MetaCrtc *crtc; - - gboolean is_primary; - gboolean is_presentation; - - gboolean is_underscanning; - - int backlight; -} MetaOutputPrivate; - -G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaOutput, meta_output, G_TYPE_OBJECT) - -G_DEFINE_BOXED_TYPE (MetaOutputInfo, meta_output_info, - meta_output_info_ref, - meta_output_info_unref) - -MetaOutputInfo * -meta_output_info_new (void) -{ - MetaOutputInfo *output_info; - - output_info = g_new0 (MetaOutputInfo, 1); - g_ref_count_init (&output_info->ref_count); - - return output_info; -} - -MetaOutputInfo * -meta_output_info_ref (MetaOutputInfo *output_info) -{ - g_ref_count_inc (&output_info->ref_count); - return output_info; -} - -void -meta_output_info_unref (MetaOutputInfo *output_info) -{ - if (g_ref_count_dec (&output_info->ref_count)) - { - g_free (output_info->name); - g_free (output_info->vendor); - g_free (output_info->product); - g_free (output_info->serial); - g_free (output_info->modes); - g_free (output_info->possible_crtcs); - g_free (output_info->possible_clones); - g_free (output_info); - } -} - -uint64_t -meta_output_get_id (MetaOutput *output) -{ - MetaOutputPrivate *priv = meta_output_get_instance_private (output); - - return priv->id; -} - -MetaGpu * -meta_output_get_gpu (MetaOutput *output) -{ - MetaOutputPrivate *priv = meta_output_get_instance_private (output); - - return priv->gpu; -} - -MetaMonitor * -meta_output_get_monitor (MetaOutput *output) -{ - MetaOutputPrivate *priv = meta_output_get_instance_private (output); - - g_warn_if_fail (priv->monitor); - - return priv->monitor; -} - -void -meta_output_set_monitor (MetaOutput *output, - MetaMonitor *monitor) -{ - MetaOutputPrivate *priv = meta_output_get_instance_private (output); - - g_warn_if_fail (!priv->monitor); - - priv->monitor = monitor; -} - -void -meta_output_unset_monitor (MetaOutput *output) -{ - MetaOutputPrivate *priv = meta_output_get_instance_private (output); - - g_warn_if_fail (priv->monitor); - - priv->monitor = NULL; -} - -const char * -meta_output_get_name (MetaOutput *output) -{ - MetaOutputPrivate *priv = meta_output_get_instance_private (output); - - return priv->info->name; -} - -gboolean -meta_output_is_primary (MetaOutput *output) -{ - MetaOutputPrivate *priv = meta_output_get_instance_private (output); - - return priv->is_primary; -} - -gboolean -meta_output_is_presentation (MetaOutput *output) -{ - MetaOutputPrivate *priv = meta_output_get_instance_private (output); - - return priv->is_presentation; -} - -gboolean -meta_output_is_underscanning (MetaOutput *output) -{ - MetaOutputPrivate *priv = meta_output_get_instance_private (output); - - return priv->is_underscanning; -} - -void -meta_output_set_backlight (MetaOutput *output, - int backlight) -{ - MetaOutputPrivate *priv = meta_output_get_instance_private (output); - - priv->backlight = backlight; -} - -int -meta_output_get_backlight (MetaOutput *output) -{ - MetaOutputPrivate *priv = meta_output_get_instance_private (output); - - return priv->backlight; -} - -void -meta_output_add_possible_clone (MetaOutput *output, - MetaOutput *possible_clone) -{ - MetaOutputPrivate *priv = meta_output_get_instance_private (output); - MetaOutputInfo *output_info = priv->info; - - output_info->n_possible_clones++; - output_info->possible_clones = g_renew (MetaOutput *, - output_info->possible_clones, - output_info->n_possible_clones); - output_info->possible_clones[output_info->n_possible_clones - 1] = - possible_clone; -} - -const MetaOutputInfo * -meta_output_get_info (MetaOutput *output) -{ - MetaOutputPrivate *priv = meta_output_get_instance_private (output); - - return priv->info; -} - -void -meta_output_assign_crtc (MetaOutput *output, - MetaCrtc *crtc, - const MetaOutputAssignment *output_assignment) -{ - MetaOutputPrivate *priv = meta_output_get_instance_private (output); - - g_assert (crtc); - - meta_output_unassign_crtc (output); - - g_set_object (&priv->crtc, crtc); - - meta_crtc_assign_output (crtc, output); - - priv->is_primary = output_assignment->is_primary; - priv->is_presentation = output_assignment->is_presentation; - priv->is_underscanning = output_assignment->is_underscanning; -} - -void -meta_output_unassign_crtc (MetaOutput *output) -{ - MetaOutputPrivate *priv = meta_output_get_instance_private (output); - - if (priv->crtc) - { - meta_crtc_unassign_output (priv->crtc, output); - g_clear_object (&priv->crtc); - } - - priv->is_primary = FALSE; - priv->is_presentation = FALSE; -} - -MetaCrtc * -meta_output_get_assigned_crtc (MetaOutput *output) -{ - MetaOutputPrivate *priv = meta_output_get_instance_private (output); - - return priv->crtc; -} - -MetaMonitorTransform -meta_output_logical_to_crtc_transform (MetaOutput *output, - MetaMonitorTransform transform) -{ - MetaOutputPrivate *priv = meta_output_get_instance_private (output); - MetaMonitorTransform panel_orientation_transform; - - panel_orientation_transform = priv->info->panel_orientation_transform; - return meta_monitor_transform_transform (transform, - panel_orientation_transform); -} - -MetaMonitorTransform -meta_output_crtc_to_logical_transform (MetaOutput *output, - MetaMonitorTransform transform) -{ - MetaOutputPrivate *priv = meta_output_get_instance_private (output); - MetaMonitorTransform inverted_panel_orientation_transform; - - inverted_panel_orientation_transform = - meta_monitor_transform_invert (priv->info->panel_orientation_transform); - return meta_monitor_transform_transform (transform, - inverted_panel_orientation_transform); -} - -void -meta_output_info_parse_edid (MetaOutputInfo *output_info, - GBytes *edid) -{ - MonitorInfo *parsed_edid; - size_t len; - - if (!edid) - goto out; - - parsed_edid = decode_edid (g_bytes_get_data (edid, &len)); - - if (parsed_edid) - { - output_info->vendor = g_strndup (parsed_edid->manufacturer_code, 4); - if (!g_utf8_validate (output_info->vendor, -1, NULL)) - g_clear_pointer (&output_info->vendor, g_free); - - output_info->product = g_strndup (parsed_edid->dsc_product_name, 14); - if (!g_utf8_validate (output_info->product, -1, NULL) || - output_info->product[0] == '\0') - { - g_clear_pointer (&output_info->product, g_free); - output_info->product = g_strdup_printf ("0x%04x", (unsigned) parsed_edid->product_code); - } - - output_info->serial = g_strndup (parsed_edid->dsc_serial_number, 14); - if (!g_utf8_validate (output_info->serial, -1, NULL) || - output_info->serial[0] == '\0') - { - g_clear_pointer (&output_info->serial, g_free); - output_info->serial = g_strdup_printf ("0x%08x", parsed_edid->serial_number); - } - - g_free (parsed_edid); - } - - out: - if (!output_info->vendor) - output_info->vendor = g_strdup ("unknown"); - if (!output_info->product) - output_info->product = g_strdup ("unknown"); - if (!output_info->serial) - output_info->serial = g_strdup ("unknown"); -} - -gboolean -meta_output_is_laptop (MetaOutput *output) -{ - const MetaOutputInfo *output_info = meta_output_get_info (output); - - switch (output_info->connector_type) - { - case META_CONNECTOR_TYPE_eDP: - case META_CONNECTOR_TYPE_LVDS: - case META_CONNECTOR_TYPE_DSI: - return TRUE; - default: - return FALSE; - } -} - -static void -meta_output_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaOutput *output = META_OUTPUT (object); - MetaOutputPrivate *priv = meta_output_get_instance_private (output); - - switch (prop_id) - { - case PROP_ID: - priv->id = g_value_get_uint64 (value); - break; - case PROP_GPU: - priv->gpu = g_value_get_object (value); - break; - case PROP_INFO: - priv->info = meta_output_info_ref (g_value_get_boxed (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_output_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaOutput *output = META_OUTPUT (object); - MetaOutputPrivate *priv = meta_output_get_instance_private (output); - - switch (prop_id) - { - case PROP_ID: - g_value_set_uint64 (value, priv->id); - break; - case PROP_GPU: - g_value_set_object (value, priv->gpu); - break; - case PROP_INFO: - g_value_set_boxed (value, priv->info); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_output_dispose (GObject *object) -{ - MetaOutput *output = META_OUTPUT (object); - MetaOutputPrivate *priv = meta_output_get_instance_private (output); - - g_clear_object (&priv->crtc); - - G_OBJECT_CLASS (meta_output_parent_class)->dispose (object); -} - -static void -meta_output_finalize (GObject *object) -{ - MetaOutput *output = META_OUTPUT (object); - MetaOutputPrivate *priv = meta_output_get_instance_private (output); - - g_clear_pointer (&priv->info, meta_output_info_unref); - - G_OBJECT_CLASS (meta_output_parent_class)->finalize (object); -} - -static void -meta_output_init (MetaOutput *output) -{ - MetaOutputPrivate *priv = meta_output_get_instance_private (output); - - priv->backlight = -1; -} - -static void -meta_output_class_init (MetaOutputClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->set_property = meta_output_set_property; - object_class->get_property = meta_output_get_property; - object_class->dispose = meta_output_dispose; - object_class->finalize = meta_output_finalize; - - obj_props[PROP_ID] = - g_param_spec_uint64 ("id", - "id", - "CRTC id", - 0, UINT64_MAX, 0, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - obj_props[PROP_GPU] = - g_param_spec_object ("gpu", - "gpu", - "MetaGpu", - META_TYPE_GPU, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - obj_props[PROP_INFO] = - g_param_spec_boxed ("info", - "info", - "MetaOutputInfo", - META_TYPE_OUTPUT_INFO, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, N_PROPS, obj_props); -} diff --git a/src/backends/meta-output.h b/src/backends/meta-output.h deleted file mode 100644 index b96c118d8..000000000 --- a/src/backends/meta-output.h +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (C) 2017 Red Hat - * Copyright (C) 2020 NVIDIA CORPORATION - * - * 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_OUTPUT_H -#define META_OUTPUT_H - -#include - -#include "backends/meta-backend-types.h" -#include "backends/meta-gpu.h" -#include "core/util-private.h" - -struct _MetaTileInfo -{ - uint32_t group_id; - uint32_t flags; - uint32_t max_h_tiles; - uint32_t max_v_tiles; - uint32_t loc_h_tile; - uint32_t loc_v_tile; - uint32_t tile_w; - uint32_t tile_h; -}; - -/* The first 17 matches the values in drm_mode.h, the ones starting with - * 1000 do not. */ -typedef enum -{ - META_CONNECTOR_TYPE_Unknown = 0, - META_CONNECTOR_TYPE_VGA = 1, - META_CONNECTOR_TYPE_DVII = 2, - META_CONNECTOR_TYPE_DVID = 3, - META_CONNECTOR_TYPE_DVIA = 4, - META_CONNECTOR_TYPE_Composite = 5, - META_CONNECTOR_TYPE_SVIDEO = 6, - META_CONNECTOR_TYPE_LVDS = 7, - META_CONNECTOR_TYPE_Component = 8, - META_CONNECTOR_TYPE_9PinDIN = 9, - META_CONNECTOR_TYPE_DisplayPort = 10, - META_CONNECTOR_TYPE_HDMIA = 11, - META_CONNECTOR_TYPE_HDMIB = 12, - META_CONNECTOR_TYPE_TV = 13, - META_CONNECTOR_TYPE_eDP = 14, - META_CONNECTOR_TYPE_VIRTUAL = 15, - META_CONNECTOR_TYPE_DSI = 16, - - META_CONNECTOR_TYPE_META = 1000, -} MetaConnectorType; - -typedef struct _MetaOutputInfo -{ - grefcount ref_count; - - char *name; - char *vendor; - char *product; - char *serial; - int width_mm; - int height_mm; - CoglSubpixelOrder subpixel_order; - - MetaConnectorType connector_type; - MetaMonitorTransform panel_orientation_transform; - - MetaCrtcMode *preferred_mode; - MetaCrtcMode **modes; - unsigned int n_modes; - - MetaCrtc **possible_crtcs; - unsigned int n_possible_crtcs; - - MetaOutput **possible_clones; - unsigned int n_possible_clones; - - int backlight_min; - int backlight_max; - - gboolean supports_underscanning; - gboolean supports_color_transform; - - /* - * Get a new preferred mode on hotplug events, to handle dynamic guest - * resizing. - */ - gboolean hotplug_mode_update; - int suggested_x; - int suggested_y; - - MetaTileInfo tile_info; -} MetaOutputInfo; - -#define META_TYPE_OUTPUT_INFO (meta_output_info_get_type ()) -META_EXPORT_TEST -GType meta_output_info_get_type (void); - -META_EXPORT_TEST -MetaOutputInfo * meta_output_info_new (void); - -META_EXPORT_TEST -MetaOutputInfo * meta_output_info_ref (MetaOutputInfo *output_info); - -META_EXPORT_TEST -void meta_output_info_unref (MetaOutputInfo *output_info); - -META_EXPORT_TEST -void meta_output_info_parse_edid (MetaOutputInfo *output_info, - GBytes *edid); - -gboolean meta_output_is_laptop (MetaOutput *output); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaOutputInfo, meta_output_info_unref) - -#define META_TYPE_OUTPUT (meta_output_get_type ()) -META_EXPORT_TEST -G_DECLARE_DERIVABLE_TYPE (MetaOutput, meta_output, META, OUTPUT, GObject) - -struct _MetaOutputClass -{ - GObjectClass parent_class; -}; - -META_EXPORT_TEST -uint64_t meta_output_get_id (MetaOutput *output); - -META_EXPORT_TEST -MetaGpu * meta_output_get_gpu (MetaOutput *output); - -META_EXPORT_TEST -MetaMonitor * meta_output_get_monitor (MetaOutput *output); - -void meta_output_set_monitor (MetaOutput *output, - MetaMonitor *monitor); - -void meta_output_unset_monitor (MetaOutput *output); - -const char * meta_output_get_name (MetaOutput *output); - -META_EXPORT_TEST -gboolean meta_output_is_primary (MetaOutput *output); - -META_EXPORT_TEST -gboolean meta_output_is_presentation (MetaOutput *output); - -META_EXPORT_TEST -gboolean meta_output_is_underscanning (MetaOutput *output); - -void meta_output_set_backlight (MetaOutput *output, - int backlight); - -int meta_output_get_backlight (MetaOutput *output); - -void meta_output_add_possible_clone (MetaOutput *output, - MetaOutput *possible_clone); - -META_EXPORT_TEST -const MetaOutputInfo * meta_output_get_info (MetaOutput *output); - -META_EXPORT_TEST -void meta_output_assign_crtc (MetaOutput *output, - MetaCrtc *crtc, - const MetaOutputAssignment *output_assignment); - -META_EXPORT_TEST -void meta_output_unassign_crtc (MetaOutput *output); - -META_EXPORT_TEST -MetaCrtc * meta_output_get_assigned_crtc (MetaOutput *output); - -MetaMonitorTransform meta_output_logical_to_crtc_transform (MetaOutput *output, - MetaMonitorTransform transform); - -MetaMonitorTransform meta_output_crtc_to_logical_transform (MetaOutput *output, - MetaMonitorTransform transform); - -#endif /* META_OUTPUT_H */ diff --git a/src/backends/meta-pointer-constraint.c b/src/backends/meta-pointer-constraint.c deleted file mode 100644 index 7682b14b0..000000000 --- a/src/backends/meta-pointer-constraint.c +++ /dev/null @@ -1,146 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -/** - * SECTION:meta-pointer-constraint - * @title: MetaPointerConstraint - * @short_description: Pointer client constraints. - * - * A MetaPointerConstraint can be used to implement any kind of pointer - * constraint as requested by a client, such as cursor lock. - * - * Examples of pointer constraints are "pointer confinement" and "pointer - * locking" (as defined in the wayland pointer constraint protocol extension), - * which restrict movement in relation to a given client. - */ - -#include "config.h" - -#include "backends/meta-pointer-constraint.h" - -#ifdef HAVE_NATIVE_BACKEND -#include "backends/native/meta-backend-native.h" -#include "backends/native/meta-pointer-constraint-native.h" -#endif - -#include - -struct _MetaPointerConstraint -{ - GObject parent_instance; - cairo_region_t *region; -}; - -G_DEFINE_TYPE (MetaPointerConstraint, meta_pointer_constraint, G_TYPE_OBJECT); - -G_DEFINE_TYPE (MetaPointerConstraintImpl, meta_pointer_constraint_impl, - G_TYPE_OBJECT); - -static void -meta_pointer_constraint_finalize (GObject *object) -{ - MetaPointerConstraint *constraint = META_POINTER_CONSTRAINT (object); - - g_clear_pointer (&constraint->region, cairo_region_destroy); - - G_OBJECT_CLASS (meta_pointer_constraint_parent_class)->finalize (object); -} - -static void -meta_pointer_constraint_init (MetaPointerConstraint *constraint) -{ -} - -static void -meta_pointer_constraint_class_init (MetaPointerConstraintClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_pointer_constraint_finalize; -} - - -MetaPointerConstraint * -meta_pointer_constraint_new (const cairo_region_t *region) -{ - MetaPointerConstraint *constraint; - - constraint = g_object_new (META_TYPE_POINTER_CONSTRAINT, NULL); - constraint->region = cairo_region_copy (region); - - return constraint; -} - -cairo_region_t * -meta_pointer_constraint_get_region (MetaPointerConstraint *constraint) -{ - return constraint->region; -} - -static void -meta_pointer_constraint_impl_init (MetaPointerConstraintImpl *constraint_impl) -{ -} - -static void -meta_pointer_constraint_impl_class_init (MetaPointerConstraintImplClass *klass) -{ -} - -/** - * meta_pointer_constraint_impl_constrain: - * @constraint_impl: a #MetaPointerConstraintImpl. - * @device; the device of the pointer. - * @time: the timestamp (in ms) of the event. - * @prev_x: X-coordinate of the previous pointer position. - * @prev_y: Y-coordinate of the previous pointer position. - * @x: The modifiable X-coordinate to which the pointer would like to go to. - * @y: The modifiable Y-coordinate to which the pointer would like to go to. - * - * Constrains the pointer movement from point (@prev_x, @prev_y) to (@x, @y), - * if needed. - */ -void -meta_pointer_constraint_impl_constrain (MetaPointerConstraintImpl *constraint_impl, - ClutterInputDevice *device, - uint32_t time, - float prev_x, - float prev_y, - float *x, - float *y) -{ - META_POINTER_CONSTRAINT_IMPL_GET_CLASS (constraint_impl)->constrain (constraint_impl, - device, - time, - prev_x, prev_y, - x, y); -} - -void -meta_pointer_constraint_impl_ensure_constrained (MetaPointerConstraintImpl *constraint_impl, - ClutterInputDevice *device) -{ - META_POINTER_CONSTRAINT_IMPL_GET_CLASS (constraint_impl)->ensure_constrained (constraint_impl, - device); -} diff --git a/src/backends/meta-pointer-constraint.h b/src/backends/meta-pointer-constraint.h deleted file mode 100644 index b47eda490..000000000 --- a/src/backends/meta-pointer-constraint.h +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#ifndef META_POINTER_CONSTRAINT_H -#define META_POINTER_CONSTRAINT_H - -#include - -#include "clutter/clutter.h" - -G_BEGIN_DECLS - -#define META_TYPE_POINTER_CONSTRAINT (meta_pointer_constraint_get_type ()) -G_DECLARE_FINAL_TYPE (MetaPointerConstraint, meta_pointer_constraint, - META, POINTER_CONSTRAINT, GObject); - -MetaPointerConstraint * meta_pointer_constraint_new (const cairo_region_t *region); -cairo_region_t * meta_pointer_constraint_get_region (MetaPointerConstraint *constraint); - -#define META_TYPE_POINTER_CONSTRAINT_IMPL (meta_pointer_constraint_impl_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaPointerConstraintImpl, meta_pointer_constraint_impl, - META, POINTER_CONSTRAINT_IMPL, GObject); - -/** - * MetaPointerConstraintImplClass: - * @constrain: the virtual function pointer for - * meta_pointer_constraint_impl_constrain(). - */ -struct _MetaPointerConstraintImplClass -{ - GObjectClass parent_class; - - void (* constrain) (MetaPointerConstraintImpl *constraint_impl, - ClutterInputDevice *device, - uint32_t time, - float prev_x, - float prev_y, - float *x, - float *y); - void (* ensure_constrained) (MetaPointerConstraintImpl *constraint_impl, - ClutterInputDevice *device); -}; - -void meta_pointer_constraint_impl_constrain (MetaPointerConstraintImpl *constraint_impl, - ClutterInputDevice *device, - uint32_t time, - float prev_x, - float prev_y, - float *x, - float *y); -void meta_pointer_constraint_impl_ensure_constrained (MetaPointerConstraintImpl *constraint_impl, - ClutterInputDevice *device); - -G_END_DECLS - -#endif /* META_POINTER_CONSTRAINT_H */ diff --git a/src/backends/meta-profiler.c b/src/backends/meta-profiler.c deleted file mode 100644 index 7a18b85ce..000000000 --- a/src/backends/meta-profiler.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * 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 -#include -#include - -#include "cogl/cogl.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, - GUnixFDList *fd_list, - GVariant *options, - GVariant *fd_variant) -{ - MetaProfiler *profiler = META_PROFILER (dbus_profiler); - GMainContext *main_context = g_main_context_default (); - 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); - - 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, NULL); - 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", 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", 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); -} diff --git a/src/backends/meta-profiler.h b/src/backends/meta-profiler.h deleted file mode 100644 index aa0d72640..000000000 --- a/src/backends/meta-profiler.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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 - -#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 */ diff --git a/src/backends/meta-remote-access-controller-private.h b/src/backends/meta-remote-access-controller-private.h deleted file mode 100644 index 8c8a319c4..000000000 --- a/src/backends/meta-remote-access-controller-private.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_REMOTE_ACCESS_CONTROLLER_PRIVATE_H -#define META_REMOTE_ACCESS_CONTROLLER_PRIVATE_H - -#include "backends/meta-backend-types.h" -#include "meta/meta-remote-access-controller.h" - -MetaRemoteAccessController * meta_remote_access_controller_new (MetaRemoteDesktop *remote_desktop, - MetaScreenCast *screen_cast); - -void meta_remote_access_controller_notify_new_handle (MetaRemoteAccessController *controller, - MetaRemoteAccessHandle *handle); - -void meta_remote_access_handle_notify_stopped (MetaRemoteAccessHandle *handle); - -void meta_remote_access_handle_set_disable_animations (MetaRemoteAccessHandle *handle, - gboolean disable_animations); - -#endif /* META_REMOTE_ACCESS_CONTROLLER_PRIVATE_H */ diff --git a/src/backends/meta-remote-access-controller.c b/src/backends/meta-remote-access-controller.c deleted file mode 100644 index b2ac93d88..000000000 --- a/src/backends/meta-remote-access-controller.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (C) 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "backends/meta-remote-access-controller-private.h" - -#ifdef HAVE_REMOTE_DESKTOP -#include "backends/meta-remote-desktop.h" -#include "backends/meta-screen-cast.h" -#endif - -enum -{ - HANDLE_STOPPED, - - N_HANDLE_SIGNALS -}; - -static int handle_signals[N_HANDLE_SIGNALS]; - -enum -{ - PROP_0, - - PROP_IS_RECORDING, - - N_PROPS -}; - -static GParamSpec *obj_props[N_PROPS]; - -enum -{ - CONTROLLER_NEW_HANDLE, - - N_CONTROLLER_SIGNALS -}; - -static int controller_signals[N_CONTROLLER_SIGNALS]; - -typedef struct _MetaRemoteAccessHandlePrivate -{ - gboolean has_stopped; - - gboolean disable_animations; - - gboolean is_recording; -} MetaRemoteAccessHandlePrivate; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaRemoteAccessHandle, - meta_remote_access_handle, - G_TYPE_OBJECT) - -struct _MetaRemoteAccessController -{ - GObject parent; - - MetaRemoteDesktop *remote_desktop; - MetaScreenCast *screen_cast; -}; - -G_DEFINE_TYPE (MetaRemoteAccessController, - meta_remote_access_controller, - G_TYPE_OBJECT) - -/** - * meta_remote_access_handle_stop: - * @handle: A #MetaRemoteAccessHandle - * - * Stop the associated remote access session. - */ -void -meta_remote_access_handle_stop (MetaRemoteAccessHandle *handle) -{ - MetaRemoteAccessHandlePrivate *priv = - meta_remote_access_handle_get_instance_private (handle); - - if (priv->has_stopped) - return; - - META_REMOTE_ACCESS_HANDLE_GET_CLASS (handle)->stop (handle); -} - -/** - * meta_remote_access_get_disable_animations: - * @handle: A #MetaRemoteAccessHandle - * - * Returns: %TRUE if the remote access requested that animations should be - * disabled. - */ -gboolean -meta_remote_access_handle_get_disable_animations (MetaRemoteAccessHandle *handle) -{ - MetaRemoteAccessHandlePrivate *priv = - meta_remote_access_handle_get_instance_private (handle); - - return priv->disable_animations; -} - -void -meta_remote_access_handle_set_disable_animations (MetaRemoteAccessHandle *handle, - gboolean disable_animations) -{ - MetaRemoteAccessHandlePrivate *priv = - meta_remote_access_handle_get_instance_private (handle); - - priv->disable_animations = disable_animations; -} - -void -meta_remote_access_handle_notify_stopped (MetaRemoteAccessHandle *handle) -{ - MetaRemoteAccessHandlePrivate *priv = - meta_remote_access_handle_get_instance_private (handle); - - priv->has_stopped = TRUE; - g_signal_emit (handle, handle_signals[HANDLE_STOPPED], 0); -} - -void -meta_remote_access_controller_notify_new_handle (MetaRemoteAccessController *controller, - MetaRemoteAccessHandle *handle) -{ - g_signal_emit (controller, controller_signals[CONTROLLER_NEW_HANDLE], 0, - handle); -} - -/** - * meta_remote_access_controller_inhibit_remote_access: - * @controller: a #MetaRemoteAccessController - * - * Inhibits remote access sessions from being created and running. Any active - * remote access session will be terminated. - */ -void -meta_remote_access_controller_inhibit_remote_access (MetaRemoteAccessController *controller) -{ -#ifdef HAVE_REMOTE_DESKTOP - meta_remote_desktop_inhibit (controller->remote_desktop); - meta_screen_cast_inhibit (controller->screen_cast); -#endif -} - -/** - * meta_remote_access_controller_uninhibit_remote_access: - * @controller: a #MetaRemoteAccessController - * - * Uninhibits remote access sessions from being created and running. If this was - * the last inhibitation that was inhibited, new remote access sessions can now - * be created. - */ -void -meta_remote_access_controller_uninhibit_remote_access (MetaRemoteAccessController *controller) -{ -#ifdef HAVE_REMOTE_DESKTOP - meta_screen_cast_uninhibit (controller->screen_cast); - meta_remote_desktop_uninhibit (controller->remote_desktop); -#endif -} - -MetaRemoteAccessController * -meta_remote_access_controller_new (MetaRemoteDesktop *remote_desktop, - MetaScreenCast *screen_cast) -{ - MetaRemoteAccessController *remote_access_controller; - - remote_access_controller = g_object_new (META_TYPE_REMOTE_ACCESS_CONTROLLER, - NULL); - remote_access_controller->remote_desktop = remote_desktop; - remote_access_controller->screen_cast = screen_cast; - - return remote_access_controller; -} - -static void -meta_remote_access_handle_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaRemoteAccessHandle *handle = META_REMOTE_ACCESS_HANDLE (object); - MetaRemoteAccessHandlePrivate *priv = - meta_remote_access_handle_get_instance_private (handle); - - switch (prop_id) - { - case PROP_IS_RECORDING: - g_value_set_boolean (value, priv->is_recording); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_remote_access_handle_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaRemoteAccessHandle *handle = META_REMOTE_ACCESS_HANDLE (object); - MetaRemoteAccessHandlePrivate *priv = - meta_remote_access_handle_get_instance_private (handle); - - switch (prop_id) - { - case PROP_IS_RECORDING: - priv->is_recording = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_remote_access_handle_init (MetaRemoteAccessHandle *handle) -{ -} - -static void -meta_remote_access_handle_class_init (MetaRemoteAccessHandleClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->get_property = meta_remote_access_handle_get_property; - object_class->set_property = meta_remote_access_handle_set_property; - - handle_signals[HANDLE_STOPPED] = - g_signal_new ("stopped", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - obj_props[PROP_IS_RECORDING] = - g_param_spec_boolean ("is-recording", - "is-recording", - "Is a screen recording", - FALSE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, N_PROPS, obj_props); -} - -static void -meta_remote_access_controller_init (MetaRemoteAccessController *controller) -{ -} - -static void -meta_remote_access_controller_class_init (MetaRemoteAccessControllerClass *klass) -{ - controller_signals[CONTROLLER_NEW_HANDLE] = - g_signal_new ("new-handle", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 1, - META_TYPE_REMOTE_ACCESS_HANDLE); -} diff --git a/src/backends/meta-remote-desktop-session.c b/src/backends/meta-remote-desktop-session.c deleted file mode 100644 index e15bd63de..000000000 --- a/src/backends/meta-remote-desktop-session.c +++ /dev/null @@ -1,1725 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015-2017 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "backends/meta-remote-desktop-session.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "backends/meta-dbus-session-watcher.h" -#include "backends/meta-screen-cast-session.h" -#include "backends/meta-remote-access-controller-private.h" -#include "backends/x11/meta-backend-x11.h" -#include "cogl/cogl.h" -#include "core/display-private.h" -#include "core/meta-selection-private.h" -#include "core/meta-selection-source-remote.h" -#include "meta/meta-backend.h" - -#include "meta-dbus-remote-desktop.h" - -#define META_REMOTE_DESKTOP_SESSION_DBUS_PATH "/org/gnome/Mutter/RemoteDesktop/Session" - -#define TRANSFER_REQUEST_CLEANUP_TIMEOUT_MS (s2ms (15)) - -typedef enum _MetaRemoteDesktopNotifyAxisFlags -{ - META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_NONE = 0, - META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_FINISH = 1 << 0, - META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_SOURCE_WHEEL = 1 << 1, - META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_SOURCE_FINGER = 1 << 2, - META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_SOURCE_CONTINUOUS = 1 << 3, -} MetaRemoteDesktopNotifyAxisFlags; - -typedef struct _SelectionReadData -{ - MetaRemoteDesktopSession *session; - GOutputStream *stream; - GCancellable *cancellable; -} SelectionReadData; - -struct _MetaRemoteDesktopSession -{ - MetaDBusRemoteDesktopSessionSkeleton parent; - - MetaRemoteDesktop *remote_desktop; - - GDBusConnection *connection; - char *peer_name; - - char *session_id; - char *object_path; - - MetaScreenCastSession *screen_cast_session; - gulong screen_cast_session_closed_handler_id; - guint started : 1; - - ClutterVirtualInputDevice *virtual_pointer; - ClutterVirtualInputDevice *virtual_keyboard; - ClutterVirtualInputDevice *virtual_touchscreen; - - MetaRemoteDesktopSessionHandle *handle; - - gboolean is_clipboard_enabled; - gulong owner_changed_handler_id; - SelectionReadData *read_data; - unsigned int transfer_serial; - MetaSelectionSourceRemote *current_source; - GHashTable *transfer_requests; - guint transfer_request_timeout_id; -}; - -static void -meta_remote_desktop_session_init_iface (MetaDBusRemoteDesktopSessionIface *iface); - -static void -meta_dbus_session_init_iface (MetaDbusSessionInterface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaRemoteDesktopSession, - meta_remote_desktop_session, - META_DBUS_TYPE_REMOTE_DESKTOP_SESSION_SKELETON, - G_IMPLEMENT_INTERFACE (META_DBUS_TYPE_REMOTE_DESKTOP_SESSION, - meta_remote_desktop_session_init_iface) - G_IMPLEMENT_INTERFACE (META_TYPE_DBUS_SESSION, - meta_dbus_session_init_iface)) - -struct _MetaRemoteDesktopSessionHandle -{ - MetaRemoteAccessHandle parent; - - MetaRemoteDesktopSession *session; -}; - -G_DEFINE_TYPE (MetaRemoteDesktopSessionHandle, - meta_remote_desktop_session_handle, - META_TYPE_REMOTE_ACCESS_HANDLE) - -static MetaRemoteDesktopSessionHandle * -meta_remote_desktop_session_handle_new (MetaRemoteDesktopSession *session); - -static gboolean -meta_remote_desktop_session_is_running (MetaRemoteDesktopSession *session) -{ - return !!session->started; -} - -static void -init_remote_access_handle (MetaRemoteDesktopSession *session) -{ - MetaBackend *backend = meta_get_backend (); - MetaRemoteAccessController *remote_access_controller; - MetaRemoteAccessHandle *remote_access_handle; - - session->handle = meta_remote_desktop_session_handle_new (session); - - remote_access_controller = meta_backend_get_remote_access_controller (backend); - remote_access_handle = META_REMOTE_ACCESS_HANDLE (session->handle); - meta_remote_access_controller_notify_new_handle (remote_access_controller, - remote_access_handle); -} - -static void -ensure_virtual_device (MetaRemoteDesktopSession *session, - ClutterInputDeviceType device_type) -{ - MetaRemoteDesktop *remote_desktop = session->remote_desktop; - MetaBackend *backend = meta_remote_desktop_get_backend (remote_desktop); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - ClutterSeat *seat = clutter_backend_get_default_seat (clutter_backend); - ClutterVirtualInputDevice **virtual_device_ptr = NULL; - - switch (device_type) - { - case CLUTTER_POINTER_DEVICE: - virtual_device_ptr = &session->virtual_pointer; - break; - case CLUTTER_KEYBOARD_DEVICE: - virtual_device_ptr = &session->virtual_keyboard; - break; - case CLUTTER_TOUCHSCREEN_DEVICE: - virtual_device_ptr = &session->virtual_touchscreen; - break; - default: - g_assert_not_reached (); - } - - g_assert (virtual_device_ptr); - - if (*virtual_device_ptr) - return; - - *virtual_device_ptr = clutter_seat_create_virtual_device (seat, device_type); -} - -static gboolean -meta_remote_desktop_session_start (MetaRemoteDesktopSession *session, - GError **error) -{ - g_assert (!session->started); - - if (session->screen_cast_session) - { - if (!meta_screen_cast_session_start (session->screen_cast_session, error)) - return FALSE; - } - - init_remote_access_handle (session); - session->started = TRUE; - - return TRUE; -} - -void -meta_remote_desktop_session_close (MetaRemoteDesktopSession *session) -{ - MetaDBusRemoteDesktopSession *skeleton = - META_DBUS_REMOTE_DESKTOP_SESSION (session); - - session->started = FALSE; - - if (session->screen_cast_session) - { - g_clear_signal_handler (&session->screen_cast_session_closed_handler_id, - session->screen_cast_session); - meta_screen_cast_session_close (session->screen_cast_session); - session->screen_cast_session = NULL; - } - - g_clear_object (&session->virtual_pointer); - g_clear_object (&session->virtual_keyboard); - g_clear_object (&session->virtual_touchscreen); - - meta_dbus_session_notify_closed (META_DBUS_SESSION (session)); - meta_dbus_remote_desktop_session_emit_closed (skeleton); - g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (session)); - - if (session->handle) - { - MetaRemoteAccessHandle *remote_access_handle = - META_REMOTE_ACCESS_HANDLE (session->handle); - - meta_remote_access_handle_notify_stopped (remote_access_handle); - } - - g_object_unref (session); -} - -char * -meta_remote_desktop_session_get_object_path (MetaRemoteDesktopSession *session) -{ - return session->object_path; -} - -char * -meta_remote_desktop_session_get_session_id (MetaRemoteDesktopSession *session) -{ - return session->session_id; -} - -static void -on_screen_cast_session_closed (MetaScreenCastSession *screen_cast_session, - MetaRemoteDesktopSession *session) -{ - session->screen_cast_session = NULL; - meta_remote_desktop_session_close (session); -} - -gboolean -meta_remote_desktop_session_register_screen_cast (MetaRemoteDesktopSession *session, - MetaScreenCastSession *screen_cast_session, - GError **error) -{ - if (session->screen_cast_session) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Remote desktop session already have an associated " - "screen cast session"); - return FALSE; - } - - session->screen_cast_session = screen_cast_session; - session->screen_cast_session_closed_handler_id = - g_signal_connect (screen_cast_session, "session-closed", - G_CALLBACK (on_screen_cast_session_closed), - session); - - return TRUE; -} - -MetaRemoteDesktopSession * -meta_remote_desktop_session_new (MetaRemoteDesktop *remote_desktop, - const char *peer_name, - GError **error) -{ - MetaBackend *backend = meta_remote_desktop_get_backend (remote_desktop); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - ClutterSeat *seat = clutter_backend_get_default_seat (clutter_backend); - ClutterKeymap *keymap = clutter_seat_get_keymap (seat); - GDBusInterfaceSkeleton *interface_skeleton; - MetaRemoteDesktopSession *session; - - session = g_object_new (META_TYPE_REMOTE_DESKTOP_SESSION, NULL); - - session->remote_desktop = remote_desktop; - session->peer_name = g_strdup (peer_name); - - interface_skeleton = G_DBUS_INTERFACE_SKELETON (session); - session->connection = meta_remote_desktop_get_connection (remote_desktop); - if (!g_dbus_interface_skeleton_export (interface_skeleton, - session->connection, - session->object_path, - error)) - { - g_object_unref (session); - return NULL; - } - - g_object_bind_property (keymap, "caps-lock-state", - session, "caps-lock-state", - G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE); - g_object_bind_property (keymap, "num-lock-state", - session, "num-lock-state", - G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE); - - return session; -} - -static gboolean -check_permission (MetaRemoteDesktopSession *session, - GDBusMethodInvocation *invocation) -{ - return g_strcmp0 (session->peer_name, - g_dbus_method_invocation_get_sender (invocation)) == 0; -} - -static gboolean -meta_remote_desktop_session_check_can_notify (MetaRemoteDesktopSession *session, - GDBusMethodInvocation *invocation) -{ - if (!session->started) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Session not started"); - return FALSE; - } - - if (!check_permission (session, invocation)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Permission denied"); - return FALSE; - } - - return TRUE; -} - -static gboolean -handle_start (MetaDBusRemoteDesktopSession *skeleton, - GDBusMethodInvocation *invocation) -{ - MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton); - GError *error = NULL; - - if (session->started) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Already started"); - return TRUE; - } - - if (!check_permission (session, invocation)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Permission denied"); - return TRUE; - } - - if (!meta_remote_desktop_session_start (session, &error)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Failed to start remote desktop: %s", - error->message); - g_error_free (error); - - meta_remote_desktop_session_close (session); - - return TRUE; - } - - meta_dbus_remote_desktop_session_complete_start (skeleton, invocation); - - return TRUE; -} - -static gboolean -handle_stop (MetaDBusRemoteDesktopSession *skeleton, - GDBusMethodInvocation *invocation) -{ - MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton); - - if (!session->started) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Session not started"); - return TRUE; - } - - if (!check_permission (session, invocation)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Permission denied"); - return TRUE; - } - - meta_remote_desktop_session_close (session); - - meta_dbus_remote_desktop_session_complete_stop (skeleton, invocation); - - return TRUE; -} - -static gboolean -handle_notify_keyboard_keycode (MetaDBusRemoteDesktopSession *skeleton, - GDBusMethodInvocation *invocation, - unsigned int keycode, - gboolean pressed) -{ - MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton); - ClutterKeyState state; - - if (!meta_remote_desktop_session_check_can_notify (session, invocation)) - return TRUE; - - if (pressed) - { - ensure_virtual_device (session, CLUTTER_KEYBOARD_DEVICE); - state = CLUTTER_KEY_STATE_PRESSED; - } - else - { - if (!session->virtual_keyboard) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Invalid key event"); - return TRUE; - } - - state = CLUTTER_KEY_STATE_RELEASED; - } - - clutter_virtual_input_device_notify_key (session->virtual_keyboard, - CLUTTER_CURRENT_TIME, - keycode, - state); - - meta_dbus_remote_desktop_session_complete_notify_keyboard_keycode (skeleton, - invocation); - return TRUE; -} - -static gboolean -handle_notify_keyboard_keysym (MetaDBusRemoteDesktopSession *skeleton, - GDBusMethodInvocation *invocation, - unsigned int keysym, - gboolean pressed) -{ - MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton); - ClutterKeyState state; - - if (!meta_remote_desktop_session_check_can_notify (session, invocation)) - return TRUE; - - if (pressed) - { - ensure_virtual_device (session, CLUTTER_KEYBOARD_DEVICE); - state = CLUTTER_KEY_STATE_PRESSED; - } - else - { - if (!session->virtual_keyboard) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Invalid key event"); - return TRUE; - } - - state = CLUTTER_KEY_STATE_RELEASED; - } - - clutter_virtual_input_device_notify_keyval (session->virtual_keyboard, - CLUTTER_CURRENT_TIME, - keysym, - state); - - meta_dbus_remote_desktop_session_complete_notify_keyboard_keysym (skeleton, - invocation); - return TRUE; -} - -/* Translation taken from the clutter evdev backend. */ -static int -translate_to_clutter_button (int button) -{ - switch (button) - { - case BTN_LEFT: - return CLUTTER_BUTTON_PRIMARY; - case BTN_RIGHT: - return CLUTTER_BUTTON_SECONDARY; - case BTN_MIDDLE: - return CLUTTER_BUTTON_MIDDLE; - default: - /* - * For compatibility reasons, all additional buttons go after the old - * 4-7 scroll ones. - */ - return button - (BTN_LEFT - 1) + 4; - } -} - -static gboolean -handle_notify_pointer_button (MetaDBusRemoteDesktopSession *skeleton, - GDBusMethodInvocation *invocation, - int button_code, - gboolean pressed) -{ - MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton); - uint32_t button; - ClutterButtonState state; - - if (!meta_remote_desktop_session_check_can_notify (session, invocation)) - return TRUE; - - button = translate_to_clutter_button (button_code); - - if (pressed) - { - ensure_virtual_device (session, CLUTTER_POINTER_DEVICE); - state = CLUTTER_BUTTON_STATE_PRESSED; - } - else - { - if (!session->virtual_pointer) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Invalid button event"); - return TRUE; - } - - state = CLUTTER_BUTTON_STATE_RELEASED; - } - - clutter_virtual_input_device_notify_button (session->virtual_pointer, - CLUTTER_CURRENT_TIME, - button, - state); - - meta_dbus_remote_desktop_session_complete_notify_pointer_button (skeleton, - invocation); - - return TRUE; -} - -static gboolean -clutter_scroll_source_from_axis_flags (MetaRemoteDesktopNotifyAxisFlags axis_flags, - ClutterScrollSource *scroll_source) -{ - MetaRemoteDesktopNotifyAxisFlags scroll_mask; - - scroll_mask = META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_SOURCE_WHEEL | - META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_SOURCE_FINGER | - META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_SOURCE_CONTINUOUS; - - switch (axis_flags & scroll_mask) - { - case META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_SOURCE_WHEEL: - *scroll_source = CLUTTER_SCROLL_SOURCE_WHEEL; - return TRUE; - case META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_NONE: - case META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_SOURCE_FINGER: - *scroll_source = CLUTTER_SCROLL_SOURCE_FINGER; - return TRUE; - case META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_SOURCE_CONTINUOUS: - *scroll_source = CLUTTER_SCROLL_SOURCE_CONTINUOUS; - return TRUE; - } - - return FALSE; -} - -static gboolean -handle_notify_pointer_axis (MetaDBusRemoteDesktopSession *skeleton, - GDBusMethodInvocation *invocation, - double dx, - double dy, - uint32_t flags) -{ - MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton); - ClutterScrollFinishFlags finish_flags = CLUTTER_SCROLL_FINISHED_NONE; - ClutterScrollSource scroll_source; - - if (!meta_remote_desktop_session_check_can_notify (session, invocation)) - return TRUE; - - if (!clutter_scroll_source_from_axis_flags (flags, &scroll_source)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Invalid scroll source"); - return TRUE; - } - - if (flags & META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_FINISH) - { - finish_flags |= (CLUTTER_SCROLL_FINISHED_HORIZONTAL | - CLUTTER_SCROLL_FINISHED_VERTICAL); - } - - ensure_virtual_device (session, CLUTTER_POINTER_DEVICE); - - clutter_virtual_input_device_notify_scroll_continuous (session->virtual_pointer, - CLUTTER_CURRENT_TIME, - dx, dy, - scroll_source, - finish_flags); - - meta_dbus_remote_desktop_session_complete_notify_pointer_axis (skeleton, - invocation); - - return TRUE; -} - -static ClutterScrollDirection -discrete_steps_to_scroll_direction (unsigned int axis, - int steps) -{ - if (axis == 0 && steps < 0) - return CLUTTER_SCROLL_UP; - if (axis == 0 && steps > 0) - return CLUTTER_SCROLL_DOWN; - if (axis == 1 && steps < 0) - return CLUTTER_SCROLL_LEFT; - if (axis == 1 && steps > 0) - return CLUTTER_SCROLL_RIGHT; - - g_assert_not_reached (); - return 0; -} - -static gboolean -handle_notify_pointer_axis_discrete (MetaDBusRemoteDesktopSession *skeleton, - GDBusMethodInvocation *invocation, - unsigned int axis, - int steps) -{ - MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton); - ClutterScrollDirection direction; - int step_count; - - if (!meta_remote_desktop_session_check_can_notify (session, invocation)) - return TRUE; - - if (axis > 1) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Invalid axis value"); - return TRUE; - } - - if (steps == 0) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Invalid axis steps value"); - return TRUE; - } - - ensure_virtual_device (session, CLUTTER_POINTER_DEVICE); - - /* - * We don't have the actual scroll source, but only know they should be - * considered as discrete steps. The device that produces such scroll events - * is the scroll wheel, so pretend that is the scroll source. - */ - direction = discrete_steps_to_scroll_direction (axis, steps); - - for (step_count = 0; step_count < abs (steps); step_count++) - clutter_virtual_input_device_notify_discrete_scroll (session->virtual_pointer, - CLUTTER_CURRENT_TIME, - direction, - CLUTTER_SCROLL_SOURCE_WHEEL); - - meta_dbus_remote_desktop_session_complete_notify_pointer_axis_discrete (skeleton, - invocation); - - return TRUE; -} - -static gboolean -handle_notify_pointer_motion_relative (MetaDBusRemoteDesktopSession *skeleton, - GDBusMethodInvocation *invocation, - double dx, - double dy) -{ - MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton); - - if (!meta_remote_desktop_session_check_can_notify (session, invocation)) - return TRUE; - - ensure_virtual_device (session, CLUTTER_POINTER_DEVICE); - - clutter_virtual_input_device_notify_relative_motion (session->virtual_pointer, - CLUTTER_CURRENT_TIME, - dx, dy); - - meta_dbus_remote_desktop_session_complete_notify_pointer_motion_relative (skeleton, - invocation); - - return TRUE; -} - -static gboolean -handle_notify_pointer_motion_absolute (MetaDBusRemoteDesktopSession *skeleton, - GDBusMethodInvocation *invocation, - const char *stream_path, - double x, - double y) -{ - MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton); - MetaScreenCastStream *stream; - double abs_x, abs_y; - - if (!meta_remote_desktop_session_check_can_notify (session, invocation)) - return TRUE; - - - if (!session->screen_cast_session) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "No screen cast active"); - return TRUE; - } - - stream = meta_screen_cast_session_get_stream (session->screen_cast_session, - stream_path); - if (!stream) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Unknown stream"); - return TRUE; - } - - ensure_virtual_device (session, CLUTTER_POINTER_DEVICE); - - if (meta_screen_cast_stream_transform_position (stream, x, y, &abs_x, &abs_y)) - { - clutter_virtual_input_device_notify_absolute_motion (session->virtual_pointer, - CLUTTER_CURRENT_TIME, - abs_x, abs_y); - } - else - { - meta_topic (META_DEBUG_REMOTE_DESKTOP, - "Dropping early absolute pointer motion (%f, %f)", x, y); - } - - meta_dbus_remote_desktop_session_complete_notify_pointer_motion_absolute (skeleton, - invocation); - - return TRUE; -} - -static gboolean -handle_notify_touch_down (MetaDBusRemoteDesktopSession *skeleton, - GDBusMethodInvocation *invocation, - const char *stream_path, - unsigned int slot, - double x, - double y) -{ - MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton); - MetaScreenCastStream *stream; - double abs_x, abs_y; - - if (!meta_remote_desktop_session_check_can_notify (session, invocation)) - return TRUE; - - if (slot > CLUTTER_VIRTUAL_INPUT_DEVICE_MAX_TOUCH_SLOTS) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Touch slot out of range"); - return TRUE; - } - - if (!session->screen_cast_session) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "No screen cast active"); - return TRUE; - } - - stream = meta_screen_cast_session_get_stream (session->screen_cast_session, - stream_path); - if (!stream) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Unknown stream"); - return TRUE; - } - - ensure_virtual_device (session, CLUTTER_TOUCHSCREEN_DEVICE); - - if (meta_screen_cast_stream_transform_position (stream, x, y, &abs_x, &abs_y)) - { - clutter_virtual_input_device_notify_touch_down (session->virtual_touchscreen, - CLUTTER_CURRENT_TIME, - slot, - abs_x, abs_y); - } - else - { - meta_topic (META_DEBUG_REMOTE_DESKTOP, - "Dropping early touch down (%f, %f)", x, y); - } - - meta_dbus_remote_desktop_session_complete_notify_touch_down (skeleton, - invocation); - - return TRUE; -} - -static gboolean -handle_notify_touch_motion (MetaDBusRemoteDesktopSession *skeleton, - GDBusMethodInvocation *invocation, - const char *stream_path, - unsigned int slot, - double x, - double y) -{ - MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton); - MetaScreenCastStream *stream; - double abs_x, abs_y; - - if (!meta_remote_desktop_session_check_can_notify (session, invocation)) - return TRUE; - - - if (slot > CLUTTER_VIRTUAL_INPUT_DEVICE_MAX_TOUCH_SLOTS) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Touch slot out of range"); - return TRUE; - } - - if (!session->screen_cast_session) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "No screen cast active"); - return TRUE; - } - - stream = meta_screen_cast_session_get_stream (session->screen_cast_session, - stream_path); - if (!stream) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Unknown stream"); - return TRUE; - } - - if (!session->virtual_touchscreen) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Invalid touch point"); - return TRUE; - } - - if (meta_screen_cast_stream_transform_position (stream, x, y, &abs_x, &abs_y)) - { - clutter_virtual_input_device_notify_touch_motion (session->virtual_touchscreen, - CLUTTER_CURRENT_TIME, - slot, - abs_x, abs_y); - } - else - { - meta_topic (META_DEBUG_REMOTE_DESKTOP, - "Dropping early touch motion (%f, %f)", x, y); - } - - meta_dbus_remote_desktop_session_complete_notify_touch_motion (skeleton, - invocation); - - return TRUE; -} - -static gboolean -handle_notify_touch_up (MetaDBusRemoteDesktopSession *skeleton, - GDBusMethodInvocation *invocation, - unsigned int slot) -{ - MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton); - - if (!meta_remote_desktop_session_check_can_notify (session, invocation)) - return TRUE; - - if (slot > CLUTTER_VIRTUAL_INPUT_DEVICE_MAX_TOUCH_SLOTS) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Touch slot out of range"); - return TRUE; - } - - if (!session->virtual_touchscreen) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Invalid touch point"); - return TRUE; - } - - clutter_virtual_input_device_notify_touch_up (session->virtual_touchscreen, - CLUTTER_CURRENT_TIME, - slot); - - meta_dbus_remote_desktop_session_complete_notify_touch_up (skeleton, - invocation); - - return TRUE; -} - -static MetaSelectionSourceRemote * -create_remote_desktop_source (MetaRemoteDesktopSession *session, - GVariant *mime_types_variant, - GError **error) -{ - GVariantIter iter; - char *mime_type; - GList *mime_types = NULL; - - g_variant_iter_init (&iter, mime_types_variant); - if (g_variant_iter_n_children (&iter) == 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, - "No mime types in mime types list"); - return NULL; - } - - while (g_variant_iter_next (&iter, "s", &mime_type)) - mime_types = g_list_prepend (mime_types, mime_type); - - mime_types = g_list_reverse (mime_types); - - return meta_selection_source_remote_new (session, mime_types); -} - -static const char * -mime_types_to_string (char **formats, - char *buf, - int buf_len) -{ - g_autofree char *mime_types_string = NULL; - int len; - - if (!formats) - return "N\\A"; - - mime_types_string = g_strjoinv (",", formats); - len = strlen (mime_types_string); - strncpy (buf, mime_types_string, buf_len - 1); - if (len >= buf_len - 1) - buf[buf_len - 2] = '*'; - buf[buf_len - 1] = '\0'; - - return buf; -} - -static gboolean -is_own_source (MetaRemoteDesktopSession *session, - MetaSelectionSource *source) -{ - return source && source == META_SELECTION_SOURCE (session->current_source); -} - -static GVariant * -generate_owner_changed_variant (char **mime_types_array, - gboolean is_own_source) -{ - GVariantBuilder builder; - - g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); - if (mime_types_array) - { - g_variant_builder_add (&builder, "{sv}", "mime-types", - g_variant_new ("(^as)", mime_types_array)); - g_variant_builder_add (&builder, "{sv}", "session-is-owner", - g_variant_new_boolean (is_own_source)); - } - - return g_variant_builder_end (&builder); -} - -static void -emit_owner_changed (MetaRemoteDesktopSession *session, - MetaSelectionSource *owner) -{ - char log_buf[255]; - g_autofree char **mime_types_array = NULL; - GList *l; - int i; - GVariant *options_variant; - const char *object_path; - - if (owner) - { - GList *mime_types; - - mime_types = meta_selection_source_get_mimetypes (owner); - mime_types_array = g_new0 (char *, g_list_length (mime_types) + 1); - for (l = meta_selection_source_get_mimetypes (owner), i = 0; - l; - l = l->next, i++) - mime_types_array[i] = l->data; - } - - meta_topic (META_DEBUG_REMOTE_DESKTOP, - "Clipboard owner changed, owner: %p (%s, is own? %s), mime types: [%s], " - "notifying %s", - owner, - owner ? g_type_name_from_instance ((GTypeInstance *) owner) - : "NULL", - is_own_source (session, owner) ? "yes" : "no", - mime_types_to_string (mime_types_array, log_buf, - G_N_ELEMENTS (log_buf)), - session->peer_name); - - options_variant = - generate_owner_changed_variant (mime_types_array, - is_own_source (session, owner)); - - object_path = g_dbus_interface_skeleton_get_object_path ( - G_DBUS_INTERFACE_SKELETON (session)); - g_dbus_connection_emit_signal (session->connection, - NULL, - object_path, - "org.gnome.Mutter.RemoteDesktop.Session", - "SelectionOwnerChanged", - g_variant_new ("(@a{sv})", options_variant), - NULL); -} - -static void -on_selection_owner_changed (MetaSelection *selection, - MetaSelectionType selection_type, - MetaSelectionSource *owner, - MetaRemoteDesktopSession *session) -{ - if (selection_type != META_SELECTION_CLIPBOARD) - return; - - emit_owner_changed (session, owner); -} - -static gboolean -handle_enable_clipboard (MetaDBusRemoteDesktopSession *skeleton, - GDBusMethodInvocation *invocation, - GVariant *arg_options) -{ - MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton); - GVariant *mime_types_variant; - g_autoptr (GError) error = NULL; - MetaDisplay *display = meta_get_display (); - MetaSelection *selection = meta_display_get_selection (display); - g_autoptr (MetaSelectionSourceRemote) source_remote = NULL; - - meta_topic (META_DEBUG_REMOTE_DESKTOP, - "Enable clipboard for %s", - g_dbus_method_invocation_get_sender (invocation)); - - if (session->is_clipboard_enabled) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Already enabled"); - return TRUE; - } - - mime_types_variant = g_variant_lookup_value (arg_options, - "mime-types", - G_VARIANT_TYPE_STRING_ARRAY); - if (mime_types_variant) - { - source_remote = create_remote_desktop_source (session, - mime_types_variant, - &error); - if (!source_remote) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Invalid mime type list: %s", - error->message); - return TRUE; - } - } - - if (source_remote) - { - meta_topic (META_DEBUG_REMOTE_DESKTOP, - "Setting remote desktop clipboard source: %p from %s", - source_remote, session->peer_name); - - g_set_object (&session->current_source, source_remote); - meta_selection_set_owner (selection, - META_SELECTION_CLIPBOARD, - META_SELECTION_SOURCE (source_remote)); - } - else - { - MetaSelectionSource *owner; - - owner = meta_selection_get_current_owner (selection, - META_SELECTION_CLIPBOARD); - - if (owner) - emit_owner_changed (session, owner); - } - - session->is_clipboard_enabled = TRUE; - session->owner_changed_handler_id = - g_signal_connect (selection, "owner-changed", - G_CALLBACK (on_selection_owner_changed), - session); - - meta_dbus_remote_desktop_session_complete_enable_clipboard (skeleton, - invocation); - - return TRUE; -} - -static gboolean -cancel_transfer_request (gpointer key, - gpointer value, - gpointer user_data) -{ - GTask *task = G_TASK (value); - MetaRemoteDesktopSession *session = user_data; - - meta_selection_source_remote_cancel_transfer (session->current_source, - task); - - return TRUE; -} - -static void -meta_remote_desktop_session_cancel_transfer_requests (MetaRemoteDesktopSession *session) -{ - g_return_if_fail (session->current_source); - - g_hash_table_foreach_remove (session->transfer_requests, - cancel_transfer_request, - session); -} - -static gboolean -transfer_request_cleanup_timout (gpointer user_data) -{ - MetaRemoteDesktopSession *session = user_data; - - meta_topic (META_DEBUG_REMOTE_DESKTOP, - "Cancel unanswered SelectionTransfer requests for %s, " - "waited for %.02f seconds already", - session->peer_name, - TRANSFER_REQUEST_CLEANUP_TIMEOUT_MS / 1000.0); - - meta_remote_desktop_session_cancel_transfer_requests (session); - - session->transfer_request_timeout_id = 0; - return G_SOURCE_REMOVE; -} - -static void -reset_current_selection_source (MetaRemoteDesktopSession *session) -{ - MetaDisplay *display = meta_get_display (); - MetaSelection *selection = meta_display_get_selection (display); - - if (!session->current_source) - return; - - meta_selection_unset_owner (selection, - META_SELECTION_CLIPBOARD, - META_SELECTION_SOURCE (session->current_source)); - meta_remote_desktop_session_cancel_transfer_requests (session); - g_clear_handle_id (&session->transfer_request_timeout_id, g_source_remove); - g_clear_object (&session->current_source); -} - -static void -cancel_selection_read (MetaRemoteDesktopSession *session) -{ - if (!session->read_data) - return; - - g_cancellable_cancel (session->read_data->cancellable); - session->read_data->session = NULL; - session->read_data = NULL; -} - -static gboolean -handle_disable_clipboard (MetaDBusRemoteDesktopSession *skeleton, - GDBusMethodInvocation *invocation) -{ - MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton); - MetaDisplay *display = meta_get_display (); - MetaSelection *selection = meta_display_get_selection (display); - - meta_topic (META_DEBUG_REMOTE_DESKTOP, - "Disable clipboard for %s", - g_dbus_method_invocation_get_sender (invocation)); - - if (!session->is_clipboard_enabled) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Was not enabled"); - return TRUE; - } - - g_clear_signal_handler (&session->owner_changed_handler_id, selection); - reset_current_selection_source (session); - cancel_selection_read (session); - - meta_dbus_remote_desktop_session_complete_disable_clipboard (skeleton, - invocation); - - return TRUE; -} - -static gboolean -handle_set_selection (MetaDBusRemoteDesktopSession *skeleton, - GDBusMethodInvocation *invocation, - GVariant *arg_options) -{ - MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton); - g_autoptr (GVariant) mime_types_variant = NULL; - g_autoptr (GError) error = NULL; - - if (!session->is_clipboard_enabled) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Clipboard not enabled"); - return TRUE; - } - - if (session->current_source) - { - meta_remote_desktop_session_cancel_transfer_requests (session); - g_clear_handle_id (&session->transfer_request_timeout_id, - g_source_remove); - } - - mime_types_variant = g_variant_lookup_value (arg_options, - "mime-types", - G_VARIANT_TYPE_STRING_ARRAY); - if (mime_types_variant) - { - g_autoptr (MetaSelectionSourceRemote) source_remote = NULL; - MetaDisplay *display = meta_get_display (); - - source_remote = create_remote_desktop_source (session, - mime_types_variant, - &error); - if (!source_remote) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Invalid format list: %s", - error->message); - return TRUE; - } - - meta_topic (META_DEBUG_REMOTE_DESKTOP, - "Set selection for %s to %p", - g_dbus_method_invocation_get_sender (invocation), - source_remote); - - g_set_object (&session->current_source, source_remote); - meta_selection_set_owner (meta_display_get_selection (display), - META_SELECTION_CLIPBOARD, - META_SELECTION_SOURCE (source_remote)); - } - else - { - meta_topic (META_DEBUG_REMOTE_DESKTOP, - "Unset selection for %s", - g_dbus_method_invocation_get_sender (invocation)); - - reset_current_selection_source (session); - } - - meta_dbus_remote_desktop_session_complete_set_selection (skeleton, - invocation); - - return TRUE; -} - -static void -reset_transfer_cleanup_timeout (MetaRemoteDesktopSession *session) -{ - g_clear_handle_id (&session->transfer_request_timeout_id, g_source_remove); - session->transfer_request_timeout_id = - g_timeout_add (TRANSFER_REQUEST_CLEANUP_TIMEOUT_MS, - transfer_request_cleanup_timout, - session); -} - -void -meta_remote_desktop_session_request_transfer (MetaRemoteDesktopSession *session, - const char *mime_type, - GTask *task) -{ - const char *object_path; - - session->transfer_serial++; - - meta_topic (META_DEBUG_REMOTE_DESKTOP, - "Emit SelectionTransfer ('%s', %u) for %s", - mime_type, - session->transfer_serial, - session->peer_name); - - g_hash_table_insert (session->transfer_requests, - GUINT_TO_POINTER (session->transfer_serial), - task); - reset_transfer_cleanup_timeout (session); - - object_path = g_dbus_interface_skeleton_get_object_path ( - G_DBUS_INTERFACE_SKELETON (session)); - g_dbus_connection_emit_signal (session->connection, - NULL, - object_path, - "org.gnome.Mutter.RemoteDesktop.Session", - "SelectionTransfer", - g_variant_new ("(su)", - mime_type, - session->transfer_serial), - NULL); -} - -static gboolean -handle_selection_write (MetaDBusRemoteDesktopSession *skeleton, - GDBusMethodInvocation *invocation, - GUnixFDList *fd_list_in, - unsigned int serial) -{ - MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton); - g_autoptr (GError) error = NULL; - int pipe_fds[2]; - g_autoptr (GUnixFDList) fd_list = NULL; - int fd_idx; - GVariant *fd_variant; - GTask *task; - - meta_topic (META_DEBUG_REMOTE_DESKTOP, - "Write selection for %s", - g_dbus_method_invocation_get_sender (invocation)); - - if (!session->is_clipboard_enabled) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Clipboard not enabled"); - return TRUE; - } - - if (!session->current_source) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "No current selection owned"); - return TRUE; - } - - if (!g_hash_table_steal_extended (session->transfer_requests, - GUINT_TO_POINTER (serial), - NULL, - (gpointer *) &task)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Transfer serial %u doesn't match " - "any transfer request", - serial); - return TRUE; - } - - if (!g_unix_open_pipe (pipe_fds, FD_CLOEXEC, &error)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Failed open pipe: %s", - error->message); - return TRUE; - } - - if (!g_unix_set_fd_nonblocking (pipe_fds[0], TRUE, &error)) - { - close (pipe_fds[0]); - close (pipe_fds[1]); - - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Failed to make pipe non-blocking: %s", - error->message); - return TRUE; - } - - fd_list = g_unix_fd_list_new (); - - fd_idx = g_unix_fd_list_append (fd_list, pipe_fds[1], NULL); - close (pipe_fds[1]); - fd_variant = g_variant_new_handle (fd_idx); - - meta_selection_source_remote_complete_transfer (session->current_source, - pipe_fds[0], - task); - - meta_dbus_remote_desktop_session_complete_selection_write (skeleton, - invocation, - fd_list, - fd_variant); - - return TRUE; -} - -static gboolean -handle_selection_write_done (MetaDBusRemoteDesktopSession *skeleton, - GDBusMethodInvocation *invocation, - unsigned int arg_serial, - gboolean arg_success) -{ - MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton); - - meta_topic (META_DEBUG_REMOTE_DESKTOP, - "Write selection done for %s", - g_dbus_method_invocation_get_sender (invocation)); - - if (!session->is_clipboard_enabled) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Clipboard not enabled"); - return TRUE; - } - - meta_dbus_remote_desktop_session_complete_selection_write_done (skeleton, - invocation); - - return TRUE; -} - -static void -transfer_cb (MetaSelection *selection, - GAsyncResult *res, - SelectionReadData *read_data) -{ - g_autoptr (GError) error = NULL; - - if (!meta_selection_transfer_finish (selection, res, &error)) - { - g_warning ("Could not fetch selection data " - "for remote desktop session: %s", - error->message); - } - - if (read_data->session) - { - meta_topic (META_DEBUG_REMOTE_DESKTOP, "Finished selection transfer for %s", - read_data->session->peer_name); - } - - g_output_stream_close (read_data->stream, NULL, NULL); - g_clear_object (&read_data->stream); - g_clear_object (&read_data->cancellable); - - if (read_data->session) - read_data->session->read_data = NULL; - - g_free (read_data); -} - -static gboolean -handle_selection_read (MetaDBusRemoteDesktopSession *skeleton, - GDBusMethodInvocation *invocation, - GUnixFDList *fd_list_in, - const char *mime_type) -{ - MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton); - MetaDisplay *display = meta_get_display (); - MetaSelection *selection = meta_display_get_selection (display); - MetaSelectionSource *source; - g_autoptr (GError) error = NULL; - int pipe_fds[2]; - g_autoptr (GUnixFDList) fd_list = NULL; - int fd_idx; - GVariant *fd_variant; - SelectionReadData *read_data; - - meta_topic (META_DEBUG_REMOTE_DESKTOP, - "Read selection for %s", - g_dbus_method_invocation_get_sender (invocation)); - - if (!session->is_clipboard_enabled) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Clipboard not enabled"); - return TRUE; - } - - source = meta_selection_get_current_owner (selection, - META_SELECTION_CLIPBOARD); - if (!source) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FILE_NOT_FOUND, - "No selection owner available"); - return TRUE; - } - - if (is_own_source (session, source)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Tried to read own selection"); - return TRUE; - } - - if (session->read_data) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_LIMITS_EXCEEDED, - "Tried to read in parallel"); - return TRUE; - } - - if (!g_unix_open_pipe (pipe_fds, FD_CLOEXEC, &error)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Failed open pipe: %s", - error->message); - return TRUE; - } - - if (!g_unix_set_fd_nonblocking (pipe_fds[0], TRUE, &error)) - { - close (pipe_fds[0]); - close (pipe_fds[1]); - - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Failed to make pipe non-blocking: %s", - error->message); - return TRUE; - } - - fd_list = g_unix_fd_list_new (); - - fd_idx = g_unix_fd_list_append (fd_list, pipe_fds[0], NULL); - close (pipe_fds[0]); - fd_variant = g_variant_new_handle (fd_idx); - - session->read_data = read_data = g_new0 (SelectionReadData, 1); - read_data->session = session; - read_data->stream = g_unix_output_stream_new (pipe_fds[1], TRUE); - read_data->cancellable = g_cancellable_new (); - meta_selection_transfer_async (selection, - META_SELECTION_CLIPBOARD, - mime_type, - -1, - read_data->stream, - read_data->cancellable, - (GAsyncReadyCallback) transfer_cb, - read_data); - - meta_dbus_remote_desktop_session_complete_selection_read (skeleton, - invocation, - fd_list, - fd_variant); - - return TRUE; -} - -static void -meta_remote_desktop_session_init_iface (MetaDBusRemoteDesktopSessionIface *iface) -{ - iface->handle_start = handle_start; - iface->handle_stop = handle_stop; - iface->handle_notify_keyboard_keycode = handle_notify_keyboard_keycode; - iface->handle_notify_keyboard_keysym = handle_notify_keyboard_keysym; - iface->handle_notify_pointer_button = handle_notify_pointer_button; - iface->handle_notify_pointer_axis = handle_notify_pointer_axis; - iface->handle_notify_pointer_axis_discrete = handle_notify_pointer_axis_discrete; - iface->handle_notify_pointer_motion_relative = handle_notify_pointer_motion_relative; - iface->handle_notify_pointer_motion_absolute = handle_notify_pointer_motion_absolute; - iface->handle_notify_touch_down = handle_notify_touch_down; - iface->handle_notify_touch_motion = handle_notify_touch_motion; - iface->handle_notify_touch_up = handle_notify_touch_up; - iface->handle_enable_clipboard = handle_enable_clipboard; - iface->handle_disable_clipboard = handle_disable_clipboard; - iface->handle_set_selection = handle_set_selection; - iface->handle_selection_write = handle_selection_write; - iface->handle_selection_write_done = handle_selection_write_done; - iface->handle_selection_read = handle_selection_read; -} - -static void -meta_remote_desktop_session_client_vanished (MetaDbusSession *dbus_session) -{ - meta_remote_desktop_session_close (META_REMOTE_DESKTOP_SESSION (dbus_session)); -} - -static void -meta_dbus_session_init_iface (MetaDbusSessionInterface *iface) -{ - iface->client_vanished = meta_remote_desktop_session_client_vanished; -} - -static void -meta_remote_desktop_session_finalize (GObject *object) -{ - MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (object); - MetaDisplay *display = meta_get_display (); - MetaSelection *selection = meta_display_get_selection (display); - - g_assert (!meta_remote_desktop_session_is_running (session)); - - g_clear_signal_handler (&session->owner_changed_handler_id, selection); - reset_current_selection_source (session); - cancel_selection_read (session); - g_hash_table_unref (session->transfer_requests); - - g_clear_object (&session->handle); - g_free (session->peer_name); - g_free (session->session_id); - g_free (session->object_path); - - G_OBJECT_CLASS (meta_remote_desktop_session_parent_class)->finalize (object); -} - -static void -meta_remote_desktop_session_init (MetaRemoteDesktopSession *session) -{ - MetaDBusRemoteDesktopSession *skeleton = - META_DBUS_REMOTE_DESKTOP_SESSION (session); - GRand *rand; - static unsigned int global_session_number = 0; - - rand = g_rand_new (); - session->session_id = meta_generate_random_id (rand, 32); - g_rand_free (rand); - - meta_dbus_remote_desktop_session_set_session_id (skeleton, session->session_id); - - session->object_path = - g_strdup_printf (META_REMOTE_DESKTOP_SESSION_DBUS_PATH "/u%u", - ++global_session_number); - - session->transfer_requests = g_hash_table_new (NULL, NULL); -} - -static void -meta_remote_desktop_session_class_init (MetaRemoteDesktopSessionClass *klass) -{ - - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_remote_desktop_session_finalize; -} - -static MetaRemoteDesktopSessionHandle * -meta_remote_desktop_session_handle_new (MetaRemoteDesktopSession *session) -{ - MetaRemoteDesktopSessionHandle *handle; - - handle = g_object_new (META_TYPE_REMOTE_DESKTOP_SESSION_HANDLE, NULL); - handle->session = session; - - return handle; -} - -static void -meta_remote_desktop_session_handle_stop (MetaRemoteAccessHandle *handle) -{ - MetaRemoteDesktopSession *session; - - session = META_REMOTE_DESKTOP_SESSION_HANDLE (handle)->session; - if (!session) - return; - - meta_remote_desktop_session_close (session); -} - -static void -meta_remote_desktop_session_handle_init (MetaRemoteDesktopSessionHandle *handle) -{ -} - -static void -meta_remote_desktop_session_handle_class_init (MetaRemoteDesktopSessionHandleClass *klass) -{ - MetaRemoteAccessHandleClass *remote_access_handle_class = - META_REMOTE_ACCESS_HANDLE_CLASS (klass); - - remote_access_handle_class->stop = meta_remote_desktop_session_handle_stop; -} diff --git a/src/backends/meta-remote-desktop-session.h b/src/backends/meta-remote-desktop-session.h deleted file mode 100644 index 7af9c4897..000000000 --- a/src/backends/meta-remote-desktop-session.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015-2017 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_REMOTE_DESKTOP_SESSION_H -#define META_REMOTE_DESKTOP_SESSION_H - -#include - -#include "backends/meta-remote-desktop.h" -#include "backends/meta-screen-cast-session.h" - -#define META_TYPE_REMOTE_DESKTOP_SESSION (meta_remote_desktop_session_get_type ()) -G_DECLARE_FINAL_TYPE (MetaRemoteDesktopSession, meta_remote_desktop_session, - META, REMOTE_DESKTOP_SESSION, - MetaDBusRemoteDesktopSessionSkeleton) - -#define META_TYPE_REMOTE_DESKTOP_SESSION_HANDLE (meta_remote_desktop_session_handle_get_type ()) -G_DECLARE_FINAL_TYPE (MetaRemoteDesktopSessionHandle, - meta_remote_desktop_session_handle, - META, REMOTE_DESKTOP_SESSION_HANDLE, - MetaRemoteAccessHandle) - -char * meta_remote_desktop_session_get_object_path (MetaRemoteDesktopSession *session); - -char * meta_remote_desktop_session_get_session_id (MetaRemoteDesktopSession *session); - -gboolean meta_remote_desktop_session_register_screen_cast (MetaRemoteDesktopSession *session, - MetaScreenCastSession *screen_cast_session, - GError **error); - -void meta_remote_desktop_session_request_transfer (MetaRemoteDesktopSession *session, - const char *mime_type, - GTask *task); - -void meta_remote_desktop_session_close (MetaRemoteDesktopSession *session); - -MetaRemoteDesktopSession * meta_remote_desktop_session_new (MetaRemoteDesktop *remote_desktop, - const char *peer_name, - GError **error); - -#endif /* META_REMOTE_DESKTOP_SESSION_H */ diff --git a/src/backends/meta-remote-desktop.c b/src/backends/meta-remote-desktop.c deleted file mode 100644 index f0a499818..000000000 --- a/src/backends/meta-remote-desktop.c +++ /dev/null @@ -1,342 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015-2017 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "backends/meta-remote-desktop.h" - -#include -#include -#include -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-cursor-renderer.h" -#include "backends/meta-remote-desktop-session.h" -#include "backends/native/meta-cursor-renderer-native.h" -#include "meta/meta-backend.h" - -#include "meta-dbus-remote-desktop.h" - -#define META_REMOTE_DESKTOP_DBUS_SERVICE "org.gnome.Mutter.RemoteDesktop" -#define META_REMOTE_DESKTOP_DBUS_PATH "/org/gnome/Mutter/RemoteDesktop" -#define META_REMOTE_DESKTOP_API_VERSION 1 - -typedef enum _MetaRemoteDesktopDeviceTypes -{ - META_REMOTE_DESKTOP_DEVICE_TYPE_NONE = 0, - META_REMOTE_DESKTOP_DEVICE_TYPE_KEYBOARD = 1 << 0, - META_REMOTE_DESKTOP_DEVICE_TYPE_POINTER = 1 << 1, - META_REMOTE_DESKTOP_DEVICE_TYPE_TOUCHSCREEN = 1 << 2, -} MetaRemoteDesktopDeviceTypes; - -struct _MetaRemoteDesktop -{ - MetaDBusRemoteDesktopSkeleton parent; - - MetaBackend *backend; - int dbus_name_id; - - int inhibit_count; - - GHashTable *sessions; - - MetaDbusSessionWatcher *session_watcher; -}; - -static void -meta_remote_desktop_init_iface (MetaDBusRemoteDesktopIface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaRemoteDesktop, - meta_remote_desktop, - META_DBUS_TYPE_REMOTE_DESKTOP_SKELETON, - G_IMPLEMENT_INTERFACE (META_DBUS_TYPE_REMOTE_DESKTOP, - meta_remote_desktop_init_iface)); - -void -meta_remote_desktop_inhibit (MetaRemoteDesktop *remote_desktop) -{ - remote_desktop->inhibit_count++; - if (remote_desktop->inhibit_count == 1) - { - GHashTableIter iter; - gpointer key, value; - - g_hash_table_iter_init (&iter, remote_desktop->sessions); - while (g_hash_table_iter_next (&iter, &key, &value)) - { - MetaRemoteDesktopSession *session = value; - - g_hash_table_iter_steal (&iter); - meta_remote_desktop_session_close (session); - } - } -} - -void -meta_remote_desktop_uninhibit (MetaRemoteDesktop *remote_desktop) -{ - g_return_if_fail (remote_desktop->inhibit_count > 0); - - remote_desktop->inhibit_count--; -} - -MetaBackend * -meta_remote_desktop_get_backend (MetaRemoteDesktop *remote_desktop) -{ - return remote_desktop->backend; -} - -GDBusConnection * -meta_remote_desktop_get_connection (MetaRemoteDesktop *remote_desktop) -{ - GDBusInterfaceSkeleton *interface_skeleton = - G_DBUS_INTERFACE_SKELETON (remote_desktop); - - return g_dbus_interface_skeleton_get_connection (interface_skeleton); -} - -MetaRemoteDesktopSession * -meta_remote_desktop_get_session (MetaRemoteDesktop *remote_desktop, - const char *session_id) -{ - return g_hash_table_lookup (remote_desktop->sessions, session_id); -} - -static void -on_session_closed (MetaRemoteDesktopSession *session, - MetaRemoteDesktop *remote_desktop) -{ - char *session_id; - - session_id = meta_remote_desktop_session_get_session_id (session); - g_hash_table_remove (remote_desktop->sessions, session_id); -} - -static gboolean -handle_create_session (MetaDBusRemoteDesktop *skeleton, - GDBusMethodInvocation *invocation) -{ - MetaRemoteDesktop *remote_desktop = META_REMOTE_DESKTOP (skeleton); - const char *peer_name; - MetaRemoteDesktopSession *session; - GError *error = NULL; - char *session_id; - char *session_path; - const char *client_dbus_name; - - if (remote_desktop->inhibit_count > 0) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Session creation inhibited"); - - return TRUE; - } - - peer_name = g_dbus_method_invocation_get_sender (invocation); - session = meta_remote_desktop_session_new (remote_desktop, - peer_name, - &error); - if (!session) - { - g_warning ("Failed to create remote desktop session: %s", - error->message); - - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Failed to create session: %s", - error->message); - g_error_free (error); - - return TRUE; - } - - session_id = meta_remote_desktop_session_get_session_id (session); - g_hash_table_insert (remote_desktop->sessions, - session_id, - session); - - client_dbus_name = g_dbus_method_invocation_get_sender (invocation); - meta_dbus_session_watcher_watch_session (remote_desktop->session_watcher, - client_dbus_name, - META_DBUS_SESSION (session)); - - session_path = meta_remote_desktop_session_get_object_path (session); - meta_dbus_remote_desktop_complete_create_session (skeleton, - invocation, - session_path); - - g_signal_connect (session, "session-closed", - G_CALLBACK (on_session_closed), - remote_desktop); - - return TRUE; -} - -static void -meta_remote_desktop_init_iface (MetaDBusRemoteDesktopIface *iface) -{ - iface->handle_create_session = handle_create_session; -} - -static void -on_bus_acquired (GDBusConnection *connection, - const char *name, - gpointer user_data) -{ - MetaRemoteDesktop *remote_desktop = user_data; - GDBusInterfaceSkeleton *interface_skeleton = - G_DBUS_INTERFACE_SKELETON (remote_desktop); - GError *error = NULL; - - if (!g_dbus_interface_skeleton_export (interface_skeleton, - connection, - META_REMOTE_DESKTOP_DBUS_PATH, - &error)) - g_warning ("Failed to export remote desktop object: %s", error->message); -} - -static void -on_name_acquired (GDBusConnection *connection, - const char *name, - gpointer user_data) -{ - g_info ("Acquired name %s", name); -} - -static void -on_name_lost (GDBusConnection *connection, - const char *name, - gpointer user_data) -{ - g_warning ("Lost or failed to acquire name %s", name); -} - -static void -meta_remote_desktop_constructed (GObject *object) -{ - MetaRemoteDesktop *remote_desktop = META_REMOTE_DESKTOP (object); - - remote_desktop->dbus_name_id = - g_bus_own_name (G_BUS_TYPE_SESSION, - META_REMOTE_DESKTOP_DBUS_SERVICE, - G_BUS_NAME_OWNER_FLAGS_NONE, - on_bus_acquired, - on_name_acquired, - on_name_lost, - remote_desktop, - NULL); -} - -static void -on_prepare_shutdown (MetaBackend *backend, - MetaRemoteDesktop *remote_desktop) -{ - GHashTableIter iter; - gpointer value; - - g_hash_table_iter_init (&iter, remote_desktop->sessions); - while (g_hash_table_iter_next (&iter, NULL, &value)) - { - MetaRemoteDesktopSession *session = value; - - g_hash_table_iter_steal (&iter); - meta_remote_desktop_session_close (session); - } -} - -static void -meta_remote_desktop_finalize (GObject *object) -{ - MetaRemoteDesktop *remote_desktop = META_REMOTE_DESKTOP (object); - - if (remote_desktop->dbus_name_id != 0) - g_bus_unown_name (remote_desktop->dbus_name_id); - - g_assert (g_hash_table_size (remote_desktop->sessions) == 0); - g_hash_table_destroy (remote_desktop->sessions); - - G_OBJECT_CLASS (meta_remote_desktop_parent_class)->finalize (object); -} - -MetaRemoteDesktop * -meta_remote_desktop_new (MetaBackend *backend, - MetaDbusSessionWatcher *session_watcher) -{ - MetaRemoteDesktop *remote_desktop; - - remote_desktop = g_object_new (META_TYPE_REMOTE_DESKTOP, NULL); - remote_desktop->backend = backend; - remote_desktop->session_watcher = session_watcher; - - g_signal_connect (backend, "prepare-shutdown", - G_CALLBACK (on_prepare_shutdown), - remote_desktop); - - return remote_desktop; -} - -static MetaRemoteDesktopDeviceTypes -calculate_supported_device_types (void) -{ - ClutterBackend *backend = clutter_get_default_backend (); - ClutterSeat *seat = clutter_backend_get_default_seat (backend); - ClutterVirtualDeviceType device_types; - MetaRemoteDesktopDeviceTypes supported_devices = - META_REMOTE_DESKTOP_DEVICE_TYPE_NONE; - - device_types = - clutter_seat_get_supported_virtual_device_types (seat); - - if (device_types & CLUTTER_VIRTUAL_DEVICE_TYPE_KEYBOARD) - supported_devices |= META_REMOTE_DESKTOP_DEVICE_TYPE_KEYBOARD; - if (device_types & CLUTTER_VIRTUAL_DEVICE_TYPE_POINTER) - supported_devices |= META_REMOTE_DESKTOP_DEVICE_TYPE_POINTER; - if (device_types & CLUTTER_VIRTUAL_DEVICE_TYPE_TOUCHSCREEN) - supported_devices |= META_REMOTE_DESKTOP_DEVICE_TYPE_TOUCHSCREEN; - - return supported_devices; -} - -static void -meta_remote_desktop_init (MetaRemoteDesktop *remote_desktop) -{ - remote_desktop->sessions = g_hash_table_new (g_str_hash, g_str_equal); - - meta_dbus_remote_desktop_set_supported_device_types ( - META_DBUS_REMOTE_DESKTOP (remote_desktop), - calculate_supported_device_types ()); - meta_dbus_remote_desktop_set_version ( - META_DBUS_REMOTE_DESKTOP (remote_desktop), - META_REMOTE_DESKTOP_API_VERSION); -} - -static void -meta_remote_desktop_class_init (MetaRemoteDesktopClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->constructed = meta_remote_desktop_constructed; - object_class->finalize = meta_remote_desktop_finalize; -} diff --git a/src/backends/meta-remote-desktop.h b/src/backends/meta-remote-desktop.h deleted file mode 100644 index 3a7f38563..000000000 --- a/src/backends/meta-remote-desktop.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015-2017 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_REMOTE_DESKTOP_H -#define META_REMOTE_DESKTOP_H - -#include - -#include "backends/meta-backend-types.h" -#include "backends/meta-dbus-session-watcher.h" - -#include "meta-dbus-remote-desktop.h" - -typedef struct _MetaRemoteDesktopSession MetaRemoteDesktopSession; - -#define META_TYPE_REMOTE_DESKTOP (meta_remote_desktop_get_type ()) -G_DECLARE_FINAL_TYPE (MetaRemoteDesktop, meta_remote_desktop, - META, REMOTE_DESKTOP, - MetaDBusRemoteDesktopSkeleton) - -void meta_remote_desktop_inhibit (MetaRemoteDesktop *remote_desktop); - -void meta_remote_desktop_uninhibit (MetaRemoteDesktop *remote_desktop); - -MetaBackend * meta_remote_desktop_get_backend (MetaRemoteDesktop *remote_desktop); - -MetaRemoteDesktopSession * meta_remote_desktop_get_session (MetaRemoteDesktop *remote_desktop, - const char *session_id); - -GDBusConnection * meta_remote_desktop_get_connection (MetaRemoteDesktop *remote_desktop); - -MetaRemoteDesktop * meta_remote_desktop_new (MetaBackend *backend, - MetaDbusSessionWatcher *session_watcher); - -#endif /* META_REMOTE_DESKTOP_H */ diff --git a/src/backends/meta-renderer-view.c b/src/backends/meta-renderer-view.c deleted file mode 100644 index 55617fc68..000000000 --- a/src/backends/meta-renderer-view.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (C) 2016 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 . - */ - -/** - * SECTION:meta-renderer-view - * @title: MetaRendererView - * @short_description: Renders (a part of) the global stage. - * - * A MetaRendererView object is responsible for rendering (a part of) the - * global stage, or more precisely: the part that matches what can be seen on a - * #MetaLogicalMonitor. By splitting up the rendering into different parts and - * attaching it to a #MetaLogicalMonitor, we can do the rendering so that each - * renderer view is responsible for applying the right #MetaMonitorTransform - * and the right scaling. - */ - -#include "config.h" - -#include "backends/meta-renderer-view.h" - -#include "backends/meta-crtc.h" -#include "backends/meta-renderer.h" -#include "clutter/clutter-mutter.h" -#include "compositor/region-utils.h" - -enum -{ - PROP_0, - - PROP_TRANSFORM, - PROP_CRTC, - - PROP_LAST -}; - -static GParamSpec *obj_props[PROP_LAST]; - -struct _MetaRendererView -{ - MetaStageView parent; - - MetaMonitorTransform transform; - - MetaCrtc *crtc; -}; - -G_DEFINE_TYPE (MetaRendererView, meta_renderer_view, - META_TYPE_STAGE_VIEW) - -MetaMonitorTransform -meta_renderer_view_get_transform (MetaRendererView *view) -{ - return view->transform; -} - -MetaCrtc * -meta_renderer_view_get_crtc (MetaRendererView *view) -{ - return view->crtc; -} - -static void -meta_renderer_view_get_offscreen_transformation_matrix (ClutterStageView *view, - graphene_matrix_t *matrix) -{ - MetaRendererView *renderer_view = META_RENDERER_VIEW (view); - - graphene_matrix_init_identity (matrix); - - switch (renderer_view->transform) - { - case META_MONITOR_TRANSFORM_NORMAL: - break; - case META_MONITOR_TRANSFORM_90: - graphene_matrix_translate (matrix, &GRAPHENE_POINT3D_INIT (0, -1, 0)); - graphene_matrix_rotate (matrix, 90, graphene_vec3_z_axis ()); - break; - case META_MONITOR_TRANSFORM_180: - graphene_matrix_translate (matrix, &GRAPHENE_POINT3D_INIT (-1, -1, 0)); - graphene_matrix_rotate (matrix, 180, graphene_vec3_z_axis ()); - break; - case META_MONITOR_TRANSFORM_270: - graphene_matrix_translate (matrix, &GRAPHENE_POINT3D_INIT (-1, 0, 0)); - graphene_matrix_rotate (matrix, 270, graphene_vec3_z_axis ()); - break; - case META_MONITOR_TRANSFORM_FLIPPED: - graphene_matrix_translate (matrix, &GRAPHENE_POINT3D_INIT (-1, 0, 0)); - graphene_matrix_scale (matrix, -1, 1, 1); - break; - case META_MONITOR_TRANSFORM_FLIPPED_90: - graphene_matrix_rotate (matrix, 90, graphene_vec3_z_axis ()); - graphene_matrix_scale (matrix, -1, 1, 1); - break; - case META_MONITOR_TRANSFORM_FLIPPED_180: - graphene_matrix_translate (matrix, &GRAPHENE_POINT3D_INIT (0, -1, 0)); - graphene_matrix_rotate (matrix, 180, graphene_vec3_z_axis ()); - graphene_matrix_scale (matrix, -1, 1, 1); - break; - case META_MONITOR_TRANSFORM_FLIPPED_270: - graphene_matrix_translate (matrix, &GRAPHENE_POINT3D_INIT (-1, -1, 0)); - graphene_matrix_rotate (matrix, 270, graphene_vec3_z_axis ()); - graphene_matrix_scale (matrix, -1, 1, 1); - break; - } -} - -static void -meta_renderer_view_setup_offscreen_blit_pipeline (ClutterStageView *view, - CoglPipeline *pipeline) -{ - graphene_matrix_t matrix; - - meta_renderer_view_get_offscreen_transformation_matrix (view, &matrix); - cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix); -} - -static void -meta_renderer_view_transform_rect_to_onscreen (ClutterStageView *view, - const cairo_rectangle_int_t *src_rect, - int dst_width, - int dst_height, - cairo_rectangle_int_t *dst_rect) -{ - MetaRendererView *renderer_view = META_RENDERER_VIEW (view); - MetaMonitorTransform inverted_transform; - - inverted_transform = - meta_monitor_transform_invert (renderer_view->transform); - return meta_rectangle_transform (src_rect, - inverted_transform, - dst_width, - dst_height, - dst_rect); -} - -static void -meta_renderer_view_set_transform (MetaRendererView *view, - MetaMonitorTransform transform) -{ - if (view->transform == transform) - return; - - view->transform = transform; - clutter_stage_view_invalidate_offscreen_blit_pipeline (CLUTTER_STAGE_VIEW (view)); -} - -static void -meta_renderer_view_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaRendererView *view = META_RENDERER_VIEW (object); - - switch (prop_id) - { - case PROP_TRANSFORM: - g_value_set_uint (value, view->transform); - break; - case PROP_CRTC: - g_value_set_object (value, view->crtc); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_renderer_view_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaRendererView *view = META_RENDERER_VIEW (object); - - switch (prop_id) - { - case PROP_TRANSFORM: - meta_renderer_view_set_transform (view, g_value_get_uint (value)); - break; - case PROP_CRTC: - view->crtc = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_renderer_view_init (MetaRendererView *view) -{ -} - -static void -meta_renderer_view_class_init (MetaRendererViewClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - ClutterStageViewClass *view_class = CLUTTER_STAGE_VIEW_CLASS (klass); - - view_class->setup_offscreen_blit_pipeline = - meta_renderer_view_setup_offscreen_blit_pipeline; - view_class->get_offscreen_transformation_matrix = - meta_renderer_view_get_offscreen_transformation_matrix; - view_class->transform_rect_to_onscreen = - meta_renderer_view_transform_rect_to_onscreen; - - object_class->get_property = meta_renderer_view_get_property; - object_class->set_property = meta_renderer_view_set_property; - - obj_props[PROP_TRANSFORM] = - g_param_spec_uint ("transform", - "Transform", - "Transform to apply to the view", - META_MONITOR_TRANSFORM_NORMAL, - META_MONITOR_TRANSFORM_FLIPPED_270, - META_MONITOR_TRANSFORM_NORMAL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - - obj_props[PROP_CRTC] = - g_param_spec_object ("crtc", - "MetaCrtc", - "MetaCrtc", - META_TYPE_CRTC, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties (object_class, PROP_LAST, obj_props); -} diff --git a/src/backends/meta-renderer-view.h b/src/backends/meta-renderer-view.h deleted file mode 100644 index 3f21c7c48..000000000 --- a/src/backends/meta-renderer-view.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2016 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 . - */ - -#ifndef META_RENDERER_VIEW_H -#define META_RENDERER_VIEW_H - -#include "backends/meta-monitor-manager-private.h" -#include "backends/meta-stage-impl-private.h" -#include "backends/meta-stage-view-private.h" - -#define META_TYPE_RENDERER_VIEW (meta_renderer_view_get_type ()) -G_DECLARE_FINAL_TYPE (MetaRendererView, meta_renderer_view, - META, RENDERER_VIEW, - MetaStageView) - -MetaMonitorTransform meta_renderer_view_get_transform (MetaRendererView *view); - -MetaCrtc *meta_renderer_view_get_crtc (MetaRendererView *view); - -#endif /* META_RENDERER_VIEW_H */ diff --git a/src/backends/meta-renderer.c b/src/backends/meta-renderer.c deleted file mode 100644 index 8808a52ef..000000000 --- a/src/backends/meta-renderer.c +++ /dev/null @@ -1,405 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -/** - * SECTION:meta-renderer - * @title: MetaRenderer - * @short_description: Keeps track of the different renderer views. - * - * A MetaRenderer object has 2 functions: - * - * 1) Keeping a list of #MetaRendererViews, each responsible for - * rendering a part of the stage, corresponding to each #MetaLogicalMonitor. It - * keeps track of this list by querying the list of logical monitors in the - * #MetaBackend's #MetaMonitorManager, and creating a renderer view for each - * logical monitor it encounters. - * - * 2) Creating and setting up an appropriate #CoglRenderer. For example, a - * #MetaRenderer might call cogl_renderer_set_custom_winsys() to tie the - * backend-specific mechanisms into Cogl. - */ - -#include "config.h" - -#include "backends/meta-renderer.h" - -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-logical-monitor.h" - -enum -{ - PROP_0, - - PROP_BACKEND, - - N_PROPS -}; - -static GParamSpec *obj_props[N_PROPS]; - -typedef struct _MetaRendererPrivate -{ - MetaBackend *backend; - GList *views; - gboolean is_paused; -} MetaRendererPrivate; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaRenderer, meta_renderer, G_TYPE_OBJECT) - -MetaBackend * -meta_renderer_get_backend (MetaRenderer *renderer) -{ - MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer); - - return priv->backend; -} - -/** - * meta_renderer_create_cogl_renderer: - * @renderer: a #MetaRenderer object - * - * Creates a #CoglRenderer that is appropriate for a certain backend. For - * example, a #MetaRenderer might call cogl_renderer_set_custom_winsys() to tie - * the backend-specific mechanisms (such as swapBuffers and vsync) into Cogl. - * - * Returns: (transfer full): a newly made #CoglRenderer. - */ -CoglRenderer * -meta_renderer_create_cogl_renderer (MetaRenderer *renderer) -{ - return META_RENDERER_GET_CLASS (renderer)->create_cogl_renderer (renderer); -} - -static MetaRendererView * -meta_renderer_create_view (MetaRenderer *renderer, - MetaLogicalMonitor *logical_monitor, - MetaOutput *output, - MetaCrtc *crtc) -{ - return META_RENDERER_GET_CLASS (renderer)->create_view (renderer, - logical_monitor, - output, - crtc); -} - -/** - * meta_renderer_rebuild_views: - * @renderer: a #MetaRenderer object - * - * Rebuilds the internal list of #MetaRendererView objects by querying the - * current #MetaBackend's #MetaMonitorManager. - * - * This also leads to the original list of monitors being unconditionally freed. - */ -void -meta_renderer_rebuild_views (MetaRenderer *renderer) -{ - return META_RENDERER_GET_CLASS (renderer)->rebuild_views (renderer); -} - -static void -create_crtc_view (MetaLogicalMonitor *logical_monitor, - MetaMonitor *monitor, - MetaOutput *output, - MetaCrtc *crtc, - gpointer user_data) -{ - MetaRenderer *renderer = user_data; - MetaRendererView *view; - - view = meta_renderer_create_view (renderer, logical_monitor, output, crtc); - meta_renderer_add_view (renderer, view); -} - -static void -meta_renderer_real_rebuild_views (MetaRenderer *renderer) -{ - MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer); - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - GList *logical_monitors, *l; - - g_clear_list (&priv->views, (GDestroyNotify) clutter_stage_view_destroy); - - logical_monitors = - meta_monitor_manager_get_logical_monitors (monitor_manager); - - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - - if (meta_logical_monitor_is_primary (logical_monitor)) - { - ClutterBackend *clutter_backend; - float scale; - - clutter_backend = meta_backend_get_clutter_backend (backend); - scale = meta_is_stage_views_scaled () - ? meta_logical_monitor_get_scale (logical_monitor) - : 1.f; - - clutter_backend_set_fallback_resource_scale (clutter_backend, scale); - } - - meta_logical_monitor_foreach_crtc (logical_monitor, - create_crtc_view, - renderer); - } -} - -MetaRendererView * -meta_renderer_get_view_for_crtc (MetaRenderer *renderer, - MetaCrtc *crtc) -{ - MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer); - GList *l; - - for (l = priv->views; l; l = l->next) - { - MetaRendererView *view = l->data; - - if (meta_renderer_view_get_crtc (view) == crtc) - return view; - } - - return NULL; -} - -typedef struct _CollectViewsData -{ - MetaRenderer *renderer; - GList *out_views; -} CollectViewsData; - -static gboolean -collect_views (MetaMonitor *monitor, - MetaMonitorMode *mode, - MetaMonitorCrtcMode *monitor_crtc_mode, - gpointer user_data, - GError **error) -{ - CollectViewsData *data = user_data; - MetaCrtc *crtc; - MetaRendererView *view; - - crtc = meta_output_get_assigned_crtc (monitor_crtc_mode->output); - view = meta_renderer_get_view_for_crtc (data->renderer, crtc); - if (!g_list_find (data->out_views, view)) - data->out_views = g_list_prepend (data->out_views, view); - - return TRUE; -} - -static GList * -meta_renderer_real_get_views_for_monitor (MetaRenderer *renderer, - MetaMonitor *monitor) -{ - CollectViewsData data = { 0 }; - MetaMonitorMode *monitor_mode; - - data.renderer = renderer; - - monitor_mode = meta_monitor_get_current_mode (monitor); - meta_monitor_mode_foreach_crtc (monitor, monitor_mode, - collect_views, - &data, - NULL); - - return data.out_views; -} - -GList * -meta_renderer_get_views_for_monitor (MetaRenderer *renderer, - MetaMonitor *monitor) -{ - return META_RENDERER_GET_CLASS (renderer)->get_views_for_monitor (renderer, - monitor); -} - -void -meta_renderer_add_view (MetaRenderer *renderer, - MetaRendererView *view) -{ - MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer); - - priv->views = g_list_append (priv->views, view); - - if (priv->is_paused) - { - ClutterFrameClock *frame_clock = - clutter_stage_view_get_frame_clock (CLUTTER_STAGE_VIEW (view)); - - clutter_frame_clock_inhibit (frame_clock); - } -} - -/** - * meta_renderer_get_views: - * @renderer: a #MetaRenderer object - * - * Returns a list of #MetaRendererView objects, each dealing with a part of the - * stage. - * - * Returns: (transfer none) (element-type MetaRendererView): a list of - * #MetaRendererView objects. - */ -GList * -meta_renderer_get_views (MetaRenderer *renderer) -{ - MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer); - - return priv->views; -} - -void -meta_renderer_pause (MetaRenderer *renderer) -{ - MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer); - GList *l; - - g_return_if_fail (!priv->is_paused); - priv->is_paused = TRUE; - - for (l = priv->views; l; l = l->next) - { - ClutterStageView *stage_view = l->data; - ClutterFrameClock *frame_clock = - clutter_stage_view_get_frame_clock (stage_view); - - clutter_frame_clock_inhibit (frame_clock); - } -} - -void -meta_renderer_resume (MetaRenderer *renderer) -{ - MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer); - GList *l; - - g_return_if_fail (priv->is_paused); - priv->is_paused = FALSE; - - for (l = priv->views; l; l = l->next) - { - ClutterStageView *stage_view = l->data; - ClutterFrameClock *frame_clock = - clutter_stage_view_get_frame_clock (stage_view); - - clutter_frame_clock_uninhibit (frame_clock); - } -} - -gboolean -meta_renderer_is_hardware_accelerated (MetaRenderer *renderer) -{ - MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer); - MetaBackend *backend = priv->backend; - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = - clutter_backend_get_cogl_context (clutter_backend); - - return cogl_context_is_hardware_accelerated (cogl_context); -} - -static void -meta_renderer_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaRenderer *renderer = META_RENDERER (object); - MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer); - - switch (prop_id) - { - case PROP_BACKEND: - g_value_set_object (value, priv->backend); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_renderer_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaRenderer *renderer = META_RENDERER (object); - MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer); - - switch (prop_id) - { - case PROP_BACKEND: - priv->backend = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_renderer_dispose (GObject *object) -{ - MetaRenderer *renderer = META_RENDERER (object); - MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer); - - g_clear_list (&priv->views, g_object_unref); - - G_OBJECT_CLASS (meta_renderer_parent_class)->dispose (object); -} - -static void -meta_renderer_init (MetaRenderer *renderer) -{ -} - -static void -meta_renderer_class_init (MetaRendererClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->get_property = meta_renderer_get_property; - object_class->set_property = meta_renderer_set_property; - object_class->dispose = meta_renderer_dispose; - - klass->rebuild_views = meta_renderer_real_rebuild_views; - klass->get_views_for_monitor = meta_renderer_real_get_views_for_monitor; - - 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); - g_object_class_install_properties (object_class, N_PROPS, obj_props); -} diff --git a/src/backends/meta-renderer.h b/src/backends/meta-renderer.h deleted file mode 100644 index 92b0727bb..000000000 --- a/src/backends/meta-renderer.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#ifndef META_RENDERER_H -#define META_RENDERER_H - -#include - -#include "backends/meta-monitor-manager-private.h" -#include "backends/meta-renderer-view.h" -#include "core/util-private.h" -#include "clutter/clutter-mutter.h" -#include "cogl/cogl.h" - -#define META_TYPE_RENDERER (meta_renderer_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaRenderer, meta_renderer, META, RENDERER, GObject) - -struct _MetaRendererClass -{ - GObjectClass parent_class; - - CoglRenderer * (* create_cogl_renderer) (MetaRenderer *renderer); - MetaRendererView * (* create_view) (MetaRenderer *renderer, - MetaLogicalMonitor *logical_monitor, - MetaOutput *output, - MetaCrtc *crtc); - void (* rebuild_views) (MetaRenderer *renderer); - GList * (* get_views_for_monitor) (MetaRenderer *renderer, - MetaMonitor *monitor); -}; - -MetaBackend * meta_renderer_get_backend (MetaRenderer *renderer); - -CoglRenderer * meta_renderer_create_cogl_renderer (MetaRenderer *renderer); - -void meta_renderer_rebuild_views (MetaRenderer *renderer); - -void meta_renderer_add_view (MetaRenderer *renderer, - MetaRendererView *view); - -GList * meta_renderer_get_views_for_monitor (MetaRenderer *renderer, - MetaMonitor *monitor); - -META_EXPORT_TEST -MetaRendererView * meta_renderer_get_view_for_crtc (MetaRenderer *renderer, - MetaCrtc *crtc); - -META_EXPORT_TEST -GList * meta_renderer_get_views (MetaRenderer *renderer); - -gboolean meta_renderer_is_hardware_accelerated (MetaRenderer *renderer); - -void meta_renderer_pause (MetaRenderer *renderer); - -void meta_renderer_resume (MetaRenderer *renderer); - -#endif /* META_RENDERER_H */ diff --git a/src/backends/meta-screen-cast-area-stream-src.c b/src/backends/meta-screen-cast-area-stream-src.c deleted file mode 100644 index aa1548101..000000000 --- a/src/backends/meta-screen-cast-area-stream-src.c +++ /dev/null @@ -1,652 +0,0 @@ -/* - * Copyright (C) 2020 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "backends/meta-screen-cast-area-stream-src.h" - -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-cursor-tracker-private.h" -#include "backends/meta-screen-cast-area-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" - -struct _MetaScreenCastAreaStreamSrc -{ - MetaScreenCastStreamSrc parent; - - gboolean cursor_bitmap_invalid; - gboolean hw_cursor_inhibited; - - GList *watches; - - gulong position_invalidated_handler_id; - gulong cursor_changed_handler_id; - - guint maybe_record_idle_id; -}; - -static void -hw_cursor_inhibitor_iface_init (MetaHwCursorInhibitorInterface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaScreenCastAreaStreamSrc, - meta_screen_cast_area_stream_src, - META_TYPE_SCREEN_CAST_STREAM_SRC, - G_IMPLEMENT_INTERFACE (META_TYPE_HW_CURSOR_INHIBITOR, - hw_cursor_inhibitor_iface_init)) - -static ClutterStage * -get_stage (MetaScreenCastAreaStreamSrc *area_src) -{ - MetaScreenCastStreamSrc *src; - MetaScreenCastStream *stream; - MetaScreenCastAreaStream *area_stream; - - src = META_SCREEN_CAST_STREAM_SRC (area_src); - stream = meta_screen_cast_stream_src_get_stream (src); - area_stream = META_SCREEN_CAST_AREA_STREAM (stream); - - return meta_screen_cast_area_stream_get_stage (area_stream); -} - -static MetaBackend * -get_backend (MetaScreenCastAreaStreamSrc *area_src) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (area_src); - MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src); - MetaScreenCastSession *session = meta_screen_cast_stream_get_session (stream); - MetaScreenCast *screen_cast = - meta_screen_cast_session_get_screen_cast (session); - - return meta_screen_cast_get_backend (screen_cast); -} - -static gboolean -meta_screen_cast_area_stream_src_get_specs (MetaScreenCastStreamSrc *src, - int *width, - int *height, - float *frame_rate) -{ - MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src); - MetaScreenCastAreaStream *area_stream = META_SCREEN_CAST_AREA_STREAM (stream); - MetaRectangle *area; - float scale; - - area = meta_screen_cast_area_stream_get_area (area_stream); - scale = meta_screen_cast_area_stream_get_scale (area_stream); - - *width = (int) roundf (area->width * scale); - *height = (int) roundf (area->height * scale); - *frame_rate = 60.0; - - return TRUE; -} - -static gboolean -is_cursor_in_stream (MetaScreenCastAreaStreamSrc *area_src) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (area_src); - MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src); - MetaScreenCastAreaStream *area_stream = META_SCREEN_CAST_AREA_STREAM (stream); - MetaBackend *backend = get_backend (area_src); - MetaCursorRenderer *cursor_renderer = - meta_backend_get_cursor_renderer (backend); - MetaRectangle *area; - graphene_rect_t area_rect; - MetaCursorSprite *cursor_sprite; - - area = meta_screen_cast_area_stream_get_area (area_stream); - area_rect = meta_rectangle_to_graphene_rect (area); - - cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer); - if (cursor_sprite) - { - graphene_rect_t cursor_rect; - - cursor_rect = meta_cursor_renderer_calculate_rect (cursor_renderer, - cursor_sprite); - return graphene_rect_intersection (&cursor_rect, &area_rect, NULL); - } - else - { - MetaCursorTracker *cursor_tracker = - meta_backend_get_cursor_tracker (backend); - graphene_point_t cursor_position; - - meta_cursor_tracker_get_pointer (cursor_tracker, &cursor_position, NULL); - return graphene_rect_contains_point (&area_rect, &cursor_position); - } -} - -static gboolean -is_redraw_queued (MetaScreenCastAreaStreamSrc *area_src) -{ - ClutterStage *stage = get_stage (area_src); - GList *l; - - for (l = clutter_stage_peek_stage_views (stage); l; l = l->next) - { - ClutterStageView *view = l->data; - - if (clutter_stage_is_redraw_queued_on_view (stage, view)) - return TRUE; - } - - return FALSE; -} - -static void -sync_cursor_state (MetaScreenCastAreaStreamSrc *area_src) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (area_src); - MetaScreenCastRecordFlag flags; - - if (is_redraw_queued (area_src)) - return; - - flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY; - meta_screen_cast_stream_src_maybe_record_frame (src, flags); -} - -static void -pointer_position_invalidated (MetaCursorTracker *cursor_tracker, - MetaScreenCastAreaStreamSrc *area_src) -{ - sync_cursor_state (area_src); -} - -static void -cursor_changed (MetaCursorTracker *cursor_tracker, - MetaScreenCastAreaStreamSrc *area_src) -{ - area_src->cursor_bitmap_invalid = TRUE; - sync_cursor_state (area_src); -} - -static void -inhibit_hw_cursor (MetaScreenCastAreaStreamSrc *area_src) -{ - MetaHwCursorInhibitor *inhibitor; - MetaBackend *backend; - - g_return_if_fail (!area_src->hw_cursor_inhibited); - - backend = get_backend (area_src); - inhibitor = META_HW_CURSOR_INHIBITOR (area_src); - meta_backend_add_hw_cursor_inhibitor (backend, inhibitor); - - area_src->hw_cursor_inhibited = TRUE; -} - -static void -uninhibit_hw_cursor (MetaScreenCastAreaStreamSrc *area_src) -{ - MetaHwCursorInhibitor *inhibitor; - MetaBackend *backend; - - g_return_if_fail (area_src->hw_cursor_inhibited); - - backend = get_backend (area_src); - inhibitor = META_HW_CURSOR_INHIBITOR (area_src); - meta_backend_remove_hw_cursor_inhibitor (backend, inhibitor); - - area_src->hw_cursor_inhibited = FALSE; -} - -static gboolean -maybe_record_frame_on_idle (gpointer user_data) -{ - MetaScreenCastAreaStreamSrc *area_src = - META_SCREEN_CAST_AREA_STREAM_SRC (user_data); - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (area_src); - MetaScreenCastRecordFlag flags; - - area_src->maybe_record_idle_id = 0; - - flags = META_SCREEN_CAST_RECORD_FLAG_NONE; - meta_screen_cast_stream_src_maybe_record_frame (src, flags); - - return G_SOURCE_REMOVE; -} - -static void -before_stage_painted (MetaStage *stage, - ClutterStageView *view, - ClutterPaintContext *paint_context, - gpointer user_data) -{ - MetaScreenCastAreaStreamSrc *area_src = - META_SCREEN_CAST_AREA_STREAM_SRC (user_data); - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (area_src); - - if (area_src->maybe_record_idle_id) - return; - - if (!clutter_stage_view_peek_scanout (view)) - return; - - area_src->maybe_record_idle_id = g_idle_add (maybe_record_frame_on_idle, src); -} - -static void -stage_painted (MetaStage *stage, - ClutterStageView *view, - ClutterPaintContext *paint_context, - gpointer user_data) -{ - MetaScreenCastAreaStreamSrc *area_src = - META_SCREEN_CAST_AREA_STREAM_SRC (user_data); - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (area_src); - MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src); - MetaScreenCastAreaStream *area_stream = META_SCREEN_CAST_AREA_STREAM (stream); - const cairo_region_t *redraw_clip; - MetaRectangle *area; - - if (area_src->maybe_record_idle_id) - return; - - area = meta_screen_cast_area_stream_get_area (area_stream); - redraw_clip = clutter_paint_context_get_redraw_clip (paint_context); - - if (redraw_clip) - { - switch (cairo_region_contains_rectangle (redraw_clip, area)) - { - case CAIRO_REGION_OVERLAP_IN: - case CAIRO_REGION_OVERLAP_PART: - break; - case CAIRO_REGION_OVERLAP_OUT: - return; - } - } - - area_src->maybe_record_idle_id = g_idle_add (maybe_record_frame_on_idle, src); -} - -static void -add_view_painted_watches (MetaScreenCastAreaStreamSrc *area_src) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (area_src); - MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src); - MetaScreenCastAreaStream *area_stream = META_SCREEN_CAST_AREA_STREAM (stream); - MetaBackend *backend = get_backend (area_src); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - ClutterStage *stage; - MetaStage *meta_stage; - MetaRectangle *area; - GList *l; - - stage = get_stage (area_src); - meta_stage = META_STAGE (stage); - area = meta_screen_cast_area_stream_get_area (area_stream); - - for (l = meta_renderer_get_views (renderer); l; l = l->next) - { - MetaRendererView *view = l->data; - MetaRectangle view_layout; - - clutter_stage_view_get_layout (CLUTTER_STAGE_VIEW (view), &view_layout); - if (meta_rectangle_overlap (area, &view_layout)) - { - MetaStageWatch *watch; - - watch = meta_stage_watch_view (meta_stage, - CLUTTER_STAGE_VIEW (view), - META_STAGE_WATCH_BEFORE_PAINT, - before_stage_painted, - area_src); - - area_src->watches = g_list_prepend (area_src->watches, watch); - - watch = meta_stage_watch_view (meta_stage, - CLUTTER_STAGE_VIEW (view), - META_STAGE_WATCH_AFTER_ACTOR_PAINT, - stage_painted, - area_src); - - area_src->watches = g_list_prepend (area_src->watches, watch); - } - } -} - -static void -on_monitors_changed (MetaMonitorManager *monitor_manager, - MetaScreenCastAreaStreamSrc *area_src) -{ - MetaStage *stage = META_STAGE (get_stage (area_src)); - GList *l; - - for (l = area_src->watches; l; l = l->next) - meta_stage_remove_watch (stage, l->data); - g_clear_pointer (&area_src->watches, g_list_free); - - add_view_painted_watches (area_src); -} - -static void -meta_screen_cast_area_stream_src_enable (MetaScreenCastStreamSrc *src) -{ - MetaScreenCastAreaStreamSrc *area_src = - META_SCREEN_CAST_AREA_STREAM_SRC (src); - MetaBackend *backend = get_backend (area_src); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); - ClutterStage *stage; - MetaScreenCastStream *stream; - - stream = meta_screen_cast_stream_src_get_stream (src); - stage = get_stage (area_src); - - switch (meta_screen_cast_stream_get_cursor_mode (stream)) - { - case META_SCREEN_CAST_CURSOR_MODE_METADATA: - area_src->position_invalidated_handler_id = - g_signal_connect_after (cursor_tracker, "position-invalidated", - G_CALLBACK (pointer_position_invalidated), - area_src); - area_src->cursor_changed_handler_id = - g_signal_connect_after (cursor_tracker, "cursor-changed", - G_CALLBACK (cursor_changed), - area_src); - meta_cursor_tracker_track_position (cursor_tracker); - G_GNUC_FALLTHROUGH; - case META_SCREEN_CAST_CURSOR_MODE_HIDDEN: - add_view_painted_watches (area_src); - break; - case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED: - inhibit_hw_cursor (area_src); - meta_cursor_tracker_track_position (cursor_tracker); - add_view_painted_watches (area_src); - break; - } - - g_signal_connect_object (monitor_manager, "monitors-changed-internal", - G_CALLBACK (on_monitors_changed), - area_src, 0); - - clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); -} - -static void -meta_screen_cast_area_stream_src_disable (MetaScreenCastStreamSrc *src) -{ - MetaScreenCastAreaStreamSrc *area_src = - META_SCREEN_CAST_AREA_STREAM_SRC (src); - MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src); - MetaBackend *backend = get_backend (area_src); - MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); - ClutterStage *stage; - MetaStage *meta_stage; - GList *l; - - stage = get_stage (area_src); - meta_stage = META_STAGE (stage); - - for (l = area_src->watches; l; l = l->next) - { - MetaStageWatch *watch = l->data; - - meta_stage_remove_watch (meta_stage, watch); - } - g_clear_pointer (&area_src->watches, g_list_free); - - if (area_src->hw_cursor_inhibited) - uninhibit_hw_cursor (area_src); - - g_clear_signal_handler (&area_src->position_invalidated_handler_id, - cursor_tracker); - g_clear_signal_handler (&area_src->cursor_changed_handler_id, - cursor_tracker); - - g_clear_handle_id (&area_src->maybe_record_idle_id, g_source_remove); - - switch (meta_screen_cast_stream_get_cursor_mode (stream)) - { - case META_SCREEN_CAST_CURSOR_MODE_METADATA: - case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED: - meta_cursor_tracker_untrack_position (cursor_tracker); - break; - case META_SCREEN_CAST_CURSOR_MODE_HIDDEN: - break; - } -} - -static gboolean -meta_screen_cast_area_stream_src_record_to_buffer (MetaScreenCastStreamSrc *src, - int width, - int height, - int stride, - uint8_t *data, - GError **error) -{ - MetaScreenCastAreaStreamSrc *area_src = - META_SCREEN_CAST_AREA_STREAM_SRC (src); - MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src); - MetaScreenCastAreaStream *area_stream = META_SCREEN_CAST_AREA_STREAM (stream); - ClutterStage *stage; - MetaRectangle *area; - float scale; - ClutterPaintFlag paint_flags = CLUTTER_PAINT_FLAG_CLEAR; - - stage = get_stage (area_src); - area = meta_screen_cast_area_stream_get_area (area_stream); - scale = meta_screen_cast_area_stream_get_scale (area_stream); - - switch (meta_screen_cast_stream_get_cursor_mode (stream)) - { - case META_SCREEN_CAST_CURSOR_MODE_METADATA: - case META_SCREEN_CAST_CURSOR_MODE_HIDDEN: - paint_flags |= CLUTTER_PAINT_FLAG_NO_CURSORS; - break; - case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED: - paint_flags |= CLUTTER_PAINT_FLAG_FORCE_CURSORS; - break; - } - - if (!clutter_stage_paint_to_buffer (stage, area, scale, - data, - stride, - CLUTTER_CAIRO_FORMAT_ARGB32, - paint_flags, - error)) - return FALSE; - - return TRUE; -} - -static gboolean -meta_screen_cast_area_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc *src, - CoglFramebuffer *framebuffer, - GError **error) -{ - MetaScreenCastAreaStreamSrc *area_src = - META_SCREEN_CAST_AREA_STREAM_SRC (src); - MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src); - MetaScreenCastAreaStream *area_stream = META_SCREEN_CAST_AREA_STREAM (stream); - MetaBackend *backend = get_backend (area_src); - ClutterStage *stage; - MetaRectangle *area; - float scale; - ClutterPaintFlag paint_flags = CLUTTER_PAINT_FLAG_CLEAR; - - stage = CLUTTER_STAGE (meta_backend_get_stage (backend)); - area = meta_screen_cast_area_stream_get_area (area_stream); - scale = meta_screen_cast_area_stream_get_scale (area_stream); - - switch (meta_screen_cast_stream_get_cursor_mode (stream)) - { - case META_SCREEN_CAST_CURSOR_MODE_METADATA: - case META_SCREEN_CAST_CURSOR_MODE_HIDDEN: - paint_flags |= CLUTTER_PAINT_FLAG_NO_CURSORS; - break; - case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED: - paint_flags |= CLUTTER_PAINT_FLAG_FORCE_CURSORS; - break; - } - clutter_stage_paint_to_framebuffer (stage, framebuffer, - area, scale, - paint_flags); - - cogl_framebuffer_flush (framebuffer); - - return TRUE; -} - -static void -meta_screen_cast_area_stream_record_follow_up (MetaScreenCastStreamSrc *src) -{ - MetaScreenCastAreaStreamSrc *area_src = - META_SCREEN_CAST_AREA_STREAM_SRC (src); - MetaScreenCastRecordFlag flags; - - g_clear_handle_id (&area_src->maybe_record_idle_id, g_source_remove); - - flags = META_SCREEN_CAST_RECORD_FLAG_NONE; - meta_screen_cast_stream_src_maybe_record_frame (src, flags); -} - -static void -meta_screen_cast_area_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src, - struct spa_meta_cursor *spa_meta_cursor) -{ - MetaScreenCastAreaStreamSrc *area_src = - META_SCREEN_CAST_AREA_STREAM_SRC (src); - MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src); - MetaScreenCastAreaStream *area_stream = META_SCREEN_CAST_AREA_STREAM (stream); - MetaBackend *backend = get_backend (area_src); - MetaCursorRenderer *cursor_renderer = - meta_backend_get_cursor_renderer (backend); - MetaCursorTracker *cursor_tracker = - meta_backend_get_cursor_tracker (backend); - MetaCursorSprite *cursor_sprite; - MetaRectangle *area; - float scale; - graphene_point_t cursor_position; - int x, y; - - cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer); - - if (!meta_cursor_tracker_get_pointer_visible (cursor_tracker) || - !is_cursor_in_stream (area_src)) - { - meta_screen_cast_stream_src_unset_cursor_metadata (src, - spa_meta_cursor); - return; - } - - area = meta_screen_cast_area_stream_get_area (area_stream); - scale = meta_screen_cast_area_stream_get_scale (area_stream); - - meta_cursor_tracker_get_pointer (cursor_tracker, &cursor_position, NULL); - cursor_position.x -= area->x; - cursor_position.y -= area->y; - cursor_position.x *= scale; - cursor_position.y *= scale; - - x = (int) roundf (cursor_position.x); - y = (int) roundf (cursor_position.y); - - if (area_src->cursor_bitmap_invalid) - { - if (cursor_sprite) - { - float cursor_scale; - float metadata_scale; - - cursor_scale = meta_cursor_sprite_get_texture_scale (cursor_sprite); - metadata_scale = scale * cursor_scale; - meta_screen_cast_stream_src_set_cursor_sprite_metadata (src, - spa_meta_cursor, - cursor_sprite, - x, y, - metadata_scale); - } - else - { - meta_screen_cast_stream_src_set_empty_cursor_sprite_metadata (src, - spa_meta_cursor, - x, y); - } - - area_src->cursor_bitmap_invalid = FALSE; - } - else - { - meta_screen_cast_stream_src_set_cursor_position_metadata (src, - spa_meta_cursor, - x, y); - } -} - -static gboolean -meta_screen_cast_area_stream_src_is_cursor_inhibited (MetaHwCursorInhibitor *inhibitor) -{ - MetaScreenCastAreaStreamSrc *area_src = - META_SCREEN_CAST_AREA_STREAM_SRC (inhibitor); - - return is_cursor_in_stream (area_src); -} - -static void -hw_cursor_inhibitor_iface_init (MetaHwCursorInhibitorInterface *iface) -{ - iface->is_cursor_inhibited = - meta_screen_cast_area_stream_src_is_cursor_inhibited; -} - -MetaScreenCastAreaStreamSrc * -meta_screen_cast_area_stream_src_new (MetaScreenCastAreaStream *area_stream, - GError **error) -{ - return g_initable_new (META_TYPE_SCREEN_CAST_AREA_STREAM_SRC, NULL, error, - "stream", area_stream, - NULL); -} - -static void -meta_screen_cast_area_stream_src_init (MetaScreenCastAreaStreamSrc *area_src) -{ - area_src->cursor_bitmap_invalid = TRUE; -} - -static void -meta_screen_cast_area_stream_src_class_init (MetaScreenCastAreaStreamSrcClass *klass) -{ - MetaScreenCastStreamSrcClass *src_class = - META_SCREEN_CAST_STREAM_SRC_CLASS (klass); - - src_class->get_specs = meta_screen_cast_area_stream_src_get_specs; - src_class->enable = meta_screen_cast_area_stream_src_enable; - src_class->disable = meta_screen_cast_area_stream_src_disable; - src_class->record_to_buffer = - meta_screen_cast_area_stream_src_record_to_buffer; - src_class->record_to_framebuffer = - meta_screen_cast_area_stream_src_record_to_framebuffer; - src_class->record_follow_up = - meta_screen_cast_area_stream_record_follow_up; - src_class->set_cursor_metadata = - meta_screen_cast_area_stream_src_set_cursor_metadata; -} diff --git a/src/backends/meta-screen-cast-area-stream-src.h b/src/backends/meta-screen-cast-area-stream-src.h deleted file mode 100644 index 72261642c..000000000 --- a/src/backends/meta-screen-cast-area-stream-src.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2020 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_SCREEN_CAST_AREA_STREAM_SRC_H -#define META_SCREEN_CAST_AREA_STREAM_SRC_H - -#include "backends/meta-screen-cast-stream-src.h" - -typedef struct _MetaScreenCastAreaStream MetaScreenCastAreaStream; - -#define META_TYPE_SCREEN_CAST_AREA_STREAM_SRC (meta_screen_cast_area_stream_src_get_type ()) -G_DECLARE_FINAL_TYPE (MetaScreenCastAreaStreamSrc, - meta_screen_cast_area_stream_src, - META, SCREEN_CAST_AREA_STREAM_SRC, - MetaScreenCastStreamSrc) - -MetaScreenCastAreaStreamSrc * meta_screen_cast_area_stream_src_new (MetaScreenCastAreaStream *area_stream, - GError **error); - -#endif /* META_SCREEN_CAST_AREA_STREAM_SRC_H */ diff --git a/src/backends/meta-screen-cast-area-stream.c b/src/backends/meta-screen-cast-area-stream.c deleted file mode 100644 index 23d8c9828..000000000 --- a/src/backends/meta-screen-cast-area-stream.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2020 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "backends/meta-screen-cast-area-stream.h" - -#include "backends/meta-screen-cast-area-stream-src.h" - -struct _MetaScreenCastAreaStream -{ - MetaScreenCastStream parent; - - ClutterStage *stage; - - MetaRectangle area; - float scale; -}; - -G_DEFINE_TYPE (MetaScreenCastAreaStream, - meta_screen_cast_area_stream, - META_TYPE_SCREEN_CAST_STREAM) - -ClutterStage * -meta_screen_cast_area_stream_get_stage (MetaScreenCastAreaStream *area_stream) -{ - return area_stream->stage; -} - -MetaRectangle * -meta_screen_cast_area_stream_get_area (MetaScreenCastAreaStream *area_stream) -{ - return &area_stream->area; -} - -float -meta_screen_cast_area_stream_get_scale (MetaScreenCastAreaStream *area_stream) -{ - return area_stream->scale; -} - -static gboolean -calculate_scale (ClutterStage *stage, - MetaRectangle *area, - float *out_scale) -{ - GList *l; - float scale = 0.0; - - for (l = clutter_stage_peek_stage_views (stage); l; l = l->next) - { - ClutterStageView *stage_view = l->data; - MetaRectangle view_layout; - - clutter_stage_view_get_layout (stage_view, &view_layout); - if (meta_rectangle_overlap (area, &view_layout)) - scale = MAX (clutter_stage_view_get_scale (stage_view), scale); - } - - if (scale == 0.0) - return FALSE; - - *out_scale = scale; - return TRUE; -} - -MetaScreenCastAreaStream * -meta_screen_cast_area_stream_new (MetaScreenCastSession *session, - GDBusConnection *connection, - MetaRectangle *area, - ClutterStage *stage, - MetaScreenCastCursorMode cursor_mode, - MetaScreenCastFlag flags, - GError **error) -{ - MetaScreenCastAreaStream *area_stream; - float scale; - - if (!calculate_scale (stage, area, &scale)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Area is off-screen"); - return NULL; - } - - area_stream = g_initable_new (META_TYPE_SCREEN_CAST_AREA_STREAM, - NULL, - error, - "session", session, - "connection", connection, - "cursor-mode", cursor_mode, - "flags", flags, - NULL); - if (!area_stream) - return NULL; - - area_stream->area = *area; - area_stream->scale = scale; - area_stream->stage = stage; - - return area_stream; -} - -static MetaScreenCastStreamSrc * -meta_screen_cast_area_stream_create_src (MetaScreenCastStream *stream, - GError **error) -{ - MetaScreenCastAreaStream *area_stream = - META_SCREEN_CAST_AREA_STREAM (stream); - MetaScreenCastAreaStreamSrc *area_stream_src; - - area_stream_src = meta_screen_cast_area_stream_src_new (area_stream, - error); - if (!area_stream_src) - return NULL; - - return META_SCREEN_CAST_STREAM_SRC (area_stream_src); -} - -static void -meta_screen_cast_area_stream_set_parameters (MetaScreenCastStream *stream, - GVariantBuilder *parameters_builder) -{ - MetaScreenCastAreaStream *area_stream = - META_SCREEN_CAST_AREA_STREAM (stream); - - g_variant_builder_add (parameters_builder, "{sv}", - "size", - g_variant_new ("(ii)", - area_stream->area.width, - area_stream->area.height)); -} - -static gboolean -meta_screen_cast_area_stream_transform_position (MetaScreenCastStream *stream, - double stream_x, - double stream_y, - double *x, - double *y) -{ - MetaScreenCastAreaStream *area_stream = - META_SCREEN_CAST_AREA_STREAM (stream); - - *x = area_stream->area.x + (int) roundf (stream_x / area_stream->scale); - *y = area_stream->area.y + (int) roundf (stream_y / area_stream->scale); - - return TRUE; -} - -static void -meta_screen_cast_area_stream_init (MetaScreenCastAreaStream *area_stream) -{ -} - -static void -meta_screen_cast_area_stream_class_init (MetaScreenCastAreaStreamClass *klass) -{ - MetaScreenCastStreamClass *stream_class = - META_SCREEN_CAST_STREAM_CLASS (klass); - - stream_class->create_src = meta_screen_cast_area_stream_create_src; - stream_class->set_parameters = meta_screen_cast_area_stream_set_parameters; - stream_class->transform_position = meta_screen_cast_area_stream_transform_position; -} diff --git a/src/backends/meta-screen-cast-area-stream.h b/src/backends/meta-screen-cast-area-stream.h deleted file mode 100644 index b11ec1fb9..000000000 --- a/src/backends/meta-screen-cast-area-stream.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2020 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_SCREEN_CAST_AREA_STREAM_H -#define META_SCREEN_CAST_AREA_STREAM_H - -#include - -#include "backends/meta-screen-cast-stream.h" -#include "backends/meta-screen-cast.h" - -#define META_TYPE_SCREEN_CAST_AREA_STREAM (meta_screen_cast_area_stream_get_type ()) -G_DECLARE_FINAL_TYPE (MetaScreenCastAreaStream, - meta_screen_cast_area_stream, - META, SCREEN_CAST_AREA_STREAM, - MetaScreenCastStream) - -MetaScreenCastAreaStream * meta_screen_cast_area_stream_new (MetaScreenCastSession *session, - GDBusConnection *connection, - MetaRectangle *area, - ClutterStage *stage, - MetaScreenCastCursorMode cursor_mode, - MetaScreenCastFlag flags, - GError **error); - -ClutterStage * meta_screen_cast_area_stream_get_stage (MetaScreenCastAreaStream *area_stream); - -MetaRectangle * meta_screen_cast_area_stream_get_area (MetaScreenCastAreaStream *area_stream); - -float meta_screen_cast_area_stream_get_scale (MetaScreenCastAreaStream *area_stream); - -#endif /* META_SCREEN_CAST_AREA_STREAM_H */ diff --git a/src/backends/meta-screen-cast-monitor-stream-src.c b/src/backends/meta-screen-cast-monitor-stream-src.c deleted file mode 100644 index b85c44fe1..000000000 --- a/src/backends/meta-screen-cast-monitor-stream-src.c +++ /dev/null @@ -1,793 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "backends/meta-screen-cast-monitor-stream-src.h" - -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-cursor-tracker-private.h" -#include "backends/meta-logical-monitor.h" -#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" - -struct _MetaScreenCastMonitorStreamSrc -{ - MetaScreenCastStreamSrc parent; - - gboolean cursor_bitmap_invalid; - gboolean hw_cursor_inhibited; - - GList *watches; - - gulong position_invalidated_handler_id; - gulong cursor_changed_handler_id; -}; - -static void -hw_cursor_inhibitor_iface_init (MetaHwCursorInhibitorInterface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaScreenCastMonitorStreamSrc, - meta_screen_cast_monitor_stream_src, - META_TYPE_SCREEN_CAST_STREAM_SRC, - G_IMPLEMENT_INTERFACE (META_TYPE_HW_CURSOR_INHIBITOR, - hw_cursor_inhibitor_iface_init)) - -static ClutterStage * -get_stage (MetaScreenCastMonitorStreamSrc *monitor_src) -{ - MetaScreenCastStreamSrc *src; - MetaScreenCastStream *stream; - MetaScreenCastMonitorStream *monitor_stream; - - src = META_SCREEN_CAST_STREAM_SRC (monitor_src); - stream = meta_screen_cast_stream_src_get_stream (src); - monitor_stream = META_SCREEN_CAST_MONITOR_STREAM (stream); - - return meta_screen_cast_monitor_stream_get_stage (monitor_stream); -} - -static MetaMonitor * -get_monitor (MetaScreenCastMonitorStreamSrc *monitor_src) -{ - MetaScreenCastStreamSrc *src; - MetaScreenCastStream *stream; - MetaScreenCastMonitorStream *monitor_stream; - - src = META_SCREEN_CAST_STREAM_SRC (monitor_src); - stream = meta_screen_cast_stream_src_get_stream (src); - monitor_stream = META_SCREEN_CAST_MONITOR_STREAM (stream); - - return meta_screen_cast_monitor_stream_get_monitor (monitor_stream); -} - -static gboolean -meta_screen_cast_monitor_stream_src_get_specs (MetaScreenCastStreamSrc *src, - int *width, - int *height, - float *frame_rate) -{ - MetaScreenCastMonitorStreamSrc *monitor_src = - META_SCREEN_CAST_MONITOR_STREAM_SRC (src); - MetaMonitor *monitor; - MetaLogicalMonitor *logical_monitor; - float scale; - MetaMonitorMode *mode; - - monitor = get_monitor (monitor_src); - logical_monitor = meta_monitor_get_logical_monitor (monitor); - mode = meta_monitor_get_current_mode (monitor); - - if (meta_is_stage_views_scaled ()) - scale = logical_monitor->scale; - else - scale = 1.0; - - *width = (int) roundf (logical_monitor->rect.width * scale); - *height = (int) roundf (logical_monitor->rect.height * scale); - *frame_rate = meta_monitor_mode_get_refresh_rate (mode); - - return TRUE; -} - -static void -stage_painted (MetaStage *stage, - ClutterStageView *view, - ClutterPaintContext *paint_context, - gpointer user_data) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (user_data); - MetaScreenCastRecordFlag flags; - - flags = META_SCREEN_CAST_RECORD_FLAG_NONE; - meta_screen_cast_stream_src_maybe_record_frame (src, flags); -} - -static void -before_stage_painted (MetaStage *stage, - ClutterStageView *view, - ClutterPaintContext *paint_context, - gpointer user_data) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (user_data); - CoglScanout *scanout; - - scanout = clutter_stage_view_peek_scanout (view); - if (scanout) - { - MetaScreenCastRecordFlag flags; - - flags = META_SCREEN_CAST_RECORD_FLAG_NONE; - meta_screen_cast_stream_src_maybe_record_frame (src, flags); - } -} - -static MetaBackend * -get_backend (MetaScreenCastMonitorStreamSrc *monitor_src) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (monitor_src); - MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src); - MetaScreenCastSession *session = meta_screen_cast_stream_get_session (stream); - MetaScreenCast *screen_cast = - meta_screen_cast_session_get_screen_cast (session); - - return meta_screen_cast_get_backend (screen_cast); -} - -static gboolean -is_cursor_in_stream (MetaScreenCastMonitorStreamSrc *monitor_src) -{ - MetaBackend *backend = get_backend (monitor_src); - MetaCursorRenderer *cursor_renderer = - meta_backend_get_cursor_renderer (backend); - MetaMonitor *monitor; - MetaLogicalMonitor *logical_monitor; - MetaRectangle logical_monitor_layout; - graphene_rect_t logical_monitor_rect; - MetaCursorSprite *cursor_sprite; - - monitor = get_monitor (monitor_src); - logical_monitor = meta_monitor_get_logical_monitor (monitor); - logical_monitor_layout = meta_logical_monitor_get_layout (logical_monitor); - logical_monitor_rect = - meta_rectangle_to_graphene_rect (&logical_monitor_layout); - - cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer); - if (cursor_sprite) - { - graphene_rect_t cursor_rect; - - cursor_rect = meta_cursor_renderer_calculate_rect (cursor_renderer, - cursor_sprite); - return graphene_rect_intersection (&cursor_rect, - &logical_monitor_rect, - NULL); - } - else - { - MetaCursorTracker *cursor_tracker = - meta_backend_get_cursor_tracker (backend); - graphene_point_t cursor_position; - - meta_cursor_tracker_get_pointer (cursor_tracker, &cursor_position, NULL); - return graphene_rect_contains_point (&logical_monitor_rect, - &cursor_position); - } -} - -static gboolean -is_redraw_queued (MetaScreenCastMonitorStreamSrc *monitor_src) -{ - MetaBackend *backend = get_backend (monitor_src); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - ClutterStage *stage = get_stage (monitor_src); - MetaMonitor *monitor = get_monitor (monitor_src); - g_autoptr (GList) views = NULL; - GList *l; - - views = meta_renderer_get_views_for_monitor (renderer, monitor); - for (l = views; l; l = l->next) - { - MetaRendererView *view = l->data; - - if (clutter_stage_is_redraw_queued_on_view (stage, CLUTTER_STAGE_VIEW (view))) - return TRUE; - } - - return FALSE; -} - -static void -sync_cursor_state (MetaScreenCastMonitorStreamSrc *monitor_src) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (monitor_src); - MetaScreenCastRecordFlag flags; - - if (is_redraw_queued (monitor_src)) - return; - - if (meta_screen_cast_stream_src_pending_follow_up_frame (src)) - return; - - flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY; - meta_screen_cast_stream_src_maybe_record_frame (src, flags); -} - -static void -pointer_position_invalidated (MetaCursorTracker *cursor_tracker, - MetaScreenCastMonitorStreamSrc *monitor_src) -{ - sync_cursor_state (monitor_src); -} - -static void -cursor_changed (MetaCursorTracker *cursor_tracker, - MetaScreenCastMonitorStreamSrc *monitor_src) -{ - monitor_src->cursor_bitmap_invalid = TRUE; - sync_cursor_state (monitor_src); -} - -static void -inhibit_hw_cursor (MetaScreenCastMonitorStreamSrc *monitor_src) -{ - MetaHwCursorInhibitor *inhibitor; - MetaBackend *backend; - - g_return_if_fail (!monitor_src->hw_cursor_inhibited); - - backend = get_backend (monitor_src); - inhibitor = META_HW_CURSOR_INHIBITOR (monitor_src); - meta_backend_add_hw_cursor_inhibitor (backend, inhibitor); - - monitor_src->hw_cursor_inhibited = TRUE; -} - -static void -uninhibit_hw_cursor (MetaScreenCastMonitorStreamSrc *monitor_src) -{ - MetaHwCursorInhibitor *inhibitor; - MetaBackend *backend; - - g_return_if_fail (monitor_src->hw_cursor_inhibited); - - backend = get_backend (monitor_src); - inhibitor = META_HW_CURSOR_INHIBITOR (monitor_src); - meta_backend_remove_hw_cursor_inhibitor (backend, inhibitor); - - monitor_src->hw_cursor_inhibited = FALSE; -} - -static void -add_view_watches (MetaScreenCastMonitorStreamSrc *monitor_src, - MetaStageWatchPhase watch_phase, - MetaStageWatchFunc callback) -{ - MetaBackend *backend = get_backend (monitor_src); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - ClutterStage *stage; - MetaStage *meta_stage; - MetaMonitor *monitor; - MetaLogicalMonitor *logical_monitor; - MetaRectangle logical_monitor_layout; - GList *l; - - stage = get_stage (monitor_src); - meta_stage = META_STAGE (stage); - monitor = get_monitor (monitor_src); - logical_monitor = meta_monitor_get_logical_monitor (monitor); - logical_monitor_layout = meta_logical_monitor_get_layout (logical_monitor); - - for (l = meta_renderer_get_views (renderer); l; l = l->next) - { - MetaRendererView *view = l->data; - MetaRectangle view_layout; - - clutter_stage_view_get_layout (CLUTTER_STAGE_VIEW (view), &view_layout); - if (meta_rectangle_overlap (&logical_monitor_layout, &view_layout)) - { - MetaStageWatch *watch; - - watch = meta_stage_watch_view (meta_stage, - CLUTTER_STAGE_VIEW (view), - watch_phase, - callback, - monitor_src); - - monitor_src->watches = g_list_prepend (monitor_src->watches, watch); - } - } -} - -static void -reattach_watches (MetaScreenCastMonitorStreamSrc *monitor_src) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (monitor_src); - MetaScreenCastStream *stream; - ClutterStage *stage; - GList *l; - - stream = meta_screen_cast_stream_src_get_stream (src); - stage = get_stage (monitor_src); - - for (l = monitor_src->watches; l; l = l->next) - meta_stage_remove_watch (META_STAGE (stage), l->data); - g_clear_pointer (&monitor_src->watches, g_list_free); - - switch (meta_screen_cast_stream_get_cursor_mode (stream)) - { - case META_SCREEN_CAST_CURSOR_MODE_METADATA: - case META_SCREEN_CAST_CURSOR_MODE_HIDDEN: - add_view_watches (monitor_src, - META_STAGE_WATCH_BEFORE_PAINT, - before_stage_painted); - add_view_watches (monitor_src, - META_STAGE_WATCH_AFTER_ACTOR_PAINT, - stage_painted); - break; - case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED: - add_view_watches (monitor_src, - META_STAGE_WATCH_AFTER_PAINT, - stage_painted); - break; - } -} - -static void -on_monitors_changed (MetaMonitorManager *monitor_manager, - MetaScreenCastMonitorStreamSrc *monitor_src) -{ - reattach_watches (monitor_src); -} - -static void -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); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); - MetaScreenCastStream *stream; - - stream = meta_screen_cast_stream_src_get_stream (src); - - switch (meta_screen_cast_stream_get_cursor_mode (stream)) - { - case META_SCREEN_CAST_CURSOR_MODE_METADATA: - monitor_src->position_invalidated_handler_id = - g_signal_connect_after (cursor_tracker, "position-invalidated", - G_CALLBACK (pointer_position_invalidated), - monitor_src); - monitor_src->cursor_changed_handler_id = - g_signal_connect_after (cursor_tracker, "cursor-changed", - G_CALLBACK (cursor_changed), - monitor_src); - meta_cursor_tracker_track_position (cursor_tracker); - break; - case META_SCREEN_CAST_CURSOR_MODE_HIDDEN: - break; - case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED: - inhibit_hw_cursor (monitor_src); - meta_cursor_tracker_track_position (cursor_tracker); - break; - } - - reattach_watches (monitor_src); - g_signal_connect_object (monitor_manager, "monitors-changed-internal", - G_CALLBACK (on_monitors_changed), - monitor_src, 0); - - clutter_actor_queue_redraw (CLUTTER_ACTOR (get_stage (monitor_src))); -} - -static void -meta_screen_cast_monitor_stream_src_disable (MetaScreenCastStreamSrc *src) -{ - MetaScreenCastMonitorStreamSrc *monitor_src = - META_SCREEN_CAST_MONITOR_STREAM_SRC (src); - MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src); - MetaBackend *backend = get_backend (monitor_src); - MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); - ClutterStage *stage; - MetaStage *meta_stage; - GList *l; - - stage = get_stage (monitor_src); - meta_stage = META_STAGE (stage); - - for (l = monitor_src->watches; l; l = l->next) - { - MetaStageWatch *watch = l->data; - - meta_stage_remove_watch (meta_stage, watch); - } - g_clear_pointer (&monitor_src->watches, g_list_free); - - if (monitor_src->hw_cursor_inhibited) - uninhibit_hw_cursor (monitor_src); - - g_clear_signal_handler (&monitor_src->position_invalidated_handler_id, - cursor_tracker); - g_clear_signal_handler (&monitor_src->cursor_changed_handler_id, - cursor_tracker); - - switch (meta_screen_cast_stream_get_cursor_mode (stream)) - { - case META_SCREEN_CAST_CURSOR_MODE_METADATA: - case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED: - meta_cursor_tracker_untrack_position (cursor_tracker); - break; - case META_SCREEN_CAST_CURSOR_MODE_HIDDEN: - break; - } -} - -static void -maybe_paint_cursor_sprite (MetaScreenCastMonitorStreamSrc *monitor_src, - int width, - int height, - int stride, - uint8_t *data) -{ - MetaBackend *backend = get_backend (monitor_src); - MetaCursorRenderer *cursor_renderer = - meta_backend_get_cursor_renderer (backend); - MetaCursorSprite *cursor_sprite; - CoglTexture *sprite_texture; - int sprite_width, sprite_height, sprite_stride; - float sprite_scale; - uint8_t *sprite_data; - cairo_surface_t *sprite_surface; - graphene_rect_t sprite_rect; - cairo_surface_t *surface; - cairo_t *cr; - - if (!is_cursor_in_stream (monitor_src)) - return; - - cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer); - if (!cursor_sprite) - return; - - if (meta_cursor_renderer_is_overlay_visible (cursor_renderer)) - return; - - sprite_rect = meta_cursor_renderer_calculate_rect (cursor_renderer, - cursor_sprite); - sprite_texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); - sprite_width = cogl_texture_get_width (sprite_texture); - sprite_height = cogl_texture_get_height (sprite_texture); - sprite_stride = sprite_width * 4; - sprite_scale = meta_cursor_sprite_get_texture_scale (cursor_sprite); - sprite_data = g_new0 (uint8_t, sprite_stride * sprite_height); - cogl_texture_get_data (sprite_texture, - CLUTTER_CAIRO_FORMAT_ARGB32, - sprite_stride, - sprite_data); - sprite_surface = cairo_image_surface_create_for_data (sprite_data, - CAIRO_FORMAT_ARGB32, - sprite_width, - sprite_height, - sprite_stride); - cairo_surface_set_device_scale (sprite_surface, sprite_scale, sprite_scale); - - surface = cairo_image_surface_create_for_data (data, - CAIRO_FORMAT_ARGB32, - width, height, stride); - - cr = cairo_create (surface); - cairo_set_source_surface (cr, sprite_surface, - sprite_rect.origin.x, - sprite_rect.origin.y); - cairo_paint (cr); - cairo_destroy (cr); - cairo_surface_destroy (sprite_surface); - cairo_surface_destroy (surface); - g_free (sprite_data); -} - -static gboolean -meta_screen_cast_monitor_stream_src_record_to_buffer (MetaScreenCastStreamSrc *src, - int width, - int height, - int stride, - uint8_t *data, - GError **error) -{ - MetaScreenCastMonitorStreamSrc *monitor_src = - META_SCREEN_CAST_MONITOR_STREAM_SRC (src); - MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src); - ClutterStage *stage; - MetaMonitor *monitor; - MetaLogicalMonitor *logical_monitor; - float scale; - - monitor = get_monitor (monitor_src); - logical_monitor = meta_monitor_get_logical_monitor (monitor); - stage = get_stage (monitor_src); - - if (meta_is_stage_views_scaled ()) - scale = meta_logical_monitor_get_scale (logical_monitor); - else - scale = 1.0; - - clutter_stage_capture_into (stage, &logical_monitor->rect, scale, data, stride); - - switch (meta_screen_cast_stream_get_cursor_mode (stream)) - { - case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED: - maybe_paint_cursor_sprite (monitor_src, width, height, stride, data); - break; - case META_SCREEN_CAST_CURSOR_MODE_METADATA: - case META_SCREEN_CAST_CURSOR_MODE_HIDDEN: - break; - } - - return TRUE; -} - -static gboolean -meta_screen_cast_monitor_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc *src, - CoglFramebuffer *framebuffer, - GError **error) -{ - MetaScreenCastMonitorStreamSrc *monitor_src = - META_SCREEN_CAST_MONITOR_STREAM_SRC (src); - MetaBackend *backend = get_backend (monitor_src); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - MetaMonitor *monitor; - MetaLogicalMonitor *logical_monitor; - MetaRectangle logical_monitor_layout; - GList *l; - float view_scale; - - monitor = get_monitor (monitor_src); - logical_monitor = meta_monitor_get_logical_monitor (monitor); - logical_monitor_layout = meta_logical_monitor_get_layout (logical_monitor); - - if (meta_is_stage_views_scaled ()) - view_scale = meta_logical_monitor_get_scale (logical_monitor); - else - view_scale = 1.0; - - for (l = meta_renderer_get_views (renderer); l; l = l->next) - { - ClutterStageView *view = CLUTTER_STAGE_VIEW (l->data); - CoglFramebuffer *view_framebuffer; - CoglScanout *scanout; - MetaRectangle view_layout; - int x, y; - - clutter_stage_view_get_layout (view, &view_layout); - - if (!meta_rectangle_overlap (&logical_monitor_layout, &view_layout)) - continue; - - x = (int) roundf ((view_layout.x - logical_monitor_layout.x) * view_scale); - y = (int) roundf ((view_layout.y - logical_monitor_layout.y) * view_scale); - - scanout = clutter_stage_view_peek_scanout (view); - if (scanout) - { - if (!cogl_scanout_blit_to_framebuffer (scanout, - framebuffer, - x, y, - error)) - return FALSE; - } - else - { - view_framebuffer = clutter_stage_view_get_framebuffer (view); - if (!cogl_blit_framebuffer (view_framebuffer, - framebuffer, - 0, 0, - x, y, - cogl_framebuffer_get_width (view_framebuffer), - cogl_framebuffer_get_height (view_framebuffer), - error)) - return FALSE; - } - } - - cogl_framebuffer_flush (framebuffer); - - return TRUE; -} - -static void -meta_screen_cast_monitor_stream_record_follow_up (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); - ClutterStage *stage = get_stage (monitor_src); - MetaMonitor *monitor; - MetaLogicalMonitor *logical_monitor; - MetaRectangle logical_monitor_layout; - GList *l; - - monitor = get_monitor (monitor_src); - logical_monitor = meta_monitor_get_logical_monitor (monitor); - logical_monitor_layout = meta_logical_monitor_get_layout (logical_monitor); - - for (l = meta_renderer_get_views (renderer); l; l = l->next) - { - MetaRendererView *view = l->data; - MetaRectangle view_layout; - MetaRectangle damage; - - clutter_stage_view_get_layout (CLUTTER_STAGE_VIEW (view), &view_layout); - - if (!meta_rectangle_overlap (&logical_monitor_layout, &view_layout)) - continue; - - damage = (cairo_rectangle_int_t) { - .x = view_layout.x, - .y = view_layout.y, - .width = 1, - .height = 1, - }; - clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &damage); - } -} - -static void -meta_screen_cast_monitor_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src, - struct spa_meta_cursor *spa_meta_cursor) -{ - MetaScreenCastMonitorStreamSrc *monitor_src = - META_SCREEN_CAST_MONITOR_STREAM_SRC (src); - MetaBackend *backend = get_backend (monitor_src); - MetaCursorRenderer *cursor_renderer = - meta_backend_get_cursor_renderer (backend); - MetaCursorTracker *cursor_tracker = - meta_backend_get_cursor_tracker (backend); - MetaCursorSprite *cursor_sprite; - MetaMonitor *monitor; - MetaLogicalMonitor *logical_monitor; - MetaRectangle logical_monitor_layout; - graphene_rect_t logical_monitor_rect; - float view_scale; - graphene_point_t cursor_position; - int x, y; - - cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer); - - if (!meta_cursor_tracker_get_pointer_visible (cursor_tracker) || - !is_cursor_in_stream (monitor_src)) - { - meta_screen_cast_stream_src_unset_cursor_metadata (src, - spa_meta_cursor); - return; - } - - monitor = get_monitor (monitor_src); - logical_monitor = meta_monitor_get_logical_monitor (monitor); - logical_monitor_layout = meta_logical_monitor_get_layout (logical_monitor); - logical_monitor_rect = - meta_rectangle_to_graphene_rect (&logical_monitor_layout); - - if (meta_is_stage_views_scaled ()) - view_scale = meta_logical_monitor_get_scale (logical_monitor); - else - view_scale = 1.0; - - meta_cursor_tracker_get_pointer (cursor_tracker, &cursor_position, NULL); - cursor_position.x -= logical_monitor_rect.origin.x; - cursor_position.y -= logical_monitor_rect.origin.y; - cursor_position.x *= view_scale; - cursor_position.y *= view_scale; - - x = (int) roundf (cursor_position.x); - y = (int) roundf (cursor_position.y); - - if (monitor_src->cursor_bitmap_invalid) - { - if (cursor_sprite) - { - float cursor_scale; - float scale; - - cursor_scale = meta_cursor_sprite_get_texture_scale (cursor_sprite); - scale = view_scale * cursor_scale; - meta_screen_cast_stream_src_set_cursor_sprite_metadata (src, - spa_meta_cursor, - cursor_sprite, - x, y, - scale); - } - else - { - meta_screen_cast_stream_src_set_empty_cursor_sprite_metadata (src, - spa_meta_cursor, - x, y); - } - - monitor_src->cursor_bitmap_invalid = FALSE; - } - else - { - meta_screen_cast_stream_src_set_cursor_position_metadata (src, - spa_meta_cursor, - x, y); - } -} - -static gboolean -meta_screen_cast_monitor_stream_src_is_cursor_inhibited (MetaHwCursorInhibitor *inhibitor) -{ - MetaScreenCastMonitorStreamSrc *monitor_src = - META_SCREEN_CAST_MONITOR_STREAM_SRC (inhibitor); - - return is_cursor_in_stream (monitor_src); -} - -static void -hw_cursor_inhibitor_iface_init (MetaHwCursorInhibitorInterface *iface) -{ - iface->is_cursor_inhibited = - meta_screen_cast_monitor_stream_src_is_cursor_inhibited; -} - -MetaScreenCastMonitorStreamSrc * -meta_screen_cast_monitor_stream_src_new (MetaScreenCastMonitorStream *monitor_stream, - GError **error) -{ - return g_initable_new (META_TYPE_SCREEN_CAST_MONITOR_STREAM_SRC, NULL, error, - "stream", monitor_stream, - NULL); -} - -static void -meta_screen_cast_monitor_stream_src_init (MetaScreenCastMonitorStreamSrc *monitor_src) -{ - monitor_src->cursor_bitmap_invalid = TRUE; -} - -static void -meta_screen_cast_monitor_stream_src_class_init (MetaScreenCastMonitorStreamSrcClass *klass) -{ - MetaScreenCastStreamSrcClass *src_class = - META_SCREEN_CAST_STREAM_SRC_CLASS (klass); - - src_class->get_specs = meta_screen_cast_monitor_stream_src_get_specs; - src_class->enable = meta_screen_cast_monitor_stream_src_enable; - src_class->disable = meta_screen_cast_monitor_stream_src_disable; - src_class->record_to_buffer = - meta_screen_cast_monitor_stream_src_record_to_buffer; - src_class->record_to_framebuffer = - meta_screen_cast_monitor_stream_src_record_to_framebuffer; - src_class->record_follow_up = - meta_screen_cast_monitor_stream_record_follow_up; - src_class->set_cursor_metadata = - meta_screen_cast_monitor_stream_src_set_cursor_metadata; -} diff --git a/src/backends/meta-screen-cast-monitor-stream-src.h b/src/backends/meta-screen-cast-monitor-stream-src.h deleted file mode 100644 index 7417a81e0..000000000 --- a/src/backends/meta-screen-cast-monitor-stream-src.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_SCREEN_CAST_MONITOR_STREAM_SRC_H -#define META_SCREEN_CAST_MONITOR_STREAM_SRC_H - -#include "backends/meta-monitor-manager-private.h" -#include "backends/meta-screen-cast-stream-src.h" - -typedef struct _MetaScreenCastMonitorStream MetaScreenCastMonitorStream; - -#define META_TYPE_SCREEN_CAST_MONITOR_STREAM_SRC (meta_screen_cast_monitor_stream_src_get_type ()) -G_DECLARE_FINAL_TYPE (MetaScreenCastMonitorStreamSrc, - meta_screen_cast_monitor_stream_src, - META, SCREEN_CAST_MONITOR_STREAM_SRC, - MetaScreenCastStreamSrc) - -MetaScreenCastMonitorStreamSrc * meta_screen_cast_monitor_stream_src_new (MetaScreenCastMonitorStream *monitor_stream, - GError **error); - -#endif /* META_SCREEN_CAST_MONITOR_STREAM_SRC_H */ diff --git a/src/backends/meta-screen-cast-monitor-stream.c b/src/backends/meta-screen-cast-monitor-stream.c deleted file mode 100644 index ada9bc95f..000000000 --- a/src/backends/meta-screen-cast-monitor-stream.c +++ /dev/null @@ -1,295 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "backends/meta-screen-cast-monitor-stream.h" - -#include "backends/meta-logical-monitor.h" -#include "backends/meta-screen-cast-monitor-stream-src.h" - -enum -{ - PROP_0, - - PROP_MONITOR, -}; - -struct _MetaScreenCastMonitorStream -{ - MetaScreenCastStream parent; - - ClutterStage *stage; - - MetaMonitor *monitor; - MetaLogicalMonitor *logical_monitor; -}; - -G_DEFINE_TYPE (MetaScreenCastMonitorStream, - meta_screen_cast_monitor_stream, - META_TYPE_SCREEN_CAST_STREAM) - -static gboolean -update_monitor (MetaScreenCastMonitorStream *monitor_stream, - MetaMonitor *new_monitor) -{ - MetaLogicalMonitor *new_logical_monitor; - - new_logical_monitor = meta_monitor_get_logical_monitor (new_monitor); - if (!new_logical_monitor) - return FALSE; - - if (!meta_rectangle_equal (&new_logical_monitor->rect, - &monitor_stream->logical_monitor->rect)) - return FALSE; - - g_set_object (&monitor_stream->monitor, new_monitor); - g_set_object (&monitor_stream->logical_monitor, new_logical_monitor); - - return TRUE; -} - -static void -on_monitors_changed (MetaMonitorManager *monitor_manager, - MetaScreenCastMonitorStream *monitor_stream) -{ - MetaMonitor *new_monitor = NULL; - GList *monitors; - GList *l; - - monitors = meta_monitor_manager_get_monitors (monitor_manager); - for (l = monitors; l; l = l->next) - { - MetaMonitor *other_monitor = l->data; - - if (meta_monitor_is_same_as (monitor_stream->monitor, other_monitor)) - { - new_monitor = other_monitor; - break; - } - } - - if (!new_monitor || !update_monitor (monitor_stream, new_monitor)) - meta_screen_cast_stream_close (META_SCREEN_CAST_STREAM (monitor_stream)); -} - -ClutterStage * -meta_screen_cast_monitor_stream_get_stage (MetaScreenCastMonitorStream *monitor_stream) -{ - return monitor_stream->stage; -} - -MetaMonitor * -meta_screen_cast_monitor_stream_get_monitor (MetaScreenCastMonitorStream *monitor_stream) -{ - return monitor_stream->monitor; -} - -MetaScreenCastMonitorStream * -meta_screen_cast_monitor_stream_new (MetaScreenCastSession *session, - GDBusConnection *connection, - MetaMonitor *monitor, - ClutterStage *stage, - MetaScreenCastCursorMode cursor_mode, - MetaScreenCastFlag flags, - GError **error) -{ - MetaBackend *backend = meta_monitor_get_backend (monitor); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaScreenCastMonitorStream *monitor_stream; - - if (!meta_monitor_is_active (monitor)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Monitor not active"); - return NULL; - } - - monitor_stream = g_initable_new (META_TYPE_SCREEN_CAST_MONITOR_STREAM, - NULL, - error, - "session", session, - "connection", connection, - "cursor-mode", cursor_mode, - "flags", flags, - "monitor", monitor, - NULL); - if (!monitor_stream) - return NULL; - - monitor_stream->stage = stage; - - g_signal_connect_object (monitor_manager, "monitors-changed-internal", - G_CALLBACK (on_monitors_changed), - monitor_stream, 0); - - return monitor_stream; -} - -static MetaScreenCastStreamSrc * -meta_screen_cast_monitor_stream_create_src (MetaScreenCastStream *stream, - GError **error) -{ - MetaScreenCastMonitorStream *monitor_stream = - META_SCREEN_CAST_MONITOR_STREAM (stream); - MetaScreenCastMonitorStreamSrc *monitor_stream_src; - - monitor_stream_src = meta_screen_cast_monitor_stream_src_new (monitor_stream, - error); - if (!monitor_stream_src) - return NULL; - - return META_SCREEN_CAST_STREAM_SRC (monitor_stream_src); -} - -static void -meta_screen_cast_monitor_stream_set_parameters (MetaScreenCastStream *stream, - GVariantBuilder *parameters_builder) -{ - MetaScreenCastMonitorStream *monitor_stream = - META_SCREEN_CAST_MONITOR_STREAM (stream); - MetaRectangle logical_monitor_layout; - - logical_monitor_layout = - meta_logical_monitor_get_layout (monitor_stream->logical_monitor); - - g_variant_builder_add (parameters_builder, "{sv}", - "position", - g_variant_new ("(ii)", - logical_monitor_layout.x, - logical_monitor_layout.y)); - g_variant_builder_add (parameters_builder, "{sv}", - "size", - g_variant_new ("(ii)", - logical_monitor_layout.width, - logical_monitor_layout.height)); -} - -static gboolean -meta_screen_cast_monitor_stream_transform_position (MetaScreenCastStream *stream, - double stream_x, - double stream_y, - double *x, - double *y) -{ - MetaScreenCastMonitorStream *monitor_stream = - META_SCREEN_CAST_MONITOR_STREAM (stream); - MetaRectangle logical_monitor_layout; - double scale; - - logical_monitor_layout = - meta_logical_monitor_get_layout (monitor_stream->logical_monitor); - - if (meta_is_stage_views_scaled ()) - scale = meta_logical_monitor_get_scale (monitor_stream->logical_monitor); - else - scale = 1.0; - - *x = logical_monitor_layout.x + stream_x / scale; - *y = logical_monitor_layout.y + stream_y / scale; - - return TRUE; -} - -static void -meta_screen_cast_monitor_stream_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaScreenCastMonitorStream *monitor_stream = - META_SCREEN_CAST_MONITOR_STREAM (object); - MetaLogicalMonitor *logical_monitor; - - switch (prop_id) - { - case PROP_MONITOR: - g_set_object (&monitor_stream->monitor, g_value_get_object (value)); - logical_monitor = meta_monitor_get_logical_monitor (monitor_stream->monitor); - g_set_object (&monitor_stream->logical_monitor, logical_monitor); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_screen_cast_monitor_stream_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaScreenCastMonitorStream *monitor_stream = - META_SCREEN_CAST_MONITOR_STREAM (object); - - switch (prop_id) - { - case PROP_MONITOR: - g_value_set_object (value, monitor_stream->monitor); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_screen_cast_monitor_stream_finalize (GObject *object) -{ - MetaScreenCastMonitorStream *monitor_stream = - META_SCREEN_CAST_MONITOR_STREAM (object); - - g_clear_object (&monitor_stream->monitor); - g_clear_object (&monitor_stream->logical_monitor); - - G_OBJECT_CLASS (meta_screen_cast_monitor_stream_parent_class)->finalize (object); -} - -static void -meta_screen_cast_monitor_stream_init (MetaScreenCastMonitorStream *monitor_stream) -{ -} - -static void -meta_screen_cast_monitor_stream_class_init (MetaScreenCastMonitorStreamClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaScreenCastStreamClass *stream_class = - META_SCREEN_CAST_STREAM_CLASS (klass); - - object_class->set_property = meta_screen_cast_monitor_stream_set_property; - object_class->get_property = meta_screen_cast_monitor_stream_get_property; - object_class->finalize = meta_screen_cast_monitor_stream_finalize; - - stream_class->create_src = meta_screen_cast_monitor_stream_create_src; - stream_class->set_parameters = meta_screen_cast_monitor_stream_set_parameters; - stream_class->transform_position = meta_screen_cast_monitor_stream_transform_position; - - g_object_class_install_property (object_class, - PROP_MONITOR, - g_param_spec_object ("monitor", - "monitor", - "MetaMonitor", - META_TYPE_MONITOR, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); -} diff --git a/src/backends/meta-screen-cast-monitor-stream.h b/src/backends/meta-screen-cast-monitor-stream.h deleted file mode 100644 index 04c48e980..000000000 --- a/src/backends/meta-screen-cast-monitor-stream.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_SCREEN_CAST_MONITOR_STREAM_H -#define META_SCREEN_CAST_MONITOR_STREAM_H - -#include - -#include "backends/meta-monitor-manager-private.h" -#include "backends/meta-screen-cast-stream.h" -#include "backends/meta-screen-cast.h" - -#define META_TYPE_SCREEN_CAST_MONITOR_STREAM (meta_screen_cast_monitor_stream_get_type ()) -G_DECLARE_FINAL_TYPE (MetaScreenCastMonitorStream, - meta_screen_cast_monitor_stream, - META, SCREEN_CAST_MONITOR_STREAM, - MetaScreenCastStream) - -MetaScreenCastMonitorStream * meta_screen_cast_monitor_stream_new (MetaScreenCastSession *session, - GDBusConnection *connection, - MetaMonitor *monitor, - ClutterStage *stage, - MetaScreenCastCursorMode cursor_mode, - MetaScreenCastFlag flags, - GError **error); - -ClutterStage * meta_screen_cast_monitor_stream_get_stage (MetaScreenCastMonitorStream *monitor_stream); - -MetaMonitor * meta_screen_cast_monitor_stream_get_monitor (MetaScreenCastMonitorStream *monitor_stream); - -#endif /* META_SCREEN_CAST_MONITOR_STREAM_H */ diff --git a/src/backends/meta-screen-cast-session.c b/src/backends/meta-screen-cast-session.c deleted file mode 100644 index 60fffdea5..000000000 --- a/src/backends/meta-screen-cast-session.c +++ /dev/null @@ -1,825 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015-2017 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "backends/meta-screen-cast-session.h" - -#include "backends/meta-backend-private.h" -#include "backends/meta-dbus-session-watcher.h" -#include "backends/meta-remote-access-controller-private.h" -#include "backends/meta-screen-cast-area-stream.h" -#include "backends/meta-screen-cast-monitor-stream.h" -#include "backends/meta-screen-cast-stream.h" -#include "backends/meta-screen-cast-virtual-stream.h" -#include "backends/meta-screen-cast-window-stream.h" -#include "core/display-private.h" - -#define META_SCREEN_CAST_SESSION_DBUS_PATH "/org/gnome/Mutter/ScreenCast/Session" - -struct _MetaScreenCastSession -{ - MetaDBusScreenCastSessionSkeleton parent; - - MetaScreenCast *screen_cast; - - char *peer_name; - - MetaScreenCastSessionType session_type; - char *object_path; - - GList *streams; - - MetaScreenCastSessionHandle *handle; - - gboolean disable_animations; -}; - -static void -meta_screen_cast_session_init_iface (MetaDBusScreenCastSessionIface *iface); - -static void -meta_dbus_session_init_iface (MetaDbusSessionInterface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaScreenCastSession, - meta_screen_cast_session, - META_DBUS_TYPE_SCREEN_CAST_SESSION_SKELETON, - G_IMPLEMENT_INTERFACE (META_DBUS_TYPE_SCREEN_CAST_SESSION, - meta_screen_cast_session_init_iface) - G_IMPLEMENT_INTERFACE (META_TYPE_DBUS_SESSION, - meta_dbus_session_init_iface)) - -struct _MetaScreenCastSessionHandle -{ - MetaRemoteAccessHandle parent; - - MetaScreenCastSession *session; -}; - -G_DEFINE_TYPE (MetaScreenCastSessionHandle, - meta_screen_cast_session_handle, - META_TYPE_REMOTE_ACCESS_HANDLE) - -static MetaScreenCastSessionHandle * -meta_screen_cast_session_handle_new (MetaScreenCastSession *session); - -static void -init_remote_access_handle (MetaScreenCastSession *session) -{ - MetaBackend *backend = meta_get_backend (); - MetaRemoteAccessController *remote_access_controller; - MetaRemoteAccessHandle *remote_access_handle; - - session->handle = meta_screen_cast_session_handle_new (session); - - remote_access_controller = meta_backend_get_remote_access_controller (backend); - remote_access_handle = META_REMOTE_ACCESS_HANDLE (session->handle); - - meta_remote_access_handle_set_disable_animations (remote_access_handle, - session->disable_animations); - - meta_remote_access_controller_notify_new_handle (remote_access_controller, - remote_access_handle); -} - -gboolean -meta_screen_cast_session_start (MetaScreenCastSession *session, - GError **error) -{ - GList *l; - - for (l = session->streams; l; l = l->next) - { - MetaScreenCastStream *stream = l->data; - - if (!meta_screen_cast_stream_start (stream, error)) - return FALSE; - } - - init_remote_access_handle (session); - - return TRUE; -} - -void -meta_screen_cast_session_close (MetaScreenCastSession *session) -{ - MetaDBusScreenCastSession *skeleton = META_DBUS_SCREEN_CAST_SESSION (session); - - g_list_free_full (session->streams, g_object_unref); - - meta_dbus_session_notify_closed (META_DBUS_SESSION (session)); - - switch (session->session_type) - { - case META_SCREEN_CAST_SESSION_TYPE_NORMAL: - meta_dbus_screen_cast_session_emit_closed (skeleton); - break; - case META_SCREEN_CAST_SESSION_TYPE_REMOTE_DESKTOP: - break; - } - - g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (session)); - - if (session->handle) - { - MetaRemoteAccessHandle *remote_access_handle = - META_REMOTE_ACCESS_HANDLE (session->handle); - - meta_remote_access_handle_notify_stopped (remote_access_handle); - } - - g_object_unref (session); -} - -MetaScreenCastStream * -meta_screen_cast_session_get_stream (MetaScreenCastSession *session, - const char *path) -{ - GList *l; - - for (l = session->streams; l; l = l->next) - { - MetaScreenCastStream *stream = l->data; - - if (g_strcmp0 (meta_screen_cast_stream_get_object_path (stream), - path) == 0) - return stream; - } - - return NULL; -} - -MetaScreenCast * -meta_screen_cast_session_get_screen_cast (MetaScreenCastSession *session) -{ - return session->screen_cast; -} - -void -meta_screen_cast_session_set_disable_animations (MetaScreenCastSession *session, - gboolean disable_animations) -{ - session->disable_animations = disable_animations; -} - -char * -meta_screen_cast_session_get_object_path (MetaScreenCastSession *session) -{ - return session->object_path; -} - -char * -meta_screen_cast_session_get_peer_name (MetaScreenCastSession *session) -{ - return session->peer_name; -} - -MetaScreenCastSessionType -meta_screen_cast_session_get_session_type (MetaScreenCastSession *session) -{ - return session->session_type; -} - -static gboolean -check_permission (MetaScreenCastSession *session, - GDBusMethodInvocation *invocation) -{ - return g_strcmp0 (session->peer_name, - g_dbus_method_invocation_get_sender (invocation)) == 0; -} - -static gboolean -handle_start (MetaDBusScreenCastSession *skeleton, - GDBusMethodInvocation *invocation) -{ - MetaScreenCastSession *session = META_SCREEN_CAST_SESSION (skeleton); - GError *error = NULL; - - if (!check_permission (session, invocation)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Permission denied"); - return TRUE; - } - - switch (session->session_type) - { - case META_SCREEN_CAST_SESSION_TYPE_NORMAL: - break; - case META_SCREEN_CAST_SESSION_TYPE_REMOTE_DESKTOP: - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Must be started from remote desktop session"); - return TRUE; - } - - if (!meta_screen_cast_session_start (session, &error)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Failed to start screen cast: %s", - error->message); - g_error_free (error); - - return TRUE; - } - - meta_dbus_screen_cast_session_complete_start (skeleton, invocation); - - return TRUE; -} - -static gboolean -handle_stop (MetaDBusScreenCastSession *skeleton, - GDBusMethodInvocation *invocation) -{ - MetaScreenCastSession *session = META_SCREEN_CAST_SESSION (skeleton); - - if (!check_permission (session, invocation)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Permission denied"); - return TRUE; - } - - switch (session->session_type) - { - case META_SCREEN_CAST_SESSION_TYPE_NORMAL: - break; - case META_SCREEN_CAST_SESSION_TYPE_REMOTE_DESKTOP: - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Must be stopped from remote desktop session"); - return TRUE; - } - - meta_screen_cast_session_close (session); - - meta_dbus_screen_cast_session_complete_stop (skeleton, invocation); - - return TRUE; -} - -static void -on_stream_closed (MetaScreenCastStream *stream, - MetaScreenCastSession *session) -{ - meta_screen_cast_session_close (session); -} - -static gboolean -is_valid_cursor_mode (MetaScreenCastCursorMode cursor_mode) -{ - switch (cursor_mode) - { - case META_SCREEN_CAST_CURSOR_MODE_HIDDEN: - case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED: - case META_SCREEN_CAST_CURSOR_MODE_METADATA: - return TRUE; - } - - return FALSE; -} - -static gboolean -handle_record_monitor (MetaDBusScreenCastSession *skeleton, - GDBusMethodInvocation *invocation, - const char *connector, - GVariant *properties_variant) -{ - MetaScreenCastSession *session = META_SCREEN_CAST_SESSION (skeleton); - GDBusInterfaceSkeleton *interface_skeleton; - GDBusConnection *connection; - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitor *monitor; - MetaScreenCastCursorMode cursor_mode; - gboolean is_recording; - MetaScreenCastFlag flags; - ClutterStage *stage; - GError *error = NULL; - MetaScreenCastMonitorStream *monitor_stream; - MetaScreenCastStream *stream; - char *stream_path; - - if (!check_permission (session, invocation)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Permission denied"); - return TRUE; - } - - interface_skeleton = G_DBUS_INTERFACE_SKELETON (skeleton); - connection = g_dbus_interface_skeleton_get_connection (interface_skeleton); - - if (g_str_equal (connector, "")) - monitor = meta_monitor_manager_get_primary_monitor (monitor_manager); - else - monitor = meta_monitor_manager_get_monitor_from_connector (monitor_manager, - connector); - - if (!monitor) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Unknown monitor"); - return TRUE; - } - - if (!g_variant_lookup (properties_variant, "cursor-mode", "u", &cursor_mode)) - { - cursor_mode = META_SCREEN_CAST_CURSOR_MODE_HIDDEN; - } - else - { - if (!is_valid_cursor_mode (cursor_mode)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Unknown cursor mode"); - return TRUE; - } - } - - if (!g_variant_lookup (properties_variant, "is-recording", "b", &is_recording)) - is_recording = FALSE; - - stage = CLUTTER_STAGE (meta_backend_get_stage (backend)); - - flags = META_SCREEN_CAST_FLAG_NONE; - if (is_recording) - flags |= META_SCREEN_CAST_FLAG_IS_RECORDING; - - monitor_stream = meta_screen_cast_monitor_stream_new (session, - connection, - monitor, - stage, - cursor_mode, - flags, - &error); - if (!monitor_stream) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Failed to record monitor: %s", - error->message); - g_error_free (error); - return TRUE; - } - - stream = META_SCREEN_CAST_STREAM (monitor_stream); - stream_path = meta_screen_cast_stream_get_object_path (stream); - - session->streams = g_list_append (session->streams, stream); - - g_signal_connect (stream, "closed", G_CALLBACK (on_stream_closed), session); - - meta_dbus_screen_cast_session_complete_record_monitor (skeleton, - invocation, - stream_path); - - return TRUE; -} - -static gboolean -handle_record_window (MetaDBusScreenCastSession *skeleton, - GDBusMethodInvocation *invocation, - GVariant *properties_variant) -{ - MetaScreenCastSession *session = META_SCREEN_CAST_SESSION (skeleton); - GDBusInterfaceSkeleton *interface_skeleton; - GDBusConnection *connection; - MetaWindow *window; - MetaScreenCastCursorMode cursor_mode; - gboolean is_recording; - MetaScreenCastFlag flags; - GError *error = NULL; - MetaDisplay *display; - GVariant *window_id_variant = NULL; - MetaScreenCastWindowStream *window_stream; - MetaScreenCastStream *stream; - char *stream_path; - - if (!check_permission (session, invocation)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Permission denied"); - return TRUE; - } - - if (properties_variant) - window_id_variant = g_variant_lookup_value (properties_variant, - "window-id", - G_VARIANT_TYPE ("t")); - - display = meta_get_display (); - if (window_id_variant) - { - uint64_t window_id; - - g_variant_get (window_id_variant, "t", &window_id); - window = meta_display_get_window_from_id (display, window_id); - } - else - { - window = meta_display_get_focus_window (display); - } - - if (!window) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Window not found"); - return TRUE; - } - - if (!g_variant_lookup (properties_variant, "cursor-mode", "u", &cursor_mode)) - { - cursor_mode = META_SCREEN_CAST_CURSOR_MODE_HIDDEN; - } - else - { - if (!is_valid_cursor_mode (cursor_mode)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Unknown cursor mode"); - return TRUE; - } - } - - if (!g_variant_lookup (properties_variant, "is-recording", "b", &is_recording)) - is_recording = FALSE; - - interface_skeleton = G_DBUS_INTERFACE_SKELETON (skeleton); - connection = g_dbus_interface_skeleton_get_connection (interface_skeleton); - - flags = META_SCREEN_CAST_FLAG_NONE; - if (is_recording) - flags |= META_SCREEN_CAST_FLAG_IS_RECORDING; - - window_stream = meta_screen_cast_window_stream_new (session, - connection, - window, - cursor_mode, - flags, - &error); - if (!window_stream) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Failed to record window: %s", - error->message); - g_error_free (error); - return TRUE; - } - - stream = META_SCREEN_CAST_STREAM (window_stream); - stream_path = meta_screen_cast_stream_get_object_path (stream); - - session->streams = g_list_append (session->streams, stream); - - g_signal_connect (stream, "closed", G_CALLBACK (on_stream_closed), session); - - meta_dbus_screen_cast_session_complete_record_window (skeleton, - invocation, - stream_path); - - return TRUE; -} - -static gboolean -handle_record_area (MetaDBusScreenCastSession *skeleton, - GDBusMethodInvocation *invocation, - int x, - int y, - int width, - int height, - GVariant *properties_variant) -{ - MetaScreenCastSession *session = META_SCREEN_CAST_SESSION (skeleton); - GDBusInterfaceSkeleton *interface_skeleton; - GDBusConnection *connection; - MetaBackend *backend; - ClutterStage *stage; - MetaScreenCastCursorMode cursor_mode; - gboolean is_recording; - MetaScreenCastFlag flags; - g_autoptr (GError) error = NULL; - MetaRectangle rect; - MetaScreenCastAreaStream *area_stream; - MetaScreenCastStream *stream; - char *stream_path; - - if (!check_permission (session, invocation)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Permission denied"); - return TRUE; - } - - if (!g_variant_lookup (properties_variant, "cursor-mode", "u", &cursor_mode)) - { - cursor_mode = META_SCREEN_CAST_CURSOR_MODE_HIDDEN; - } - else - { - if (!is_valid_cursor_mode (cursor_mode)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Unknown cursor mode"); - return TRUE; - } - } - - if (!g_variant_lookup (properties_variant, "is-recording", "b", &is_recording)) - is_recording = FALSE; - - interface_skeleton = G_DBUS_INTERFACE_SKELETON (skeleton); - connection = g_dbus_interface_skeleton_get_connection (interface_skeleton); - backend = meta_screen_cast_get_backend (session->screen_cast); - stage = CLUTTER_STAGE (meta_backend_get_stage (backend)); - - flags = META_SCREEN_CAST_FLAG_NONE; - if (is_recording) - flags |= META_SCREEN_CAST_FLAG_IS_RECORDING; - - rect = (MetaRectangle) { - .x = x, - .y = y, - .width = width, - .height = height - }; - area_stream = meta_screen_cast_area_stream_new (session, - connection, - &rect, - stage, - cursor_mode, - flags, - &error); - if (!area_stream) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Failed to record area: %s", - error->message); - return TRUE; - } - - stream = META_SCREEN_CAST_STREAM (area_stream); - stream_path = meta_screen_cast_stream_get_object_path (stream); - - session->streams = g_list_append (session->streams, stream); - - g_signal_connect (stream, "closed", G_CALLBACK (on_stream_closed), session); - - meta_dbus_screen_cast_session_complete_record_area (skeleton, - invocation, - stream_path); - - return TRUE; -} - -static gboolean -handle_record_virtual (MetaDBusScreenCastSession *skeleton, - GDBusMethodInvocation *invocation, - GVariant *properties_variant) -{ - MetaScreenCastSession *session = META_SCREEN_CAST_SESSION (skeleton); - GDBusInterfaceSkeleton *interface_skeleton; - GDBusConnection *connection; - MetaScreenCastCursorMode cursor_mode; - gboolean is_platform; - MetaScreenCastFlag flags; - g_autoptr (GError) error = NULL; - MetaScreenCastVirtualStream *virtual_stream; - MetaScreenCastStream *stream; - char *stream_path; - - if (!check_permission (session, invocation)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Permission denied"); - return TRUE; - } - - if (!g_variant_lookup (properties_variant, "cursor-mode", "u", &cursor_mode)) - { - cursor_mode = META_SCREEN_CAST_CURSOR_MODE_HIDDEN; - } - else - { - if (!is_valid_cursor_mode (cursor_mode)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Unknown cursor mode"); - return TRUE; - } - } - - if (!g_variant_lookup (properties_variant, "is-platform", "b", &is_platform)) - is_platform = FALSE; - - interface_skeleton = G_DBUS_INTERFACE_SKELETON (skeleton); - connection = g_dbus_interface_skeleton_get_connection (interface_skeleton); - - flags = META_SCREEN_CAST_FLAG_NONE; - if (is_platform) - flags |= META_SCREEN_CAST_FLAG_IS_PLATFORM; - - virtual_stream = meta_screen_cast_virtual_stream_new (session, - connection, - cursor_mode, - flags, - &error); - if (!virtual_stream) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Failed to record virtual: %s", - error->message); - return TRUE; - } - - stream = META_SCREEN_CAST_STREAM (virtual_stream); - stream_path = meta_screen_cast_stream_get_object_path (stream); - - session->streams = g_list_append (session->streams, stream); - - g_signal_connect (stream, "closed", G_CALLBACK (on_stream_closed), session); - - meta_dbus_screen_cast_session_complete_record_virtual (skeleton, - invocation, - stream_path); - - return TRUE; -} - -static void -meta_screen_cast_session_init_iface (MetaDBusScreenCastSessionIface *iface) -{ - iface->handle_start = handle_start; - iface->handle_stop = handle_stop; - iface->handle_record_monitor = handle_record_monitor; - iface->handle_record_window = handle_record_window; - iface->handle_record_area = handle_record_area; - iface->handle_record_virtual = handle_record_virtual; -} - -static void -meta_screen_cast_session_client_vanished (MetaDbusSession *dbus_session) -{ - meta_screen_cast_session_close (META_SCREEN_CAST_SESSION (dbus_session)); -} - -static void -meta_dbus_session_init_iface (MetaDbusSessionInterface *iface) -{ - iface->client_vanished = meta_screen_cast_session_client_vanished; -} - -MetaScreenCastSession * -meta_screen_cast_session_new (MetaScreenCast *screen_cast, - MetaScreenCastSessionType session_type, - const char *peer_name, - GError **error) -{ - GDBusInterfaceSkeleton *interface_skeleton; - MetaScreenCastSession *session; - GDBusConnection *connection; - static unsigned int global_session_number = 0; - - session = g_object_new (META_TYPE_SCREEN_CAST_SESSION, NULL); - session->screen_cast = screen_cast; - session->session_type = session_type; - session->peer_name = g_strdup (peer_name); - session->object_path = - g_strdup_printf (META_SCREEN_CAST_SESSION_DBUS_PATH "/u%u", - ++global_session_number); - - interface_skeleton = G_DBUS_INTERFACE_SKELETON (session); - connection = meta_screen_cast_get_connection (screen_cast); - if (!g_dbus_interface_skeleton_export (interface_skeleton, - connection, - session->object_path, - error)) - return NULL; - - return session; -} - -static void -meta_screen_cast_session_finalize (GObject *object) -{ - MetaScreenCastSession *session = META_SCREEN_CAST_SESSION (object); - - g_clear_object (&session->handle); - g_free (session->peer_name); - g_free (session->object_path); - - G_OBJECT_CLASS (meta_screen_cast_session_parent_class)->finalize (object); -} - -static void -meta_screen_cast_session_init (MetaScreenCastSession *session) -{ -} - -static void -meta_screen_cast_session_class_init (MetaScreenCastSessionClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_screen_cast_session_finalize; -} - -static gboolean -meta_screen_cast_session_is_recording (MetaScreenCastSession *session) -{ - GList *l; - - if (!session->streams) - return FALSE; - - for (l = session->streams; l; l = l->next) - { - MetaScreenCastStream *stream = l->data; - MetaScreenCastFlag flags; - - flags = meta_screen_cast_stream_get_flags (stream); - if (!(flags & META_SCREEN_CAST_FLAG_IS_RECORDING)) - return FALSE; - } - - return TRUE; -} - -static MetaScreenCastSessionHandle * -meta_screen_cast_session_handle_new (MetaScreenCastSession *session) -{ - MetaScreenCastSessionHandle *handle; - gboolean is_recording; - - is_recording = meta_screen_cast_session_is_recording (session); - handle = g_object_new (META_TYPE_SCREEN_CAST_SESSION_HANDLE, - "is-recording", is_recording, - NULL); - handle->session = session; - - return handle; -} - -static void -meta_screen_cast_session_handle_stop (MetaRemoteAccessHandle *handle) -{ - MetaScreenCastSession *session; - - session = META_SCREEN_CAST_SESSION_HANDLE (handle)->session; - if (!session) - return; - - meta_screen_cast_session_close (session); -} - -static void -meta_screen_cast_session_handle_init (MetaScreenCastSessionHandle *handle) -{ -} - -static void -meta_screen_cast_session_handle_class_init (MetaScreenCastSessionHandleClass *klass) -{ - MetaRemoteAccessHandleClass *remote_access_handle_class = - META_REMOTE_ACCESS_HANDLE_CLASS (klass); - - remote_access_handle_class->stop = meta_screen_cast_session_handle_stop; -} diff --git a/src/backends/meta-screen-cast-session.h b/src/backends/meta-screen-cast-session.h deleted file mode 100644 index 46bde5eb9..000000000 --- a/src/backends/meta-screen-cast-session.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015-2017 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_SCREEN_CAST_SESSION_H -#define META_SCREEN_CAST_SESSION_H - -#include "backends/meta-screen-cast.h" - -#include "backends/meta-screen-cast-stream.h" -#include "meta/meta-remote-access-controller.h" - -typedef enum _MetaScreenCastSessionType -{ - META_SCREEN_CAST_SESSION_TYPE_NORMAL, - META_SCREEN_CAST_SESSION_TYPE_REMOTE_DESKTOP, -} MetaScreenCastSessionType; - -#define META_TYPE_SCREEN_CAST_SESSION (meta_screen_cast_session_get_type ()) -G_DECLARE_FINAL_TYPE (MetaScreenCastSession, meta_screen_cast_session, - META, SCREEN_CAST_SESSION, - MetaDBusScreenCastSessionSkeleton) - -#define META_TYPE_SCREEN_CAST_SESSION_HANDLE (meta_screen_cast_session_handle_get_type ()) -G_DECLARE_FINAL_TYPE (MetaScreenCastSessionHandle, - meta_screen_cast_session_handle, - META, SCREEN_CAST_SESSION_HANDLE, - MetaRemoteAccessHandle) - -char * meta_screen_cast_session_get_object_path (MetaScreenCastSession *session); - -char * meta_screen_cast_session_get_peer_name (MetaScreenCastSession *session); - -MetaScreenCastSessionType meta_screen_cast_session_get_session_type (MetaScreenCastSession *session); - -MetaScreenCastSession * meta_screen_cast_session_new (MetaScreenCast *screen_cast, - MetaScreenCastSessionType session_type, - const char *peer_name, - GError **error); - -gboolean meta_screen_cast_session_start (MetaScreenCastSession *session, - GError **error); - -void meta_screen_cast_session_close (MetaScreenCastSession *session); - -MetaScreenCastStream * meta_screen_cast_session_get_stream (MetaScreenCastSession *session, - const char *path); - -MetaScreenCast * meta_screen_cast_session_get_screen_cast (MetaScreenCastSession *session); - -void meta_screen_cast_session_set_disable_animations (MetaScreenCastSession *session, - gboolean disable_animations); - -#endif /* META_SCREEN_CAST_SESSION_H */ diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c deleted file mode 100644 index c3ede8aea..000000000 --- a/src/backends/meta-screen-cast-stream-src.c +++ /dev/null @@ -1,1237 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015-2017 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "backends/meta-screen-cast-stream-src.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "backends/meta-screen-cast-session.h" -#include "backends/meta-screen-cast-stream.h" -#include "clutter/clutter-mutter.h" -#include "core/meta-fraction.h" -#include "meta/boxes.h" - -#define PRIVATE_OWNER_FROM_FIELD(TypeName, field_ptr, field_name) \ - (TypeName *)((guint8 *)(field_ptr) - G_PRIVATE_OFFSET (TypeName, field_name)) - -#define CURSOR_META_SIZE(width, height) \ - (sizeof (struct spa_meta_cursor) + \ - sizeof (struct spa_meta_bitmap) + width * height * 4) - -#define DEFAULT_SIZE SPA_RECTANGLE (1280, 720) -#define MIN_SIZE SPA_RECTANGLE (1, 1) -#define MAX_SIZE SPA_RECTANGLE (16384, 16386) - -#define DEFAULT_FRAME_RATE SPA_FRACTION (60, 1) -#define MIN_FRAME_RATE SPA_FRACTION (1, 1) -#define MAX_FRAME_RATE SPA_FRACTION (1000, 1) - -enum -{ - PROP_0, - - PROP_STREAM, -}; - -enum -{ - READY, - CLOSED, - - N_SIGNALS -}; - -static guint signals[N_SIGNALS]; - -typedef struct _MetaPipeWireSource -{ - GSource base; - - MetaScreenCastStreamSrc *src; - struct pw_loop *pipewire_loop; -} MetaPipeWireSource; - -typedef struct _MetaScreenCastStreamSrcPrivate -{ - MetaScreenCastStream *stream; - - struct pw_context *pipewire_context; - struct pw_core *pipewire_core; - MetaPipeWireSource *pipewire_source; - struct spa_hook pipewire_core_listener; - - gboolean is_enabled; - gboolean emit_closed_after_dispatch; - - struct pw_stream *pipewire_stream; - struct spa_hook pipewire_stream_listener; - uint32_t node_id; - - struct spa_video_info_raw video_format; - int video_stride; - - int64_t last_frame_timestamp_us; - guint follow_up_frame_source_id; - - GHashTable *dmabuf_handles; -} MetaScreenCastStreamSrcPrivate; - -static void -meta_screen_cast_stream_src_init_initable_iface (GInitableIface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaScreenCastStreamSrc, - meta_screen_cast_stream_src, - G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - meta_screen_cast_stream_src_init_initable_iface) - G_ADD_PRIVATE (MetaScreenCastStreamSrc)) - -static gboolean -meta_screen_cast_stream_src_get_specs (MetaScreenCastStreamSrc *src, - int *width, - int *height, - float *frame_rate) -{ - MetaScreenCastStreamSrcClass *klass = - META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src); - - return klass->get_specs (src, width, height, frame_rate); -} - -static gboolean -meta_screen_cast_stream_src_get_videocrop (MetaScreenCastStreamSrc *src, - MetaRectangle *crop_rect) -{ - MetaScreenCastStreamSrcClass *klass = - META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src); - - if (klass->get_videocrop) - return klass->get_videocrop (src, crop_rect); - - return FALSE; -} - -static gboolean -meta_screen_cast_stream_src_record_to_buffer (MetaScreenCastStreamSrc *src, - int width, - int height, - int stride, - uint8_t *data, - GError **error) -{ - MetaScreenCastStreamSrcClass *klass = - META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src); - - return klass->record_to_buffer (src, width, height, stride, data, error); -} - -static gboolean -meta_screen_cast_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc *src, - CoglFramebuffer *framebuffer, - GError **error) -{ - MetaScreenCastStreamSrcClass *klass = - META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src); - - return klass->record_to_framebuffer (src, framebuffer, error); -} - -static void -meta_screen_cast_stream_src_record_follow_up (MetaScreenCastStreamSrc *src) -{ - MetaScreenCastStreamSrcClass *klass = - META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src); - - klass->record_follow_up (src); -} - -static void -meta_screen_cast_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src, - struct spa_meta_cursor *spa_meta_cursor) -{ - MetaScreenCastStreamSrcClass *klass = - META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src); - - if (klass->set_cursor_metadata) - klass->set_cursor_metadata (src, spa_meta_cursor); -} - -static gboolean -draw_cursor_sprite_via_offscreen (MetaScreenCastStreamSrc *src, - CoglTexture *cursor_texture, - int bitmap_width, - int bitmap_height, - uint8_t *bitmap_data, - GError **error) -{ - MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src); - MetaScreenCastSession *session = meta_screen_cast_stream_get_session (stream); - MetaScreenCast *screen_cast = - meta_screen_cast_session_get_screen_cast (session); - MetaBackend *backend = meta_screen_cast_get_backend (screen_cast); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = - clutter_backend_get_cogl_context (clutter_backend); - CoglTexture2D *bitmap_texture; - CoglOffscreen *offscreen; - CoglFramebuffer *fb; - CoglPipeline *pipeline; - CoglColor clear_color; - - bitmap_texture = cogl_texture_2d_new_with_size (cogl_context, - bitmap_width, bitmap_height); - cogl_primitive_texture_set_auto_mipmap (COGL_PRIMITIVE_TEXTURE (bitmap_texture), - FALSE); - if (!cogl_texture_allocate (COGL_TEXTURE (bitmap_texture), error)) - { - cogl_object_unref (bitmap_texture); - return FALSE; - } - - offscreen = cogl_offscreen_new_with_texture (COGL_TEXTURE (bitmap_texture)); - fb = COGL_FRAMEBUFFER (offscreen); - cogl_object_unref (bitmap_texture); - if (!cogl_framebuffer_allocate (fb, error)) - { - g_object_unref (fb); - return FALSE; - } - - pipeline = cogl_pipeline_new (cogl_context); - cogl_pipeline_set_layer_texture (pipeline, 0, cursor_texture); - cogl_pipeline_set_layer_filters (pipeline, 0, - COGL_PIPELINE_FILTER_LINEAR, - COGL_PIPELINE_FILTER_LINEAR); - cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 0); - cogl_framebuffer_clear (fb, COGL_BUFFER_BIT_COLOR, &clear_color); - cogl_framebuffer_draw_rectangle (fb, pipeline, - -1, 1, 1, -1); - cogl_object_unref (pipeline); - - cogl_framebuffer_read_pixels (fb, - 0, 0, - bitmap_width, bitmap_height, - COGL_PIXEL_FORMAT_RGBA_8888_PRE, - bitmap_data); - g_object_unref (fb); - - return TRUE; -} - -gboolean -meta_screen_cast_stream_src_draw_cursor_into (MetaScreenCastStreamSrc *src, - CoglTexture *cursor_texture, - float scale, - uint8_t *data, - GError **error) -{ - int texture_width, texture_height; - int width, height; - - texture_width = cogl_texture_get_width (cursor_texture); - texture_height = cogl_texture_get_height (cursor_texture); - width = texture_width * scale; - height = texture_height * scale; - - if (texture_width == width && - texture_height == height) - { - cogl_texture_get_data (cursor_texture, - COGL_PIXEL_FORMAT_RGBA_8888_PRE, - texture_width * 4, - data); - } - else - { - if (!draw_cursor_sprite_via_offscreen (src, - cursor_texture, - width, - height, - data, - error)) - return FALSE; - } - - return TRUE; -} - -void -meta_screen_cast_stream_src_unset_cursor_metadata (MetaScreenCastStreamSrc *src, - struct spa_meta_cursor *spa_meta_cursor) -{ - spa_meta_cursor->id = 0; -} - -void -meta_screen_cast_stream_src_set_cursor_position_metadata (MetaScreenCastStreamSrc *src, - struct spa_meta_cursor *spa_meta_cursor, - int x, - int y) -{ - spa_meta_cursor->id = 1; - spa_meta_cursor->position.x = x; - spa_meta_cursor->position.y = y; - spa_meta_cursor->hotspot.x = 0; - spa_meta_cursor->hotspot.y = 0; - spa_meta_cursor->bitmap_offset = 0; -} - -void -meta_screen_cast_stream_src_set_empty_cursor_sprite_metadata (MetaScreenCastStreamSrc *src, - struct spa_meta_cursor *spa_meta_cursor, - int x, - int y) -{ - struct spa_meta_bitmap *spa_meta_bitmap; - - spa_meta_cursor->id = 1; - spa_meta_cursor->position.x = x; - spa_meta_cursor->position.y = y; - - spa_meta_cursor->bitmap_offset = sizeof (struct spa_meta_cursor); - - spa_meta_bitmap = SPA_MEMBER (spa_meta_cursor, - spa_meta_cursor->bitmap_offset, - struct spa_meta_bitmap); - spa_meta_bitmap->format = SPA_VIDEO_FORMAT_RGBA; - spa_meta_bitmap->offset = sizeof (struct spa_meta_bitmap); - - spa_meta_cursor->hotspot.x = 0; - spa_meta_cursor->hotspot.y = 0; - - *spa_meta_bitmap = (struct spa_meta_bitmap) { 0 }; -} - -void -meta_screen_cast_stream_src_set_cursor_sprite_metadata (MetaScreenCastStreamSrc *src, - struct spa_meta_cursor *spa_meta_cursor, - MetaCursorSprite *cursor_sprite, - int x, - int y, - float scale) -{ - CoglTexture *cursor_texture; - struct spa_meta_bitmap *spa_meta_bitmap; - int hotspot_x, hotspot_y; - int texture_width, texture_height; - int bitmap_width, bitmap_height; - uint8_t *bitmap_data; - GError *error = NULL; - - cursor_texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); - if (!cursor_texture) - { - meta_screen_cast_stream_src_set_empty_cursor_sprite_metadata (src, - spa_meta_cursor, - x, y); - return; - } - - spa_meta_cursor->id = 1; - spa_meta_cursor->position.x = x; - spa_meta_cursor->position.y = y; - - spa_meta_cursor->bitmap_offset = sizeof (struct spa_meta_cursor); - - spa_meta_bitmap = SPA_MEMBER (spa_meta_cursor, - spa_meta_cursor->bitmap_offset, - struct spa_meta_bitmap); - spa_meta_bitmap->format = SPA_VIDEO_FORMAT_RGBA; - spa_meta_bitmap->offset = sizeof (struct spa_meta_bitmap); - - meta_cursor_sprite_get_hotspot (cursor_sprite, &hotspot_x, &hotspot_y); - spa_meta_cursor->hotspot.x = (int32_t) roundf (hotspot_x * scale); - spa_meta_cursor->hotspot.y = (int32_t) roundf (hotspot_y * scale); - - texture_width = cogl_texture_get_width (cursor_texture); - texture_height = cogl_texture_get_height (cursor_texture); - bitmap_width = texture_width * scale; - bitmap_height = texture_height * scale; - - spa_meta_bitmap->size.width = bitmap_width; - spa_meta_bitmap->size.height = bitmap_height; - spa_meta_bitmap->stride = bitmap_width * 4; - - bitmap_data = SPA_MEMBER (spa_meta_bitmap, - spa_meta_bitmap->offset, - uint8_t); - - if (!meta_screen_cast_stream_src_draw_cursor_into (src, - cursor_texture, - scale, - bitmap_data, - &error)) - { - g_warning ("Failed to draw cursor: %s", error->message); - g_error_free (error); - spa_meta_cursor->id = 0; - } -} - -static void -add_cursor_metadata (MetaScreenCastStreamSrc *src, - struct spa_buffer *spa_buffer) -{ - struct spa_meta_cursor *spa_meta_cursor; - - spa_meta_cursor = spa_buffer_find_meta_data (spa_buffer, SPA_META_Cursor, - sizeof (*spa_meta_cursor)); - if (spa_meta_cursor) - meta_screen_cast_stream_src_set_cursor_metadata (src, spa_meta_cursor); -} - -static void -maybe_record_cursor (MetaScreenCastStreamSrc *src, - struct spa_buffer *spa_buffer) -{ - MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src); - - switch (meta_screen_cast_stream_get_cursor_mode (stream)) - { - case META_SCREEN_CAST_CURSOR_MODE_HIDDEN: - case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED: - return; - case META_SCREEN_CAST_CURSOR_MODE_METADATA: - add_cursor_metadata (src, spa_buffer); - return; - } - - g_assert_not_reached (); -} - -static gboolean -do_record_frame (MetaScreenCastStreamSrc *src, - struct spa_buffer *spa_buffer, - uint8_t *data, - GError **error) -{ - MetaScreenCastStreamSrcPrivate *priv = - meta_screen_cast_stream_src_get_instance_private (src); - - if (spa_buffer->datas[0].data || - spa_buffer->datas[0].type == SPA_DATA_MemFd) - { - int width = priv->video_format.size.width; - int height = priv->video_format.size.height; - int stride = priv->video_stride; - - return meta_screen_cast_stream_src_record_to_buffer (src, - width, - height, - stride, - data, - error); - } - else if (spa_buffer->datas[0].type == SPA_DATA_DmaBuf) - { - CoglDmaBufHandle *dmabuf_handle = - g_hash_table_lookup (priv->dmabuf_handles, - GINT_TO_POINTER (spa_buffer->datas[0].fd)); - CoglFramebuffer *dmabuf_fbo = - cogl_dma_buf_handle_get_framebuffer (dmabuf_handle); - - return meta_screen_cast_stream_src_record_to_framebuffer (src, - dmabuf_fbo, - error); - } - - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Unknown SPA buffer type %u", spa_buffer->datas[0].type); - return FALSE; -} - -gboolean -meta_screen_cast_stream_src_pending_follow_up_frame (MetaScreenCastStreamSrc *src) -{ - MetaScreenCastStreamSrcPrivate *priv = - meta_screen_cast_stream_src_get_instance_private (src); - - return priv->follow_up_frame_source_id != 0; -} - -static gboolean -follow_up_frame_cb (gpointer user_data) -{ - MetaScreenCastStreamSrc *src = user_data; - MetaScreenCastStreamSrcPrivate *priv = - meta_screen_cast_stream_src_get_instance_private (src); - - priv->follow_up_frame_source_id = 0; - meta_screen_cast_stream_src_record_follow_up (src); - - return G_SOURCE_REMOVE; -} - -static void -maybe_schedule_follow_up_frame (MetaScreenCastStreamSrc *src, - int64_t timeout_us) -{ - MetaScreenCastStreamSrcPrivate *priv = - meta_screen_cast_stream_src_get_instance_private (src); - - if (priv->follow_up_frame_source_id) - return; - - priv->follow_up_frame_source_id = g_timeout_add (us2ms (timeout_us), - follow_up_frame_cb, - src); -} - -void -meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src, - MetaScreenCastRecordFlag flags) -{ - MetaScreenCastStreamSrcPrivate *priv = - meta_screen_cast_stream_src_get_instance_private (src); - MetaRectangle crop_rect; - struct pw_buffer *buffer; - struct spa_buffer *spa_buffer; - uint8_t *data = NULL; - uint64_t now_us; - g_autoptr (GError) error = NULL; - - now_us = g_get_monotonic_time (); - if (priv->video_format.max_framerate.num > 0 && - priv->last_frame_timestamp_us != 0) - { - int64_t min_interval_us; - int64_t time_since_last_frame_us; - - min_interval_us = - ((G_USEC_PER_SEC * priv->video_format.max_framerate.denom) / - priv->video_format.max_framerate.num); - - time_since_last_frame_us = now_us - priv->last_frame_timestamp_us; - if (time_since_last_frame_us < min_interval_us) - { - int64_t timeout_us; - - timeout_us = min_interval_us - time_since_last_frame_us; - maybe_schedule_follow_up_frame (src, timeout_us); - return; - } - } - - if (!priv->pipewire_stream) - return; - - buffer = pw_stream_dequeue_buffer (priv->pipewire_stream); - if (!buffer) - { - meta_topic (META_DEBUG_SCREEN_CAST, - "Couldn't dequeue a buffer from pipewire stream (node id %u), " - "maybe your encoding is too slow?", - pw_stream_get_node_id (priv->pipewire_stream)); - return; - } - - spa_buffer = buffer->buffer; - data = spa_buffer->datas[0].data; - - if (spa_buffer->datas[0].type != SPA_DATA_DmaBuf && !data) - { - g_critical ("Invalid buffer data"); - return; - } - - if (!(flags & META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY)) - { - g_clear_handle_id (&priv->follow_up_frame_source_id, g_source_remove); - if (do_record_frame (src, spa_buffer, data, &error)) - { - struct spa_meta_region *spa_meta_video_crop; - - spa_buffer->datas[0].chunk->size = spa_buffer->datas[0].maxsize; - spa_buffer->datas[0].chunk->stride = priv->video_stride; - - /* Update VideoCrop if needed */ - spa_meta_video_crop = - spa_buffer_find_meta_data (spa_buffer, SPA_META_VideoCrop, - sizeof (*spa_meta_video_crop)); - if (spa_meta_video_crop) - { - if (meta_screen_cast_stream_src_get_videocrop (src, &crop_rect)) - { - spa_meta_video_crop->region.position.x = crop_rect.x; - spa_meta_video_crop->region.position.y = crop_rect.y; - spa_meta_video_crop->region.size.width = crop_rect.width; - spa_meta_video_crop->region.size.height = crop_rect.height; - } - else - { - spa_meta_video_crop->region.position.x = 0; - spa_meta_video_crop->region.position.y = 0; - spa_meta_video_crop->region.size.width = - priv->video_format.size.width; - spa_meta_video_crop->region.size.height = - priv->video_format.size.height; - } - } - } - else - { - g_warning ("Failed to record screen cast frame: %s", error->message); - spa_buffer->datas[0].chunk->size = 0; - } - } - else - { - spa_buffer->datas[0].chunk->size = 0; - } - - maybe_record_cursor (src, spa_buffer); - - priv->last_frame_timestamp_us = now_us; - - pw_stream_queue_buffer (priv->pipewire_stream, buffer); -} - -static gboolean -meta_screen_cast_stream_src_is_enabled (MetaScreenCastStreamSrc *src) -{ - MetaScreenCastStreamSrcPrivate *priv = - meta_screen_cast_stream_src_get_instance_private (src); - - return priv->is_enabled; -} - -static void -meta_screen_cast_stream_src_enable (MetaScreenCastStreamSrc *src) -{ - MetaScreenCastStreamSrcPrivate *priv = - meta_screen_cast_stream_src_get_instance_private (src); - - META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src)->enable (src); - - priv->is_enabled = TRUE; -} - -static void -meta_screen_cast_stream_src_disable (MetaScreenCastStreamSrc *src) -{ - MetaScreenCastStreamSrcPrivate *priv = - meta_screen_cast_stream_src_get_instance_private (src); - - META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src)->disable (src); - - g_clear_handle_id (&priv->follow_up_frame_source_id, g_source_remove); - - priv->is_enabled = FALSE; -} - -void -meta_screen_cast_stream_src_close (MetaScreenCastStreamSrc *src) -{ - MetaScreenCastStreamSrcPrivate *priv = - meta_screen_cast_stream_src_get_instance_private (src); - - if (meta_screen_cast_stream_src_is_enabled (src)) - meta_screen_cast_stream_src_disable (src); - priv->emit_closed_after_dispatch = TRUE; -} - -static void -on_stream_state_changed (void *data, - enum pw_stream_state old, - enum pw_stream_state state, - const char *error_message) -{ - MetaScreenCastStreamSrc *src = data; - MetaScreenCastStreamSrcPrivate *priv = - meta_screen_cast_stream_src_get_instance_private (src); - - switch (state) - { - case PW_STREAM_STATE_ERROR: - g_warning ("pipewire stream error: %s", error_message); - meta_screen_cast_stream_src_close (src); - break; - case PW_STREAM_STATE_PAUSED: - if (priv->node_id == SPA_ID_INVALID && priv->pipewire_stream) - { - priv->node_id = pw_stream_get_node_id (priv->pipewire_stream); - g_signal_emit (src, signals[READY], 0, (unsigned int) priv->node_id); - } - if (meta_screen_cast_stream_src_is_enabled (src)) - meta_screen_cast_stream_src_disable (src); - break; - case PW_STREAM_STATE_STREAMING: - if (!meta_screen_cast_stream_src_is_enabled (src)) - meta_screen_cast_stream_src_enable (src); - break; - case PW_STREAM_STATE_UNCONNECTED: - case PW_STREAM_STATE_CONNECTING: - break; - } -} - -static void -on_stream_param_changed (void *data, - uint32_t id, - const struct spa_pod *format) -{ - MetaScreenCastStreamSrc *src = data; - MetaScreenCastStreamSrcPrivate *priv = - meta_screen_cast_stream_src_get_instance_private (src); - MetaScreenCastStreamSrcClass *klass = - META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src); - uint8_t params_buffer[1024]; - int32_t width, height, stride, size; - struct spa_pod_builder pod_builder; - const struct spa_pod *params[3]; - const int bpp = 4; - - if (!format || id != SPA_PARAM_Format) - return; - - spa_format_video_raw_parse (format, - &priv->video_format); - - width = priv->video_format.size.width; - height = priv->video_format.size.height; - stride = SPA_ROUND_UP_N (width * bpp, 4); - size = height * stride; - - priv->video_stride = stride; - - pod_builder = SPA_POD_BUILDER_INIT (params_buffer, sizeof (params_buffer)); - - params[0] = spa_pod_builder_add_object ( - &pod_builder, - SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers, - SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int (16, 2, 16), - SPA_PARAM_BUFFERS_blocks, SPA_POD_Int (1), - SPA_PARAM_BUFFERS_size, SPA_POD_Int (size), - SPA_PARAM_BUFFERS_stride, SPA_POD_Int (stride), - SPA_PARAM_BUFFERS_align, SPA_POD_Int (16)); - - params[1] = spa_pod_builder_add_object ( - &pod_builder, - SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, - SPA_PARAM_META_type, SPA_POD_Id (SPA_META_VideoCrop), - SPA_PARAM_META_size, SPA_POD_Int (sizeof (struct spa_meta_region))); - - params[2] = spa_pod_builder_add_object ( - &pod_builder, - SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, - SPA_PARAM_META_type, SPA_POD_Id (SPA_META_Cursor), - SPA_PARAM_META_size, SPA_POD_Int (CURSOR_META_SIZE (384, 384))); - - pw_stream_update_params (priv->pipewire_stream, params, G_N_ELEMENTS (params)); - - if (klass->notify_params_updated) - klass->notify_params_updated (src, &priv->video_format); -} - -static void -on_stream_add_buffer (void *data, - struct pw_buffer *buffer) -{ - MetaScreenCastStreamSrc *src = data; - MetaScreenCastStreamSrcPrivate *priv = - meta_screen_cast_stream_src_get_instance_private (src); - MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src); - MetaScreenCastSession *session = meta_screen_cast_stream_get_session (stream); - MetaScreenCast *screen_cast = - meta_screen_cast_session_get_screen_cast (session); - CoglDmaBufHandle *dmabuf_handle; - struct spa_buffer *spa_buffer = buffer->buffer; - struct spa_data *spa_data = spa_buffer->datas; - const int bpp = 4; - int stride; - - stride = SPA_ROUND_UP_N (priv->video_format.size.width * bpp, 4); - - spa_data[0].mapoffset = 0; - spa_data[0].maxsize = stride * priv->video_format.size.height; - spa_data[0].data = NULL; - - if (spa_data[0].type & (1 << SPA_DATA_DmaBuf)) - { - dmabuf_handle = - meta_screen_cast_create_dma_buf_handle (screen_cast, - priv->video_format.size.width, - priv->video_format.size.height); - } - else - { - dmabuf_handle = NULL; - } - - if (dmabuf_handle) - { - spa_data[0].type = SPA_DATA_DmaBuf; - spa_data[0].flags = SPA_DATA_FLAG_READWRITE; - spa_data[0].fd = cogl_dma_buf_handle_get_fd (dmabuf_handle); - - g_hash_table_insert (priv->dmabuf_handles, - GINT_TO_POINTER (spa_data[0].fd), - dmabuf_handle); - } - else - { - unsigned int seals; - - if (!(spa_data[0].type & (1 << SPA_DATA_MemFd))) - { - g_critical ("No supported PipeWire stream buffer data type could " - "be negotiated"); - return; - } - - /* Fallback to a memfd buffer */ - spa_data[0].type = SPA_DATA_MemFd; - spa_data[0].flags = SPA_DATA_FLAG_READWRITE; - spa_data[0].fd = memfd_create ("mutter-screen-cast-memfd", - MFD_CLOEXEC | MFD_ALLOW_SEALING); - if (spa_data[0].fd == -1) - { - g_critical ("Can't create memfd: %m"); - return; - } - spa_data[0].mapoffset = 0; - spa_data[0].maxsize = stride * priv->video_format.size.height; - - if (ftruncate (spa_data[0].fd, spa_data[0].maxsize) < 0) - { - close (spa_data[0].fd); - spa_data[0].fd = -1; - g_critical ("Can't truncate to %d: %m", spa_data[0].maxsize); - return; - } - - seals = F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL; - if (fcntl (spa_data[0].fd, F_ADD_SEALS, seals) == -1) - g_warning ("Failed to add seals: %m"); - - spa_data[0].data = mmap (NULL, - spa_data[0].maxsize, - PROT_READ | PROT_WRITE, - MAP_SHARED, - spa_data[0].fd, - spa_data[0].mapoffset); - if (spa_data[0].data == MAP_FAILED) - { - close (spa_data[0].fd); - spa_data[0].fd = -1; - g_critical ("Failed to mmap memory: %m"); - return; - } - } -} - -static void -on_stream_remove_buffer (void *data, - struct pw_buffer *buffer) -{ - MetaScreenCastStreamSrc *src = data; - MetaScreenCastStreamSrcPrivate *priv = - meta_screen_cast_stream_src_get_instance_private (src); - struct spa_buffer *spa_buffer = buffer->buffer; - struct spa_data *spa_data = spa_buffer->datas; - - if (spa_data[0].type == SPA_DATA_DmaBuf) - { - if (!g_hash_table_remove (priv->dmabuf_handles, GINT_TO_POINTER (spa_data[0].fd))) - g_critical ("Failed to remove non-exported DMA buffer"); - } - else if (spa_data[0].type == SPA_DATA_MemFd) - { - g_warn_if_fail (spa_data[0].fd > 0 || !spa_data[0].data); - - if (spa_data[0].fd > 0) - { - munmap (spa_data[0].data, spa_data[0].maxsize); - close (spa_data[0].fd); - } - } -} - -static const struct pw_stream_events stream_events = { - PW_VERSION_STREAM_EVENTS, - .state_changed = on_stream_state_changed, - .param_changed = on_stream_param_changed, - .add_buffer = on_stream_add_buffer, - .remove_buffer = on_stream_remove_buffer, -}; - -static struct pw_stream * -create_pipewire_stream (MetaScreenCastStreamSrc *src, - GError **error) -{ - MetaScreenCastStreamSrcPrivate *priv = - meta_screen_cast_stream_src_get_instance_private (src); - struct pw_stream *pipewire_stream; - uint8_t buffer[1024]; - struct spa_pod_builder pod_builder = - SPA_POD_BUILDER_INIT (buffer, sizeof (buffer)); - int width; - int height; - float frame_rate; - const struct spa_pod *params[1]; - int result; - - priv->node_id = SPA_ID_INVALID; - - pipewire_stream = pw_stream_new (priv->pipewire_core, - "meta-screen-cast-src", - NULL); - if (!pipewire_stream) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to create PipeWire stream: %s", - strerror (errno)); - return NULL; - } - - if (meta_screen_cast_stream_src_get_specs (src, &width, &height, &frame_rate)) - { - MetaFraction frame_rate_fraction; - struct spa_fraction max_framerate; - struct spa_fraction min_framerate; - - frame_rate_fraction = meta_fraction_from_double (frame_rate); - - min_framerate = SPA_FRACTION (1, 1); - max_framerate = SPA_FRACTION (frame_rate_fraction.num, - frame_rate_fraction.denom); - - params[0] = spa_pod_builder_add_object ( - &pod_builder, - SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, - SPA_FORMAT_mediaType, SPA_POD_Id (SPA_MEDIA_TYPE_video), - SPA_FORMAT_mediaSubtype, SPA_POD_Id (SPA_MEDIA_SUBTYPE_raw), - SPA_FORMAT_VIDEO_format, SPA_POD_Id (SPA_VIDEO_FORMAT_BGRx), - SPA_FORMAT_VIDEO_size, SPA_POD_Rectangle (&SPA_RECTANGLE (width, - height)), - SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction (&SPA_FRACTION (0, 1)), - SPA_FORMAT_VIDEO_maxFramerate, - SPA_POD_CHOICE_RANGE_Fraction (&max_framerate, - &min_framerate, - &max_framerate)); - } - else - { - params[0] = spa_pod_builder_add_object ( - &pod_builder, - SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, - SPA_FORMAT_mediaType, SPA_POD_Id (SPA_MEDIA_TYPE_video), - SPA_FORMAT_mediaSubtype, SPA_POD_Id (SPA_MEDIA_SUBTYPE_raw), - SPA_FORMAT_VIDEO_format, SPA_POD_Id (SPA_VIDEO_FORMAT_BGRx), - SPA_FORMAT_VIDEO_size, SPA_POD_CHOICE_RANGE_Rectangle (&DEFAULT_SIZE, - &MIN_SIZE, - &MAX_SIZE), - SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction (&SPA_FRACTION (0, 1)), - SPA_FORMAT_VIDEO_maxFramerate, - SPA_POD_CHOICE_RANGE_Fraction (&DEFAULT_FRAME_RATE, - &MIN_FRAME_RATE, - &MAX_FRAME_RATE)); - } - - pw_stream_add_listener (pipewire_stream, - &priv->pipewire_stream_listener, - &stream_events, - src); - - result = pw_stream_connect (pipewire_stream, - PW_DIRECTION_OUTPUT, - SPA_ID_INVALID, - (PW_STREAM_FLAG_DRIVER | - PW_STREAM_FLAG_ALLOC_BUFFERS), - params, G_N_ELEMENTS (params)); - if (result != 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Could not connect: %s", spa_strerror (result)); - return NULL; - } - - return pipewire_stream; -} - -static void -on_core_error (void *data, - uint32_t id, - int seq, - int res, - const char *message) -{ - MetaScreenCastStreamSrc *src = data; - - g_warning ("pipewire remote error: id:%u %s", id, message); - - if (id == PW_ID_CORE && res == -EPIPE) - meta_screen_cast_stream_src_close (src); -} - -static gboolean -pipewire_loop_source_prepare (GSource *base, - int *timeout) -{ - *timeout = -1; - return FALSE; -} - -static gboolean -pipewire_loop_source_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data) -{ - MetaPipeWireSource *pipewire_source = (MetaPipeWireSource *) source; - MetaScreenCastStreamSrc *src = pipewire_source->src; - MetaScreenCastStreamSrcPrivate *priv = - meta_screen_cast_stream_src_get_instance_private (src); - int result; - - result = pw_loop_iterate (pipewire_source->pipewire_loop, 0); - if (result < 0) - g_warning ("pipewire_loop_iterate failed: %s", spa_strerror (result)); - - if (priv->emit_closed_after_dispatch) - g_signal_emit (src, signals[CLOSED], 0); - - return TRUE; -} - -static void -pipewire_loop_source_finalize (GSource *source) -{ - MetaPipeWireSource *pipewire_source = (MetaPipeWireSource *) source; - - pw_loop_leave (pipewire_source->pipewire_loop); - pw_loop_destroy (pipewire_source->pipewire_loop); -} - -static GSourceFuncs pipewire_source_funcs = -{ - pipewire_loop_source_prepare, - NULL, - pipewire_loop_source_dispatch, - pipewire_loop_source_finalize -}; - -static MetaPipeWireSource * -create_pipewire_source (MetaScreenCastStreamSrc *src) -{ - MetaPipeWireSource *pipewire_source; - - pipewire_source = - (MetaPipeWireSource *) g_source_new (&pipewire_source_funcs, - sizeof (MetaPipeWireSource)); - pipewire_source->src = src; - pipewire_source->pipewire_loop = pw_loop_new (NULL); - if (!pipewire_source->pipewire_loop) - { - g_source_unref ((GSource *) pipewire_source); - return NULL; - } - - g_source_add_unix_fd (&pipewire_source->base, - pw_loop_get_fd (pipewire_source->pipewire_loop), - G_IO_IN | G_IO_ERR); - - pw_loop_enter (pipewire_source->pipewire_loop); - g_source_attach (&pipewire_source->base, NULL); - - return pipewire_source; -} - -static const struct pw_core_events core_events = { - PW_VERSION_CORE_EVENTS, - .error = on_core_error, -}; - -static gboolean -meta_screen_cast_stream_src_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (initable); - MetaScreenCastStreamSrcPrivate *priv = - meta_screen_cast_stream_src_get_instance_private (src); - - priv->pipewire_source = create_pipewire_source (src); - if (!priv->pipewire_source) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to create PipeWire source"); - return FALSE; - } - - priv->pipewire_context = pw_context_new (priv->pipewire_source->pipewire_loop, - NULL, 0); - if (!priv->pipewire_context) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to create pipewire context"); - return FALSE; - } - - priv->pipewire_core = pw_context_connect (priv->pipewire_context, NULL, 0); - if (!priv->pipewire_core) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Couldn't connect pipewire context"); - return FALSE; - } - - pw_core_add_listener (priv->pipewire_core, - &priv->pipewire_core_listener, - &core_events, - src); - - priv->pipewire_stream = create_pipewire_stream (src, error); - if (!priv->pipewire_stream) - return FALSE; - - return TRUE; -} - -static void -meta_screen_cast_stream_src_init_initable_iface (GInitableIface *iface) -{ - iface->init = meta_screen_cast_stream_src_initable_init; -} - -MetaScreenCastStream * -meta_screen_cast_stream_src_get_stream (MetaScreenCastStreamSrc *src) -{ - MetaScreenCastStreamSrcPrivate *priv = - meta_screen_cast_stream_src_get_instance_private (src); - - return priv->stream; -} - -static void -meta_screen_cast_stream_src_finalize (GObject *object) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (object); - MetaScreenCastStreamSrcPrivate *priv = - meta_screen_cast_stream_src_get_instance_private (src); - - if (meta_screen_cast_stream_src_is_enabled (src)) - meta_screen_cast_stream_src_disable (src); - - g_clear_pointer (&priv->pipewire_stream, pw_stream_destroy); - g_clear_pointer (&priv->dmabuf_handles, g_hash_table_destroy); - g_clear_pointer (&priv->pipewire_core, pw_core_disconnect); - g_clear_pointer (&priv->pipewire_context, pw_context_destroy); - g_source_destroy (&priv->pipewire_source->base); - g_source_unref (&priv->pipewire_source->base); - - G_OBJECT_CLASS (meta_screen_cast_stream_src_parent_class)->finalize (object); -} - -static void -meta_screen_cast_stream_src_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (object); - MetaScreenCastStreamSrcPrivate *priv = - meta_screen_cast_stream_src_get_instance_private (src); - - switch (prop_id) - { - case PROP_STREAM: - priv->stream = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_screen_cast_stream_src_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (object); - MetaScreenCastStreamSrcPrivate *priv = - meta_screen_cast_stream_src_get_instance_private (src); - - switch (prop_id) - { - case PROP_STREAM: - g_value_set_object (value, priv->stream); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_screen_cast_stream_src_init (MetaScreenCastStreamSrc *src) -{ - MetaScreenCastStreamSrcPrivate *priv = - meta_screen_cast_stream_src_get_instance_private (src); - - priv->dmabuf_handles = - g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) cogl_dma_buf_handle_free); -} - -static void -meta_screen_cast_stream_src_class_init (MetaScreenCastStreamSrcClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_screen_cast_stream_src_finalize; - object_class->set_property = meta_screen_cast_stream_src_set_property; - object_class->get_property = meta_screen_cast_stream_src_get_property; - - g_object_class_install_property (object_class, - PROP_STREAM, - g_param_spec_object ("stream", - "stream", - "MetaScreenCastStream", - META_TYPE_SCREEN_CAST_STREAM, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - signals[READY] = g_signal_new ("ready", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 1, - G_TYPE_UINT); - signals[CLOSED] = g_signal_new ("closed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); -} diff --git a/src/backends/meta-screen-cast-stream-src.h b/src/backends/meta-screen-cast-stream-src.h deleted file mode 100644 index 456b5bd97..000000000 --- a/src/backends/meta-screen-cast-stream-src.h +++ /dev/null @@ -1,117 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015-2017 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_SCREEN_CAST_STREAM_SRC_H -#define META_SCREEN_CAST_STREAM_SRC_H - -#include -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-cursor-renderer.h" -#include "backends/meta-cursor.h" -#include "backends/meta-renderer.h" -#include "clutter/clutter.h" -#include "cogl/cogl.h" -#include "meta/boxes.h" - -typedef struct _MetaScreenCastStream MetaScreenCastStream; - -typedef enum _MetaScreenCastRecordFlag -{ - META_SCREEN_CAST_RECORD_FLAG_NONE = 0, - META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY = 1 << 0, -} MetaScreenCastRecordFlag; - -#define META_TYPE_SCREEN_CAST_STREAM_SRC (meta_screen_cast_stream_src_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaScreenCastStreamSrc, - meta_screen_cast_stream_src, - META, SCREEN_CAST_STREAM_SRC, - GObject) - -struct _MetaScreenCastStreamSrcClass -{ - GObjectClass parent_class; - - gboolean (* get_specs) (MetaScreenCastStreamSrc *src, - int *width, - int *height, - float *frame_rate); - void (* enable) (MetaScreenCastStreamSrc *src); - void (* disable) (MetaScreenCastStreamSrc *src); - gboolean (* record_to_buffer) (MetaScreenCastStreamSrc *src, - int width, - int height, - int stride, - uint8_t *data, - GError **error); - gboolean (* record_to_framebuffer) (MetaScreenCastStreamSrc *src, - CoglFramebuffer *framebuffer, - GError **error); - void (* record_follow_up) (MetaScreenCastStreamSrc *src); - - gboolean (* get_videocrop) (MetaScreenCastStreamSrc *src, - MetaRectangle *crop_rect); - void (* set_cursor_metadata) (MetaScreenCastStreamSrc *src, - struct spa_meta_cursor *spa_meta_cursor); - - void (* notify_params_updated) (MetaScreenCastStreamSrc *src, - struct spa_video_info_raw *video_format); -}; - -void meta_screen_cast_stream_src_close (MetaScreenCastStreamSrc *src); - -void meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src, - MetaScreenCastRecordFlag flags); - -gboolean meta_screen_cast_stream_src_pending_follow_up_frame (MetaScreenCastStreamSrc *src); - -MetaScreenCastStream * meta_screen_cast_stream_src_get_stream (MetaScreenCastStreamSrc *src); - -gboolean meta_screen_cast_stream_src_draw_cursor_into (MetaScreenCastStreamSrc *src, - CoglTexture *cursor_texture, - float scale, - uint8_t *data, - GError **error); - -void meta_screen_cast_stream_src_unset_cursor_metadata (MetaScreenCastStreamSrc *src, - struct spa_meta_cursor *spa_meta_cursor); - -void meta_screen_cast_stream_src_set_cursor_position_metadata (MetaScreenCastStreamSrc *src, - struct spa_meta_cursor *spa_meta_cursor, - int x, - int y); - -void meta_screen_cast_stream_src_set_empty_cursor_sprite_metadata (MetaScreenCastStreamSrc *src, - struct spa_meta_cursor *spa_meta_cursor, - int x, - int y); - -void meta_screen_cast_stream_src_set_cursor_sprite_metadata (MetaScreenCastStreamSrc *src, - struct spa_meta_cursor *spa_meta_cursor, - MetaCursorSprite *cursor_sprite, - int x, - int y, - float scale); - -#endif /* META_SCREEN_CAST_STREAM_SRC_H */ diff --git a/src/backends/meta-screen-cast-stream.c b/src/backends/meta-screen-cast-stream.c deleted file mode 100644 index b8ab5abd5..000000000 --- a/src/backends/meta-screen-cast-stream.c +++ /dev/null @@ -1,383 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "backends/meta-screen-cast-stream.h" - -#include "backends/meta-screen-cast-session.h" - -#include "meta-private-enum-types.h" - -#define META_SCREEN_CAST_STREAM_DBUS_IFACE "org.gnome.Mutter.ScreenCast.Stream" -#define META_SCREEN_CAST_STREAM_DBUS_PATH "/org/gnome/Mutter/ScreenCast/Stream" - -enum -{ - PROP_0, - - PROP_SESSION, - PROP_CONNECTION, - PROP_CURSOR_MODE, - PROP_FLAGS, -}; - -enum -{ - CLOSED, - - N_SIGNALS -}; - -static guint signals[N_SIGNALS]; - -typedef struct _MetaScreenCastStreamPrivate -{ - MetaScreenCastSession *session; - - GDBusConnection *connection; - char *object_path; - - MetaScreenCastCursorMode cursor_mode; - MetaScreenCastFlag flags; - - MetaScreenCastStreamSrc *src; -} MetaScreenCastStreamPrivate; - -static void -meta_screen_cast_stream_init_initable_iface (GInitableIface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaScreenCastStream, - meta_screen_cast_stream, - META_DBUS_TYPE_SCREEN_CAST_STREAM_SKELETON, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - meta_screen_cast_stream_init_initable_iface) - G_ADD_PRIVATE (MetaScreenCastStream)) - -static MetaScreenCastStreamSrc * -meta_screen_cast_stream_create_src (MetaScreenCastStream *stream, - GError **error) -{ - return META_SCREEN_CAST_STREAM_GET_CLASS (stream)->create_src (stream, - error); -} - -static void -meta_screen_cast_stream_set_parameters (MetaScreenCastStream *stream, - GVariantBuilder *parameters_builder) -{ - META_SCREEN_CAST_STREAM_GET_CLASS (stream)->set_parameters (stream, - parameters_builder); -} - -static void -on_stream_src_closed (MetaScreenCastStreamSrc *src, - MetaScreenCastStream *stream) -{ - MetaScreenCastStreamPrivate *priv = - meta_screen_cast_stream_get_instance_private (stream); - - if (priv->src) - meta_screen_cast_stream_close (stream); -} - -static void -on_stream_src_ready (MetaScreenCastStreamSrc *src, - uint32_t node_id, - MetaScreenCastStream *stream) -{ - MetaScreenCastStreamPrivate *priv = - meta_screen_cast_stream_get_instance_private (stream); - GDBusConnection *connection = priv->connection; - char *peer_name; - - peer_name = meta_screen_cast_session_get_peer_name (priv->session); - g_dbus_connection_emit_signal (connection, - peer_name, - priv->object_path, - META_SCREEN_CAST_STREAM_DBUS_IFACE, - "PipeWireStreamAdded", - g_variant_new ("(u)", node_id), - NULL); -} - -MetaScreenCastSession * -meta_screen_cast_stream_get_session (MetaScreenCastStream *stream) -{ - MetaScreenCastStreamPrivate *priv = - meta_screen_cast_stream_get_instance_private (stream); - - return priv->session; -} - -gboolean -meta_screen_cast_stream_start (MetaScreenCastStream *stream, - GError **error) -{ - MetaScreenCastStreamPrivate *priv = - meta_screen_cast_stream_get_instance_private (stream); - MetaScreenCastStreamSrc *src; - - src = meta_screen_cast_stream_create_src (stream, error); - if (!src) - return FALSE; - - priv->src = src; - g_signal_connect (src, "ready", G_CALLBACK (on_stream_src_ready), stream); - g_signal_connect (src, "closed", G_CALLBACK (on_stream_src_closed), stream); - - return TRUE; -} - -void -meta_screen_cast_stream_close (MetaScreenCastStream *stream) -{ - MetaScreenCastStreamPrivate *priv = - meta_screen_cast_stream_get_instance_private (stream); - - g_clear_object (&priv->src); - - g_signal_emit (stream, signals[CLOSED], 0); -} - -char * -meta_screen_cast_stream_get_object_path (MetaScreenCastStream *stream) -{ - MetaScreenCastStreamPrivate *priv = - meta_screen_cast_stream_get_instance_private (stream); - - return priv->object_path; -} - -MetaScreenCastStreamSrc * -meta_screen_cast_stream_get_src (MetaScreenCastStream *stream) -{ - MetaScreenCastStreamPrivate *priv = - meta_screen_cast_stream_get_instance_private (stream); - - return priv->src; -} - -gboolean -meta_screen_cast_stream_transform_position (MetaScreenCastStream *stream, - double stream_x, - double stream_y, - double *x, - double *y) -{ - MetaScreenCastStreamClass *klass = META_SCREEN_CAST_STREAM_GET_CLASS (stream); - - return klass->transform_position (stream, stream_x, stream_y, x, y); -} - -MetaScreenCastCursorMode -meta_screen_cast_stream_get_cursor_mode (MetaScreenCastStream *stream) -{ - MetaScreenCastStreamPrivate *priv = - meta_screen_cast_stream_get_instance_private (stream); - - return priv->cursor_mode; -} - -MetaScreenCastFlag -meta_screen_cast_stream_get_flags (MetaScreenCastStream *stream) -{ - MetaScreenCastStreamPrivate *priv = - meta_screen_cast_stream_get_instance_private (stream); - - return priv->flags; -} - -static void -meta_screen_cast_stream_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaScreenCastStream *stream = META_SCREEN_CAST_STREAM (object); - MetaScreenCastStreamPrivate *priv = - meta_screen_cast_stream_get_instance_private (stream); - - switch (prop_id) - { - case PROP_SESSION: - priv->session = g_value_get_object (value); - break; - case PROP_CONNECTION: - priv->connection = g_value_get_object (value); - break; - case PROP_CURSOR_MODE: - priv->cursor_mode = g_value_get_uint (value); - break; - case PROP_FLAGS: - priv->flags = g_value_get_flags (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_screen_cast_stream_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaScreenCastStream *stream = META_SCREEN_CAST_STREAM (object); - MetaScreenCastStreamPrivate *priv = - meta_screen_cast_stream_get_instance_private (stream); - - switch (prop_id) - { - case PROP_SESSION: - g_value_set_object (value, priv->session); - break; - case PROP_CONNECTION: - g_value_set_object (value, priv->connection); - break; - case PROP_CURSOR_MODE: - g_value_set_uint (value, priv->cursor_mode); - break; - case PROP_FLAGS: - g_value_set_flags (value, priv->flags); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_screen_cast_stream_finalize (GObject *object) -{ - MetaScreenCastStream *stream = META_SCREEN_CAST_STREAM (object); - MetaScreenCastStreamPrivate *priv = - meta_screen_cast_stream_get_instance_private (stream); - - if (priv->src) - meta_screen_cast_stream_close (stream); - - g_clear_pointer (&priv->object_path, g_free); - - G_OBJECT_CLASS (meta_screen_cast_stream_parent_class)->finalize (object); -} - -static gboolean -meta_screen_cast_stream_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - MetaScreenCastStream *stream = META_SCREEN_CAST_STREAM (initable); - MetaDBusScreenCastStream *skeleton = META_DBUS_SCREEN_CAST_STREAM (stream); - MetaScreenCastStreamPrivate *priv = - meta_screen_cast_stream_get_instance_private (stream); - GVariantBuilder parameters_builder; - GVariant *parameters_variant; - static unsigned int global_stream_number = 0; - - g_variant_builder_init (¶meters_builder, G_VARIANT_TYPE_VARDICT); - meta_screen_cast_stream_set_parameters (stream, ¶meters_builder); - - parameters_variant = g_variant_builder_end (¶meters_builder); - meta_dbus_screen_cast_stream_set_parameters (skeleton, parameters_variant); - - priv->object_path = - g_strdup_printf (META_SCREEN_CAST_STREAM_DBUS_PATH "/u%u", - ++global_stream_number); - if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (stream), - priv->connection, - priv->object_path, - error)) - return FALSE; - - return TRUE; -} - -static void -meta_screen_cast_stream_init_initable_iface (GInitableIface *iface) -{ - iface->init = meta_screen_cast_stream_initable_init; -} - -static void -meta_screen_cast_stream_init (MetaScreenCastStream *stream) -{ -} - -static void -meta_screen_cast_stream_class_init (MetaScreenCastStreamClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_screen_cast_stream_finalize; - object_class->set_property = meta_screen_cast_stream_set_property; - object_class->get_property = meta_screen_cast_stream_get_property; - - g_object_class_install_property (object_class, - PROP_SESSION, - g_param_spec_object ("session", - "session", - "MetaScreenSession", - META_TYPE_SCREEN_CAST_SESSION, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (object_class, - PROP_CONNECTION, - g_param_spec_object ("connection", - "connection", - "GDBus connection", - G_TYPE_DBUS_CONNECTION, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (object_class, - PROP_CURSOR_MODE, - g_param_spec_uint ("cursor-mode", - "cursor-mode", - "Cursor mode", - META_SCREEN_CAST_CURSOR_MODE_HIDDEN, - META_SCREEN_CAST_CURSOR_MODE_METADATA, - META_SCREEN_CAST_CURSOR_MODE_HIDDEN, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (object_class, - PROP_FLAGS, - g_param_spec_flags ("flags", - "flags", - "Screen cast flags", - META_TYPE_SCREEN_CAST_FLAG, - META_SCREEN_CAST_FLAG_NONE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - signals[CLOSED] = g_signal_new ("closed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); -} diff --git a/src/backends/meta-screen-cast-stream.h b/src/backends/meta-screen-cast-stream.h deleted file mode 100644 index 3424def20..000000000 --- a/src/backends/meta-screen-cast-stream.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_SCREEN_CAST_STREAM_H -#define META_SCREEN_CAST_STREAM_H - -#include - -#include "backends/meta-screen-cast-stream-src.h" -#include "backends/meta-screen-cast.h" - -#include "meta-dbus-screen-cast.h" - -#define META_TYPE_SCREEN_CAST_STREAM (meta_screen_cast_stream_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaScreenCastStream, meta_screen_cast_stream, - META, SCREEN_CAST_STREAM, - MetaDBusScreenCastStreamSkeleton) - -struct _MetaScreenCastStreamClass -{ - MetaDBusScreenCastStreamSkeletonClass parent_class; - - MetaScreenCastStreamSrc * (* create_src) (MetaScreenCastStream *stream, - GError **error); - void (* set_parameters) (MetaScreenCastStream *stream, - GVariantBuilder *parameters_builder); - gboolean (* transform_position) (MetaScreenCastStream *stream, - double stream_x, - double stream_y, - double *x, - double *y); -}; - -MetaScreenCastSession * meta_screen_cast_stream_get_session (MetaScreenCastStream *stream); - -gboolean meta_screen_cast_stream_start (MetaScreenCastStream *stream, - GError **error); - -void meta_screen_cast_stream_close (MetaScreenCastStream *stream); - -char * meta_screen_cast_stream_get_object_path (MetaScreenCastStream *stream); - -MetaScreenCastStreamSrc * meta_screen_cast_stream_get_src (MetaScreenCastStream *stream); - -gboolean meta_screen_cast_stream_transform_position (MetaScreenCastStream *stream, - double stream_x, - double stream_y, - double *x, - double *y); - -MetaScreenCastCursorMode meta_screen_cast_stream_get_cursor_mode (MetaScreenCastStream *stream); - -MetaScreenCastFlag meta_screen_cast_stream_get_flags (MetaScreenCastStream *stream); - -#endif /* META_SCREEN_CAST_STREAM_H */ diff --git a/src/backends/meta-screen-cast-virtual-stream-src.c b/src/backends/meta-screen-cast-virtual-stream-src.c deleted file mode 100644 index 47a917da9..000000000 --- a/src/backends/meta-screen-cast-virtual-stream-src.c +++ /dev/null @@ -1,612 +0,0 @@ -/* - * Copyright (C) 2021 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "backends/meta-screen-cast-virtual-stream-src.h" - -#include "backends/meta-crtc-mode.h" -#include "backends/meta-cursor-tracker-private.h" -#include "backends/meta-screen-cast-session.h" -#include "backends/meta-stage-private.h" -#include "backends/meta-virtual-monitor.h" -#include "core/boxes-private.h" - -struct _MetaScreenCastVirtualStreamSrc -{ - MetaScreenCastStreamSrc parent; - - MetaVirtualMonitor *virtual_monitor; - - gboolean cursor_bitmap_invalid; - gboolean hw_cursor_inhibited; - - MetaStageWatch *watch; - - gulong position_invalidated_handler_id; - gulong cursor_changed_handler_id; - - gulong monitors_changed_handler_id; -}; - -static void -hw_cursor_inhibitor_iface_init (MetaHwCursorInhibitorInterface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaScreenCastVirtualStreamSrc, - meta_screen_cast_virtual_stream_src, - META_TYPE_SCREEN_CAST_STREAM_SRC, - G_IMPLEMENT_INTERFACE (META_TYPE_HW_CURSOR_INHIBITOR, - hw_cursor_inhibitor_iface_init)) - -static gboolean -meta_screen_cast_virtual_stream_src_get_specs (MetaScreenCastStreamSrc *src, - int *width, - int *height, - float *frame_rate) -{ - return FALSE; -} - -static MetaBackend * -backend_from_src (MetaScreenCastStreamSrc *src) -{ - MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src); - MetaScreenCastSession *session = meta_screen_cast_stream_get_session (stream); - MetaScreenCast *screen_cast = - meta_screen_cast_session_get_screen_cast (session); - - return meta_screen_cast_get_backend (screen_cast); -} - -static ClutterStageView * -view_from_src (MetaScreenCastStreamSrc *src) -{ - MetaScreenCastVirtualStreamSrc *virtual_src = - META_SCREEN_CAST_VIRTUAL_STREAM_SRC (src); - MetaVirtualMonitor *virtual_monitor = virtual_src->virtual_monitor; - MetaCrtc *crtc = meta_virtual_monitor_get_crtc (virtual_monitor); - MetaRenderer *renderer = meta_backend_get_renderer (backend_from_src (src)); - MetaRendererView *view = meta_renderer_get_view_for_crtc (renderer, crtc); - - return CLUTTER_STAGE_VIEW (view); -} - -static ClutterStage * -stage_from_src (MetaScreenCastStreamSrc *src) -{ - return CLUTTER_STAGE (meta_backend_get_stage (backend_from_src (src))); -} - -static gboolean -is_redraw_queued (MetaScreenCastVirtualStreamSrc *virtual_src) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (virtual_src); - - return clutter_stage_is_redraw_queued_on_view (stage_from_src (src), - view_from_src (src)); -} - -ClutterStageView * -meta_screen_cast_virtual_stream_src_get_view (MetaScreenCastVirtualStreamSrc *virtual_src) -{ - return view_from_src (META_SCREEN_CAST_STREAM_SRC (virtual_src)); -} - -static void -sync_cursor_state (MetaScreenCastVirtualStreamSrc *virtual_src) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (virtual_src); - MetaScreenCastRecordFlag flags; - - if (is_redraw_queued (virtual_src)) - return; - - if (meta_screen_cast_stream_src_pending_follow_up_frame (src)) - return; - - flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY; - meta_screen_cast_stream_src_maybe_record_frame (src, flags); -} - -static void -pointer_position_invalidated (MetaCursorTracker *cursor_tracker, - MetaScreenCastVirtualStreamSrc *virtual_src) -{ - sync_cursor_state (virtual_src); -} - -static void -cursor_changed (MetaCursorTracker *cursor_tracker, - MetaScreenCastVirtualStreamSrc *virtual_src) -{ - virtual_src->cursor_bitmap_invalid = TRUE; - sync_cursor_state (virtual_src); -} - -static void -inhibit_hw_cursor (MetaScreenCastVirtualStreamSrc *virtual_src) -{ - MetaHwCursorInhibitor *inhibitor; - MetaBackend *backend; - - g_return_if_fail (!virtual_src->hw_cursor_inhibited); - - backend = backend_from_src (META_SCREEN_CAST_STREAM_SRC (virtual_src)); - inhibitor = META_HW_CURSOR_INHIBITOR (virtual_src); - meta_backend_add_hw_cursor_inhibitor (backend, inhibitor); - - virtual_src->hw_cursor_inhibited = TRUE; -} - -static void -uninhibit_hw_cursor (MetaScreenCastVirtualStreamSrc *virtual_src) -{ - MetaHwCursorInhibitor *inhibitor; - MetaBackend *backend; - - g_return_if_fail (virtual_src->hw_cursor_inhibited); - - backend = backend_from_src (META_SCREEN_CAST_STREAM_SRC (virtual_src)); - inhibitor = META_HW_CURSOR_INHIBITOR (virtual_src); - meta_backend_remove_hw_cursor_inhibitor (backend, inhibitor); - - virtual_src->hw_cursor_inhibited = FALSE; -} - -static void -actors_painted (MetaStage *stage, - ClutterStageView *view, - ClutterPaintContext *paint_context, - gpointer user_data) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (user_data); - MetaScreenCastRecordFlag flags; - - flags = META_SCREEN_CAST_RECORD_FLAG_NONE; - meta_screen_cast_stream_src_maybe_record_frame (src, flags); -} - -static void -add_watch (MetaScreenCastVirtualStreamSrc *virtual_src) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (virtual_src); - MetaStage *meta_stage = META_STAGE (stage_from_src (src)); - - g_return_if_fail (!virtual_src->watch); - - virtual_src->watch = meta_stage_watch_view (meta_stage, - view_from_src (src), - META_STAGE_WATCH_AFTER_PAINT, - actors_painted, - virtual_src); -} - -static void -on_monitors_changed (MetaMonitorManager *monitor_manager, - MetaScreenCastVirtualStreamSrc *virtual_src) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (virtual_src); - MetaStage *stage = META_STAGE (stage_from_src (src)); - - meta_stage_remove_watch (stage, virtual_src->watch); - virtual_src->watch = NULL; - add_watch (virtual_src); -} - -static void -init_record_callbacks (MetaScreenCastVirtualStreamSrc *virtual_src) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (virtual_src); - MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src); - MetaBackend *backend = backend_from_src (src); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaCursorTracker *cursor_tracker = - meta_backend_get_cursor_tracker (backend); - - switch (meta_screen_cast_stream_get_cursor_mode (stream)) - { - case META_SCREEN_CAST_CURSOR_MODE_METADATA: - virtual_src->position_invalidated_handler_id = - g_signal_connect_after (cursor_tracker, "position-invalidated", - G_CALLBACK (pointer_position_invalidated), - virtual_src); - virtual_src->cursor_changed_handler_id = - g_signal_connect_after (cursor_tracker, "cursor-changed", - G_CALLBACK (cursor_changed), - virtual_src); - G_GNUC_FALLTHROUGH; - case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED: - case META_SCREEN_CAST_CURSOR_MODE_HIDDEN: - add_watch (virtual_src); - break; - } - - if (meta_screen_cast_stream_get_cursor_mode (stream) == - META_SCREEN_CAST_CURSOR_MODE_EMBEDDED) - inhibit_hw_cursor (virtual_src); - - virtual_src->monitors_changed_handler_id = - g_signal_connect (monitor_manager, "monitors-changed-internal", - G_CALLBACK (on_monitors_changed), - virtual_src); -} - -static void -meta_screen_cast_virtual_stream_src_enable (MetaScreenCastStreamSrc *src) -{ - MetaScreenCastVirtualStreamSrc *virtual_src = - META_SCREEN_CAST_VIRTUAL_STREAM_SRC (src); - MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src); - MetaBackend *backend = backend_from_src (src); - MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); - - switch (meta_screen_cast_stream_get_cursor_mode (stream)) - { - case META_SCREEN_CAST_CURSOR_MODE_METADATA: - case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED: - meta_cursor_tracker_track_position (cursor_tracker); - break; - case META_SCREEN_CAST_CURSOR_MODE_HIDDEN: - break; - } - - init_record_callbacks (virtual_src); - clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage_from_src (src)), - NULL); - clutter_stage_schedule_update (stage_from_src (src)); -} - -static void -meta_screen_cast_virtual_stream_src_disable (MetaScreenCastStreamSrc *src) -{ - MetaScreenCastVirtualStreamSrc *virtual_src = - META_SCREEN_CAST_VIRTUAL_STREAM_SRC (src); - MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src); - MetaBackend *backend = backend_from_src (src); - MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - - if (virtual_src->hw_cursor_inhibited) - uninhibit_hw_cursor (virtual_src); - - if (virtual_src->watch) - { - meta_stage_remove_watch (META_STAGE (stage_from_src (src)), - virtual_src->watch); - virtual_src->watch = NULL; - } - - g_clear_signal_handler (&virtual_src->position_invalidated_handler_id, - cursor_tracker); - g_clear_signal_handler (&virtual_src->cursor_changed_handler_id, - cursor_tracker); - - g_clear_signal_handler (&virtual_src->monitors_changed_handler_id, - monitor_manager); - - switch (meta_screen_cast_stream_get_cursor_mode (stream)) - { - case META_SCREEN_CAST_CURSOR_MODE_METADATA: - case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED: - meta_cursor_tracker_untrack_position (cursor_tracker); - break; - case META_SCREEN_CAST_CURSOR_MODE_HIDDEN: - break; - } - - g_clear_object (&virtual_src->virtual_monitor); -} - -static gboolean -meta_screen_cast_virtual_stream_src_record_to_buffer (MetaScreenCastStreamSrc *src, - int width, - int height, - int stride, - uint8_t *data, - GError **error) -{ - clutter_stage_capture_view_into (stage_from_src (src), - view_from_src (src), - NULL, - data, - stride); - - return TRUE; -} - -static gboolean -meta_screen_cast_virtual_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc *src, - CoglFramebuffer *framebuffer, - GError **error) -{ - ClutterStageView *view; - CoglFramebuffer *view_framebuffer; - - view = view_from_src (src); - view_framebuffer = clutter_stage_view_get_framebuffer (view); - if (!cogl_blit_framebuffer (view_framebuffer, - framebuffer, - 0, 0, - 0, 0, - cogl_framebuffer_get_width (view_framebuffer), - cogl_framebuffer_get_height (view_framebuffer), - error)) - return FALSE; - - cogl_framebuffer_flush (framebuffer); - return TRUE; -} - -static void -meta_screen_cast_virtual_stream_record_follow_up (MetaScreenCastStreamSrc *src) -{ - MetaRectangle damage; - - clutter_stage_view_get_layout (view_from_src (src), &damage); - damage.width = 1; - damage.height = 1; - - clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage_from_src (src)), - &damage); -} - -static gboolean -is_cursor_in_stream (MetaScreenCastVirtualStreamSrc *virtual_src) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (virtual_src); - MetaBackend *backend = backend_from_src (src); - MetaCursorRenderer *cursor_renderer = - meta_backend_get_cursor_renderer (backend); - ClutterStageView *stage_view = view_from_src (src); - MetaRectangle view_layout; - graphene_rect_t view_rect; - MetaCursorSprite *cursor_sprite; - - clutter_stage_view_get_layout (stage_view, &view_layout); - view_rect = meta_rectangle_to_graphene_rect (&view_layout); - - cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer); - if (cursor_sprite) - { - graphene_rect_t cursor_rect; - - cursor_rect = meta_cursor_renderer_calculate_rect (cursor_renderer, - cursor_sprite); - return graphene_rect_intersection (&cursor_rect, &view_rect, NULL); - } - else - { - MetaCursorTracker *cursor_tracker = - meta_backend_get_cursor_tracker (backend); - graphene_point_t cursor_position; - - meta_cursor_tracker_get_pointer (cursor_tracker, &cursor_position, NULL); - return graphene_rect_contains_point (&view_rect, - &cursor_position); - } -} - -static void -meta_screen_cast_virtual_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src, - struct spa_meta_cursor *spa_meta_cursor) -{ - MetaScreenCastVirtualStreamSrc *virtual_src = - META_SCREEN_CAST_VIRTUAL_STREAM_SRC (src); - MetaBackend *backend = backend_from_src (src); - MetaCursorRenderer *cursor_renderer = - meta_backend_get_cursor_renderer (backend); - MetaCursorTracker *cursor_tracker = - meta_backend_get_cursor_tracker (backend); - MetaCursorSprite *cursor_sprite; - ClutterStageView *stage_view; - MetaRectangle view_layout; - float view_scale; - graphene_rect_t view_rect; - graphene_point_t cursor_position; - int x, y; - - cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer); - - if (!meta_cursor_tracker_get_pointer_visible (cursor_tracker) || - !is_cursor_in_stream (virtual_src)) - { - meta_screen_cast_stream_src_unset_cursor_metadata (src, - spa_meta_cursor); - return; - } - - stage_view = view_from_src (src); - clutter_stage_view_get_layout (stage_view, &view_layout); - view_rect = meta_rectangle_to_graphene_rect (&view_layout); - view_scale = clutter_stage_view_get_scale (stage_view); - - meta_cursor_tracker_get_pointer (cursor_tracker, &cursor_position, NULL); - cursor_position.x -= view_rect.origin.x; - cursor_position.y -= view_rect.origin.y; - cursor_position.x *= view_scale; - cursor_position.y *= view_scale; - - x = (int) roundf (cursor_position.x); - y = (int) roundf (cursor_position.y); - - if (virtual_src->cursor_bitmap_invalid) - { - if (cursor_sprite) - { - float cursor_scale; - float scale; - - cursor_scale = meta_cursor_sprite_get_texture_scale (cursor_sprite); - scale = view_scale * cursor_scale; - meta_screen_cast_stream_src_set_cursor_sprite_metadata (src, - spa_meta_cursor, - cursor_sprite, - x, y, - scale); - } - else - { - meta_screen_cast_stream_src_set_empty_cursor_sprite_metadata (src, - spa_meta_cursor, - x, y); - } - - virtual_src->cursor_bitmap_invalid = FALSE; - } - else - { - meta_screen_cast_stream_src_set_cursor_position_metadata (src, - spa_meta_cursor, - x, y); - } -} - -static MetaVirtualMonitor * -create_virtual_monitor (MetaScreenCastVirtualStreamSrc *virtual_src, - struct spa_video_info_raw *video_format, - GError **error) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (virtual_src); - MetaBackend *backend = backend_from_src (src); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - static int virtual_monitor_src_seq = 0; - int width, height; - float refresh_rate; - g_autofree char *serial = NULL; - g_autoptr (MetaVirtualMonitorInfo) info = NULL; - - width = video_format->size.width; - height = video_format->size.height; - refresh_rate = ((float) video_format->max_framerate.num / - video_format->max_framerate.denom); - serial = g_strdup_printf ("0x%.6x", ++virtual_monitor_src_seq); - info = meta_virtual_monitor_info_new (width, height, refresh_rate, - "MetaVendor", - "Virtual remote monitor", - serial); - return meta_monitor_manager_create_virtual_monitor (monitor_manager, - info, - error); -} - -static void -ensure_virtual_monitor (MetaScreenCastVirtualStreamSrc *virtual_src, - struct spa_video_info_raw *video_format) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (virtual_src); - MetaBackend *backend = backend_from_src (src); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - g_autoptr (GError) error = NULL; - MetaVirtualMonitor *virtual_monitor; - - virtual_monitor = virtual_src->virtual_monitor; - if (virtual_monitor) - { - MetaCrtcMode *crtc_mode = - meta_virtual_monitor_get_crtc_mode (virtual_monitor); - const MetaCrtcModeInfo *mode_info = meta_crtc_mode_get_info (crtc_mode); - - if (mode_info->width == video_format->size.width && - mode_info->height == video_format->size.height) - return; - - g_clear_object (&virtual_src->virtual_monitor); - } - - virtual_monitor = create_virtual_monitor (virtual_src, video_format, &error); - if (!virtual_monitor) - { - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (virtual_src); - - g_warning ("Failed to create virtual monitor with size %dx%d: %s", - video_format->size.width, video_format->size.height, - error->message); - meta_screen_cast_stream_src_close (src); - return; - } - virtual_src->virtual_monitor = virtual_monitor; - - meta_monitor_manager_reload (monitor_manager); -} - -static void -meta_screen_cast_virtual_stream_src_notify_params_updated (MetaScreenCastStreamSrc *src, - struct spa_video_info_raw *video_format) -{ - MetaScreenCastVirtualStreamSrc *virtual_src = - META_SCREEN_CAST_VIRTUAL_STREAM_SRC (src); - - ensure_virtual_monitor (virtual_src, video_format); -} - -MetaScreenCastVirtualStreamSrc * -meta_screen_cast_virtual_stream_src_new (MetaScreenCastVirtualStream *virtual_stream, - GError **error) -{ - return g_initable_new (META_TYPE_SCREEN_CAST_VIRTUAL_STREAM_SRC, NULL, error, - "stream", virtual_stream, - NULL); -} - -static gboolean -meta_screen_cast_virtual_stream_src_is_cursor_inhibited (MetaHwCursorInhibitor *inhibitor) -{ - MetaScreenCastVirtualStreamSrc *virtual_src = - META_SCREEN_CAST_VIRTUAL_STREAM_SRC (inhibitor); - - return is_cursor_in_stream (virtual_src); -} - -static void -hw_cursor_inhibitor_iface_init (MetaHwCursorInhibitorInterface *iface) -{ - iface->is_cursor_inhibited = - meta_screen_cast_virtual_stream_src_is_cursor_inhibited; -} - -static void -meta_screen_cast_virtual_stream_src_init (MetaScreenCastVirtualStreamSrc *virtual_src) -{ -} - -static void -meta_screen_cast_virtual_stream_src_class_init (MetaScreenCastVirtualStreamSrcClass *klass) -{ - MetaScreenCastStreamSrcClass *src_class = - META_SCREEN_CAST_STREAM_SRC_CLASS (klass); - - src_class->get_specs = meta_screen_cast_virtual_stream_src_get_specs; - src_class->enable = meta_screen_cast_virtual_stream_src_enable; - src_class->disable = meta_screen_cast_virtual_stream_src_disable; - src_class->record_to_buffer = - meta_screen_cast_virtual_stream_src_record_to_buffer; - src_class->record_to_framebuffer = - meta_screen_cast_virtual_stream_src_record_to_framebuffer; - src_class->record_follow_up = - meta_screen_cast_virtual_stream_record_follow_up; - src_class->set_cursor_metadata = - meta_screen_cast_virtual_stream_src_set_cursor_metadata; - src_class->notify_params_updated = - meta_screen_cast_virtual_stream_src_notify_params_updated; -} diff --git a/src/backends/meta-screen-cast-virtual-stream-src.h b/src/backends/meta-screen-cast-virtual-stream-src.h deleted file mode 100644 index a891166bd..000000000 --- a/src/backends/meta-screen-cast-virtual-stream-src.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2021 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_SCREEN_CAST_VIRTUAL_STREAM_SRC_H -#define META_SCREEN_CAST_VIRTUAL_STREAM_SRC_H - -#include "backends/meta-screen-cast-stream-src.h" -#include "backends/meta-screen-cast-virtual-stream.h" - -#define META_TYPE_SCREEN_CAST_VIRTUAL_STREAM_SRC (meta_screen_cast_virtual_stream_src_get_type ()) -G_DECLARE_FINAL_TYPE (MetaScreenCastVirtualStreamSrc, - meta_screen_cast_virtual_stream_src, - META, SCREEN_CAST_VIRTUAL_STREAM_SRC, - MetaScreenCastStreamSrc) - -MetaScreenCastVirtualStreamSrc * meta_screen_cast_virtual_stream_src_new (MetaScreenCastVirtualStream *virtual_stream, - GError **error); - -ClutterStageView * meta_screen_cast_virtual_stream_src_get_view (MetaScreenCastVirtualStreamSrc *virtual_src); - -#endif /* META_SCREEN_CAST_VIRTUAL_STREAM_SRC_H */ diff --git a/src/backends/meta-screen-cast-virtual-stream.c b/src/backends/meta-screen-cast-virtual-stream.c deleted file mode 100644 index 34dd2a00c..000000000 --- a/src/backends/meta-screen-cast-virtual-stream.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2021 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "backends/meta-screen-cast-virtual-stream.h" - -#include "backends/meta-screen-cast-virtual-stream-src.h" -#include "backends/meta-virtual-monitor.h" - - -struct _MetaScreenCastVirtualStream -{ - MetaScreenCastStream parent; -}; - -G_DEFINE_TYPE (MetaScreenCastVirtualStream, - meta_screen_cast_virtual_stream, - META_TYPE_SCREEN_CAST_STREAM) - -MetaScreenCastVirtualStream * -meta_screen_cast_virtual_stream_new (MetaScreenCastSession *session, - GDBusConnection *connection, - MetaScreenCastCursorMode cursor_mode, - MetaScreenCastFlag flags, - GError **error) -{ - MetaScreenCastVirtualStream *virtual_stream; - - virtual_stream = g_initable_new (META_TYPE_SCREEN_CAST_VIRTUAL_STREAM, - NULL, - error, - "session", session, - "connection", connection, - "cursor-mode", cursor_mode, - "flags", flags, - NULL); - if (!virtual_stream) - return NULL; - - return virtual_stream; -} - -static MetaScreenCastStreamSrc * -meta_screen_cast_virtual_stream_create_src (MetaScreenCastStream *stream, - GError **error) -{ - MetaScreenCastVirtualStream *virtual_stream = - META_SCREEN_CAST_VIRTUAL_STREAM (stream); - MetaScreenCastVirtualStreamSrc *virtual_stream_src; - - virtual_stream_src = meta_screen_cast_virtual_stream_src_new (virtual_stream, - error); - if (!virtual_stream_src) - return NULL; - - return META_SCREEN_CAST_STREAM_SRC (virtual_stream_src); -} - -static void -meta_screen_cast_virtual_stream_set_parameters (MetaScreenCastStream *stream, - GVariantBuilder *parameters_builder) -{ -} - -static gboolean -meta_screen_cast_virtual_stream_transform_position (MetaScreenCastStream *stream, - double stream_x, - double stream_y, - double *x, - double *y) -{ - MetaScreenCastStreamSrc *src = meta_screen_cast_stream_get_src (stream); - MetaScreenCastVirtualStreamSrc *virtual_src = - META_SCREEN_CAST_VIRTUAL_STREAM_SRC (src); - ClutterStageView *view; - MetaRectangle view_layout; - - view = meta_screen_cast_virtual_stream_src_get_view (virtual_src); - if (!view) - return FALSE; - - clutter_stage_view_get_layout (view, &view_layout); - *x = stream_x + view_layout.x; - *y = stream_y + view_layout.y; - - return TRUE; -} - -static void -meta_screen_cast_virtual_stream_init (MetaScreenCastVirtualStream *virtual_stream) -{ -} - -static void -meta_screen_cast_virtual_stream_class_init (MetaScreenCastVirtualStreamClass *klass) -{ - MetaScreenCastStreamClass *stream_class = - META_SCREEN_CAST_STREAM_CLASS (klass); - - stream_class->create_src = meta_screen_cast_virtual_stream_create_src; - stream_class->set_parameters = meta_screen_cast_virtual_stream_set_parameters; - stream_class->transform_position = meta_screen_cast_virtual_stream_transform_position; -} diff --git a/src/backends/meta-screen-cast-virtual-stream.h b/src/backends/meta-screen-cast-virtual-stream.h deleted file mode 100644 index 422db5e26..000000000 --- a/src/backends/meta-screen-cast-virtual-stream.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2021 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_SCREEN_CAST_VIRTUAL_STREAM_H -#define META_SCREEN_CAST_VIRTUAL_STREAM_H - -#include "backends/meta-screen-cast-stream.h" - -#define META_TYPE_SCREEN_CAST_VIRTUAL_STREAM (meta_screen_cast_virtual_stream_get_type ()) -G_DECLARE_FINAL_TYPE (MetaScreenCastVirtualStream, - meta_screen_cast_virtual_stream, - META, SCREEN_CAST_VIRTUAL_STREAM, - MetaScreenCastStream) - -MetaScreenCastVirtualStream * meta_screen_cast_virtual_stream_new (MetaScreenCastSession *session, - GDBusConnection *connection, - MetaScreenCastCursorMode cursor_mode, - MetaScreenCastFlag flags, - GError **error); - -MetaVirtualMonitor * meta_screen_cast_virtual_stream_get_virtual_monitor (MetaScreenCastVirtualStream *virtual_stream); - -#endif /* META_SCREEN_CAST_VIRTUAL_STREAM_H */ diff --git a/src/backends/meta-screen-cast-window-stream-src.c b/src/backends/meta-screen-cast-window-stream-src.c deleted file mode 100644 index 3fa932b4b..000000000 --- a/src/backends/meta-screen-cast-window-stream-src.c +++ /dev/null @@ -1,614 +0,0 @@ -/* - * Copyright (C) 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "backends/meta-screen-cast-window-stream-src.h" - -#include "backends/meta-backend-private.h" -#include "backends/meta-cursor-tracker-private.h" -#include "backends/meta-screen-cast-session.h" -#include "backends/meta-screen-cast-window.h" -#include "backends/meta-screen-cast-window-stream.h" -#include "compositor/meta-window-actor-private.h" - -struct _MetaScreenCastWindowStreamSrc -{ - MetaScreenCastStreamSrc parent; - - MetaScreenCastWindow *screen_cast_window; - - unsigned long screen_cast_window_damaged_handler_id; - unsigned long screen_cast_window_destroyed_handler_id; - unsigned long position_invalidated_handler_id; - unsigned long cursor_changed_handler_id; - - gboolean cursor_bitmap_invalid; -}; - -G_DEFINE_TYPE (MetaScreenCastWindowStreamSrc, - meta_screen_cast_window_stream_src, - META_TYPE_SCREEN_CAST_STREAM_SRC) - -static MetaBackend * -get_backend (MetaScreenCastWindowStreamSrc *window_src) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src); - MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src); - MetaScreenCastSession *session = meta_screen_cast_stream_get_session (stream); - MetaScreenCast *screen_cast = - meta_screen_cast_session_get_screen_cast (session); - - return meta_screen_cast_get_backend (screen_cast); -} - -static MetaScreenCastWindowStream * -get_window_stream (MetaScreenCastWindowStreamSrc *window_src) -{ - MetaScreenCastStreamSrc *src; - MetaScreenCastStream *stream; - - src = META_SCREEN_CAST_STREAM_SRC (window_src); - stream = meta_screen_cast_stream_src_get_stream (src); - - return META_SCREEN_CAST_WINDOW_STREAM (stream); -} - -static MetaWindow * -get_window (MetaScreenCastWindowStreamSrc *window_src) -{ - MetaScreenCastWindowStream *window_stream; - - window_stream = get_window_stream (window_src); - - return meta_screen_cast_window_stream_get_window (window_stream); -} - -static int -get_stream_width (MetaScreenCastWindowStreamSrc *window_src) -{ - MetaScreenCastWindowStream *window_stream; - - window_stream = get_window_stream (window_src); - - return meta_screen_cast_window_stream_get_width (window_stream); -} - -static int -get_stream_height (MetaScreenCastWindowStreamSrc *window_src) -{ - MetaScreenCastWindowStream *window_stream; - - window_stream = get_window_stream (window_src); - - return meta_screen_cast_window_stream_get_height (window_stream); -} - -static void -maybe_draw_cursor_sprite (MetaScreenCastWindowStreamSrc *window_src, - uint8_t *data, - MetaRectangle *stream_rect) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src); - MetaBackend *backend = get_backend (window_src); - MetaCursorRenderer *cursor_renderer = - meta_backend_get_cursor_renderer (backend); - MetaCursorTracker *cursor_tracker = - meta_backend_get_cursor_tracker (backend); - MetaCursorSprite *cursor_sprite; - CoglTexture *cursor_texture; - MetaScreenCastWindow *screen_cast_window; - graphene_point_t cursor_position; - graphene_point_t relative_cursor_position; - cairo_surface_t *cursor_surface; - uint8_t *cursor_surface_data; - GError *error = NULL; - cairo_surface_t *stream_surface; - int width, height; - float scale; - int hotspot_x, hotspot_y; - cairo_t *cr; - - cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer); - if (!cursor_sprite) - return; - - cursor_texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); - if (!cursor_texture) - return; - - screen_cast_window = window_src->screen_cast_window; - meta_cursor_tracker_get_pointer (cursor_tracker, &cursor_position, NULL); - if (!meta_screen_cast_window_transform_cursor_position (screen_cast_window, - cursor_sprite, - &cursor_position, - &scale, - &relative_cursor_position)) - return; - - meta_cursor_sprite_get_hotspot (cursor_sprite, &hotspot_x, &hotspot_y); - - width = cogl_texture_get_width (cursor_texture) * scale; - height = cogl_texture_get_height (cursor_texture) * scale; - cursor_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - width, height); - - cursor_surface_data = cairo_image_surface_get_data (cursor_surface); - if (!meta_screen_cast_stream_src_draw_cursor_into (src, - cursor_texture, - scale, - cursor_surface_data, - &error)) - { - g_warning ("Failed to draw cursor: %s", error->message); - g_error_free (error); - cairo_surface_destroy (cursor_surface); - return; - } - - stream_surface = - cairo_image_surface_create_for_data (data, CAIRO_FORMAT_ARGB32, - stream_rect->width, - stream_rect->height, - stream_rect->width * 4); - - cr = cairo_create (stream_surface); - cairo_surface_mark_dirty (cursor_surface); - cairo_surface_flush (cursor_surface); - cairo_set_source_surface (cr, cursor_surface, - relative_cursor_position.x - hotspot_x * scale, - relative_cursor_position.y - hotspot_y * scale); - cairo_paint (cr); - cairo_destroy (cr); - cairo_surface_destroy (stream_surface); - cairo_surface_destroy (cursor_surface); -} - -static void -maybe_blit_cursor_sprite (MetaScreenCastWindowStreamSrc *window_src, - CoglFramebuffer *framebuffer, - MetaRectangle *stream_rect) -{ - MetaBackend *backend = get_backend (window_src); - CoglContext *cogl_context = - clutter_backend_get_cogl_context (clutter_get_default_backend ()); - MetaCursorRenderer *cursor_renderer = - meta_backend_get_cursor_renderer (backend); - MetaCursorTracker *cursor_tracker = - meta_backend_get_cursor_tracker (backend); - MetaScreenCastWindow *screen_cast_window; - MetaCursorSprite *cursor_sprite; - graphene_point_t relative_cursor_position; - graphene_point_t cursor_position; - CoglTexture *cursor_texture; - CoglPipeline *pipeline; - int width, height; - float scale; - int hotspot_x, hotspot_y; - float x, y; - - cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer); - if (!cursor_sprite) - return; - - cursor_texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); - if (!cursor_texture) - return; - - screen_cast_window = window_src->screen_cast_window; - meta_cursor_tracker_get_pointer (cursor_tracker, &cursor_position, NULL); - if (!meta_screen_cast_window_transform_cursor_position (screen_cast_window, - cursor_sprite, - &cursor_position, - &scale, - &relative_cursor_position)) - return; - - meta_cursor_sprite_get_hotspot (cursor_sprite, &hotspot_x, &hotspot_y); - - x = (relative_cursor_position.x - hotspot_x) * scale; - y = (relative_cursor_position.y - hotspot_y) * scale; - width = cogl_texture_get_width (cursor_texture); - height = cogl_texture_get_height (cursor_texture); - - pipeline = cogl_pipeline_new (cogl_context); - cogl_pipeline_set_layer_texture (pipeline, 0, cursor_texture); - cogl_pipeline_set_layer_filters (pipeline, 0, - COGL_PIPELINE_FILTER_LINEAR, - COGL_PIPELINE_FILTER_LINEAR); - - cogl_framebuffer_draw_rectangle (framebuffer, - pipeline, - x, y, - x + width, y + height); - - cogl_object_unref (pipeline); -} - -static gboolean -capture_into (MetaScreenCastWindowStreamSrc *window_src, - int width, - int height, - int stride, - uint8_t *data) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src); - MetaRectangle stream_rect; - MetaScreenCastStream *stream; - - stream_rect = (MetaRectangle) { - .width = width, - .height = height, - }; - - meta_screen_cast_window_capture_into (window_src->screen_cast_window, - &stream_rect, data); - - stream = meta_screen_cast_stream_src_get_stream (src); - switch (meta_screen_cast_stream_get_cursor_mode (stream)) - { - case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED: - maybe_draw_cursor_sprite (window_src, data, &stream_rect); - break; - case META_SCREEN_CAST_CURSOR_MODE_METADATA: - case META_SCREEN_CAST_CURSOR_MODE_HIDDEN: - break; - } - - return TRUE; -} - -static gboolean -meta_screen_cast_window_stream_src_get_specs (MetaScreenCastStreamSrc *src, - int *width, - int *height, - float *frame_rate) -{ - MetaScreenCastWindowStreamSrc *window_src = - META_SCREEN_CAST_WINDOW_STREAM_SRC (src); - - *width = get_stream_width (window_src); - *height = get_stream_height (window_src); - *frame_rate = 60.0f; - - return TRUE; -} - -static gboolean -meta_screen_cast_window_stream_src_get_videocrop (MetaScreenCastStreamSrc *src, - MetaRectangle *crop_rect) -{ - MetaScreenCastWindowStreamSrc *window_src = - META_SCREEN_CAST_WINDOW_STREAM_SRC (src); - MetaRectangle stream_rect; - - meta_screen_cast_window_get_buffer_bounds (window_src->screen_cast_window, - crop_rect); - - stream_rect.x = 0; - stream_rect.y = 0; - stream_rect.width = get_stream_width (window_src); - stream_rect.height = get_stream_height (window_src); - - meta_rectangle_intersect (crop_rect, &stream_rect, crop_rect); - - return TRUE; -} - -static void -meta_screen_cast_window_stream_src_stop (MetaScreenCastWindowStreamSrc *window_src) - -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src); - MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src); - MetaBackend *backend = get_backend (window_src); - MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); - - if (!window_src->screen_cast_window) - return; - - g_clear_signal_handler (&window_src->screen_cast_window_damaged_handler_id, - window_src->screen_cast_window); - g_clear_signal_handler (&window_src->screen_cast_window_destroyed_handler_id, - window_src->screen_cast_window); - g_clear_signal_handler (&window_src->position_invalidated_handler_id, - cursor_tracker); - g_clear_signal_handler (&window_src->cursor_changed_handler_id, - cursor_tracker); - - switch (meta_screen_cast_stream_get_cursor_mode (stream)) - { - case META_SCREEN_CAST_CURSOR_MODE_METADATA: - case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED: - meta_cursor_tracker_untrack_position (cursor_tracker); - break; - case META_SCREEN_CAST_CURSOR_MODE_HIDDEN: - break; - } -} - -static void -screen_cast_window_damaged (MetaWindowActor *actor, - MetaScreenCastWindowStreamSrc *window_src) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src); - MetaScreenCastRecordFlag flags; - - flags = META_SCREEN_CAST_RECORD_FLAG_NONE; - meta_screen_cast_stream_src_maybe_record_frame (src, flags); -} - -static void -screen_cast_window_destroyed (MetaWindowActor *actor, - MetaScreenCastWindowStreamSrc *window_src) -{ - meta_screen_cast_window_stream_src_stop (window_src); - window_src->screen_cast_window = NULL; -} - -static void -sync_cursor_state (MetaScreenCastWindowStreamSrc *window_src) -{ - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src); - MetaScreenCastRecordFlag flags; - - if (meta_screen_cast_window_has_damage (window_src->screen_cast_window)) - return; - - flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY; - meta_screen_cast_stream_src_maybe_record_frame (src, flags); -} - -static void -pointer_position_invalidated (MetaCursorTracker *cursor_tracker, - MetaScreenCastWindowStreamSrc *window_src) -{ - sync_cursor_state (window_src); -} - -static void -cursor_changed (MetaCursorTracker *cursor_tracker, - MetaScreenCastWindowStreamSrc *window_src) -{ - window_src->cursor_bitmap_invalid = TRUE; - sync_cursor_state (window_src); -} - -static void -meta_screen_cast_window_stream_src_enable (MetaScreenCastStreamSrc *src) -{ - MetaScreenCastWindowStreamSrc *window_src = - META_SCREEN_CAST_WINDOW_STREAM_SRC (src); - MetaBackend *backend = get_backend (window_src); - MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); - MetaWindowActor *window_actor; - MetaScreenCastStream *stream; - MetaScreenCastRecordFlag flags; - - window_actor = meta_window_actor_from_window (get_window (window_src)); - if (!window_actor) - return; - - window_src->screen_cast_window = META_SCREEN_CAST_WINDOW (window_actor); - - window_src->screen_cast_window_damaged_handler_id = - g_signal_connect (window_src->screen_cast_window, - "damaged", - G_CALLBACK (screen_cast_window_damaged), - window_src); - - window_src->screen_cast_window_destroyed_handler_id = - g_signal_connect (window_src->screen_cast_window, - "destroy", - G_CALLBACK (screen_cast_window_destroyed), - window_src); - - stream = meta_screen_cast_stream_src_get_stream (src); - switch (meta_screen_cast_stream_get_cursor_mode (stream)) - { - case META_SCREEN_CAST_CURSOR_MODE_METADATA: - case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED: - window_src->position_invalidated_handler_id = - g_signal_connect_after (cursor_tracker, "position-invalidated", - G_CALLBACK (pointer_position_invalidated), - window_src); - window_src->cursor_changed_handler_id = - g_signal_connect_after (cursor_tracker, "cursor-changed", - G_CALLBACK (cursor_changed), - window_src); - meta_cursor_tracker_track_position (cursor_tracker); - break; - case META_SCREEN_CAST_CURSOR_MODE_HIDDEN: - break; - } - - flags = META_SCREEN_CAST_RECORD_FLAG_NONE; - meta_screen_cast_stream_src_maybe_record_frame (src, flags); -} - -static void -meta_screen_cast_window_stream_src_disable (MetaScreenCastStreamSrc *src) -{ - MetaScreenCastWindowStreamSrc *window_src = - META_SCREEN_CAST_WINDOW_STREAM_SRC (src); - - meta_screen_cast_window_stream_src_stop (window_src); -} - -static gboolean -meta_screen_cast_window_stream_src_record_to_buffer (MetaScreenCastStreamSrc *src, - int width, - int height, - int stride, - uint8_t *data, - GError **error) -{ - MetaScreenCastWindowStreamSrc *window_src = - META_SCREEN_CAST_WINDOW_STREAM_SRC (src); - - capture_into (window_src, width, height, stride, data); - - return TRUE; -} - -static gboolean -meta_screen_cast_window_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc *src, - CoglFramebuffer *framebuffer, - GError **error) -{ - MetaScreenCastWindowStreamSrc *window_src = - META_SCREEN_CAST_WINDOW_STREAM_SRC (src); - MetaScreenCastStream *stream; - MetaRectangle stream_rect; - - stream_rect.x = 0; - stream_rect.y = 0; - stream_rect.width = cogl_framebuffer_get_width (framebuffer); - stream_rect.height = cogl_framebuffer_get_height (framebuffer); - - if (!meta_screen_cast_window_blit_to_framebuffer (window_src->screen_cast_window, - &stream_rect, - framebuffer)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to blit window content to framebuffer"); - return FALSE; - } - - stream = meta_screen_cast_stream_src_get_stream (src); - switch (meta_screen_cast_stream_get_cursor_mode (stream)) - { - case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED: - maybe_blit_cursor_sprite (window_src, framebuffer, &stream_rect); - break; - case META_SCREEN_CAST_CURSOR_MODE_METADATA: - case META_SCREEN_CAST_CURSOR_MODE_HIDDEN: - break; - } - - cogl_framebuffer_flush (framebuffer); - - return TRUE; -} - -static void -meta_screen_cast_window_stream_record_follow_up (MetaScreenCastStreamSrc *src) -{ - MetaScreenCastRecordFlag flags; - - flags = META_SCREEN_CAST_RECORD_FLAG_NONE; - meta_screen_cast_stream_src_maybe_record_frame (src, flags); -} - -static void -meta_screen_cast_window_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src, - struct spa_meta_cursor *spa_meta_cursor) -{ - MetaScreenCastWindowStreamSrc *window_src = - META_SCREEN_CAST_WINDOW_STREAM_SRC (src); - MetaBackend *backend = get_backend (window_src); - MetaCursorRenderer *cursor_renderer = - meta_backend_get_cursor_renderer (backend); - MetaCursorTracker *cursor_tracker = - meta_backend_get_cursor_tracker (backend); - MetaScreenCastWindow *screen_cast_window = window_src->screen_cast_window; - MetaCursorSprite *cursor_sprite; - graphene_point_t cursor_position; - float scale; - graphene_point_t relative_cursor_position; - int x, y; - - cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer); - meta_cursor_tracker_get_pointer (cursor_tracker, &cursor_position, NULL); - - if (!meta_cursor_tracker_get_pointer_visible (cursor_tracker) || - !meta_screen_cast_window_transform_cursor_position (screen_cast_window, - cursor_sprite, - &cursor_position, - &scale, - &relative_cursor_position)) - { - meta_screen_cast_stream_src_unset_cursor_metadata (src, - spa_meta_cursor); - return; - } - - x = (int) roundf (relative_cursor_position.x); - y = (int) roundf (relative_cursor_position.y); - - if (window_src->cursor_bitmap_invalid) - { - if (cursor_sprite) - { - meta_screen_cast_stream_src_set_cursor_sprite_metadata (src, - spa_meta_cursor, - cursor_sprite, - x, y, - scale); - } - else - { - meta_screen_cast_stream_src_set_empty_cursor_sprite_metadata (src, - spa_meta_cursor, - x, y); - } - window_src->cursor_bitmap_invalid = FALSE; - } - else - { - meta_screen_cast_stream_src_set_cursor_position_metadata (src, - spa_meta_cursor, - x, y); - } -} - -MetaScreenCastWindowStreamSrc * -meta_screen_cast_window_stream_src_new (MetaScreenCastWindowStream *window_stream, - GError **error) -{ - return g_initable_new (META_TYPE_SCREEN_CAST_WINDOW_STREAM_SRC, NULL, error, - "stream", window_stream, - NULL); -} - -static void -meta_screen_cast_window_stream_src_init (MetaScreenCastWindowStreamSrc *window_src) -{ - window_src->cursor_bitmap_invalid = TRUE; -} - -static void -meta_screen_cast_window_stream_src_class_init (MetaScreenCastWindowStreamSrcClass *klass) -{ - MetaScreenCastStreamSrcClass *src_class = - META_SCREEN_CAST_STREAM_SRC_CLASS (klass); - - src_class->get_specs = meta_screen_cast_window_stream_src_get_specs; - src_class->enable = meta_screen_cast_window_stream_src_enable; - src_class->disable = meta_screen_cast_window_stream_src_disable; - src_class->record_to_buffer = - meta_screen_cast_window_stream_src_record_to_buffer; - src_class->record_to_framebuffer = - meta_screen_cast_window_stream_src_record_to_framebuffer; - src_class->record_follow_up = - meta_screen_cast_window_stream_record_follow_up; - src_class->get_videocrop = meta_screen_cast_window_stream_src_get_videocrop; - src_class->set_cursor_metadata = meta_screen_cast_window_stream_src_set_cursor_metadata; -} diff --git a/src/backends/meta-screen-cast-window-stream-src.h b/src/backends/meta-screen-cast-window-stream-src.h deleted file mode 100644 index 37f786979..000000000 --- a/src/backends/meta-screen-cast-window-stream-src.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_SCREEN_CAST_WINDOW_STREAM_SRC_H -#define META_SCREEN_CAST_WINDOW_STREAM_SRC_H - -#include "backends/meta-screen-cast-stream-src.h" - -typedef struct _MetaScreenCastWindowStream MetaScreenCastWindowStream; - -#define META_TYPE_SCREEN_CAST_WINDOW_STREAM_SRC (meta_screen_cast_window_stream_src_get_type ()) -G_DECLARE_FINAL_TYPE (MetaScreenCastWindowStreamSrc, - meta_screen_cast_window_stream_src, - META, SCREEN_CAST_WINDOW_STREAM_SRC, - MetaScreenCastStreamSrc) - -MetaScreenCastWindowStreamSrc * meta_screen_cast_window_stream_src_new (MetaScreenCastWindowStream *window_stream, - GError **error); - -#endif /* META_SCREEN_CAST_WINDOW_STREAM_SRC_H */ diff --git a/src/backends/meta-screen-cast-window-stream.c b/src/backends/meta-screen-cast-window-stream.c deleted file mode 100644 index 6f42a446e..000000000 --- a/src/backends/meta-screen-cast-window-stream.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (C) 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "backends/meta-screen-cast-window-stream.h" - -#include "backends/meta-logical-monitor.h" -#include "backends/meta-monitor-manager-private.h" -#include "backends/meta-screen-cast-window.h" -#include "backends/meta-screen-cast-window-stream-src.h" -#include "compositor/meta-window-actor-private.h" -#include "core/window-private.h" - -enum -{ - PROP_0, - - PROP_WINDOW, -}; - -struct _MetaScreenCastWindowStream -{ - MetaScreenCastStream parent; - - MetaWindow *window; - - int stream_width; - int stream_height; - int logical_width; - int logical_height; - - unsigned long window_unmanaged_handler_id; -}; - -static GInitableIface *initable_parent_iface; - -static void -meta_screen_cast_window_stream_init_initable_iface (GInitableIface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaScreenCastWindowStream, - meta_screen_cast_window_stream, - META_TYPE_SCREEN_CAST_STREAM, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - meta_screen_cast_window_stream_init_initable_iface)) - -MetaWindow * -meta_screen_cast_window_stream_get_window (MetaScreenCastWindowStream *window_stream) -{ - return window_stream->window; -} - -int -meta_screen_cast_window_stream_get_width (MetaScreenCastWindowStream *window_stream) -{ - return window_stream->stream_width; -} - -int -meta_screen_cast_window_stream_get_height (MetaScreenCastWindowStream *window_stream) -{ - return window_stream->stream_height; -} - -MetaScreenCastWindowStream * -meta_screen_cast_window_stream_new (MetaScreenCastSession *session, - GDBusConnection *connection, - MetaWindow *window, - MetaScreenCastCursorMode cursor_mode, - MetaScreenCastFlag flags, - GError **error) -{ - return g_initable_new (META_TYPE_SCREEN_CAST_WINDOW_STREAM, - NULL, - error, - "session", session, - "connection", connection, - "cursor-mode", cursor_mode, - "flags", flags, - "window", window, - NULL); -} - -static MetaScreenCastStreamSrc * -meta_screen_cast_window_stream_create_src (MetaScreenCastStream *stream, - GError **error) -{ - MetaScreenCastWindowStream *window_stream = - META_SCREEN_CAST_WINDOW_STREAM (stream); - MetaScreenCastWindowStreamSrc *window_stream_src; - - window_stream_src = meta_screen_cast_window_stream_src_new (window_stream, - error); - if (!window_stream_src) - return NULL; - - return META_SCREEN_CAST_STREAM_SRC (window_stream_src); -} - -static void -meta_screen_cast_window_stream_set_parameters (MetaScreenCastStream *stream, - GVariantBuilder *parameters_builder) -{ - MetaScreenCastWindowStream *window_stream = - META_SCREEN_CAST_WINDOW_STREAM (stream); - - g_variant_builder_add (parameters_builder, "{sv}", - "size", - g_variant_new ("(ii)", - window_stream->logical_width, - window_stream->logical_height)); -} - -static gboolean -meta_screen_cast_window_stream_transform_position (MetaScreenCastStream *stream, - double stream_x, - double stream_y, - double *x, - double *y) -{ - MetaScreenCastWindowStream *window_stream = - META_SCREEN_CAST_WINDOW_STREAM (stream); - MetaScreenCastWindow *screen_cast_window = - META_SCREEN_CAST_WINDOW (meta_window_actor_from_window (window_stream->window)); - - meta_screen_cast_window_transform_relative_position (screen_cast_window, - stream_x, - stream_y, - x, - y); - return TRUE; -} - -static void -on_window_unmanaged (MetaScreenCastWindowStream *window_stream) -{ - meta_screen_cast_stream_close (META_SCREEN_CAST_STREAM (window_stream)); -} - -static void -meta_screen_cast_window_stream_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaScreenCastWindowStream *window_stream = - META_SCREEN_CAST_WINDOW_STREAM (object); - - switch (prop_id) - { - case PROP_WINDOW: - window_stream->window = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_screen_cast_window_stream_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaScreenCastWindowStream *window_stream = - META_SCREEN_CAST_WINDOW_STREAM (object); - - switch (prop_id) - { - case PROP_WINDOW: - g_value_set_object (value, window_stream->window); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_screen_cast_window_stream_finalize (GObject *object) -{ - MetaScreenCastWindowStream *window_stream = - META_SCREEN_CAST_WINDOW_STREAM (object); - - g_clear_signal_handler (&window_stream->window_unmanaged_handler_id, - window_stream->window); - - G_OBJECT_CLASS (meta_screen_cast_window_stream_parent_class)->finalize (object); -} - -static gboolean -meta_screen_cast_window_stream_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - MetaScreenCastWindowStream *window_stream = - META_SCREEN_CAST_WINDOW_STREAM (initable); - MetaWindow *window = window_stream->window; - MetaLogicalMonitor *logical_monitor; - int scale; - - logical_monitor = meta_window_get_main_logical_monitor (window); - if (!logical_monitor) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Main logical monitor not found"); - return FALSE; - } - - window_stream->window_unmanaged_handler_id = - g_signal_connect_swapped (window, "unmanaged", - G_CALLBACK (on_window_unmanaged), - window_stream); - - if (meta_is_stage_views_scaled ()) - scale = (int) ceilf (meta_logical_monitor_get_scale (logical_monitor)); - else - scale = 1; - - /* We cannot set the stream size to the exact size of the window, because - * windows can be resized, whereas streams cannot. - * So we set a size equals to the size of the logical monitor for the window. - */ - window_stream->logical_width = logical_monitor->rect.width; - window_stream->logical_height = logical_monitor->rect.height; - window_stream->stream_width = logical_monitor->rect.width * scale; - window_stream->stream_height = logical_monitor->rect.height * scale; - - return initable_parent_iface->init (initable, cancellable, error); -} - -static void -meta_screen_cast_window_stream_init_initable_iface (GInitableIface *iface) -{ - initable_parent_iface = g_type_interface_peek_parent (iface); - - iface->init = meta_screen_cast_window_stream_initable_init; -} - -static void -meta_screen_cast_window_stream_init (MetaScreenCastWindowStream *window_stream) -{ -} - -static void -meta_screen_cast_window_stream_class_init (MetaScreenCastWindowStreamClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaScreenCastStreamClass *stream_class = - META_SCREEN_CAST_STREAM_CLASS (klass); - - object_class->set_property = meta_screen_cast_window_stream_set_property; - object_class->get_property = meta_screen_cast_window_stream_get_property; - object_class->finalize = meta_screen_cast_window_stream_finalize; - - stream_class->create_src = meta_screen_cast_window_stream_create_src; - stream_class->set_parameters = meta_screen_cast_window_stream_set_parameters; - stream_class->transform_position = meta_screen_cast_window_stream_transform_position; - - g_object_class_install_property (object_class, - PROP_WINDOW, - g_param_spec_object ("window", - "window", - "MetaWindow", - META_TYPE_WINDOW, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); -} diff --git a/src/backends/meta-screen-cast-window-stream.h b/src/backends/meta-screen-cast-window-stream.h deleted file mode 100644 index 0acceaac6..000000000 --- a/src/backends/meta-screen-cast-window-stream.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_SCREEN_CAST_WINDOW_STREAM_H -#define META_SCREEN_CAST_WINDOW_STREAM_H - -#include - -#include "backends/meta-screen-cast-stream.h" -#include "meta/window.h" - -#define META_TYPE_SCREEN_CAST_WINDOW_STREAM (meta_screen_cast_window_stream_get_type ()) -G_DECLARE_FINAL_TYPE (MetaScreenCastWindowStream, - meta_screen_cast_window_stream, - META, SCREEN_CAST_WINDOW_STREAM, - MetaScreenCastStream) - -MetaScreenCastWindowStream * meta_screen_cast_window_stream_new (MetaScreenCastSession *session, - GDBusConnection *connection, - MetaWindow *window, - MetaScreenCastCursorMode cursor_mode, - MetaScreenCastFlag flags, - GError **error); - -MetaWindow * meta_screen_cast_window_stream_get_window (MetaScreenCastWindowStream *window_stream); -int meta_screen_cast_window_stream_get_width (MetaScreenCastWindowStream *window_stream); -int meta_screen_cast_window_stream_get_height (MetaScreenCastWindowStream *window_stream); - -#endif /* META_SCREEN_CAST_WINDOW_STREAM_H */ diff --git a/src/backends/meta-screen-cast-window.c b/src/backends/meta-screen-cast-window.c deleted file mode 100644 index ab3e4ebe3..000000000 --- a/src/backends/meta-screen-cast-window.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "backends/meta-screen-cast-window.h" - -G_DEFINE_INTERFACE (MetaScreenCastWindow, meta_screen_cast_window, G_TYPE_OBJECT) - -static void -meta_screen_cast_window_default_init (MetaScreenCastWindowInterface *iface) -{ -} - -void -meta_screen_cast_window_get_buffer_bounds (MetaScreenCastWindow *screen_cast_window, - MetaRectangle *bounds) -{ - META_SCREEN_CAST_WINDOW_GET_IFACE (screen_cast_window)->get_buffer_bounds (screen_cast_window, - bounds); -} - -void -meta_screen_cast_window_transform_relative_position (MetaScreenCastWindow *screen_cast_window, - double x, - double y, - double *x_out, - double *y_out) -{ - META_SCREEN_CAST_WINDOW_GET_IFACE (screen_cast_window)->transform_relative_position (screen_cast_window, - x, - y, - x_out, - y_out); -} - -gboolean -meta_screen_cast_window_transform_cursor_position (MetaScreenCastWindow *screen_cast_window, - MetaCursorSprite *cursor_sprite, - graphene_point_t *cursor_position, - float *out_cursor_scale, - graphene_point_t *out_relative_cursor_position) -{ - MetaScreenCastWindowInterface *iface = - META_SCREEN_CAST_WINDOW_GET_IFACE (screen_cast_window); - - return iface->transform_cursor_position (screen_cast_window, - cursor_sprite, - cursor_position, - out_cursor_scale, - out_relative_cursor_position); -} - -void -meta_screen_cast_window_capture_into (MetaScreenCastWindow *screen_cast_window, - MetaRectangle *bounds, - uint8_t *data) -{ - META_SCREEN_CAST_WINDOW_GET_IFACE (screen_cast_window)->capture_into (screen_cast_window, - bounds, - data); -} - -gboolean -meta_screen_cast_window_blit_to_framebuffer (MetaScreenCastWindow *screen_cast_window, - MetaRectangle *bounds, - CoglFramebuffer *framebuffer) -{ - MetaScreenCastWindowInterface *iface = - META_SCREEN_CAST_WINDOW_GET_IFACE (screen_cast_window); - - return iface->blit_to_framebuffer (screen_cast_window, bounds, framebuffer); -} - -gboolean -meta_screen_cast_window_has_damage (MetaScreenCastWindow *screen_cast_window) -{ - MetaScreenCastWindowInterface *iface = - META_SCREEN_CAST_WINDOW_GET_IFACE (screen_cast_window); - - return iface->has_damage (screen_cast_window); -} diff --git a/src/backends/meta-screen-cast-window.h b/src/backends/meta-screen-cast-window.h deleted file mode 100644 index e149646ed..000000000 --- a/src/backends/meta-screen-cast-window.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_SCREEN_CAST_WINDOW_H -#define META_SCREEN_CAST_WINDOW_H - -#include -#include - -#include "backends/meta-cursor.h" -#include "meta/boxes.h" - -G_BEGIN_DECLS - -#define META_TYPE_SCREEN_CAST_WINDOW (meta_screen_cast_window_get_type ()) -G_DECLARE_INTERFACE (MetaScreenCastWindow, meta_screen_cast_window, - META, SCREEN_CAST_WINDOW, GObject) - -struct _MetaScreenCastWindowInterface -{ - GTypeInterface parent_iface; - - void (*get_buffer_bounds) (MetaScreenCastWindow *screen_cast_window, - MetaRectangle *bounds); - - void (*transform_relative_position) (MetaScreenCastWindow *screen_cast_window, - double x, - double y, - double *x_out, - double *y_out); - - gboolean (*transform_cursor_position) (MetaScreenCastWindow *screen_cast_window, - MetaCursorSprite *cursor_sprite, - graphene_point_t *cursor_position, - float *out_cursor_scale, - graphene_point_t *out_relative_cursor_position); - - void (*capture_into) (MetaScreenCastWindow *screen_cast_window, - MetaRectangle *bounds, - uint8_t *data); - - gboolean (*blit_to_framebuffer) (MetaScreenCastWindow *screen_cast_window, - MetaRectangle *bounds, - CoglFramebuffer *framebuffer); - - gboolean (*has_damage) (MetaScreenCastWindow *screen_cast_window); -}; - -void meta_screen_cast_window_get_buffer_bounds (MetaScreenCastWindow *screen_cast_window, - MetaRectangle *bounds); - -void meta_screen_cast_window_transform_relative_position (MetaScreenCastWindow *screen_cast_window, - double x, - double y, - double *x_out, - double *y_out); - -gboolean meta_screen_cast_window_transform_cursor_position (MetaScreenCastWindow *screen_cast_window, - MetaCursorSprite *cursor_sprite, - graphene_point_t *cursor_position, - float *out_cursor_scale, - graphene_point_t *out_relative_cursor_position); - -void meta_screen_cast_window_capture_into (MetaScreenCastWindow *screen_cast_window, - MetaRectangle *bounds, - uint8_t *data); - -gboolean meta_screen_cast_window_blit_to_framebuffer (MetaScreenCastWindow *screen_cast_window, - MetaRectangle *bounds, - CoglFramebuffer *framebuffer); - -gboolean meta_screen_cast_window_has_damage (MetaScreenCastWindow *screen_cast_window); - -G_END_DECLS - -#endif /* META_SCREEN_CAST_WINDOW_H */ diff --git a/src/backends/meta-screen-cast.c b/src/backends/meta-screen-cast.c deleted file mode 100644 index 6162b8d27..000000000 --- a/src/backends/meta-screen-cast.c +++ /dev/null @@ -1,385 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015-2017 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "backends/meta-screen-cast.h" - -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-remote-desktop-session.h" -#include "backends/meta-screen-cast-session.h" - -#define META_SCREEN_CAST_DBUS_SERVICE "org.gnome.Mutter.ScreenCast" -#define META_SCREEN_CAST_DBUS_PATH "/org/gnome/Mutter/ScreenCast" -#define META_SCREEN_CAST_API_VERSION 4 - -struct _MetaScreenCast -{ - MetaDBusScreenCastSkeleton parent; - - int dbus_name_id; - - int inhibit_count; - - GList *sessions; - - MetaDbusSessionWatcher *session_watcher; - MetaBackend *backend; - - gboolean disable_dma_bufs; -}; - -static void -meta_screen_cast_init_iface (MetaDBusScreenCastIface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaScreenCast, meta_screen_cast, - META_DBUS_TYPE_SCREEN_CAST_SKELETON, - G_IMPLEMENT_INTERFACE (META_DBUS_TYPE_SCREEN_CAST, - meta_screen_cast_init_iface)) - -void -meta_screen_cast_inhibit (MetaScreenCast *screen_cast) -{ - screen_cast->inhibit_count++; - if (screen_cast->inhibit_count == 1) - { - while (screen_cast->sessions) - { - MetaScreenCastSession *session = screen_cast->sessions->data; - - meta_screen_cast_session_close (session); - } - } -} - -void -meta_screen_cast_uninhibit (MetaScreenCast *screen_cast) -{ - g_return_if_fail (screen_cast->inhibit_count > 0); - - screen_cast->inhibit_count--; -} - -GDBusConnection * -meta_screen_cast_get_connection (MetaScreenCast *screen_cast) -{ - GDBusInterfaceSkeleton *interface_skeleton = - G_DBUS_INTERFACE_SKELETON (screen_cast); - - return g_dbus_interface_skeleton_get_connection (interface_skeleton); -} - -MetaBackend * -meta_screen_cast_get_backend (MetaScreenCast *screen_cast) -{ - return screen_cast->backend; -} - -void -meta_screen_cast_disable_dma_bufs (MetaScreenCast *screen_cast) -{ - screen_cast->disable_dma_bufs = TRUE; -} - -CoglDmaBufHandle * -meta_screen_cast_create_dma_buf_handle (MetaScreenCast *screen_cast, - int width, - int height) -{ - ClutterBackend *clutter_backend = - meta_backend_get_clutter_backend (screen_cast->backend); - CoglContext *cogl_context = - clutter_backend_get_cogl_context (clutter_backend); - CoglRenderer *cogl_renderer = cogl_context_get_renderer (cogl_context); - g_autoptr (GError) error = NULL; - CoglDmaBufHandle *dmabuf_handle; - - if (screen_cast->disable_dma_bufs) - return NULL; - - dmabuf_handle = cogl_renderer_create_dma_buf (cogl_renderer, - width, height, - &error); - if (!dmabuf_handle) - { - g_warning ("Failed to allocate DMA buffer, " - "disabling DMA buffer based screen casting: %s", - error->message); - screen_cast->disable_dma_bufs = TRUE; - return NULL; - } - - return dmabuf_handle; -} - -static gboolean -register_remote_desktop_screen_cast_session (MetaScreenCastSession *session, - const char *remote_desktop_session_id, - GError **error) -{ - MetaScreenCast *screen_cast = - meta_screen_cast_session_get_screen_cast (session); - MetaBackend *backend = meta_screen_cast_get_backend (screen_cast); - MetaRemoteDesktop *remote_desktop = meta_backend_get_remote_desktop (backend); - MetaRemoteDesktopSession *remote_desktop_session; - - remote_desktop_session = - meta_remote_desktop_get_session (remote_desktop, remote_desktop_session_id); - if (!remote_desktop_session) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "No remote desktop session found"); - return FALSE; - } - - if (!meta_remote_desktop_session_register_screen_cast (remote_desktop_session, - session, - error)) - return FALSE; - - return TRUE; -} - -static void -on_session_closed (MetaScreenCastSession *session, - MetaScreenCast *screen_cast) -{ - screen_cast->sessions = g_list_remove (screen_cast->sessions, session); -} - -static gboolean -handle_create_session (MetaDBusScreenCast *skeleton, - GDBusMethodInvocation *invocation, - GVariant *properties) -{ - MetaScreenCast *screen_cast = META_SCREEN_CAST (skeleton); - const char *peer_name; - MetaScreenCastSession *session; - GError *error = NULL; - const char *session_path; - const char *client_dbus_name; - char *remote_desktop_session_id = NULL; - gboolean disable_animations; - MetaScreenCastSessionType session_type; - - if (screen_cast->inhibit_count > 0) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_ACCESS_DENIED, - "Session creation inhibited"); - - return TRUE; - } - - g_variant_lookup (properties, "remote-desktop-session-id", "s", - &remote_desktop_session_id); - - if (remote_desktop_session_id) - session_type = META_SCREEN_CAST_SESSION_TYPE_REMOTE_DESKTOP; - else - session_type = META_SCREEN_CAST_SESSION_TYPE_NORMAL; - - peer_name = g_dbus_method_invocation_get_sender (invocation); - session = meta_screen_cast_session_new (screen_cast, - session_type, - peer_name, - &error); - if (!session) - { - g_warning ("Failed to create screen cast session: %s", - error->message); - - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "Failed to create session: %s", - error->message); - g_error_free (error); - - return TRUE; - } - - if (remote_desktop_session_id) - { - if (!register_remote_desktop_screen_cast_session (session, - remote_desktop_session_id, - &error)) - { - g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, - G_DBUS_ERROR_FAILED, - "%s", error->message); - g_error_free (error); - g_object_unref (session); - return TRUE; - } - } - - if (g_variant_lookup (properties, "disable-animations", "b", - &disable_animations)) - { - meta_screen_cast_session_set_disable_animations (session, - disable_animations); - } - - client_dbus_name = g_dbus_method_invocation_get_sender (invocation); - meta_dbus_session_watcher_watch_session (screen_cast->session_watcher, - client_dbus_name, - META_DBUS_SESSION (session)); - - session_path = meta_screen_cast_session_get_object_path (session); - meta_dbus_screen_cast_complete_create_session (skeleton, - invocation, - session_path); - - screen_cast->sessions = g_list_append (screen_cast->sessions, session); - - g_signal_connect (session, "session-closed", - G_CALLBACK (on_session_closed), - screen_cast); - - return TRUE; -} - -static void -meta_screen_cast_init_iface (MetaDBusScreenCastIface *iface) -{ - iface->handle_create_session = handle_create_session; -} - -static void -on_bus_acquired (GDBusConnection *connection, - const char *name, - gpointer user_data) -{ - MetaScreenCast *screen_cast = user_data; - GDBusInterfaceSkeleton *interface_skeleton = - G_DBUS_INTERFACE_SKELETON (screen_cast); - GError *error = NULL; - - if (!g_dbus_interface_skeleton_export (interface_skeleton, - connection, - META_SCREEN_CAST_DBUS_PATH, - &error)) - g_warning ("Failed to export remote desktop object: %s", error->message); -} - -static void -on_name_acquired (GDBusConnection *connection, - const char *name, - gpointer user_data) -{ - g_info ("Acquired name %s", name); -} - -static void -on_name_lost (GDBusConnection *connection, - const char *name, - gpointer user_data) -{ - g_warning ("Lost or failed to acquire name %s", name); -} - -static void -meta_screen_cast_constructed (GObject *object) -{ - MetaScreenCast *screen_cast = META_SCREEN_CAST (object); - - screen_cast->dbus_name_id = - g_bus_own_name (G_BUS_TYPE_SESSION, - META_SCREEN_CAST_DBUS_SERVICE, - G_BUS_NAME_OWNER_FLAGS_NONE, - on_bus_acquired, - on_name_acquired, - on_name_lost, - screen_cast, - NULL); -} - -static void -meta_screen_cast_finalize (GObject *object) -{ - MetaScreenCast *screen_cast = META_SCREEN_CAST (object); - - if (screen_cast->dbus_name_id) - g_bus_unown_name (screen_cast->dbus_name_id); - - g_assert (!screen_cast->sessions); - - G_OBJECT_CLASS (meta_screen_cast_parent_class)->finalize (object); -} - -static void -on_prepare_shutdown (MetaBackend *backend, - MetaScreenCast *screen_cast) -{ - while (screen_cast->sessions) - { - MetaScreenCastSession *session = screen_cast->sessions->data; - - if (meta_screen_cast_session_get_session_type (session) != - META_SCREEN_CAST_SESSION_TYPE_REMOTE_DESKTOP) - meta_screen_cast_session_close (session); - } -} - -MetaScreenCast * -meta_screen_cast_new (MetaBackend *backend, - MetaDbusSessionWatcher *session_watcher) -{ - MetaScreenCast *screen_cast; - - screen_cast = g_object_new (META_TYPE_SCREEN_CAST, NULL); - screen_cast->backend = backend; - screen_cast->session_watcher = session_watcher; - - g_signal_connect (backend, "prepare-shutdown", - G_CALLBACK (on_prepare_shutdown), - screen_cast); - - return screen_cast; -} - - -static void -meta_screen_cast_init (MetaScreenCast *screen_cast) -{ - static gboolean is_pipewire_initialized = FALSE; - - if (!is_pipewire_initialized) - { - pw_init (NULL, NULL); - is_pipewire_initialized = TRUE; - } - - meta_dbus_screen_cast_set_version (META_DBUS_SCREEN_CAST (screen_cast), - META_SCREEN_CAST_API_VERSION); -} - -static void -meta_screen_cast_class_init (MetaScreenCastClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->constructed = meta_screen_cast_constructed; - object_class->finalize = meta_screen_cast_finalize; -} diff --git a/src/backends/meta-screen-cast.h b/src/backends/meta-screen-cast.h deleted file mode 100644 index be297e28d..000000000 --- a/src/backends/meta-screen-cast.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015-2017 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_SCREEN_CAST_H -#define META_SCREEN_CAST_H - -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-dbus-session-watcher.h" - -#include "meta-dbus-screen-cast.h" - -typedef enum _MetaScreenCastCursorMode -{ - META_SCREEN_CAST_CURSOR_MODE_HIDDEN = 0, - META_SCREEN_CAST_CURSOR_MODE_EMBEDDED = 1, - META_SCREEN_CAST_CURSOR_MODE_METADATA = 2, -} MetaScreenCastCursorMode; - -typedef enum _MetaScreenCastFlag -{ - META_SCREEN_CAST_FLAG_NONE = 0, - META_SCREEN_CAST_FLAG_IS_RECORDING = 1 << 0, - META_SCREEN_CAST_FLAG_IS_PLATFORM = 1 << 1, -} MetaScreenCastFlag; - -#define META_TYPE_SCREEN_CAST (meta_screen_cast_get_type ()) -G_DECLARE_FINAL_TYPE (MetaScreenCast, meta_screen_cast, - META, SCREEN_CAST, - MetaDBusScreenCastSkeleton) - -void meta_screen_cast_inhibit (MetaScreenCast *screen_cast); - -void meta_screen_cast_uninhibit (MetaScreenCast *screen_cast); - -GDBusConnection * meta_screen_cast_get_connection (MetaScreenCast *screen_cast); - -MetaBackend * meta_screen_cast_get_backend (MetaScreenCast *screen_cast); - -void meta_screen_cast_disable_dma_bufs (MetaScreenCast *screen_cast); - -CoglDmaBufHandle * meta_screen_cast_create_dma_buf_handle (MetaScreenCast *screen_cast, - int width, - int height); - -MetaScreenCast * meta_screen_cast_new (MetaBackend *backend, - MetaDbusSessionWatcher *session_watcher); - -#endif /* META_SCREEN_CAST_H */ diff --git a/src/backends/meta-settings-private.h b/src/backends/meta-settings-private.h deleted file mode 100644 index cde7e0439..000000000 --- a/src/backends/meta-settings-private.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 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_SETTINGS_PRIVATE_H -#define META_SETTINGS_PRIVATE_H - -#include - -#include "meta/meta-settings.h" -#include "meta/types.h" -#include "core/util-private.h" - -typedef enum _MetaExperimentalFeature -{ - META_EXPERIMENTAL_FEATURE_NONE = 0, - META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER = (1 << 0), - META_EXPERIMENTAL_FEATURE_KMS_MODIFIERS = (1 << 1), - META_EXPERIMENTAL_FEATURE_RT_SCHEDULER = (1 << 2), - META_EXPERIMENTAL_FEATURE_DMA_BUF_SCREEN_SHARING = (1 << 3), - META_EXPERIMENTAL_FEATURE_AUTOCLOSE_XWAYLAND = (1 << 4), -} MetaExperimentalFeature; - -typedef enum _MetaXwaylandExtension -{ - META_XWAYLAND_EXTENSION_SECURITY = (1 << 0), - META_XWAYLAND_EXTENSION_XTEST = (1 << 1), -} MetaXwaylandExtension; - -#define META_TYPE_SETTINGS (meta_settings_get_type ()) -G_DECLARE_FINAL_TYPE (MetaSettings, meta_settings, - META, SETTINGS, GObject) - -MetaSettings * meta_settings_new (MetaBackend *backend); - -void meta_settings_post_init (MetaSettings *settings); - -void meta_settings_update_ui_scaling_factor (MetaSettings *settings); - -gboolean meta_settings_get_global_scaling_factor (MetaSettings *settings, - int *scaing_factor); - -META_EXPORT_TEST -gboolean meta_settings_is_experimental_feature_enabled (MetaSettings *settings, - MetaExperimentalFeature feature); - -MetaExperimentalFeature meta_settings_get_experimental_features (MetaSettings *settings); - -META_EXPORT_TEST -void meta_settings_override_experimental_features (MetaSettings *settings); - -META_EXPORT_TEST -void meta_settings_enable_experimental_feature (MetaSettings *settings, - MetaExperimentalFeature feature); - -void meta_settings_get_xwayland_grab_patterns (MetaSettings *settings, - GPtrArray **allow_list_patterns, - GPtrArray **deny_list_patterns); - -gboolean meta_settings_are_xwayland_grabs_allowed (MetaSettings *settings); - -int meta_settings_get_xwayland_disable_extensions (MetaSettings *settings); - -#endif /* META_SETTINGS_PRIVATE_H */ diff --git a/src/backends/meta-settings.c b/src/backends/meta-settings.c deleted file mode 100644 index 6a754d4e0..000000000 --- a/src/backends/meta-settings.c +++ /dev/null @@ -1,559 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 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. - */ - -#include "config.h" - -#include "backends/meta-settings-private.h" - -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-logical-monitor.h" -#include "backends/meta-monitor-manager-private.h" -#include "ui/theme-private.h" - -#ifndef XWAYLAND_GRAB_DEFAULT_ACCESS_RULES -# warning "XWAYLAND_GRAB_DEFAULT_ACCESS_RULES is not set" -# define XWAYLAND_GRAB_DEFAULT_ACCESS_RULES "" -#endif - -enum -{ - UI_SCALING_FACTOR_CHANGED, - GLOBAL_SCALING_FACTOR_CHANGED, - FONT_DPI_CHANGED, - EXPERIMENTAL_FEATURES_CHANGED, - - N_SIGNALS -}; - -static guint signals[N_SIGNALS]; - -struct _MetaSettings -{ - GObject parent; - - MetaBackend *backend; - - GSettings *interface_settings; - GSettings *mutter_settings; - GSettings *wayland_settings; - - int ui_scaling_factor; - int global_scaling_factor; - - int font_dpi; - - MetaExperimentalFeature experimental_features; - gboolean experimental_features_overridden; - - gboolean xwayland_allow_grabs; - GPtrArray *xwayland_grab_allow_list_patterns; - GPtrArray *xwayland_grab_deny_list_patterns; - - /* A bitmask of MetaXwaylandExtension enum */ - int xwayland_disable_extensions; -}; - -G_DEFINE_TYPE (MetaSettings, meta_settings, G_TYPE_OBJECT) - -static int -calculate_ui_scaling_factor (MetaSettings *settings) -{ - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (settings->backend); - MetaLogicalMonitor *primary_logical_monitor; - - primary_logical_monitor = - meta_monitor_manager_get_primary_logical_monitor (monitor_manager); - if (!primary_logical_monitor) - return 1; - - return (int) meta_logical_monitor_get_scale (primary_logical_monitor); -} - -static gboolean -update_ui_scaling_factor (MetaSettings *settings) -{ - int ui_scaling_factor; - - if (meta_is_stage_views_scaled ()) - ui_scaling_factor = 1; - else - ui_scaling_factor = calculate_ui_scaling_factor (settings); - - if (settings->ui_scaling_factor != ui_scaling_factor) - { - settings->ui_scaling_factor = ui_scaling_factor; - return TRUE; - } - else - { - return FALSE; - } -} - -void -meta_settings_update_ui_scaling_factor (MetaSettings *settings) -{ - if (update_ui_scaling_factor (settings)) - g_signal_emit (settings, signals[UI_SCALING_FACTOR_CHANGED], 0); -} - -int -meta_settings_get_ui_scaling_factor (MetaSettings *settings) -{ - g_assert (settings->ui_scaling_factor != 0); - - return settings->ui_scaling_factor; -} - -static gboolean -update_global_scaling_factor (MetaSettings *settings) -{ - int global_scaling_factor; - - global_scaling_factor = - (int) g_settings_get_uint (settings->interface_settings, - "scaling-factor"); - - if (settings->global_scaling_factor != global_scaling_factor) - { - settings->global_scaling_factor = global_scaling_factor; - return TRUE; - } - else - { - return FALSE; - } -} - -gboolean -meta_settings_get_global_scaling_factor (MetaSettings *settings, - int *out_scaling_factor) -{ - if (settings->global_scaling_factor == 0) - return FALSE; - - *out_scaling_factor = settings->global_scaling_factor; - return TRUE; -} - -static gboolean -update_font_dpi (MetaSettings *settings) -{ - double text_scaling_factor; - /* Number of logical pixels on an inch when unscaled */ - const double dots_per_inch = 96; - /* Being based on Xft, API users expect the DPI to be 1/1024th of an inch. */ - const double xft_factor = 1024; - int font_dpi; - - text_scaling_factor = g_settings_get_double (settings->interface_settings, - "text-scaling-factor"); - font_dpi = (int) (text_scaling_factor * - dots_per_inch * - xft_factor * - settings->ui_scaling_factor); - - if (font_dpi != settings->font_dpi) - { - settings->font_dpi = font_dpi; - - g_object_set (clutter_settings_get_default (), - "font-dpi", font_dpi, - NULL); - - return TRUE; - } - else - { - return FALSE; - } -} - -static void -meta_settings_update_font_dpi (MetaSettings *settings) -{ - if (update_font_dpi (settings)) - g_signal_emit (settings, signals[FONT_DPI_CHANGED], 0); -} - -int -meta_settings_get_font_dpi (MetaSettings *settings) -{ - g_assert (settings->font_dpi != 0); - - return settings->font_dpi; -} - -static void -interface_settings_changed (GSettings *interface_settings, - const char *key, - MetaSettings *settings) -{ - if (g_str_equal (key, "scaling-factor")) - { - if (update_global_scaling_factor (settings)) - g_signal_emit (settings, signals[GLOBAL_SCALING_FACTOR_CHANGED], 0); - } - else if (g_str_equal (key, "text-scaling-factor")) - { - meta_settings_update_font_dpi (settings); - } -} - -gboolean -meta_settings_is_experimental_feature_enabled (MetaSettings *settings, - MetaExperimentalFeature feature) -{ - return !!(settings->experimental_features & feature); -} - -void -meta_settings_override_experimental_features (MetaSettings *settings) -{ - settings->experimental_features = META_EXPERIMENTAL_FEATURE_NONE; - settings->experimental_features_overridden = TRUE; -} - -void -meta_settings_enable_experimental_feature (MetaSettings *settings, - MetaExperimentalFeature feature) -{ - g_assert (settings->experimental_features_overridden); - - settings->experimental_features |= feature; -} - -static gboolean -experimental_features_handler (GVariant *features_variant, - gpointer *result, - gpointer data) -{ - MetaSettings *settings = data; - GVariantIter features_iter; - char *feature_str; - MetaExperimentalFeature features = META_EXPERIMENTAL_FEATURE_NONE; - - if (settings->experimental_features_overridden) - { - *result = GINT_TO_POINTER (FALSE); - return TRUE; - } - - g_variant_iter_init (&features_iter, features_variant); - while (g_variant_iter_loop (&features_iter, "s", &feature_str)) - { - MetaExperimentalFeature feature = META_EXPERIMENTAL_FEATURE_NONE; - - if (g_str_equal (feature_str, "scale-monitor-framebuffer")) - feature = META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER; - else if (g_str_equal (feature_str, "kms-modifiers")) - feature = META_EXPERIMENTAL_FEATURE_KMS_MODIFIERS; - else if (g_str_equal (feature_str, "rt-scheduler")) - feature = META_EXPERIMENTAL_FEATURE_RT_SCHEDULER; - else if (g_str_equal (feature_str, "dma-buf-screen-sharing")) - feature = META_EXPERIMENTAL_FEATURE_DMA_BUF_SCREEN_SHARING; - else if (g_str_equal (feature_str, "autoclose-xwayland")) - feature = META_EXPERIMENTAL_FEATURE_AUTOCLOSE_XWAYLAND; - - if (feature) - g_message ("Enabling experimental feature '%s'", feature_str); - else - g_warning ("Unknown experimental feature '%s'", feature_str); - - features |= feature; - } - - if (features != settings->experimental_features) - { - settings->experimental_features = features; - *result = GINT_TO_POINTER (TRUE); - } - else - { - *result = GINT_TO_POINTER (FALSE); - } - - return TRUE; -} - -static gboolean -update_experimental_features (MetaSettings *settings) -{ - return GPOINTER_TO_INT (g_settings_get_mapped (settings->mutter_settings, - "experimental-features", - experimental_features_handler, - settings)); -} - -static void -mutter_settings_changed (GSettings *mutter_settings, - gchar *key, - MetaSettings *settings) -{ - MetaExperimentalFeature old_experimental_features; - - if (!g_str_equal (key, "experimental-features")) - return; - - old_experimental_features = settings->experimental_features; - if (update_experimental_features (settings)) - g_signal_emit (settings, signals[EXPERIMENTAL_FEATURES_CHANGED], 0, - (unsigned int) old_experimental_features); -} - -static void -xwayland_grab_list_add_item (MetaSettings *settings, - char *item) -{ - /* If first character is '!', it's a denied value */ - if (item[0] != '!') - g_ptr_array_add (settings->xwayland_grab_allow_list_patterns, - g_pattern_spec_new (item)); - else if (item[1] != 0) - g_ptr_array_add (settings->xwayland_grab_deny_list_patterns, - g_pattern_spec_new (&item[1])); -} - -static gboolean -xwayland_grab_access_rules_handler (GVariant *variant, - gpointer *result, - gpointer data) -{ - MetaSettings *settings = data; - GVariantIter iter; - char *item; - - /* Create a GPatternSpec for each element */ - g_variant_iter_init (&iter, variant); - while (g_variant_iter_loop (&iter, "s", &item)) - xwayland_grab_list_add_item (settings, item); - - *result = GINT_TO_POINTER (TRUE); - - return TRUE; -} - -static void -update_xwayland_grab_access_rules (MetaSettings *settings) -{ - gchar **system_defaults; - int i; - - /* Free previous patterns and create new arrays */ - g_clear_pointer (&settings->xwayland_grab_allow_list_patterns, - g_ptr_array_unref); - settings->xwayland_grab_allow_list_patterns = - g_ptr_array_new_with_free_func ((GDestroyNotify) g_pattern_spec_free); - - g_clear_pointer (&settings->xwayland_grab_deny_list_patterns, - g_ptr_array_unref); - settings->xwayland_grab_deny_list_patterns = - g_ptr_array_new_with_free_func ((GDestroyNotify) g_pattern_spec_free); - - /* Add system defaults values */ - system_defaults = g_strsplit (XWAYLAND_GRAB_DEFAULT_ACCESS_RULES, ",", -1); - for (i = 0; system_defaults[i]; i++) - xwayland_grab_list_add_item (settings, system_defaults[i]); - g_strfreev (system_defaults); - - /* Then add gsettings values */ - g_settings_get_mapped (settings->wayland_settings, - "xwayland-grab-access-rules", - xwayland_grab_access_rules_handler, - settings); -} - -static void -update_xwayland_allow_grabs (MetaSettings *settings) -{ - settings->xwayland_allow_grabs = - g_settings_get_boolean (settings->wayland_settings, - "xwayland-allow-grabs"); -} - -static void -update_xwayland_disable_extensions (MetaSettings *settings) -{ - settings->xwayland_disable_extensions = - g_settings_get_flags (settings->wayland_settings, - "xwayland-disable-extension"); -} - -static void -wayland_settings_changed (GSettings *wayland_settings, - gchar *key, - MetaSettings *settings) -{ - - if (g_str_equal (key, "xwayland-allow-grabs")) - { - update_xwayland_allow_grabs (settings); - } - else if (g_str_equal (key, "xwayland-grab-access-rules")) - { - update_xwayland_grab_access_rules (settings); - } - else if (g_str_equal (key, "xwayland-disable-extension")) - { - update_xwayland_disable_extensions (settings); - } -} - -void -meta_settings_get_xwayland_grab_patterns (MetaSettings *settings, - GPtrArray **allow_list_patterns, - GPtrArray **deny_list_patterns) -{ - *allow_list_patterns = settings->xwayland_grab_allow_list_patterns; - *deny_list_patterns = settings->xwayland_grab_deny_list_patterns; -} - -gboolean -meta_settings_are_xwayland_grabs_allowed (MetaSettings *settings) -{ - return (settings->xwayland_allow_grabs); -} - -int -meta_settings_get_xwayland_disable_extensions (MetaSettings *settings) -{ - return (settings->xwayland_disable_extensions); -} - -MetaSettings * -meta_settings_new (MetaBackend *backend) -{ - MetaSettings *settings; - - settings = g_object_new (META_TYPE_SETTINGS, NULL); - settings->backend = backend; - - return settings; -} - -static void -meta_settings_dispose (GObject *object) -{ - MetaSettings *settings = META_SETTINGS (object); - - g_clear_object (&settings->mutter_settings); - g_clear_object (&settings->interface_settings); - g_clear_object (&settings->wayland_settings); - g_clear_pointer (&settings->xwayland_grab_allow_list_patterns, - g_ptr_array_unref); - g_clear_pointer (&settings->xwayland_grab_deny_list_patterns, - g_ptr_array_unref); - - G_OBJECT_CLASS (meta_settings_parent_class)->dispose (object); -} - -static void -meta_settings_init (MetaSettings *settings) -{ - settings->interface_settings = g_settings_new ("org.gnome.desktop.interface"); - g_signal_connect (settings->interface_settings, "changed", - G_CALLBACK (interface_settings_changed), - settings); - settings->mutter_settings = g_settings_new ("org.gnome.mutter"); - g_signal_connect (settings->mutter_settings, "changed", - G_CALLBACK (mutter_settings_changed), - settings); - settings->wayland_settings = g_settings_new ("org.gnome.mutter.wayland"); - g_signal_connect (settings->wayland_settings, "changed", - G_CALLBACK (wayland_settings_changed), - settings); - - /* Chain up inter-dependent settings. */ - g_signal_connect (settings, "global-scaling-factor-changed", - G_CALLBACK (meta_settings_update_ui_scaling_factor), NULL); - g_signal_connect (settings, "ui-scaling-factor-changed", - G_CALLBACK (meta_settings_update_font_dpi), NULL); - - update_global_scaling_factor (settings); - update_experimental_features (settings); - update_xwayland_grab_access_rules (settings); - update_xwayland_allow_grabs (settings); - update_xwayland_disable_extensions (settings); -} - -static void -on_monitors_changed (MetaMonitorManager *monitor_manager, - MetaSettings *settings) -{ - meta_settings_update_ui_scaling_factor (settings); -} - -void -meta_settings_post_init (MetaSettings *settings) -{ - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (settings->backend); - - update_ui_scaling_factor (settings); - update_font_dpi (settings); - - g_signal_connect_object (monitor_manager, "monitors-changed-internal", - G_CALLBACK (on_monitors_changed), - settings, G_CONNECT_AFTER); -} - -static void -meta_settings_class_init (MetaSettingsClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = meta_settings_dispose; - - signals[UI_SCALING_FACTOR_CHANGED] = - g_signal_new ("ui-scaling-factor-changed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - signals[GLOBAL_SCALING_FACTOR_CHANGED] = - g_signal_new ("global-scaling-factor-changed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - signals[FONT_DPI_CHANGED] = - g_signal_new ("font-dpi-changed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - signals[EXPERIMENTAL_FEATURES_CHANGED] = - g_signal_new ("experimental-features-changed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 1, G_TYPE_UINT); -} diff --git a/src/backends/meta-stage-impl-private.h b/src/backends/meta-stage-impl-private.h deleted file mode 100644 index ab3e0d391..000000000 --- a/src/backends/meta-stage-impl-private.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2007,2008,2009,2010,2011 Intel Corporation. - * Copyright (C) 2021 Red Hat - * - * 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 . - * - * Written by: - * Matthew Allum - * Robert Bragg - * Neil Roberts - * Emmanuele Bassi - * - */ - -#ifndef META_STAGE_IMPL_PRIVATE_H -#define META_STAGE_IMPL_PRIVATE_H - -#include - -#include "clutter/clutter.h" - -G_BEGIN_DECLS - -#define META_TYPE_STAGE_IMPL (meta_stage_impl_get_type ()) -#define META_STAGE_IMPL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_STAGE_IMPL, MetaStageImpl)) -#define META_IS_STAGE_IMPL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_STAGE_IMPL)) -#define META_STAGE_IMPL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_STAGE_IMPL, MetaStageImplClass)) -#define META_IS_STAGE_IMPL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_STAGE_IMPL)) -#define META_STAGE_IMPL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_STAGE_IMPL, MetaStageImplClass)) - -typedef struct _MetaStageImpl MetaStageImpl; -typedef struct _MetaStageImplClass MetaStageImplClass; - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaStageImpl, g_object_unref) - -#define META_TYPE_STAGE_VIEW (meta_stage_view_get_type ()) - -struct _MetaStageImpl -{ - GObject parent_instance; - - /* the stage wrapper */ - ClutterStage *wrapper; - - /* back pointer to the backend */ - ClutterBackend *backend; -}; - -struct _MetaStageImplClass -{ - GObjectClass parent_class; -}; - -GType meta_stage_impl_get_type (void) G_GNUC_CONST; - -void meta_stage_impl_presented (MetaStageImpl *stage_impl, - CoglFrameEvent frame_event, - ClutterFrameInfo *frame_info); - -void meta_stage_impl_add_onscreen_frame_info (MetaStageImpl *stage_impl, - ClutterStageView *view); - -G_END_DECLS - -#endif /* META_STAGE_IMPL_PRIVATE_H */ diff --git a/src/backends/meta-stage-impl.c b/src/backends/meta-stage-impl.c deleted file mode 100644 index 28534ec81..000000000 --- a/src/backends/meta-stage-impl.c +++ /dev/null @@ -1,756 +0,0 @@ -/* - * Clutter. - * - * An OpenGL based 'interactive canvas' library. - * - * Copyright (C) 2007,2008,2009,2010,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 . - - * Authors: - * Matthew Allum - * Robert Bragg - * Neil Roberts - * Emmanuele Bassi - */ - -#include "config.h" - -#include "backends/meta-stage-impl-private.h" - -#include -#include - -#include "backends/meta-stage-view-private.h" -#include "clutter/clutter-mutter.h" -#include "cogl/cogl.h" -#include "core/util-private.h" - -#define MAX_STACK_RECTS 256 - -typedef struct _MetaStageImplPrivate -{ - int64_t global_frame_counter; -} MetaStageImplPrivate; - -static void -clutter_stage_window_iface_init (ClutterStageWindowInterface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaStageImpl, - meta_stage_impl, - G_TYPE_OBJECT, - G_ADD_PRIVATE (MetaStageImpl) - G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW, - clutter_stage_window_iface_init)); - -enum -{ - PROP_0, - PROP_WRAPPER, - PROP_BACKEND, - PROP_LAST -}; - -static void -meta_stage_impl_unrealize (ClutterStageWindow *stage_window) -{ - meta_topic (META_DEBUG_BACKEND, "Unrealizing Cogl stage [%p]", stage_window); -} - -static gboolean -meta_stage_impl_realize (ClutterStageWindow *stage_window) -{ - ClutterBackend *backend; - - meta_topic (META_DEBUG_BACKEND, - "Realizing stage '%s' [%p]", - G_OBJECT_TYPE_NAME (stage_window), - stage_window); - - backend = clutter_get_default_backend (); - - if (backend->cogl_context == NULL) - { - g_warning ("Failed to realize stage: missing Cogl context"); - return FALSE; - } - - return TRUE; -} - -static int64_t -meta_stage_impl_get_frame_counter (ClutterStageWindow *stage_window) -{ - MetaStageImpl *stage_impl = META_STAGE_IMPL (stage_window); - MetaStageImplPrivate *priv = - meta_stage_impl_get_instance_private (stage_impl); - - return priv->global_frame_counter; -} - -static ClutterActor * -meta_stage_impl_get_wrapper (ClutterStageWindow *stage_window) -{ - return CLUTTER_ACTOR (META_STAGE_IMPL (stage_window)->wrapper); -} - -static void -meta_stage_impl_show (ClutterStageWindow *stage_window, - gboolean do_raise) -{ - MetaStageImpl *stage_impl = META_STAGE_IMPL (stage_window); - - clutter_actor_map (CLUTTER_ACTOR (stage_impl->wrapper)); -} - -static void -meta_stage_impl_hide (ClutterStageWindow *stage_window) -{ - MetaStageImpl *stage_impl = META_STAGE_IMPL (stage_window); - - clutter_actor_unmap (CLUTTER_ACTOR (stage_impl->wrapper)); -} - -static void -meta_stage_impl_resize (ClutterStageWindow *stage_window, - gint width, - gint height) -{ -} - -static void -paint_damage_region (ClutterStageWindow *stage_window, - ClutterStageView *view, - cairo_region_t *swap_region, - cairo_region_t *queued_redraw_clip) -{ - CoglFramebuffer *framebuffer = clutter_stage_view_get_framebuffer (view); - CoglContext *ctx = cogl_framebuffer_get_context (framebuffer); - static CoglPipeline *overlay_blue = NULL; - MetaStageImpl *stage_impl = META_STAGE_IMPL (stage_window); - ClutterActor *actor = CLUTTER_ACTOR (stage_impl->wrapper); - graphene_matrix_t transform; - int n_rects, i; - - cogl_framebuffer_push_matrix (framebuffer); - clutter_actor_get_transform (actor, &transform); - cogl_framebuffer_transform (framebuffer, &transform); - - /* Blue for the swap region */ - if (G_UNLIKELY (overlay_blue == NULL)) - { - overlay_blue = cogl_pipeline_new (ctx); - cogl_pipeline_set_color4ub (overlay_blue, 0x00, 0x00, 0x33, 0x33); - } - - n_rects = cairo_region_num_rectangles (swap_region); - for (i = 0; i < n_rects; i++) - { - cairo_rectangle_int_t rect; - float x_1, x_2, y_1, y_2; - - cairo_region_get_rectangle (swap_region, i, &rect); - x_1 = rect.x; - x_2 = rect.x + rect.width; - y_1 = rect.y; - y_2 = rect.y + rect.height; - - cogl_framebuffer_draw_rectangle (framebuffer, overlay_blue, x_1, y_1, x_2, y_2); - } - - /* Red for the clip */ - if (queued_redraw_clip) - { - static CoglPipeline *overlay_red = NULL; - - if (G_UNLIKELY (overlay_red == NULL)) - { - overlay_red = cogl_pipeline_new (ctx); - cogl_pipeline_set_color4ub (overlay_red, 0x33, 0x00, 0x00, 0x33); - } - - n_rects = cairo_region_num_rectangles (queued_redraw_clip); - for (i = 0; i < n_rects; i++) - { - cairo_rectangle_int_t rect; - float x_1, x_2, y_1, y_2; - - cairo_region_get_rectangle (queued_redraw_clip, i, &rect); - x_1 = rect.x; - x_2 = rect.x + rect.width; - y_1 = rect.y; - y_2 = rect.y + rect.height; - - cogl_framebuffer_draw_rectangle (framebuffer, overlay_red, x_1, y_1, x_2, y_2); - } - } - - cogl_framebuffer_pop_matrix (framebuffer); -} - -static void -swap_framebuffer (ClutterStageWindow *stage_window, - ClutterStageView *stage_view, - cairo_region_t *swap_region, - gboolean swap_with_damage, - ClutterFrame *frame) -{ - MetaStageImpl *stage_impl = META_STAGE_IMPL (stage_window); - MetaStageImplPrivate *priv = - meta_stage_impl_get_instance_private (stage_impl); - CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (stage_view); - CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer); - - clutter_stage_view_before_swap_buffer (stage_view, swap_region); - - if (COGL_IS_ONSCREEN (framebuffer)) - { - CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); - int *damage, n_rects, i; - CoglFrameInfo *frame_info; - - n_rects = cairo_region_num_rectangles (swap_region); - damage = g_newa (int, n_rects * 4); - for (i = 0; i < n_rects; i++) - { - cairo_rectangle_int_t rect; - - cairo_region_get_rectangle (swap_region, i, &rect); - damage[i * 4] = rect.x; - damage[i * 4 + 1] = rect.y; - damage[i * 4 + 2] = rect.width; - damage[i * 4 + 3] = rect.height; - } - - frame_info = - cogl_frame_info_new (cogl_context, priv->global_frame_counter); - priv->global_frame_counter++; - - /* push on the screen */ - if (n_rects > 0 && !swap_with_damage) - { - meta_topic (META_DEBUG_BACKEND, - "cogl_onscreen_swap_region (onscreen: %p)", - onscreen); - - cogl_onscreen_swap_region (onscreen, - damage, n_rects, - frame_info, - frame); - } - else - { - meta_topic (META_DEBUG_BACKEND, - "cogl_onscreen_swap_buffers (onscreen: %p)", - onscreen); - - cogl_onscreen_swap_buffers_with_damage (onscreen, - damage, n_rects, - frame_info, - frame); - } - } - else - { - MetaStageView *view = META_STAGE_VIEW (stage_view); - - meta_topic (META_DEBUG_BACKEND, - "fake offscreen swap (framebuffer: %p)", - framebuffer); - meta_stage_view_perform_fake_swap (view, priv->global_frame_counter); - priv->global_frame_counter++; - } -} - -static cairo_region_t * -offset_scale_and_clamp_region (const cairo_region_t *region, - int offset_x, - int offset_y, - float scale) -{ - int n_rects, i; - cairo_rectangle_int_t *rects; - g_autofree cairo_rectangle_int_t *freeme = NULL; - - n_rects = cairo_region_num_rectangles (region); - - if (n_rects == 0) - return cairo_region_create (); - - if (n_rects < MAX_STACK_RECTS) - rects = g_newa (cairo_rectangle_int_t, n_rects); - else - rects = freeme = g_new (cairo_rectangle_int_t, n_rects); - - for (i = 0; i < n_rects; i++) - { - cairo_rectangle_int_t *rect = &rects[i]; - graphene_rect_t tmp; - - cairo_region_get_rectangle (region, i, rect); - - _clutter_util_rect_from_rectangle (rect, &tmp); - graphene_rect_offset (&tmp, offset_x, offset_y); - graphene_rect_scale (&tmp, scale, scale, &tmp); - _clutter_util_rectangle_int_extents (&tmp, rect); - } - - return cairo_region_create_rectangles (rects, n_rects); -} - -static cairo_region_t * -scale_offset_and_clamp_region (const cairo_region_t *region, - float scale, - int offset_x, - int offset_y) -{ - int n_rects, i; - cairo_rectangle_int_t *rects; - g_autofree cairo_rectangle_int_t *freeme = NULL; - - n_rects = cairo_region_num_rectangles (region); - - if (n_rects == 0) - return cairo_region_create (); - - if (n_rects < MAX_STACK_RECTS) - rects = g_newa (cairo_rectangle_int_t, n_rects); - else - rects = freeme = g_new (cairo_rectangle_int_t, n_rects); - - for (i = 0; i < n_rects; i++) - { - cairo_rectangle_int_t *rect = &rects[i]; - graphene_rect_t tmp; - - cairo_region_get_rectangle (region, i, rect); - - _clutter_util_rect_from_rectangle (rect, &tmp); - graphene_rect_scale (&tmp, scale, scale, &tmp); - graphene_rect_offset (&tmp, offset_x, offset_y); - _clutter_util_rectangle_int_extents (&tmp, rect); - } - - return cairo_region_create_rectangles (rects, n_rects); -} - -static void -paint_stage (MetaStageImpl *stage_impl, - ClutterStageView *stage_view, - cairo_region_t *redraw_clip) -{ - ClutterStage *stage = stage_impl->wrapper; - - _clutter_stage_maybe_setup_viewport (stage, stage_view); - clutter_stage_paint_view (stage, stage_view, redraw_clip); - - clutter_stage_view_after_paint (stage_view, redraw_clip); -} - -static cairo_region_t * -transform_swap_region_to_onscreen (ClutterStageView *stage_view, - cairo_region_t *swap_region) -{ - CoglFramebuffer *onscreen = clutter_stage_view_get_onscreen (stage_view); - int n_rects, i; - cairo_rectangle_int_t *rects; - cairo_region_t *transformed_region; - int width, height; - - width = cogl_framebuffer_get_width (onscreen); - height = cogl_framebuffer_get_height (onscreen); - - n_rects = cairo_region_num_rectangles (swap_region); - rects = g_newa (cairo_rectangle_int_t, n_rects); - for (i = 0; i < n_rects; i++) - { - cairo_region_get_rectangle (swap_region, i, &rects[i]); - clutter_stage_view_transform_rect_to_onscreen (stage_view, - &rects[i], - width, - height, - &rects[i]); - } - transformed_region = cairo_region_create_rectangles (rects, n_rects); - - return transformed_region; -} - -static void -meta_stage_impl_redraw_view_primary (MetaStageImpl *stage_impl, - ClutterStageView *stage_view, - ClutterFrame *frame) -{ - ClutterStageWindow *stage_window = CLUTTER_STAGE_WINDOW (stage_impl); - MetaStageView *view = META_STAGE_VIEW (stage_view); - CoglFramebuffer *fb = clutter_stage_view_get_framebuffer (stage_view); - CoglFramebuffer *onscreen = clutter_stage_view_get_onscreen (stage_view); - cairo_rectangle_int_t view_rect; - gboolean is_full_redraw; - gboolean use_clipped_redraw = TRUE; - gboolean can_blit_sub_buffer; - gboolean has_buffer_age; - gboolean swap_with_damage; - cairo_region_t *redraw_clip; - cairo_region_t *queued_redraw_clip = NULL; - cairo_region_t *fb_clip_region; - cairo_region_t *swap_region; - ClutterDrawDebugFlag paint_debug_flags; - ClutterDamageHistory *damage_history; - float fb_scale; - int fb_width, fb_height; - int buffer_age = 0; - - clutter_stage_view_get_layout (stage_view, &view_rect); - fb_scale = clutter_stage_view_get_scale (stage_view); - fb_width = cogl_framebuffer_get_width (fb); - fb_height = cogl_framebuffer_get_height (fb); - - can_blit_sub_buffer = - COGL_IS_ONSCREEN (onscreen) && - cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_REGION); - - has_buffer_age = - COGL_IS_ONSCREEN (onscreen) && - cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_BUFFER_AGE); - - redraw_clip = clutter_stage_view_take_redraw_clip (stage_view); - - /* NB: a NULL redraw clip == full stage redraw */ - if (!redraw_clip) - is_full_redraw = TRUE; - else - is_full_redraw = FALSE; - - damage_history = meta_stage_view_get_damage_history (view); - - if (has_buffer_age) - { - buffer_age = cogl_onscreen_get_buffer_age (COGL_ONSCREEN (onscreen)); - if (!clutter_damage_history_is_age_valid (damage_history, buffer_age)) - { - meta_topic (META_DEBUG_BACKEND, - "Invalid back buffer(age=%d): forcing full redraw", - buffer_age); - use_clipped_redraw = FALSE; - } - } - - meta_get_clutter_debug_flags (NULL, &paint_debug_flags, NULL); - - use_clipped_redraw = - use_clipped_redraw && - !(paint_debug_flags & CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS) && - _clutter_stage_window_can_clip_redraws (stage_window) && - (can_blit_sub_buffer || has_buffer_age) && - !is_full_redraw && - /* some drivers struggle to get going and produce some junk - * frames when starting up... */ - cogl_onscreen_get_frame_counter (COGL_ONSCREEN (onscreen)) > 3; - - if (use_clipped_redraw) - { - fb_clip_region = offset_scale_and_clamp_region (redraw_clip, - -view_rect.x, - -view_rect.y, - fb_scale); - - if (G_UNLIKELY (paint_debug_flags & CLUTTER_DEBUG_PAINT_DAMAGE_REGION)) - { - queued_redraw_clip = - scale_offset_and_clamp_region (fb_clip_region, - 1.0 / fb_scale, - view_rect.x, - view_rect.y); - } - } - else - { - cairo_rectangle_int_t fb_rect; - - fb_rect = (cairo_rectangle_int_t) { - .width = fb_width, - .height = fb_height, - }; - fb_clip_region = cairo_region_create_rectangle (&fb_rect); - - g_clear_pointer (&redraw_clip, cairo_region_destroy); - redraw_clip = cairo_region_create_rectangle (&view_rect); - - if (G_UNLIKELY (paint_debug_flags & CLUTTER_DEBUG_PAINT_DAMAGE_REGION)) - queued_redraw_clip = cairo_region_reference (redraw_clip); - } - - g_return_if_fail (!cairo_region_is_empty (fb_clip_region)); - - swap_with_damage = FALSE; - if (has_buffer_age) - { - clutter_damage_history_record (damage_history, fb_clip_region); - - if (use_clipped_redraw) - { - int age; - - for (age = 1; age <= buffer_age; age++) - { - const cairo_region_t *old_damage; - - old_damage = - clutter_damage_history_lookup (damage_history, age); - cairo_region_union (fb_clip_region, old_damage); - } - - meta_topic (META_DEBUG_BACKEND, - "Reusing back buffer(age=%d) - repairing region: num rects: %d", - buffer_age, - cairo_region_num_rectangles (fb_clip_region)); - - swap_with_damage = TRUE; - } - - clutter_damage_history_step (damage_history); - } - - if (use_clipped_redraw) - { - /* Regenerate redraw_clip because: - * 1. It's missing the regions added from damage_history above; and - * 2. If using fractional scaling then it might be a fraction of a - * logical pixel (or one physical pixel) smaller than - * fb_clip_region, due to the clamping from - * offset_scale_and_clamp_region. So we need to ensure redraw_clip - * is a superset of fb_clip_region to avoid such gaps. - */ - cairo_region_destroy (redraw_clip); - redraw_clip = scale_offset_and_clamp_region (fb_clip_region, - 1.0 / fb_scale, - view_rect.x, - view_rect.y); - } - - if (paint_debug_flags & CLUTTER_DEBUG_PAINT_DAMAGE_REGION) - { - cairo_region_t *debug_redraw_clip; - - debug_redraw_clip = cairo_region_create_rectangle (&view_rect); - paint_stage (stage_impl, stage_view, debug_redraw_clip); - cairo_region_destroy (debug_redraw_clip); - } - else if (use_clipped_redraw) - { - cogl_framebuffer_push_region_clip (fb, fb_clip_region); - - paint_stage (stage_impl, stage_view, redraw_clip); - - cogl_framebuffer_pop_clip (fb); - } - else - { - meta_topic (META_DEBUG_BACKEND, "Unclipped stage paint"); - - paint_stage (stage_impl, stage_view, redraw_clip); - } - - /* XXX: It seems there will be a race here in that the stage - * window may be resized before the cogl_onscreen_swap_region - * is handled and so we may copy the wrong region. I can't - * really see how we can handle this with the current state of X - * but at least in this case a full redraw should be queued by - * the resize anyway so it should only exhibit temporary - * artefacts. - */ - if (use_clipped_redraw) - swap_region = cairo_region_reference (fb_clip_region); - else - swap_region = cairo_region_create (); - - g_clear_pointer (&redraw_clip, cairo_region_destroy); - g_clear_pointer (&fb_clip_region, cairo_region_destroy); - - COGL_TRACE_BEGIN_SCOPED (MetaStageImplRedrawViewSwapFramebuffer, - "Paint (swap framebuffer)"); - - if (clutter_stage_view_get_onscreen (stage_view) != - clutter_stage_view_get_framebuffer (stage_view)) - { - cairo_region_t *transformed_swap_region; - - transformed_swap_region = - transform_swap_region_to_onscreen (stage_view, swap_region); - cairo_region_destroy (swap_region); - swap_region = transformed_swap_region; - } - - if (queued_redraw_clip) - { - cairo_region_t *swap_region_in_stage_space; - - swap_region_in_stage_space = - scale_offset_and_clamp_region (swap_region, - 1.0f / fb_scale, - view_rect.x, - view_rect.y); - - cairo_region_subtract (swap_region_in_stage_space, queued_redraw_clip); - - paint_damage_region (stage_window, stage_view, - swap_region_in_stage_space, queued_redraw_clip); - - cairo_region_destroy (queued_redraw_clip); - cairo_region_destroy (swap_region_in_stage_space); - } - - swap_framebuffer (stage_window, - stage_view, - swap_region, - swap_with_damage, - frame); - - cairo_region_destroy (swap_region); -} - -static gboolean -meta_stage_impl_scanout_view (MetaStageImpl *stage_impl, - ClutterStageView *stage_view, - CoglScanout *scanout, - ClutterFrame *frame, - GError **error) -{ - MetaStageImplPrivate *priv = - meta_stage_impl_get_instance_private (stage_impl); - CoglFramebuffer *framebuffer = - clutter_stage_view_get_framebuffer (stage_view); - CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer); - CoglOnscreen *onscreen; - CoglFrameInfo *frame_info; - - g_assert (COGL_IS_ONSCREEN (framebuffer)); - - onscreen = COGL_ONSCREEN (framebuffer); - - frame_info = cogl_frame_info_new (cogl_context, priv->global_frame_counter); - - if (!cogl_onscreen_direct_scanout (onscreen, - scanout, - frame_info, - frame, - error)) - { - cogl_object_unref (frame_info); - return FALSE; - } - - priv->global_frame_counter++; - - return TRUE; -} - -static void -meta_stage_impl_redraw_view (ClutterStageWindow *stage_window, - ClutterStageView *stage_view, - ClutterFrame *frame) -{ - MetaStageImpl *stage_impl = META_STAGE_IMPL (stage_window); - g_autoptr (CoglScanout) scanout = NULL; - - scanout = clutter_stage_view_take_scanout (stage_view); - if (scanout) - { - g_autoptr (GError) error = NULL; - - if (meta_stage_impl_scanout_view (stage_impl, - stage_view, - scanout, - frame, - &error)) - return; - - if (!g_error_matches (error, - COGL_SCANOUT_ERROR, - COGL_SCANOUT_ERROR_INHIBITED)) - g_warning ("Failed to scan out client buffer: %s", error->message); - } - - meta_stage_impl_redraw_view_primary (stage_impl, stage_view, frame); -} - -void -meta_stage_impl_add_onscreen_frame_info (MetaStageImpl *stage_impl, - ClutterStageView *stage_view) -{ - MetaStageImplPrivate *priv = - meta_stage_impl_get_instance_private (stage_impl); - CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (stage_view); - CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer); - CoglFrameInfo *frame_info; - - frame_info = cogl_frame_info_new (cogl_context, priv->global_frame_counter); - priv->global_frame_counter++; - - cogl_onscreen_add_frame_info (COGL_ONSCREEN (framebuffer), frame_info); -} - -static void -clutter_stage_window_iface_init (ClutterStageWindowInterface *iface) -{ - iface->realize = meta_stage_impl_realize; - iface->unrealize = meta_stage_impl_unrealize; - iface->get_wrapper = meta_stage_impl_get_wrapper; - iface->resize = meta_stage_impl_resize; - iface->show = meta_stage_impl_show; - iface->hide = meta_stage_impl_hide; - iface->get_frame_counter = meta_stage_impl_get_frame_counter; - iface->redraw_view = meta_stage_impl_redraw_view; -} - -static void -meta_stage_impl_set_property (GObject *gobject, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaStageImpl *self = META_STAGE_IMPL (gobject); - - switch (prop_id) - { - case PROP_WRAPPER: - self->wrapper = g_value_get_object (value); - break; - - case PROP_BACKEND: - self->backend = g_value_get_object (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); - break; - } -} - -static void -meta_stage_impl_class_init (MetaStageImplClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - gobject_class->set_property = meta_stage_impl_set_property; - - g_object_class_override_property (gobject_class, PROP_WRAPPER, "wrapper"); - g_object_class_override_property (gobject_class, PROP_BACKEND, "backend"); -} - -static void -meta_stage_impl_init (MetaStageImpl *stage) -{ -} diff --git a/src/backends/meta-stage-private.h b/src/backends/meta-stage-private.h deleted file mode 100644 index 07534f6e3..000000000 --- a/src/backends/meta-stage-private.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2012 Intel Corporation - * - * 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_STAGE_PRIVATE_H -#define META_STAGE_PRIVATE_H - -#include "backends/meta-cursor.h" -#include "core/util-private.h" -#include "meta/boxes.h" -#include "meta/meta-stage.h" -#include "meta/types.h" - -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, - ClutterPaintContext *paint_context, - gpointer user_data); - -ClutterActor *meta_stage_new (MetaBackend *backend); - -MetaOverlay *meta_stage_create_cursor_overlay (MetaStage *stage); -void meta_stage_remove_cursor_overlay (MetaStage *stage, - MetaOverlay *overlay); - -void meta_stage_update_cursor_overlay (MetaStage *stage, - MetaOverlay *overlay, - CoglTexture *texture, - graphene_rect_t *rect); - -void meta_overlay_set_visible (MetaOverlay *overlay, - gboolean is_visible); - -gboolean meta_overlay_is_visible (MetaOverlay *overlay); - -void meta_stage_set_active (MetaStage *stage, - gboolean is_active); - -META_EXPORT_TEST -MetaStageWatch * meta_stage_watch_view (MetaStage *stage, - ClutterStageView *view, - MetaStageWatchPhase watch_mode, - MetaStageWatchFunc callback, - gpointer user_data); - -META_EXPORT_TEST -void meta_stage_remove_watch (MetaStage *stage, - MetaStageWatch *watch); - -G_END_DECLS - -#endif /* META_STAGE_PRIVATE_H */ diff --git a/src/backends/meta-stage-view-private.h b/src/backends/meta-stage-view-private.h deleted file mode 100644 index aaf3f31eb..000000000 --- a/src/backends/meta-stage-view-private.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2007,2008,2009,2010,2011 Intel Corporation. - * Copyright (C) 2021 Red Hat - * - * 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 . - * - * Written by: - * Matthew Allum - * Robert Bragg - * Neil Roberts - * Emmanuele Bassi - * - */ - -#ifndef META_STAGE_VIEW_H -#define META_STAGE_VIEW_H - -#include - -#include "clutter/clutter-mutter.h" - -G_BEGIN_DECLS - -#define META_TYPE_STAGE_VIEW (meta_stage_view_get_type ()) - -G_DECLARE_DERIVABLE_TYPE (MetaStageView, - meta_stage_view, - META, STAGE_VIEW, - ClutterStageView) - -struct _MetaStageViewClass -{ - ClutterStageViewClass parent_class; -}; - -ClutterDamageHistory * meta_stage_view_get_damage_history (MetaStageView *view); -void meta_stage_view_perform_fake_swap (MetaStageView *view, - int64_t counter); - -#endif /* META_STAGE_VIEW_H */ diff --git a/src/backends/meta-stage-view.c b/src/backends/meta-stage-view.c deleted file mode 100644 index 473943196..000000000 --- a/src/backends/meta-stage-view.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2007,2008,2009,2010,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 . - - * Authors: - * Matthew Allum - * Robert Bragg - * Neil Roberts - * Emmanuele Bassi - */ - -#include "config.h" - -#include "meta-stage-view-private.h" - -typedef struct _MetaStageViewPrivate -{ - /* Damage history, in stage view render target framebuffer coordinate space. - */ - ClutterDamageHistory *damage_history; - - guint notify_presented_handle_id; - - CoglFrameClosure *frame_cb_closure; -} MetaStageViewPrivate; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaStageView, meta_stage_view, - CLUTTER_TYPE_STAGE_VIEW) - -static void -frame_cb (CoglOnscreen *onscreen, - CoglFrameEvent frame_event, - CoglFrameInfo *frame_info, - void *user_data) -{ - ClutterStageView *view = user_data; - - if (frame_event == COGL_FRAME_EVENT_SYNC) - return; - - if (cogl_frame_info_get_is_symbolic (frame_info)) - { - clutter_stage_view_notify_ready (view); - } - else - { - ClutterFrameInfo clutter_frame_info; - ClutterFrameInfoFlag flags = CLUTTER_FRAME_INFO_FLAG_NONE; - - if (cogl_frame_info_is_hw_clock (frame_info)) - flags |= CLUTTER_FRAME_INFO_FLAG_HW_CLOCK; - - if (cogl_frame_info_is_zero_copy (frame_info)) - flags |= CLUTTER_FRAME_INFO_FLAG_ZERO_COPY; - - if (cogl_frame_info_is_vsync (frame_info)) - flags |= CLUTTER_FRAME_INFO_FLAG_VSYNC; - - clutter_frame_info = (ClutterFrameInfo) { - .frame_counter = cogl_frame_info_get_global_frame_counter (frame_info), - .refresh_rate = cogl_frame_info_get_refresh_rate (frame_info), - .presentation_time = - cogl_frame_info_get_presentation_time_us (frame_info), - .flags = flags, - .sequence = cogl_frame_info_get_sequence (frame_info), - .gpu_rendering_duration_ns = - cogl_frame_info_get_rendering_duration_ns (frame_info), - .cpu_time_before_buffer_swap_us = - cogl_frame_info_get_time_before_buffer_swap_us (frame_info), - }; - clutter_stage_view_notify_presented (view, &clutter_frame_info); - } -} - -static void -meta_stage_view_dispose (GObject *object) -{ - MetaStageView *view = META_STAGE_VIEW (object); - MetaStageViewPrivate *priv = - meta_stage_view_get_instance_private (view); - ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (view); - - g_clear_handle_id (&priv->notify_presented_handle_id, g_source_remove); - g_clear_pointer (&priv->damage_history, clutter_damage_history_free); - - if (priv->frame_cb_closure) - { - CoglFramebuffer *framebuffer; - - framebuffer = clutter_stage_view_get_onscreen (stage_view); - cogl_onscreen_remove_frame_callback (COGL_ONSCREEN (framebuffer), - priv->frame_cb_closure); - priv->frame_cb_closure = NULL; - } - - G_OBJECT_CLASS (meta_stage_view_parent_class)->dispose (object); -} - -static void -meta_stage_view_constructed (GObject *object) -{ - MetaStageView *view = META_STAGE_VIEW (object); - MetaStageViewPrivate *priv = - meta_stage_view_get_instance_private (view); - ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (view); - CoglFramebuffer *framebuffer; - - framebuffer = clutter_stage_view_get_onscreen (stage_view); - if (framebuffer && COGL_IS_ONSCREEN (framebuffer)) - { - priv->frame_cb_closure = - cogl_onscreen_add_frame_callback (COGL_ONSCREEN (framebuffer), - frame_cb, - view, - NULL); - } - - G_OBJECT_CLASS (meta_stage_view_parent_class)->constructed (object); -} - -static void -meta_stage_view_init (MetaStageView *view) -{ - MetaStageViewPrivate *priv = - meta_stage_view_get_instance_private (view); - - priv->damage_history = clutter_damage_history_new (); -} - -static void -meta_stage_view_class_init (MetaStageViewClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->constructed = meta_stage_view_constructed; - object_class->dispose = meta_stage_view_dispose; -} - -ClutterDamageHistory * -meta_stage_view_get_damage_history (MetaStageView *view) -{ - MetaStageViewPrivate *priv = - meta_stage_view_get_instance_private (view); - - return priv->damage_history; -} - -typedef struct _NotifyPresentedClosure -{ - ClutterStageView *view; - ClutterFrameInfo frame_info; -} NotifyPresentedClosure; - -static gboolean -notify_presented_idle (gpointer user_data) -{ - NotifyPresentedClosure *closure = user_data; - MetaStageView *view = META_STAGE_VIEW (closure->view); - MetaStageViewPrivate *priv = - meta_stage_view_get_instance_private (view); - - priv->notify_presented_handle_id = 0; - clutter_stage_view_notify_presented (closure->view, &closure->frame_info); - - return G_SOURCE_REMOVE; -} - -void -meta_stage_view_perform_fake_swap (MetaStageView *view, - int64_t counter) -{ - ClutterStageView *clutter_view = CLUTTER_STAGE_VIEW (view); - MetaStageViewPrivate *priv = - meta_stage_view_get_instance_private (view); - NotifyPresentedClosure *closure; - - closure = g_new0 (NotifyPresentedClosure, 1); - closure->view = clutter_view; - closure->frame_info = (ClutterFrameInfo) { - .frame_counter = counter, - .refresh_rate = clutter_stage_view_get_refresh_rate (clutter_view), - .presentation_time = g_get_monotonic_time (), - .flags = CLUTTER_FRAME_INFO_FLAG_NONE, - .sequence = 0, - }; - - g_warn_if_fail (priv->notify_presented_handle_id == 0); - priv->notify_presented_handle_id = - g_idle_add_full (G_PRIORITY_DEFAULT, - notify_presented_idle, - closure, g_free); -} diff --git a/src/backends/meta-stage.c b/src/backends/meta-stage.c deleted file mode 100644 index 6f8e3feae..000000000 --- a/src/backends/meta-stage.c +++ /dev/null @@ -1,485 +0,0 @@ -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -#include "config.h" - -#include "backends/meta-stage-private.h" - -#include "backends/meta-backend-private.h" -#include "backends/meta-cursor-tracker-private.h" -#include "clutter/clutter-mutter.h" -#include "meta/meta-backend.h" -#include "meta/meta-monitor-manager.h" -#include "meta/util.h" - -#define N_WATCH_MODES 4 - -enum -{ - ACTORS_PAINTED, - - N_SIGNALS -}; - -static guint signals[N_SIGNALS]; - -struct _MetaStageWatch -{ - ClutterStageView *view; - MetaStageWatchFunc callback; - gpointer user_data; -}; - -struct _MetaOverlay -{ - MetaStage *stage; - - gboolean is_visible; - - CoglPipeline *pipeline; - CoglTexture *texture; - - graphene_rect_t current_rect; - graphene_rect_t previous_rect; - gboolean previous_is_valid; -}; - -struct _MetaStage -{ - ClutterStage parent; - - MetaBackend *backend; - - GPtrArray *watchers[N_WATCH_MODES]; - - GList *overlays; - gboolean is_active; -}; - -G_DEFINE_TYPE (MetaStage, meta_stage, CLUTTER_TYPE_STAGE); - -static MetaOverlay * -meta_overlay_new (MetaStage *stage) -{ - ClutterBackend *clutter_backend = - meta_backend_get_clutter_backend (stage->backend); - CoglContext *ctx = clutter_backend_get_cogl_context (clutter_backend); - MetaOverlay *overlay; - - overlay = g_new0 (MetaOverlay, 1); - overlay->stage = stage; - overlay->pipeline = cogl_pipeline_new (ctx); - - return overlay; -} - -static void -meta_overlay_free (MetaOverlay *overlay) -{ - if (overlay->pipeline) - cogl_object_unref (overlay->pipeline); - - g_free (overlay); -} - -static void -meta_overlay_set (MetaOverlay *overlay, - CoglTexture *texture, - graphene_rect_t *rect) -{ - if (overlay->texture != texture) - { - overlay->texture = texture; - - if (texture) - cogl_pipeline_set_layer_texture (overlay->pipeline, 0, texture); - else - cogl_pipeline_set_layer_texture (overlay->pipeline, 0, NULL); - } - - overlay->current_rect = *rect; -} - -static void -meta_overlay_paint (MetaOverlay *overlay, - ClutterPaintContext *paint_context) -{ - CoglFramebuffer *framebuffer; - - if (!overlay->texture) - return; - - if (!overlay->is_visible && - !(clutter_paint_context_get_paint_flags (paint_context) & - CLUTTER_PAINT_FLAG_FORCE_CURSORS)) - return; - - framebuffer = clutter_paint_context_get_framebuffer (paint_context); - cogl_framebuffer_draw_rectangle (framebuffer, - overlay->pipeline, - overlay->current_rect.origin.x, - overlay->current_rect.origin.y, - (overlay->current_rect.origin.x + - overlay->current_rect.size.width), - (overlay->current_rect.origin.y + - overlay->current_rect.size.height)); - - if (!graphene_rect_equal (&overlay->previous_rect, &overlay->current_rect)) - { - overlay->previous_rect = overlay->current_rect; - overlay->previous_is_valid = TRUE; - } -} - -static void -meta_stage_finalize (GObject *object) -{ - MetaStage *stage = META_STAGE (object); - GList *l; - int i; - - l = stage->overlays; - while (l) - { - meta_overlay_free (l->data); - 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, - ClutterPaintContext *paint_context, - 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, paint_context, watch->user_data); - } -} - -static void -meta_stage_before_paint (ClutterStage *stage, - ClutterStageView *view) -{ - MetaStage *meta_stage = META_STAGE (stage); - - notify_watchers_for_mode (meta_stage, view, NULL, - META_STAGE_WATCH_BEFORE_PAINT); -} - -static void -meta_stage_paint (ClutterActor *actor, - ClutterPaintContext *paint_context) -{ - MetaStage *stage = META_STAGE (actor); - ClutterStageView *view; - - CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor, paint_context); - - view = clutter_paint_context_get_stage_view (paint_context); - if (view) - { - notify_watchers_for_mode (stage, view, paint_context, - META_STAGE_WATCH_AFTER_ACTOR_PAINT); - } - - g_signal_emit (stage, signals[ACTORS_PAINTED], 0); - - if ((clutter_paint_context_get_paint_flags (paint_context) & - CLUTTER_PAINT_FLAG_FORCE_CURSORS)) - { - MetaCursorTracker *cursor_tracker = - meta_backend_get_cursor_tracker (stage->backend); - - meta_cursor_tracker_track_position (cursor_tracker); - } - - if (!(clutter_paint_context_get_paint_flags (paint_context) & - CLUTTER_PAINT_FLAG_NO_CURSORS)) - g_list_foreach (stage->overlays, (GFunc) meta_overlay_paint, paint_context); - - if ((clutter_paint_context_get_paint_flags (paint_context) & - CLUTTER_PAINT_FLAG_FORCE_CURSORS)) - { - MetaCursorTracker *cursor_tracker = - meta_backend_get_cursor_tracker (stage->backend); - - meta_cursor_tracker_untrack_position (cursor_tracker); - } - - if (view) - { - notify_watchers_for_mode (stage, view, paint_context, - META_STAGE_WATCH_AFTER_OVERLAY_PAINT); - } -} - -static void -meta_stage_paint_view (ClutterStage *stage, - ClutterStageView *view, - const cairo_region_t *redraw_clip) -{ - MetaStage *meta_stage = META_STAGE (stage); - - CLUTTER_STAGE_CLASS (meta_stage_parent_class)->paint_view (stage, view, - redraw_clip); - - notify_watchers_for_mode (meta_stage, view, NULL, - META_STAGE_WATCH_AFTER_PAINT); -} - -static void -meta_stage_activate (ClutterStage *actor) -{ - MetaStage *stage = META_STAGE (actor); - - CLUTTER_STAGE_CLASS (meta_stage_parent_class)->activate (actor); - - stage->is_active = TRUE; -} - -static void -meta_stage_deactivate (ClutterStage *actor) -{ - MetaStage *stage = META_STAGE (actor); - - CLUTTER_STAGE_CLASS (meta_stage_parent_class)->deactivate (actor); - - stage->is_active = FALSE; -} - -static void -on_power_save_changed (MetaMonitorManager *monitor_manager, - MetaStage *stage) -{ - if (meta_monitor_manager_get_power_save_mode (monitor_manager) == - META_POWER_SAVE_ON) - clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); -} - -static void -meta_stage_class_init (MetaStageClass *klass) -{ - ClutterStageClass *stage_class = (ClutterStageClass *) klass; - ClutterActorClass *actor_class = (ClutterActorClass *) klass; - GObjectClass *object_class = (GObjectClass *) klass; - - object_class->finalize = meta_stage_finalize; - - actor_class->paint = meta_stage_paint; - - stage_class->activate = meta_stage_activate; - stage_class->deactivate = meta_stage_deactivate; - stage_class->before_paint = meta_stage_before_paint; - stage_class->paint_view = meta_stage_paint_view; - - signals[ACTORS_PAINTED] = g_signal_new ("actors-painted", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); -} - -static void -meta_stage_init (MetaStage *stage) -{ - int i; - - for (i = 0; i < N_WATCH_MODES; i++) - stage->watchers[i] = g_ptr_array_new_with_free_func (g_free); -} - -ClutterActor * -meta_stage_new (MetaBackend *backend) -{ - MetaStage *stage; - MetaMonitorManager *monitor_manager; - - stage = g_object_new (META_TYPE_STAGE, NULL); - stage->backend = backend; - - monitor_manager = meta_backend_get_monitor_manager (backend); - g_signal_connect (monitor_manager, "power-save-mode-changed", - G_CALLBACK (on_power_save_changed), - stage); - - return CLUTTER_ACTOR (stage); -} - -static void -queue_redraw_clutter_rect (MetaStage *stage, - MetaOverlay *overlay, - graphene_rect_t *rect) -{ - cairo_rectangle_int_t clip = { - .x = floorf (rect->origin.x), - .y = floorf (rect->origin.y), - .width = ceilf (rect->size.width), - .height = ceilf (rect->size.height) - }; - - /* Since we're flooring the coordinates, we need to enlarge the clip by the - * difference between the actual coordinate and the floored value */ - clip.width += ceilf (rect->origin.x - clip.x) * 2; - clip.height += ceilf (rect->origin.y - clip.y) * 2; - - clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip); -} - -static void -queue_redraw_for_overlay (MetaStage *stage, - MetaOverlay *overlay) -{ - /* Clear the location the overlay was at before, if we need to. */ - if (overlay->previous_is_valid) - { - queue_redraw_clutter_rect (stage, overlay, &overlay->previous_rect); - overlay->previous_is_valid = FALSE; - } - - /* Draw the overlay at the new position */ - if (overlay->is_visible && overlay->texture) - queue_redraw_clutter_rect (stage, overlay, &overlay->current_rect); -} - -MetaOverlay * -meta_stage_create_cursor_overlay (MetaStage *stage) -{ - MetaOverlay *overlay; - - overlay = meta_overlay_new (stage); - stage->overlays = g_list_prepend (stage->overlays, overlay); - - return overlay; -} - -void -meta_stage_remove_cursor_overlay (MetaStage *stage, - MetaOverlay *overlay) -{ - GList *link; - - link = g_list_find (stage->overlays, overlay); - if (!link) - return; - - stage->overlays = g_list_delete_link (stage->overlays, link); - meta_overlay_free (overlay); -} - -void -meta_stage_update_cursor_overlay (MetaStage *stage, - MetaOverlay *overlay, - CoglTexture *texture, - graphene_rect_t *rect) -{ - meta_overlay_set (overlay, texture, rect); - queue_redraw_for_overlay (stage, overlay); -} - -void -meta_overlay_set_visible (MetaOverlay *overlay, - gboolean is_visible) -{ - if (overlay->is_visible == is_visible) - return; - - overlay->is_visible = is_visible; - queue_redraw_for_overlay (overlay->stage, overlay); -} - -gboolean -meta_overlay_is_visible (MetaOverlay *overlay) -{ - return overlay->is_visible; -} - -void -meta_stage_set_active (MetaStage *stage, - gboolean is_active) -{ - if (stage->is_active == is_active) - return; - - if (is_active) - g_signal_emit_by_name (CLUTTER_STAGE (stage), "activate"); - else - g_signal_emit_by_name (CLUTTER_STAGE (stage), "deactivate"); -} - -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); -} diff --git a/src/backends/meta-viewport-info.c b/src/backends/meta-viewport-info.c deleted file mode 100644 index 1adef8759..000000000 --- a/src/backends/meta-viewport-info.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (C) 2020 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Carlos Garnacho - */ - -#include "config.h" - -#include "backends/meta-viewport-info.h" -#include "core/boxes-private.h" - -typedef struct _ViewInfo ViewInfo; - -struct _ViewInfo -{ - MetaRectangle rect; - float scale; -}; - -struct _MetaViewportInfo -{ - GObject parent; - GArray *views; - gboolean is_views_scaled; -}; - -G_DEFINE_TYPE (MetaViewportInfo, meta_viewport_info, G_TYPE_OBJECT) - -static void -meta_viewport_info_finalize (GObject *object) -{ - MetaViewportInfo *info = META_VIEWPORT_INFO (object); - - g_array_unref (info->views); - - G_OBJECT_CLASS (meta_viewport_info_parent_class)->finalize (object); -} - -static void -meta_viewport_info_class_init (MetaViewportInfoClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_viewport_info_finalize; -} - -static void -meta_viewport_info_init (MetaViewportInfo *info) -{ - info->views = g_array_new (FALSE, FALSE, sizeof (ViewInfo)); -} - -MetaViewportInfo * -meta_viewport_info_new (cairo_rectangle_int_t *views, - float *scales, - int n_views, - gboolean is_views_scaled) -{ - MetaViewportInfo *viewport_info; - int i; - - viewport_info = g_object_new (META_TYPE_VIEWPORT_INFO, NULL); - - for (i = 0; i < n_views; i++) - { - ViewInfo info; - - info.rect = views[i]; - info.scale = scales[i]; - g_array_append_val (viewport_info->views, info); - } - - viewport_info->is_views_scaled = is_views_scaled; - - return viewport_info; -} - -int -meta_viewport_info_get_view_at (MetaViewportInfo *viewport_info, - float x, - float y) -{ - int i; - - for (i = 0; i < viewport_info->views->len; i++) - { - ViewInfo *info = &g_array_index (viewport_info->views, ViewInfo, i); - - if (META_POINT_IN_RECT (x, y, info->rect)) - return i; - } - - return -1; -} - -gboolean -meta_viewport_info_get_view_info (MetaViewportInfo *viewport_info, - int idx, - cairo_rectangle_int_t *rect, - float *scale) -{ - ViewInfo *info; - - if (idx < 0 || idx >= viewport_info->views->len) - return FALSE; - - info = &g_array_index (viewport_info->views, ViewInfo, idx); - if (rect) - *rect = info->rect; - if (scale) - *scale = info->scale; - - return TRUE; -} - -static gboolean -view_has_neighbor (cairo_rectangle_int_t *view, - cairo_rectangle_int_t *neighbor, - MetaDisplayDirection neighbor_direction) -{ - switch (neighbor_direction) - { - case META_DISPLAY_RIGHT: - if (neighbor->x == (view->x + view->width) && - meta_rectangle_vert_overlap (neighbor, view)) - return TRUE; - break; - case META_DISPLAY_LEFT: - if (view->x == (neighbor->x + neighbor->width) && - meta_rectangle_vert_overlap (neighbor, view)) - return TRUE; - break; - case META_DISPLAY_UP: - if (view->y == (neighbor->y + neighbor->height) && - meta_rectangle_horiz_overlap (neighbor, view)) - return TRUE; - break; - case META_DISPLAY_DOWN: - if (neighbor->y == (view->y + view->height) && - meta_rectangle_horiz_overlap (neighbor, view)) - return TRUE; - break; - } - - return FALSE; -} - -int -meta_viewport_info_get_neighbor (MetaViewportInfo *viewport_info, - int idx, - MetaDisplayDirection direction) -{ - cairo_rectangle_int_t rect; - int i; - - if (!meta_viewport_info_get_view_info (viewport_info, idx, &rect, NULL)) - return -1; - - for (i = 0; i < viewport_info->views->len; i++) - { - ViewInfo *info = &g_array_index (viewport_info->views, ViewInfo, i); - - if (idx == i) - continue; - if (view_has_neighbor (&rect, &info->rect, direction)) - return i; - } - - return -1; -} - -int -meta_viewport_info_get_num_views (MetaViewportInfo *info) -{ - return info->views->len; -} - -void -meta_viewport_info_get_extents (MetaViewportInfo *viewport_info, - float *width, - float *height) -{ - int min_x = G_MAXINT, min_y = G_MAXINT, max_x = G_MININT, max_y = G_MININT, i; - - g_return_if_fail (viewport_info != NULL); - - for (i = 0; i < viewport_info->views->len; i++) - { - ViewInfo *info = &g_array_index (viewport_info->views, ViewInfo, i); - - min_x = MIN (min_x, info->rect.x); - max_x = MAX (max_x, info->rect.x + info->rect.width); - min_y = MIN (min_y, info->rect.y); - max_y = MAX (max_y, info->rect.y + info->rect.height); - } - - if (width) - *width = (float) max_x - min_x; - if (height) - *height = (float) max_y - min_y; -} - -gboolean -meta_viewport_info_is_views_scaled (MetaViewportInfo *viewport_info) -{ - return viewport_info->is_views_scaled; -} diff --git a/src/backends/meta-viewport-info.h b/src/backends/meta-viewport-info.h deleted file mode 100644 index e10f5b78f..000000000 --- a/src/backends/meta-viewport-info.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2020 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Carlos Garnacho - */ - -#ifndef META_VIEWPORT_INFO_H -#define META_VIEWPORT_INFO_H - -#include -#include - -#include "meta/display.h" - -#define META_TYPE_VIEWPORT_INFO (meta_viewport_info_get_type ()) -G_DECLARE_FINAL_TYPE (MetaViewportInfo, meta_viewport_info, - META, VIEWPORT_INFO, GObject) - -MetaViewportInfo * meta_viewport_info_new (cairo_rectangle_int_t *views, - float *scales, - int n_views, - gboolean is_views_scaled); - -int meta_viewport_info_get_view_at (MetaViewportInfo *info, - float x, - float y); - -gboolean meta_viewport_info_get_view_info (MetaViewportInfo *viewport_info, - int idx, - cairo_rectangle_int_t *rect, - float *scale); - -int meta_viewport_info_get_neighbor (MetaViewportInfo *info, - int idx, - MetaDisplayDirection direction); - -int meta_viewport_info_get_num_views (MetaViewportInfo *info); - -void meta_viewport_info_get_extents (MetaViewportInfo *info, - float *width, - float *height); - -gboolean meta_viewport_info_is_views_scaled (MetaViewportInfo *info); - -#endif /* META_VIEWPORT_INFO_H */ diff --git a/src/backends/meta-virtual-monitor.c b/src/backends/meta-virtual-monitor.c deleted file mode 100644 index 2bd95ffd7..000000000 --- a/src/backends/meta-virtual-monitor.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright (C) 2021 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "backends/meta-virtual-monitor.h" - -#include "backends/meta-crtc.h" -#include "backends/meta-crtc-mode.h" -#include "backends/meta-output.h" - -enum -{ - DESTROY, - - N_SIGNALS -}; - -static guint signals[N_SIGNALS] = { 0 }; - -enum -{ - PROP_0, - - PROP_CRTC, - PROP_CRTC_MODE, - PROP_OUTPUT, - - N_PROPS -}; - -static GParamSpec *obj_props[N_PROPS]; - -typedef struct _MetaVirtualMonitorPrivate -{ - MetaCrtc *crtc; - MetaCrtcMode *crtc_mode; - MetaOutput *output; - - gboolean is_destroyed; -} MetaVirtualMonitorPrivate; - -G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaVirtualMonitor, meta_virtual_monitor, - G_TYPE_OBJECT) - -MetaVirtualMonitorInfo * -meta_virtual_monitor_info_new (int width, - int height, - float refresh_rate, - const char *vendor, - const char *product, - const char *serial) -{ - MetaVirtualMonitorInfo *info; - - info = g_new0 (MetaVirtualMonitorInfo, 1); - info->width = width; - info->height = height; - info->refresh_rate = refresh_rate; - info->vendor = g_strdup (vendor); - info->product = g_strdup (product); - info->serial = g_strdup (serial); - - return info; -} - -void -meta_virtual_monitor_info_free (MetaVirtualMonitorInfo *info) -{ - g_free (info->vendor); - g_free (info->product); - g_free (info->serial); - g_free (info); -} - -MetaCrtc * -meta_virtual_monitor_get_crtc (MetaVirtualMonitor *virtual_monitor) -{ - MetaVirtualMonitorPrivate *priv = - meta_virtual_monitor_get_instance_private (virtual_monitor); - - return priv->crtc; -} - -MetaCrtcMode * -meta_virtual_monitor_get_crtc_mode (MetaVirtualMonitor *virtual_monitor) -{ - MetaVirtualMonitorPrivate *priv = - meta_virtual_monitor_get_instance_private (virtual_monitor); - - return priv->crtc_mode; -} - -MetaOutput * -meta_virtual_monitor_get_output (MetaVirtualMonitor *virtual_monitor) -{ - MetaVirtualMonitorPrivate *priv = - meta_virtual_monitor_get_instance_private (virtual_monitor); - - return priv->output; -} - -static void -meta_virtual_monitor_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaVirtualMonitor *virtual_monitor = META_VIRTUAL_MONITOR (object); - MetaVirtualMonitorPrivate *priv = - meta_virtual_monitor_get_instance_private (virtual_monitor); - - switch (prop_id) - { - case PROP_CRTC: - priv->crtc = g_value_get_object (value); - break; - case PROP_CRTC_MODE: - priv->crtc_mode = g_value_get_object (value); - break; - case PROP_OUTPUT: - priv->output = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_virtual_monitor_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaVirtualMonitor *virtual_monitor = META_VIRTUAL_MONITOR (object); - MetaVirtualMonitorPrivate *priv = - meta_virtual_monitor_get_instance_private (virtual_monitor); - - switch (prop_id) - { - case PROP_CRTC: - g_value_set_object (value, priv->crtc); - break; - case PROP_CRTC_MODE: - g_value_set_object (value, priv->crtc_mode); - break; - case PROP_OUTPUT: - g_value_set_object (value, priv->output); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_virtual_monitor_dispose (GObject *object) -{ - MetaVirtualMonitor *virtual_monitor = META_VIRTUAL_MONITOR (object); - MetaVirtualMonitorPrivate *priv = - meta_virtual_monitor_get_instance_private (virtual_monitor); - - if (!priv->is_destroyed) - { - g_signal_emit (virtual_monitor, signals[DESTROY], 0); - priv->is_destroyed = TRUE; - } - - g_clear_object (&priv->crtc); - g_clear_object (&priv->crtc_mode); - g_clear_object (&priv->output); - - G_OBJECT_CLASS (meta_virtual_monitor_parent_class)->dispose (object); -} - -static void -meta_virtual_monitor_init (MetaVirtualMonitor *virtual_monitor) -{ -} - -static void -meta_virtual_monitor_class_init (MetaVirtualMonitorClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->set_property = meta_virtual_monitor_set_property; - object_class->get_property = meta_virtual_monitor_get_property; - object_class->dispose = meta_virtual_monitor_dispose; - - obj_props[PROP_CRTC] = - g_param_spec_object ("crtc", - "crtc", - "The virtual CRTC", - META_TYPE_CRTC, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - obj_props[PROP_CRTC_MODE] = - g_param_spec_object ("crtc-mode", - "crtc-mode", - "The virtual CRTC mode", - META_TYPE_CRTC_MODE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - obj_props[PROP_OUTPUT] = - g_param_spec_object ("output", - "output", - "The virtual output", - META_TYPE_OUTPUT, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, N_PROPS, obj_props); - - signals[DESTROY] = - g_signal_new ("destroy", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); -} diff --git a/src/backends/meta-virtual-monitor.h b/src/backends/meta-virtual-monitor.h deleted file mode 100644 index 2b733df9c..000000000 --- a/src/backends/meta-virtual-monitor.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2021 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_VIRTUAL_MONITOR_H -#define META_VIRTUAL_MONITOR_H - -#include - -#include "backends/meta-backend-types.h" -#include "core/util-private.h" - -typedef struct _MetaVirtualMonitorInfo -{ - int width; - int height; - float refresh_rate; - - char *vendor; - char *product; - char *serial; -} MetaVirtualMonitorInfo; - -#define META_TYPE_VIRTUAL_MONITOR (meta_virtual_monitor_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaVirtualMonitor, meta_virtual_monitor, - META, VIRTUAL_MONITOR, - GObject) - -struct _MetaVirtualMonitorClass -{ - GObjectClass parent_class; -}; - -META_EXPORT_TEST -MetaVirtualMonitorInfo * meta_virtual_monitor_info_new (int width, - int height, - float refresh_rate, - const char *vendor, - const char *product, - const char *serial); - -META_EXPORT_TEST -void meta_virtual_monitor_info_free (MetaVirtualMonitorInfo *info); - -MetaCrtc * meta_virtual_monitor_get_crtc (MetaVirtualMonitor *virtual_monitor); - -MetaCrtcMode * meta_virtual_monitor_get_crtc_mode (MetaVirtualMonitor *virtual_monitor); - -META_EXPORT_TEST -MetaOutput * meta_virtual_monitor_get_output (MetaVirtualMonitor *virtual_monitor); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaVirtualMonitorInfo, - meta_virtual_monitor_info_free) - -#endif /* META_VIRTUAL_MONITOR_H */ diff --git a/src/backends/native/dbus-utils.c b/src/backends/native/dbus-utils.c deleted file mode 100644 index 79fafe881..000000000 --- a/src/backends/native/dbus-utils.c +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -#include "config.h" - -#include "backends/native/dbus-utils.h" - -#include - -/* Stolen from tp_escape_as_identifier, from tp-glib, - * which follows the same escaping convention as systemd. - */ -static inline gboolean -_esc_ident_bad (gchar c, gboolean is_first) -{ - return ((c < 'a' || c > 'z') && - (c < 'A' || c > 'Z') && - (c < '0' || c > '9' || is_first)); -} - -static gchar * -escape_dbus_component (const gchar *name) -{ - gboolean bad = FALSE; - size_t len = 0; - GString *op; - const gchar *ptr, *first_ok; - - g_return_val_if_fail (name != NULL, NULL); - - /* fast path for empty name */ - if (name[0] == '\0') - return g_strdup ("_"); - - for (ptr = name; *ptr; ptr++) - { - if (_esc_ident_bad (*ptr, ptr == name)) - { - bad = TRUE; - len += 3; - } - else - len++; - } - - /* fast path if it's clean */ - if (!bad) - return g_strdup (name); - - /* If strictly less than ptr, first_ok is the first uncopied safe character. - */ - first_ok = name; - op = g_string_sized_new (len); - for (ptr = name; *ptr; ptr++) - { - if (_esc_ident_bad (*ptr, ptr == name)) - { - /* copy preceding safe characters if any */ - if (first_ok < ptr) - { - g_string_append_len (op, first_ok, ptr - first_ok); - } - /* escape the unsafe character */ - g_string_append_printf (op, "_%02x", (unsigned char)(*ptr)); - /* restart after it */ - first_ok = ptr + 1; - } - } - /* copy trailing safe characters if any */ - if (first_ok < ptr) - { - g_string_append_len (op, first_ok, ptr - first_ok); - } - return g_string_free (op, FALSE); -} - -char * -get_escaped_dbus_path (const char *prefix, - const char *component) -{ - char *escaped_component = escape_dbus_component (component); - char *path = g_strconcat (prefix, "/", escaped_component, NULL); - - g_free (escaped_component); - return path; -} diff --git a/src/backends/native/dbus-utils.h b/src/backends/native/dbus-utils.h deleted file mode 100644 index ee56c455a..000000000 --- a/src/backends/native/dbus-utils.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -#ifndef DBUS_UTILS_H -#define DBUS_UTILS_H - -char * -get_escaped_dbus_path (const char *prefix, - const char *component); - -#endif /* DBUS_UTILS_H */ diff --git a/src/backends/native/gen-default-modes.py b/src/backends/native/gen-default-modes.py deleted file mode 100755 index fed514d45..000000000 --- a/src/backends/native/gen-default-modes.py +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright (C) 2016 Red Hat Inc. -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 2 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -import os -import sys - -if len(sys.argv) != 2: - print("Usage: %s [output file]"%sys.argv[0]) - exit(1) - -common_resolutions = [ - # 4:3 - (800, 600), - (1024, 768), - (1152, 864), - (1280, 960), - (1400, 1050), - (1440, 1080), - (1600, 1200), - (1920, 1440), - (2048, 1536), - # 16:10 - (1280, 800), - (1440, 900), - (1680, 1050), - (1920, 1200), - (2560, 1600), - # 16:9 - (1280, 720), - (1366, 768), - (1600, 900), - (1920, 1080), - (2048, 1152), - (2560, 1440), - (2880, 1620), - (3200, 1800), - (3840, 2160), - (4096, 2304), - (5120, 2880), -] - -output_lines = [ - "/* Generated by gen-default-modes.py */\n", - "static const drmModeModeInfo meta_default_landscape_drm_mode_infos[] = {", -] - -def sync_flags(hsync, vsync): - flags = "DRM_MODE_FLAG_" - flags += "NHSYNC" if hsync[0] == '-' else "PHSYNC" - flags += " | DRM_MODE_FLAG_" - flags += "NVSYNC" if vsync[0] == '-' else "PVSYNC" - return flags - -def drm_mode_info_from_modeline(line): - sline = line.split() - return "{ %d, %d, %d, %d, %d, 0, %d, %d, %d, %d, 0, 0, %s, DRM_MODE_TYPE_DEFAULT, %s }," % \ - (int(float(sline[2]) * 1000), - int(sline[3]), - int(sline[4]), - int(sline[5]), - int(sline[6]), - int(sline[7]), - int(sline[8]), - int(sline[9]), - int(sline[10]), - sync_flags(sline[11], sline[12]), - sline[1]) - -def portrait_drm_mode_info_from_modeline(line): - sline = line.split() - return "{ %d, %d, %d, %d, %d, 0, %d, %d, %d, %d, 0, 0, %s, DRM_MODE_TYPE_DEFAULT, \"%dx%d_60.00\" }," % \ - (int(float(sline[2]) * 1000), - int(sline[7]), - int(sline[8]), - int(sline[9]), - int(sline[10]), - int(sline[3]), - int(sline[4]), - int(sline[5]), - int(sline[6]), - sync_flags(sline[12], sline[11]), - int(sline[7]), int(sline[3])) - -for resolution in common_resolutions: - cvt = os.popen("%s %s %s" % ('cvt', resolution[0], resolution[1])) - cvt.readline() # discard comment line - line = cvt.readline() - output_lines.append(drm_mode_info_from_modeline(line)) - cvt.close() -output_lines.append("};") - -output_lines.append("") -output_lines.append("static const drmModeModeInfo meta_default_portrait_drm_mode_infos[] = {") -for resolution in common_resolutions: - cvt = os.popen("%s %s %s" % ('cvt', resolution[0], resolution[1])) - cvt.readline() # discard comment line - line = cvt.readline() - output_lines.append(portrait_drm_mode_info_from_modeline(line)) - cvt.close() -output_lines.append("};") - -try: - output_file = open(sys.argv[1], 'w') - - for line in output_lines: - output_file.write(line + "\n") - output_file.flush() - output_file.close() -except: - print("Failed to generate modelines:", sys.exc_info()[0]) - exit(1) diff --git a/src/backends/native/meta-backend-native-private.h b/src/backends/native/meta-backend-native-private.h deleted file mode 100644 index cd184685f..000000000 --- a/src/backends/native/meta-backend-native-private.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#ifndef META_BACKEND_NATIVE_PRIVATE_H -#define META_BACKEND_NATIVE_PRIVATE_H - -#include "backends/native/meta-backend-native.h" -#include "backends/native/meta-barrier-native.h" - -MetaBarrierManagerNative *meta_backend_native_get_barrier_manager (MetaBackendNative *native); - -MetaDevicePool * meta_backend_native_get_device_pool (MetaBackendNative *native); - -#endif /* META_BACKEND_NATIVE_PRIVATE_H */ diff --git a/src/backends/native/meta-backend-native-types.h b/src/backends/native/meta-backend-native-types.h deleted file mode 100644 index 152b57cf6..000000000 --- a/src/backends/native/meta-backend-native-types.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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; -typedef struct _MetaSeatNative MetaSeatNative; -typedef struct _MetaSeatImpl MetaSeatImpl; -typedef struct _MetaKeymapNative MetaKeymapNative; -typedef struct _MetaRendererNative MetaRendererNative; -typedef struct _MetaGpuKms MetaGpuKms; -typedef struct _MetaCrtcVirtual MetaCrtcVirtual; -typedef struct _MetaCrtcModeVirtual MetaCrtcModeVirtual; -typedef struct _MetaDevicePool MetaDevicePool; -typedef struct _MetaDeviceFile MetaDeviceFile; - -typedef enum _MetaSeatNativeFlag -{ - META_SEAT_NATIVE_FLAG_NONE = 0, - META_SEAT_NATIVE_FLAG_NO_LIBINPUT = 1 << 0, -} MetaSeatNativeFlag; - -#endif /* META_BACKEND_NATIVE_TYPES_H */ diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c deleted file mode 100644 index 81d9629d0..000000000 --- a/src/backends/native/meta-backend-native.c +++ /dev/null @@ -1,768 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -/** - * SECTION:meta-backend-native - * @title: MetaBackendNative - * @short_description: A native (KMS/evdev) MetaBackend - * - * MetaBackendNative is an implementation of #MetaBackend that uses "native" - * technologies like DRM/KMS and libinput/evdev to perform the necessary - * functions. - */ - -#include "config.h" - -#include "backends/native/meta-backend-native.h" -#include "backends/native/meta-backend-native-private.h" -#include "backends/native/meta-input-thread.h" - -#include -#include - -#include "backends/meta-cursor-tracker-private.h" -#include "backends/meta-idle-manager.h" -#include "backends/meta-keymap-utils.h" -#include "backends/meta-logical-monitor.h" -#include "backends/meta-monitor-manager-private.h" -#include "backends/meta-pointer-constraint.h" -#include "backends/meta-settings-private.h" -#include "backends/meta-stage-private.h" -#include "backends/native/meta-clutter-backend-native.h" -#include "backends/native/meta-device-pool-private.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-native.h" -#include "backends/native/meta-renderer-native.h" -#include "backends/native/meta-seat-native.h" -#include "backends/native/meta-stage-native.h" -#include "cogl/cogl.h" -#include "core/meta-border.h" -#include "meta/main.h" - -#ifdef HAVE_REMOTE_DESKTOP -#include "backends/meta-screen-cast.h" -#endif - -enum -{ - PROP_0, - - PROP_HEADLESS, - - N_PROPS -}; - -static GParamSpec *obj_props[N_PROPS]; - -struct _MetaBackendNative -{ - MetaBackend parent; - - MetaLauncher *launcher; - MetaDevicePool *device_pool; - MetaUdev *udev; - MetaKms *kms; - - gboolean is_headless; - - gulong udev_device_added_handler_id; -}; - -static GInitableIface *initable_parent_iface; - -static void -initable_iface_init (GInitableIface *initable_iface); - -G_DEFINE_TYPE_WITH_CODE (MetaBackendNative, meta_backend_native, META_TYPE_BACKEND, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - initable_iface_init)) - -static void -disconnect_udev_device_added_handler (MetaBackendNative *native); - -static void -meta_backend_native_dispose (GObject *object) -{ - MetaBackendNative *native = META_BACKEND_NATIVE (object); - - if (native->udev_device_added_handler_id) - { - disconnect_udev_device_added_handler (native); - native->udev_device_added_handler_id = 0; - } - - if (native->kms) - meta_kms_prepare_shutdown (native->kms); - - G_OBJECT_CLASS (meta_backend_native_parent_class)->dispose (object); - - g_clear_object (&native->kms); - g_clear_object (&native->udev); - g_clear_object (&native->device_pool); - g_clear_pointer (&native->launcher, meta_launcher_free); -} - -static ClutterBackend * -meta_backend_native_create_clutter_backend (MetaBackend *backend) -{ - return g_object_new (META_TYPE_CLUTTER_BACKEND_NATIVE, NULL); -} - -static ClutterSeat * -meta_backend_native_create_default_seat (MetaBackend *backend, - GError **error) -{ - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - const char *seat_id; - MetaSeatNativeFlag flags; - - seat_id = meta_backend_native_get_seat_id (backend_native); - - if (meta_backend_native_is_headless (backend_native)) - flags = META_SEAT_NATIVE_FLAG_NO_LIBINPUT; - else - flags = META_SEAT_NATIVE_FLAG_NONE; - - return CLUTTER_SEAT (g_object_new (META_TYPE_SEAT_NATIVE, - "backend", backend, - "seat-id", seat_id, - "flags", flags, - NULL)); -} - -#ifdef HAVE_REMOTE_DESKTOP -static void -maybe_disable_screen_cast_dma_bufs (MetaBackendNative *native) -{ - MetaBackend *backend = META_BACKEND (native); - MetaSettings *settings = meta_backend_get_settings (backend); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer); - MetaScreenCast *screen_cast = meta_backend_get_screen_cast (backend); - MetaGpuKms *primary_gpu; - MetaKmsDevice *kms_device; - const char *driver_name; - static const char *enable_dma_buf_drivers[] = { - "i915", - NULL, - }; - - primary_gpu = meta_renderer_native_get_primary_gpu (renderer_native); - if (!primary_gpu) - { - g_message ("Disabling DMA buffer screen sharing (surfaceless)"); - goto disable_dma_bufs; - } - - kms_device = meta_gpu_kms_get_kms_device (primary_gpu); - driver_name = meta_kms_device_get_driver_name (kms_device); - - if (g_strv_contains (enable_dma_buf_drivers, driver_name)) - return; - - if (meta_settings_is_experimental_feature_enabled (settings, - META_EXPERIMENTAL_FEATURE_DMA_BUF_SCREEN_SHARING)) - return; - - g_message ("Disabling DMA buffer screen sharing for driver '%s'.", - driver_name); - -disable_dma_bufs: - meta_screen_cast_disable_dma_bufs (screen_cast); -} -#endif /* HAVE_REMOTE_DESKTOP */ - -static void -update_viewports (MetaBackend *backend) -{ - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - MetaSeatNative *seat = - META_SEAT_NATIVE (clutter_backend_get_default_seat (clutter_backend)); - MetaViewportInfo *viewports; - - viewports = meta_monitor_manager_get_viewports (monitor_manager); - meta_seat_native_set_viewports (seat, viewports); - g_object_unref (viewports); -} - -static void -meta_backend_native_post_init (MetaBackend *backend) -{ - MetaSettings *settings = meta_backend_get_settings (backend); - - META_BACKEND_CLASS (meta_backend_native_parent_class)->post_init (backend); - - if (meta_settings_is_experimental_feature_enabled (settings, - META_EXPERIMENTAL_FEATURE_RT_SCHEDULER)) - { - int retval; - struct sched_param sp = { - .sched_priority = sched_get_priority_min (SCHED_RR) - }; - - retval = sched_setscheduler (0, SCHED_RR | SCHED_RESET_ON_FORK, &sp); - - if (retval != 0) - g_warning ("Failed to set RT scheduler: %m"); - } - -#ifdef HAVE_REMOTE_DESKTOP - maybe_disable_screen_cast_dma_bufs (META_BACKEND_NATIVE (backend)); -#endif - - update_viewports (backend); -} - -static MetaMonitorManager * -meta_backend_native_create_monitor_manager (MetaBackend *backend, - GError **error) -{ - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - MetaMonitorManager *manager; - - manager = g_initable_new (META_TYPE_MONITOR_MANAGER_NATIVE, NULL, error, - "backend", backend, - "needs-outputs", !backend_native->is_headless, - NULL); - if (!manager) - return NULL; - - g_signal_connect_swapped (manager, "monitors-changed-internal", - G_CALLBACK (update_viewports), backend); - - return manager; -} - -static MetaCursorRenderer * -meta_backend_native_get_cursor_renderer (MetaBackend *backend, - ClutterInputDevice *device) -{ - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - MetaSeatNative *seat_native = - META_SEAT_NATIVE (clutter_backend_get_default_seat (clutter_backend)); - - return meta_seat_native_maybe_ensure_cursor_renderer (seat_native, device); -} - -static MetaRenderer * -meta_backend_native_create_renderer (MetaBackend *backend, - GError **error) -{ - MetaBackendNative *native = META_BACKEND_NATIVE (backend); - MetaRendererNative *renderer_native; - - renderer_native = meta_renderer_native_new (native, error); - if (!renderer_native) - return NULL; - - return META_RENDERER (renderer_native); -} - -static MetaInputSettings * -meta_backend_native_get_input_settings (MetaBackend *backend) -{ - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - MetaSeatNative *seat_native = - META_SEAT_NATIVE (clutter_backend_get_default_seat (clutter_backend)); - - return meta_seat_impl_get_input_settings (seat_native->impl); -} - -static MetaLogicalMonitor * -meta_backend_native_get_current_logical_monitor (MetaBackend *backend) -{ - MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - graphene_point_t point; - - meta_cursor_tracker_get_pointer (cursor_tracker, &point, NULL); - return meta_monitor_manager_get_logical_monitor_at (monitor_manager, - point.x, point.y); -} - -static void -meta_backend_native_set_keymap (MetaBackend *backend, - const char *layouts, - const char *variants, - const char *options) -{ - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - ClutterSeat *seat; - - seat = clutter_backend_get_default_seat (clutter_backend); - meta_seat_native_set_keyboard_map (META_SEAT_NATIVE (seat), - layouts, variants, options); - - meta_backend_notify_keymap_changed (backend); -} - -static struct xkb_keymap * -meta_backend_native_get_keymap (MetaBackend *backend) -{ - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - ClutterSeat *seat; - - seat = clutter_backend_get_default_seat (clutter_backend); - return meta_seat_native_get_keyboard_map (META_SEAT_NATIVE (seat)); -} - -static xkb_layout_index_t -meta_backend_native_get_keymap_layout_group (MetaBackend *backend) -{ - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - ClutterSeat *seat; - - seat = clutter_backend_get_default_seat (clutter_backend); - return meta_seat_native_get_keyboard_layout_index (META_SEAT_NATIVE (seat)); -} - -static void -meta_backend_native_lock_layout_group (MetaBackend *backend, - guint idx) -{ - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - xkb_layout_index_t old_idx; - ClutterSeat *seat; - - old_idx = meta_backend_native_get_keymap_layout_group (backend); - if (old_idx == idx) - return; - - seat = clutter_backend_get_default_seat (clutter_backend); - meta_seat_native_set_keyboard_layout_index (META_SEAT_NATIVE (seat), idx); - meta_backend_notify_keymap_layout_group_changed (backend, idx); -} - -const char * -meta_backend_native_get_seat_id (MetaBackendNative *backend_native) -{ - if (backend_native->is_headless) - return "seat0"; - else - return meta_launcher_get_seat_id (backend_native->launcher); -} - -gboolean -meta_backend_native_is_headless (MetaBackendNative *backend_native) -{ - return backend_native->is_headless; -} - -static void -meta_backend_native_set_pointer_constraint (MetaBackend *backend, - MetaPointerConstraint *constraint) -{ - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - ClutterSeat *seat = clutter_backend_get_default_seat (clutter_backend); - MetaPointerConstraintImpl *constraint_impl = NULL; - cairo_region_t *region; - - if (constraint) - { - region = meta_pointer_constraint_get_region (constraint); - constraint_impl = meta_pointer_constraint_impl_native_new (constraint, - region); - } - - meta_seat_native_set_pointer_constraint (META_SEAT_NATIVE (seat), - constraint_impl); -} - -static void -meta_backend_native_update_screen_size (MetaBackend *backend, - int width, int height) -{ - ClutterActor *stage = meta_backend_get_stage (backend); - ClutterStageWindow *stage_window = - _clutter_stage_get_window (CLUTTER_STAGE (stage)); - MetaStageNative *stage_native = META_STAGE_NATIVE (stage_window); - - meta_stage_native_rebuild_views (stage_native); - - 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; - - if (meta_is_udev_device_disable_modifiers (device)) - flags |= META_KMS_DEVICE_FLAG_DISABLE_MODIFIERS; - - if (meta_is_udev_device_preferred_primary (device)) - flags |= META_KMS_DEVICE_FLAG_PREFERRED_PRIMARY; - - 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; - } - } - - if (meta_is_udev_device_ignore (device)) - { - g_message ("Ignoring DRM device '%s' (from udev rule)", device_path); - 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); - 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_clear_signal_handler (&native->udev_device_added_handler_id, native->udev); -} - -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 (*error) - return FALSE; - - for (l = devices; l; l = l->next) - { - GUdevDevice *device = l->data; - MetaGpuKms *gpu_kms; - GError *local_error = NULL; - - if (meta_is_udev_device_ignore (device)) - { - g_message ("Ignoring DRM device '%s' (from udev rule)", - g_udev_device_get_device_file (device)); - continue; - } - - 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 (!native->is_headless && - 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); - MetaKmsFlags kms_flags; - - if (!meta_is_stage_views_enabled ()) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "The native backend requires stage views"); - return FALSE; - } - - if (!native->is_headless) - { - native->launcher = meta_launcher_new (error); - if (!native->launcher) - return FALSE; - } - - native->device_pool = meta_device_pool_new (native->launcher); - native->udev = meta_udev_new (native); - - kms_flags = META_KMS_FLAG_NONE; - if (native->is_headless) - kms_flags |= META_KMS_FLAG_NO_MODE_SETTING; - - native->kms = meta_kms_new (META_BACKEND (native), kms_flags, error); - if (!native->kms) - return FALSE; - - if (!init_gpus (native, error)) - return FALSE; - - return initable_parent_iface->init (initable, cancellable, error); -} - -static void -meta_backend_native_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaBackendNative *backend_native = META_BACKEND_NATIVE (object); - - switch (prop_id) - { - case PROP_HEADLESS: - backend_native->is_headless = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -initable_iface_init (GInitableIface *initable_iface) -{ - initable_parent_iface = g_type_interface_peek_parent (initable_iface); - - initable_iface->init = meta_backend_native_initable_init; -} - -static void -meta_backend_native_class_init (MetaBackendNativeClass *klass) -{ - MetaBackendClass *backend_class = META_BACKEND_CLASS (klass); - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->set_property = meta_backend_native_set_property; - object_class->dispose = meta_backend_native_dispose; - - backend_class->create_clutter_backend = meta_backend_native_create_clutter_backend; - backend_class->create_default_seat = meta_backend_native_create_default_seat; - - backend_class->post_init = meta_backend_native_post_init; - - backend_class->create_monitor_manager = meta_backend_native_create_monitor_manager; - backend_class->get_cursor_renderer = meta_backend_native_get_cursor_renderer; - backend_class->create_renderer = meta_backend_native_create_renderer; - backend_class->get_input_settings = meta_backend_native_get_input_settings; - - backend_class->get_current_logical_monitor = meta_backend_native_get_current_logical_monitor; - - backend_class->set_keymap = meta_backend_native_set_keymap; - backend_class->get_keymap = meta_backend_native_get_keymap; - backend_class->get_keymap_layout_group = meta_backend_native_get_keymap_layout_group; - backend_class->lock_layout_group = meta_backend_native_lock_layout_group; - backend_class->update_screen_size = meta_backend_native_update_screen_size; - - backend_class->set_pointer_constraint = meta_backend_native_set_pointer_constraint; - - obj_props[PROP_HEADLESS] = - g_param_spec_boolean ("headless", - "headless", - "Headless", - FALSE, - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, N_PROPS, obj_props); -} - -static void -meta_backend_native_init (MetaBackendNative *native) -{ -} - -MetaLauncher * -meta_backend_native_get_launcher (MetaBackendNative *native) -{ - return native->launcher; -} - -MetaDevicePool * -meta_backend_native_get_device_pool (MetaBackendNative *native) -{ - return native->device_pool; -} - -MetaUdev * -meta_backend_native_get_udev (MetaBackendNative *native) -{ - return native->udev; -} - -MetaKms * -meta_backend_native_get_kms (MetaBackendNative *native) -{ - return native->kms; -} - -gboolean -meta_activate_vt (int vt, GError **error) -{ - MetaBackend *backend = meta_get_backend (); - MetaBackendNative *native = META_BACKEND_NATIVE (backend); - MetaLauncher *launcher = meta_backend_native_get_launcher (native); - - if (native->is_headless) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Can't switch VT while headless"); - return FALSE; - } - - return meta_launcher_activate_vt (launcher, vt, error); -} - -void -meta_backend_native_pause (MetaBackendNative *native) -{ - MetaBackend *backend = META_BACKEND (native); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerNative *monitor_manager_native = - META_MONITOR_MANAGER_NATIVE (monitor_manager); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - MetaSeatNative *seat = - META_SEAT_NATIVE (clutter_backend_get_default_seat (clutter_backend)); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - - COGL_TRACE_BEGIN_SCOPED (MetaBackendNativePause, - "Backend (pause)"); - - meta_seat_native_release_devices (seat); - meta_renderer_pause (renderer); - - disconnect_udev_device_added_handler (native); - - meta_monitor_manager_native_pause (monitor_manager_native); -} - -void meta_backend_native_resume (MetaBackendNative *native) -{ - MetaBackend *backend = META_BACKEND (native); - ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend)); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerNative *monitor_manager_native = - META_MONITOR_MANAGER_NATIVE (monitor_manager); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - MetaSeatNative *seat = - META_SEAT_NATIVE (clutter_backend_get_default_seat (clutter_backend)); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - MetaIdleManager *idle_manager; - MetaInputSettings *input_settings; - - COGL_TRACE_BEGIN_SCOPED (MetaBackendNativeResume, - "Backend (resume)"); - - meta_monitor_manager_native_resume (monitor_manager_native); - meta_kms_resume (native->kms); - - connect_udev_device_added_handler (native); - - meta_seat_native_reclaim_devices (seat); - meta_renderer_resume (renderer); - - clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); - - idle_manager = meta_backend_get_idle_manager (backend); - meta_idle_manager_reset_idle_time (idle_manager); - - input_settings = meta_backend_get_input_settings (backend); - meta_input_settings_maybe_restore_numlock_state (input_settings); - - clutter_seat_ensure_a11y_state (CLUTTER_SEAT (seat)); -} diff --git a/src/backends/native/meta-backend-native.h b/src/backends/native/meta-backend-native.h deleted file mode 100644 index aad4c8413..000000000 --- a/src/backends/native/meta-backend-native.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -#ifndef META_BACKEND_NATIVE_H -#define META_BACKEND_NATIVE_H - -#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 ()) -META_EXPORT_TEST -G_DECLARE_FINAL_TYPE (MetaBackendNative, meta_backend_native, - META, BACKEND_NATIVE, MetaBackend) - -gboolean meta_activate_vt (int vt, GError **error); - -void meta_backend_native_pause (MetaBackendNative *backend_native); - -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); - -const char * meta_backend_native_get_seat_id (MetaBackendNative *backend_native); - -gboolean meta_backend_native_is_headless (MetaBackendNative *backend_native); - -#endif /* META_BACKEND_NATIVE_H */ diff --git a/src/backends/native/meta-barrier-native.c b/src/backends/native/meta-barrier-native.c deleted file mode 100644 index 3c9c1eabe..000000000 --- a/src/backends/native/meta-barrier-native.c +++ /dev/null @@ -1,652 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -/** - * SECTION:barrier-native - * @Title: MetaBarrierImplNative - * @Short_Description: Pointer barriers implementation for the native backend - */ - -#include "config.h" - -#include "backends/native/meta-barrier-native.h" - -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-barrier-private.h" -#include "backends/native/meta-seat-native.h" -#include "meta/barrier.h" -#include "meta/util.h" - -struct _MetaBarrierManagerNative -{ - GHashTable *barriers; - GMutex mutex; -}; - -typedef enum -{ - /* The barrier is active and responsive to pointer motion. */ - META_BARRIER_STATE_ACTIVE, - - /* An intermediate state after a pointer hit the pointer barrier. */ - META_BARRIER_STATE_HIT, - - /* The barrier was hit by a pointer and is still within the hit box and - * has not been released.*/ - META_BARRIER_STATE_HELD, - - /* The pointer was released by the user. If the following motion hits - * the barrier, it will pass through. */ - META_BARRIER_STATE_RELEASE, - - /* An intermediate state when the pointer has left the barrier. */ - META_BARRIER_STATE_LEFT, -} MetaBarrierState; - -struct _MetaBarrierImplNative -{ - MetaBarrierImpl parent; - - MetaBarrier *barrier; - MetaBarrierManagerNative *manager; - - gboolean is_active; - MetaBarrierState state; - int trigger_serial; - guint32 last_event_time; - MetaBarrierDirection blocked_dir; - GMainContext *main_context; -}; - -G_DEFINE_TYPE (MetaBarrierImplNative, - meta_barrier_impl_native, - META_TYPE_BARRIER_IMPL) - -static int -next_serial (void) -{ - static int barrier_serial = 1; - - barrier_serial++; - - /* If it wraps, avoid 0 as it's not a valid serial. */ - if (barrier_serial == 0) - barrier_serial++; - - return barrier_serial; -} - -static gboolean -is_barrier_horizontal (MetaBarrier *barrier) -{ - return meta_border_is_horizontal (&barrier->priv->border); -} - -static gboolean -is_barrier_blocking_directions (MetaBarrier *barrier, - MetaBarrierDirection directions) -{ - return meta_border_is_blocking_directions (&barrier->priv->border, - directions); -} - -static void -dismiss_pointer (MetaBarrierImplNative *self) -{ - self->state = META_BARRIER_STATE_LEFT; -} - -/* - * Calculate the hit box for a held motion. The hit box is a 2 px wide region - * in the opposite direction of every direction the barrier blocks. The purpose - * of this is to allow small movements without receiving a "left" signal. This - * heuristic comes from the X.org pointer barrier implementation. - */ -static MetaLine2 -calculate_barrier_hit_box (MetaBarrier *barrier) -{ - MetaLine2 hit_box = barrier->priv->border.line; - - if (is_barrier_horizontal (barrier)) - { - if (is_barrier_blocking_directions (barrier, - META_BARRIER_DIRECTION_POSITIVE_Y)) - hit_box.a.y -= 2.0f; - if (is_barrier_blocking_directions (barrier, - META_BARRIER_DIRECTION_NEGATIVE_Y)) - hit_box.b.y += 2.0f; - } - else - { - if (is_barrier_blocking_directions (barrier, - META_BARRIER_DIRECTION_POSITIVE_X)) - hit_box.a.x -= 2.0f; - if (is_barrier_blocking_directions (barrier, - META_BARRIER_DIRECTION_NEGATIVE_X)) - hit_box.b.x += 2.0f; - } - - return hit_box; -} - -static gboolean -is_within_box (MetaLine2 box, - MetaVector2 point) -{ - return (point.x >= box.a.x && point.x < box.b.x && - point.y >= box.a.y && point.y < box.b.y); -} - -static void -maybe_release_barrier (gpointer key, - gpointer value, - gpointer user_data) -{ - MetaBarrierImplNative *self = key; - MetaBarrier *barrier = self->barrier; - MetaLine2 *motion = user_data; - MetaLine2 hit_box; - - if (self->state != META_BARRIER_STATE_HELD) - return; - - /* Release if we end up outside barrier end points. */ - if (is_barrier_horizontal (barrier)) - { - if (motion->b.x > MAX (barrier->priv->border.line.a.x, - barrier->priv->border.line.b.x) || - motion->b.x < MIN (barrier->priv->border.line.a.x, - barrier->priv->border.line.b.x)) - { - dismiss_pointer (self); - return; - } - } - else - { - if (motion->b.y > MAX (barrier->priv->border.line.a.y, - barrier->priv->border.line.b.y) || - motion->b.y < MIN (barrier->priv->border.line.a.y, - barrier->priv->border.line.b.y)) - { - dismiss_pointer (self); - return; - } - } - - /* Release if we don't intersect and end up outside of hit box. */ - hit_box = calculate_barrier_hit_box (barrier); - if (!is_within_box (hit_box, motion->b)) - { - dismiss_pointer (self); - return; - } -} - -static void -maybe_release_barriers (MetaBarrierManagerNative *manager, - float prev_x, - float prev_y, - float x, - float y) -{ - MetaLine2 motion = { - .a = { - .x = prev_x, - .y = prev_y, - }, - .b = { - .x = x, - .y = y, - }, - }; - - g_hash_table_foreach (manager->barriers, - maybe_release_barrier, - &motion); -} - -typedef struct _MetaClosestBarrierData -{ - struct - { - MetaLine2 motion; - MetaBarrierDirection directions; - } in; - - struct - { - float closest_distance_2; - MetaBarrierImplNative *barrier_impl; - } out; -} MetaClosestBarrierData; - -static void -update_closest_barrier (gpointer key, - gpointer value, - gpointer user_data) -{ - MetaBarrierImplNative *self = key; - MetaBarrier *barrier = self->barrier; - MetaClosestBarrierData *data = user_data; - MetaVector2 intersection; - float dx, dy; - float distance_2; - - /* Ignore if the barrier is not blocking in any of the motions directions. */ - if (!is_barrier_blocking_directions (barrier, data->in.directions)) - return; - - /* Ignore if the barrier released the pointer. */ - if (self->state == META_BARRIER_STATE_RELEASE) - return; - - /* Ignore if we are moving away from barrier. */ - if (self->state == META_BARRIER_STATE_HELD && - (data->in.directions & self->blocked_dir) == 0) - return; - - /* Check if the motion intersects with the barrier, and retrieve the - * intersection point if any. */ - if (!meta_line2_intersects_with (&barrier->priv->border.line, - &data->in.motion, - &intersection)) - return; - - /* Calculate the distance to the barrier and keep track of the closest - * barrier. */ - dx = intersection.x - data->in.motion.a.x; - dy = intersection.y - data->in.motion.a.y; - distance_2 = dx*dx + dy*dy; - if (data->out.barrier_impl == NULL || - distance_2 < data->out.closest_distance_2) - { - data->out.barrier_impl = self; - data->out.closest_distance_2 = distance_2; - } -} - -static gboolean -get_closest_barrier (MetaBarrierManagerNative *manager, - float prev_x, - float prev_y, - float x, - float y, - MetaBarrierDirection motion_dir, - MetaBarrierImplNative **barrier_impl) -{ - MetaClosestBarrierData closest_barrier_data; - - closest_barrier_data = (MetaClosestBarrierData) { - .in = { - .motion = { - .a = { - .x = prev_x, - .y = prev_y, - }, - .b = { - .x = x, - .y = y, - }, - }, - .directions = motion_dir, - }, - }; - - g_hash_table_foreach (manager->barriers, - update_closest_barrier, - &closest_barrier_data); - - if (closest_barrier_data.out.barrier_impl != NULL) - { - *barrier_impl = closest_barrier_data.out.barrier_impl; - return TRUE; - } - else - { - return FALSE; - } -} - -typedef struct _MetaBarrierEventData -{ - guint32 time; - float prev_x; - float prev_y; - float x; - float y; - float dx; - float dy; -} MetaBarrierEventData; - -typedef struct -{ - MetaBarrierEvent *event; - MetaBarrier *barrier; - MetaBarrierState state; -} MetaBarrierIdleData; - -static gboolean -emit_event_idle (MetaBarrierIdleData *idle_data) -{ - if (idle_data->state == META_BARRIER_STATE_HELD) - _meta_barrier_emit_hit_signal (idle_data->barrier, idle_data->event); - else - _meta_barrier_emit_left_signal (idle_data->barrier, idle_data->event); - - meta_barrier_event_unref (idle_data->event); - - return G_SOURCE_REMOVE; -} - -static void -queue_event (MetaBarrierImplNative *self, - MetaBarrierEvent *event) -{ - MetaBarrierIdleData *idle_data; - GSource *source; - - idle_data = g_new0 (MetaBarrierIdleData, 1); - idle_data->state = self->state; - idle_data->barrier = self->barrier; - idle_data->event = event; - - source = g_idle_source_new (); - g_source_set_priority (source, G_PRIORITY_HIGH); - g_source_set_callback (source, - (GSourceFunc) emit_event_idle, - idle_data, - g_free); - - g_source_attach (source, self->main_context); - g_source_unref (source); -} - -static void -emit_barrier_event (MetaBarrierImplNative *self, - guint32 time, - float prev_x, - float prev_y, - float x, - float y, - float dx, - float dy) -{ - MetaBarrierEvent *event = g_new0 (MetaBarrierEvent, 1); - MetaBarrierState old_state = self->state; - - switch (self->state) - { - case META_BARRIER_STATE_HIT: - self->state = META_BARRIER_STATE_HELD; - self->trigger_serial = next_serial (); - event->dt = 0; - - break; - case META_BARRIER_STATE_RELEASE: - case META_BARRIER_STATE_LEFT: - self->state = META_BARRIER_STATE_ACTIVE; - - G_GNUC_FALLTHROUGH; - case META_BARRIER_STATE_HELD: - event->dt = time - self->last_event_time; - - break; - case META_BARRIER_STATE_ACTIVE: - g_assert_not_reached (); /* Invalid state. */ - } - - event->ref_count = 1; - event->event_id = self->trigger_serial; - event->time = time; - - event->x = x; - event->y = y; - event->dx = dx; - event->dy = dy; - - event->grabbed = self->state == META_BARRIER_STATE_HELD; - event->released = old_state == META_BARRIER_STATE_RELEASE; - - self->last_event_time = time; - - queue_event (self, event); -} - -static void -maybe_emit_barrier_event (gpointer key, gpointer value, gpointer user_data) -{ - MetaBarrierImplNative *self = key; - MetaBarrierEventData *data = user_data; - - switch (self->state) - { - case META_BARRIER_STATE_ACTIVE: - break; - case META_BARRIER_STATE_HIT: - case META_BARRIER_STATE_HELD: - case META_BARRIER_STATE_RELEASE: - case META_BARRIER_STATE_LEFT: - emit_barrier_event (self, - data->time, - data->prev_x, - data->prev_y, - data->x, - data->y, - data->dx, - data->dy); - break; - } -} - -/* Clamp (x, y) to the barrier and remove clamped direction from motion_dir. */ -static void -clamp_to_barrier (MetaBarrierImplNative *self, - MetaBarrierDirection *motion_dir, - float *x, - float *y) -{ - MetaBarrier *barrier = self->barrier; - - if (is_barrier_horizontal (barrier)) - { - if (*motion_dir & META_BARRIER_DIRECTION_POSITIVE_Y) - *y = barrier->priv->border.line.a.y; - else if (*motion_dir & META_BARRIER_DIRECTION_NEGATIVE_Y) - *y = barrier->priv->border.line.a.y; - - self->blocked_dir = *motion_dir & (META_BARRIER_DIRECTION_POSITIVE_Y | - META_BARRIER_DIRECTION_NEGATIVE_Y); - *motion_dir &= ~(META_BARRIER_DIRECTION_POSITIVE_Y | - META_BARRIER_DIRECTION_NEGATIVE_Y); - } - else - { - if (*motion_dir & META_BARRIER_DIRECTION_POSITIVE_X) - *x = barrier->priv->border.line.a.x; - else if (*motion_dir & META_BARRIER_DIRECTION_NEGATIVE_X) - *x = barrier->priv->border.line.a.x; - - self->blocked_dir = *motion_dir & (META_BARRIER_DIRECTION_POSITIVE_X | - META_BARRIER_DIRECTION_NEGATIVE_X); - *motion_dir &= ~(META_BARRIER_DIRECTION_POSITIVE_X | - META_BARRIER_DIRECTION_NEGATIVE_X); - } - - self->state = META_BARRIER_STATE_HIT; -} - -void -meta_barrier_manager_native_process_in_impl (MetaBarrierManagerNative *manager, - ClutterInputDevice *device, - guint32 time, - float *x, - float *y) -{ - graphene_point_t prev_pos; - float prev_x; - float prev_y; - float orig_x = *x; - float orig_y = *y; - MetaBarrierDirection motion_dir = 0; - MetaBarrierEventData barrier_event_data; - MetaBarrierImplNative *barrier_impl; - - if (!clutter_seat_query_state (clutter_input_device_get_seat (device), - device, NULL, &prev_pos, NULL)) - return; - - g_mutex_lock (&manager->mutex); - - prev_x = prev_pos.x; - prev_y = prev_pos.y; - - /* Get the direction of the motion vector. */ - if (prev_x < *x) - motion_dir |= META_BARRIER_DIRECTION_POSITIVE_X; - else if (prev_x > *x) - motion_dir |= META_BARRIER_DIRECTION_NEGATIVE_X; - if (prev_y < *y) - motion_dir |= META_BARRIER_DIRECTION_POSITIVE_Y; - else if (prev_y > *y) - motion_dir |= META_BARRIER_DIRECTION_NEGATIVE_Y; - - /* Clamp to the closest barrier in any direction until either there are no - * more barriers to clamp to or all directions have been clamped. */ - while (motion_dir != 0) - { - if (get_closest_barrier (manager, - prev_x, prev_y, - *x, *y, - motion_dir, - &barrier_impl)) - clamp_to_barrier (barrier_impl, &motion_dir, x, y); - else - break; - } - - /* Potentially release active barrier movements. */ - maybe_release_barriers (manager, prev_x, prev_y, *x, *y); - - /* Initiate or continue barrier interaction. */ - barrier_event_data = (MetaBarrierEventData) { - .time = time, - .prev_x = prev_x, - .prev_y = prev_y, - .x = *x, - .y = *y, - .dx = orig_x - prev_x, - .dy = orig_y - prev_y, - }; - - g_hash_table_foreach (manager->barriers, - maybe_emit_barrier_event, - &barrier_event_data); - - g_mutex_unlock (&manager->mutex); -} - -static gboolean -_meta_barrier_impl_native_is_active (MetaBarrierImpl *impl) -{ - MetaBarrierImplNative *self = META_BARRIER_IMPL_NATIVE (impl); - - return self->is_active; -} - -static void -_meta_barrier_impl_native_release (MetaBarrierImpl *impl, - MetaBarrierEvent *event) -{ - MetaBarrierImplNative *self = META_BARRIER_IMPL_NATIVE (impl); - - if (self->state == META_BARRIER_STATE_HELD && - event->event_id == self->trigger_serial) - self->state = META_BARRIER_STATE_RELEASE; -} - -static void -_meta_barrier_impl_native_destroy (MetaBarrierImpl *impl) -{ - MetaBarrierImplNative *self = META_BARRIER_IMPL_NATIVE (impl); - - g_mutex_lock (&self->manager->mutex); - g_hash_table_remove (self->manager->barriers, self); - g_mutex_unlock (&self->manager->mutex); - g_main_context_unref (self->main_context); - self->is_active = FALSE; -} - -MetaBarrierImpl * -meta_barrier_impl_native_new (MetaBarrier *barrier) -{ - MetaBarrierImplNative *self; - MetaBarrierManagerNative *manager; - ClutterBackend *backend = clutter_get_default_backend (); - ClutterSeat *seat = clutter_backend_get_default_seat (backend); - - self = g_object_new (META_TYPE_BARRIER_IMPL_NATIVE, NULL); - - self->barrier = barrier; - self->is_active = TRUE; - self->main_context = g_main_context_ref_thread_default (); - - manager = meta_seat_native_get_barrier_manager (META_SEAT_NATIVE (seat)); - self->manager = manager; - g_mutex_lock (&manager->mutex); - g_hash_table_add (manager->barriers, self); - g_mutex_unlock (&manager->mutex); - - return META_BARRIER_IMPL (self); -} - -static void -meta_barrier_impl_native_class_init (MetaBarrierImplNativeClass *klass) -{ - MetaBarrierImplClass *impl_class = META_BARRIER_IMPL_CLASS (klass); - - impl_class->is_active = _meta_barrier_impl_native_is_active; - impl_class->release = _meta_barrier_impl_native_release; - impl_class->destroy = _meta_barrier_impl_native_destroy; -} - -static void -meta_barrier_impl_native_init (MetaBarrierImplNative *self) -{ -} - -MetaBarrierManagerNative * -meta_barrier_manager_native_new (void) -{ - MetaBarrierManagerNative *manager; - - manager = g_new0 (MetaBarrierManagerNative, 1); - - manager->barriers = g_hash_table_new (NULL, NULL); - g_mutex_init (&manager->mutex); - - return manager; -} diff --git a/src/backends/native/meta-barrier-native.h b/src/backends/native/meta-barrier-native.h deleted file mode 100644 index 1bcf56c7c..000000000 --- a/src/backends/native/meta-barrier-native.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#ifndef META_BARRIER_NATIVE_H -#define META_BARRIER_NATIVE_H - -#include "backends/meta-barrier-private.h" - -G_BEGIN_DECLS - -#define META_TYPE_BARRIER_IMPL_NATIVE (meta_barrier_impl_native_get_type ()) -G_DECLARE_FINAL_TYPE (MetaBarrierImplNative, - meta_barrier_impl_native, - META, BARRIER_IMPL_NATIVE, - MetaBarrierImpl) - -typedef struct _MetaBarrierManagerNative MetaBarrierManagerNative; - - -MetaBarrierImpl *meta_barrier_impl_native_new (MetaBarrier *barrier); - -MetaBarrierManagerNative *meta_barrier_manager_native_new (void); -void meta_barrier_manager_native_process_in_impl (MetaBarrierManagerNative *manager, - ClutterInputDevice *device, - guint32 time, - float *x, - float *y); - -G_END_DECLS - -#endif /* META_BARRIER_NATIVE_H */ diff --git a/src/backends/native/meta-clutter-backend-native.c b/src/backends/native/meta-clutter-backend-native.c deleted file mode 100644 index a28ecea99..000000000 --- a/src/backends/native/meta-clutter-backend-native.c +++ /dev/null @@ -1,111 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -/** - * SECTION:meta-clutter-backend-native - * @title: MetaClutterBackendNatve - * @short_description: A native backend which renders using EGL. - * - * MetaClutterBackendNative is the #ClutterBackend which is used by the native - * (as opposed to the X) backend. It creates a stage with #MetaStageNative and - * renders using the #CoglRenderer. - * - * Note that MetaClutterBackendNative is something different than a - * #MetaBackendNative. The former is a #ClutterBackend implementation, while - * the latter is a #MetaBackend implementation. - */ - -#include "config.h" - -#include "backends/native/meta-clutter-backend-native.h" - -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-renderer.h" -#include "backends/native/meta-backend-native.h" -#include "backends/native/meta-seat-native.h" -#include "backends/native/meta-stage-native.h" -#include "clutter/clutter.h" -#include "core/bell.h" -#include "meta/meta-backend.h" - -struct _MetaClutterBackendNative -{ - ClutterBackend parent; -}; - -G_DEFINE_TYPE (MetaClutterBackendNative, meta_clutter_backend_native, - CLUTTER_TYPE_BACKEND) - -static CoglRenderer * -meta_clutter_backend_native_get_renderer (ClutterBackend *clutter_backend, - GError **error) -{ - MetaBackend *backend = meta_get_backend (); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - - return meta_renderer_create_cogl_renderer (renderer); -} - -static ClutterStageWindow * -meta_clutter_backend_native_create_stage (ClutterBackend *clutter_backend, - ClutterStage *wrapper, - GError **error) -{ - return g_object_new (META_TYPE_STAGE_NATIVE, - "backend", clutter_backend, - "wrapper", wrapper, - NULL); -} - -static ClutterSeat * -meta_clutter_backend_native_get_default_seat (ClutterBackend *clutter_backend) -{ - MetaBackend *backend = meta_get_backend (); - - return meta_backend_get_default_seat (backend); -} - -static gboolean -meta_clutter_backend_native_is_display_server (ClutterBackend *clutter_backend) -{ - return TRUE; -} - -static void -meta_clutter_backend_native_init (MetaClutterBackendNative *clutter_backend_nativen) -{ -} - -static void -meta_clutter_backend_native_class_init (MetaClutterBackendNativeClass *klass) -{ - ClutterBackendClass *clutter_backend_class = CLUTTER_BACKEND_CLASS (klass); - - clutter_backend_class->get_renderer = meta_clutter_backend_native_get_renderer; - clutter_backend_class->create_stage = meta_clutter_backend_native_create_stage; - clutter_backend_class->get_default_seat = meta_clutter_backend_native_get_default_seat; - clutter_backend_class->is_display_server = meta_clutter_backend_native_is_display_server; -} diff --git a/src/backends/native/meta-clutter-backend-native.h b/src/backends/native/meta-clutter-backend-native.h deleted file mode 100644 index dea35988c..000000000 --- a/src/backends/native/meta-clutter-backend-native.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#ifndef META_CLUTTER_BACKEND_NATIVE_H -#define META_CLUTTER_BACKEND_NATIVE_H - -#include - -#include "backends/native/meta-stage-native.h" -#include "clutter/clutter.h" - -#define META_TYPE_CLUTTER_BACKEND_NATIVE (meta_clutter_backend_native_get_type ()) -G_DECLARE_FINAL_TYPE (MetaClutterBackendNative, meta_clutter_backend_native, - META, CLUTTER_BACKEND_NATIVE, - ClutterBackend) - -#endif /* META_CLUTTER_BACKEND_NATIVE_H */ diff --git a/src/backends/native/meta-cogl-utils.c b/src/backends/native/meta-cogl-utils.c deleted file mode 100644 index 582f86661..000000000 --- a/src/backends/native/meta-cogl-utils.c +++ /dev/null @@ -1,85 +0,0 @@ -/* meta-cogl-utils.c - * - * Copyright 2020 Georges Basile Stavracas Neto - * - * 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. - * - * SPDX-License-Identifier: GPL-2.0-or-later - * - */ - -#include "backends/native/meta-cogl-utils.h" - -#include - -typedef struct _PixelFormatMap { - uint32_t drm_format; - CoglPixelFormat cogl_format; - CoglTextureComponents cogl_components; -} PixelFormatMap; - -static const PixelFormatMap pixel_format_map[] = { -/* DRM formats are defined as little-endian, not machine endian. */ -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - { DRM_FORMAT_RGB565, COGL_PIXEL_FORMAT_RGB_565, COGL_TEXTURE_COMPONENTS_RGB }, - { DRM_FORMAT_ABGR8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_XBGR8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB }, - { DRM_FORMAT_ARGB8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_XRGB8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB }, - { DRM_FORMAT_BGRA8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_BGRX8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB }, - { DRM_FORMAT_RGBA8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_RGBX8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB }, -#elif G_BYTE_ORDER == G_BIG_ENDIAN - /* DRM_FORMAT_RGB565 cannot be expressed. */ - { DRM_FORMAT_ABGR8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_XBGR8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB }, - { DRM_FORMAT_ARGB8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_XRGB8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB }, - { DRM_FORMAT_BGRA8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_BGRX8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB }, - { DRM_FORMAT_RGBA8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA }, - { DRM_FORMAT_RGBX8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB }, -#else -#error "unexpected G_BYTE_ORDER" -#endif -}; - -gboolean -meta_cogl_pixel_format_from_drm_format (uint32_t drm_format, - CoglPixelFormat *out_format, - CoglTextureComponents *out_components) -{ - const size_t n = G_N_ELEMENTS (pixel_format_map); - size_t i; - - for (i = 0; i < n; i++) - { - if (pixel_format_map[i].drm_format == drm_format) - break; - } - - if (i == n) - return FALSE; - - if (out_format) - *out_format = pixel_format_map[i].cogl_format; - - if (out_components) - *out_components = pixel_format_map[i].cogl_components; - - return TRUE; -} diff --git a/src/backends/native/meta-cogl-utils.h b/src/backends/native/meta-cogl-utils.h deleted file mode 100644 index b5fe6296f..000000000 --- a/src/backends/native/meta-cogl-utils.h +++ /dev/null @@ -1,38 +0,0 @@ -/* meta-cogl-utils.h - * - * Copyright 2020 Georges Basile Stavracas Neto - * - * 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. - * - * SPDX-License-Identifier: GPL-2.0-or-later - * - */ - -#ifndef META_COGL_UTILS_H -#define META_COGL_UTILS_H - -#include "cogl/cogl.h" - -G_BEGIN_DECLS - -gboolean -meta_cogl_pixel_format_from_drm_format (uint32_t drm_format, - CoglPixelFormat *out_format, - CoglTextureComponents *out_components); - -G_END_DECLS - -#endif /* META_COGL_UTILS_H */ diff --git a/src/backends/native/meta-crtc-kms.c b/src/backends/native/meta-crtc-kms.c deleted file mode 100644 index f1bc79146..000000000 --- a/src/backends/native/meta-crtc-kms.c +++ /dev/null @@ -1,386 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2013-2017 Red Hat - * Copyright (C) 2018 DisplayLink (UK) Ltd. - * - * 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 "backends/native/meta-crtc-kms.h" - -#include "backends/meta-backend-private.h" -#include "backends/meta-logical-monitor.h" -#include "backends/native/meta-crtc-mode-kms.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-mode.h" -#include "backends/native/meta-kms-plane.h" -#include "backends/native/meta-kms-update.h" -#include "backends/native/meta-kms.h" -#include "backends/native/meta-monitor-manager-native.h" - -#define ALL_TRANSFORMS_MASK ((1 << META_MONITOR_N_TRANSFORMS) - 1) - -struct _MetaCrtcKms -{ - MetaCrtcNative parent; - - MetaKmsCrtc *kms_crtc; - - MetaKmsPlane *primary_plane; - - gpointer cursor_renderer_private; - GDestroyNotify cursor_renderer_private_destroy_notify; - - gboolean is_gamma_valid; -}; - -static GQuark kms_crtc_crtc_kms_quark; - -G_DEFINE_TYPE (MetaCrtcKms, meta_crtc_kms, META_TYPE_CRTC_NATIVE) - -gpointer -meta_crtc_kms_get_cursor_renderer_private (MetaCrtcKms *crtc_kms) -{ - return crtc_kms->cursor_renderer_private; -} - -void -meta_crtc_kms_set_cursor_renderer_private (MetaCrtcKms *crtc_kms, - gpointer cursor_renderer_private, - GDestroyNotify destroy_notify) -{ - g_clear_pointer (&crtc_kms->cursor_renderer_private, - crtc_kms->cursor_renderer_private_destroy_notify); - - crtc_kms->cursor_renderer_private = cursor_renderer_private; - crtc_kms->cursor_renderer_private_destroy_notify = destroy_notify; -} - -static gboolean -is_transform_handled (MetaCrtcKms *crtc_kms, - MetaMonitorTransform transform) -{ - if (!crtc_kms->primary_plane) - return FALSE; - - return meta_kms_plane_is_transform_handled (crtc_kms->primary_plane, - transform); -} - -static gboolean -meta_crtc_kms_is_transform_handled (MetaCrtcNative *crtc_native, - MetaMonitorTransform transform) -{ - MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc_native); - - return is_transform_handled (crtc_kms, transform); -} - -void -meta_crtc_kms_apply_transform (MetaCrtcKms *crtc_kms, - MetaKmsPlaneAssignment *kms_plane_assignment) -{ - MetaCrtc *crtc = META_CRTC (crtc_kms); - const MetaCrtcConfig *crtc_config; - MetaMonitorTransform hw_transform; - - crtc_config = meta_crtc_get_config (crtc); - - hw_transform = crtc_config->transform; - if (!is_transform_handled (crtc_kms, hw_transform)) - hw_transform = META_MONITOR_TRANSFORM_NORMAL; - if (!is_transform_handled (crtc_kms, hw_transform)) - return; - - meta_kms_plane_update_set_rotation (crtc_kms->primary_plane, - kms_plane_assignment, - hw_transform); -} - -void -meta_crtc_kms_assign_primary_plane (MetaCrtcKms *crtc_kms, - MetaDrmBuffer *buffer, - MetaKmsUpdate *kms_update) -{ - MetaCrtc *crtc = META_CRTC (crtc_kms); - const MetaCrtcConfig *crtc_config; - const MetaCrtcModeInfo *crtc_mode_info; - MetaFixed16Rectangle src_rect; - MetaRectangle dst_rect; - MetaKmsAssignPlaneFlag flags; - MetaKmsCrtc *kms_crtc; - MetaKmsDevice *kms_device; - MetaKmsPlane *primary_kms_plane; - MetaKmsPlaneAssignment *plane_assignment; - - crtc_config = meta_crtc_get_config (crtc); - crtc_mode_info = meta_crtc_mode_get_info (crtc_config->mode); - - src_rect = (MetaFixed16Rectangle) { - .x = meta_fixed_16_from_int (0), - .y = meta_fixed_16_from_int (0), - .width = meta_fixed_16_from_int (crtc_mode_info->width), - .height = meta_fixed_16_from_int (crtc_mode_info->height), - }; - dst_rect = (MetaRectangle) { - .x = 0, - .y = 0, - .width = crtc_mode_info->width, - .height = crtc_mode_info->height, - }; - - flags = META_KMS_ASSIGN_PLANE_FLAG_NONE; - - kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); - 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, - buffer, - src_rect, - dst_rect, - flags); - meta_crtc_kms_apply_transform (crtc_kms, 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) - { - MetaOutput *output = l->data; - MetaCrtc *assigned_crtc; - - assigned_crtc = meta_output_get_assigned_crtc (output); - if (assigned_crtc == crtc) - { - MetaKmsConnector *kms_connector = - meta_output_kms_get_kms_connector (META_OUTPUT_KMS (output)); - - connectors = g_list_prepend (connectors, kms_connector); - } - } - - return connectors; -} - -void -meta_crtc_kms_maybe_set_gamma (MetaCrtcKms *crtc_kms, - MetaKmsDevice *kms_device) -{ - MetaGpu *gpu = meta_crtc_get_gpu (META_CRTC (crtc_kms)); - MetaBackend *backend = meta_gpu_get_backend (gpu); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerNative *monitor_manager_native = - META_MONITOR_MANAGER_NATIVE (monitor_manager); - MetaKms *kms = meta_kms_device_get_kms (kms_device); - MetaKmsUpdate *kms_update; - MetaKmsCrtcGamma *gamma; - - if (crtc_kms->is_gamma_valid) - return; - - gamma = meta_monitor_manager_native_get_cached_crtc_gamma (monitor_manager_native, - crtc_kms); - if (!gamma) - return; - - kms_update = meta_kms_ensure_pending_update (kms, kms_device); - meta_kms_update_set_crtc_gamma (kms_update, - meta_crtc_kms_get_kms_crtc (crtc_kms), - gamma->size, - gamma->red, - gamma->green, - gamma->blue); - - crtc_kms->is_gamma_valid = TRUE; -} - -void -meta_crtc_kms_set_mode (MetaCrtcKms *crtc_kms, - MetaKmsUpdate *kms_update) -{ - MetaCrtc *crtc = META_CRTC (crtc_kms); - MetaGpu *gpu = meta_crtc_get_gpu (crtc); - GList *connectors; - MetaKmsMode *kms_mode; - - connectors = generate_crtc_connector_list (gpu, crtc); - - if (connectors) - { - const MetaCrtcConfig *crtc_config = meta_crtc_get_config (crtc); - MetaCrtcModeKms *crtc_mode_kms = META_CRTC_MODE_KMS (crtc_config->mode); - - kms_mode = meta_crtc_mode_kms_get_kms_mode (crtc_mode_kms); - - meta_topic (META_DEBUG_KMS, - "Setting CRTC (%" G_GUINT64_FORMAT ") mode to %s", - meta_crtc_get_id (crtc), meta_kms_mode_get_name (kms_mode)); - } - else - { - kms_mode = NULL; - - meta_topic (META_DEBUG_KMS, - "Unsetting CRTC (%" G_GUINT64_FORMAT ") mode", - meta_crtc_get_id (crtc)); - } - - meta_kms_update_mode_set (kms_update, - meta_crtc_kms_get_kms_crtc (crtc_kms), - g_steal_pointer (&connectors), - kms_mode); -} - -MetaKmsCrtc * -meta_crtc_kms_get_kms_crtc (MetaCrtcKms *crtc_kms) -{ - return crtc_kms->kms_crtc; -} - -/** - * meta_crtc_kms_get_modifiers: - * @crtc_kms: a #MetaCrtc object that has to be a #MetaCrtcKms - * @format: a DRM pixel format - * - * Returns a pointer to a #GArray containing all the supported - * modifiers for the given DRM pixel format on the CRTC's primary - * plane. The array element type is uint64_t. - * - * The caller must not modify or destroy the array or its contents. - * - * Returns NULL if the modifiers are not known or the format is not - * supported. - */ -GArray * -meta_crtc_kms_get_modifiers (MetaCrtcKms *crtc_kms, - uint32_t format) -{ - return meta_kms_plane_get_modifiers_for_format (crtc_kms->primary_plane, - format); -} - -/** - * meta_crtc_kms_copy_drm_format_list: - * @crtc_kms: a #MetaCrtc object that has to be a #MetaCrtcKms - * - * Returns a new #GArray that the caller must destroy. The array - * contains all the DRM pixel formats the CRTC supports on - * its primary plane. The array element type is uint32_t. - */ -GArray * -meta_crtc_kms_copy_drm_format_list (MetaCrtcKms *crtc_kms) -{ - return meta_kms_plane_copy_drm_format_list (crtc_kms->primary_plane); -} - -/** - * meta_crtc_kms_supports_format: - * @crtc_kms: a #MetaCrtcKms - * @drm_format: a DRM pixel format - * - * Returns true if the CRTC supports the format on its primary plane. - */ -gboolean -meta_crtc_kms_supports_format (MetaCrtcKms *crtc_kms, - uint32_t drm_format) -{ - return meta_kms_plane_is_format_supported (crtc_kms->primary_plane, - drm_format); -} - -void -meta_crtc_kms_invalidate_gamma (MetaCrtcKms *crtc_kms) -{ - crtc_kms->is_gamma_valid = FALSE; -} - -MetaCrtcKms * -meta_crtc_kms_from_kms_crtc (MetaKmsCrtc *kms_crtc) -{ - return g_object_get_qdata (G_OBJECT (kms_crtc), kms_crtc_crtc_kms_quark); -} - -MetaCrtcKms * -meta_crtc_kms_new (MetaGpuKms *gpu_kms, - MetaKmsCrtc *kms_crtc) -{ - MetaGpu *gpu = META_GPU (gpu_kms); - MetaKmsDevice *kms_device; - MetaCrtcKms *crtc_kms; - MetaKmsPlane *primary_plane; - - kms_device = meta_gpu_kms_get_kms_device (gpu_kms); - primary_plane = meta_kms_device_get_primary_plane_for (kms_device, - kms_crtc); - crtc_kms = g_object_new (META_TYPE_CRTC_KMS, - "id", (uint64_t) meta_kms_crtc_get_id (kms_crtc), - "gpu", gpu, - NULL); - - crtc_kms->kms_crtc = kms_crtc; - crtc_kms->primary_plane = primary_plane; - - 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_kms); - - return crtc_kms; -} - -static void -meta_crtc_kms_dispose (GObject *object) -{ - MetaCrtcKms *crtc_kms = META_CRTC_KMS (object); - - g_clear_pointer (&crtc_kms->cursor_renderer_private, - crtc_kms->cursor_renderer_private_destroy_notify); - - G_OBJECT_CLASS (meta_crtc_kms_parent_class)->dispose (object); -} - -static void -meta_crtc_kms_init (MetaCrtcKms *crtc_kms) -{ -} - -static void -meta_crtc_kms_class_init (MetaCrtcKmsClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaCrtcNativeClass *crtc_native_class = META_CRTC_NATIVE_CLASS (klass); - - object_class->dispose = meta_crtc_kms_dispose; - - crtc_native_class->is_transform_handled = meta_crtc_kms_is_transform_handled; -} diff --git a/src/backends/native/meta-crtc-kms.h b/src/backends/native/meta-crtc-kms.h deleted file mode 100644 index f8d241bbb..000000000 --- a/src/backends/native/meta-crtc-kms.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 Red Hat - * Copyright (C) 2018 DisplayLink (UK) Ltd. - * - * 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_CRTC_KMS_H -#define META_CRTC_KMS_H - -#include -#include - -#include "backends/meta-backend-types.h" -#include "backends/meta-crtc.h" -#include "backends/native/meta-crtc-native.h" -#include "backends/native/meta-drm-buffer.h" -#include "backends/native/meta-gpu-kms.h" -#include "backends/native/meta-kms-crtc.h" -#include "backends/native/meta-kms-update.h" - -#define META_TYPE_CRTC_KMS (meta_crtc_kms_get_type ()) -G_DECLARE_FINAL_TYPE (MetaCrtcKms, meta_crtc_kms, - META, CRTC_KMS, - MetaCrtcNative) - -gpointer meta_crtc_kms_get_cursor_renderer_private (MetaCrtcKms *crtc_kms); - -void meta_crtc_kms_set_cursor_renderer_private (MetaCrtcKms *crtc_kms, - gpointer cursor_renderer_private, - GDestroyNotify destroy_notify); - -void meta_crtc_kms_apply_transform (MetaCrtcKms *crtc_kms, - MetaKmsPlaneAssignment *kms_plane_assignment); - -void meta_crtc_kms_assign_primary_plane (MetaCrtcKms *crtc_kms, - MetaDrmBuffer *buffer, - MetaKmsUpdate *kms_update); - -void meta_crtc_kms_set_mode (MetaCrtcKms *crtc_kms, - MetaKmsUpdate *kms_update); - -void meta_crtc_kms_set_is_underscanning (MetaCrtcKms *crtc_kms, - gboolean is_underscanning); - -MetaKmsCrtc * meta_crtc_kms_get_kms_crtc (MetaCrtcKms *crtc_kms); - -GArray * meta_crtc_kms_get_modifiers (MetaCrtcKms *crtc_kms, - uint32_t format); - -GArray * -meta_crtc_kms_copy_drm_format_list (MetaCrtcKms *crtc_kms); - -gboolean -meta_crtc_kms_supports_format (MetaCrtcKms *crtc_kms, - uint32_t drm_format); - -void meta_crtc_kms_invalidate_gamma (MetaCrtcKms *crtc_kms); - -void meta_crtc_kms_maybe_set_gamma (MetaCrtcKms *crtc_kms, - MetaKmsDevice *kms_device); - -MetaCrtcKms * meta_crtc_kms_from_kms_crtc (MetaKmsCrtc *kms_crtc); - -MetaCrtcKms * meta_crtc_kms_new (MetaGpuKms *gpu_kms, - MetaKmsCrtc *kms_crtc); - -#endif /* META_CRTC_KMS_H */ diff --git a/src/backends/native/meta-crtc-mode-kms.c b/src/backends/native/meta-crtc-mode-kms.c deleted file mode 100644 index 053367cfd..000000000 --- a/src/backends/native/meta-crtc-mode-kms.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2017-2020 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. - */ - -#include "config.h" - -#include "backends/native/meta-crtc-mode-kms.h" - -#include "backends/native/meta-kms-mode.h" -#include "backends/native/meta-kms-utils.h" - -struct _MetaCrtcModeKms -{ - MetaCrtcMode parent; - - MetaKmsMode *kms_mode; -}; - -G_DEFINE_TYPE (MetaCrtcModeKms, meta_crtc_mode_kms, - META_TYPE_CRTC_MODE) - -MetaKmsMode * -meta_crtc_mode_kms_get_kms_mode (MetaCrtcModeKms *mode_kms) -{ - return mode_kms->kms_mode; -} - -MetaCrtcModeKms * -meta_crtc_mode_kms_new (MetaKmsMode *kms_mode, - uint64_t id) -{ - const drmModeModeInfo *drm_mode = meta_kms_mode_get_drm_mode (kms_mode); - g_autoptr (MetaCrtcModeInfo) crtc_mode_info = NULL; - g_autofree char *crtc_mode_name = NULL; - MetaCrtcModeKms *mode_kms; - - crtc_mode_info = meta_crtc_mode_info_new (); - crtc_mode_info->width = drm_mode->hdisplay; - crtc_mode_info->height = drm_mode->vdisplay; - crtc_mode_info->flags = drm_mode->flags; - crtc_mode_info->refresh_rate = - meta_calculate_drm_mode_refresh_rate (drm_mode); - crtc_mode_info->vblank_duration_us = - meta_calculate_drm_mode_vblank_duration_us (drm_mode); - - crtc_mode_name = g_strndup (drm_mode->name, DRM_DISPLAY_MODE_LEN); - mode_kms = g_object_new (META_TYPE_CRTC_MODE_KMS, - "id", id, - "name", crtc_mode_name, - "info", crtc_mode_info, - NULL); - - mode_kms->kms_mode = kms_mode; - - return mode_kms; -} - -static void -meta_crtc_mode_kms_init (MetaCrtcModeKms *mode_kms) -{ -} - -static void -meta_crtc_mode_kms_class_init (MetaCrtcModeKmsClass *klass) -{ -} diff --git a/src/backends/native/meta-crtc-mode-kms.h b/src/backends/native/meta-crtc-mode-kms.h deleted file mode 100644 index f39268612..000000000 --- a/src/backends/native/meta-crtc-mode-kms.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2017-2020 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_CRTC_MODE_KMS_H -#define META_CRTC_MODE_KMS_H - -#include -#include - -#include "backends/meta-crtc-mode.h" -#include "backends/native/meta-kms-types.h" - -#define META_TYPE_CRTC_MODE_KMS (meta_crtc_mode_kms_get_type ()) -G_DECLARE_FINAL_TYPE (MetaCrtcModeKms, meta_crtc_mode_kms, - META, CRTC_MODE_KMS, - MetaCrtcMode) - -MetaKmsMode * meta_crtc_mode_kms_get_kms_mode (MetaCrtcModeKms *mode_kms); - -MetaCrtcModeKms * meta_crtc_mode_kms_new (MetaKmsMode *kms_mode, - uint64_t id); - -#endif /* META_CRTC_MODE_KMS_H */ diff --git a/src/backends/native/meta-crtc-mode-virtual.c b/src/backends/native/meta-crtc-mode-virtual.c deleted file mode 100644 index 3bb883049..000000000 --- a/src/backends/native/meta-crtc-mode-virtual.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2021 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. - */ - -#include "config.h" - -#include "backends/native/meta-crtc-mode-virtual.h" - -#include "backends/meta-virtual-monitor.h" - -struct _MetaCrtcModeVirtual -{ - MetaCrtcMode parent; -}; - -#define META_CRTC_MODE_VIRTUAL_ID_BIT (((uint64_t) 1) << 63) - -G_DEFINE_TYPE (MetaCrtcModeVirtual, meta_crtc_mode_virtual, - META_TYPE_CRTC_MODE) - -MetaCrtcModeVirtual * -meta_crtc_mode_virtual_new (uint64_t id, - const MetaVirtualMonitorInfo *info) -{ - g_autoptr (MetaCrtcModeInfo) crtc_mode_info = NULL; - g_autofree char *crtc_mode_name = NULL; - MetaCrtcModeVirtual *mode_virtual; - - crtc_mode_info = meta_crtc_mode_info_new (); - crtc_mode_info->width = info->width; - crtc_mode_info->height = info->height; - crtc_mode_info->refresh_rate = info->refresh_rate; - - crtc_mode_name = g_strdup_printf ("%dx%d@%f", - info->width, - info->height, - info->refresh_rate); - mode_virtual = g_object_new (META_TYPE_CRTC_MODE_VIRTUAL, - "id", META_CRTC_MODE_VIRTUAL_ID_BIT | id, - "name", crtc_mode_name, - "info", crtc_mode_info, - NULL); - - return mode_virtual; -} - -static void -meta_crtc_mode_virtual_init (MetaCrtcModeVirtual *mode_virtual) -{ -} - -static void -meta_crtc_mode_virtual_class_init (MetaCrtcModeVirtualClass *klass) -{ -} diff --git a/src/backends/native/meta-crtc-mode-virtual.h b/src/backends/native/meta-crtc-mode-virtual.h deleted file mode 100644 index e3ddb289c..000000000 --- a/src/backends/native/meta-crtc-mode-virtual.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2021 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_CRTC_MODE_VIRTUAL_H -#define META_CRTC_MODE_VIRTUAL_H - -#include "backends/meta-backend-types.h" -#include "backends/meta-crtc-mode.h" - -#define META_TYPE_CRTC_MODE_VIRTUAL (meta_crtc_mode_virtual_get_type ()) -G_DECLARE_FINAL_TYPE (MetaCrtcModeVirtual, meta_crtc_mode_virtual, - META, CRTC_MODE_VIRTUAL, - MetaCrtcMode) - -MetaCrtcModeVirtual * meta_crtc_mode_virtual_new (uint64_t id, - const MetaVirtualMonitorInfo *info); - -#endif /* META_CRTC_MODE_VIRTUAL_H */ diff --git a/src/backends/native/meta-crtc-native.c b/src/backends/native/meta-crtc-native.c deleted file mode 100644 index 5e5751780..000000000 --- a/src/backends/native/meta-crtc-native.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2021 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. - */ - -#include "config.h" - -#include "backends/native/meta-crtc-native.h" - -G_DEFINE_ABSTRACT_TYPE (MetaCrtcNative, meta_crtc_native, - META_TYPE_CRTC) - -gboolean -meta_crtc_native_is_transform_handled (MetaCrtcNative *crtc_native, - MetaMonitorTransform transform) -{ - MetaCrtcNativeClass *klass = META_CRTC_NATIVE_GET_CLASS (crtc_native); - - return klass->is_transform_handled (crtc_native, transform); -} - -static void -meta_crtc_native_init (MetaCrtcNative *crtc_native) -{ -} - -static void -meta_crtc_native_class_init (MetaCrtcNativeClass *klass) -{ -} diff --git a/src/backends/native/meta-crtc-native.h b/src/backends/native/meta-crtc-native.h deleted file mode 100644 index 0c16e5895..000000000 --- a/src/backends/native/meta-crtc-native.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2021 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_CRTC_NATIVE_H -#define META_CRTC_NATIVE_H - -#include "backends/meta-crtc.h" - -#define META_TYPE_CRTC_NATIVE (meta_crtc_native_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaCrtcNative, meta_crtc_native, - META, CRTC_NATIVE, - MetaCrtc) - -struct _MetaCrtcNativeClass -{ - MetaCrtcClass parent_class; - - gboolean (* is_transform_handled) (MetaCrtcNative *crtc_native, - MetaMonitorTransform monitor_transform); -}; - -gboolean meta_crtc_native_is_transform_handled (MetaCrtcNative *crtc_native, - MetaMonitorTransform transform); - -#endif /* META_CRTC_NATIVE_H */ diff --git a/src/backends/native/meta-crtc-virtual.c b/src/backends/native/meta-crtc-virtual.c deleted file mode 100644 index eee346a23..000000000 --- a/src/backends/native/meta-crtc-virtual.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2021 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. - */ - -#include "config.h" - -#include "backends/native/meta-crtc-virtual.h" - -struct _MetaCrtcVirtual -{ - MetaCrtcNative parent; -}; - -#define META_CRTC_VIRTUAL_ID_BIT (((uint64_t) 1) << 63) - -G_DEFINE_TYPE (MetaCrtcVirtual, meta_crtc_virtual, META_TYPE_CRTC_NATIVE) - -MetaCrtcVirtual * -meta_crtc_virtual_new (uint64_t id) -{ - return g_object_new (META_TYPE_CRTC_VIRTUAL, - "id", META_CRTC_VIRTUAL_ID_BIT | id, - NULL); -} - -static gboolean -meta_crtc_virtual_is_transform_handled (MetaCrtcNative *crtc_native, - MetaMonitorTransform transform) -{ - return transform == META_MONITOR_TRANSFORM_NORMAL; -} - -static void -meta_crtc_virtual_init (MetaCrtcVirtual *crtc_virtual) -{ -} - -static void -meta_crtc_virtual_class_init (MetaCrtcVirtualClass *klass) -{ - MetaCrtcNativeClass *crtc_native_class = META_CRTC_NATIVE_CLASS (klass); - - crtc_native_class->is_transform_handled = - meta_crtc_virtual_is_transform_handled; -} diff --git a/src/backends/native/meta-crtc-virtual.h b/src/backends/native/meta-crtc-virtual.h deleted file mode 100644 index 89b1bcc7a..000000000 --- a/src/backends/native/meta-crtc-virtual.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2021 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_CRTC_VIRTUAL_H -#define META_CRTC_VIRTUAL_H - -#include "backends/native/meta-crtc-native.h" - -#define META_TYPE_CRTC_VIRTUAL (meta_crtc_virtual_get_type ()) -G_DECLARE_FINAL_TYPE (MetaCrtcVirtual, meta_crtc_virtual, - META, CRTC_VIRTUAL, - MetaCrtcNative) - -MetaCrtcVirtual * meta_crtc_virtual_new (uint64_t id); - -#endif /* META_CRTC_VIRTUAL_H */ diff --git a/src/backends/native/meta-cursor-renderer-native.c b/src/backends/native/meta-cursor-renderer-native.c deleted file mode 100644 index effa0851d..000000000 --- a/src/backends/native/meta-cursor-renderer-native.c +++ /dev/null @@ -1,1878 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Red Hat - * Copyright 2020 DisplayLink (UK) Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -#include "config.h" - -#include "backends/native/meta-cursor-renderer-native.h" - -#include -#include -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-cursor-sprite-xcursor.h" -#include "backends/meta-logical-monitor.h" -#include "backends/meta-monitor.h" -#include "backends/meta-monitor-manager-private.h" -#include "backends/meta-output.h" -#include "backends/native/meta-backend-native-private.h" -#include "backends/native/meta-crtc-kms.h" -#include "backends/native/meta-device-pool.h" -#include "backends/native/meta-drm-buffer-gbm.h" -#include "backends/native/meta-kms-device.h" -#include "backends/native/meta-kms-plane.h" -#include "backends/native/meta-kms-update.h" -#include "backends/native/meta-kms.h" -#include "backends/native/meta-renderer-native.h" -#include "core/boxes-private.h" -#include "meta/boxes.h" -#include "meta/meta-backend.h" -#include "meta/util.h" - -#ifdef HAVE_WAYLAND -#include "wayland/meta-cursor-sprite-wayland.h" -#include "wayland/meta-wayland-buffer.h" -#endif - -#ifndef DRM_CAP_CURSOR_WIDTH -#define DRM_CAP_CURSOR_WIDTH 0x8 -#endif -#ifndef DRM_CAP_CURSOR_HEIGHT -#define DRM_CAP_CURSOR_HEIGHT 0x9 -#endif - -/* When animating a cursor, we usually call drmModeSetCursor2 once per frame. - * Though, testing shows that we need to triple buffer the cursor buffer in - * order to avoid glitches when animating the cursor, at least when running on - * Intel. The reason for this might be (but is not confirmed to be) due to - * the user space gbm_bo cache, making us reuse and overwrite the kernel side - * buffer content before it was scanned out. To avoid this, we keep a user space - * reference to each buffer we set until at least one frame after it was drawn. - * In effect, this means we three active cursor gbm_bo's: one that that just has - * been set, one that was previously set and may or may not have been scanned - * out, and one pending that will be replaced if the cursor sprite changes. - */ -#define HW_CURSOR_BUFFER_COUNT 3 - -static GQuark quark_cursor_sprite = 0; - -typedef struct _CrtcCursorData -{ - MetaDrmBuffer *buffer; - gboolean needs_sync_position; - gboolean hw_state_invalidated; -} CrtcCursorData; - -struct _MetaCursorRendererNative -{ - MetaCursorRenderer parent; -}; - -struct _MetaCursorRendererNativePrivate -{ - MetaBackend *backend; - - gboolean has_hw_cursor; - - MetaCursorSprite *last_cursor; - guint animation_timeout_id; -}; -typedef struct _MetaCursorRendererNativePrivate MetaCursorRendererNativePrivate; - -typedef struct _MetaCursorRendererNativeGpuData -{ - gboolean hw_cursor_broken; - - uint64_t cursor_width; - uint64_t cursor_height; -} MetaCursorRendererNativeGpuData; - -typedef enum _MetaCursorBufferState -{ - META_CURSOR_BUFFER_STATE_NONE, - META_CURSOR_BUFFER_STATE_SET, - META_CURSOR_BUFFER_STATE_INVALIDATED, -} MetaCursorBufferState; - -typedef struct _MetaCursorNativeGpuState -{ - MetaGpu *gpu; - unsigned int active_buffer_idx; - MetaCursorBufferState pending_buffer_state; - MetaDrmBuffer *buffers[HW_CURSOR_BUFFER_COUNT]; -} MetaCursorNativeGpuState; - -typedef struct _MetaCursorNativePrivate -{ - GHashTable *gpu_states; - - struct { - gboolean can_preprocess; - float current_relative_scale; - MetaMonitorTransform current_relative_transform; - } preprocess_state; -} MetaCursorNativePrivate; - -static GQuark quark_cursor_renderer_native_gpu_data = 0; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererNative, meta_cursor_renderer_native, META_TYPE_CURSOR_RENDERER); - -static void -on_kms_update_result (const MetaKmsFeedback *kms_feedback, - gpointer user_data); - -static void -realize_cursor_sprite (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite, - GList *gpus); - -static MetaCursorNativeGpuState * -get_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv, - MetaGpuKms *gpu_kms); - -static MetaCursorNativeGpuState * -ensure_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv, - MetaGpuKms *gpu_kms); - -static void -invalidate_cursor_gpu_state (MetaCursorSprite *cursor_sprite); - -static MetaCursorNativePrivate * -ensure_cursor_priv (MetaCursorSprite *cursor_sprite); - -static MetaCursorNativePrivate * -get_cursor_priv (MetaCursorSprite *cursor_sprite); - -static MetaCursorRendererNativeGpuData * -meta_cursor_renderer_native_gpu_data_from_gpu (MetaGpuKms *gpu_kms) -{ - return g_object_get_qdata (G_OBJECT (gpu_kms), - quark_cursor_renderer_native_gpu_data); -} - -static MetaCursorRendererNativeGpuData * -meta_create_cursor_renderer_native_gpu_data (MetaGpuKms *gpu_kms) -{ - MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data; - - cursor_renderer_gpu_data = g_new0 (MetaCursorRendererNativeGpuData, 1); - g_object_set_qdata_full (G_OBJECT (gpu_kms), - quark_cursor_renderer_native_gpu_data, - cursor_renderer_gpu_data, - g_free); - - return cursor_renderer_gpu_data; -} - -static void -meta_cursor_renderer_native_finalize (GObject *object) -{ - MetaCursorRendererNative *renderer = META_CURSOR_RENDERER_NATIVE (object); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (renderer); - - g_clear_handle_id (&priv->animation_timeout_id, g_source_remove); - - G_OBJECT_CLASS (meta_cursor_renderer_native_parent_class)->finalize (object); -} - -static unsigned int -get_pending_cursor_sprite_buffer_index (MetaCursorNativeGpuState *cursor_gpu_state) -{ - return (cursor_gpu_state->active_buffer_idx + 1) % HW_CURSOR_BUFFER_COUNT; -} - -static MetaDrmBuffer * -get_pending_cursor_sprite_buffer (MetaCursorNativeGpuState *cursor_gpu_state) -{ - unsigned int pending_buffer_idx; - - pending_buffer_idx = - get_pending_cursor_sprite_buffer_index (cursor_gpu_state); - return cursor_gpu_state->buffers[pending_buffer_idx]; -} - -static MetaDrmBuffer * -get_active_cursor_sprite_buffer (MetaCursorNativeGpuState *cursor_gpu_state) -{ - return cursor_gpu_state->buffers[cursor_gpu_state->active_buffer_idx]; -} - -static void -set_pending_cursor_sprite_buffer (MetaCursorSprite *cursor_sprite, - MetaGpuKms *gpu_kms, - MetaDrmBuffer *buffer) -{ - MetaCursorNativePrivate *cursor_priv; - MetaCursorNativeGpuState *cursor_gpu_state; - unsigned int pending_buffer_idx; - - cursor_priv = ensure_cursor_priv (cursor_sprite); - cursor_gpu_state = ensure_cursor_gpu_state (cursor_priv, gpu_kms); - - pending_buffer_idx = - get_pending_cursor_sprite_buffer_index (cursor_gpu_state); - cursor_gpu_state->buffers[pending_buffer_idx] = buffer; - cursor_gpu_state->pending_buffer_state = META_CURSOR_BUFFER_STATE_SET; -} - -static void -calculate_crtc_cursor_hotspot (MetaCursorSprite *cursor_sprite, - int *cursor_hotspot_x, - int *cursor_hotspot_y) -{ - MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite); - int hot_x, hot_y; - int width, height; - float scale; - MetaMonitorTransform transform; - - scale = cursor_priv->preprocess_state.current_relative_scale; - transform = cursor_priv->preprocess_state.current_relative_transform; - - meta_cursor_sprite_get_hotspot (cursor_sprite, &hot_x, &hot_y); - width = meta_cursor_sprite_get_width (cursor_sprite); - height = meta_cursor_sprite_get_height (cursor_sprite); - meta_monitor_transform_transform_point (transform, - width, height, - hot_x, hot_y, - &hot_x, &hot_y); - *cursor_hotspot_x = (int) roundf (hot_x * scale); - *cursor_hotspot_y = (int) roundf (hot_y * scale); -} - -static CrtcCursorData * -ensure_crtc_cursor_data (MetaCrtcKms *crtc_kms) -{ - CrtcCursorData *crtc_cursor_data; - - crtc_cursor_data = meta_crtc_kms_get_cursor_renderer_private (crtc_kms); - if (!crtc_cursor_data) - { - crtc_cursor_data = g_new0 (CrtcCursorData, 1); - crtc_cursor_data->hw_state_invalidated = TRUE; - meta_crtc_kms_set_cursor_renderer_private (crtc_kms, - crtc_cursor_data, - g_free); - } - - return crtc_cursor_data; -} - -static void -assign_cursor_plane (MetaCursorRendererNative *native, - MetaCrtcKms *crtc_kms, - int x, - int y, - MetaCursorSprite *cursor_sprite) -{ - MetaCrtc *crtc = META_CRTC (crtc_kms); - MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite); - MetaGpuKms *gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc)); - MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data = - meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms); - MetaCursorNativeGpuState *cursor_gpu_state = - get_cursor_gpu_state (cursor_priv, gpu_kms); - MetaKmsCrtc *kms_crtc; - MetaKmsDevice *kms_device; - MetaKmsPlane *cursor_plane; - MetaDrmBuffer *buffer; - int cursor_width, cursor_height; - MetaFixed16Rectangle src_rect; - MetaRectangle dst_rect; - MetaDrmBuffer *crtc_buffer; - MetaKmsAssignPlaneFlag flags; - CrtcCursorData *crtc_cursor_data; - int cursor_hotspot_x; - int cursor_hotspot_y; - MetaKmsUpdate *kms_update; - MetaKmsPlaneAssignment *plane_assignment; - - if (cursor_gpu_state->pending_buffer_state == META_CURSOR_BUFFER_STATE_SET) - buffer = get_pending_cursor_sprite_buffer (cursor_gpu_state); - else - buffer = get_active_cursor_sprite_buffer (cursor_gpu_state); - - kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); - kms_device = meta_kms_crtc_get_device (kms_crtc); - cursor_plane = meta_kms_device_get_cursor_plane_for (kms_device, kms_crtc); - g_return_if_fail (cursor_plane); - - cursor_width = cursor_renderer_gpu_data->cursor_width; - cursor_height = cursor_renderer_gpu_data->cursor_height; - src_rect = (MetaFixed16Rectangle) { - .x = meta_fixed_16_from_int (0), - .y = meta_fixed_16_from_int (0), - .width = meta_fixed_16_from_int (cursor_width), - .height = meta_fixed_16_from_int (cursor_height), - }; - dst_rect = (MetaRectangle) { - .x = x, - .y = y, - .width = cursor_width, - .height = cursor_height, - }; - - flags = META_KMS_ASSIGN_PLANE_FLAG_ALLOW_FAIL; - crtc_cursor_data = ensure_crtc_cursor_data (crtc_kms); - crtc_buffer = crtc_cursor_data->buffer; - if (!crtc_cursor_data->hw_state_invalidated && buffer == crtc_buffer) - flags |= META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED; - - kms_update = - meta_kms_ensure_pending_update (meta_kms_device_get_kms (kms_device), - meta_kms_crtc_get_device (kms_crtc)); - plane_assignment = meta_kms_update_assign_plane (kms_update, - kms_crtc, - cursor_plane, - buffer, - src_rect, - dst_rect, - flags); - - calculate_crtc_cursor_hotspot (cursor_sprite, - &cursor_hotspot_x, - &cursor_hotspot_y); - meta_kms_plane_assignment_set_cursor_hotspot (plane_assignment, - cursor_hotspot_x, - cursor_hotspot_y); - - meta_kms_update_add_result_listener (kms_update, - on_kms_update_result, - native); - - crtc_cursor_data->buffer = buffer; - - if (cursor_gpu_state->pending_buffer_state == META_CURSOR_BUFFER_STATE_SET) - { - cursor_gpu_state->active_buffer_idx = - (cursor_gpu_state->active_buffer_idx + 1) % HW_CURSOR_BUFFER_COUNT; - cursor_gpu_state->pending_buffer_state = META_CURSOR_BUFFER_STATE_NONE; - } -} - -static float -calculate_cursor_crtc_sprite_scale (MetaCursorSprite *cursor_sprite, - MetaLogicalMonitor *logical_monitor) -{ - if (meta_is_stage_views_scaled ()) - { - return (meta_logical_monitor_get_scale (logical_monitor) * - meta_cursor_sprite_get_texture_scale (cursor_sprite)); - } - else - { - return 1.0; - } -} - -static void -set_crtc_cursor (MetaCursorRendererNative *cursor_renderer_native, - MetaRendererView *view, - MetaCrtc *crtc, - MetaCursorSprite *cursor_sprite) -{ - MetaCursorRenderer *cursor_renderer = - META_CURSOR_RENDERER (cursor_renderer_native); - MetaOutput *output = meta_crtc_get_outputs (crtc)->data; - MetaMonitor *monitor = meta_output_get_monitor (output); - MetaLogicalMonitor *logical_monitor = - meta_monitor_get_logical_monitor (monitor); - const MetaCrtcConfig *crtc_config = meta_crtc_get_config (crtc); - graphene_rect_t rect; - graphene_rect_t local_crtc_rect; - graphene_rect_t local_cursor_rect; - float view_scale; - float crtc_cursor_x, crtc_cursor_y; - CoglTexture *texture; - int tex_width, tex_height; - float cursor_crtc_scale; - MetaRectangle cursor_rect; - MetaMonitorTransform transform; - MetaMonitorTransform inverted_transform; - MetaMonitorMode *monitor_mode; - MetaMonitorCrtcMode *monitor_crtc_mode; - const MetaCrtcModeInfo *crtc_mode_info; - - view_scale = clutter_stage_view_get_scale (CLUTTER_STAGE_VIEW (view)); - - rect = meta_cursor_renderer_calculate_rect (cursor_renderer, cursor_sprite); - local_cursor_rect = - GRAPHENE_RECT_INIT (rect.origin.x - logical_monitor->rect.x, - rect.origin.y - logical_monitor->rect.y, - rect.size.width, - rect.size.height); - - local_crtc_rect = crtc_config->layout; - graphene_rect_offset (&local_crtc_rect, - -logical_monitor->rect.x, - -logical_monitor->rect.y); - - crtc_cursor_x = (local_cursor_rect.origin.x - - local_crtc_rect.origin.x) * view_scale; - crtc_cursor_y = (local_cursor_rect.origin.y - - local_crtc_rect.origin.y) * view_scale; - - texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); - tex_width = cogl_texture_get_width (texture); - tex_height = cogl_texture_get_height (texture); - - cursor_crtc_scale = - calculate_cursor_crtc_sprite_scale (cursor_sprite, - logical_monitor); - - cursor_rect = (MetaRectangle) { - .x = floorf (crtc_cursor_x), - .y = floorf (crtc_cursor_y), - .width = roundf (tex_width * cursor_crtc_scale), - .height = roundf (tex_height * cursor_crtc_scale) - }; - - transform = meta_logical_monitor_get_transform (logical_monitor); - transform = meta_monitor_logical_to_crtc_transform (monitor, transform); - - inverted_transform = meta_monitor_transform_invert (transform); - - monitor_mode = meta_monitor_get_current_mode (monitor); - monitor_crtc_mode = meta_monitor_get_crtc_mode_for_output (monitor, - monitor_mode, - output); - crtc_mode_info = meta_crtc_mode_get_info (monitor_crtc_mode->crtc_mode); - meta_rectangle_transform (&cursor_rect, - inverted_transform, - crtc_mode_info->width, - crtc_mode_info->height, - &cursor_rect); - - assign_cursor_plane (cursor_renderer_native, - META_CRTC_KMS (crtc), - cursor_rect.x, - cursor_rect.y, - cursor_sprite); -} - -static void -unset_crtc_cursor (MetaCursorRendererNative *native, - MetaCrtc *crtc) -{ - MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc); - CrtcCursorData *crtc_cursor_data; - MetaKmsCrtc *kms_crtc; - MetaKmsDevice *kms_device; - MetaKmsPlane *cursor_plane; - MetaDrmBuffer *crtc_buffer; - - crtc_cursor_data = ensure_crtc_cursor_data (crtc_kms); - crtc_buffer = crtc_cursor_data->buffer; - if (!crtc_cursor_data->hw_state_invalidated && !crtc_buffer) - return; - - kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); - kms_device = meta_kms_crtc_get_device (kms_crtc); - cursor_plane = meta_kms_device_get_cursor_plane_for (kms_device, kms_crtc); - - if (cursor_plane) - { - MetaKms *kms = meta_kms_device_get_kms (kms_device); - MetaKmsUpdate *kms_update; - - kms_update = meta_kms_ensure_pending_update (kms, kms_device); - meta_kms_update_unassign_plane (kms_update, kms_crtc, cursor_plane); - } - - crtc_cursor_data->buffer = NULL; -} - -static void -disable_hw_cursor_for_crtc (MetaKmsCrtc *kms_crtc, - const GError *error) -{ - MetaCrtcKms *crtc_kms = meta_crtc_kms_from_kms_crtc (kms_crtc); - MetaCrtc *crtc = META_CRTC (crtc_kms); - MetaGpuKms *gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc)); - MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data = - meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms); - - g_warning ("Failed to set hardware cursor (%s), " - "using OpenGL from now on", - error->message); - cursor_renderer_gpu_data->hw_cursor_broken = TRUE; -} - -void -meta_cursor_renderer_native_prepare_frame (MetaCursorRendererNative *cursor_renderer_native, - MetaRendererView *view) -{ - MetaCursorRenderer *cursor_renderer = - META_CURSOR_RENDERER (cursor_renderer_native); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - MetaBackend *backend = priv->backend; - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaCrtc *crtc = meta_renderer_view_get_crtc (view); - MetaCursorSprite *cursor_sprite; - graphene_rect_t cursor_rect; - cairo_rectangle_int_t view_layout; - graphene_rect_t view_rect; - CrtcCursorData *crtc_cursor_data; - - if (meta_monitor_manager_get_power_save_mode (monitor_manager) != - META_POWER_SAVE_ON) - return; - - if (!meta_crtc_get_gpu (crtc)) - return; - - crtc_cursor_data = ensure_crtc_cursor_data (META_CRTC_KMS (crtc)); - if (!crtc_cursor_data->hw_state_invalidated && - !crtc_cursor_data->needs_sync_position) - return; - - cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer); - if (!cursor_sprite) - goto unset_cursor; - - if (!priv->has_hw_cursor) - goto unset_cursor; - - cursor_rect = meta_cursor_renderer_calculate_rect (cursor_renderer, - cursor_sprite); - clutter_stage_view_get_layout (CLUTTER_STAGE_VIEW (view), &view_layout); - view_rect = GRAPHENE_RECT_INIT (view_layout.x, view_layout.y, - view_layout.width, view_layout.height); - if (!graphene_rect_intersection (&cursor_rect, &view_rect, NULL)) - goto unset_cursor; - - set_crtc_cursor (cursor_renderer_native, view, crtc, cursor_sprite); - - meta_cursor_renderer_emit_painted (cursor_renderer, - cursor_sprite, - CLUTTER_STAGE_VIEW (view)); - - crtc_cursor_data->needs_sync_position = FALSE; - crtc_cursor_data->hw_state_invalidated = FALSE; - return; - -unset_cursor: - unset_crtc_cursor (cursor_renderer_native, crtc); - - crtc_cursor_data = ensure_crtc_cursor_data (META_CRTC_KMS (crtc)); - crtc_cursor_data->hw_state_invalidated = FALSE; -} - -static gboolean -has_valid_cursor_sprite_buffer (MetaCursorSprite *cursor_sprite, - MetaGpuKms *gpu_kms) -{ - MetaCursorNativePrivate *cursor_priv; - MetaCursorNativeGpuState *cursor_gpu_state; - - cursor_priv = get_cursor_priv (cursor_sprite); - if (!cursor_priv) - return FALSE; - - cursor_gpu_state = get_cursor_gpu_state (cursor_priv, gpu_kms); - if (!cursor_gpu_state) - return FALSE; - - switch (cursor_gpu_state->pending_buffer_state) - { - case META_CURSOR_BUFFER_STATE_NONE: - return get_active_cursor_sprite_buffer (cursor_gpu_state) != NULL; - case META_CURSOR_BUFFER_STATE_SET: - return TRUE; - case META_CURSOR_BUFFER_STATE_INVALIDATED: - return FALSE; - } - - g_assert_not_reached (); - - return FALSE; -} - -static void -set_can_preprocess (MetaCursorSprite *cursor_sprite, - float scale, - MetaMonitorTransform transform) -{ - MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite); - - cursor_priv->preprocess_state.current_relative_scale = scale; - cursor_priv->preprocess_state.current_relative_transform = transform; - cursor_priv->preprocess_state.can_preprocess = TRUE; - - invalidate_cursor_gpu_state (cursor_sprite); -} - -static void -unset_can_preprocess (MetaCursorSprite *cursor_sprite) -{ - MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite); - - memset (&cursor_priv->preprocess_state, - 0, - sizeof (cursor_priv->preprocess_state)); - cursor_priv->preprocess_state.can_preprocess = FALSE; - - invalidate_cursor_gpu_state (cursor_sprite); -} - -static gboolean -get_can_preprocess (MetaCursorSprite *cursor_sprite) -{ - MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite); - - return cursor_priv->preprocess_state.can_preprocess; -} - -static float -get_current_relative_scale (MetaCursorSprite *cursor_sprite) -{ - MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite); - - return cursor_priv->preprocess_state.current_relative_scale; -} - -static MetaMonitorTransform -get_current_relative_transform (MetaCursorSprite *cursor_sprite) -{ - MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite); - - return cursor_priv->preprocess_state.current_relative_transform; -} - -static void -has_cursor_plane (MetaLogicalMonitor *logical_monitor, - MetaMonitor *monitor, - MetaOutput *output, - MetaCrtc *crtc, - gpointer user_data) -{ - gboolean *has_cursor_planes = user_data; - MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc); - MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); - MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); - - *has_cursor_planes &= !!meta_kms_device_get_cursor_plane_for (kms_device, - kms_crtc); -} - -static gboolean -crtcs_has_cursor_planes (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite) -{ - MetaCursorRendererNative *cursor_renderer_native = - META_CURSOR_RENDERER_NATIVE (renderer); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - MetaBackend *backend = priv->backend; - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - GList *logical_monitors; - GList *l; - graphene_rect_t cursor_rect; - - cursor_rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite); - - logical_monitors = - meta_monitor_manager_get_logical_monitors (monitor_manager); - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - MetaRectangle logical_monitor_layout; - graphene_rect_t logical_monitor_rect; - gboolean has_cursor_planes; - - logical_monitor_layout = - meta_logical_monitor_get_layout (logical_monitor); - logical_monitor_rect = - meta_rectangle_to_graphene_rect (&logical_monitor_layout); - - if (!graphene_rect_intersection (&cursor_rect, &logical_monitor_rect, - NULL)) - continue; - - has_cursor_planes = TRUE; - meta_logical_monitor_foreach_crtc (logical_monitor, - has_cursor_plane, - &has_cursor_planes); - if (!has_cursor_planes) - return FALSE; - } - - return TRUE; -} - -static gboolean -get_common_crtc_sprite_scale_for_logical_monitors (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite, - float *out_scale) -{ - MetaCursorRendererNative *cursor_renderer_native = - META_CURSOR_RENDERER_NATIVE (renderer); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - MetaBackend *backend = priv->backend; - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - graphene_rect_t cursor_rect; - float scale = 1.0; - gboolean has_visible_crtc_sprite = FALSE; - GList *logical_monitors; - GList *l; - - cursor_rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite); - - logical_monitors = - meta_monitor_manager_get_logical_monitors (monitor_manager); - - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - graphene_rect_t logical_monitor_rect = - meta_rectangle_to_graphene_rect (&logical_monitor->rect); - float tmp_scale; - - if (!graphene_rect_intersection (&cursor_rect, - &logical_monitor_rect, - NULL)) - continue; - - tmp_scale = - calculate_cursor_crtc_sprite_scale (cursor_sprite, logical_monitor); - - if (has_visible_crtc_sprite && scale != tmp_scale) - return FALSE; - - has_visible_crtc_sprite = TRUE; - scale = tmp_scale; - } - - if (!has_visible_crtc_sprite) - return FALSE; - - *out_scale = scale; - return TRUE; -} - -static gboolean -get_common_crtc_sprite_transform_for_logical_monitors (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite, - MetaMonitorTransform *out_transform) -{ - MetaCursorRendererNative *cursor_renderer_native = - META_CURSOR_RENDERER_NATIVE (renderer); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - MetaBackend *backend = priv->backend; - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - graphene_rect_t cursor_rect; - MetaMonitorTransform transform = META_MONITOR_TRANSFORM_NORMAL; - gboolean has_visible_crtc_sprite = FALSE; - GList *logical_monitors; - GList *l; - - cursor_rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite); - - logical_monitors = - meta_monitor_manager_get_logical_monitors (monitor_manager); - - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - graphene_rect_t logical_monitor_rect = - meta_rectangle_to_graphene_rect (&logical_monitor->rect); - MetaMonitorTransform logical_transform, tmp_transform; - GList *monitors, *l_mon; - - if (!graphene_rect_intersection (&cursor_rect, - &logical_monitor_rect, - NULL)) - continue; - - logical_transform = meta_logical_monitor_get_transform (logical_monitor); - monitors = meta_logical_monitor_get_monitors (logical_monitor); - for (l_mon = monitors; l_mon; l_mon = l_mon->next) - { - MetaMonitor *monitor = l_mon->data; - - tmp_transform = meta_monitor_transform_relative_transform ( - meta_cursor_sprite_get_texture_transform (cursor_sprite), - meta_monitor_logical_to_crtc_transform (monitor, logical_transform)); - - if (has_visible_crtc_sprite && transform != tmp_transform) - return FALSE; - - has_visible_crtc_sprite = TRUE; - transform = tmp_transform; - } - } - - if (!has_visible_crtc_sprite) - return FALSE; - - *out_transform = transform; - return TRUE; -} - -static gboolean -should_have_hw_cursor (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite, - GList *gpus) -{ - MetaCursorRendererNative *cursor_renderer_native = - META_CURSOR_RENDERER_NATIVE (renderer); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - CoglTexture *texture; - MetaMonitorTransform transform; - float scale; - GList *l; - - if (!gpus) - return FALSE; - - if (!cursor_sprite) - return FALSE; - - if (meta_backend_is_hw_cursors_inhibited (priv->backend)) - return FALSE; - - for (l = gpus; l; l = l->next) - { - MetaGpuKms *gpu_kms = l->data; - MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data; - - cursor_renderer_gpu_data = - meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms); - if (!cursor_renderer_gpu_data) - return FALSE; - - if (cursor_renderer_gpu_data->hw_cursor_broken) - return FALSE; - - if (!has_valid_cursor_sprite_buffer (cursor_sprite, gpu_kms)) - return FALSE; - } - - if (!crtcs_has_cursor_planes (renderer, cursor_sprite)) - return FALSE; - - texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); - if (!texture) - return FALSE; - - if (!get_common_crtc_sprite_scale_for_logical_monitors (renderer, - cursor_sprite, - &scale)) - return FALSE; - - if (!get_common_crtc_sprite_transform_for_logical_monitors (renderer, - cursor_sprite, - &transform)) - return FALSE; - - if (G_APPROX_VALUE (scale, 1.f, FLT_EPSILON) && - transform == META_MONITOR_TRANSFORM_NORMAL) - return TRUE; - else - return get_can_preprocess (cursor_sprite); - - return TRUE; -} - -static gboolean -meta_cursor_renderer_native_update_animation (MetaCursorRendererNative *native) -{ - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (native); - MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native); - MetaCursorSprite *cursor_sprite = meta_cursor_renderer_get_cursor (renderer); - - priv->animation_timeout_id = 0; - meta_cursor_sprite_tick_frame (cursor_sprite); - meta_cursor_renderer_force_update (renderer); - - return G_SOURCE_REMOVE; -} - -static void -maybe_schedule_cursor_sprite_animation_frame (MetaCursorRendererNative *native, - MetaCursorSprite *cursor_sprite) -{ - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (native); - gboolean cursor_change; - guint delay; - - cursor_change = cursor_sprite != priv->last_cursor; - priv->last_cursor = cursor_sprite; - - if (!cursor_change && priv->animation_timeout_id) - return; - - g_clear_handle_id (&priv->animation_timeout_id, g_source_remove); - - if (cursor_sprite && meta_cursor_sprite_is_animated (cursor_sprite)) - { - delay = meta_cursor_sprite_get_current_frame_time (cursor_sprite); - - if (delay == 0) - return; - - priv->animation_timeout_id = - g_timeout_add (delay, - (GSourceFunc) meta_cursor_renderer_native_update_animation, - native); - g_source_set_name_by_id (priv->animation_timeout_id, - "[mutter] meta_cursor_renderer_native_update_animation"); - } -} - -static GList * -calculate_cursor_sprite_gpus (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite) -{ - MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (native); - MetaBackend *backend = priv->backend; - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - GList *gpus = NULL; - GList *logical_monitors; - GList *l; - graphene_rect_t cursor_rect; - - cursor_rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite); - - logical_monitors = - meta_monitor_manager_get_logical_monitors (monitor_manager); - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - MetaRectangle logical_monitor_layout; - graphene_rect_t logical_monitor_rect; - GList *monitors, *l_mon; - - logical_monitor_layout = - meta_logical_monitor_get_layout (logical_monitor); - logical_monitor_rect = - meta_rectangle_to_graphene_rect (&logical_monitor_layout); - - if (!graphene_rect_intersection (&cursor_rect, &logical_monitor_rect, - NULL)) - continue; - - monitors = meta_logical_monitor_get_monitors (logical_monitor); - for (l_mon = monitors; l_mon; l_mon = l_mon->next) - { - MetaMonitor *monitor = l_mon->data; - MetaOutput *output = meta_monitor_get_main_output (monitor); - MetaGpu *gpu; - - gpu = meta_output_get_gpu (output); - if (gpu && !g_list_find (gpus, gpu)) - gpus = g_list_prepend (gpus, gpu); - } - } - - return gpus; -} - -static void -on_kms_update_result (const MetaKmsFeedback *kms_feedback, - gpointer user_data) -{ - MetaCursorRendererNative *cursor_renderer_native = user_data; - MetaCursorRenderer *cursor_renderer = - META_CURSOR_RENDERER (cursor_renderer_native); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - gboolean has_hw_cursor_failure = FALSE; - GList *l; - - for (l = meta_kms_feedback_get_failed_planes (kms_feedback); l; l = l->next) - { - MetaKmsPlaneFeedback *plane_feedback = l->data; - - switch (meta_kms_plane_get_plane_type (plane_feedback->plane)) - { - case META_KMS_PLANE_TYPE_CURSOR: - break; - case META_KMS_PLANE_TYPE_PRIMARY: - case META_KMS_PLANE_TYPE_OVERLAY: - continue; - } - - disable_hw_cursor_for_crtc (plane_feedback->crtc, - plane_feedback->error); - has_hw_cursor_failure = TRUE; - } - - if (has_hw_cursor_failure) - { - priv->has_hw_cursor = FALSE; - meta_cursor_renderer_force_update (cursor_renderer); - } -} - -static void -schedule_sync_position (MetaCursorRendererNative *cursor_renderer_native) -{ - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - GList *l; - - for (l = meta_backend_get_gpus (priv->backend); l; l = l->next) - { - MetaGpu *gpu = l->data; - GList *l_crtc; - - for (l_crtc = meta_gpu_get_crtcs (gpu); l_crtc; l_crtc = l_crtc->next) - { - MetaCrtcKms *crtc_kms = META_CRTC_KMS (l_crtc->data); - CrtcCursorData *crtc_cursor_data; - - crtc_cursor_data = ensure_crtc_cursor_data (crtc_kms); - crtc_cursor_data->needs_sync_position = TRUE; - } - } -} - -static gboolean -meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite) -{ - MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (native); - ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (priv->backend)); - g_autoptr (GList) gpus = NULL; - - if (cursor_sprite) - { - meta_cursor_sprite_realize_texture (cursor_sprite); - gpus = calculate_cursor_sprite_gpus (renderer, cursor_sprite); - realize_cursor_sprite (renderer, cursor_sprite, gpus); - } - - maybe_schedule_cursor_sprite_animation_frame (native, cursor_sprite); - - priv->has_hw_cursor = should_have_hw_cursor (renderer, cursor_sprite, gpus); - - schedule_sync_position (native); - clutter_stage_schedule_update (stage); - - return (priv->has_hw_cursor || - !cursor_sprite || - !meta_cursor_sprite_get_cogl_texture (cursor_sprite)); -} - -static void -unset_crtc_cursor_renderer_privates (MetaGpu *gpu, - MetaDrmBuffer *buffer) -{ - GList *l; - - for (l = meta_gpu_get_crtcs (gpu); l; l = l->next) - { - MetaCrtcKms *crtc_kms = META_CRTC_KMS (l->data); - MetaDrmBuffer *crtc_buffer; - - crtc_buffer = meta_crtc_kms_get_cursor_renderer_private (crtc_kms); - if (buffer == crtc_buffer) - meta_crtc_kms_set_cursor_renderer_private (crtc_kms, NULL, NULL); - } -} - -static void -cursor_gpu_state_free (MetaCursorNativeGpuState *cursor_gpu_state) -{ - int i; - MetaDrmBuffer *active_buffer; - - active_buffer = get_active_cursor_sprite_buffer (cursor_gpu_state); - if (active_buffer) - unset_crtc_cursor_renderer_privates (cursor_gpu_state->gpu, - active_buffer); - - for (i = 0; i < HW_CURSOR_BUFFER_COUNT; i++) - g_clear_object (&cursor_gpu_state->buffers[i]); - g_free (cursor_gpu_state); -} - -static MetaCursorNativeGpuState * -get_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv, - MetaGpuKms *gpu_kms) -{ - return g_hash_table_lookup (cursor_priv->gpu_states, gpu_kms); -} - -static MetaCursorNativeGpuState * -ensure_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv, - MetaGpuKms *gpu_kms) -{ - MetaCursorNativeGpuState *cursor_gpu_state; - - cursor_gpu_state = get_cursor_gpu_state (cursor_priv, gpu_kms); - if (cursor_gpu_state) - return cursor_gpu_state; - - cursor_gpu_state = g_new0 (MetaCursorNativeGpuState, 1); - cursor_gpu_state->gpu = META_GPU (gpu_kms); - g_hash_table_insert (cursor_priv->gpu_states, gpu_kms, cursor_gpu_state); - - return cursor_gpu_state; -} - -static void -invalidate_cursor_gpu_state (MetaCursorSprite *cursor_sprite) -{ - MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite); - GHashTableIter iter; - MetaCursorNativeGpuState *cursor_gpu_state; - - g_hash_table_iter_init (&iter, cursor_priv->gpu_states); - while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &cursor_gpu_state)) - { - unsigned int pending_buffer_idx; - - pending_buffer_idx = get_pending_cursor_sprite_buffer_index (cursor_gpu_state); - g_clear_object (&cursor_gpu_state->buffers[pending_buffer_idx]); - cursor_gpu_state->pending_buffer_state = - META_CURSOR_BUFFER_STATE_INVALIDATED; - } -} - -static void -on_cursor_sprite_texture_changed (MetaCursorSprite *cursor_sprite) -{ - invalidate_cursor_gpu_state (cursor_sprite); -} - -static void -cursor_priv_free (MetaCursorNativePrivate *cursor_priv) -{ - g_hash_table_destroy (cursor_priv->gpu_states); - g_free (cursor_priv); -} - -static MetaCursorNativePrivate * -get_cursor_priv (MetaCursorSprite *cursor_sprite) -{ - return g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite); -} - -static MetaCursorNativePrivate * -ensure_cursor_priv (MetaCursorSprite *cursor_sprite) -{ - MetaCursorNativePrivate *cursor_priv; - - cursor_priv = get_cursor_priv (cursor_sprite); - if (cursor_priv) - return cursor_priv; - - cursor_priv = g_new0 (MetaCursorNativePrivate, 1); - cursor_priv->gpu_states = - g_hash_table_new_full (g_direct_hash, - g_direct_equal, - NULL, - (GDestroyNotify) cursor_gpu_state_free); - g_object_set_qdata_full (G_OBJECT (cursor_sprite), - quark_cursor_sprite, - cursor_priv, - (GDestroyNotify) cursor_priv_free); - - g_signal_connect (cursor_sprite, "texture-changed", - G_CALLBACK (on_cursor_sprite_texture_changed), NULL); - - unset_can_preprocess (cursor_sprite); - - return cursor_priv; -} - -static void -load_cursor_sprite_gbm_buffer_for_gpu (MetaCursorRendererNative *native, - MetaGpuKms *gpu_kms, - MetaCursorSprite *cursor_sprite, - uint8_t *pixels, - uint width, - uint height, - int rowstride, - uint32_t gbm_format) -{ - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (native); - uint64_t cursor_width, cursor_height; - MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data; - struct gbm_device *gbm_device; - - cursor_renderer_gpu_data = - meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms); - if (!cursor_renderer_gpu_data) - return; - - cursor_width = (uint64_t) cursor_renderer_gpu_data->cursor_width; - cursor_height = (uint64_t) cursor_renderer_gpu_data->cursor_height; - - if (width > cursor_width || height > cursor_height) - { - meta_warning ("Invalid theme cursor size (must be at most %ux%u)", - (unsigned int)cursor_width, (unsigned int)cursor_height); - return; - } - - gbm_device = meta_gbm_device_from_gpu (gpu_kms); - if (gbm_device_is_format_supported (gbm_device, gbm_format, - GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE)) - { - MetaBackendNative *backend_native = META_BACKEND_NATIVE (priv->backend); - MetaDevicePool *device_pool = - meta_backend_native_get_device_pool (backend_native); - g_autoptr (MetaDeviceFile) device_file = NULL; - struct gbm_bo *bo; - uint8_t buf[4 * cursor_width * cursor_height]; - uint i; - g_autoptr (GError) error = NULL; - MetaDrmBufferGbm *buffer_gbm; - - device_file = meta_device_pool_open (device_pool, - meta_gpu_kms_get_file_path (gpu_kms), - META_DEVICE_FILE_FLAG_TAKE_CONTROL, - &error); - if (!device_file) - { - g_warning ("Failed to open '%s' for updating the cursor: %s", - meta_gpu_kms_get_file_path (gpu_kms), - error->message); - return; - } - - bo = gbm_bo_create (gbm_device, cursor_width, cursor_height, - gbm_format, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE); - if (!bo) - { - meta_warning ("Failed to allocate HW cursor buffer"); - return; - } - - memset (buf, 0, sizeof(buf)); - for (i = 0; i < height; i++) - memcpy (buf + i * 4 * cursor_width, pixels + i * rowstride, width * 4); - if (gbm_bo_write (bo, buf, cursor_width * cursor_height * 4) != 0) - { - meta_warning ("Failed to write cursors buffer data: %s", - g_strerror (errno)); - gbm_bo_destroy (bo); - return; - } - - buffer_gbm = meta_drm_buffer_gbm_new_take (device_file, bo, FALSE, &error); - if (!buffer_gbm) - { - meta_warning ("Failed to create DRM buffer wrapper: %s", - error->message); - gbm_bo_destroy (bo); - return; - } - - set_pending_cursor_sprite_buffer (cursor_sprite, gpu_kms, - META_DRM_BUFFER (buffer_gbm)); - } - else - { - meta_warning ("HW cursor for format %d not supported", gbm_format); - } -} - -static gboolean -is_cursor_hw_state_valid (MetaCursorSprite *cursor_sprite, - MetaGpuKms *gpu_kms) -{ - MetaCursorNativePrivate *cursor_priv; - MetaCursorNativeGpuState *cursor_gpu_state; - - cursor_priv = get_cursor_priv (cursor_sprite); - if (!cursor_priv) - return FALSE; - - cursor_gpu_state = get_cursor_gpu_state (cursor_priv, gpu_kms); - if (!cursor_gpu_state) - return FALSE; - - switch (cursor_gpu_state->pending_buffer_state) - { - case META_CURSOR_BUFFER_STATE_SET: - case META_CURSOR_BUFFER_STATE_NONE: - return TRUE; - case META_CURSOR_BUFFER_STATE_INVALIDATED: - return FALSE; - } - - g_assert_not_reached (); - return FALSE; -} - -static gboolean -is_cursor_scale_and_transform_valid (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite) -{ - MetaMonitorTransform transform; - float scale; - - if (!get_common_crtc_sprite_scale_for_logical_monitors (renderer, - cursor_sprite, - &scale)) - return FALSE; - - if (!get_common_crtc_sprite_transform_for_logical_monitors (renderer, - cursor_sprite, - &transform)) - return FALSE; - - return (scale == get_current_relative_scale (cursor_sprite) && - transform == get_current_relative_transform (cursor_sprite)); -} - -static cairo_surface_t * -scale_and_transform_cursor_sprite_cpu (uint8_t *pixels, - int width, - int height, - int rowstride, - float scale, - MetaMonitorTransform transform) -{ - cairo_t *cr; - cairo_surface_t *source_surface; - cairo_surface_t *target_surface; - int image_width; - int image_height; - - image_width = ceilf (width * scale); - image_height = ceilf (height * scale); - - target_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - image_width, - image_height); - - cr = cairo_create (target_surface); - if (transform != META_MONITOR_TRANSFORM_NORMAL) - { - cairo_translate (cr, 0.5 * image_width, 0.5 * image_height); - switch (transform) - { - case META_MONITOR_TRANSFORM_90: - cairo_rotate (cr, M_PI * 1.5); - break; - case META_MONITOR_TRANSFORM_180: - cairo_rotate (cr, M_PI); - break; - case META_MONITOR_TRANSFORM_270: - cairo_rotate (cr, M_PI * 0.5); - break; - case META_MONITOR_TRANSFORM_FLIPPED: - cairo_scale (cr, 1, -1); - break; - case META_MONITOR_TRANSFORM_FLIPPED_90: - cairo_rotate (cr, M_PI * 1.5); - cairo_scale (cr, -1, 1); - break; - case META_MONITOR_TRANSFORM_FLIPPED_180: - cairo_rotate (cr, M_PI); - cairo_scale (cr, 1, -1); - break; - case META_MONITOR_TRANSFORM_FLIPPED_270: - cairo_rotate (cr, M_PI * 0.5); - cairo_scale (cr, -1, 1); - break; - case META_MONITOR_TRANSFORM_NORMAL: - g_assert_not_reached (); - } - cairo_translate (cr, -0.5 * image_width, -0.5 * image_height); - } - cairo_scale (cr, scale, scale); - - source_surface = cairo_image_surface_create_for_data (pixels, - CAIRO_FORMAT_ARGB32, - width, - height, - rowstride); - - cairo_set_source_surface (cr, source_surface, 0, 0); - cairo_paint (cr); - cairo_destroy (cr); - cairo_surface_destroy (source_surface); - - return target_surface; -} - -static void -load_scaled_and_transformed_cursor_sprite (MetaCursorRendererNative *native, - MetaGpuKms *gpu_kms, - MetaCursorSprite *cursor_sprite, - float relative_scale, - MetaMonitorTransform relative_transform, - uint8_t *data, - int width, - int height, - int rowstride, - uint32_t gbm_format) -{ - if (!G_APPROX_VALUE (relative_scale, 1.f, FLT_EPSILON) || - relative_transform != META_MONITOR_TRANSFORM_NORMAL) - { - cairo_surface_t *surface; - - surface = scale_and_transform_cursor_sprite_cpu (data, - width, - height, - rowstride, - relative_scale, - relative_transform); - - load_cursor_sprite_gbm_buffer_for_gpu (native, - gpu_kms, - cursor_sprite, - cairo_image_surface_get_data (surface), - cairo_image_surface_get_width (surface), - cairo_image_surface_get_width (surface), - cairo_image_surface_get_stride (surface), - gbm_format); - - cairo_surface_destroy (surface); - } - else - { - load_cursor_sprite_gbm_buffer_for_gpu (native, - gpu_kms, - cursor_sprite, - data, - width, - height, - rowstride, - gbm_format); - } -} - -#ifdef HAVE_WAYLAND -static void -realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer, - MetaGpuKms *gpu_kms, - MetaCursorSpriteWayland *sprite_wayland) -{ - MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (native); - MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (sprite_wayland); - MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data; - uint64_t cursor_width, cursor_height; - CoglTexture *texture; - uint width, height; - MetaWaylandBuffer *buffer; - struct wl_resource *buffer_resource; - struct wl_shm_buffer *shm_buffer; - - cursor_renderer_gpu_data = - meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms); - if (!cursor_renderer_gpu_data || cursor_renderer_gpu_data->hw_cursor_broken) - return; - - if (is_cursor_hw_state_valid (cursor_sprite, gpu_kms) && - is_cursor_scale_and_transform_valid (renderer, cursor_sprite)) - return; - - buffer = meta_cursor_sprite_wayland_get_buffer (sprite_wayland); - if (!buffer) - return; - - buffer_resource = meta_wayland_buffer_get_resource (buffer); - if (!buffer_resource) - return; - - ensure_cursor_priv (cursor_sprite); - - shm_buffer = wl_shm_buffer_get (buffer_resource); - if (shm_buffer) - { - int rowstride = wl_shm_buffer_get_stride (shm_buffer); - uint8_t *buffer_data; - float relative_scale; - MetaMonitorTransform relative_transform; - uint32_t gbm_format; - - if (!get_common_crtc_sprite_scale_for_logical_monitors (renderer, - cursor_sprite, - &relative_scale)) - { - unset_can_preprocess (cursor_sprite); - return; - } - - if (!get_common_crtc_sprite_transform_for_logical_monitors (renderer, - cursor_sprite, - &relative_transform)) - { - unset_can_preprocess (cursor_sprite); - return; - } - - set_can_preprocess (cursor_sprite, - relative_scale, - relative_transform); - - wl_shm_buffer_begin_access (shm_buffer); - buffer_data = wl_shm_buffer_get_data (shm_buffer); - - width = wl_shm_buffer_get_width (shm_buffer); - height = wl_shm_buffer_get_height (shm_buffer); - - switch (wl_shm_buffer_get_format (shm_buffer)) - { - case WL_SHM_FORMAT_ARGB8888: - gbm_format = GBM_FORMAT_ARGB8888; - break; - case WL_SHM_FORMAT_XRGB8888: - gbm_format = GBM_FORMAT_XRGB8888; - break; - default: - g_warn_if_reached (); - gbm_format = GBM_FORMAT_ARGB8888; - } - - load_scaled_and_transformed_cursor_sprite (native, - gpu_kms, - cursor_sprite, - relative_scale, - relative_transform, - buffer_data, - width, - height, - rowstride, - gbm_format); - - wl_shm_buffer_end_access (shm_buffer); - } - else - { - MetaBackendNative *backend_native = META_BACKEND_NATIVE (priv->backend); - MetaDevicePool *device_pool = - meta_backend_native_get_device_pool (backend_native); - g_autoptr (MetaDeviceFile) device_file = NULL; - struct gbm_device *gbm_device; - struct gbm_bo *bo; - g_autoptr (GError) error = NULL; - MetaDrmBufferGbm *buffer_gbm; - - device_file = meta_device_pool_open (device_pool, - meta_gpu_kms_get_file_path (gpu_kms), - META_DEVICE_FILE_FLAG_TAKE_CONTROL, - &error); - if (!device_file) - { - g_warning ("Failed to open '%s' for updating the cursor: %s", - meta_gpu_kms_get_file_path (gpu_kms), - error->message); - return; - } - - /* HW cursors have a predefined size (at least 64x64), which usually is - * bigger than cursor theme size, so themed cursors must be padded with - * transparent pixels to fill the overlay. This is trivial if we have CPU - * access to the data, but it's not possible if the buffer is in GPU - * memory (and possibly tiled too), so if we don't get the right size, we - * fallback to GL. */ - cursor_width = (uint64_t) cursor_renderer_gpu_data->cursor_width; - cursor_height = (uint64_t) cursor_renderer_gpu_data->cursor_height; - - texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); - width = cogl_texture_get_width (texture); - height = cogl_texture_get_height (texture); - - if (width != cursor_width || height != cursor_height) - { - meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors"); - return; - } - - gbm_device = meta_gbm_device_from_gpu (gpu_kms); - bo = gbm_bo_import (gbm_device, - GBM_BO_IMPORT_WL_BUFFER, - buffer, - GBM_BO_USE_CURSOR); - if (!bo) - { - meta_warning ("Importing HW cursor from wl_buffer failed"); - return; - } - - unset_can_preprocess (cursor_sprite); - - buffer_gbm = meta_drm_buffer_gbm_new_take (device_file, bo, FALSE, &error); - if (!buffer_gbm) - { - meta_warning ("Failed to create DRM buffer wrapper: %s", - error->message); - gbm_bo_destroy (bo); - return; - } - - set_pending_cursor_sprite_buffer (cursor_sprite, gpu_kms, - META_DRM_BUFFER (buffer_gbm)); - } -} -#endif - -static void -realize_cursor_sprite_from_xcursor_for_gpu (MetaCursorRenderer *renderer, - MetaGpuKms *gpu_kms, - MetaCursorSpriteXcursor *sprite_xcursor) -{ - MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); - MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data; - MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (sprite_xcursor); - XcursorImage *xc_image; - float relative_scale; - MetaMonitorTransform relative_transform; - - ensure_cursor_priv (cursor_sprite); - - cursor_renderer_gpu_data = - meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms); - if (!cursor_renderer_gpu_data || cursor_renderer_gpu_data->hw_cursor_broken) - return; - - if (is_cursor_hw_state_valid (cursor_sprite, gpu_kms) && - is_cursor_scale_and_transform_valid (renderer, cursor_sprite)) - return; - - if (!get_common_crtc_sprite_scale_for_logical_monitors (renderer, - cursor_sprite, - &relative_scale)) - { - unset_can_preprocess (cursor_sprite); - return; - } - - if (!get_common_crtc_sprite_transform_for_logical_monitors (renderer, - cursor_sprite, - &relative_transform)) - { - unset_can_preprocess (cursor_sprite); - return; - } - - set_can_preprocess (cursor_sprite, - relative_scale, - relative_transform); - - xc_image = meta_cursor_sprite_xcursor_get_current_image (sprite_xcursor); - - load_scaled_and_transformed_cursor_sprite (native, - gpu_kms, - cursor_sprite, - relative_scale, - relative_transform, - (uint8_t *) xc_image->pixels, - xc_image->width, - xc_image->height, - xc_image->width * 4, - GBM_FORMAT_ARGB8888); -} - -static void -realize_cursor_sprite_for_gpu (MetaCursorRenderer *renderer, - MetaGpuKms *gpu_kms, - MetaCursorSprite *cursor_sprite) -{ - if (META_IS_CURSOR_SPRITE_XCURSOR (cursor_sprite)) - { - MetaCursorSpriteXcursor *sprite_xcursor = - META_CURSOR_SPRITE_XCURSOR (cursor_sprite); - - realize_cursor_sprite_from_xcursor_for_gpu (renderer, - gpu_kms, - sprite_xcursor); - } -#ifdef HAVE_WAYLAND - else if (META_IS_CURSOR_SPRITE_WAYLAND (cursor_sprite)) - { - MetaCursorSpriteWayland *sprite_wayland = - META_CURSOR_SPRITE_WAYLAND (cursor_sprite); - - realize_cursor_sprite_from_wl_buffer_for_gpu (renderer, - gpu_kms, - sprite_wayland); - } -#endif -} - -static void -realize_cursor_sprite (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite, - GList *gpus) -{ - GList *l; - - for (l = gpus; l; l = l->next) - { - MetaGpuKms *gpu_kms = l->data; - - realize_cursor_sprite_for_gpu (renderer, gpu_kms, cursor_sprite); - } -} - -static void -meta_cursor_renderer_native_class_init (MetaCursorRendererNativeClass *klass) -{ - MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_CLASS (klass); - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_cursor_renderer_native_finalize; - renderer_class->update_cursor = meta_cursor_renderer_native_update_cursor; - - quark_cursor_sprite = g_quark_from_static_string ("-meta-cursor-native"); - quark_cursor_renderer_native_gpu_data = - g_quark_from_static_string ("-meta-cursor-renderer-native-gpu-data"); -} - -static void -force_update_hw_cursor (MetaCursorRendererNative *native) -{ - MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native); - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (native); - GList *l; - - for (l = meta_backend_get_gpus (priv->backend); l; l = l->next) - { - MetaGpu *gpu = l->data; - GList *l_crtc; - - for (l_crtc = meta_gpu_get_crtcs (gpu); l_crtc; l_crtc = l_crtc->next) - { - MetaCrtcKms *crtc_kms = META_CRTC_KMS (l_crtc->data); - CrtcCursorData *crtc_cursor_data; - - crtc_cursor_data = ensure_crtc_cursor_data (crtc_kms); - crtc_cursor_data->hw_state_invalidated = TRUE; - } - } - - meta_cursor_renderer_force_update (renderer); -} - -static void -on_monitors_changed (MetaMonitorManager *monitors, - MetaCursorRendererNative *native) -{ - force_update_hw_cursor (native); -} - -static void -init_hw_cursor_support_for_gpu (MetaGpuKms *gpu_kms) -{ - MetaKmsDevice *kms_device = meta_gpu_kms_get_kms_device (gpu_kms); - MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data; - struct gbm_device *gbm_device; - uint64_t width, height; - - gbm_device = meta_gbm_device_from_gpu (gpu_kms); - if (!gbm_device) - return; - - cursor_renderer_gpu_data = - meta_create_cursor_renderer_native_gpu_data (gpu_kms); - - if (!meta_kms_device_get_cursor_size (kms_device, &width, &height)) - { - width = 64; - height = 64; - } - - cursor_renderer_gpu_data->cursor_width = width; - cursor_renderer_gpu_data->cursor_height = height; -} - -static void -on_gpu_added_for_cursor (MetaBackend *backend, - MetaGpuKms *gpu_kms) -{ - init_hw_cursor_support_for_gpu (gpu_kms); -} - -static void -init_hw_cursor_support (MetaCursorRendererNative *cursor_renderer_native) -{ - MetaCursorRendererNativePrivate *priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - GList *gpus; - GList *l; - - gpus = meta_backend_get_gpus (priv->backend); - for (l = gpus; l; l = l->next) - { - MetaGpuKms *gpu_kms = l->data; - - init_hw_cursor_support_for_gpu (gpu_kms); - } -} - -MetaCursorRendererNative * -meta_cursor_renderer_native_new (MetaBackend *backend, - ClutterInputDevice *device) -{ - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaCursorRendererNative *cursor_renderer_native; - MetaCursorRendererNativePrivate *priv; - - cursor_renderer_native = g_object_new (META_TYPE_CURSOR_RENDERER_NATIVE, - "backend", backend, - "device", device, - NULL); - priv = - meta_cursor_renderer_native_get_instance_private (cursor_renderer_native); - - g_signal_connect_object (monitor_manager, "monitors-changed-internal", - G_CALLBACK (on_monitors_changed), - cursor_renderer_native, 0); - g_signal_connect (backend, "gpu-added", - G_CALLBACK (on_gpu_added_for_cursor), NULL); - - priv->backend = backend; - - init_hw_cursor_support (cursor_renderer_native); - - return cursor_renderer_native; -} - -static void -meta_cursor_renderer_native_init (MetaCursorRendererNative *native) -{ -} diff --git a/src/backends/native/meta-cursor-renderer-native.h b/src/backends/native/meta-cursor-renderer-native.h deleted file mode 100644 index 5113b96ce..000000000 --- a/src/backends/native/meta-cursor-renderer-native.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -#ifndef META_CURSOR_RENDERER_NATIVE_H -#define META_CURSOR_RENDERER_NATIVE_H - -#include "backends/meta-cursor-renderer.h" -#include "meta/meta-backend.h" - -#define META_TYPE_CURSOR_RENDERER_NATIVE (meta_cursor_renderer_native_get_type ()) -G_DECLARE_FINAL_TYPE (MetaCursorRendererNative, meta_cursor_renderer_native, - META, CURSOR_RENDERER_NATIVE, - MetaCursorRenderer) - -void meta_cursor_renderer_native_prepare_frame (MetaCursorRendererNative *cursor_renderer_native, - MetaRendererView *view); - -MetaCursorRendererNative * meta_cursor_renderer_native_new (MetaBackend *backend, - ClutterInputDevice *device); - -#endif /* META_CURSOR_RENDERER_NATIVE_H */ diff --git a/src/backends/native/meta-device-pool-private.h b/src/backends/native/meta-device-pool-private.h deleted file mode 100644 index 06a43f6f4..000000000 --- a/src/backends/native/meta-device-pool-private.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2021 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_DEVICE_POOL_PRIVATE_H -#define META_DEVICE_POOL_PRIVATE_H - -#include - -#include "backends/native/meta-device-pool.h" -#include "backends/native/meta-launcher.h" - -#define META_TYPE_DEVICE_POOL (meta_device_pool_get_type ()) -G_DECLARE_FINAL_TYPE (MetaDevicePool, meta_device_pool, - META, DEVICE_POOL, - GObject) - -MetaDevicePool * meta_device_pool_new (MetaLauncher *launcher); - -#endif /* META_DEVICE_POOL_PRIVATE_H */ diff --git a/src/backends/native/meta-device-pool.c b/src/backends/native/meta-device-pool.c deleted file mode 100644 index 8bbbe3e34..000000000 --- a/src/backends/native/meta-device-pool.c +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Copyright (C) 2013-2021 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include "config.h" - -#include "backends/native/meta-device-pool-private.h" - -#include -#include -#include -#include -#include -#include - -#include "backends/native/meta-launcher.h" -#include "meta/util.h" - -#include "meta-dbus-login1.h" - -struct _MetaDeviceFile -{ - MetaDevicePool *pool; - - grefcount ref_count; - - char *path; - int major; - int minor; - int fd; - MetaDeviceFileFlags flags; - uint32_t tags[META_DEVICE_FILE_N_TAGS]; -}; - -struct _MetaDevicePool -{ - GObject parent; - - MetaDbusLogin1Session *session_proxy; - - GMutex mutex; - - GList *files; -}; - -G_DEFINE_TYPE (MetaDevicePool, meta_device_pool, G_TYPE_OBJECT) - -static void -release_device_file (MetaDevicePool *pool, - MetaDeviceFile *file); - -static MetaDeviceFile * -meta_device_file_new (MetaDevicePool *pool, - const char *path, - int major, - int minor, - int fd, - MetaDeviceFileFlags flags) -{ - MetaDeviceFile *file; - - file = g_new0 (MetaDeviceFile, 1); - - file->pool = pool; - g_ref_count_init (&file->ref_count); - - file->path = g_strdup (path); - file->major = major; - file->minor = minor; - file->fd = fd; - file->flags = flags; - - return file; -} - -static void -meta_device_file_free (MetaDeviceFile *file) -{ - g_free (file->path); - g_free (file); -} - -int -meta_device_file_get_fd (MetaDeviceFile *device_file) -{ - g_assert (!g_ref_count_compare (&device_file->ref_count, 0)); - - return device_file->fd; -} - -const char * -meta_device_file_get_path (MetaDeviceFile *device_file) -{ - return device_file->path; -} - -void -meta_device_file_tag (MetaDeviceFile *device_file, - MetaDeviceFileTags tag, - uint32_t value) -{ - device_file->tags[tag] |= value; -} - -uint32_t -meta_device_file_has_tag (MetaDeviceFile *device_file, - MetaDeviceFileTags tag, - uint32_t value) -{ - return (device_file->tags[tag] & value) == value; -} - -static MetaDeviceFile * -meta_device_file_acquire_locked (MetaDeviceFile *file) -{ - g_ref_count_inc (&file->ref_count); - return file; -} - -MetaDeviceFile * -meta_device_file_acquire (MetaDeviceFile *file) -{ - g_mutex_lock (&file->pool->mutex); - meta_topic (META_DEBUG_BACKEND, "Acquiring device file '%s'", file->path); - meta_device_file_acquire_locked (file); - g_mutex_unlock (&file->pool->mutex); - - return file; -} - -void -meta_device_file_release (MetaDeviceFile *file) -{ - g_warn_if_fail (file->fd != -1); - - release_device_file (file->pool, file); -} - -MetaDevicePool * -meta_device_file_get_pool (MetaDeviceFile *device_file) -{ - return device_file->pool; -} - -static MetaDeviceFile * -find_device_file_from_path (MetaDevicePool *pool, - const char *path) -{ - GList *l; - - for (l = pool->files; l; l = l->next) - { - MetaDeviceFile *file = l->data; - - if (g_strcmp0 (file->path, path) == 0) - return file; - } - - return NULL; -} - -static gboolean -take_device (MetaDbusLogin1Session *session_proxy, - int dev_major, - int dev_minor, - int *out_fd, - GCancellable *cancellable, - GError **error) -{ - g_autoptr (GVariant) fd_variant = NULL; - g_autoptr (GUnixFDList) fd_list = NULL; - int fd = -1; - - if (!meta_dbus_login1_session_call_take_device_sync (session_proxy, - dev_major, - dev_minor, - NULL, - &fd_variant, - NULL, /* paused */ - &fd_list, - cancellable, - error)) - return FALSE; - - fd = g_unix_fd_list_get (fd_list, g_variant_get_handle (fd_variant), error); - if (fd == -1) - return FALSE; - - *out_fd = fd; - return TRUE; -} - -static gboolean -get_device_info_from_path (const char *path, - int *out_major, - int *out_minor) -{ - int ret; - struct stat st; - - ret = stat (path, &st); - if (ret < 0 || !S_ISCHR (st.st_mode)) - return FALSE; - - *out_major = major (st.st_rdev); - *out_minor = minor (st.st_rdev); - return TRUE; -} - -MetaDeviceFile * -meta_device_pool_open (MetaDevicePool *pool, - const char *path, - MetaDeviceFileFlags flags, - GError **error) -{ - g_autoptr (GMutexLocker) locker = NULL; - MetaDeviceFile *file; - int major = -1, minor = -1; - int fd; - - locker = g_mutex_locker_new (&pool->mutex); - - file = find_device_file_from_path (pool, path); - if (file) - { - g_warn_if_fail (file->flags == flags); - meta_device_file_acquire_locked (file); - return file; - } - - if (flags & META_DEVICE_FILE_FLAG_TAKE_CONTROL) - { - meta_topic (META_DEBUG_BACKEND, - "Opening and taking control of device file '%s'", - path); - - if (!pool->session_proxy) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - "Can't take control without logind session"); - return NULL; - } - - if (!get_device_info_from_path (path, &major, &minor)) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - "Could not get device info for path %s: %m", path); - return NULL; - } - - if (!take_device (pool->session_proxy, major, minor, &fd, NULL, error)) - return NULL; - } - else - { - int open_flags; - - meta_topic (META_DEBUG_BACKEND, - "Opening device file '%s'", - path); - - if (flags & META_DEVICE_FILE_FLAG_READ_ONLY) - open_flags = O_RDONLY; - else - open_flags = O_RDWR; - open_flags |= O_CLOEXEC; - - do - { - fd = open (path, open_flags); - } - while (fd == -1 && errno == EINTR); - - if (fd == -1) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "Failed to open device '%s': %s", - path, g_strerror (errno)); - return NULL; - } - } - - file = meta_device_file_new (pool, path, major, minor, fd, flags); - pool->files = g_list_prepend (pool->files, file); - - return file; -} - -static void -release_device_file (MetaDevicePool *pool, - MetaDeviceFile *file) -{ - g_autoptr (GMutexLocker) locker = NULL; - g_autoptr (GError) error = NULL; - - locker = g_mutex_locker_new (&pool->mutex); - - meta_topic (META_DEBUG_BACKEND, "Releasing device file '%s'", file->path); - - if (!g_ref_count_dec (&file->ref_count)) - return; - - pool->files = g_list_remove (pool->files, file); - - if (file->flags & META_DEVICE_FILE_FLAG_TAKE_CONTROL) - { - MetaDbusLogin1Session *session_proxy; - - meta_topic (META_DEBUG_BACKEND, - "Releasing control of and closing device file '%s'", - file->path); - - session_proxy = pool->session_proxy; - if (!meta_dbus_login1_session_call_release_device_sync (session_proxy, - file->major, - file->minor, - NULL, &error)) - { - g_warning ("Could not release device '%s' (%d,%d): %s", - file->path, - file->major, file->minor, - error->message); - } - } - else - { - meta_topic (META_DEBUG_BACKEND, - "Closing device file '%s'", - file->path); - } - - close (file->fd); - - meta_device_file_free (file); -} - -MetaDevicePool * -meta_device_pool_new (MetaLauncher *launcher) -{ - MetaDevicePool *pool; - - pool = g_object_new (META_TYPE_DEVICE_POOL, NULL); - - if (launcher) - pool->session_proxy = meta_launcher_get_session_proxy (launcher); - - return pool; -} - -static void -meta_device_pool_finalize (GObject *object) -{ - MetaDevicePool *pool = META_DEVICE_POOL (object); - - g_mutex_clear (&pool->mutex); - g_warn_if_fail (!pool->files); - - G_OBJECT_CLASS (meta_device_pool_parent_class)->finalize (object); -} - -static void -meta_device_pool_init (MetaDevicePool *pool) -{ - g_mutex_init (&pool->mutex); -} - -static void -meta_device_pool_class_init (MetaDevicePoolClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_device_pool_finalize; -} diff --git a/src/backends/native/meta-device-pool.h b/src/backends/native/meta-device-pool.h deleted file mode 100644 index 0e9653bd6..000000000 --- a/src/backends/native/meta-device-pool.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2021 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_DEVICE_POOL_H -#define META_DEVICE_POOL_H - -#include -#include - -typedef enum _MetaDeviceFileFlags -{ - META_DEVICE_FILE_FLAG_NONE = 0, - META_DEVICE_FILE_FLAG_TAKE_CONTROL = 1 << 0, - META_DEVICE_FILE_FLAG_READ_ONLY = 1 << 1, -} MetaDeviceFileFlags; - -typedef enum _MetaDeviceFileTags -{ - META_DEVICE_FILE_TAG_KMS, - - META_DEVICE_FILE_N_TAGS, -} MetaDeviceFileTags; - -typedef struct _MetaDeviceFile MetaDeviceFile; -typedef struct _MetaDevicePool MetaDevicePool; - -int meta_device_file_get_fd (MetaDeviceFile *device_file); - -const char * meta_device_file_get_path (MetaDeviceFile *device_file); - -void meta_device_file_tag (MetaDeviceFile *device_file, - MetaDeviceFileTags tag, - uint32_t value); - -uint32_t meta_device_file_has_tag (MetaDeviceFile *device_file, - MetaDeviceFileTags tag, - uint32_t value); - -MetaDeviceFile * meta_device_file_acquire (MetaDeviceFile *file); - -void meta_device_file_release (MetaDeviceFile *device_file); - -MetaDevicePool * meta_device_file_get_pool (MetaDeviceFile *device_file); - -MetaDeviceFile * meta_device_pool_open (MetaDevicePool *pool, - const char *path, - MetaDeviceFileFlags flags, - GError **error); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaDeviceFile, meta_device_file_release) - -#endif /* META_DEVICE_FILE_POOL_H */ diff --git a/src/backends/native/meta-drm-buffer-dumb.c b/src/backends/native/meta-drm-buffer-dumb.c deleted file mode 100644 index d2fcad2f0..000000000 --- a/src/backends/native/meta-drm-buffer-dumb.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (C) 2011 Intel Corporation. - * Copyright (C) 2016 Red Hat - * Copyright (C) 2018 DisplayLink (UK) Ltd. - * Copyright (C) 2018 Canonical Ltd. - * - * 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 "backends/native/meta-drm-buffer-dumb.h" - -#include -#include -#include -#include - -#include "backends/native/meta-device-pool.h" - -struct _MetaDrmBufferDumb -{ - MetaDrmBuffer parent; - - uint32_t handle; - void *map; - uint64_t map_size; - int width; - int height; - int stride_bytes; - uint32_t drm_format; - int dmabuf_fd; -}; - -G_DEFINE_TYPE (MetaDrmBufferDumb, meta_drm_buffer_dumb, META_TYPE_DRM_BUFFER) - -static int -meta_drm_buffer_dumb_get_width (MetaDrmBuffer *buffer) -{ - MetaDrmBufferDumb *buffer_dumb = META_DRM_BUFFER_DUMB (buffer); - - return buffer_dumb->width; -} - -static int -meta_drm_buffer_dumb_get_height (MetaDrmBuffer *buffer) -{ - MetaDrmBufferDumb *buffer_dumb = META_DRM_BUFFER_DUMB (buffer); - - return buffer_dumb->height; -} - -static int -meta_drm_buffer_dumb_get_stride (MetaDrmBuffer *buffer) -{ - MetaDrmBufferDumb *buffer_dumb = META_DRM_BUFFER_DUMB (buffer); - - return buffer_dumb->stride_bytes; -} - -static uint32_t -meta_drm_buffer_dumb_get_format (MetaDrmBuffer *buffer) -{ - MetaDrmBufferDumb *buffer_dumb = META_DRM_BUFFER_DUMB (buffer); - - return buffer_dumb->drm_format; -} - -static int -handle_to_dmabuf_fd (MetaDrmBufferDumb *buffer_dumb, - GError **error) -{ - MetaDrmBuffer *buffer = META_DRM_BUFFER (buffer_dumb); - MetaDeviceFile *device_file; - int fd; - int ret; - int dmabuf_fd; - - device_file = meta_drm_buffer_get_device_file (buffer); - fd = meta_device_file_get_fd (device_file); - - ret = drmPrimeHandleToFD (fd, buffer_dumb->handle, DRM_CLOEXEC, - &dmabuf_fd); - if (ret) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmPrimeHandleToFd: %s", g_strerror (-ret)); - return -1; - } - - return dmabuf_fd; -} - -int -meta_drm_buffer_dumb_ensure_dmabuf_fd (MetaDrmBufferDumb *buffer_dumb, - GError **error) -{ - if (buffer_dumb->dmabuf_fd != -1) - return buffer_dumb->dmabuf_fd; - - buffer_dumb->dmabuf_fd = handle_to_dmabuf_fd (buffer_dumb, error); - return buffer_dumb->dmabuf_fd; -} - -void * -meta_drm_buffer_dumb_get_data (MetaDrmBufferDumb *buffer_dumb) -{ - return buffer_dumb->map; -} - -static gboolean -init_dumb_buffer (MetaDrmBufferDumb *buffer_dumb, - int width, - int height, - uint32_t format, - GError **error) -{ - MetaDrmBuffer *buffer = META_DRM_BUFFER (buffer_dumb); - MetaDeviceFile *device_file; - int fd; - struct drm_mode_create_dumb create_arg; - struct drm_mode_destroy_dumb destroy_arg; - struct drm_mode_map_dumb map_arg; - void *map; - MetaDrmFbArgs fb_args; - - device_file = meta_drm_buffer_get_device_file (buffer); - fd = meta_device_file_get_fd (device_file); - - create_arg = (struct drm_mode_create_dumb) { - .bpp = 32, /* RGBX8888 */ - .width = width, - .height = height - }; - if (drmIoctl (fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_arg) != 0) - { - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Failed to create dumb drm buffer: %s", - g_strerror (errno)); - goto err_ioctl; - } - - fb_args = (MetaDrmFbArgs) { - .width = width, - .height = height, - .format = format, - .handles = { create_arg.handle }, - .strides = { create_arg.pitch }, - }; - if (!meta_drm_buffer_ensure_fb_id (buffer, FALSE, &fb_args, error)) - goto err_add_fb; - - map_arg = (struct drm_mode_map_dumb) { - .handle = create_arg.handle - }; - if (drmIoctl (fd, DRM_IOCTL_MODE_MAP_DUMB, - &map_arg) != 0) - { - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Failed to map dumb drm buffer: %s", - g_strerror (errno)); - goto err_map_dumb; - } - - map = mmap (NULL, create_arg.size, PROT_WRITE, MAP_SHARED, - fd, map_arg.offset); - if (map == MAP_FAILED) - { - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Failed to mmap dumb drm buffer memory: %s", - g_strerror (errno)); - goto err_mmap; - } - - buffer_dumb->handle = create_arg.handle; - buffer_dumb->map = map; - buffer_dumb->map_size = create_arg.size; - buffer_dumb->width = width; - buffer_dumb->height = height; - buffer_dumb->stride_bytes = create_arg.pitch; - buffer_dumb->drm_format = format; - - return TRUE; - -err_mmap: -err_map_dumb: -err_add_fb: - destroy_arg = (struct drm_mode_destroy_dumb) { - .handle = create_arg.handle - }; - drmIoctl (fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg); - -err_ioctl: - return FALSE; -} - -MetaDrmBufferDumb * -meta_drm_buffer_dumb_new (MetaDeviceFile *device_file, - int width, - int height, - uint32_t format, - GError **error) -{ - MetaDrmBufferDumb *buffer_dumb; - - buffer_dumb = g_object_new (META_TYPE_DRM_BUFFER_DUMB, - "device-file", device_file, - NULL); - - if (!init_dumb_buffer (buffer_dumb, width, height, format, error)) - { - g_object_unref (buffer_dumb); - return NULL; - } - - return buffer_dumb; -} - -static void -destroy_dumb_buffer (MetaDrmBufferDumb *buffer_dumb) -{ - MetaDrmBuffer *buffer = META_DRM_BUFFER (buffer_dumb); - MetaDeviceFile *device_file; - int fd; - struct drm_mode_destroy_dumb destroy_arg; - - device_file = meta_drm_buffer_get_device_file (buffer); - fd = meta_device_file_get_fd (device_file); - - munmap (buffer_dumb->map, buffer_dumb->map_size); - - destroy_arg = (struct drm_mode_destroy_dumb) { - .handle = buffer_dumb->handle - }; - drmIoctl (fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg); - - if (buffer_dumb->dmabuf_fd != -1) - close (buffer_dumb->dmabuf_fd); -} - -static void -meta_drm_buffer_dumb_finalize (GObject *object) -{ - MetaDrmBufferDumb *buffer_dumb = META_DRM_BUFFER_DUMB (object); - - if (buffer_dumb->handle) - destroy_dumb_buffer (buffer_dumb); - - G_OBJECT_CLASS (meta_drm_buffer_dumb_parent_class)->finalize (object); -} - -static void -meta_drm_buffer_dumb_init (MetaDrmBufferDumb *buffer_dumb) -{ - buffer_dumb->dmabuf_fd = -1; -} - -static void -meta_drm_buffer_dumb_class_init (MetaDrmBufferDumbClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaDrmBufferClass *buffer_class = META_DRM_BUFFER_CLASS (klass); - - object_class->finalize = meta_drm_buffer_dumb_finalize; - - buffer_class->get_width = meta_drm_buffer_dumb_get_width; - buffer_class->get_height = meta_drm_buffer_dumb_get_height; - buffer_class->get_stride = meta_drm_buffer_dumb_get_stride; - buffer_class->get_format = meta_drm_buffer_dumb_get_format; -} diff --git a/src/backends/native/meta-drm-buffer-dumb.h b/src/backends/native/meta-drm-buffer-dumb.h deleted file mode 100644 index afc14660b..000000000 --- a/src/backends/native/meta-drm-buffer-dumb.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2018 Canonical Ltd. - * Copyright (C) 2019 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_DRM_BUFFER_DUMB_H -#define META_DRM_BUFFER_DUMB_H - -#include "backends/native/meta-backend-native-types.h" -#include "backends/native/meta-drm-buffer-private.h" - -#define META_TYPE_DRM_BUFFER_DUMB (meta_drm_buffer_dumb_get_type ()) -G_DECLARE_FINAL_TYPE (MetaDrmBufferDumb, - meta_drm_buffer_dumb, - META, DRM_BUFFER_DUMB, - MetaDrmBuffer) - -MetaDrmBufferDumb * meta_drm_buffer_dumb_new (MetaDeviceFile *device, - int width, - int height, - uint32_t format, - GError **error); - -int meta_drm_buffer_dumb_ensure_dmabuf_fd (MetaDrmBufferDumb *buffer_dumb, - GError **error); - -void * meta_drm_buffer_dumb_get_data (MetaDrmBufferDumb *buffer_dumb); - -#endif /* META_DRM_BUFFER_DUMB_H */ diff --git a/src/backends/native/meta-drm-buffer-gbm.c b/src/backends/native/meta-drm-buffer-gbm.c deleted file mode 100644 index f011afaca..000000000 --- a/src/backends/native/meta-drm-buffer-gbm.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - * Copyright (C) 2011 Intel Corporation. - * Copyright (C) 2016 Red Hat - * Copyright (C) 2018 DisplayLink (UK) Ltd. - * Copyright (C) 2018 Canonical Ltd. - * - * 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 "backends/native/meta-drm-buffer-gbm.h" - -#include -#include -#include -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/native/meta-cogl-utils.h" -#include "backends/native/meta-drm-buffer-private.h" - -struct _MetaDrmBufferGbm -{ - MetaDrmBuffer parent; - - struct gbm_surface *surface; - - struct gbm_bo *bo; -}; - -static void -cogl_scanout_iface_init (CoglScanoutInterface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaDrmBufferGbm, meta_drm_buffer_gbm, META_TYPE_DRM_BUFFER, - G_IMPLEMENT_INTERFACE (COGL_TYPE_SCANOUT, - cogl_scanout_iface_init)) - -struct gbm_bo * -meta_drm_buffer_gbm_get_bo (MetaDrmBufferGbm *buffer_gbm) -{ - return buffer_gbm->bo; -} - -static int -meta_drm_buffer_gbm_get_width (MetaDrmBuffer *buffer) -{ - MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (buffer); - - return gbm_bo_get_width (buffer_gbm->bo); -} - -static int -meta_drm_buffer_gbm_get_height (MetaDrmBuffer *buffer) -{ - MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (buffer); - - return gbm_bo_get_height (buffer_gbm->bo); -} - -static int -meta_drm_buffer_gbm_get_stride (MetaDrmBuffer *buffer) -{ - MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (buffer); - - return gbm_bo_get_stride (buffer_gbm->bo); -} - -static uint32_t -meta_drm_buffer_gbm_get_format (MetaDrmBuffer *buffer) -{ - MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (buffer); - - return gbm_bo_get_format (buffer_gbm->bo); -} - -static gboolean -init_fb_id (MetaDrmBufferGbm *buffer_gbm, - struct gbm_bo *bo, - gboolean use_modifiers, - GError **error) -{ - MetaDrmFbArgs fb_args = { 0, }; - - if (gbm_bo_get_handle_for_plane (bo, 0).s32 == -1) - { - /* Failed to fetch handle to plane, falling back to old method */ - fb_args.strides[0] = gbm_bo_get_stride (bo); - fb_args.handles[0] = gbm_bo_get_handle (bo).u32; - fb_args.offsets[0] = 0; - fb_args.modifiers[0] = DRM_FORMAT_MOD_INVALID; - } - else - { - int i; - - for (i = 0; i < gbm_bo_get_plane_count (bo); i++) - { - fb_args.strides[i] = gbm_bo_get_stride_for_plane (bo, i); - fb_args.handles[i] = gbm_bo_get_handle_for_plane (bo, i).u32; - fb_args.offsets[i] = gbm_bo_get_offset (bo, i); - fb_args.modifiers[i] = gbm_bo_get_modifier (bo); - } - } - - fb_args.width = gbm_bo_get_width (bo); - fb_args.height = gbm_bo_get_height (bo); - fb_args.format = gbm_bo_get_format (bo); - - if (!meta_drm_buffer_ensure_fb_id (META_DRM_BUFFER (buffer_gbm), - use_modifiers, &fb_args, error)) - return FALSE; - - return TRUE; -} - -static gboolean -lock_front_buffer (MetaDrmBufferGbm *buffer_gbm, - gboolean use_modifiers, - GError **error) -{ - buffer_gbm->bo = gbm_surface_lock_front_buffer (buffer_gbm->surface); - if (!buffer_gbm->bo) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_FAILED, - "gbm_surface_lock_front_buffer failed"); - return FALSE; - } - - return init_fb_id (buffer_gbm, buffer_gbm->bo, use_modifiers, error); -} - -MetaDrmBufferGbm * -meta_drm_buffer_gbm_new_lock_front (MetaDeviceFile *device_file, - struct gbm_surface *gbm_surface, - gboolean use_modifiers, - GError **error) -{ - MetaDrmBufferGbm *buffer_gbm; - - buffer_gbm = g_object_new (META_TYPE_DRM_BUFFER_GBM, - "device-file", device_file, - NULL); - buffer_gbm->surface = gbm_surface; - - if (!lock_front_buffer (buffer_gbm, use_modifiers, error)) - { - g_object_unref (buffer_gbm); - return NULL; - } - - return buffer_gbm; -} - -MetaDrmBufferGbm * -meta_drm_buffer_gbm_new_take (MetaDeviceFile *device_file, - struct gbm_bo *bo, - gboolean use_modifiers, - GError **error) -{ - MetaDrmBufferGbm *buffer_gbm; - - buffer_gbm = g_object_new (META_TYPE_DRM_BUFFER_GBM, - "device-file", device_file, - NULL); - - if (!init_fb_id (buffer_gbm, bo, use_modifiers, error)) - { - g_object_unref (buffer_gbm); - return NULL; - } - - buffer_gbm->bo = bo; - - return buffer_gbm; -} - -static gboolean -meta_drm_buffer_gbm_fill_timings (MetaDrmBuffer *buffer, - CoglFrameInfo *info, - GError **error) -{ - MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (buffer); - MetaBackend *backend = meta_get_backend (); - MetaEgl *egl = meta_backend_get_egl (backend); - ClutterBackend *clutter_backend = - meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = - clutter_backend_get_cogl_context (clutter_backend); - CoglDisplay *cogl_display = cogl_context->display; - CoglRenderer *cogl_renderer = cogl_display->renderer; - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - EGLDisplay egl_display = cogl_renderer_egl->edpy; - EGLImageKHR egl_image; - CoglPixelFormat cogl_format; - CoglEglImageFlags flags; - g_autoptr (CoglOffscreen) cogl_fbo = NULL; - CoglTexture2D *cogl_tex; - uint32_t n_planes; - uint64_t *modifiers; - uint32_t *strides; - uint32_t *offsets; - uint32_t width; - uint32_t height; - uint32_t drm_format; - int *fds; - gboolean result; - int dmabuf_fd = -1; - uint32_t i; - - dmabuf_fd = gbm_bo_get_fd (buffer_gbm->bo); - if (dmabuf_fd == -1) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to export buffer's DMA fd: %s", - g_strerror (errno)); - return FALSE; - } - - drm_format = gbm_bo_get_format (buffer_gbm->bo); - result = meta_cogl_pixel_format_from_drm_format (drm_format, - &cogl_format, - NULL); - g_assert (result); - - width = gbm_bo_get_width (buffer_gbm->bo); - height = gbm_bo_get_height (buffer_gbm->bo); - n_planes = gbm_bo_get_plane_count (buffer_gbm->bo); - fds = g_alloca (sizeof (int) * n_planes); - strides = g_alloca (sizeof (uint32_t) * n_planes); - offsets = g_alloca (sizeof (uint32_t) * n_planes); - modifiers = g_alloca (sizeof (uint64_t) * n_planes); - - for (i = 0; i < n_planes; i++) - { - fds[i] = dmabuf_fd; - strides[i] = gbm_bo_get_stride_for_plane (buffer_gbm->bo, i); - offsets[i] = gbm_bo_get_offset (buffer_gbm->bo, i); - modifiers[i] = gbm_bo_get_modifier (buffer_gbm->bo); - } - - egl_image = meta_egl_create_dmabuf_image (egl, - egl_display, - width, - height, - drm_format, - n_planes, - fds, - strides, - offsets, - modifiers, - error); - if (egl_image == EGL_NO_IMAGE_KHR) - goto out; - - flags = COGL_EGL_IMAGE_FLAG_NO_GET_DATA; - cogl_tex = cogl_egl_texture_2d_new_from_image (cogl_context, - width, - height, - cogl_format, - egl_image, - flags, - error); - - meta_egl_destroy_image (egl, egl_display, egl_image, NULL); - - if (!cogl_tex) - goto out; - - cogl_fbo = cogl_offscreen_new_with_texture (COGL_TEXTURE (cogl_tex)); - cogl_object_unref (cogl_tex); - - if (cogl_has_feature (cogl_context, COGL_FEATURE_ID_GET_GPU_TIME)) - { - info->gpu_time_before_buffer_swap_ns = - cogl_context_get_gpu_time_ns (cogl_context); - } - - info->cpu_time_before_buffer_swap_us = g_get_monotonic_time (); - - /* Set up a timestamp query for when all rendering will be finished. */ - if (cogl_has_feature (cogl_context, COGL_FEATURE_ID_TIMESTAMP_QUERY)) - { - info->timestamp_query = - cogl_framebuffer_create_timestamp_query (COGL_FRAMEBUFFER (cogl_fbo)); - } - -out: - close (dmabuf_fd); - - return TRUE; -} - -static gboolean -meta_drm_buffer_gbm_blit_to_framebuffer (CoglScanout *scanout, - CoglFramebuffer *framebuffer, - int x, - int y, - GError **error) -{ - MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (scanout); - MetaBackend *backend = meta_get_backend (); - MetaEgl *egl = meta_backend_get_egl (backend); - ClutterBackend *clutter_backend = - meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = - clutter_backend_get_cogl_context (clutter_backend); - CoglDisplay *cogl_display = cogl_context->display; - CoglRenderer *cogl_renderer = cogl_display->renderer; - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - EGLDisplay egl_display = cogl_renderer_egl->edpy; - EGLImageKHR egl_image; - CoglPixelFormat cogl_format; - CoglEglImageFlags flags; - CoglOffscreen *cogl_fbo = NULL; - CoglTexture2D *cogl_tex; - uint32_t n_planes; - uint64_t *modifiers; - uint32_t *strides; - uint32_t *offsets; - uint32_t width; - uint32_t height; - uint32_t drm_format; - int *fds; - gboolean result; - int dmabuf_fd = -1; - uint32_t i; - - dmabuf_fd = gbm_bo_get_fd (buffer_gbm->bo); - if (dmabuf_fd == -1) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS, - "Failed to export buffer's DMA fd: %s", - g_strerror (errno)); - return FALSE; - } - - drm_format = gbm_bo_get_format (buffer_gbm->bo); - result = meta_cogl_pixel_format_from_drm_format (drm_format, - &cogl_format, - NULL); - g_assert (result); - - width = gbm_bo_get_width (buffer_gbm->bo); - height = gbm_bo_get_height (buffer_gbm->bo); - n_planes = gbm_bo_get_plane_count (buffer_gbm->bo); - fds = g_alloca (sizeof (int) * n_planes); - strides = g_alloca (sizeof (uint32_t) * n_planes); - offsets = g_alloca (sizeof (uint32_t) * n_planes); - modifiers = g_alloca (sizeof (uint64_t) * n_planes); - - for (i = 0; i < n_planes; i++) - { - fds[i] = dmabuf_fd; - strides[i] = gbm_bo_get_stride_for_plane (buffer_gbm->bo, i); - offsets[i] = gbm_bo_get_offset (buffer_gbm->bo, i); - modifiers[i] = gbm_bo_get_modifier (buffer_gbm->bo); - } - - egl_image = meta_egl_create_dmabuf_image (egl, - egl_display, - width, - height, - drm_format, - n_planes, - fds, - strides, - offsets, - modifiers, - error); - if (egl_image == EGL_NO_IMAGE_KHR) - { - result = FALSE; - goto out; - } - - flags = COGL_EGL_IMAGE_FLAG_NO_GET_DATA; - cogl_tex = cogl_egl_texture_2d_new_from_image (cogl_context, - width, - height, - cogl_format, - egl_image, - flags, - error); - - meta_egl_destroy_image (egl, egl_display, egl_image, NULL); - - if (!cogl_tex) - { - result = FALSE; - goto out; - } - - cogl_fbo = cogl_offscreen_new_with_texture (COGL_TEXTURE (cogl_tex)); - cogl_object_unref (cogl_tex); - - if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (cogl_fbo), error)) - { - result = FALSE; - goto out; - } - - result = cogl_blit_framebuffer (COGL_FRAMEBUFFER (cogl_fbo), - framebuffer, - 0, 0, - x, y, - width, height, - error); - -out: - g_clear_object (&cogl_fbo); - close (dmabuf_fd); - - return result; -} - -static void -cogl_scanout_iface_init (CoglScanoutInterface *iface) -{ - iface->blit_to_framebuffer = meta_drm_buffer_gbm_blit_to_framebuffer; -} - -static void -meta_drm_buffer_gbm_finalize (GObject *object) -{ - MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (object); - - if (buffer_gbm->bo) - { - if (buffer_gbm->surface) - gbm_surface_release_buffer (buffer_gbm->surface, buffer_gbm->bo); - else - gbm_bo_destroy (buffer_gbm->bo); - } - - G_OBJECT_CLASS (meta_drm_buffer_gbm_parent_class)->finalize (object); -} - -static void -meta_drm_buffer_gbm_init (MetaDrmBufferGbm *buffer_gbm) -{ -} - -static void -meta_drm_buffer_gbm_class_init (MetaDrmBufferGbmClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaDrmBufferClass *buffer_class = META_DRM_BUFFER_CLASS (klass); - - object_class->finalize = meta_drm_buffer_gbm_finalize; - - buffer_class->get_width = meta_drm_buffer_gbm_get_width; - buffer_class->get_height = meta_drm_buffer_gbm_get_height; - buffer_class->get_stride = meta_drm_buffer_gbm_get_stride; - buffer_class->get_format = meta_drm_buffer_gbm_get_format; - buffer_class->fill_timings = meta_drm_buffer_gbm_fill_timings; -} diff --git a/src/backends/native/meta-drm-buffer-gbm.h b/src/backends/native/meta-drm-buffer-gbm.h deleted file mode 100644 index 0413c9fa2..000000000 --- a/src/backends/native/meta-drm-buffer-gbm.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2018 Canonical Ltd. - * Copyright (C) 2019 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_DRM_BUFFER_GBM_H -#define META_DRM_BUFFER_GBM_H - -#include - -#include "backends/native/meta-backend-native-types.h" -#include "backends/native/meta-drm-buffer-private.h" - -#define META_TYPE_DRM_BUFFER_GBM (meta_drm_buffer_gbm_get_type ()) -G_DECLARE_FINAL_TYPE (MetaDrmBufferGbm, - meta_drm_buffer_gbm, - META, DRM_BUFFER_GBM, - MetaDrmBuffer) - -MetaDrmBufferGbm * meta_drm_buffer_gbm_new_lock_front (MetaDeviceFile *device_file, - struct gbm_surface *gbm_surface, - gboolean use_modifiers, - GError **error); - - -MetaDrmBufferGbm * meta_drm_buffer_gbm_new_take (MetaDeviceFile *device_file, - struct gbm_bo *gbm_bo, - gboolean use_modifiers, - GError **error); - -struct gbm_bo * meta_drm_buffer_gbm_get_bo (MetaDrmBufferGbm *buffer_gbm); - -#endif /* META_DRM_BUFFER_GBM_H */ diff --git a/src/backends/native/meta-drm-buffer-import.c b/src/backends/native/meta-drm-buffer-import.c deleted file mode 100644 index 77cd138d2..000000000 --- a/src/backends/native/meta-drm-buffer-import.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (C) 2011 Intel Corporation. - * Copyright (C) 2016,2017 Red Hat - * Copyright (C) 2018,2019 DisplayLink (UK) Ltd. - * Copyright (C) 2018 Canonical Ltd. - * - * 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 "backends/native/meta-drm-buffer-import.h" - -#include -#include -#include -#include - -#include "backends/native/meta-drm-buffer-gbm.h" -#include "backends/native/meta-kms-utils.h" -#include "backends/native/meta-renderer-native.h" - -struct _MetaDrmBufferImport -{ - MetaDrmBuffer parent; - - MetaDrmBufferGbm *importee; -}; - -G_DEFINE_TYPE (MetaDrmBufferImport, meta_drm_buffer_import, - META_TYPE_DRM_BUFFER) - -static int -meta_drm_buffer_import_get_width (MetaDrmBuffer *buffer) -{ - MetaDrmBufferImport *buffer_import = META_DRM_BUFFER_IMPORT (buffer); - - return meta_drm_buffer_get_width (META_DRM_BUFFER (buffer_import->importee)); -} - -static int -meta_drm_buffer_import_get_height (MetaDrmBuffer *buffer) -{ - MetaDrmBufferImport *buffer_import = META_DRM_BUFFER_IMPORT (buffer); - - return meta_drm_buffer_get_height (META_DRM_BUFFER (buffer_import->importee)); -} - -static int -meta_drm_buffer_import_get_stride (MetaDrmBuffer *buffer) -{ - MetaDrmBufferImport *buffer_import = META_DRM_BUFFER_IMPORT (buffer); - - return meta_drm_buffer_get_stride (META_DRM_BUFFER (buffer_import->importee)); -} - -static uint32_t -meta_drm_buffer_import_get_format (MetaDrmBuffer *buffer) -{ - MetaDrmBufferImport *buffer_import = META_DRM_BUFFER_IMPORT (buffer); - - return meta_drm_buffer_get_format (META_DRM_BUFFER (buffer_import->importee)); -} - -static struct gbm_bo * -dmabuf_to_gbm_bo (struct gbm_device *importer, - int dmabuf_fd, - uint32_t width, - uint32_t height, - uint32_t stride, - uint32_t format) -{ - struct gbm_import_fd_data data = { - .fd = dmabuf_fd, - .width = width, - .height = height, - .stride = stride, - .format = format - }; - - return gbm_bo_import (importer, - GBM_BO_IMPORT_FD, - &data, - GBM_BO_USE_SCANOUT); -} - -static gboolean -import_gbm_buffer (MetaDrmBufferImport *buffer_import, - struct gbm_device *importer, - GError **error) -{ - MetaDrmFbArgs fb_args = { 0, }; - struct gbm_bo *primary_bo; - struct gbm_bo *imported_bo; - int dmabuf_fd; - gboolean ret; - - primary_bo = meta_drm_buffer_gbm_get_bo (buffer_import->importee); - - dmabuf_fd = gbm_bo_get_fd (primary_bo); - if (dmabuf_fd == -1) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_FAILED, - "getting dmabuf fd failed"); - return FALSE; - } - - fb_args.strides[0] = gbm_bo_get_stride (primary_bo); - fb_args.width = gbm_bo_get_width (primary_bo); - fb_args.height = gbm_bo_get_height (primary_bo); - fb_args.format = gbm_bo_get_format (primary_bo); - - imported_bo = dmabuf_to_gbm_bo (importer, - dmabuf_fd, - fb_args.width, - fb_args.height, - fb_args.strides[0], - fb_args.format); - if (!imported_bo) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_FAILED, - "importing dmabuf fd failed"); - ret = FALSE; - goto out_close; - } - - fb_args.handles[0] = gbm_bo_get_handle (imported_bo).u32; - - ret = meta_drm_buffer_ensure_fb_id (META_DRM_BUFFER (buffer_import), - FALSE /* use_modifiers */, - &fb_args, - error); - - gbm_bo_destroy (imported_bo); - -out_close: - close (dmabuf_fd); - - return ret; -} - -MetaDrmBufferImport * -meta_drm_buffer_import_new (MetaDeviceFile *device_file, - struct gbm_device *gbm_device, - MetaDrmBufferGbm *buffer_gbm, - GError **error) -{ - MetaDrmBufferImport *buffer_import; - - buffer_import = g_object_new (META_TYPE_DRM_BUFFER_IMPORT, - "device-file", device_file, - NULL); - g_set_object (&buffer_import->importee, buffer_gbm); - - if (!import_gbm_buffer (buffer_import, gbm_device, error)) - { - g_object_unref (buffer_import); - return NULL; - } - - return buffer_import; -} - -static void -meta_drm_buffer_import_finalize (GObject *object) -{ - MetaDrmBufferImport *buffer_import = META_DRM_BUFFER_IMPORT (object); - - g_clear_object (&buffer_import->importee); - - G_OBJECT_CLASS (meta_drm_buffer_import_parent_class)->finalize (object); -} - -static void -meta_drm_buffer_import_init (MetaDrmBufferImport *buffer_import) -{ -} - -static void -meta_drm_buffer_import_class_init (MetaDrmBufferImportClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaDrmBufferClass *buffer_class = META_DRM_BUFFER_CLASS (klass); - - object_class->finalize = meta_drm_buffer_import_finalize; - - buffer_class->get_width = meta_drm_buffer_import_get_width; - buffer_class->get_height = meta_drm_buffer_import_get_height; - buffer_class->get_stride = meta_drm_buffer_import_get_stride; - buffer_class->get_format = meta_drm_buffer_import_get_format; -} diff --git a/src/backends/native/meta-drm-buffer-import.h b/src/backends/native/meta-drm-buffer-import.h deleted file mode 100644 index faff560fa..000000000 --- a/src/backends/native/meta-drm-buffer-import.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2018 Canonical Ltd. - * Copyright (C) 2019 Red Hat Inc. - * Copyright (C) 2019 DisplayLink (UK) Ltd. - * - * 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_DRM_BUFFER_IMPORT_H -#define META_DRM_BUFFER_IMPORT_H - -#include - -#include "backends/native/meta-drm-buffer.h" -#include "backends/native/meta-drm-buffer-gbm.h" -#include "backends/native/meta-gpu-kms.h" - -#define META_TYPE_DRM_BUFFER_IMPORT (meta_drm_buffer_import_get_type ()) -G_DECLARE_FINAL_TYPE (MetaDrmBufferImport, - meta_drm_buffer_import, - META, DRM_BUFFER_IMPORT, - MetaDrmBuffer) - -/* - * MetaDrmBufferImport is a buffer that refers to the storage of a - * MetaDrmBufferGbm buffer on another MetaGpuKms. - * - * When creating an imported buffer, the given GBM buffer is exported - * as a dma_buf and then imported to the given MetaGpuKms. A reference - * is kept to the GBM buffer so that it won't disappear while the - * imported buffer exists. - * - * The import has a high chance of failing under normal operating - * conditions and needs to be handled with fallbacks to something else. - */ -MetaDrmBufferImport * meta_drm_buffer_import_new (MetaDeviceFile *device_file, - struct gbm_device *gbm_device, - MetaDrmBufferGbm *buffer_gbm, - GError **error); - -#endif /* META_DRM_BUFFER_IMPORT_H */ diff --git a/src/backends/native/meta-drm-buffer-private.h b/src/backends/native/meta-drm-buffer-private.h deleted file mode 100644 index a54ce7c31..000000000 --- a/src/backends/native/meta-drm-buffer-private.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2018 Canonical Ltd. - * Copyright (C) 2019-2020 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_DRM_BUFFER_PRIVATE_H -#define META_DRM_BUFFER_PRIVATE_H - -#include "backends/native/meta-backend-native-types.h" -#include "backends/native/meta-drm-buffer.h" - -typedef struct _MetaDrmFbArgs -{ - uint32_t width; - uint32_t height; - uint32_t format; - uint32_t handles[4]; - uint32_t offsets[4]; - uint32_t strides[4]; - uint64_t modifiers[4]; -} MetaDrmFbArgs; - -struct _MetaDrmBufferClass -{ - GObjectClass parent_class; - - int (* get_width) (MetaDrmBuffer *buffer); - int (* get_height) (MetaDrmBuffer *buffer); - int (* get_stride) (MetaDrmBuffer *buffer); - uint32_t (* get_format) (MetaDrmBuffer *buffer); - - gboolean (* fill_timings) (MetaDrmBuffer *buffer, - CoglFrameInfo *info, - GError **error); -}; - -MetaDeviceFile * meta_drm_buffer_get_device_file (MetaDrmBuffer *buffer); - -gboolean meta_drm_buffer_ensure_fb_id (MetaDrmBuffer *buffer, - gboolean use_modifiers, - const MetaDrmFbArgs *fb_args, - GError **error); - -gboolean meta_drm_buffer_ensure_fb_in_impl (MetaDrmBuffer *buffer, - gboolean use_modifiers, - const MetaDrmFbArgs *fb_args, - GError **error); - -#endif /* META_DRM_BUFFER_PRIVATE_H */ diff --git a/src/backends/native/meta-drm-buffer.c b/src/backends/native/meta-drm-buffer.c deleted file mode 100644 index 1da622037..000000000 --- a/src/backends/native/meta-drm-buffer.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright (C) 2011 Intel Corporation. - * Copyright (C) 2016-2020 Red Hat - * Copyright (C) 2018 DisplayLink (UK) Ltd. - * Copyright (C) 2018 Canonical Ltd. - * - * 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: Daniel van Vugt - */ - -#include "config.h" - -#include "backends/native/meta-drm-buffer-private.h" - -#include - -#include "backends/native/meta-device-pool.h" -#include "backends/native/meta-kms-utils.h" - -#define INVALID_FB_ID 0U - -enum -{ - PROP_0, - - PROP_DEVICE_FILE, - - N_PROPS -}; - -static GParamSpec *obj_props[N_PROPS]; - -typedef struct _MetaDrmBufferPrivate -{ - MetaDeviceFile *device_file; - uint32_t fb_id; -} MetaDrmBufferPrivate; - -G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaDrmBuffer, meta_drm_buffer, - G_TYPE_OBJECT) - -MetaDeviceFile * -meta_drm_buffer_get_device_file (MetaDrmBuffer *buffer) -{ - MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer); - - return priv->device_file; -} - -gboolean -meta_drm_buffer_ensure_fb_id (MetaDrmBuffer *buffer, - gboolean use_modifiers, - const MetaDrmFbArgs *fb_args, - GError **error) -{ - MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer); - int fd; - MetaDrmFormatBuf tmp; - uint32_t fb_id; - - fd = meta_device_file_get_fd (priv->device_file); - - if (use_modifiers && fb_args->modifiers[0] != DRM_FORMAT_MOD_INVALID) - { - if (drmModeAddFB2WithModifiers (fd, - fb_args->width, - fb_args->height, - fb_args->format, - fb_args->handles, - fb_args->strides, - fb_args->offsets, - fb_args->modifiers, - &fb_id, - DRM_MODE_FB_MODIFIERS)) - { - g_set_error (error, - G_IO_ERROR, - g_io_error_from_errno (errno), - "drmModeAddFB2WithModifiers failed: %s", - g_strerror (errno)); - return FALSE; - } - } - else if (drmModeAddFB2 (fd, - fb_args->width, - fb_args->height, - fb_args->format, - fb_args->handles, - fb_args->strides, - fb_args->offsets, - &fb_id, - 0)) - { - if (fb_args->format != DRM_FORMAT_XRGB8888) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_FAILED, - "drmModeAddFB does not support format '%s' (0x%x)", - meta_drm_format_to_string (&tmp, fb_args->format), - fb_args->format); - return FALSE; - } - - if (drmModeAddFB (fd, - fb_args->width, - fb_args->height, - 24, - 32, - fb_args->strides[0], - fb_args->handles[0], - &fb_id)) - { - g_set_error (error, - G_IO_ERROR, - g_io_error_from_errno (errno), - "drmModeAddFB failed: %s", - g_strerror (errno)); - return FALSE; - } - } - - priv->fb_id = fb_id; - return TRUE; -} - -static void -meta_drm_buffer_release_fb_id (MetaDrmBuffer *buffer) -{ - MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer); - int fd; - int ret; - - fd = meta_device_file_get_fd (priv->device_file); - ret = drmModeRmFB (fd, priv->fb_id); - if (ret != 0) - g_warning ("drmModeRmFB: %s", g_strerror (-ret)); - - priv->fb_id = 0; -} - -uint32_t -meta_drm_buffer_get_fb_id (MetaDrmBuffer *buffer) -{ - MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer); - - return priv->fb_id; -} - -int -meta_drm_buffer_get_width (MetaDrmBuffer *buffer) -{ - return META_DRM_BUFFER_GET_CLASS (buffer)->get_width (buffer); -} - -int -meta_drm_buffer_get_height (MetaDrmBuffer *buffer) -{ - return META_DRM_BUFFER_GET_CLASS (buffer)->get_height (buffer); -} - -int -meta_drm_buffer_get_stride (MetaDrmBuffer *buffer) -{ - return META_DRM_BUFFER_GET_CLASS (buffer)->get_stride (buffer); -} - -uint32_t -meta_drm_buffer_get_format (MetaDrmBuffer *buffer) -{ - return META_DRM_BUFFER_GET_CLASS (buffer)->get_format (buffer); -} - -gboolean -meta_drm_buffer_supports_fill_timings (MetaDrmBuffer *buffer) -{ - return META_DRM_BUFFER_GET_CLASS (buffer)->fill_timings != NULL; -} - -gboolean -meta_drm_buffer_fill_timings (MetaDrmBuffer *buffer, - CoglFrameInfo *info, - GError **error) -{ - if (!meta_drm_buffer_supports_fill_timings (buffer)) - { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - "Buffer doesn't support filling timing info"); - return FALSE; - } - - return META_DRM_BUFFER_GET_CLASS (buffer)->fill_timings (buffer, info, error); -} - -static void -meta_drm_buffer_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaDrmBuffer *buffer = META_DRM_BUFFER (object); - MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer); - - switch (prop_id) - { - case PROP_DEVICE_FILE: - g_value_set_pointer (value, priv->device_file); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_drm_buffer_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaDrmBuffer *buffer = META_DRM_BUFFER (object); - MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer); - - switch (prop_id) - { - case PROP_DEVICE_FILE: - priv->device_file = g_value_get_pointer (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_drm_buffer_finalize (GObject *object) -{ - MetaDrmBuffer *buffer = META_DRM_BUFFER (object); - MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer); - - if (priv->fb_id != INVALID_FB_ID) - meta_drm_buffer_release_fb_id (buffer); - meta_device_file_release (priv->device_file); - - G_OBJECT_CLASS (meta_drm_buffer_parent_class)->finalize (object); -} - -static void -meta_drm_buffer_constructed (GObject *object) -{ - MetaDrmBuffer *buffer = META_DRM_BUFFER (object); - MetaDrmBufferPrivate *priv = meta_drm_buffer_get_instance_private (buffer); - - meta_device_file_acquire (priv->device_file); - - G_OBJECT_CLASS (meta_drm_buffer_parent_class)->constructed (object); -} - -static void -meta_drm_buffer_init (MetaDrmBuffer *buffer) -{ -} - -static void -meta_drm_buffer_class_init (MetaDrmBufferClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->get_property = meta_drm_buffer_get_property; - object_class->set_property = meta_drm_buffer_set_property; - object_class->constructed = meta_drm_buffer_constructed; - object_class->finalize = meta_drm_buffer_finalize; - - obj_props[PROP_DEVICE_FILE] = - g_param_spec_pointer ("device-file", - "device file", - "MetaDeviceFile", - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, N_PROPS, obj_props); -} diff --git a/src/backends/native/meta-drm-buffer.h b/src/backends/native/meta-drm-buffer.h deleted file mode 100644 index d32135591..000000000 --- a/src/backends/native/meta-drm-buffer.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2018 Canonical Ltd. - * Copyright (C) 2019-2020 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Author: Daniel van Vugt - */ - -#ifndef META_DRM_BUFFER_H -#define META_DRM_BUFFER_H - -#include -#include - -#include "cogl/cogl.h" - -#define META_TYPE_DRM_BUFFER (meta_drm_buffer_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaDrmBuffer, - meta_drm_buffer, - META, DRM_BUFFER, - GObject) - -uint32_t meta_drm_buffer_get_fb_id (MetaDrmBuffer *buffer); - -int meta_drm_buffer_get_width (MetaDrmBuffer *buffer); - -int meta_drm_buffer_get_height (MetaDrmBuffer *buffer); - -int meta_drm_buffer_get_stride (MetaDrmBuffer *buffer); - -uint32_t meta_drm_buffer_get_format (MetaDrmBuffer *buffer); - -gboolean meta_drm_buffer_supports_fill_timings (MetaDrmBuffer *buffer); - -gboolean meta_drm_buffer_fill_timings (MetaDrmBuffer *buffer, - CoglFrameInfo *info, - GError **error); - -#endif /* META_DRM_BUFFER_H */ diff --git a/src/backends/native/meta-gpu-kms.c b/src/backends/native/meta-gpu-kms.c deleted file mode 100644 index 97b47f9f9..000000000 --- a/src/backends/native/meta-gpu-kms.c +++ /dev/null @@ -1,422 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 Red Hat - * Copyright (c) 2018 DisplayLink (UK) Ltd. - * - * 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 "backends/native/meta-gpu-kms.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "backends/meta-crtc.h" -#include "backends/meta-monitor-manager-private.h" -#include "backends/meta-output.h" -#include "backends/native/meta-backend-native.h" -#include "backends/native/meta-crtc-kms.h" -#include "backends/native/meta-crtc-mode-kms.h" -#include "backends/native/meta-kms-connector.h" -#include "backends/native/meta-kms-device.h" -#include "backends/native/meta-kms-mode.h" -#include "backends/native/meta-kms-update.h" -#include "backends/native/meta-kms-utils.h" -#include "backends/native/meta-kms.h" -#include "backends/native/meta-launcher.h" -#include "backends/native/meta-output-kms.h" - -struct _MetaGpuKms -{ - MetaGpu parent; - - MetaKmsDevice *kms_device; - - uint32_t id; - int fd; - - gboolean resources_init_failed_before; -}; - -G_DEFINE_TYPE (MetaGpuKms, meta_gpu_kms, META_TYPE_GPU) - -gboolean -meta_gpu_kms_is_crtc_active (MetaGpuKms *gpu_kms, - MetaCrtc *crtc) -{ - MetaGpu *gpu = META_GPU (gpu_kms); - MetaBackend *backend = meta_gpu_get_backend (gpu); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - GList *l; - gboolean connected_crtc_found; - - g_assert (meta_crtc_get_gpu (crtc) == META_GPU (gpu_kms)); - - if (meta_monitor_manager_get_power_save_mode (monitor_manager)) - return FALSE; - - connected_crtc_found = FALSE; - for (l = meta_gpu_get_outputs (gpu); l; l = l->next) - { - MetaOutput *output = l->data; - MetaCrtc *assigned_crtc; - - assigned_crtc = meta_output_get_assigned_crtc (output); - if (assigned_crtc == crtc) - { - connected_crtc_found = TRUE; - break; - } - } - - if (!connected_crtc_found) - return FALSE; - - return TRUE; -} - -MetaKmsDevice * -meta_gpu_kms_get_kms_device (MetaGpuKms *gpu_kms) -{ - return gpu_kms->kms_device; -} - -uint32_t -meta_gpu_kms_get_id (MetaGpuKms *gpu_kms) -{ - return gpu_kms->id; -} - -const char * -meta_gpu_kms_get_file_path (MetaGpuKms *gpu_kms) -{ - return meta_kms_device_get_path (gpu_kms->kms_device); -} - -gboolean -meta_gpu_kms_is_boot_vga (MetaGpuKms *gpu_kms) -{ - MetaKmsDeviceFlag flags; - - flags = meta_kms_device_get_flags (gpu_kms->kms_device); - return !!(flags & META_KMS_DEVICE_FLAG_BOOT_VGA); -} - -gboolean -meta_gpu_kms_is_platform_device (MetaGpuKms *gpu_kms) -{ - MetaKmsDeviceFlag flags; - - flags = meta_kms_device_get_flags (gpu_kms->kms_device); - return !!(flags & META_KMS_DEVICE_FLAG_PLATFORM_DEVICE); -} - -gboolean -meta_gpu_kms_disable_modifiers (MetaGpuKms *gpu_kms) -{ - MetaKmsDeviceFlag flags; - - flags = meta_kms_device_get_flags (gpu_kms->kms_device); - return !!(flags & META_KMS_DEVICE_FLAG_DISABLE_MODIFIERS); -} - -static int -compare_outputs (gconstpointer one, - gconstpointer two) -{ - MetaOutput *o_one = (MetaOutput *) one; - MetaOutput *o_two = (MetaOutput *) two; - const MetaOutputInfo *output_info_one = meta_output_get_info (o_one); - const MetaOutputInfo *output_info_two = meta_output_get_info (o_two); - - return strcmp (output_info_one->name, output_info_two->name); -} - -MetaCrtcMode * -meta_gpu_kms_get_mode_from_kms_mode (MetaGpuKms *gpu_kms, - MetaKmsMode *kms_mode) -{ - MetaGpu *gpu = META_GPU (gpu_kms); - GList *l; - - for (l = meta_gpu_get_modes (gpu); l; l = l->next) - { - MetaCrtcModeKms *crtc_mode_kms = l->data; - - if (meta_kms_mode_equal (kms_mode, - meta_crtc_mode_kms_get_kms_mode (crtc_mode_kms))) - return META_CRTC_MODE (crtc_mode_kms); - } - - g_assert_not_reached (); - return NULL; -} - -static MetaOutput * -find_output_by_connector_id (GList *outputs, - uint32_t connector_id) -{ - GList *l; - - for (l = outputs; l; l = l->next) - { - MetaOutput *output = l->data; - - if (meta_output_kms_get_connector_id (META_OUTPUT_KMS (output)) == - connector_id) - return output; - } - - return NULL; -} - -static void -setup_output_clones (MetaGpu *gpu) -{ - GList *l; - - for (l = meta_gpu_get_outputs (gpu); l; l = l->next) - { - MetaOutput *output = l->data; - GList *k; - - for (k = meta_gpu_get_outputs (gpu); k; k = k->next) - { - MetaOutput *other_output = k->data; - - if (other_output == output) - continue; - - if (meta_output_kms_can_clone (META_OUTPUT_KMS (output), - META_OUTPUT_KMS (other_output))) - meta_output_add_possible_clone (output, other_output); - } - } -} - -static void -init_modes (MetaGpuKms *gpu_kms) -{ - MetaGpu *gpu = META_GPU (gpu_kms); - MetaKmsDevice *kms_device = gpu_kms->kms_device; - GHashTable *modes_table; - GList *l; - GList *modes; - GHashTableIter iter; - gpointer value; - uint64_t mode_id; - - /* - * Gather all modes on all connected connectors. - */ - modes_table = g_hash_table_new ((GHashFunc) meta_kms_mode_hash, - (GEqualFunc) meta_kms_mode_equal); - for (l = meta_kms_device_get_connectors (kms_device); l; l = l->next) - { - MetaKmsConnector *kms_connector = l->data; - const MetaKmsConnectorState *state; - GList *l_mode; - - state = meta_kms_connector_get_current_state (kms_connector); - if (!state) - continue; - - for (l_mode = state->modes; l_mode; l_mode = l_mode->next) - { - MetaKmsMode *kms_mode = l_mode->data; - - g_hash_table_add (modes_table, kms_mode); - } - } - - for (l = meta_kms_device_get_fallback_modes (kms_device); l; l = l->next) - { - MetaKmsMode *fallback_mode = l->data; - - g_hash_table_add (modes_table, fallback_mode); - } - - modes = NULL; - - g_hash_table_iter_init (&iter, modes_table); - mode_id = 0; - while (g_hash_table_iter_next (&iter, NULL, &value)) - { - MetaKmsMode *kms_mode = value; - MetaCrtcModeKms *mode; - - mode = meta_crtc_mode_kms_new (kms_mode, mode_id); - modes = g_list_append (modes, mode); - - mode_id++; - } - - g_hash_table_destroy (modes_table); - - meta_gpu_take_modes (gpu, modes); -} - -static void -init_crtcs (MetaGpuKms *gpu_kms) -{ - MetaGpu *gpu = META_GPU (gpu_kms); - MetaKmsDevice *kms_device = gpu_kms->kms_device; - GList *l; - GList *crtcs; - - crtcs = NULL; - - for (l = meta_kms_device_get_crtcs (kms_device); l; l = l->next) - { - MetaKmsCrtc *kms_crtc = l->data; - MetaCrtcKms *crtc_kms; - - crtc_kms = meta_crtc_kms_new (gpu_kms, kms_crtc); - - crtcs = g_list_append (crtcs, crtc_kms); - } - - meta_gpu_take_crtcs (gpu, crtcs); -} - -static void -init_outputs (MetaGpuKms *gpu_kms) -{ - MetaGpu *gpu = META_GPU (gpu_kms); - GList *old_outputs; - GList *outputs; - GList *l; - - old_outputs = meta_gpu_get_outputs (gpu); - - outputs = NULL; - - for (l = meta_kms_device_get_connectors (gpu_kms->kms_device); l; l = l->next) - { - MetaKmsConnector *kms_connector = l->data; - const MetaKmsConnectorState *connector_state; - MetaOutputKms *output_kms; - MetaOutput *old_output; - GError *error = NULL; - - connector_state = meta_kms_connector_get_current_state (kms_connector); - if (!connector_state || connector_state->non_desktop) - continue; - - old_output = - find_output_by_connector_id (old_outputs, - meta_kms_connector_get_id (kms_connector)); - output_kms = meta_output_kms_new (gpu_kms, - kms_connector, - old_output, - &error); - if (!output_kms) - { - g_warning ("Failed to create KMS output: %s", error->message); - g_error_free (error); - } - else - { - outputs = g_list_prepend (outputs, output_kms); - } - } - - - /* Sort the outputs for easier handling in MetaMonitorConfig */ - outputs = g_list_sort (outputs, compare_outputs); - meta_gpu_take_outputs (gpu, outputs); - - setup_output_clones (gpu); -} - -static gboolean -meta_gpu_kms_read_current (MetaGpu *gpu, - GError **error) -{ - MetaGpuKms *gpu_kms = META_GPU_KMS (gpu); - - /* Note: we must not free the public structures (output, crtc, monitor - mode and monitor info) here, they must be kept alive until the API - users are done with them after we emit monitors-changed, and thus - are freed by the platform-independent layer. */ - - init_modes (gpu_kms); - init_crtcs (gpu_kms); - init_outputs (gpu_kms); - - return TRUE; -} - -gboolean -meta_gpu_kms_can_have_outputs (MetaGpuKms *gpu_kms) -{ - GList *l; - int n_connected_connectors = 0; - - for (l = meta_kms_device_get_connectors (gpu_kms->kms_device); l; l = l->next) - { - MetaKmsConnector *kms_connector = l->data; - - if (meta_kms_connector_get_current_state (kms_connector)) - n_connected_connectors++; - } - - return n_connected_connectors > 0; -} - -MetaGpuKms * -meta_gpu_kms_new (MetaBackendNative *backend_native, - MetaKmsDevice *kms_device, - GError **error) -{ - MetaGpuKms *gpu_kms; - - gpu_kms = g_object_new (META_TYPE_GPU_KMS, - "backend", backend_native, - NULL); - - gpu_kms->kms_device = kms_device; - - meta_gpu_kms_read_current (META_GPU (gpu_kms), NULL); - - return gpu_kms; -} - -static void -meta_gpu_kms_init (MetaGpuKms *gpu_kms) -{ - static uint32_t id = 0; - - gpu_kms->id = ++id; -} - -static void -meta_gpu_kms_class_init (MetaGpuKmsClass *klass) -{ - MetaGpuClass *gpu_class = META_GPU_CLASS (klass); - - gpu_class->read_current = meta_gpu_kms_read_current; -} diff --git a/src/backends/native/meta-gpu-kms.h b/src/backends/native/meta-gpu-kms.h deleted file mode 100644 index 06f6e100a..000000000 --- a/src/backends/native/meta-gpu-kms.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 Red Hat - * Copyright (C) 2018 DisplayLink (UK) Ltd. - * - * 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_GPU_KMS_H -#define META_GPU_KMS_H - -#include -#include -#include - -#include "backends/meta-gpu.h" -#include "backends/native/meta-backend-native.h" -#include "backends/native/meta-kms-types.h" - -#define META_TYPE_GPU_KMS (meta_gpu_kms_get_type ()) -G_DECLARE_FINAL_TYPE (MetaGpuKms, meta_gpu_kms, META, GPU_KMS, MetaGpu) - -typedef struct _MetaGpuKmsFlipClosureContainer MetaGpuKmsFlipClosureContainer; - -MetaGpuKms * meta_gpu_kms_new (MetaBackendNative *backend_native, - MetaKmsDevice *kms_device, - GError **error); - -gboolean meta_gpu_kms_can_have_outputs (MetaGpuKms *gpu_kms); - -gboolean meta_gpu_kms_is_crtc_active (MetaGpuKms *gpu_kms, - MetaCrtc *crtc); - -gboolean meta_gpu_kms_is_boot_vga (MetaGpuKms *gpu_kms); -gboolean meta_gpu_kms_is_platform_device (MetaGpuKms *gpu_kms); -gboolean meta_gpu_kms_disable_modifiers (MetaGpuKms *gpu_kms); - -MetaKmsDevice * meta_gpu_kms_get_kms_device (MetaGpuKms *gpu_kms); - -uint32_t meta_gpu_kms_get_id (MetaGpuKms *gpu_kms); - -const char * meta_gpu_kms_get_file_path (MetaGpuKms *gpu_kms); - -void meta_gpu_kms_set_power_save_mode (MetaGpuKms *gpu_kms, - uint64_t state, - MetaKmsUpdate *kms_update); - -MetaCrtcMode * meta_gpu_kms_get_mode_from_kms_mode (MetaGpuKms *gpu_kms, - MetaKmsMode *kms_mode); - -gboolean meta_drm_mode_equal (const drmModeModeInfo *one, - const drmModeModeInfo *two); - -MetaGpuKmsFlipClosureContainer * meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu_kms, - MetaCrtc *crtc, - GClosure *flip_closure); - -void meta_gpu_kms_flip_closure_container_free (MetaGpuKmsFlipClosureContainer *closure_container); - -#endif /* META_GPU_KMS_H */ diff --git a/src/backends/native/meta-input-device-native.c b/src/backends/native/meta-input-device-native.c deleted file mode 100644 index 468aef557..000000000 --- a/src/backends/native/meta-input-device-native.c +++ /dev/null @@ -1,1599 +0,0 @@ -/* - * Copyright (C) 2010 Intel Corp. - * Copyright (C) 2014 Jonas Ådahl - * - * 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 . - * - * Author: Damien Lespiau - * Author: Jonas Ådahl - */ - -#include "config.h" - -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/native/meta-input-thread.h" -#include "clutter/clutter-mutter.h" - -G_DEFINE_TYPE (MetaInputDeviceNative, - meta_input_device_native, - META_TYPE_INPUT_DEVICE) - -enum -{ - PROP_0, - PROP_DEVICE_MATRIX, - PROP_OUTPUT_ASPECT_RATIO, - N_PROPS -}; - -static GParamSpec *obj_props[N_PROPS] = { 0 }; - -typedef struct _SlowKeysEventPending -{ - MetaInputDeviceNative *device; - ClutterEvent *event; - GSource *timer; -} SlowKeysEventPending; - -typedef struct _PadFeature PadFeature; - -struct _PadFeature -{ - ClutterInputDevicePadFeature feature; - int n_feature; - int group; - gboolean mode_switch; -}; - -static void clear_slow_keys (MetaInputDeviceNative *device); -static void stop_bounce_keys (MetaInputDeviceNative *device); -static void stop_toggle_slowkeys (MetaInputDeviceNative *device); -static void stop_mousekeys_move (MetaInputDeviceNative *device); - -static void -meta_input_device_native_finalize (GObject *object) -{ - MetaInputDeviceNative *device_evdev = META_INPUT_DEVICE_NATIVE (object); - - g_warn_if_fail (!device_evdev->libinput_device); - - clear_slow_keys (device_evdev); - stop_bounce_keys (device_evdev); - stop_toggle_slowkeys (device_evdev); - stop_mousekeys_move (device_evdev); - - g_clear_pointer (&device_evdev->pad_features, g_array_unref); - g_clear_pointer (&device_evdev->modes, g_array_unref); - - G_OBJECT_CLASS (meta_input_device_native_parent_class)->finalize (object); -} - -static void -meta_input_device_native_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaInputDeviceNative *device = META_INPUT_DEVICE_NATIVE (object); - - switch (prop_id) - { - case PROP_DEVICE_MATRIX: - { - const cairo_matrix_t *matrix = g_value_get_boxed (value); - cairo_matrix_init_identity (&device->device_matrix); - cairo_matrix_multiply (&device->device_matrix, - &device->device_matrix, matrix); - break; - } - case PROP_OUTPUT_ASPECT_RATIO: - device->output_ratio = g_value_get_double (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_input_device_native_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaInputDeviceNative *device = META_INPUT_DEVICE_NATIVE (object); - - switch (prop_id) - { - case PROP_DEVICE_MATRIX: - g_value_set_boxed (value, &device->device_matrix); - break; - case PROP_OUTPUT_ASPECT_RATIO: - g_value_set_double (value, device->output_ratio); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static gboolean -meta_input_device_native_is_mode_switch_button (ClutterInputDevice *device, - uint32_t group, - uint32_t button) -{ - MetaInputDeviceNative *device_native = META_INPUT_DEVICE_NATIVE (device); - int i; - - if (!device_native->pad_features) - return FALSE; - - for (i = 0; i < device_native->pad_features->len; i++) - { - PadFeature *pad_feature; - - pad_feature = &g_array_index (device_native->pad_features, PadFeature, i); - - if (pad_feature->feature == CLUTTER_PAD_FEATURE_BUTTON && - pad_feature->group == group && - pad_feature->n_feature == button) - return pad_feature->mode_switch; - } - - return FALSE; -} - -static int -meta_input_device_native_get_group_n_modes (ClutterInputDevice *device, - int group) -{ - MetaInputDeviceNative *device_native = META_INPUT_DEVICE_NATIVE (device); - - if (!device_native->modes || group >= device_native->modes->len) - return -1; - - return g_array_index (device_native->modes, int, group); -} - -static gboolean -meta_input_device_native_is_grouped (ClutterInputDevice *device, - ClutterInputDevice *other_device) -{ - MetaInputDeviceNative *device_native, *other_device_native; - - device_native = META_INPUT_DEVICE_NATIVE (device); - other_device_native = META_INPUT_DEVICE_NATIVE (other_device); - - return device_native->group == other_device_native->group; -} - -static int -meta_input_device_native_get_pad_feature_group (ClutterInputDevice *device, - ClutterInputDevicePadFeature feature, - int n_feature) -{ - MetaInputDeviceNative *device_native = META_INPUT_DEVICE_NATIVE (device); - int i; - - if (!device_native->pad_features) - return -1; - - for (i = 0; i < device_native->pad_features->len; i++) - { - PadFeature *pad_feature; - - pad_feature = &g_array_index (device_native->pad_features, PadFeature, i); - - if (pad_feature->feature == feature && - pad_feature->n_feature == n_feature) - return pad_feature->group; - } - - return -1; -} - -static void -meta_input_device_native_bell_notify (MetaInputDeviceNative *device) -{ - meta_seat_impl_notify_bell_in_impl (device->seat_impl); -} - -static void -meta_input_device_native_free_pending_slow_key (gpointer data) -{ - SlowKeysEventPending *slow_keys_event = data; - - clutter_event_free (slow_keys_event->event); - g_clear_pointer (&slow_keys_event->timer, g_source_destroy); - g_free (slow_keys_event); -} - -static void -clear_slow_keys (MetaInputDeviceNative *device) -{ - g_list_free_full (device->slow_keys_list, meta_input_device_native_free_pending_slow_key); - g_list_free (device->slow_keys_list); - device->slow_keys_list = NULL; -} - -static guint -get_slow_keys_delay (ClutterInputDevice *device) -{ - MetaInputDeviceNative *device_native = META_INPUT_DEVICE_NATIVE (device); - MetaKbdA11ySettings a11y_settings; - MetaInputSettings *input_settings; - - input_settings = meta_seat_impl_get_input_settings (device_native->seat_impl); - meta_input_settings_get_kbd_a11y_settings (input_settings, &a11y_settings); - /* Settings use int, we use uint, make sure we dont go negative */ - return MAX (0, a11y_settings.slowkeys_delay); -} - -static gboolean -trigger_slow_keys (gpointer data) -{ - SlowKeysEventPending *slow_keys_event = data; - MetaInputDeviceNative *device = slow_keys_event->device; - ClutterKeyEvent *key_event = (ClutterKeyEvent *) slow_keys_event->event; - - /* Alter timestamp and emit the event */ - key_event->time = us2ms (g_get_monotonic_time ()); - _clutter_event_push (slow_keys_event->event, TRUE); - - /* Then remote the pending event */ - device->slow_keys_list = g_list_remove (device->slow_keys_list, slow_keys_event); - meta_input_device_native_free_pending_slow_key (slow_keys_event); - - if (device->a11y_flags & META_A11Y_SLOW_KEYS_BEEP_ACCEPT) - meta_input_device_native_bell_notify (device); - - return G_SOURCE_REMOVE; -} - -static int -find_pending_event_by_keycode (gconstpointer a, - gconstpointer b) -{ - const SlowKeysEventPending *pa = a; - const ClutterKeyEvent *ka = (ClutterKeyEvent *) pa->event; - const ClutterKeyEvent *kb = b; - - return kb->hardware_keycode - ka->hardware_keycode; -} - -static GSource * -timeout_source_new (MetaSeatImpl *seat_impl, - guint interval, - GSourceFunc func, - gpointer user_data) -{ - GSource *source; - - source = g_timeout_source_new (interval); - g_source_set_callback (source, - func, - user_data, NULL); - g_source_attach (source, seat_impl->input_context); - g_source_unref (source); - - return source; -} - -static gboolean -start_slow_keys (ClutterEvent *event, - MetaInputDeviceNative *device) -{ - SlowKeysEventPending *slow_keys_event; - ClutterKeyEvent *key_event = (ClutterKeyEvent *) event; - - if (key_event->flags & CLUTTER_EVENT_FLAG_REPEATED) - return TRUE; - - slow_keys_event = g_new0 (SlowKeysEventPending, 1); - slow_keys_event->device = device; - slow_keys_event->event = clutter_event_copy (event); - slow_keys_event->timer = - timeout_source_new (device->seat_impl, - get_slow_keys_delay (CLUTTER_INPUT_DEVICE (device)), - trigger_slow_keys, - slow_keys_event); - device->slow_keys_list = g_list_append (device->slow_keys_list, slow_keys_event); - - if (device->a11y_flags & META_A11Y_SLOW_KEYS_BEEP_PRESS) - meta_input_device_native_bell_notify (device); - - return TRUE; -} - -static gboolean -stop_slow_keys (ClutterEvent *event, - MetaInputDeviceNative *device) -{ - GList *item; - - /* Check if we have a slow key event queued for this key event */ - item = g_list_find_custom (device->slow_keys_list, event, find_pending_event_by_keycode); - if (item) - { - SlowKeysEventPending *slow_keys_event = item->data; - - device->slow_keys_list = g_list_delete_link (device->slow_keys_list, item); - meta_input_device_native_free_pending_slow_key (slow_keys_event); - - if (device->a11y_flags & META_A11Y_SLOW_KEYS_BEEP_REJECT) - meta_input_device_native_bell_notify (device); - - return TRUE; - } - - /* If no key press event was pending, just emit the key release as-is */ - return FALSE; -} - -static guint -get_debounce_delay (ClutterInputDevice *device) -{ - MetaInputDeviceNative *device_native = META_INPUT_DEVICE_NATIVE (device); - MetaKbdA11ySettings a11y_settings; - MetaInputSettings *input_settings; - - input_settings = meta_seat_impl_get_input_settings (device_native->seat_impl); - meta_input_settings_get_kbd_a11y_settings (input_settings, &a11y_settings); - /* Settings use int, we use uint, make sure we dont go negative */ - return MAX (0, a11y_settings.debounce_delay); -} - -static gboolean -clear_bounce_keys (gpointer data) -{ - MetaInputDeviceNative *device = data; - - device->debounce_key = 0; - device->debounce_timer = 0; - - return G_SOURCE_REMOVE; -} - -static void -start_bounce_keys (ClutterEvent *event, - MetaInputDeviceNative *device) -{ - stop_bounce_keys (device); - - device->debounce_key = ((ClutterKeyEvent *) event)->hardware_keycode; - device->debounce_timer = - timeout_source_new (device->seat_impl, - get_debounce_delay (CLUTTER_INPUT_DEVICE (device)), - clear_bounce_keys, - device); -} - -static void -stop_bounce_keys (MetaInputDeviceNative *device) -{ - g_clear_pointer (&device->debounce_timer, g_source_destroy); -} - -static void -notify_bounce_keys_reject (MetaInputDeviceNative *device) -{ - if (device->a11y_flags & META_A11Y_BOUNCE_KEYS_BEEP_REJECT) - meta_input_device_native_bell_notify (device); -} - -static gboolean -debounce_key (ClutterEvent *event, - MetaInputDeviceNative *device) -{ - return (device->debounce_key == ((ClutterKeyEvent *) event)->hardware_keycode); -} - -static gboolean -key_event_is_modifier (ClutterEvent *event) -{ - switch (event->key.keyval) - { - case XKB_KEY_Shift_L: - case XKB_KEY_Shift_R: - case XKB_KEY_Control_L: - case XKB_KEY_Control_R: - case XKB_KEY_Alt_L: - case XKB_KEY_Alt_R: - case XKB_KEY_Meta_L: - case XKB_KEY_Meta_R: - case XKB_KEY_Super_L: - case XKB_KEY_Super_R: - case XKB_KEY_Hyper_L: - case XKB_KEY_Hyper_R: - case XKB_KEY_Caps_Lock: - case XKB_KEY_Shift_Lock: - return TRUE; - default: - return FALSE; - } -} - -static void -notify_stickykeys_mask (MetaInputDeviceNative *device) -{ - meta_seat_impl_notify_kbd_a11y_mods_state_changed_in_impl (device->seat_impl, - device->stickykeys_latched_mask, - device->stickykeys_locked_mask); -} - -static void -update_internal_xkb_state (MetaInputDeviceNative *device, - xkb_mod_mask_t new_latched_mask, - xkb_mod_mask_t new_locked_mask) -{ - MetaSeatImpl *seat_impl = device->seat_impl; - xkb_mod_mask_t depressed_mods; - xkb_mod_mask_t latched_mods; - xkb_mod_mask_t locked_mods; - xkb_mod_mask_t group_mods; - struct xkb_state *xkb_state; - - g_rw_lock_writer_lock (&seat_impl->state_lock); - - xkb_state = meta_seat_impl_get_xkb_state_in_impl (seat_impl); - depressed_mods = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_DEPRESSED); - latched_mods = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_LATCHED); - locked_mods = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_LOCKED); - - latched_mods &= ~device->stickykeys_latched_mask; - locked_mods &= ~device->stickykeys_locked_mask; - - device->stickykeys_latched_mask = new_latched_mask; - device->stickykeys_locked_mask = new_locked_mask; - - latched_mods |= device->stickykeys_latched_mask; - locked_mods |= device->stickykeys_locked_mask; - - group_mods = xkb_state_serialize_layout (xkb_state, XKB_STATE_LAYOUT_EFFECTIVE); - - xkb_state_update_mask (xkb_state, - depressed_mods, - latched_mods, - locked_mods, - 0, 0, group_mods); - notify_stickykeys_mask (device); - - g_rw_lock_writer_unlock (&seat_impl->state_lock); -} - -static void -update_stickykeys_event (ClutterEvent *event, - MetaInputDeviceNative *device, - xkb_mod_mask_t new_latched_mask, - xkb_mod_mask_t new_locked_mask) -{ - MetaSeatImpl *seat_impl = device->seat_impl; - xkb_mod_mask_t effective_mods; - xkb_mod_mask_t latched_mods; - xkb_mod_mask_t locked_mods; - struct xkb_state *xkb_state; - - update_internal_xkb_state (device, new_latched_mask, new_locked_mask); - - xkb_state = meta_seat_impl_get_xkb_state_in_impl (seat_impl); - effective_mods = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_EFFECTIVE); - latched_mods = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_LATCHED); - locked_mods = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_LOCKED); - - _clutter_event_set_state_full (event, - seat_impl->button_state, - device->stickykeys_depressed_mask, - latched_mods, - locked_mods, - effective_mods | seat_impl->button_state); -} - -static void -notify_stickykeys_change (MetaInputDeviceNative *device) -{ - /* Every time sticky keys setting is changed, clear the masks */ - device->stickykeys_depressed_mask = 0; - update_internal_xkb_state (device, 0, 0); - - meta_seat_impl_notify_kbd_a11y_flags_changed_in_impl (device->seat_impl, - device->a11y_flags, - META_A11Y_STICKY_KEYS_ENABLED); -} - -static void -set_stickykeys_off (MetaInputDeviceNative *device) -{ - device->a11y_flags &= ~META_A11Y_STICKY_KEYS_ENABLED; - notify_stickykeys_change (device); -} - -static void -set_stickykeys_on (MetaInputDeviceNative *device) -{ - device->a11y_flags |= META_A11Y_STICKY_KEYS_ENABLED; - notify_stickykeys_change (device); -} - -static void -clear_stickykeys_event (ClutterEvent *event, - MetaInputDeviceNative *device) -{ - set_stickykeys_off (device); - update_stickykeys_event (event, device, 0, 0); -} - -static void -set_slowkeys_off (MetaInputDeviceNative *device) -{ - device->a11y_flags &= ~META_A11Y_SLOW_KEYS_ENABLED; - - meta_seat_impl_notify_kbd_a11y_flags_changed_in_impl (device->seat_impl, - device->a11y_flags, - META_A11Y_SLOW_KEYS_ENABLED); -} - -static void -set_slowkeys_on (MetaInputDeviceNative *device) -{ - device->a11y_flags |= META_A11Y_SLOW_KEYS_ENABLED; - - meta_seat_impl_notify_kbd_a11y_flags_changed_in_impl (device->seat_impl, - device->a11y_flags, - META_A11Y_SLOW_KEYS_ENABLED); -} - -static void -handle_stickykeys_press (ClutterEvent *event, - MetaInputDeviceNative *device) -{ - MetaSeatImpl *seat_impl = device->seat_impl; - xkb_mod_mask_t depressed_mods; - xkb_mod_mask_t new_latched_mask; - xkb_mod_mask_t new_locked_mask; - struct xkb_state *xkb_state; - - if (!key_event_is_modifier (event)) - return; - - if (device->stickykeys_depressed_mask && - (device->a11y_flags & META_A11Y_STICKY_KEYS_TWO_KEY_OFF)) - { - clear_stickykeys_event (event, device); - return; - } - - xkb_state = meta_seat_impl_get_xkb_state_in_impl (seat_impl); - depressed_mods = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_DEPRESSED); - /* Ignore the lock modifier mask, that one cannot be sticky, yet the - * CAPS_LOCK key itself counts as a modifier as it might be remapped - * to some other modifier which can be sticky. - */ - depressed_mods &= ~CLUTTER_LOCK_MASK; - - new_latched_mask = device->stickykeys_latched_mask; - new_locked_mask = device->stickykeys_locked_mask; - - device->stickykeys_depressed_mask = depressed_mods; - - if (new_locked_mask & depressed_mods) - { - new_locked_mask &= ~depressed_mods; - } - else if (new_latched_mask & depressed_mods) - { - new_locked_mask |= depressed_mods; - new_latched_mask &= ~depressed_mods; - } - else - { - new_latched_mask |= depressed_mods; - } - - update_stickykeys_event (event, device, new_latched_mask, new_locked_mask); -} - -static void -handle_stickykeys_release (ClutterEvent *event, - MetaInputDeviceNative *device) -{ - MetaSeatImpl *seat_impl = device->seat_impl; - struct xkb_state *xkb_state; - - xkb_state = meta_seat_impl_get_xkb_state_in_impl (seat_impl); - device->stickykeys_depressed_mask = - xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_DEPRESSED); - - if (key_event_is_modifier (event)) - { - if (device->a11y_flags & META_A11Y_STICKY_KEYS_BEEP) - meta_input_device_native_bell_notify (device); - - return; - } - - if (device->stickykeys_latched_mask == 0) - return; - - update_stickykeys_event (event, device, 0, device->stickykeys_locked_mask); -} - -static gboolean -trigger_toggle_slowkeys (gpointer data) -{ - MetaInputDeviceNative *device = data; - - device->toggle_slowkeys_timer = 0; - - if (device->a11y_flags & META_A11Y_FEATURE_STATE_CHANGE_BEEP) - meta_input_device_native_bell_notify (device); - - if (device->a11y_flags & META_A11Y_SLOW_KEYS_ENABLED) - set_slowkeys_off (device); - else - set_slowkeys_on (device); - - return G_SOURCE_REMOVE; -} - -static void -start_toggle_slowkeys (MetaInputDeviceNative *device) -{ - if (device->toggle_slowkeys_timer != 0) - return; - - device->toggle_slowkeys_timer = - timeout_source_new (device->seat_impl, - 8 * 1000 /* 8 secs */, - trigger_toggle_slowkeys, - device); -} - -static void -stop_toggle_slowkeys (MetaInputDeviceNative *device) -{ - g_clear_pointer (&device->toggle_slowkeys_timer, g_source_destroy); -} - -static void -handle_enablekeys_press (ClutterEvent *event, - MetaInputDeviceNative *device) -{ - if (event->key.keyval == XKB_KEY_Shift_L || event->key.keyval == XKB_KEY_Shift_R) - { - start_toggle_slowkeys (device); - - if (event->key.time > device->last_shift_time + 15 * 1000 /* 15 secs */) - device->shift_count = 1; - else - device->shift_count++; - - device->last_shift_time = event->key.time; - } - else - { - device->shift_count = 0; - stop_toggle_slowkeys (device); - } -} - -static void -handle_enablekeys_release (ClutterEvent *event, - MetaInputDeviceNative *device) -{ - if (event->key.keyval == XKB_KEY_Shift_L || event->key.keyval == XKB_KEY_Shift_R) - { - stop_toggle_slowkeys (device); - if (device->shift_count >= 5) - { - device->shift_count = 0; - - if (device->a11y_flags & META_A11Y_FEATURE_STATE_CHANGE_BEEP) - meta_input_device_native_bell_notify (device); - - if (device->a11y_flags & META_A11Y_STICKY_KEYS_ENABLED) - set_stickykeys_off (device); - else - set_stickykeys_on (device); - } - } -} - -static int -get_button_index (int button) -{ - switch (button) - { - case CLUTTER_BUTTON_PRIMARY: - return 0; - case CLUTTER_BUTTON_MIDDLE: - return 1; - case CLUTTER_BUTTON_SECONDARY: - return 2; - default: - break; - } - - g_warn_if_reached (); - return 0; -} - -static void -emulate_button_press (MetaInputDeviceNative *device_evdev) -{ - ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_evdev); - int btn = device_evdev->mousekeys_btn; - - if (device_evdev->mousekeys_btn_states[get_button_index (btn)]) - return; - - clutter_virtual_input_device_notify_button (device->accessibility_virtual_device, - g_get_monotonic_time (), btn, - CLUTTER_BUTTON_STATE_PRESSED); - device_evdev->mousekeys_btn_states[get_button_index (btn)] = CLUTTER_BUTTON_STATE_PRESSED; -} - -static void -emulate_button_release (MetaInputDeviceNative *device_evdev) -{ - ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_evdev); - int btn = device_evdev->mousekeys_btn; - - if (device_evdev->mousekeys_btn_states[get_button_index (btn)] == CLUTTER_BUTTON_STATE_RELEASED) - return; - - clutter_virtual_input_device_notify_button (device->accessibility_virtual_device, - g_get_monotonic_time (), btn, - CLUTTER_BUTTON_STATE_RELEASED); - device_evdev->mousekeys_btn_states[get_button_index (btn)] = CLUTTER_BUTTON_STATE_RELEASED; -} - -static void -emulate_button_click (MetaInputDeviceNative *device) -{ - emulate_button_press (device); - emulate_button_release (device); -} - -#define MOUSEKEYS_CURVE (1.0 + (((double) 50.0) * 0.001)) - -static void -update_mousekeys_params (MetaInputDeviceNative *device, - MetaKbdA11ySettings *settings) -{ - /* Prevent us from broken settings values */ - device->mousekeys_max_speed = MAX (1, settings->mousekeys_max_speed); - device->mousekeys_accel_time = MAX (1, settings->mousekeys_accel_time); - device->mousekeys_init_delay = MAX (0, settings->mousekeys_init_delay); - - device->mousekeys_curve_factor = - (((double) device->mousekeys_max_speed) / - pow ((double) device->mousekeys_accel_time, MOUSEKEYS_CURVE)); -} - -static double -mousekeys_get_speed_factor (MetaInputDeviceNative *device, - uint64_t time_us) -{ - uint32_t time; - int64_t delta_t; - int64_t init_time; - double speed; - - time = us2ms (time_us); - - if (device->mousekeys_first_motion_time == 0) - { - /* Start acceleration _after_ the first move, so take - * mousekeys_init_delay into account for t0 - */ - device->mousekeys_first_motion_time = time + device->mousekeys_init_delay; - device->mousekeys_last_motion_time = device->mousekeys_first_motion_time; - return 1.0; - } - - init_time = time - device->mousekeys_first_motion_time; - delta_t = time - device->mousekeys_last_motion_time; - - if (delta_t < 0) - return 0.0; - - if (init_time < device->mousekeys_accel_time) - speed = (double) (device->mousekeys_curve_factor * - pow ((double) init_time, MOUSEKEYS_CURVE) * delta_t / 1000.0); - else - speed = (double) (device->mousekeys_max_speed * delta_t / 1000.0); - - device->mousekeys_last_motion_time = time; - - return speed; -} - -#undef MOUSEKEYS_CURVE - -static void -emulate_pointer_motion (MetaInputDeviceNative *device_evdev, - int dx, - int dy) -{ - ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_evdev); - double dx_motion; - double dy_motion; - double speed; - int64_t time_us; - - time_us = g_get_monotonic_time (); - speed = mousekeys_get_speed_factor (device_evdev, time_us); - - if (dx < 0) - dx_motion = floor (((double) dx) * speed); - else - dx_motion = ceil (((double) dx) * speed); - - if (dy < 0) - dy_motion = floor (((double) dy) * speed); - else - dy_motion = ceil (((double) dy) * speed); - - clutter_virtual_input_device_notify_relative_motion (device->accessibility_virtual_device, - time_us, dx_motion, dy_motion); -} -static gboolean -is_numlock_active (MetaInputDeviceNative *device) -{ - MetaSeatImpl *seat_impl = device->seat_impl; - struct xkb_state *xkb_state; - - xkb_state = meta_seat_impl_get_xkb_state_in_impl (seat_impl); - - return xkb_state_mod_name_is_active (xkb_state, - "Mod2", - XKB_STATE_MODS_LOCKED); -} - -static void -enable_mousekeys (MetaInputDeviceNative *device_evdev) -{ - ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_evdev); - - 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->accessibility_virtual_device) - return; - - device->accessibility_virtual_device = - clutter_seat_create_virtual_device (clutter_input_device_get_seat (device), - CLUTTER_POINTER_DEVICE); -} - -static void -disable_mousekeys (MetaInputDeviceNative *device_evdev) -{ - ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_evdev); - - stop_mousekeys_move (device_evdev); - - /* Make sure we don't leave button pressed behind... */ - if (device_evdev->mousekeys_btn_states[get_button_index (CLUTTER_BUTTON_PRIMARY)]) - { - device_evdev->mousekeys_btn = CLUTTER_BUTTON_PRIMARY; - emulate_button_release (device_evdev); - } - - if (device_evdev->mousekeys_btn_states[get_button_index (CLUTTER_BUTTON_MIDDLE)]) - { - device_evdev->mousekeys_btn = CLUTTER_BUTTON_MIDDLE; - emulate_button_release (device_evdev); - } - - if (device_evdev->mousekeys_btn_states[get_button_index (CLUTTER_BUTTON_SECONDARY)]) - { - device_evdev->mousekeys_btn = CLUTTER_BUTTON_SECONDARY; - emulate_button_release (device_evdev); - } - - if (device->accessibility_virtual_device) - g_clear_object (&device->accessibility_virtual_device); -} - -static gboolean -trigger_mousekeys_move (gpointer data) -{ - MetaInputDeviceNative *device = data; - int dx = 0; - int dy = 0; - - if (device->mousekeys_first_motion_time == 0) - { - /* This is the first move, Secdule at mk_init_delay */ - device->move_mousekeys_timer = - timeout_source_new (device->seat_impl, - device->mousekeys_init_delay, - trigger_mousekeys_move, - device); - - } - else - { - /* More moves, reschedule at mk_interval */ - device->move_mousekeys_timer = - timeout_source_new (device->seat_impl, - 100, /* msec between mousekey events */ - trigger_mousekeys_move, - device); - } - - /* Pointer motion */ - switch (device->last_mousekeys_key) - { - case XKB_KEY_KP_Home: - case XKB_KEY_KP_7: - case XKB_KEY_KP_Up: - case XKB_KEY_KP_8: - case XKB_KEY_KP_Page_Up: - case XKB_KEY_KP_9: - dy = -1; - break; - case XKB_KEY_KP_End: - case XKB_KEY_KP_1: - case XKB_KEY_KP_Down: - case XKB_KEY_KP_2: - case XKB_KEY_KP_Page_Down: - case XKB_KEY_KP_3: - dy = 1; - break; - default: - break; - } - - switch (device->last_mousekeys_key) - { - case XKB_KEY_KP_Home: - case XKB_KEY_KP_7: - case XKB_KEY_KP_Left: - case XKB_KEY_KP_4: - case XKB_KEY_KP_End: - case XKB_KEY_KP_1: - dx = -1; - break; - case XKB_KEY_KP_Page_Up: - case XKB_KEY_KP_9: - case XKB_KEY_KP_Right: - case XKB_KEY_KP_6: - case XKB_KEY_KP_Page_Down: - case XKB_KEY_KP_3: - dx = 1; - break; - default: - break; - } - - if (dx != 0 || dy != 0) - emulate_pointer_motion (device, dx, dy); - - /* We reschedule each time */ - return G_SOURCE_REMOVE; -} - -static void -stop_mousekeys_move (MetaInputDeviceNative *device) -{ - device->mousekeys_first_motion_time = 0; - device->mousekeys_last_motion_time = 0; - - g_clear_pointer (&device->move_mousekeys_timer, g_source_destroy); -} - -static void -start_mousekeys_move (ClutterEvent *event, - MetaInputDeviceNative *device) -{ - device->last_mousekeys_key = event->key.keyval; - - if (device->move_mousekeys_timer != 0) - return; - - trigger_mousekeys_move (device); -} - -static gboolean -handle_mousekeys_press (ClutterEvent *event, - MetaInputDeviceNative *device) -{ - if (!(event->key.flags & CLUTTER_EVENT_FLAG_SYNTHETIC)) - stop_mousekeys_move (device); - - /* Do not handle mousekeys if NumLock is ON */ - if (is_numlock_active (device)) - return FALSE; - - /* Button selection */ - switch (event->key.keyval) - { - case XKB_KEY_KP_Divide: - device->mousekeys_btn = CLUTTER_BUTTON_PRIMARY; - return TRUE; - case XKB_KEY_KP_Multiply: - device->mousekeys_btn = CLUTTER_BUTTON_MIDDLE; - return TRUE; - case XKB_KEY_KP_Subtract: - device->mousekeys_btn = CLUTTER_BUTTON_SECONDARY; - return TRUE; - default: - break; - } - - /* Button events */ - switch (event->key.keyval) - { - case XKB_KEY_KP_Begin: - case XKB_KEY_KP_5: - emulate_button_click (device); - return TRUE; - case XKB_KEY_KP_Insert: - case XKB_KEY_KP_0: - emulate_button_press (device); - return TRUE; - case XKB_KEY_KP_Decimal: - case XKB_KEY_KP_Delete: - emulate_button_release (device); - return TRUE; - case XKB_KEY_KP_Add: - emulate_button_click (device); - emulate_button_click (device); - return TRUE; - default: - break; - } - - /* Pointer motion */ - switch (event->key.keyval) - { - case XKB_KEY_KP_1: - case XKB_KEY_KP_2: - case XKB_KEY_KP_3: - case XKB_KEY_KP_4: - case XKB_KEY_KP_6: - case XKB_KEY_KP_7: - case XKB_KEY_KP_8: - case XKB_KEY_KP_9: - case XKB_KEY_KP_Down: - case XKB_KEY_KP_End: - case XKB_KEY_KP_Home: - case XKB_KEY_KP_Left: - case XKB_KEY_KP_Page_Down: - case XKB_KEY_KP_Page_Up: - case XKB_KEY_KP_Right: - case XKB_KEY_KP_Up: - start_mousekeys_move (event, device); - return TRUE; - default: - break; - } - - return FALSE; -} - -static gboolean -handle_mousekeys_release (ClutterEvent *event, - MetaInputDeviceNative *device) -{ - /* Do not handle mousekeys if NumLock is ON */ - if (is_numlock_active (device)) - return FALSE; - - switch (event->key.keyval) - { - case XKB_KEY_KP_0: - case XKB_KEY_KP_1: - case XKB_KEY_KP_2: - case XKB_KEY_KP_3: - case XKB_KEY_KP_4: - case XKB_KEY_KP_5: - case XKB_KEY_KP_6: - case XKB_KEY_KP_7: - case XKB_KEY_KP_8: - case XKB_KEY_KP_9: - case XKB_KEY_KP_Add: - case XKB_KEY_KP_Begin: - case XKB_KEY_KP_Decimal: - case XKB_KEY_KP_Delete: - case XKB_KEY_KP_Divide: - case XKB_KEY_KP_Down: - case XKB_KEY_KP_End: - case XKB_KEY_KP_Home: - case XKB_KEY_KP_Insert: - case XKB_KEY_KP_Left: - case XKB_KEY_KP_Multiply: - case XKB_KEY_KP_Page_Down: - case XKB_KEY_KP_Page_Up: - case XKB_KEY_KP_Right: - case XKB_KEY_KP_Subtract: - case XKB_KEY_KP_Up: - stop_mousekeys_move (device); - return TRUE; - default: - break; - } - - return FALSE; -} - -gboolean -meta_input_device_native_process_kbd_a11y_event_in_impl (ClutterInputDevice *device, - ClutterEvent *event) -{ - MetaInputDeviceNative *device_evdev = META_INPUT_DEVICE_NATIVE (device); - - if (device_evdev->a11y_flags & META_A11Y_KEYBOARD_ENABLED) - { - if (event->type == CLUTTER_KEY_PRESS) - handle_enablekeys_press (event, device_evdev); - else - handle_enablekeys_release (event, device_evdev); - } - - if (device_evdev->a11y_flags & META_A11Y_MOUSE_KEYS_ENABLED) - { - if (event->type == CLUTTER_KEY_PRESS && - handle_mousekeys_press (event, device_evdev)) - return TRUE; /* swallow event */ - if (event->type == CLUTTER_KEY_RELEASE && - handle_mousekeys_release (event, device_evdev)) - return TRUE; /* swallow event */ - } - - if ((device_evdev->a11y_flags & META_A11Y_BOUNCE_KEYS_ENABLED) && - (get_debounce_delay (device) != 0)) - { - if ((event->type == CLUTTER_KEY_PRESS) && debounce_key (event, device_evdev)) - { - notify_bounce_keys_reject (device_evdev); - - return TRUE; - } - else if (event->type == CLUTTER_KEY_RELEASE) - start_bounce_keys (event, device_evdev); - } - - if ((device_evdev->a11y_flags & META_A11Y_SLOW_KEYS_ENABLED) && - (get_slow_keys_delay (device) != 0)) - { - if (event->type == CLUTTER_KEY_PRESS) - return start_slow_keys (event, device_evdev); - else if (event->type == CLUTTER_KEY_RELEASE) - return stop_slow_keys (event, device_evdev); - } - - if (device_evdev->a11y_flags & META_A11Y_STICKY_KEYS_ENABLED) - { - if (event->type == CLUTTER_KEY_PRESS) - handle_stickykeys_press (event, device_evdev); - else if (event->type == CLUTTER_KEY_RELEASE) - handle_stickykeys_release (event, device_evdev); - } - - return FALSE; -} - -void -meta_input_device_native_apply_kbd_a11y_settings_in_impl (MetaInputDeviceNative *device, - MetaKbdA11ySettings *settings) -{ - MetaKeyboardA11yFlags changed_flags = (device->a11y_flags ^ settings->controls); - - if (changed_flags & (META_A11Y_KEYBOARD_ENABLED | META_A11Y_SLOW_KEYS_ENABLED)) - clear_slow_keys (device); - - if (changed_flags & (META_A11Y_KEYBOARD_ENABLED | META_A11Y_BOUNCE_KEYS_ENABLED)) - device->debounce_key = 0; - - if (changed_flags & (META_A11Y_KEYBOARD_ENABLED | META_A11Y_STICKY_KEYS_ENABLED)) - { - device->stickykeys_depressed_mask = 0; - update_internal_xkb_state (device, 0, 0); - } - - if (changed_flags & META_A11Y_KEYBOARD_ENABLED) - { - device->toggle_slowkeys_timer = 0; - device->shift_count = 0; - device->last_shift_time = 0; - } - - if (changed_flags & (META_A11Y_KEYBOARD_ENABLED | META_A11Y_MOUSE_KEYS_ENABLED)) - { - if (settings->controls & - (META_A11Y_KEYBOARD_ENABLED | META_A11Y_MOUSE_KEYS_ENABLED)) - enable_mousekeys (device); - else - disable_mousekeys (device); - } - update_mousekeys_params (device, settings); - - /* Keep our own copy of keyboard a11y features flags to see what changes */ - device->a11y_flags = settings->controls; -} - -void -meta_input_device_native_a11y_maybe_notify_toggle_keys_in_impl (MetaInputDeviceNative *device) -{ - if (device->a11y_flags & META_A11Y_TOGGLE_KEYS_ENABLED) - meta_input_device_native_bell_notify (device); -} - -static void -meta_input_device_native_class_init (MetaInputDeviceNativeClass *klass) -{ - ClutterInputDeviceClass *device_class = CLUTTER_INPUT_DEVICE_CLASS (klass); - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_input_device_native_finalize; - object_class->set_property = meta_input_device_native_set_property; - object_class->get_property = meta_input_device_native_get_property; - - device_class->is_mode_switch_button = meta_input_device_native_is_mode_switch_button; - device_class->get_group_n_modes = meta_input_device_native_get_group_n_modes; - device_class->is_grouped = meta_input_device_native_is_grouped; - device_class->get_pad_feature_group = meta_input_device_native_get_pad_feature_group; - - obj_props[PROP_DEVICE_MATRIX] = - g_param_spec_boxed ("device-matrix", - "Device input matrix", - "Device input matrix", - CAIRO_GOBJECT_TYPE_MATRIX, - CLUTTER_PARAM_READWRITE); - obj_props[PROP_OUTPUT_ASPECT_RATIO] = - g_param_spec_double ("output-aspect-ratio", - "Output aspect ratio", - "Output aspect ratio", - 0, G_MAXDOUBLE, 0, - CLUTTER_PARAM_READWRITE); - - g_object_class_install_properties (object_class, N_PROPS, obj_props); -} - -static void -meta_input_device_native_init (MetaInputDeviceNative *self) -{ - cairo_matrix_init_identity (&self->device_matrix); - self->device_aspect_ratio = 0; - self->output_ratio = 0; -} - -static void -update_pad_features (MetaInputDeviceNative *device_native) -{ - ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (device_native); - struct libinput_device *libinput_device; - struct libinput_tablet_pad_mode_group *mode_group; - int n_groups, n_buttons, n_rings, n_strips, n_modes, i, j; - - libinput_device = meta_input_device_native_get_libinput_device (device); - n_rings = libinput_device_tablet_pad_get_num_rings (libinput_device); - n_strips = libinput_device_tablet_pad_get_num_strips (libinput_device); - n_groups = libinput_device_tablet_pad_get_num_mode_groups (libinput_device); - n_buttons = libinput_device_tablet_pad_get_num_buttons (libinput_device); - - device_native->pad_features = g_array_new (FALSE, FALSE, sizeof (PadFeature)); - device_native->modes = g_array_sized_new (FALSE, FALSE, sizeof (int), n_groups); - - for (i = 0; i < n_groups; i++) - { - mode_group = - libinput_device_tablet_pad_get_mode_group (libinput_device, i); - - n_modes = libinput_tablet_pad_mode_group_get_num_modes (mode_group); - g_array_append_val (device_native->modes, n_modes); - - for (j = 0; j < n_buttons; j++) - { - gboolean is_mode_switch = - libinput_tablet_pad_mode_group_button_is_toggle (mode_group, j) != 0; - PadFeature feature = { CLUTTER_PAD_FEATURE_BUTTON, j, i, is_mode_switch }; - - if (libinput_tablet_pad_mode_group_has_button (mode_group, j)) - g_array_append_val (device_native->pad_features, feature); - } - - for (j = 0; j < n_rings; j++) - { - PadFeature feature = { CLUTTER_PAD_FEATURE_RING, j, i }; - - if (libinput_tablet_pad_mode_group_has_ring (mode_group, j)) - g_array_append_val (device_native->pad_features, feature); - } - - for (j = 0; j < n_strips; j++) - { - PadFeature feature = { CLUTTER_PAD_FEATURE_STRIP, j, i }; - - if (libinput_tablet_pad_mode_group_has_strip (mode_group, j)) - g_array_append_val (device_native->pad_features, feature); - } - } -} - -/* - * meta_input_device_native_new: - * @manager: the device manager - * @seat: the seat the device will belong to - * @libinput_device: the libinput device - * - * Create a new ClutterInputDevice given a libinput device and associate - * it with the provided seat. - */ -ClutterInputDevice * -meta_input_device_native_new_in_impl (MetaSeatImpl *seat_impl, - struct libinput_device *libinput_device) -{ - MetaInputDeviceNative *device; - ClutterInputDeviceType type; - char *vendor, *product; - int n_rings = 0, n_strips = 0, n_groups = 1, n_buttons = 0; - char *node_path; - double width, height; - - type = meta_input_device_native_determine_type_in_impl (libinput_device); - vendor = g_strdup_printf ("%.4x", libinput_device_get_id_vendor (libinput_device)); - product = g_strdup_printf ("%.4x", libinput_device_get_id_product (libinput_device)); - node_path = g_strdup_printf ("/dev/input/%s", libinput_device_get_sysname (libinput_device)); - - if (libinput_device_has_capability (libinput_device, - LIBINPUT_DEVICE_CAP_TABLET_PAD)) - { - n_rings = libinput_device_tablet_pad_get_num_rings (libinput_device); - n_strips = libinput_device_tablet_pad_get_num_strips (libinput_device); - n_groups = libinput_device_tablet_pad_get_num_mode_groups (libinput_device); - n_buttons = libinput_device_tablet_pad_get_num_buttons (libinput_device); - } - - device = g_object_new (META_TYPE_INPUT_DEVICE_NATIVE, - "name", libinput_device_get_name (libinput_device), - "device-type", type, - "device-mode", CLUTTER_INPUT_MODE_PHYSICAL, - "vendor-id", vendor, - "product-id", product, - "n-rings", n_rings, - "n-strips", n_strips, - "n-mode-groups", n_groups, - "n-buttons", n_buttons, - "device-node", node_path, - "seat", seat_impl->seat_native, - NULL); - - device->seat_impl = seat_impl; - device->libinput_device = libinput_device; - - libinput_device_set_user_data (libinput_device, device); - libinput_device_ref (libinput_device); - g_free (vendor); - g_free (product); - g_free (node_path); - - if (libinput_device_has_capability (libinput_device, - LIBINPUT_DEVICE_CAP_TABLET_PAD)) - update_pad_features (device); - - if (libinput_device_get_size (libinput_device, &width, &height) == 0) - device->device_aspect_ratio = width / height; - - device->group = (intptr_t) libinput_device_get_device_group (libinput_device); - - return CLUTTER_INPUT_DEVICE (device); -} - -/* - * meta_input_device_native_new_virtual: - * @seat: the seat the device will belong to - * @type: the input device type - * - * Create a new virtual ClutterInputDevice of the given type. - */ -ClutterInputDevice * -meta_input_device_native_new_virtual (MetaSeatImpl *seat_impl, - ClutterInputDeviceType type, - ClutterInputMode mode) -{ - MetaInputDeviceNative *device; - const char *name; - - switch (type) - { - case CLUTTER_KEYBOARD_DEVICE: - name = "Virtual keyboard device for seat"; - break; - case CLUTTER_POINTER_DEVICE: - name = "Virtual pointer device for seat"; - break; - case CLUTTER_TOUCHSCREEN_DEVICE: - name = "Virtual touchscreen device for seat"; - break; - default: - name = "Virtual device for seat"; - break; - }; - - device = g_object_new (META_TYPE_INPUT_DEVICE_NATIVE, - "name", name, - "device-type", type, - "device-mode", mode, - "seat", seat_impl->seat_native, - NULL); - - device->seat_impl = seat_impl; - - return CLUTTER_INPUT_DEVICE (device); -} - -MetaSeatImpl * -meta_input_device_native_get_seat_impl (MetaInputDeviceNative *device) -{ - return device->seat_impl; -} - -void -meta_input_device_native_update_leds_in_impl (MetaInputDeviceNative *device, - enum libinput_led leds) -{ - if (!device->libinput_device) - return; - - libinput_device_led_update (device->libinput_device, leds); -} - -ClutterInputDeviceType -meta_input_device_native_determine_type_in_impl (struct libinput_device *ldev) -{ - /* This setting is specific to touchpads and alike, only in these - * devices there is this additional layer of touch event interpretation. - */ - if (libinput_device_config_tap_get_finger_count (ldev) > 0) - return CLUTTER_TOUCHPAD_DEVICE; - else if (libinput_device_has_capability (ldev, LIBINPUT_DEVICE_CAP_TABLET_TOOL)) - return CLUTTER_TABLET_DEVICE; - else if (libinput_device_has_capability (ldev, LIBINPUT_DEVICE_CAP_TABLET_PAD)) - return CLUTTER_PAD_DEVICE; - else if (libinput_device_has_capability (ldev, LIBINPUT_DEVICE_CAP_POINTER)) - return CLUTTER_POINTER_DEVICE; - else if (libinput_device_has_capability (ldev, LIBINPUT_DEVICE_CAP_TOUCH)) - return CLUTTER_TOUCHSCREEN_DEVICE; - else if (libinput_device_has_capability (ldev, LIBINPUT_DEVICE_CAP_KEYBOARD)) - return CLUTTER_KEYBOARD_DEVICE; - else - return CLUTTER_EXTENSION_DEVICE; -} - -/** - * meta_input_device_native_get_libinput_device: - * @device: a #ClutterInputDevice - * - * Retrieves the libinput_device struct held in @device. - * - * Returns: The libinput_device struct - * - * Since: 1.20 - * Stability: unstable - **/ -struct libinput_device * -meta_input_device_native_get_libinput_device (ClutterInputDevice *device) -{ - MetaInputDeviceNative *device_evdev; - - g_return_val_if_fail (META_IS_INPUT_DEVICE_NATIVE (device), NULL); - - device_evdev = META_INPUT_DEVICE_NATIVE (device); - - return device_evdev->libinput_device; -} - -void -meta_input_device_native_translate_coordinates_in_impl (ClutterInputDevice *device, - MetaViewportInfo *viewports, - float *x, - float *y) -{ - MetaInputDeviceNative *device_evdev = META_INPUT_DEVICE_NATIVE (device); - double min_x = 0, min_y = 0, max_x = 1, max_y = 1; - float stage_width, stage_height; - double x_d, y_d; - - meta_viewport_info_get_extents (viewports, &stage_width, &stage_height); - x_d = *x / stage_width; - y_d = *y / stage_height; - - /* Apply aspect ratio */ - if (device_evdev->output_ratio > 0 && - device_evdev->device_aspect_ratio > 0) - { - double ratio = device_evdev->device_aspect_ratio / device_evdev->output_ratio; - - if (ratio > 1) - x_d *= ratio; - else if (ratio < 1) - y_d *= 1 / ratio; - } - - cairo_matrix_transform_point (&device_evdev->device_matrix, &min_x, &min_y); - cairo_matrix_transform_point (&device_evdev->device_matrix, &max_x, &max_y); - cairo_matrix_transform_point (&device_evdev->device_matrix, &x_d, &y_d); - - *x = CLAMP (x_d, MIN (min_x, max_x), MAX (min_x, max_x)) * stage_width; - *y = CLAMP (y_d, MIN (min_y, max_y), MAX (min_y, max_y)) * stage_height; -} - -MetaInputDeviceMapping -meta_input_device_native_get_mapping_mode_in_impl (ClutterInputDevice *device) -{ - MetaInputDeviceNative *device_native = META_INPUT_DEVICE_NATIVE (device); - ClutterInputDeviceType device_type; - - g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), - META_INPUT_DEVICE_MAPPING_ABSOLUTE); - - device_type = clutter_input_device_get_device_type (device); - g_return_val_if_fail (device_type == CLUTTER_TABLET_DEVICE || - device_type == CLUTTER_PEN_DEVICE || - device_type == CLUTTER_ERASER_DEVICE, - META_INPUT_DEVICE_MAPPING_ABSOLUTE); - - return device_native->mapping_mode; -} - -void -meta_input_device_native_set_mapping_mode_in_impl (ClutterInputDevice *device, - MetaInputDeviceMapping mapping) -{ - MetaInputDeviceNative *device_native = META_INPUT_DEVICE_NATIVE (device); - ClutterInputDeviceType device_type; - - g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); - - device_type = clutter_input_device_get_device_type (device); - g_return_if_fail (device_type == CLUTTER_TABLET_DEVICE || - device_type == CLUTTER_PEN_DEVICE || - device_type == CLUTTER_ERASER_DEVICE); - - device_native->mapping_mode = mapping; -} - -void -meta_input_device_native_set_coords_in_impl (MetaInputDeviceNative *device_native, - float x, - float y) -{ - device_native->pointer_x = x; - device_native->pointer_y = y; -} - -void -meta_input_device_native_get_coords_in_impl (MetaInputDeviceNative *device_native, - float *x, - float *y) -{ - if (x) - *x = device_native->pointer_x; - if (y) - *y = device_native->pointer_y; -} - -void -meta_input_device_native_detach_libinput_in_impl (MetaInputDeviceNative *device_native) -{ - g_clear_pointer (&device_native->libinput_device, libinput_device_unref); -} diff --git a/src/backends/native/meta-input-device-native.h b/src/backends/native/meta-input-device-native.h deleted file mode 100644 index 88af07c43..000000000 --- a/src/backends/native/meta-input-device-native.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Clutter. - * - * An OpenGL based 'interactive canvas' library. - * - * Copyright (C) 2010 Intel Corp. - * Copyright (C) 2014 Jonas Ådahl - * - * 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 . - * - * Author: Damien Lespiau - * Author: Jonas Ådahl - */ - -#ifndef META_INPUT_DEVICE_NATIVE_H -#define META_INPUT_DEVICE_NATIVE_H - -#ifndef META_INPUT_THREAD_H_INSIDE -#error "This header cannot be included directly. Use "backends/native/meta-input-thread.h"" -#endif /* META_INPUT_THREAD_H_INSIDE */ - -#include - -#include "backends/meta-input-device-private.h" -#include "backends/meta-input-settings-private.h" -#include "backends/native/meta-seat-native.h" -#include "clutter/clutter-mutter.h" - -#define META_TYPE_INPUT_DEVICE_NATIVE meta_input_device_native_get_type() - -#define META_INPUT_DEVICE_NATIVE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - META_TYPE_INPUT_DEVICE_NATIVE, MetaInputDeviceNative)) - -#define META_INPUT_DEVICE_NATIVE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - META_TYPE_INPUT_DEVICE_NATIVE, MetaInputDeviceNativeClass)) - -#define META_IS_INPUT_DEVICE_NATIVE(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ - META_TYPE_INPUT_DEVICE_NATIVE)) - -#define META_IS_INPUT_DEVICE_NATIVE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), \ - META_TYPE_INPUT_DEVICE_NATIVE)) - -#define META_INPUT_DEVICE_NATIVE_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - META_TYPE_INPUT_DEVICE_NATIVE, MetaInputDeviceNativeClass)) - -typedef enum -{ - META_INPUT_DEVICE_MAPPING_ABSOLUTE, - META_INPUT_DEVICE_MAPPING_RELATIVE, -} MetaInputDeviceMapping; - -typedef struct _MetaInputDeviceNative MetaInputDeviceNative; -typedef struct _MetaInputDeviceNativeClass MetaInputDeviceNativeClass; - -struct _MetaInputDeviceNative -{ - ClutterInputDevice parent; - - struct libinput_device *libinput_device; - MetaSeatImpl *seat_impl; - ClutterInputDeviceTool *last_tool; - GArray *pad_features; - GArray *modes; - intptr_t group; - - cairo_matrix_t device_matrix; - double device_aspect_ratio; /* w:h */ - double output_ratio; /* w:h */ - MetaInputDeviceMapping mapping_mode; - - /* Pointer position */ - float pointer_x; - float pointer_y; - - /* Keyboard a11y */ - MetaKeyboardA11yFlags a11y_flags; - GList *slow_keys_list; - GSource *debounce_timer; - uint16_t debounce_key; - xkb_mod_mask_t stickykeys_depressed_mask; - xkb_mod_mask_t stickykeys_latched_mask; - xkb_mod_mask_t stickykeys_locked_mask; - GSource *toggle_slowkeys_timer; - uint16_t shift_count; - uint32_t last_shift_time; - int mousekeys_btn; - gboolean mousekeys_btn_states[3]; - uint32_t mousekeys_first_motion_time; /* ms */ - uint32_t mousekeys_last_motion_time; /* ms */ - guint mousekeys_init_delay; - guint mousekeys_accel_time; - guint mousekeys_max_speed; - double mousekeys_curve_factor; - GSource *move_mousekeys_timer; - uint16_t last_mousekeys_key; -}; - -struct _MetaInputDeviceNativeClass -{ - ClutterInputDeviceClass parent_class; -}; - -GType meta_input_device_native_get_type (void) G_GNUC_CONST; - -ClutterInputDevice * meta_input_device_native_new_in_impl (MetaSeatImpl *seat_impl, - struct libinput_device *libinput_device); - -ClutterInputDevice * meta_input_device_native_new_virtual (MetaSeatImpl *seat_impl, - ClutterInputDeviceType type, - ClutterInputMode mode); - -MetaSeatImpl * meta_input_device_native_get_seat_impl (MetaInputDeviceNative *device); - -void meta_input_device_native_update_leds_in_impl (MetaInputDeviceNative *device, - enum libinput_led leds); - -ClutterInputDeviceType meta_input_device_native_determine_type_in_impl (struct libinput_device *libinput_device); - - -void meta_input_device_native_translate_coordinates_in_impl (ClutterInputDevice *device, - MetaViewportInfo *viewports, - float *x, - float *y); - -MetaInputDeviceMapping meta_input_device_native_get_mapping_mode_in_impl (ClutterInputDevice *device); -void meta_input_device_native_set_mapping_mode_in_impl (ClutterInputDevice *device, - MetaInputDeviceMapping mapping); - -void meta_input_device_native_apply_kbd_a11y_settings_in_impl (MetaInputDeviceNative *device, - MetaKbdA11ySettings *settings); - -void meta_input_device_native_a11y_maybe_notify_toggle_keys_in_impl (MetaInputDeviceNative *device_evdev); - -struct libinput_device * meta_input_device_native_get_libinput_device (ClutterInputDevice *device); - -void meta_input_device_native_set_coords_in_impl (MetaInputDeviceNative *device_native, - float x, - float y); -void meta_input_device_native_get_coords_in_impl (MetaInputDeviceNative *device_native, - float *x, - float *y); -gboolean meta_input_device_native_process_kbd_a11y_event_in_impl (ClutterInputDevice *device, - ClutterEvent *event); -void meta_input_device_native_detach_libinput_in_impl (MetaInputDeviceNative *device_native); - -#endif /* META_INPUT_DEVICE_NATIVE_H */ diff --git a/src/backends/native/meta-input-device-tool-native.c b/src/backends/native/meta-input-device-tool-native.c deleted file mode 100644 index e6ec0c758..000000000 --- a/src/backends/native/meta-input-device-tool-native.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright © 2009, 2010, 2011 Intel Corp. - * - * 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 . - * - * Author: Carlos Garnacho - */ - -#include "config.h" - -#include "backends/native/meta-input-thread.h" - -G_DEFINE_TYPE (MetaInputDeviceToolNative, meta_input_device_tool_native, - CLUTTER_TYPE_INPUT_DEVICE_TOOL) - -static void -meta_input_device_tool_native_finalize (GObject *object) -{ - MetaInputDeviceToolNative *tool = META_INPUT_DEVICE_TOOL_NATIVE (object); - - g_hash_table_unref (tool->button_map); - libinput_tablet_tool_unref (tool->tool); - - G_OBJECT_CLASS (meta_input_device_tool_native_parent_class)->finalize (object); -} - -static void -meta_input_device_tool_native_class_init (MetaInputDeviceToolNativeClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_input_device_tool_native_finalize; -} - -static void -meta_input_device_tool_native_init (MetaInputDeviceToolNative *tool) -{ - tool->button_map = g_hash_table_new (NULL, NULL); -} - -static ClutterInputAxisFlags -translate_axes (struct libinput_tablet_tool *tool) -{ - ClutterInputAxisFlags axes = 0; - - if (libinput_tablet_tool_has_pressure (tool)) - axes |= CLUTTER_INPUT_AXIS_FLAG_PRESSURE; - if (libinput_tablet_tool_has_distance (tool)) - axes |= CLUTTER_INPUT_AXIS_FLAG_DISTANCE; - if (libinput_tablet_tool_has_rotation (tool)) - axes |= CLUTTER_INPUT_AXIS_FLAG_ROTATION; - if (libinput_tablet_tool_has_slider (tool)) - axes |= CLUTTER_INPUT_AXIS_FLAG_SLIDER; - if (libinput_tablet_tool_has_wheel (tool)) - axes |= CLUTTER_INPUT_AXIS_FLAG_WHEEL; - if (libinput_tablet_tool_has_tilt (tool)) - axes |= CLUTTER_INPUT_AXIS_FLAG_XTILT | CLUTTER_INPUT_AXIS_FLAG_YTILT; - - return axes; -} - -ClutterInputDeviceTool * -meta_input_device_tool_native_new (struct libinput_tablet_tool *tool, - uint64_t serial, - ClutterInputDeviceToolType type) -{ - MetaInputDeviceToolNative *evdev_tool; - - evdev_tool = g_object_new (META_TYPE_INPUT_DEVICE_TOOL_NATIVE, - "type", type, - "serial", serial, - "id", libinput_tablet_tool_get_tool_id (tool), - "axes", translate_axes (tool), - NULL); - - evdev_tool->tool = libinput_tablet_tool_ref (tool); - - return CLUTTER_INPUT_DEVICE_TOOL (evdev_tool); -} - -void -meta_input_device_tool_native_set_pressure_curve_in_impl (ClutterInputDeviceTool *tool, - double curve[4]) -{ - MetaInputDeviceToolNative *evdev_tool; - - g_return_if_fail (META_IS_INPUT_DEVICE_TOOL_NATIVE (tool)); - g_return_if_fail (curve[0] >= 0 && curve[0] <= 1 && - curve[1] >= 0 && curve[1] <= 1 && - curve[2] >= 0 && curve[2] <= 1 && - curve[3] >= 0 && curve[3] <= 1); - - evdev_tool = META_INPUT_DEVICE_TOOL_NATIVE (tool); - evdev_tool->pressure_curve[0] = curve[0]; - evdev_tool->pressure_curve[1] = curve[1]; - evdev_tool->pressure_curve[2] = curve[2]; - evdev_tool->pressure_curve[3] = curve[3]; -} - -void -meta_input_device_tool_native_set_button_code_in_impl (ClutterInputDeviceTool *tool, - uint32_t button, - uint32_t evcode) -{ - MetaInputDeviceToolNative *evdev_tool; - - g_return_if_fail (META_IS_INPUT_DEVICE_TOOL_NATIVE (tool)); - - evdev_tool = META_INPUT_DEVICE_TOOL_NATIVE (tool); - - if (evcode == 0) - { - g_hash_table_remove (evdev_tool->button_map, GUINT_TO_POINTER (button)); - } - else - { - g_hash_table_insert (evdev_tool->button_map, GUINT_TO_POINTER (button), - GUINT_TO_POINTER (evcode)); - } -} - -static double -calculate_bezier_position (double pos, - double x1, - double y1, - double x2, - double y2) -{ - double int1_y, int2_y; - - pos = CLAMP (pos, 0, 1); - - /* Intersection between 0,0 and x1,y1 */ - int1_y = pos * y1; - - /* Intersection between x2,y2 and 1,1 */ - int2_y = (pos * (1 - y2)) + y2; - - /* Find the new position in the line traced by the previous points */ - return (pos * (int2_y - int1_y)) + int1_y; -} - -double -meta_input_device_tool_native_translate_pressure_in_impl (ClutterInputDeviceTool *tool, - double pressure) -{ - MetaInputDeviceToolNative *evdev_tool; - - g_return_val_if_fail (META_IS_INPUT_DEVICE_TOOL_NATIVE (tool), pressure); - - evdev_tool = META_INPUT_DEVICE_TOOL_NATIVE (tool); - - return calculate_bezier_position (CLAMP (pressure, 0, 1), - evdev_tool->pressure_curve[0], - evdev_tool->pressure_curve[1], - evdev_tool->pressure_curve[2], - evdev_tool->pressure_curve[3]); -} - -uint32_t -meta_input_device_tool_native_get_button_code_in_impl (ClutterInputDeviceTool *tool, - uint32_t button) -{ - MetaInputDeviceToolNative *evdev_tool; - - g_return_val_if_fail (META_IS_INPUT_DEVICE_TOOL_NATIVE (tool), 0); - - evdev_tool = META_INPUT_DEVICE_TOOL_NATIVE (tool); - - return GPOINTER_TO_UINT (g_hash_table_lookup (evdev_tool->button_map, - GUINT_TO_POINTER (button))); -} diff --git a/src/backends/native/meta-input-device-tool-native.h b/src/backends/native/meta-input-device-tool-native.h deleted file mode 100644 index fa12358ad..000000000 --- a/src/backends/native/meta-input-device-tool-native.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright © 2009, 2010, 2011 Intel Corp. - * - * 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 . - * - * Author: Carlos Garnacho - */ - -#ifndef META_INPUT_DEVICE_NATIVE_TOOL_H -#define META_INPUT_DEVICE_NATIVE_TOOL_H - -#ifndef META_INPUT_THREAD_H_INSIDE -#error "This header cannot be included directly. Use "backends/native/meta-input-thread.h"" -#endif /* META_INPUT_THREAD_H_INSIDE */ - -#include - -#include "clutter/clutter.h" - -G_BEGIN_DECLS - -#define META_TYPE_INPUT_DEVICE_TOOL_NATIVE (meta_input_device_tool_native_get_type ()) - -#define META_INPUT_DEVICE_TOOL_NATIVE(o) \ - (G_TYPE_CHECK_INSTANCE_CAST ((o), \ - META_TYPE_INPUT_DEVICE_TOOL_NATIVE, MetaInputDeviceToolNative)) - -#define META_IS_INPUT_DEVICE_TOOL_NATIVE(o) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((o), \ - META_TYPE_INPUT_DEVICE_TOOL_NATIVE)) - -#define META_INPUT_DEVICE_TOOL_NATIVE_CLASS(c) \ - (G_TYPE_CHECK_CLASS_CAST ((c), \ - META_TYPE_INPUT_DEVICE_TOOL_EVDEV, MetaInputDeviceToolNativeClass)) - -#define META_IS_INPUT_DEVICE_TOOL_NATIVE_CLASS(c) \ - (G_TYPE_CHECK_CLASS_TYPE ((c), \ - META_TYPE_INPUT_DEVICE_TOOL_NATIVE)) - -#define META_INPUT_DEVICE_TOOL_NATIVE_GET_CLASS(o) \ - (G_TYPE_INSTANCE_GET_CLASS ((o), \ - META_TYPE_INPUT_DEVICE_TOOL_NATIVE, MetaInputDeviceToolNativeClass)) - -typedef struct _MetaInputDeviceToolNative MetaInputDeviceToolNative; -typedef struct _MetaInputDeviceToolNativeClass MetaInputDeviceToolNativeClass; - -struct _MetaInputDeviceToolNative -{ - ClutterInputDeviceTool parent_instance; - struct libinput_tablet_tool *tool; - GHashTable *button_map; - double pressure_curve[4]; -}; - -struct _MetaInputDeviceToolNativeClass -{ - ClutterInputDeviceToolClass parent_class; -}; - -GType meta_input_device_tool_native_get_type (void) G_GNUC_CONST; - -ClutterInputDeviceTool * meta_input_device_tool_native_new (struct libinput_tablet_tool *tool, - uint64_t serial, - ClutterInputDeviceToolType type); - -gdouble meta_input_device_tool_native_translate_pressure_in_impl (ClutterInputDeviceTool *tool, - double pressure); -uint32_t meta_input_device_tool_native_get_button_code_in_impl (ClutterInputDeviceTool *tool, - uint32_t button); - -void meta_input_device_tool_native_set_pressure_curve_in_impl (ClutterInputDeviceTool *tool, - double curve[4]); -void meta_input_device_tool_native_set_button_code_in_impl (ClutterInputDeviceTool *tool, - uint32_t button, - uint32_t evcode); - -G_END_DECLS - -#endif /* META_INPUT_DEVICE_NATIVE_TOOL_H */ diff --git a/src/backends/native/meta-input-settings-native.c b/src/backends/native/meta-input-settings-native.c deleted file mode 100644 index 8f61b8bcc..000000000 --- a/src/backends/native/meta-input-settings-native.c +++ /dev/null @@ -1,876 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Author: Carlos Garnacho - */ - -#include "config.h" - -#include -#include - -#include "backends/native/meta-backend-native.h" -#include "backends/native/meta-input-thread.h" -#include "backends/native/meta-input-settings-native.h" - -G_DEFINE_TYPE (MetaInputSettingsNative, meta_input_settings_native, META_TYPE_INPUT_SETTINGS) - -enum -{ - PROP_0, - PROP_SEAT_IMPL, - N_PROPS, -}; - -static GParamSpec *props[N_PROPS] = { 0 }; - -static void -meta_input_settings_native_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaInputSettingsNative *input_settings_native = - META_INPUT_SETTINGS_NATIVE (object); - - switch (prop_id) - { - case PROP_SEAT_IMPL: - input_settings_native->seat_impl = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_input_settings_native_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaInputSettingsNative *input_settings_native = - META_INPUT_SETTINGS_NATIVE (object); - - switch (prop_id) - { - case PROP_SEAT_IMPL: - g_value_set_object (value, input_settings_native->seat_impl); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gboolean -set_send_events (GTask *task) -{ - GDesktopDeviceSendEvents mode; - ClutterInputDevice *device; - enum libinput_config_send_events_mode libinput_mode; - struct libinput_device *libinput_device; - - device = g_task_get_source_object (task); - mode = GPOINTER_TO_UINT (g_task_get_task_data (task)); - - switch (mode) - { - case G_DESKTOP_DEVICE_SEND_EVENTS_DISABLED: - libinput_mode = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED; - break; - case G_DESKTOP_DEVICE_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE: - libinput_mode = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE; - break; - case G_DESKTOP_DEVICE_SEND_EVENTS_ENABLED: - libinput_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; - break; - default: - g_assert_not_reached (); - } - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (libinput_device) - libinput_device_config_send_events_set_mode (libinput_device, libinput_mode); - - return G_SOURCE_REMOVE; -} - -static void -meta_input_settings_native_set_send_events (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopDeviceSendEvents mode) -{ - MetaInputSettingsNative *input_settings_native; - GTask *task; - - task = g_task_new (device, NULL, NULL, NULL); - g_task_set_task_data (task, GUINT_TO_POINTER (mode), NULL); - - input_settings_native = META_INPUT_SETTINGS_NATIVE (settings); - meta_seat_impl_run_input_task (input_settings_native->seat_impl, - task, (GSourceFunc) set_send_events); - g_object_unref (task); -} - -static gboolean -set_matrix (GTask *task) -{ - ClutterInputDevice *device = g_task_get_source_object (task); - float *matrix = g_task_get_task_data (task); - cairo_matrix_t dev_matrix; - - if (clutter_input_device_get_device_type (device) == - CLUTTER_TOUCHSCREEN_DEVICE || - meta_input_device_native_get_mapping_mode_in_impl (device) == - META_INPUT_DEVICE_MAPPING_ABSOLUTE) - { - cairo_matrix_init (&dev_matrix, - matrix[0], matrix[3], matrix[1], - matrix[4], matrix[2], matrix[5]); - } - else - { - cairo_matrix_init_identity (&dev_matrix); - } - - g_object_set (device, "device-matrix", &dev_matrix, NULL); - - return G_SOURCE_REMOVE; -} - -static void -meta_input_settings_native_set_matrix (MetaInputSettings *settings, - ClutterInputDevice *device, - const float matrix[6]) -{ - MetaInputSettingsNative *input_settings_native; - GTask *task; - - task = g_task_new (device, NULL, NULL, NULL); - - g_task_set_task_data (task, g_memdup2 (matrix, sizeof (float) * 6), g_free); - - input_settings_native = META_INPUT_SETTINGS_NATIVE (settings); - meta_seat_impl_run_input_task (input_settings_native->seat_impl, - task, (GSourceFunc) set_matrix); - g_object_unref (task); -} - -static void -meta_input_settings_native_set_speed (MetaInputSettings *settings, - ClutterInputDevice *device, - gdouble speed) -{ - struct libinput_device *libinput_device; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return; - libinput_device_config_accel_set_speed (libinput_device, - CLAMP (speed, -1, 1)); -} - -static void -meta_input_settings_native_set_left_handed (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ - struct libinput_device *libinput_device; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return; - - if (libinput_device_config_left_handed_is_available (libinput_device)) - libinput_device_config_left_handed_set (libinput_device, enabled); -} - -static void -meta_input_settings_native_set_tap_enabled (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ - struct libinput_device *libinput_device; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return; - - if (libinput_device_config_tap_get_finger_count (libinput_device) > 0) - libinput_device_config_tap_set_enabled (libinput_device, - enabled ? - LIBINPUT_CONFIG_TAP_ENABLED : - LIBINPUT_CONFIG_TAP_DISABLED); -} - -static void -meta_input_settings_native_set_tap_and_drag_enabled (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ - struct libinput_device *libinput_device; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return; - - if (libinput_device_config_tap_get_finger_count (libinput_device) > 0) - libinput_device_config_tap_set_drag_enabled (libinput_device, - enabled ? - LIBINPUT_CONFIG_DRAG_ENABLED : - LIBINPUT_CONFIG_DRAG_DISABLED); -} - -static void -meta_input_settings_native_set_tap_and_drag_lock_enabled (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ - struct libinput_device *libinput_device; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return; - - if (libinput_device_config_tap_get_finger_count (libinput_device) > 0) - libinput_device_config_tap_set_drag_lock_enabled (libinput_device, - enabled ? - LIBINPUT_CONFIG_DRAG_LOCK_ENABLED : - LIBINPUT_CONFIG_DRAG_LOCK_DISABLED); -} - -static void -meta_input_settings_native_set_disable_while_typing (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ - struct libinput_device *libinput_device; - - libinput_device = meta_input_device_native_get_libinput_device (device); - - if (!libinput_device) - return; - - if (libinput_device_config_dwt_is_available (libinput_device)) - libinput_device_config_dwt_set_enabled (libinput_device, - enabled ? - LIBINPUT_CONFIG_DWT_ENABLED : - LIBINPUT_CONFIG_DWT_DISABLED); -} - -static void -meta_input_settings_native_set_invert_scroll (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean inverted) -{ - struct libinput_device *libinput_device; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return; - - if (libinput_device_config_scroll_has_natural_scroll (libinput_device)) - libinput_device_config_scroll_set_natural_scroll_enabled (libinput_device, - inverted); -} - -static gboolean -device_set_scroll_method (struct libinput_device *libinput_device, - enum libinput_config_scroll_method method) -{ - enum libinput_config_status status = - libinput_device_config_scroll_set_method (libinput_device, method); - return status == LIBINPUT_CONFIG_STATUS_SUCCESS; -} - -static gboolean -device_set_click_method (struct libinput_device *libinput_device, - enum libinput_config_click_method method) -{ - enum libinput_config_status status = - libinput_device_config_click_set_method (libinput_device, method); - return status == LIBINPUT_CONFIG_STATUS_SUCCESS; -} - -static gboolean -device_set_tap_button_map (struct libinput_device *libinput_device, - enum libinput_config_tap_button_map map) -{ - enum libinput_config_status status = - libinput_device_config_tap_set_button_map (libinput_device, map); - return status == LIBINPUT_CONFIG_STATUS_SUCCESS; -} - -static void -meta_input_settings_native_set_edge_scroll (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean edge_scrolling_enabled) -{ - struct libinput_device *libinput_device; - enum libinput_config_scroll_method current, method; - - libinput_device = meta_input_device_native_get_libinput_device (device); - - method = edge_scrolling_enabled ? LIBINPUT_CONFIG_SCROLL_EDGE : LIBINPUT_CONFIG_SCROLL_NO_SCROLL; - current = libinput_device_config_scroll_get_method (libinput_device); - current &= ~LIBINPUT_CONFIG_SCROLL_EDGE; - - device_set_scroll_method (libinput_device, current | method); -} - -static void -meta_input_settings_native_set_two_finger_scroll (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean two_finger_scroll_enabled) -{ - struct libinput_device *libinput_device; - enum libinput_config_scroll_method current, method; - - libinput_device = meta_input_device_native_get_libinput_device (device); - - method = two_finger_scroll_enabled ? LIBINPUT_CONFIG_SCROLL_2FG : LIBINPUT_CONFIG_SCROLL_NO_SCROLL; - current = libinput_device_config_scroll_get_method (libinput_device); - current &= ~LIBINPUT_CONFIG_SCROLL_2FG; - - device_set_scroll_method (libinput_device, current | method); -} - -static gboolean -meta_input_settings_native_has_two_finger_scroll (MetaInputSettings *settings, - ClutterInputDevice *device) -{ - struct libinput_device *libinput_device; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return FALSE; - - return libinput_device_config_scroll_get_methods (libinput_device) & LIBINPUT_CONFIG_SCROLL_2FG; -} - -static void -meta_input_settings_native_set_scroll_button (MetaInputSettings *settings, - ClutterInputDevice *device, - guint button, - gboolean button_lock) -{ - struct libinput_device *libinput_device; - enum libinput_config_scroll_method method; - enum libinput_config_scroll_button_lock_state lock_state; - guint evcode; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return; - - if (button == 0) - { - method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL; - evcode = 0; - } - else - { - switch (button) - { - case 1: - evcode = BTN_LEFT; - break; - case 2: - evcode = BTN_MIDDLE; - break; - case 3: - evcode = BTN_RIGHT; - break; - default: - /* Compensate for X11 scroll buttons */ - if (button > 7) - button -= 4; - - /* Button is 1-indexed */ - evcode = (BTN_LEFT - 1) + button; - } - - method = LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN; - } - - if (!device_set_scroll_method (libinput_device, method)) - return; - - libinput_device_config_scroll_set_button (libinput_device, evcode); - - if (button_lock) - lock_state = LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED; - else - lock_state = LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED; - - libinput_device_config_scroll_set_button_lock (libinput_device, lock_state); -} - -static void -meta_input_settings_native_set_click_method (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopTouchpadClickMethod mode) -{ - enum libinput_config_click_method click_method = 0; - struct libinput_device *libinput_device; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return; - - switch (mode) - { - case G_DESKTOP_TOUCHPAD_CLICK_METHOD_DEFAULT: - click_method = libinput_device_config_click_get_default_method (libinput_device); - break; - case G_DESKTOP_TOUCHPAD_CLICK_METHOD_NONE: - click_method = LIBINPUT_CONFIG_CLICK_METHOD_NONE; - break; - case G_DESKTOP_TOUCHPAD_CLICK_METHOD_AREAS: - click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; - break; - case G_DESKTOP_TOUCHPAD_CLICK_METHOD_FINGERS: - click_method = LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER; - break; - default: - g_assert_not_reached (); - return; - } - - device_set_click_method (libinput_device, click_method); -} - -static void -meta_input_settings_native_set_tap_button_map (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopTouchpadTapButtonMap mode) -{ - enum libinput_config_tap_button_map button_map = 0; - struct libinput_device *libinput_device; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return; - - if (libinput_device_config_tap_get_finger_count (libinput_device) == 0) - return; - - switch (mode) - { - case G_DESKTOP_TOUCHPAD_BUTTON_TAP_MAP_DEFAULT: - button_map = libinput_device_config_tap_get_default_button_map (libinput_device); - break; - case G_DESKTOP_TOUCHPAD_BUTTON_TAP_MAP_LRM: - button_map = LIBINPUT_CONFIG_TAP_MAP_LRM; - break; - case G_DESKTOP_TOUCHPAD_BUTTON_TAP_MAP_LMR: - button_map = LIBINPUT_CONFIG_TAP_MAP_LMR; - break; - default: - g_assert_not_reached (); - return; - } - - device_set_tap_button_map (libinput_device, button_map); -} - -static void -meta_input_settings_native_set_keyboard_repeat (MetaInputSettings *settings, - gboolean enabled, - guint delay, - guint interval) -{ - MetaInputSettingsNative *input_settings_native; - - input_settings_native = META_INPUT_SETTINGS_NATIVE (settings); - meta_seat_impl_set_keyboard_repeat_in_impl (input_settings_native->seat_impl, - enabled, delay, interval); -} - -static void -set_device_accel_profile (ClutterInputDevice *device, - GDesktopPointerAccelProfile profile) -{ - struct libinput_device *libinput_device; - enum libinput_config_accel_profile libinput_profile; - uint32_t profiles; - - libinput_device = meta_input_device_native_get_libinput_device (device); - - switch (profile) - { - case G_DESKTOP_POINTER_ACCEL_PROFILE_FLAT: - libinput_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT; - break; - case G_DESKTOP_POINTER_ACCEL_PROFILE_ADAPTIVE: - libinput_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE; - break; - default: - g_warn_if_reached (); - case G_DESKTOP_POINTER_ACCEL_PROFILE_DEFAULT: - libinput_profile = - libinput_device_config_accel_get_default_profile (libinput_device); - } - - profiles = libinput_device_config_accel_get_profiles (libinput_device); - if ((profiles & libinput_profile) == 0) - { - libinput_profile = - libinput_device_config_accel_get_default_profile (libinput_device); - } - - libinput_device_config_accel_set_profile (libinput_device, - libinput_profile); -} - -static gboolean -has_udev_property (ClutterInputDevice *device, - const char *property) -{ - struct libinput_device *libinput_device; - struct udev_device *udev_device; - struct udev_device *parent_udev_device; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return FALSE; - - udev_device = libinput_device_get_udev_device (libinput_device); - - if (!udev_device) - return FALSE; - - if (NULL != udev_device_get_property_value (udev_device, property)) - { - udev_device_unref (udev_device); - return TRUE; - } - - parent_udev_device = udev_device_get_parent (udev_device); - udev_device_unref (udev_device); - - if (!parent_udev_device) - return FALSE; - - if (NULL != udev_device_get_property_value (parent_udev_device, property)) - return TRUE; - - return FALSE; -} - -static gboolean -is_mouse_device (ClutterInputDevice *device) -{ - return (has_udev_property (device, "ID_INPUT_MOUSE") && - !has_udev_property (device, "ID_INPUT_POINTINGSTICK")); -} - -static gboolean -meta_input_settings_native_is_touchpad_device (MetaInputSettings *settings, - ClutterInputDevice *device) -{ - return has_udev_property (device, "ID_INPUT_TOUCHPAD"); -} - -static gboolean -meta_input_settings_native_is_trackball_device (MetaInputSettings *settings, - ClutterInputDevice *device) -{ - return has_udev_property (device, "ID_INPUT_TRACKBALL"); -} - -static void -meta_input_settings_native_set_mouse_accel_profile (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopPointerAccelProfile profile) -{ - if (!is_mouse_device (device)) - return; - - set_device_accel_profile (device, profile); -} - -static void -meta_input_settings_native_set_trackball_accel_profile (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopPointerAccelProfile profile) -{ - if (!meta_input_settings_native_is_trackball_device (settings, device)) - return; - - set_device_accel_profile (device, profile); -} - -static void -meta_input_settings_native_set_tablet_mapping (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopTabletMapping mapping) -{ - MetaInputDeviceMapping dev_mapping; - - if (mapping == G_DESKTOP_TABLET_MAPPING_ABSOLUTE) - dev_mapping = META_INPUT_DEVICE_MAPPING_ABSOLUTE; - else if (mapping == G_DESKTOP_TABLET_MAPPING_RELATIVE) - dev_mapping = META_INPUT_DEVICE_MAPPING_RELATIVE; - else - return; - - meta_input_device_native_set_mapping_mode_in_impl (device, dev_mapping); -} - -static gboolean -set_tablet_aspect_ratio (GTask *task) -{ - ClutterInputDevice *device; - double *aspect_ratio; - - device = g_task_get_source_object (task); - aspect_ratio = g_task_get_task_data (task); - g_object_set (device, "output-aspect-ratio", *aspect_ratio, NULL); - - return G_SOURCE_REMOVE; -} - -static void -meta_input_settings_native_set_tablet_aspect_ratio (MetaInputSettings *settings, - ClutterInputDevice *device, - gdouble aspect_ratio) -{ - MetaInputSettingsNative *input_settings_native; - GTask *task; - - if (meta_input_device_native_get_mapping_mode_in_impl (device) == - META_INPUT_DEVICE_MAPPING_RELATIVE) - aspect_ratio = 0; - - task = g_task_new (device, NULL, NULL, NULL); - g_task_set_task_data (task, - g_memdup2 (&aspect_ratio, sizeof (double)), - g_free); - - input_settings_native = META_INPUT_SETTINGS_NATIVE (settings); - meta_seat_impl_run_input_task (input_settings_native->seat_impl, - task, (GSourceFunc) set_tablet_aspect_ratio); - g_object_unref (task); -} - -static void -meta_input_settings_native_set_tablet_area (MetaInputSettings *settings, - ClutterInputDevice *device, - gdouble padding_left, - gdouble padding_right, - gdouble padding_top, - gdouble padding_bottom) -{ - struct libinput_device *libinput_device; - gfloat scale_x; - gfloat scale_y; - gfloat offset_x; - gfloat offset_y; - - scale_x = 1. / (1. - (padding_left + padding_right)); - scale_y = 1. / (1. - (padding_top + padding_bottom)); - offset_x = -padding_left * scale_x; - offset_y = -padding_top * scale_y; - - gfloat matrix[6] = { scale_x, 0., offset_x, - 0., scale_y, offset_y }; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device || - !libinput_device_config_calibration_has_matrix (libinput_device)) - return; - - libinput_device_config_calibration_set_matrix (libinput_device, matrix); -} - -static void -meta_input_settings_native_set_stylus_pressure (MetaInputSettings *settings, - ClutterInputDevice *device, - ClutterInputDeviceTool *tool, - const gint curve[4]) -{ - gdouble pressure_curve[4]; - - pressure_curve[0] = (gdouble) curve[0] / 100; - pressure_curve[1] = (gdouble) curve[1] / 100; - pressure_curve[2] = (gdouble) curve[2] / 100; - pressure_curve[3] = (gdouble) curve[3] / 100; - - meta_input_device_tool_native_set_pressure_curve_in_impl (tool, pressure_curve); -} - -static guint -action_to_evcode (GDesktopStylusButtonAction action) -{ - switch (action) - { - case G_DESKTOP_STYLUS_BUTTON_ACTION_MIDDLE: - return BTN_STYLUS; - case G_DESKTOP_STYLUS_BUTTON_ACTION_RIGHT: - return BTN_STYLUS2; - case G_DESKTOP_STYLUS_BUTTON_ACTION_BACK: - return BTN_BACK; - case G_DESKTOP_STYLUS_BUTTON_ACTION_FORWARD: - return BTN_FORWARD; - case G_DESKTOP_STYLUS_BUTTON_ACTION_DEFAULT: - default: - return 0; - } -} - -static void -meta_input_settings_native_set_stylus_button_map (MetaInputSettings *settings, - ClutterInputDevice *device, - ClutterInputDeviceTool *tool, - GDesktopStylusButtonAction primary, - GDesktopStylusButtonAction secondary, - GDesktopStylusButtonAction tertiary) -{ - meta_input_device_tool_native_set_button_code_in_impl (tool, CLUTTER_BUTTON_MIDDLE, - action_to_evcode (primary)); - meta_input_device_tool_native_set_button_code_in_impl (tool, CLUTTER_BUTTON_SECONDARY, - action_to_evcode (secondary)); - meta_input_device_tool_native_set_button_code_in_impl (tool, 8, /* Back */ - action_to_evcode (tertiary)); -} - -static void -meta_input_settings_native_set_mouse_middle_click_emulation (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ - struct libinput_device *libinput_device; - - if (!is_mouse_device (device)) - return; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return; - - if (libinput_device_config_middle_emulation_is_available (libinput_device)) - libinput_device_config_middle_emulation_set_enabled (libinput_device, enabled); -} - -static void -meta_input_settings_native_set_touchpad_middle_click_emulation (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ - struct libinput_device *libinput_device; - - if (!meta_input_settings_native_is_touchpad_device (settings, device)) - return; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return; - - if (libinput_device_config_middle_emulation_is_available (libinput_device)) - libinput_device_config_middle_emulation_set_enabled (libinput_device, enabled); -} - -static void -meta_input_settings_native_set_trackball_middle_click_emulation (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ - struct libinput_device *libinput_device; - - if (!meta_input_settings_native_is_trackball_device (settings, device)) - return; - - libinput_device = meta_input_device_native_get_libinput_device (device); - if (!libinput_device) - return; - - if (libinput_device_config_middle_emulation_is_available (libinput_device)) - libinput_device_config_middle_emulation_set_enabled (libinput_device, enabled); -} - -static void -meta_input_settings_native_class_init (MetaInputSettingsNativeClass *klass) -{ - MetaInputSettingsClass *input_settings_class = META_INPUT_SETTINGS_CLASS (klass); - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->set_property = meta_input_settings_native_set_property; - object_class->get_property = meta_input_settings_native_get_property; - - input_settings_class->set_send_events = meta_input_settings_native_set_send_events; - input_settings_class->set_matrix = meta_input_settings_native_set_matrix; - input_settings_class->set_speed = meta_input_settings_native_set_speed; - input_settings_class->set_left_handed = meta_input_settings_native_set_left_handed; - input_settings_class->set_tap_enabled = meta_input_settings_native_set_tap_enabled; - input_settings_class->set_tap_button_map = meta_input_settings_native_set_tap_button_map; - input_settings_class->set_tap_and_drag_enabled = meta_input_settings_native_set_tap_and_drag_enabled; - input_settings_class->set_tap_and_drag_lock_enabled = - meta_input_settings_native_set_tap_and_drag_lock_enabled; - input_settings_class->set_invert_scroll = meta_input_settings_native_set_invert_scroll; - input_settings_class->set_edge_scroll = meta_input_settings_native_set_edge_scroll; - input_settings_class->set_two_finger_scroll = meta_input_settings_native_set_two_finger_scroll; - input_settings_class->set_scroll_button = meta_input_settings_native_set_scroll_button; - input_settings_class->set_click_method = meta_input_settings_native_set_click_method; - input_settings_class->set_keyboard_repeat = meta_input_settings_native_set_keyboard_repeat; - input_settings_class->set_disable_while_typing = meta_input_settings_native_set_disable_while_typing; - - input_settings_class->set_tablet_mapping = meta_input_settings_native_set_tablet_mapping; - input_settings_class->set_tablet_aspect_ratio = meta_input_settings_native_set_tablet_aspect_ratio; - input_settings_class->set_tablet_area = meta_input_settings_native_set_tablet_area; - - input_settings_class->set_mouse_accel_profile = meta_input_settings_native_set_mouse_accel_profile; - input_settings_class->set_trackball_accel_profile = meta_input_settings_native_set_trackball_accel_profile; - - input_settings_class->set_stylus_pressure = meta_input_settings_native_set_stylus_pressure; - input_settings_class->set_stylus_button_map = meta_input_settings_native_set_stylus_button_map; - - input_settings_class->set_mouse_middle_click_emulation = meta_input_settings_native_set_mouse_middle_click_emulation; - input_settings_class->set_touchpad_middle_click_emulation = meta_input_settings_native_set_touchpad_middle_click_emulation; - input_settings_class->set_trackball_middle_click_emulation = meta_input_settings_native_set_trackball_middle_click_emulation; - - input_settings_class->has_two_finger_scroll = meta_input_settings_native_has_two_finger_scroll; - input_settings_class->is_trackball_device = meta_input_settings_native_is_trackball_device; - - props[PROP_SEAT_IMPL] = - g_param_spec_object ("seat-impl", - "Seat Impl", - "Seat Impl", - META_TYPE_SEAT_IMPL, - CLUTTER_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - - g_object_class_install_properties (object_class, N_PROPS, props); -} - -static void -meta_input_settings_native_init (MetaInputSettingsNative *settings) -{ -} - -MetaInputSettings * -meta_input_settings_native_new_in_impl (MetaSeatImpl *seat_impl) -{ - return g_object_new (META_TYPE_INPUT_SETTINGS_NATIVE, - "seat-impl", seat_impl, - NULL); -} diff --git a/src/backends/native/meta-input-settings-native.h b/src/backends/native/meta-input-settings-native.h deleted file mode 100644 index cddd5b15f..000000000 --- a/src/backends/native/meta-input-settings-native.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright 2014 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 . - * - * Author: Carlos Garnacho - */ - -#ifndef META_INPUT_SETTINGS_NATIVE_H -#define META_INPUT_SETTINGS_NATIVE_H - -#ifndef META_INPUT_THREAD_H_INSIDE -#error "This header cannot be included directly. Use "backends/native/meta-input-thread.h"" -#endif /* META_INPUT_THREAD_H_INSIDE */ - -#include "backends/meta-input-settings-private.h" - -#define META_TYPE_INPUT_SETTINGS_NATIVE (meta_input_settings_native_get_type ()) -#define META_INPUT_SETTINGS_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_INPUT_SETTINGS_NATIVE, MetaInputSettingsNative)) -#define META_INPUT_SETTINGS_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_INPUT_SETTINGS_NATIVE, MetaInputSettingsNativeClass)) -#define META_IS_INPUT_SETTINGS_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_INPUT_SETTINGS_NATIVE)) -#define META_IS_INPUT_SETTINGS_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_INPUT_SETTINGS_NATIVE)) -#define META_INPUT_SETTINGS_NATIVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_INPUT_SETTINGS_NATIVE, MetaInputSettingsNativeClass)) - -typedef struct _MetaInputSettingsNative MetaInputSettingsNative; -typedef struct _MetaInputSettingsNativeClass MetaInputSettingsNativeClass; - -struct _MetaInputSettingsNative -{ - MetaInputSettings parent_instance; - MetaSeatImpl *seat_impl; -}; - -struct _MetaInputSettingsNativeClass -{ - MetaInputSettingsClass parent_class; -}; - -GType meta_input_settings_native_get_type (void) G_GNUC_CONST; - -MetaInputSettings * meta_input_settings_native_new_in_impl (MetaSeatImpl *seat_impl); - -#endif /* META_INPUT_SETTINGS_NATIVE_H */ diff --git a/src/backends/native/meta-input-thread.h b/src/backends/native/meta-input-thread.h deleted file mode 100644 index 196adc27b..000000000 --- a/src/backends/native/meta-input-thread.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2020 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 . - * - * Author: Carlos Garnacho - */ - -#ifndef META_INPUT_THREAD_H -#define META_INPUT_THREAD_H - -#define META_INPUT_THREAD_H_INSIDE - -#include "src/backends/native/meta-input-device-native.h" -#include "src/backends/native/meta-input-device-tool-native.h" -#include "src/backends/native/meta-input-settings-native.h" -#include "src/backends/native/meta-keymap-native.h" -#include "src/backends/native/meta-seat-impl.h" - -#undef META_INPUT_THREAD_H_INSIDE - -#endif /* META_INPUT_THREAD_H */ diff --git a/src/backends/native/meta-keymap-native.c b/src/backends/native/meta-keymap-native.c deleted file mode 100644 index 500bb1012..000000000 --- a/src/backends/native/meta-keymap-native.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2018 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: Carlos Garnacho - */ - -#include "config.h" - -#include "backends/meta-keymap-utils.h" -#include "backends/native/meta-input-thread.h" -#include "backends/native/meta-seat-impl.h" -#include "backends/native/meta-seat-native.h" -#include "clutter/clutter-keymap-private.h" - -static const char *option_xkb_layout = "us"; -static const char *option_xkb_variant = ""; -static const char *option_xkb_options = ""; - -typedef struct _MetaKeymapNative MetaKeymapNative; - -struct _MetaKeymapNative -{ - ClutterKeymap parent_instance; - - struct xkb_keymap *keymap; - gboolean num_lock; - gboolean caps_lock; -}; - -G_DEFINE_TYPE (MetaKeymapNative, meta_keymap_native, - CLUTTER_TYPE_KEYMAP) - -static void -meta_keymap_native_finalize (GObject *object) -{ - MetaKeymapNative *keymap = META_KEYMAP_NATIVE (object); - - xkb_keymap_unref (keymap->keymap); - - G_OBJECT_CLASS (meta_keymap_native_parent_class)->finalize (object); -} - -static PangoDirection -meta_keymap_native_get_direction (ClutterKeymap *keymap) -{ - return PANGO_DIRECTION_NEUTRAL; -} - -static void -meta_keymap_native_class_init (MetaKeymapNativeClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - ClutterKeymapClass *keymap_class = CLUTTER_KEYMAP_CLASS (klass); - - object_class->finalize = meta_keymap_native_finalize; - - keymap_class->get_direction = meta_keymap_native_get_direction; -} - -static void -meta_keymap_native_init (MetaKeymapNative *keymap) -{ - struct xkb_context *ctx; - struct xkb_rule_names names; - - names.rules = "evdev"; - names.model = "pc105"; - names.layout = option_xkb_layout; - names.variant = option_xkb_variant; - names.options = option_xkb_options; - - ctx = meta_create_xkb_context (); - g_assert (ctx); - keymap->keymap = xkb_keymap_new_from_names (ctx, &names, 0); - xkb_context_unref (ctx); -} - -void -meta_keymap_native_set_keyboard_map_in_impl (MetaKeymapNative *keymap, - struct xkb_keymap *xkb_keymap) -{ - g_return_if_fail (xkb_keymap != NULL); - - if (keymap->keymap) - xkb_keymap_unref (keymap->keymap); - keymap->keymap = xkb_keymap_ref (xkb_keymap); -} - -struct xkb_keymap * -meta_keymap_native_get_keyboard_map_in_impl (MetaKeymapNative *keymap) -{ - return keymap->keymap; -} - -typedef struct -{ - MetaKeymapNative *keymap_native; - gboolean num_lock_state; - gboolean caps_lock_state; -} UpdateLockedModifierStateData; - -static gboolean -update_locked_modifier_state_in_main (gpointer user_data) -{ - UpdateLockedModifierStateData *data = user_data; - - clutter_keymap_set_lock_modifier_state (CLUTTER_KEYMAP (data->keymap_native), - data->caps_lock_state, - data->num_lock_state); - - return G_SOURCE_REMOVE; -} - -void -meta_keymap_native_update_in_impl (MetaKeymapNative *keymap_native, - MetaSeatImpl *seat_impl, - struct xkb_state *xkb_state) -{ - UpdateLockedModifierStateData *data; - - data = g_new0 (UpdateLockedModifierStateData, 1); - data->keymap_native = keymap_native; - data->num_lock_state = - xkb_state_mod_name_is_active (xkb_state, - XKB_MOD_NAME_NUM, - XKB_STATE_MODS_LATCHED | - XKB_STATE_MODS_LOCKED); - data->caps_lock_state = - xkb_state_mod_name_is_active (xkb_state, - XKB_MOD_NAME_CAPS, - XKB_STATE_MODS_LATCHED | - XKB_STATE_MODS_LOCKED); - - meta_seat_impl_queue_main_thread_idle (seat_impl, - update_locked_modifier_state_in_main, - data, g_free); -} diff --git a/src/backends/native/meta-keymap-native.h b/src/backends/native/meta-keymap-native.h deleted file mode 100644 index 0aa62d085..000000000 --- a/src/backends/native/meta-keymap-native.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2018 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: Carlos Garnacho - */ -#ifndef META_KEYMAP_NATIVE_H -#define META_KEYMAP_NATIVE_H - -#ifndef META_INPUT_THREAD_H_INSIDE -#error "This header cannot be included directly. Use "backends/native/meta-input-thread.h"" -#endif /* META_INPUT_THREAD_H_INSIDE */ - -#include "backends/native/meta-xkb-utils.h" -#include "clutter/clutter.h" - -#define META_TYPE_KEYMAP_NATIVE (meta_keymap_native_get_type ()) -G_DECLARE_FINAL_TYPE (MetaKeymapNative, meta_keymap_native, - META, KEYMAP_NATIVE, - ClutterKeymap) - -void meta_keymap_native_set_keyboard_map_in_impl (MetaKeymapNative *keymap, - struct xkb_keymap *xkb_keymap); -struct xkb_keymap * meta_keymap_native_get_keyboard_map_in_impl (MetaKeymapNative *keymap); -void meta_keymap_native_update_in_impl (MetaKeymapNative *keymap, - MetaSeatImpl *seat_impl, - struct xkb_state *xkb_state); - -#endif /* META_KEYMAP_NATIVE_H */ diff --git a/src/backends/native/meta-kms-connector-private.h b/src/backends/native/meta-kms-connector-private.h deleted file mode 100644 index 9accf8ccd..000000000 --- a/src/backends/native/meta-kms-connector-private.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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_KMS_CONNECTOR_PRIVATE_H -#define META_KMS_CONNECTOR_PRIVATE_H - -#include "backends/native/meta-kms-connector.h" - -typedef enum _MetaKmsConnectorProp -{ - META_KMS_CONNECTOR_PROP_CRTC_ID = 0, - META_KMS_CONNECTOR_PROP_DPMS, - META_KMS_CONNECTOR_PROP_UNDERSCAN, - META_KMS_CONNECTOR_PROP_UNDERSCAN_HBORDER, - META_KMS_CONNECTOR_PROP_UNDERSCAN_VBORDER, - META_KMS_CONNECTOR_N_PROPS -} MetaKmsConnectorProp; - -uint32_t meta_kms_connector_get_prop_id (MetaKmsConnector *connector, - MetaKmsConnectorProp prop); - -const char * meta_kms_connector_get_prop_name (MetaKmsConnector *connector, - MetaKmsConnectorProp prop); - -void meta_kms_connector_update_state (MetaKmsConnector *connector, - drmModeRes *drm_resources); - -void meta_kms_connector_predict_state (MetaKmsConnector *connector, - MetaKmsUpdate *update); - -MetaKmsConnector * meta_kms_connector_new (MetaKmsImplDevice *impl_device, - drmModeConnector *drm_connector, - drmModeRes *drm_resources); - -gboolean meta_kms_connector_is_same_as (MetaKmsConnector *connector, - drmModeConnector *drm_connector); - -#endif /* META_KMS_CONNECTOR_PRIVATE_H */ diff --git a/src/backends/native/meta-kms-connector.c b/src/backends/native/meta-kms-connector.c deleted file mode 100644 index a666bb45c..000000000 --- a/src/backends/native/meta-kms-connector.c +++ /dev/null @@ -1,700 +0,0 @@ -/* - * 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. - */ - -#include "config.h" - -#include "backends/native/meta-kms-connector.h" -#include "backends/native/meta-kms-connector-private.h" - -#include - -#include "backends/native/meta-kms-crtc.h" -#include "backends/native/meta-kms-device-private.h" -#include "backends/native/meta-kms-impl-device.h" -#include "backends/native/meta-kms-mode-private.h" -#include "backends/native/meta-kms-update-private.h" - -typedef struct _MetaKmsConnectorPropTable -{ - MetaKmsProp props[META_KMS_CONNECTOR_N_PROPS]; -} MetaKmsConnectorPropTable; - -struct _MetaKmsConnector -{ - GObject parent; - - MetaKmsDevice *device; - - uint32_t id; - uint32_t type; - uint32_t type_id; - char *name; - - MetaKmsConnectorState *current_state; - - MetaKmsConnectorPropTable prop_table; - - uint32_t edid_blob_id; - uint32_t tile_blob_id; - - gboolean fd_held; -}; - -G_DEFINE_TYPE (MetaKmsConnector, meta_kms_connector, G_TYPE_OBJECT) - -MetaKmsDevice * -meta_kms_connector_get_device (MetaKmsConnector *connector) -{ - return connector->device; -} - -uint32_t -meta_kms_connector_get_prop_id (MetaKmsConnector *connector, - MetaKmsConnectorProp prop) -{ - return connector->prop_table.props[prop].prop_id; -} - -const char * -meta_kms_connector_get_prop_name (MetaKmsConnector *connector, - MetaKmsConnectorProp prop) -{ - return connector->prop_table.props[prop].name; -} - -uint32_t -meta_kms_connector_get_connector_type (MetaKmsConnector *connector) -{ - return connector->type; -} - -uint32_t -meta_kms_connector_get_id (MetaKmsConnector *connector) -{ - return connector->id; -} - -const char * -meta_kms_connector_get_name (MetaKmsConnector *connector) -{ - return connector->name; -} - -gboolean -meta_kms_connector_can_clone (MetaKmsConnector *connector, - MetaKmsConnector *other_connector) -{ - MetaKmsConnectorState *state = connector->current_state; - MetaKmsConnectorState *other_state = other_connector->current_state; - - if (state->common_possible_clones == 0 || - other_state->common_possible_clones == 0) - return FALSE; - - if (state->encoder_device_idxs != other_state->encoder_device_idxs) - return FALSE; - - return TRUE; -} - -const MetaKmsConnectorState * -meta_kms_connector_get_current_state (MetaKmsConnector *connector) -{ - return connector->current_state; -} - -gboolean -meta_kms_connector_is_underscanning_supported (MetaKmsConnector *connector) -{ - uint32_t underscan_prop_id; - - underscan_prop_id = - connector->prop_table.props[META_KMS_CONNECTOR_PROP_UNDERSCAN].prop_id; - - return underscan_prop_id != 0; -} - -static void -sync_fd_held (MetaKmsConnector *connector, - MetaKmsImplDevice *impl_device) -{ - gboolean should_hold_fd; - - should_hold_fd = connector->current_state->current_crtc_id != 0; - - if (connector->fd_held == should_hold_fd) - return; - - if (should_hold_fd) - meta_kms_impl_device_hold_fd (impl_device); - else - meta_kms_impl_device_unhold_fd (impl_device); - - connector->fd_held = should_hold_fd; -} - -static void -set_panel_orientation (MetaKmsConnectorState *state, - drmModePropertyPtr prop, - uint64_t orientation) -{ - const char *name; - - name = prop->enums[orientation].name; - if (strcmp (name, "Upside Down") == 0) - { - state->panel_orientation_transform = META_MONITOR_TRANSFORM_180; - } - else if (strcmp (name, "Left Side Up") == 0) - { - /* Left side up, rotate 90 degrees counter clockwise to correct */ - state->panel_orientation_transform = META_MONITOR_TRANSFORM_90; - } - else if (strcmp (name, "Right Side Up") == 0) - { - /* Right side up, rotate 270 degrees counter clockwise to correct */ - state->panel_orientation_transform = META_MONITOR_TRANSFORM_270; - } - else - { - state->panel_orientation_transform = META_MONITOR_TRANSFORM_NORMAL; - } -} - -static void -state_set_properties (MetaKmsConnectorState *state, - MetaKmsImplDevice *impl_device, - drmModeConnector *drm_connector) -{ - int fd; - int i; - - fd = meta_kms_impl_device_get_fd (impl_device); - - for (i = 0; i < drm_connector->count_props; i++) - { - drmModePropertyPtr prop; - - prop = drmModeGetProperty (fd, drm_connector->props[i]); - if (!prop) - continue; - - if ((prop->flags & DRM_MODE_PROP_RANGE) && - strcmp (prop->name, "suggested X") == 0) - state->suggested_x = drm_connector->prop_values[i]; - else if ((prop->flags & DRM_MODE_PROP_RANGE) && - strcmp (prop->name, "suggested Y") == 0) - state->suggested_y = drm_connector->prop_values[i]; - else if ((prop->flags & DRM_MODE_PROP_RANGE) && - strcmp (prop->name, "hotplug_mode_update") == 0) - state->hotplug_mode_update = drm_connector->prop_values[i]; - else if (strcmp (prop->name, "scaling mode") == 0) - state->has_scaling = TRUE; - else if ((prop->flags & DRM_MODE_PROP_ENUM) && - strcmp (prop->name, "panel orientation") == 0) - set_panel_orientation (state, prop, drm_connector->prop_values[i]); - else if ((prop->flags & DRM_MODE_PROP_RANGE) && - strcmp (prop->name, "non-desktop") == 0) - state->non_desktop = drm_connector->prop_values[i]; - - drmModeFreeProperty (prop); - } -} - -static CoglSubpixelOrder -drm_subpixel_order_to_cogl_subpixel_order (drmModeSubPixel subpixel) -{ - switch (subpixel) - { - case DRM_MODE_SUBPIXEL_NONE: - return COGL_SUBPIXEL_ORDER_NONE; - break; - case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB: - return COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB; - break; - case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR: - return COGL_SUBPIXEL_ORDER_HORIZONTAL_BGR; - break; - case DRM_MODE_SUBPIXEL_VERTICAL_RGB: - return COGL_SUBPIXEL_ORDER_VERTICAL_RGB; - break; - case DRM_MODE_SUBPIXEL_VERTICAL_BGR: - return COGL_SUBPIXEL_ORDER_VERTICAL_BGR; - break; - case DRM_MODE_SUBPIXEL_UNKNOWN: - return COGL_SUBPIXEL_ORDER_UNKNOWN; - } - return COGL_SUBPIXEL_ORDER_UNKNOWN; -} - -static void -state_set_edid (MetaKmsConnectorState *state, - MetaKmsConnector *connector, - MetaKmsImplDevice *impl_device, - uint32_t blob_id) -{ - int fd; - drmModePropertyBlobPtr edid_blob; - GBytes *edid_data; - - fd = meta_kms_impl_device_get_fd (impl_device); - edid_blob = drmModeGetPropertyBlob (fd, blob_id); - if (!edid_blob) - { - g_warning ("Failed to read EDID of connector %s: %s", - connector->name, g_strerror (errno)); - return; - } - - edid_data = g_bytes_new (edid_blob->data, edid_blob->length); - drmModeFreePropertyBlob (edid_blob); - - state->edid_data = edid_data; -} - -static void -state_set_tile_info (MetaKmsConnectorState *state, - MetaKmsConnector *connector, - MetaKmsImplDevice *impl_device, - uint32_t blob_id) -{ - int fd; - drmModePropertyBlobPtr tile_blob; - - state->tile_info = (MetaTileInfo) { 0 }; - - fd = meta_kms_impl_device_get_fd (impl_device); - tile_blob = drmModeGetPropertyBlob (fd, blob_id); - if (!tile_blob) - { - g_warning ("Failed to read TILE of connector %s: %s", - connector->name, strerror (errno)); - return; - } - - if (tile_blob->length > 0) - { - if (sscanf ((char *) tile_blob->data, "%d:%d:%d:%d:%d:%d:%d:%d", - &state->tile_info.group_id, - &state->tile_info.flags, - &state->tile_info.max_h_tiles, - &state->tile_info.max_v_tiles, - &state->tile_info.loc_h_tile, - &state->tile_info.loc_v_tile, - &state->tile_info.tile_w, - &state->tile_info.tile_h) != 8) - { - g_warning ("Couldn't understand TILE property blob of connector %s", - connector->name); - state->tile_info = (MetaTileInfo) { 0 }; - } - } - - drmModeFreePropertyBlob (tile_blob); -} - -static void -state_set_blobs (MetaKmsConnectorState *state, - MetaKmsConnector *connector, - MetaKmsImplDevice *impl_device, - drmModeConnector *drm_connector) -{ - int fd; - int i; - - fd = meta_kms_impl_device_get_fd (impl_device); - - for (i = 0; i < drm_connector->count_props; i++) - { - drmModePropertyPtr prop; - - prop = drmModeGetProperty (fd, drm_connector->props[i]); - if (!prop) - continue; - - if (prop->flags & DRM_MODE_PROP_BLOB) - { - uint32_t blob_id; - - blob_id = drm_connector->prop_values[i]; - - if (blob_id) - { - if (strcmp (prop->name, "EDID") == 0) - state_set_edid (state, connector, impl_device, blob_id); - else if (strcmp (prop->name, "TILE") == 0) - state_set_tile_info (state, connector, impl_device, blob_id); - } - } - - drmModeFreeProperty (prop); - } -} - -static void -state_set_physical_dimensions (MetaKmsConnectorState *state, - drmModeConnector *drm_connector) -{ - state->width_mm = drm_connector->mmWidth; - state->height_mm = drm_connector->mmHeight; -} - -static void -state_set_modes (MetaKmsConnectorState *state, - MetaKmsImplDevice *impl_device, - drmModeConnector *drm_connector) -{ - int i; - - for (i = 0; i < drm_connector->count_modes; i++) - { - MetaKmsMode *mode; - - mode = meta_kms_mode_new (impl_device, &drm_connector->modes[i], - META_KMS_MODE_FLAG_NONE); - state->modes = g_list_prepend (state->modes, mode); - } - state->modes = g_list_reverse (state->modes); -} - -static void -set_encoder_device_idx_bit (uint32_t *encoder_device_idxs, - uint32_t encoder_id, - MetaKmsImplDevice *impl_device, - drmModeRes *drm_resources) -{ - int fd; - int i; - - fd = meta_kms_impl_device_get_fd (impl_device); - - for (i = 0; i < drm_resources->count_encoders; i++) - { - drmModeEncoder *drm_encoder; - - drm_encoder = drmModeGetEncoder (fd, drm_resources->encoders[i]); - if (!drm_encoder) - continue; - - if (drm_encoder->encoder_id == encoder_id) - { - *encoder_device_idxs |= (1 << i); - drmModeFreeEncoder (drm_encoder); - break; - } - - drmModeFreeEncoder (drm_encoder); - } -} - -static void -state_set_crtc_state (MetaKmsConnectorState *state, - drmModeConnector *drm_connector, - MetaKmsImplDevice *impl_device, - drmModeRes *drm_resources) -{ - int fd; - int i; - uint32_t common_possible_crtcs; - uint32_t common_possible_clones; - uint32_t encoder_device_idxs; - - fd = meta_kms_impl_device_get_fd (impl_device); - - common_possible_crtcs = UINT32_MAX; - common_possible_clones = UINT32_MAX; - encoder_device_idxs = 0; - for (i = 0; i < drm_connector->count_encoders; i++) - { - drmModeEncoder *drm_encoder; - - drm_encoder = drmModeGetEncoder (fd, drm_connector->encoders[i]); - if (!drm_encoder) - continue; - - common_possible_crtcs &= drm_encoder->possible_crtcs; - common_possible_clones &= drm_encoder->possible_clones; - - set_encoder_device_idx_bit (&encoder_device_idxs, - drm_encoder->encoder_id, - impl_device, - drm_resources); - - if (drm_connector->encoder_id == drm_encoder->encoder_id) - state->current_crtc_id = drm_encoder->crtc_id; - - drmModeFreeEncoder (drm_encoder); - } - - state->common_possible_crtcs = common_possible_crtcs; - state->common_possible_clones = common_possible_clones; - state->encoder_device_idxs = encoder_device_idxs; -} - -static MetaKmsConnectorState * -meta_kms_connector_state_new (void) -{ - MetaKmsConnectorState *state; - - state = g_new0 (MetaKmsConnectorState, 1); - state->suggested_x = -1; - state->suggested_y = -1; - - return state; -} - -static void -meta_kms_connector_state_free (MetaKmsConnectorState *state) -{ - g_clear_pointer (&state->edid_data, g_bytes_unref); - g_list_free_full (state->modes, (GDestroyNotify) meta_kms_mode_free); - g_free (state); -} - -static void -meta_kms_connector_read_state (MetaKmsConnector *connector, - MetaKmsImplDevice *impl_device, - drmModeConnector *drm_connector, - drmModeRes *drm_resources) -{ - MetaKmsConnectorState *state; - - g_clear_pointer (&connector->current_state, meta_kms_connector_state_free); - - if (!drm_connector || drm_connector->connection != DRM_MODE_CONNECTED) - return; - - state = meta_kms_connector_state_new (); - - state_set_blobs (state, connector, impl_device, drm_connector); - - state_set_properties (state, impl_device, drm_connector); - - state->subpixel_order = - drm_subpixel_order_to_cogl_subpixel_order (drm_connector->subpixel); - - state_set_physical_dimensions (state, drm_connector); - - state_set_modes (state, impl_device, drm_connector); - - state_set_crtc_state (state, drm_connector, impl_device, drm_resources); - - connector->current_state = state; - - sync_fd_held (connector, impl_device); -} - -void -meta_kms_connector_update_state (MetaKmsConnector *connector, - drmModeRes *drm_resources) -{ - MetaKmsImplDevice *impl_device; - drmModeConnector *drm_connector; - - impl_device = meta_kms_device_get_impl_device (connector->device); - drm_connector = drmModeGetConnector (meta_kms_impl_device_get_fd (impl_device), - connector->id); - meta_kms_connector_read_state (connector, impl_device, - drm_connector, - drm_resources); - if (drm_connector) - drmModeFreeConnector (drm_connector); -} - -void -meta_kms_connector_predict_state (MetaKmsConnector *connector, - MetaKmsUpdate *update) -{ - MetaKmsImplDevice *impl_device; - MetaKmsConnectorState *current_state; - GList *mode_sets; - GList *l; - current_state = connector->current_state; - if (!current_state) - return; - - mode_sets = meta_kms_update_get_mode_sets (update); - for (l = mode_sets; l; l = l->next) - { - MetaKmsModeSet *mode_set = l->data; - MetaKmsCrtc *crtc = mode_set->crtc; - - if (current_state->current_crtc_id == meta_kms_crtc_get_id (crtc)) - { - if (g_list_find (mode_set->connectors, connector)) - break; - else - current_state->current_crtc_id = 0; - } - else - { - if (g_list_find (mode_set->connectors, connector)) - { - current_state->current_crtc_id = meta_kms_crtc_get_id (crtc); - break; - } - } - } - - impl_device = meta_kms_device_get_impl_device (connector->device); - sync_fd_held (connector, impl_device); -} - -static void -init_properties (MetaKmsConnector *connector, - MetaKmsImplDevice *impl_device, - drmModeConnector *drm_connector) -{ - MetaKmsConnectorPropTable *prop_table = &connector->prop_table; - - *prop_table = (MetaKmsConnectorPropTable) { - .props = { - [META_KMS_CONNECTOR_PROP_CRTC_ID] = - { - .name = "CRTC_ID", - .type = DRM_MODE_PROP_OBJECT, - }, - [META_KMS_CONNECTOR_PROP_DPMS] = - { - .name = "DPMS", - .type = DRM_MODE_PROP_ENUM, - }, - [META_KMS_CONNECTOR_PROP_UNDERSCAN] = - { - .name = "underscan", - .type = DRM_MODE_PROP_ENUM, - }, - [META_KMS_CONNECTOR_PROP_UNDERSCAN_HBORDER] = - { - .name = "underscan hborder", - .type = DRM_MODE_PROP_RANGE, - }, - [META_KMS_CONNECTOR_PROP_UNDERSCAN_VBORDER] = - { - .name = "underscan vborder", - .type = DRM_MODE_PROP_RANGE, - }, - } - }; - - meta_kms_impl_device_init_prop_table (impl_device, - drm_connector->props, - drm_connector->prop_values, - drm_connector->count_props, - connector->prop_table.props, - META_KMS_CONNECTOR_N_PROPS, - NULL); -} - -static char * -make_connector_name (drmModeConnector *drm_connector) -{ - static const char * const connector_type_names[] = { - "None", - "VGA", - "DVI-I", - "DVI-D", - "DVI-A", - "Composite", - "SVIDEO", - "LVDS", - "Component", - "DIN", - "DP", - "HDMI", - "HDMI-B", - "TV", - "eDP", - "Virtual", - "DSI", - }; - - if (drm_connector->connector_type < G_N_ELEMENTS (connector_type_names)) - return g_strdup_printf ("%s-%d", - connector_type_names[drm_connector->connector_type], - drm_connector->connector_type_id); - else - return g_strdup_printf ("Unknown%d-%d", - drm_connector->connector_type, - drm_connector->connector_type_id); -} - -gboolean -meta_kms_connector_is_same_as (MetaKmsConnector *connector, - drmModeConnector *drm_connector) -{ - return (connector->id == drm_connector->connector_id && - connector->type == drm_connector->connector_type && - connector->type_id == drm_connector->connector_type_id); -} - -MetaKmsConnector * -meta_kms_connector_new (MetaKmsImplDevice *impl_device, - drmModeConnector *drm_connector, - drmModeRes *drm_resources) -{ - MetaKmsConnector *connector; - - connector = g_object_new (META_TYPE_KMS_CONNECTOR, NULL); - connector->device = meta_kms_impl_device_get_device (impl_device); - connector->id = drm_connector->connector_id; - connector->type = drm_connector->connector_type; - connector->type_id = drm_connector->connector_type_id; - connector->name = make_connector_name (drm_connector); - - init_properties (connector, impl_device, drm_connector); - - meta_kms_connector_read_state (connector, impl_device, - drm_connector, - drm_resources); - - return connector; -} - -static void -meta_kms_connector_finalize (GObject *object) -{ - MetaKmsConnector *connector = META_KMS_CONNECTOR (object); - - if (connector->fd_held) - { - MetaKmsImplDevice *impl_device; - - impl_device = meta_kms_device_get_impl_device (connector->device); - meta_kms_impl_device_unhold_fd (impl_device); - } - - g_clear_pointer (&connector->current_state, meta_kms_connector_state_free); - g_free (connector->name); - - G_OBJECT_CLASS (meta_kms_connector_parent_class)->finalize (object); -} - -static void -meta_kms_connector_init (MetaKmsConnector *connector) -{ -} - -static void -meta_kms_connector_class_init (MetaKmsConnectorClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_kms_connector_finalize; -} diff --git a/src/backends/native/meta-kms-connector.h b/src/backends/native/meta-kms-connector.h deleted file mode 100644 index a3a7136c5..000000000 --- a/src/backends/native/meta-kms-connector.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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_KMS_CONNECTOR_H -#define META_KMS_CONNECTOR_H - -#include -#include -#include - -#include "backends/meta-output.h" -#include "backends/native/meta-kms-types.h" - -#define META_TYPE_KMS_CONNECTOR (meta_kms_connector_get_type ()) -G_DECLARE_FINAL_TYPE (MetaKmsConnector, meta_kms_connector, - META, KMS_CONNECTOR, GObject) - -typedef struct _MetaKmsConnectorState -{ - uint32_t current_crtc_id; - - uint32_t common_possible_crtcs; - uint32_t common_possible_clones; - uint32_t encoder_device_idxs; - - GList *modes; - - uint32_t width_mm; - uint32_t height_mm; - - MetaTileInfo tile_info; - GBytes *edid_data; - - gboolean has_scaling; - gboolean non_desktop; - - CoglSubpixelOrder subpixel_order; - - int suggested_x; - int suggested_y; - gboolean hotplug_mode_update; - - MetaMonitorTransform panel_orientation_transform; -} MetaKmsConnectorState; - -MetaKmsDevice * meta_kms_connector_get_device (MetaKmsConnector *connector); - -uint32_t meta_kms_connector_get_connector_type (MetaKmsConnector *connector); - -uint32_t meta_kms_connector_get_id (MetaKmsConnector *connector); - -const char * meta_kms_connector_get_name (MetaKmsConnector *connector); - -gboolean meta_kms_connector_can_clone (MetaKmsConnector *connector, - MetaKmsConnector *other_connector); - -const MetaKmsConnectorState * meta_kms_connector_get_current_state (MetaKmsConnector *connector); - -gboolean meta_kms_connector_is_underscanning_supported (MetaKmsConnector *connector); - -#endif /* META_KMS_CONNECTOR_H */ diff --git a/src/backends/native/meta-kms-crtc-private.h b/src/backends/native/meta-kms-crtc-private.h deleted file mode 100644 index 60c5fd309..000000000 --- a/src/backends/native/meta-kms-crtc-private.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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_KMS_CRTC_PRIVATE_H -#define META_KMS_CRTC_PRIVATE_H - -#include - -#include "backends/native/meta-kms-crtc.h" - -typedef enum _MetaKmsCrtcProp -{ - META_KMS_CRTC_PROP_MODE_ID = 0, - META_KMS_CRTC_PROP_ACTIVE, - META_KMS_CRTC_PROP_GAMMA_LUT, - META_KMS_CRTC_N_PROPS -} MetaKmsCrtcProp; - -MetaKmsCrtc * meta_kms_crtc_new (MetaKmsImplDevice *impl_device, - drmModeCrtc *drm_crtc, - int idx, - GError **error); - -void meta_kms_crtc_update_state (MetaKmsCrtc *crtc); - -void meta_kms_crtc_predict_state (MetaKmsCrtc *crtc, - MetaKmsUpdate *update); - -uint32_t meta_kms_crtc_get_prop_id (MetaKmsCrtc *crtc, - MetaKmsCrtcProp prop); - -const char * meta_kms_crtc_get_prop_name (MetaKmsCrtc *crtc, - MetaKmsCrtcProp prop); - -#endif /* META_KMS_CRTC_PRIVATE_H */ diff --git a/src/backends/native/meta-kms-crtc.c b/src/backends/native/meta-kms-crtc.c deleted file mode 100644 index 51d040b44..000000000 --- a/src/backends/native/meta-kms-crtc.c +++ /dev/null @@ -1,399 +0,0 @@ -/* - * 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. - */ - -#include "config.h" - -#include "backends/native/meta-kms-crtc.h" -#include "backends/native/meta-kms-crtc-private.h" - -#include "backends/native/meta-kms-device-private.h" -#include "backends/native/meta-kms-impl-device.h" -#include "backends/native/meta-kms-mode.h" -#include "backends/native/meta-kms-update-private.h" - -typedef struct _MetaKmsCrtcPropTable -{ - MetaKmsProp props[META_KMS_CRTC_N_PROPS]; -} MetaKmsCrtcPropTable; - -struct _MetaKmsCrtc -{ - GObject parent; - - MetaKmsDevice *device; - - uint32_t id; - int idx; - - MetaKmsCrtcState current_state; - - MetaKmsCrtcPropTable prop_table; -}; - -G_DEFINE_TYPE (MetaKmsCrtc, meta_kms_crtc, G_TYPE_OBJECT) - -MetaKmsDevice * -meta_kms_crtc_get_device (MetaKmsCrtc *crtc) -{ - return crtc->device; -} - -const MetaKmsCrtcState * -meta_kms_crtc_get_current_state (MetaKmsCrtc *crtc) -{ - return &crtc->current_state; -} - -uint32_t -meta_kms_crtc_get_id (MetaKmsCrtc *crtc) -{ - return crtc->id; -} - -int -meta_kms_crtc_get_idx (MetaKmsCrtc *crtc) -{ - return crtc->idx; -} - -uint32_t -meta_kms_crtc_get_prop_id (MetaKmsCrtc *crtc, - MetaKmsCrtcProp prop) -{ - return crtc->prop_table.props[prop].prop_id; -} - -const char * -meta_kms_crtc_get_prop_name (MetaKmsCrtc *crtc, - MetaKmsCrtcProp prop) -{ - return crtc->prop_table.props[prop].name; -} - -gboolean -meta_kms_crtc_is_active (MetaKmsCrtc *crtc) -{ - return crtc->current_state.is_active; -} - -static void -read_gamma_state (MetaKmsCrtc *crtc, - MetaKmsImplDevice *impl_device, - drmModeCrtc *drm_crtc) -{ - MetaKmsCrtcState *current_state = &crtc->current_state; - - if (current_state->gamma.size != drm_crtc->gamma_size) - { - current_state->gamma.size = drm_crtc->gamma_size; - - current_state->gamma.red = g_realloc_n (current_state->gamma.red, - drm_crtc->gamma_size, - sizeof (uint16_t)); - current_state->gamma.green = g_realloc_n (current_state->gamma.green, - drm_crtc->gamma_size, - sizeof (uint16_t)); - current_state->gamma.blue = g_realloc_n (current_state->gamma.blue, - drm_crtc->gamma_size, - sizeof (uint16_t)); - } - - drmModeCrtcGetGamma (meta_kms_impl_device_get_fd (impl_device), - crtc->id, - current_state->gamma.size, - current_state->gamma.red, - current_state->gamma.green, - current_state->gamma.blue); -} - -static int -find_prop_idx (MetaKmsProp *prop, - uint32_t *drm_props, - int n_drm_props) -{ - int i; - - g_return_val_if_fail (prop->prop_id > 0, -1); - - for (i = 0; i < n_drm_props; i++) - { - if (drm_props[i] == prop->prop_id) - return i; - } - - return -1; -} - -static void -meta_kms_crtc_read_state (MetaKmsCrtc *crtc, - MetaKmsImplDevice *impl_device, - drmModeCrtc *drm_crtc, - drmModeObjectProperties *drm_props) -{ - MetaKmsProp *active_prop; - int active_idx; - - crtc->current_state.rect = (MetaRectangle) { - .x = drm_crtc->x, - .y = drm_crtc->y, - .width = drm_crtc->width, - .height = drm_crtc->height, - }; - - crtc->current_state.is_drm_mode_valid = drm_crtc->mode_valid; - crtc->current_state.drm_mode = drm_crtc->mode; - - active_prop = &crtc->prop_table.props[META_KMS_CRTC_PROP_ACTIVE]; - if (active_prop->prop_id) - { - active_idx = find_prop_idx (active_prop, - drm_props->props, - drm_props->count_props); - crtc->current_state.is_active = !!drm_props->prop_values[active_idx]; - } - else - { - crtc->current_state.is_active = drm_crtc->mode_valid; - } - - meta_topic (META_DEBUG_KMS, - "Read CRTC %u state: active: %d, mode: %s", - crtc->id, crtc->current_state.is_active, - crtc->current_state.is_drm_mode_valid - ? crtc->current_state.drm_mode.name - : "(nil)"); - - read_gamma_state (crtc, impl_device, drm_crtc); -} - -void -meta_kms_crtc_update_state (MetaKmsCrtc *crtc) -{ - MetaKmsImplDevice *impl_device; - int fd; - drmModeCrtc *drm_crtc; - drmModeObjectProperties *drm_props; - - impl_device = meta_kms_device_get_impl_device (crtc->device); - fd = meta_kms_impl_device_get_fd (impl_device); - - drm_crtc = drmModeGetCrtc (fd, crtc->id); - drm_props = drmModeObjectGetProperties (fd, crtc->id, DRM_MODE_OBJECT_CRTC); - - if (!drm_crtc || !drm_props) - { - crtc->current_state.is_active = FALSE; - crtc->current_state.rect = (MetaRectangle) { }; - crtc->current_state.is_drm_mode_valid = FALSE; - goto out; - } - - meta_kms_crtc_read_state (crtc, impl_device, drm_crtc, drm_props); - -out: - g_clear_pointer (&drm_props, drmModeFreeObjectProperties); - g_clear_pointer (&drm_crtc, drmModeFreeCrtc); -} - -static void -clear_gamma_state (MetaKmsCrtc *crtc) -{ - crtc->current_state.gamma.size = 0; - g_clear_pointer (&crtc->current_state.gamma.red, g_free); - g_clear_pointer (&crtc->current_state.gamma.green, g_free); - g_clear_pointer (&crtc->current_state.gamma.blue, g_free); -} - -void -meta_kms_crtc_predict_state (MetaKmsCrtc *crtc, - MetaKmsUpdate *update) -{ - GList *mode_sets; - GList *crtc_gammas; - GList *l; - - mode_sets = meta_kms_update_get_mode_sets (update); - for (l = mode_sets; l; l = l->next) - { - MetaKmsModeSet *mode_set = l->data; - - if (mode_set->crtc != crtc) - continue; - - if (mode_set->mode) - { - MetaKmsPlaneAssignment *plane_assignment; - const drmModeModeInfo *drm_mode; - - plane_assignment = - meta_kms_update_get_primary_plane_assignment (update, crtc); - drm_mode = meta_kms_mode_get_drm_mode (mode_set->mode); - - crtc->current_state.is_active = TRUE; - crtc->current_state.rect = - meta_fixed_16_rectangle_to_rectangle (plane_assignment->src_rect); - crtc->current_state.is_drm_mode_valid = TRUE; - crtc->current_state.drm_mode = *drm_mode; - } - else - { - crtc->current_state.is_active = FALSE; - crtc->current_state.rect = (MetaRectangle) { 0 }; - crtc->current_state.is_drm_mode_valid = FALSE; - crtc->current_state.drm_mode = (drmModeModeInfo) { 0 }; - } - - break; - } - - crtc_gammas = meta_kms_update_get_crtc_gammas (update); - for (l = crtc_gammas; l; l = l->next) - { - MetaKmsCrtcGamma *gamma = l->data; - - if (gamma->crtc != crtc) - continue; - - clear_gamma_state (crtc); - crtc->current_state.gamma.size = gamma->size; - crtc->current_state.gamma.red = - g_memdup2 (gamma->red, gamma->size * sizeof (uint16_t)); - crtc->current_state.gamma.green = - g_memdup2 (gamma->green, gamma->size * sizeof (uint16_t)); - crtc->current_state.gamma.blue = - g_memdup2 (gamma->blue, gamma->size * sizeof (uint16_t)); - - break; - } -} - -static void -parse_active (MetaKmsImplDevice *impl_device, - MetaKmsProp *prop, - drmModePropertyPtr drm_prop, - uint64_t drm_prop_value, - gpointer user_data) -{ - MetaKmsCrtc *crtc = user_data; - - crtc->current_state.is_active = !!drm_prop_value; -} - -static void -init_proporties (MetaKmsCrtc *crtc, - MetaKmsImplDevice *impl_device, - drmModeCrtc *drm_crtc) -{ - MetaKmsCrtcPropTable *prop_table = &crtc->prop_table; - int fd; - drmModeObjectProperties *drm_props; - - *prop_table = (MetaKmsCrtcPropTable) { - .props = { - [META_KMS_CRTC_PROP_MODE_ID] = - { - .name = "MODE_ID", - .type = DRM_MODE_PROP_BLOB, - }, - [META_KMS_CRTC_PROP_ACTIVE] = - { - .name = "ACTIVE", - .type = DRM_MODE_PROP_RANGE, - .parse = parse_active, - }, - [META_KMS_CRTC_PROP_GAMMA_LUT] = - { - .name = "GAMMA_LUT", - .type = DRM_MODE_PROP_BLOB, - }, - } - }; - - fd = meta_kms_impl_device_get_fd (impl_device); - drm_props = drmModeObjectGetProperties (fd, - drm_crtc->crtc_id, - DRM_MODE_OBJECT_CRTC); - - meta_kms_impl_device_init_prop_table (impl_device, - drm_props->props, - drm_props->prop_values, - drm_props->count_props, - crtc->prop_table.props, - META_KMS_CRTC_N_PROPS, - crtc); - - drmModeFreeObjectProperties (drm_props); -} - -MetaKmsCrtc * -meta_kms_crtc_new (MetaKmsImplDevice *impl_device, - drmModeCrtc *drm_crtc, - int idx, - GError **error) -{ - int fd; - drmModeObjectProperties *drm_props; - MetaKmsCrtc *crtc; - - fd = meta_kms_impl_device_get_fd (impl_device); - drm_props = drmModeObjectGetProperties (fd, drm_crtc->crtc_id, - DRM_MODE_OBJECT_CRTC); - if (!drm_props) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "drmModeObjectGetProperties: %s", g_strerror (errno)); - return NULL; - } - - crtc = g_object_new (META_TYPE_KMS_CRTC, NULL); - crtc->device = meta_kms_impl_device_get_device (impl_device); - crtc->id = drm_crtc->crtc_id; - crtc->idx = idx; - - init_proporties (crtc, impl_device, drm_crtc); - - meta_kms_crtc_read_state (crtc, impl_device, drm_crtc, drm_props); - - drmModeFreeObjectProperties (drm_props); - - return crtc; -} - -static void -meta_kms_crtc_finalize (GObject *object) -{ - MetaKmsCrtc *crtc = META_KMS_CRTC (object); - - clear_gamma_state (crtc); - - G_OBJECT_CLASS (meta_kms_crtc_parent_class)->finalize (object); -} - -static void -meta_kms_crtc_init (MetaKmsCrtc *crtc) -{ -} - -static void -meta_kms_crtc_class_init (MetaKmsCrtcClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_kms_crtc_finalize; -} diff --git a/src/backends/native/meta-kms-crtc.h b/src/backends/native/meta-kms-crtc.h deleted file mode 100644 index 406ca3ac1..000000000 --- a/src/backends/native/meta-kms-crtc.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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_KMS_CRTC_H -#define META_KMS_CRTC_H - -#include -#include -#include - -#include "backends/native/meta-kms-types.h" -#include "meta/boxes.h" - -typedef struct _MetaKmsCrtcState -{ - gboolean is_active; - - MetaRectangle rect; - gboolean is_drm_mode_valid; - drmModeModeInfo drm_mode; - - struct { - uint16_t *red; - uint16_t *green; - uint16_t *blue; - - int size; - } gamma; -} MetaKmsCrtcState; - -typedef struct _MetaKmsCrtcGamma -{ - MetaKmsCrtc *crtc; - int size; - uint16_t *red; - uint16_t *green; - uint16_t *blue; -} MetaKmsCrtcGamma; - -#define META_TYPE_KMS_CRTC (meta_kms_crtc_get_type ()) -G_DECLARE_FINAL_TYPE (MetaKmsCrtc, meta_kms_crtc, - META, KMS_CRTC, - GObject) - -MetaKmsDevice * meta_kms_crtc_get_device (MetaKmsCrtc *crtc); - -const MetaKmsCrtcState * meta_kms_crtc_get_current_state (MetaKmsCrtc *crtc); - -uint32_t meta_kms_crtc_get_id (MetaKmsCrtc *crtc); - -int meta_kms_crtc_get_idx (MetaKmsCrtc *crtc); - -gboolean meta_kms_crtc_is_active (MetaKmsCrtc *crtc); - -void meta_kms_crtc_gamma_free (MetaKmsCrtcGamma *gamma); - -MetaKmsCrtcGamma * meta_kms_crtc_gamma_new (MetaKmsCrtc *crtc, - int size, - const uint16_t *red, - const uint16_t *green, - const uint16_t *blue); - -#endif /* META_KMS_CRTC_H */ diff --git a/src/backends/native/meta-kms-device-private.h b/src/backends/native/meta-kms-device-private.h deleted file mode 100644 index 41e05a2f7..000000000 --- a/src/backends/native/meta-kms-device-private.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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_KMS_DEVICE_PRIVATE_H -#define META_KMS_DEVICE_PRIVATE_H - -#include "backends/native/meta-kms-types.h" - -MetaKmsImplDevice * meta_kms_device_get_impl_device (MetaKmsDevice *device); - -void meta_kms_device_update_states_in_impl (MetaKmsDevice *device); - -void meta_kms_device_predict_states_in_impl (MetaKmsDevice *device, - MetaKmsUpdate *update); - -void meta_kms_device_add_fake_plane_in_impl (MetaKmsDevice *device, - MetaKmsPlaneType plane_type, - MetaKmsCrtc *crtc); - -#endif /* META_KMS_DEVICE_PRIVATE_H */ diff --git a/src/backends/native/meta-kms-device.c b/src/backends/native/meta-kms-device.c deleted file mode 100644 index b4d3e5802..000000000 --- a/src/backends/native/meta-kms-device.c +++ /dev/null @@ -1,439 +0,0 @@ -/* - * Copyright (C) 2019 Red Hat - * Copyright (C) 2019 DisplayLink (UK) Ltd. - * - * 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 "backends/native/meta-kms-device-private.h" -#include "backends/native/meta-kms-device.h" - -#include -#include -#include -#include - -#include "backends/native/meta-backend-native-private.h" -#include "backends/native/meta-device-pool.h" -#include "backends/native/meta-kms-impl-device-atomic.h" -#include "backends/native/meta-kms-impl-device-dummy.h" -#include "backends/native/meta-kms-impl-device-simple.h" -#include "backends/native/meta-kms-impl-device.h" -#include "backends/native/meta-kms-impl.h" -#include "backends/native/meta-kms-plane.h" -#include "backends/native/meta-kms-private.h" - -struct _MetaKmsDevice -{ - GObject parent; - - MetaKms *kms; - - MetaKmsImplDevice *impl_device; - - MetaKmsDeviceFlag flags; - char *path; - char *driver_name; - char *driver_description; - - GList *crtcs; - GList *connectors; - GList *planes; - - MetaKmsDeviceCaps caps; - - GList *fallback_modes; -}; - -G_DEFINE_TYPE (MetaKmsDevice, meta_kms_device, G_TYPE_OBJECT); - -MetaKms * -meta_kms_device_get_kms (MetaKmsDevice *device) -{ - return device->kms; -} - -MetaKmsImplDevice * -meta_kms_device_get_impl_device (MetaKmsDevice *device) -{ - return device->impl_device; -} - -const char * -meta_kms_device_get_path (MetaKmsDevice *device) -{ - return device->path; -} - -const char * -meta_kms_device_get_driver_name (MetaKmsDevice *device) -{ - return device->driver_name; -} - -const char * -meta_kms_device_get_driver_description (MetaKmsDevice *device) -{ - return device->driver_description; -} - -MetaKmsDeviceFlag -meta_kms_device_get_flags (MetaKmsDevice *device) -{ - return device->flags; -} - -gboolean -meta_kms_device_get_cursor_size (MetaKmsDevice *device, - uint64_t *out_cursor_width, - uint64_t *out_cursor_height) -{ - if (device->caps.has_cursor_size) - { - *out_cursor_width = device->caps.cursor_width; - *out_cursor_height = device->caps.cursor_height; - return TRUE; - } - else - { - return FALSE; - } -} - -gboolean -meta_kms_device_prefers_shadow_buffer (MetaKmsDevice *device) -{ - return device->caps.prefers_shadow_buffer; -} - -gboolean -meta_kms_device_uses_monotonic_clock (MetaKmsDevice *device) -{ - return device->caps.uses_monotonic_clock; -} - -GList * -meta_kms_device_get_connectors (MetaKmsDevice *device) -{ - return device->connectors; -} - -GList * -meta_kms_device_get_crtcs (MetaKmsDevice *device) -{ - return device->crtcs; -} - -GList * -meta_kms_device_get_planes (MetaKmsDevice *device) -{ - return device->planes; -} - -static MetaKmsPlane * -get_plane_with_type_for (MetaKmsDevice *device, - MetaKmsCrtc *crtc, - MetaKmsPlaneType type) -{ - GList *l; - - for (l = meta_kms_device_get_planes (device); l; l = l->next) - { - MetaKmsPlane *plane = l->data; - - if (meta_kms_plane_get_plane_type (plane) != type) - continue; - - if (meta_kms_plane_is_usable_with (plane, crtc)) - return plane; - } - - return NULL; -} - -MetaKmsPlane * -meta_kms_device_get_primary_plane_for (MetaKmsDevice *device, - MetaKmsCrtc *crtc) -{ - return get_plane_with_type_for (device, crtc, META_KMS_PLANE_TYPE_PRIMARY); -} - -MetaKmsPlane * -meta_kms_device_get_cursor_plane_for (MetaKmsDevice *device, - MetaKmsCrtc *crtc) -{ - return get_plane_with_type_for (device, crtc, META_KMS_PLANE_TYPE_CURSOR); -} - -GList * -meta_kms_device_get_fallback_modes (MetaKmsDevice *device) -{ - return device->fallback_modes; -} - -void -meta_kms_device_update_states_in_impl (MetaKmsDevice *device) -{ - MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device); - - meta_assert_in_kms_impl (device->kms); - meta_assert_is_waiting_for_kms_impl_task (device->kms); - - meta_kms_impl_device_update_states (impl_device); - - g_list_free (device->crtcs); - device->crtcs = meta_kms_impl_device_copy_crtcs (impl_device); - - g_list_free (device->connectors); - device->connectors = meta_kms_impl_device_copy_connectors (impl_device); - - g_list_free (device->planes); - device->planes = meta_kms_impl_device_copy_planes (impl_device); -} - -void -meta_kms_device_predict_states_in_impl (MetaKmsDevice *device, - MetaKmsUpdate *update) -{ - MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device); - - meta_assert_in_kms_impl (device->kms); - - meta_kms_impl_device_predict_states (impl_device, update); -} - -void -meta_kms_device_add_fake_plane_in_impl (MetaKmsDevice *device, - MetaKmsPlaneType plane_type, - MetaKmsCrtc *crtc) -{ - MetaKmsImplDevice *impl_device = device->impl_device; - MetaKmsPlane *plane; - - meta_assert_in_kms_impl (device->kms); - - plane = meta_kms_impl_device_add_fake_plane (impl_device, - plane_type, - crtc); - device->planes = g_list_append (device->planes, plane); -} - -typedef struct _CreateImplDeviceData -{ - MetaKmsDevice *device; - const char *path; - MetaKmsDeviceFlag flags; - - MetaKmsImplDevice *out_impl_device; - GList *out_crtcs; - GList *out_connectors; - GList *out_planes; - MetaKmsDeviceCaps out_caps; - GList *out_fallback_modes; - char *out_driver_name; - char *out_driver_description; - char *out_path; -} CreateImplDeviceData; - -static const char * -impl_device_type_to_string (GType type) -{ - if (type == META_TYPE_KMS_IMPL_DEVICE_ATOMIC) - return "atomic modesetting"; - else if (type == META_TYPE_KMS_IMPL_DEVICE_SIMPLE) - return "legacy modesetting"; - else if (type == META_TYPE_KMS_IMPL_DEVICE_DUMMY) - return "no modesetting"; - g_assert_not_reached(); -} - -static MetaKmsImplDevice * -meta_create_kms_impl_device (MetaKmsDevice *device, - MetaKmsImpl *impl, - const char *path, - MetaKmsDeviceFlag flags, - GError **error) -{ - meta_assert_in_kms_impl (meta_kms_impl_get_kms (impl)); - - if (flags & META_KMS_DEVICE_FLAG_NO_MODE_SETTING) - { - return g_initable_new (META_TYPE_KMS_IMPL_DEVICE_DUMMY, - NULL, error, - "device", device, - "impl", impl, - "path", path, - "flags", flags, - NULL); - } - else - { - GType impl_device_types[] = { - META_TYPE_KMS_IMPL_DEVICE_ATOMIC, - META_TYPE_KMS_IMPL_DEVICE_SIMPLE, - }; - int i; - - for (i = 0; i < G_N_ELEMENTS (impl_device_types); i++) - { - MetaKmsImplDevice *impl_device; - g_autoptr (GError) local_error = NULL; - - impl_device = g_initable_new (impl_device_types[i], - NULL, &local_error, - "device", device, - "impl", impl, - "path", path, - "flags", flags, - NULL); - if (impl_device) - return impl_device; - - if (local_error->domain != META_KMS_ERROR) - { - g_warning ("Failed to open %s backend: %s", - impl_device_type_to_string (impl_device_types[i]), - local_error->message); - } - } - - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "No suitable mode setting backend found"); - - return NULL; - } -} - -static gpointer -create_impl_device_in_impl (MetaKmsImpl *impl, - gpointer user_data, - GError **error) -{ - CreateImplDeviceData *data = user_data; - MetaKmsImplDevice *impl_device; - - impl_device = meta_create_kms_impl_device (data->device, - impl, - data->path, - data->flags, - error); - if (!impl_device) - return FALSE; - - meta_kms_impl_add_impl_device (impl, impl_device); - - data->out_impl_device = impl_device; - data->out_crtcs = meta_kms_impl_device_copy_crtcs (impl_device); - data->out_connectors = meta_kms_impl_device_copy_connectors (impl_device); - data->out_planes = meta_kms_impl_device_copy_planes (impl_device); - data->out_caps = *meta_kms_impl_device_get_caps (impl_device); - data->out_fallback_modes = - meta_kms_impl_device_copy_fallback_modes (impl_device); - data->out_driver_name = - g_strdup (meta_kms_impl_device_get_driver_name (impl_device)); - data->out_driver_description = - g_strdup (meta_kms_impl_device_get_driver_description (impl_device)); - data->out_path = g_strdup (meta_kms_impl_device_get_path (impl_device)); - - return GINT_TO_POINTER (TRUE); -} - -MetaKmsDevice * -meta_kms_device_new (MetaKms *kms, - const char *path, - MetaKmsDeviceFlag flags, - GError **error) -{ - MetaKmsDevice *device; - CreateImplDeviceData data; - - device = g_object_new (META_TYPE_KMS_DEVICE, NULL); - device->kms = kms; - - data = (CreateImplDeviceData) { - .device = device, - .path = path, - .flags = flags, - }; - if (!meta_kms_run_impl_task_sync (kms, create_impl_device_in_impl, &data, - error)) - { - g_object_unref (device); - return NULL; - } - - device->impl_device = data.out_impl_device; - device->flags = flags; - device->path = g_strdup (path); - device->crtcs = data.out_crtcs; - device->connectors = data.out_connectors; - device->planes = data.out_planes; - device->caps = data.out_caps; - device->fallback_modes = data.out_fallback_modes; - device->driver_name = data.out_driver_name; - device->driver_description = data.out_driver_description; - free (device->path); - device->path = data.out_path; - - return device; -} - -static gpointer -free_impl_device_in_impl (MetaKmsImpl *impl, - gpointer user_data, - GError **error) -{ - MetaKmsImplDevice *impl_device = user_data; - - g_object_unref (impl_device); - - return GINT_TO_POINTER (TRUE); -} - -static void -meta_kms_device_finalize (GObject *object) -{ - MetaKmsDevice *device = META_KMS_DEVICE (object); - - g_free (device->path); - g_list_free (device->crtcs); - g_list_free (device->connectors); - g_list_free (device->planes); - - if (device->impl_device) - { - meta_kms_run_impl_task_sync (device->kms, free_impl_device_in_impl, - device->impl_device, - NULL); - } - - G_OBJECT_CLASS (meta_kms_device_parent_class)->finalize (object); -} - -static void -meta_kms_device_init (MetaKmsDevice *device) -{ -} - -static void -meta_kms_device_class_init (MetaKmsDeviceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_kms_device_finalize; -} diff --git a/src/backends/native/meta-kms-device.h b/src/backends/native/meta-kms-device.h deleted file mode 100644 index 58dda6136..000000000 --- a/src/backends/native/meta-kms-device.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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_KMS_DEVICE_H -#define META_KMS_DEVICE_H - -#include - -#include "backends/native/meta-kms-types.h" - -#define META_TYPE_KMS_DEVICE (meta_kms_device_get_type ()) -G_DECLARE_FINAL_TYPE (MetaKmsDevice, meta_kms_device, - META, KMS_DEVICE, - GObject) - -MetaKms * meta_kms_device_get_kms (MetaKmsDevice *device); - -const char * meta_kms_device_get_path (MetaKmsDevice *device); - -const char * meta_kms_device_get_driver_name (MetaKmsDevice *device); - -const char * meta_kms_device_get_driver_description (MetaKmsDevice *device); - -MetaKmsDeviceFlag meta_kms_device_get_flags (MetaKmsDevice *device); - -gboolean meta_kms_device_get_cursor_size (MetaKmsDevice *device, - uint64_t *out_cursor_width, - uint64_t *out_cursor_height); - -gboolean meta_kms_device_prefers_shadow_buffer (MetaKmsDevice *device); - -gboolean meta_kms_device_uses_monotonic_clock (MetaKmsDevice *device); - -GList * meta_kms_device_get_connectors (MetaKmsDevice *device); - -GList * meta_kms_device_get_crtcs (MetaKmsDevice *device); - -GList * meta_kms_device_get_planes (MetaKmsDevice *device); - -MetaKmsPlane * meta_kms_device_get_primary_plane_for (MetaKmsDevice *device, - MetaKmsCrtc *crtc); - -MetaKmsPlane * meta_kms_device_get_cursor_plane_for (MetaKmsDevice *device, - MetaKmsCrtc *crtc); - -GList * meta_kms_device_get_fallback_modes (MetaKmsDevice *device); - -MetaKmsDevice * meta_kms_device_new (MetaKms *kms, - const char *path, - MetaKmsDeviceFlag flags, - GError **error); - -#endif /* META_KMS_DEVICE_H */ diff --git a/src/backends/native/meta-kms-impl-device-atomic.c b/src/backends/native/meta-kms-impl-device-atomic.c deleted file mode 100644 index 8e41207ee..000000000 --- a/src/backends/native/meta-kms-impl-device-atomic.c +++ /dev/null @@ -1,1202 +0,0 @@ -/* - * Copyright (C) 2019-2020 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. - */ - -#include "config.h" - -#include "backends/native/meta-kms-impl-device-atomic.h" - -#include "backends/native/meta-backend-native-private.h" -#include "backends/native/meta-kms-connector-private.h" -#include "backends/native/meta-kms-crtc-private.h" -#include "backends/native/meta-kms-device-private.h" -#include "backends/native/meta-kms-mode-private.h" -#include "backends/native/meta-kms-plane-private.h" -#include "backends/native/meta-kms-private.h" -#include "backends/native/meta-kms-update-private.h" - -typedef gboolean (* MetaKmsAtomicProcessFunc) (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - drmModeAtomicReq *req, - GArray *blob_ids, - gpointer entry_data, - gpointer user_data, - GError **error); - -struct _MetaKmsImplDeviceAtomic -{ - MetaKmsImplDevice parent; - - GHashTable *page_flip_datas; -}; - -static GInitableIface *initable_parent_iface; - -static void -initable_iface_init (GInitableIface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaKmsImplDeviceAtomic, meta_kms_impl_device_atomic, - META_TYPE_KMS_IMPL_DEVICE, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - initable_iface_init)) - -static uint32_t -store_new_blob (MetaKmsImplDevice *impl_device, - GArray *blob_ids, - const void *data, - size_t size, - GError **error) -{ - int fd = meta_kms_impl_device_get_fd (impl_device); - uint32_t blob_id; - int ret; - - ret = drmModeCreatePropertyBlob (fd, data, size, &blob_id); - if (ret < 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModeCreatePropertyBlob: %s", g_strerror (-ret)); - return 0; - } - - g_array_append_val (blob_ids, blob_id); - - return blob_id; -} - -static void -release_blob_ids (MetaKmsImplDevice *impl_device, - GArray *blob_ids) -{ - int fd = meta_kms_impl_device_get_fd (impl_device); - unsigned int i; - - for (i = 0; i < blob_ids->len; i++) - { - uint32_t blob_id = g_array_index (blob_ids, uint32_t, i); - - drmModeDestroyPropertyBlob (fd, blob_id); - } -} - -static gboolean -add_connector_property (MetaKmsImplDevice *impl_device, - MetaKmsConnector *connector, - drmModeAtomicReq *req, - MetaKmsConnectorProp prop, - uint64_t value, - GError **error) -{ - int ret; - uint32_t prop_id; - - prop_id = meta_kms_connector_get_prop_id (connector, prop); - if (!prop_id) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - "Connector property '%s' not found", - meta_kms_connector_get_prop_name (connector, prop)); - return FALSE; - } - - meta_topic (META_DEBUG_KMS, - "[atomic] Setting connector %u (%s) property '%s' (%u) to %" - G_GUINT64_FORMAT, - meta_kms_connector_get_id (connector), - meta_kms_impl_device_get_path (impl_device), - meta_kms_connector_get_prop_name (connector, prop), - meta_kms_connector_get_prop_id (connector, prop), - value); - ret = drmModeAtomicAddProperty (req, - meta_kms_connector_get_id (connector), - prop_id, - value); - if (ret < 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModeAtomicAddProperty, connector: %u, prop id: %u: %s", - meta_kms_connector_get_id (connector), - prop_id, - g_strerror (-ret)); - return FALSE; - } - - return TRUE; -} - -static gboolean -process_connector_update (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - drmModeAtomicReq *req, - GArray *blob_ids, - gpointer update_entry, - gpointer user_data, - GError **error) -{ - MetaKmsConnectorUpdate *connector_update = update_entry; - MetaKmsConnector *connector = connector_update->connector; - - if (connector_update->underscanning.has_update && - connector_update->underscanning.is_active) - { - meta_topic (META_DEBUG_KMS, - "[atomic] Setting underscanning on connector %u (%s) to " - "%" G_GUINT64_FORMAT "x%" G_GUINT64_FORMAT, - meta_kms_connector_get_id (connector), - meta_kms_impl_device_get_path (impl_device), - connector_update->underscanning.hborder, - connector_update->underscanning.vborder); - - if (!add_connector_property (impl_device, - connector, req, - META_KMS_CONNECTOR_PROP_UNDERSCAN, - 1, - error)) - return FALSE; - if (!add_connector_property (impl_device, - connector, req, - META_KMS_CONNECTOR_PROP_UNDERSCAN_HBORDER, - connector_update->underscanning.hborder, - error)) - return FALSE; - if (!add_connector_property (impl_device, - connector, req, - META_KMS_CONNECTOR_PROP_UNDERSCAN_VBORDER, - connector_update->underscanning.vborder, - error)) - return FALSE; - } - else if (connector_update->underscanning.has_update) - { - meta_topic (META_DEBUG_KMS, - "[atomic] Unsetting underscanning on connector %u (%s)", - meta_kms_connector_get_id (connector), - meta_kms_impl_device_get_path (impl_device)); - - if (!add_connector_property (impl_device, - connector, req, - META_KMS_CONNECTOR_PROP_UNDERSCAN, - 0, - error)) - return FALSE; - } - - return TRUE; -} - -static gboolean -add_crtc_property (MetaKmsImplDevice *impl_device, - MetaKmsCrtc *crtc, - drmModeAtomicReq *req, - MetaKmsCrtcProp prop, - uint64_t value, - GError **error) -{ - int ret; - uint32_t prop_id; - - prop_id = meta_kms_crtc_get_prop_id (crtc, prop); - if (!prop_id) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - "CRTC property (%s) not found", - meta_kms_crtc_get_prop_name (crtc, prop)); - return FALSE; - } - - meta_topic (META_DEBUG_KMS, - "[atomic] Setting CRTC %u (%s) property '%s' (%u) to %" - G_GUINT64_FORMAT, - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device), - meta_kms_crtc_get_prop_name (crtc, prop), - meta_kms_crtc_get_prop_id (crtc, prop), - value); - ret = drmModeAtomicAddProperty (req, - meta_kms_crtc_get_id (crtc), - prop_id, - value); - if (ret < 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModeAtomicAddProperty, crtc: %u, prop: %s (%u): %s", - meta_kms_crtc_get_id (crtc), - meta_kms_crtc_get_prop_name (crtc, prop), - prop_id, - g_strerror (-ret)); - return FALSE; - } - - return TRUE; -} - -static gboolean -process_mode_set (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - drmModeAtomicReq *req, - GArray *blob_ids, - gpointer update_entry, - gpointer user_data, - GError **error) -{ - MetaKmsModeSet *mode_set = update_entry; - MetaKmsCrtc *crtc = mode_set->crtc; - MetaKmsMode *mode; - - mode = (MetaKmsMode *) mode_set->mode; - if (mode) - { - uint32_t mode_id; - GList *l; - - mode_id = meta_kms_mode_create_blob_id (mode, error); - if (mode_id == 0) - return FALSE; - - g_array_append_val (blob_ids, mode_id); - - meta_topic (META_DEBUG_KMS, - "[atomic] Setting mode of CRTC %u (%s) to %s", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device), - meta_kms_mode_get_name (mode)); - - if (!add_crtc_property (impl_device, - crtc, req, - META_KMS_CRTC_PROP_MODE_ID, - mode_id, - error)) - return FALSE; - - if (!add_crtc_property (impl_device, - crtc, req, - META_KMS_CRTC_PROP_ACTIVE, - 1, - error)) - return FALSE; - - for (l = mode_set->connectors; l; l = l->next) - { - MetaKmsConnector *connector = l->data; - - if (!add_connector_property (impl_device, - connector, req, - META_KMS_CONNECTOR_PROP_CRTC_ID, - meta_kms_crtc_get_id (crtc), - error)) - return FALSE; - } - } - else - { - if (!add_crtc_property (impl_device, - crtc, req, - META_KMS_CRTC_PROP_MODE_ID, - 0, - error)) - return FALSE; - - if (!add_crtc_property (impl_device, - crtc, req, - META_KMS_CRTC_PROP_ACTIVE, - 0, - error)) - return FALSE; - - meta_topic (META_DEBUG_KMS, - "[atomic] Unsetting mode of (%u, %s)", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device)); - } - - return TRUE; -} - -static gboolean -add_plane_property (MetaKmsImplDevice *impl_device, - MetaKmsPlane *plane, - drmModeAtomicReq *req, - MetaKmsCrtcProp prop, - uint64_t value, - GError **error) -{ - int ret; - uint32_t prop_id; - - prop_id = meta_kms_plane_get_prop_id (plane, prop); - if (!prop_id) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - "Plane property (%s) not found on %u", - meta_kms_plane_get_prop_name (plane, prop), - meta_kms_plane_get_id (plane)); - return FALSE; - } - - switch (meta_kms_plane_get_prop_internal_type (plane, prop)) - { - case META_KMS_PROP_TYPE_RAW: - meta_topic (META_DEBUG_KMS, - "[atomic] Setting plane %u (%s) property '%s' (%u) to %" - G_GUINT64_FORMAT, - meta_kms_plane_get_id (plane), - meta_kms_impl_device_get_path (impl_device), - meta_kms_plane_get_prop_name (plane, prop), - meta_kms_plane_get_prop_id (plane, prop), - value); - break; - case META_KMS_PROP_TYPE_FIXED_16: - meta_topic (META_DEBUG_KMS, - "[atomic] Setting plane %u (%s) property '%s' (%u) to %.2f", - meta_kms_plane_get_id (plane), - meta_kms_impl_device_get_path (impl_device), - meta_kms_plane_get_prop_name (plane, prop), - meta_kms_plane_get_prop_id (plane, prop), - meta_fixed_16_to_double (value)); - break; - } - ret = drmModeAtomicAddProperty (req, - meta_kms_plane_get_id (plane), - prop_id, - value); - if (ret < 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModeAtomicAddProperty, plane: %u, prop: %s (%u): %s", - meta_kms_plane_get_id (plane), - meta_kms_plane_get_prop_name (plane, prop), - prop_id, - g_strerror (-ret)); - return FALSE; - } - - return TRUE; -} - -static const char * -get_plane_type_string (MetaKmsPlane *plane) -{ - switch (meta_kms_plane_get_plane_type (plane)) - { - case META_KMS_PLANE_TYPE_PRIMARY: - return "primary"; - case META_KMS_PLANE_TYPE_CURSOR: - return "cursor"; - case META_KMS_PLANE_TYPE_OVERLAY: - return "overlay"; - } - - g_assert_not_reached (); -} - -static gboolean -process_plane_assignment (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - drmModeAtomicReq *req, - GArray *blob_ids, - gpointer update_entry, - gpointer user_data, - GError **error) -{ - MetaKmsPlaneAssignment *plane_assignment = update_entry; - MetaKmsPlane *plane = plane_assignment->plane; - MetaDrmBuffer *buffer; - - buffer = plane_assignment->buffer; - - meta_topic (META_DEBUG_KMS, - "[atomic] Assigning %s plane (%u, %s) to %u, " - "%hdx%hd+%hd+%hd -> %dx%d+%d+%d", - get_plane_type_string (plane), - meta_kms_plane_get_id (plane), - meta_kms_impl_device_get_path (impl_device), - buffer ? meta_drm_buffer_get_fb_id (buffer) : 0, - meta_fixed_16_to_int (plane_assignment->src_rect.width), - meta_fixed_16_to_int (plane_assignment->src_rect.height), - meta_fixed_16_to_int (plane_assignment->src_rect.x), - meta_fixed_16_to_int (plane_assignment->src_rect.y), - plane_assignment->dst_rect.width, - plane_assignment->dst_rect.height, - plane_assignment->dst_rect.x, - plane_assignment->dst_rect.y); - - if (buffer) - { - int i; - struct { - MetaKmsPlaneProp prop; - uint64_t value; - } props[] = { - { - .prop = META_KMS_PLANE_PROP_FB_ID, - .value = meta_drm_buffer_get_fb_id (buffer), - }, - { - .prop = META_KMS_PLANE_PROP_CRTC_ID, - .value = meta_kms_crtc_get_id (plane_assignment->crtc), - }, - { - .prop = META_KMS_PLANE_PROP_SRC_X, - .value = plane_assignment->src_rect.x, - }, - { - .prop = META_KMS_PLANE_PROP_SRC_Y, - .value = plane_assignment->src_rect.y, - }, - { - .prop = META_KMS_PLANE_PROP_SRC_W, - .value = plane_assignment->src_rect.width, - }, - { - .prop = META_KMS_PLANE_PROP_SRC_H, - .value = plane_assignment->src_rect.height, - }, - { - .prop = META_KMS_PLANE_PROP_CRTC_X, - .value = plane_assignment->dst_rect.x, - }, - { - .prop = META_KMS_PLANE_PROP_CRTC_Y, - .value = plane_assignment->dst_rect.y, - }, - { - .prop = META_KMS_PLANE_PROP_CRTC_W, - .value = plane_assignment->dst_rect.width, - }, - { - .prop = META_KMS_PLANE_PROP_CRTC_H, - .value = plane_assignment->dst_rect.height, - }, - }; - - for (i = 0; i < G_N_ELEMENTS (props); i++) - { - if (!add_plane_property (impl_device, - plane, req, - props[i].prop, - props[i].value, - error)) - return FALSE; - } - } - else - { - int i; - struct { - MetaKmsPlaneProp prop; - uint64_t value; - } props[] = { - { - .prop = META_KMS_PLANE_PROP_FB_ID, - .value = 0, - }, - { - .prop = META_KMS_PLANE_PROP_CRTC_ID, - .value = 0, - }, - }; - - for (i = 0; i < G_N_ELEMENTS (props); i++) - { - if (!add_plane_property (impl_device, - plane, req, - props[i].prop, - props[i].value, - error)) - return FALSE; - } - } - - if (plane_assignment->rotation) - { - meta_topic (META_DEBUG_KMS, - "[atomic] Setting plane (%u, %s) rotation to %" - G_GUINT64_FORMAT, - meta_kms_plane_get_id (plane), - meta_kms_impl_device_get_path (impl_device), - plane_assignment->rotation); - - if (!add_plane_property (impl_device, - plane, req, - META_KMS_PLANE_PROP_ROTATION, - plane_assignment->rotation, - error)) - return FALSE; - } - - return TRUE; -} - -static gboolean -process_crtc_gamma (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - drmModeAtomicReq *req, - GArray *blob_ids, - gpointer update_entry, - gpointer user_data, - GError **error) -{ - MetaKmsCrtcGamma *gamma = update_entry; - MetaKmsCrtc *crtc = gamma->crtc; - struct drm_color_lut drm_color_lut[gamma->size]; - int i; - uint32_t color_lut_blob_id; - - for (i = 0; i < gamma->size; i++) - { - drm_color_lut[i].red = gamma->red[i]; - drm_color_lut[i].green = gamma->green[i]; - drm_color_lut[i].blue = gamma->blue[i]; - } - - color_lut_blob_id = store_new_blob (impl_device, - blob_ids, - drm_color_lut, - sizeof drm_color_lut, - error); - if (!color_lut_blob_id) - return FALSE; - - meta_topic (META_DEBUG_KMS, - "[atomic] Setting CRTC (%u, %s) gamma, size: %d", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device), - gamma->size); - - if (!add_crtc_property (impl_device, - crtc, req, - META_KMS_CRTC_PROP_GAMMA_LUT, - color_lut_blob_id, - error)) - return FALSE; - - return TRUE; -} - -static gboolean -process_page_flip_listener (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - drmModeAtomicReq *req, - GArray *blob_ids, - gpointer update_entry, - gpointer user_data, - GError **error) -{ - MetaKmsImplDeviceAtomic *impl_device_atomic = - META_KMS_IMPL_DEVICE_ATOMIC (impl_device); - MetaKmsPageFlipListener *listener = update_entry; - MetaKmsPageFlipData *page_flip_data; - uint32_t crtc_id; - gpointer listener_user_data; - GDestroyNotify listener_destroy_notify; - - crtc_id = meta_kms_crtc_get_id (listener->crtc); - page_flip_data = g_hash_table_lookup (impl_device_atomic->page_flip_datas, - GUINT_TO_POINTER (crtc_id)); - if (!page_flip_data) - { - page_flip_data = meta_kms_page_flip_data_new (impl_device, - listener->crtc); - g_hash_table_insert (impl_device_atomic->page_flip_datas, - GUINT_TO_POINTER (crtc_id), - page_flip_data); - - meta_kms_impl_device_hold_fd (impl_device); - - meta_topic (META_DEBUG_KMS, - "[atomic] Adding page flip data for (%u, %s): %p", - crtc_id, - meta_kms_impl_device_get_path (impl_device), - page_flip_data); - } - - listener_user_data = g_steal_pointer (&listener->user_data); - listener_destroy_notify = g_steal_pointer (&listener->destroy_notify); - meta_kms_page_flip_data_add_listener (page_flip_data, - listener->vtable, - listener->flags, - listener_user_data, - listener_destroy_notify); - - return TRUE; -} - -static gboolean -discard_page_flip_listener (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - drmModeAtomicReq *req, - GArray *blob_ids, - gpointer update_entry, - gpointer user_data, - GError **error) -{ - MetaKmsPageFlipListener *listener = update_entry; - GError *commit_error = user_data; - MetaKmsPageFlipData *page_flip_data; - gpointer listener_user_data; - GDestroyNotify listener_destroy_notify; - - page_flip_data = meta_kms_page_flip_data_new (impl_device, - listener->crtc); - - meta_topic (META_DEBUG_KMS, - "[atomic] Creating transient page flip data for (%u, %s): %p", - meta_kms_crtc_get_id (listener->crtc), - meta_kms_impl_device_get_path (impl_device), - page_flip_data); - - listener_user_data = g_steal_pointer (&listener->user_data); - listener_destroy_notify = g_steal_pointer (&listener->destroy_notify); - meta_kms_page_flip_data_add_listener (page_flip_data, - listener->vtable, - listener->flags, - listener_user_data, - listener_destroy_notify); - - meta_kms_page_flip_data_discard_in_impl (page_flip_data, commit_error); - - return TRUE; -} - -static gboolean -process_entries (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - drmModeAtomicReq *req, - GArray *blob_ids, - GList *entries, - gpointer user_data, - MetaKmsAtomicProcessFunc func, - GError **error) -{ - GList *l; - - for (l = entries; l; l = l->next) - { - if (!func (impl_device, - update, - req, - blob_ids, - l->data, - user_data, - error)) - return FALSE; - } - - return TRUE; -} - -static void -atomic_page_flip_handler (int fd, - unsigned int sequence, - unsigned int tv_sec, - unsigned int tv_usec, - unsigned int crtc_id, - void *user_data) -{ - MetaKmsImplDeviceAtomic *impl_device_atomic = user_data; - MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (impl_device_atomic); - MetaKmsPageFlipData *page_flip_data = NULL; - - g_hash_table_steal_extended (impl_device_atomic->page_flip_datas, - GUINT_TO_POINTER (crtc_id), - NULL, - (gpointer *) &page_flip_data); - - meta_topic (META_DEBUG_KMS, - "[atomic] Page flip callback for CRTC (%u, %s), data: %p", - crtc_id, meta_kms_impl_device_get_path (impl_device), - page_flip_data); - - if (!page_flip_data) - return; - - meta_kms_impl_device_unhold_fd (impl_device); - - meta_kms_page_flip_data_set_timings_in_impl (page_flip_data, - sequence, tv_sec, tv_usec); - meta_kms_impl_device_handle_page_flip_callback (impl_device, page_flip_data); -} - -static void -meta_kms_impl_device_atomic_setup_drm_event_context (MetaKmsImplDevice *impl_device, - drmEventContext *drm_event_context) -{ - drm_event_context->version = 3; - drm_event_context->page_flip_handler2 = atomic_page_flip_handler; -} - -static const char * -commit_flags_string (uint32_t commit_flags) -{ - static char static_commit_flags_string[255]; - const char *commit_flag_strings[4] = { NULL }; - int i = 0; - g_autofree char *commit_flags_string = NULL; - - if (commit_flags & DRM_MODE_ATOMIC_NONBLOCK) - commit_flag_strings[i++] = "ATOMIC_NONBLOCK"; - if (commit_flags & DRM_MODE_ATOMIC_ALLOW_MODESET) - commit_flag_strings[i++] = "ATOMIC_ALLOW_MODESET"; - if (commit_flags & DRM_MODE_PAGE_FLIP_EVENT) - commit_flag_strings[i++] = "PAGE_FLIP_EVENT"; - - commit_flags_string = g_strjoinv ("|", (char **) commit_flag_strings); - strncpy (static_commit_flags_string, commit_flags_string, - (sizeof static_commit_flags_string) - 1); - - return static_commit_flags_string; -} - -static gboolean -disable_connectors (MetaKmsImplDevice *impl_device, - drmModeAtomicReq *req, - GError **error) -{ - GList *l; - - for (l = meta_kms_impl_device_peek_connectors (impl_device); l; l = l->next) - { - MetaKmsConnector *connector = l->data; - - if (!add_connector_property (impl_device, - connector, req, - META_KMS_CONNECTOR_PROP_CRTC_ID, - 0, - error)) - return FALSE; - } - - return TRUE; -} - -static gboolean -disable_planes (MetaKmsImplDevice *impl_device, - drmModeAtomicReq *req, - GError **error) -{ - GList *l; - - for (l = meta_kms_impl_device_peek_planes (impl_device); l; l = l->next) - { - MetaKmsPlane *plane = l->data; - - if (!add_plane_property (impl_device, - plane, req, - META_KMS_PLANE_PROP_CRTC_ID, - 0, - error)) - return FALSE; - - if (!add_plane_property (impl_device, - plane, req, - META_KMS_PLANE_PROP_FB_ID, - 0, - error)) - return FALSE; - } - - return TRUE; -} - -static gboolean -disable_crtcs (MetaKmsImplDevice *impl_device, - drmModeAtomicReq *req, - GError **error) -{ - GList *l; - - for (l = meta_kms_impl_device_peek_crtcs (impl_device); l; l = l->next) - { - MetaKmsCrtc *crtc = l->data; - - if (!add_crtc_property (impl_device, - crtc, req, - META_KMS_CRTC_PROP_ACTIVE, - 0, - error)) - return FALSE; - - if (!add_crtc_property (impl_device, - crtc, req, - META_KMS_CRTC_PROP_MODE_ID, - 0, - error)) - return FALSE; - } - - return TRUE; -} - -static gboolean -disable_planes_and_connectors (MetaKmsImplDevice *impl_device, - drmModeAtomicReq *req, - GError **error) -{ - if (!disable_connectors (impl_device, req, error)) - return FALSE; - if (!disable_planes (impl_device, req, error)) - return FALSE; - - return TRUE; -} - -static gboolean -process_power_save (MetaKmsImplDevice *impl_device, - drmModeAtomicReq *req, - GError **error) -{ - if (!disable_connectors (impl_device, req, error)) - return FALSE; - if (!disable_planes (impl_device, req, error)) - return FALSE; - if (!disable_crtcs (impl_device, req, error)) - return FALSE; - - return TRUE; -} - -static MetaKmsFeedback * -meta_kms_impl_device_atomic_process_update (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - MetaKmsUpdateFlag flags) -{ - GError *error = NULL; - GList *failed_planes = NULL; - drmModeAtomicReq *req; - g_autoptr (GArray) blob_ids = NULL; - int fd; - uint32_t commit_flags = 0; - int ret; - - blob_ids = g_array_new (FALSE, TRUE, sizeof (uint32_t)); - - meta_topic (META_DEBUG_KMS, - "[atomic] Processing update %" G_GUINT64_FORMAT, - meta_kms_update_get_sequence_number (update)); - - req = drmModeAtomicAlloc (); - if (!req) - { - g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to create atomic transaction request: %s", - g_strerror (errno)); - goto err; - } - - if (meta_kms_update_get_mode_sets (update)) - { - if (!disable_planes_and_connectors (impl_device, req, &error)) - goto err; - } - - if (meta_kms_update_is_power_save (update)) - { - meta_topic (META_DEBUG_KMS, - "[atomic] Entering power save mode for %s", - meta_kms_impl_device_get_path (impl_device)); - - if (!process_power_save (impl_device, req, &error)) - goto err; - - commit_flags = DRM_MODE_ATOMIC_ALLOW_MODESET; - goto commit; - } - - if (!process_entries (impl_device, - update, - req, - blob_ids, - meta_kms_update_get_connector_updates (update), - NULL, - process_connector_update, - &error)) - goto err; - - if (!process_entries (impl_device, - update, - req, - blob_ids, - meta_kms_update_get_mode_sets (update), - NULL, - process_mode_set, - &error)) - goto err; - - if (!process_entries (impl_device, - update, - req, - blob_ids, - meta_kms_update_get_plane_assignments (update), - NULL, - process_plane_assignment, - &error)) - goto err; - - if (!process_entries (impl_device, - update, - req, - blob_ids, - meta_kms_update_get_crtc_gammas (update), - NULL, - process_crtc_gamma, - &error)) - goto err; - - if (meta_kms_update_get_mode_sets (update)) - commit_flags |= DRM_MODE_ATOMIC_ALLOW_MODESET; - else - commit_flags |= DRM_MODE_ATOMIC_NONBLOCK; - - if (meta_kms_update_get_page_flip_listeners (update)) - commit_flags |= DRM_MODE_PAGE_FLIP_EVENT; - -commit: - meta_topic (META_DEBUG_KMS, - "[atomic] Committing update %" G_GUINT64_FORMAT ", flags: %s", - meta_kms_update_get_sequence_number (update), - commit_flags_string (commit_flags)); - - fd = meta_kms_impl_device_get_fd (impl_device); - ret = drmModeAtomicCommit (fd, req, commit_flags, impl_device); - drmModeAtomicFree (req); - if (ret < 0) - { - g_set_error (&error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModeAtomicCommit: %s", g_strerror (-ret)); - goto err; - } - - process_entries (impl_device, - update, - req, - blob_ids, - meta_kms_update_get_page_flip_listeners (update), - NULL, - process_page_flip_listener, - NULL); - - release_blob_ids (impl_device, blob_ids); - - return meta_kms_feedback_new_passed (NULL); - -err: - meta_topic (META_DEBUG_KMS, "[atomic] KMS update failed: %s", error->message); - - if (!(flags & META_KMS_UPDATE_FLAG_PRESERVE_ON_ERROR)) - { - process_entries (impl_device, - update, - req, - blob_ids, - meta_kms_update_get_page_flip_listeners (update), - error, - discard_page_flip_listener, - NULL); - } - - release_blob_ids (impl_device, blob_ids); - - return meta_kms_feedback_new_failed (failed_planes, error); -} - -static void -meta_kms_impl_device_atomic_handle_page_flip_callback (MetaKmsImplDevice *impl_device, - MetaKmsPageFlipData *page_flip_data) -{ - meta_kms_page_flip_data_flipped_in_impl (page_flip_data); -} - -static void -meta_kms_impl_device_atomic_discard_pending_page_flips (MetaKmsImplDevice *impl_device) -{ -} - -static gboolean -dispose_page_flip_data (gpointer key, - gpointer value, - gpointer user_data) -{ - MetaKmsPageFlipData *page_flip_data = value; - MetaKmsImplDevice *impl_device = user_data; - - meta_kms_page_flip_data_discard_in_impl (page_flip_data, NULL); - meta_kms_impl_device_unhold_fd (impl_device); - - return TRUE; -} - -static void -meta_kms_impl_device_atomic_prepare_shutdown (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDeviceAtomic *impl_device_atomic = - META_KMS_IMPL_DEVICE_ATOMIC (impl_device); - - g_hash_table_foreach_remove (impl_device_atomic->page_flip_datas, - dispose_page_flip_data, - impl_device); -} - -static void -meta_kms_impl_device_atomic_finalize (GObject *object) -{ - MetaKmsImplDeviceAtomic *impl_device_atomic = - META_KMS_IMPL_DEVICE_ATOMIC (object); - - g_assert (g_hash_table_size (impl_device_atomic->page_flip_datas) == 0); - - g_hash_table_unref (impl_device_atomic->page_flip_datas); - - G_OBJECT_CLASS (meta_kms_impl_device_atomic_parent_class)->finalize (object); -} - -static MetaDeviceFile * -meta_kms_impl_device_atomic_open_device_file (MetaKmsImplDevice *impl_device, - const char *path, - GError **error) -{ - MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device); - MetaKms *kms = meta_kms_device_get_kms (device); - MetaBackend *backend = meta_kms_get_backend (kms); - MetaDevicePool *device_pool = - meta_backend_native_get_device_pool (META_BACKEND_NATIVE (backend)); - g_autoptr (MetaDeviceFile) device_file = NULL; - - device_file = meta_device_pool_open (device_pool, path, - META_DEVICE_FILE_FLAG_TAKE_CONTROL, - error); - if (!device_file) - return NULL; - - if (!meta_device_file_has_tag (device_file, - META_DEVICE_FILE_TAG_KMS, - META_KMS_DEVICE_FILE_TAG_ATOMIC)) - { - int fd = meta_device_file_get_fd (device_file); - - g_warn_if_fail (!meta_device_file_has_tag (device_file, - META_DEVICE_FILE_TAG_KMS, - META_KMS_DEVICE_FILE_TAG_SIMPLE)); - - if (drmSetClientCap (fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) != 0) - { - g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_NOT_SUPPORTED, - "DRM_CLIENT_CAP_UNIVERSAL_PLANES not supported"); - return NULL; - } - - if (drmSetClientCap (fd, DRM_CLIENT_CAP_ATOMIC, 1) != 0) - { - g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_NOT_SUPPORTED, - "DRM_CLIENT_CAP_ATOMIC not supported"); - return NULL; - } - - meta_device_file_tag (device_file, - META_DEVICE_FILE_TAG_KMS, - META_KMS_DEVICE_FILE_TAG_ATOMIC); - } - - return g_steal_pointer (&device_file); -} - -static gboolean -is_atomic_allowed (const char *driver_name) -{ - const char *atomic_driver_deny_list[] = { - "qxl", - "vmwgfx", - "vboxvideo", - "nvidia-drm", - NULL, - }; - - return !g_strv_contains (atomic_driver_deny_list, driver_name); -} - -static gboolean -meta_kms_impl_device_atomic_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (initable); - const char *atomic_kms_enable_env; - - atomic_kms_enable_env = getenv ("MUTTER_DEBUG_ENABLE_ATOMIC_KMS"); - if (atomic_kms_enable_env && g_strcmp0 (atomic_kms_enable_env, "1") != 0) - { - g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_USER_INHIBITED, - "Atomic mode setting disable via env var"); - return FALSE; - } - - if (!initable_parent_iface->init (initable, cancellable, error)) - return FALSE; - - if (!is_atomic_allowed (meta_kms_impl_device_get_driver_name (impl_device))) - { - g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_DENY_LISTED, - "Atomic mode setting disable via driver deny list"); - return FALSE; - } - - if (!meta_kms_impl_device_init_mode_setting (impl_device, error)) - return FALSE; - - g_message ("Added device '%s' (%s) using atomic mode setting.", - meta_kms_impl_device_get_path (impl_device), - meta_kms_impl_device_get_driver_name (impl_device)); - - return TRUE; -} - -static void -meta_kms_impl_device_atomic_init (MetaKmsImplDeviceAtomic *impl_device_atomic) -{ - impl_device_atomic->page_flip_datas = g_hash_table_new (NULL, NULL); -} - -static void -initable_iface_init (GInitableIface *iface) -{ - initable_parent_iface = g_type_interface_peek_parent (iface); - - iface->init = meta_kms_impl_device_atomic_initable_init; -} - -static void -meta_kms_impl_device_atomic_class_init (MetaKmsImplDeviceAtomicClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaKmsImplDeviceClass *impl_device_class = - META_KMS_IMPL_DEVICE_CLASS (klass); - - object_class->finalize = meta_kms_impl_device_atomic_finalize; - - impl_device_class->open_device_file = - meta_kms_impl_device_atomic_open_device_file; - impl_device_class->setup_drm_event_context = - meta_kms_impl_device_atomic_setup_drm_event_context; - impl_device_class->process_update = - meta_kms_impl_device_atomic_process_update; - impl_device_class->handle_page_flip_callback = - meta_kms_impl_device_atomic_handle_page_flip_callback; - impl_device_class->discard_pending_page_flips = - meta_kms_impl_device_atomic_discard_pending_page_flips; - impl_device_class->prepare_shutdown = - meta_kms_impl_device_atomic_prepare_shutdown; -} diff --git a/src/backends/native/meta-kms-impl-device-atomic.h b/src/backends/native/meta-kms-impl-device-atomic.h deleted file mode 100644 index 74658797c..000000000 --- a/src/backends/native/meta-kms-impl-device-atomic.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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_KMS_IMPL_DEVICE_ATOMIC_H -#define META_KMS_IMPL_DEVICE_ATOMIC_H - -#include "backends/native/meta-kms-impl-device.h" - -#define META_TYPE_KMS_IMPL_DEVICE_ATOMIC (meta_kms_impl_device_atomic_get_type ()) -G_DECLARE_FINAL_TYPE (MetaKmsImplDeviceAtomic, meta_kms_impl_device_atomic, - META, KMS_IMPL_DEVICE_ATOMIC, MetaKmsImplDevice) - -#endif /* META_KMS_IMPL_DEVICE_ATOMIC_H */ diff --git a/src/backends/native/meta-kms-impl-device-dummy.c b/src/backends/native/meta-kms-impl-device-dummy.c deleted file mode 100644 index 02583bbeb..000000000 --- a/src/backends/native/meta-kms-impl-device-dummy.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2021 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. - */ - -#include "config.h" - -#include "backends/native/meta-kms-impl-device-dummy.h" - -#include "backends/native/meta-backend-native-private.h" -#include "backends/native/meta-kms.h" - -struct _MetaKmsImplDeviceDummy -{ - MetaKmsImplDevice parent; -}; - -static GInitableIface *initable_parent_iface; - -static void -initable_iface_init (GInitableIface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaKmsImplDeviceDummy, - meta_kms_impl_device_dummy, - META_TYPE_KMS_IMPL_DEVICE, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - initable_iface_init)) - -static void -meta_kms_impl_device_dummy_discard_pending_page_flips (MetaKmsImplDevice *impl_device) -{ -} - -static MetaDeviceFile * -meta_kms_impl_device_dummy_open_device_file (MetaKmsImplDevice *impl_device, - const char *path, - GError **error) -{ - MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device); - MetaKms *kms = meta_kms_device_get_kms (device); - MetaBackend *backend = meta_kms_get_backend (kms); - MetaDevicePool *device_pool = - meta_backend_native_get_device_pool (META_BACKEND_NATIVE (backend)); - g_autoptr (MetaDeviceFile) device_file = NULL; - int fd; - g_autofree char *render_node_path = NULL; - - device_file = meta_device_pool_open (device_pool, path, - META_DEVICE_FILE_FLAG_NONE, - error); - if (!device_file) - return NULL; - - fd = meta_device_file_get_fd (device_file); - render_node_path = drmGetRenderDeviceNameFromFd (fd); - if (!render_node_path) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Couldn't find render node device for '%s' (%s)", - meta_kms_impl_device_get_path (impl_device), - meta_kms_impl_device_get_driver_name (impl_device)); - return NULL; - } - - meta_topic (META_DEBUG_KMS, "Found render node '%s' from '%s'", - render_node_path, path); - - return meta_device_pool_open (device_pool, render_node_path, - META_DEVICE_FILE_FLAG_NONE, - error); -} - -static gboolean -meta_kms_impl_device_dummy_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (initable); - - if (!initable_parent_iface->init (initable, cancellable, error)) - return FALSE; - - g_message ("Added device '%s' (%s) using no mode setting.", - meta_kms_impl_device_get_path (impl_device), - meta_kms_impl_device_get_driver_name (impl_device)); - - return TRUE; -} - -static void -initable_iface_init (GInitableIface *iface) -{ - initable_parent_iface = g_type_interface_peek_parent (iface); - - iface->init = meta_kms_impl_device_dummy_initable_init; -} - -static void -meta_kms_impl_device_dummy_init (MetaKmsImplDeviceDummy *impl_device_dummy) -{ -} - -static void -meta_kms_impl_device_dummy_class_init (MetaKmsImplDeviceDummyClass *klass) -{ - MetaKmsImplDeviceClass *impl_device_class = - META_KMS_IMPL_DEVICE_CLASS (klass); - - impl_device_class->open_device_file = - meta_kms_impl_device_dummy_open_device_file; - impl_device_class->discard_pending_page_flips = - meta_kms_impl_device_dummy_discard_pending_page_flips; -} diff --git a/src/backends/native/meta-kms-impl-device-dummy.h b/src/backends/native/meta-kms-impl-device-dummy.h deleted file mode 100644 index 9576939ad..000000000 --- a/src/backends/native/meta-kms-impl-device-dummy.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2021 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_KMS_IMPL_DEVICE_DUMMY_H -#define META_KMS_IMPL_DEVICE_DUMMY_H - -#include "backends/native/meta-kms-impl-device.h" - -#define META_TYPE_KMS_IMPL_DEVICE_DUMMY (meta_kms_impl_device_dummy_get_type ()) -G_DECLARE_FINAL_TYPE (MetaKmsImplDeviceDummy, meta_kms_impl_device_dummy, - META, KMS_IMPL_DEVICE_DUMMY, - MetaKmsImplDevice) - -#endif /* META_KMS_IMPL_DEVICE_DUMMY_H */ diff --git a/src/backends/native/meta-kms-impl-device-simple.c b/src/backends/native/meta-kms-impl-device-simple.c deleted file mode 100644 index 28d512720..000000000 --- a/src/backends/native/meta-kms-impl-device-simple.c +++ /dev/null @@ -1,1678 +0,0 @@ -/* - * Copyright (C) 2019-2020 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. - */ - -#include "config.h" - -#include "backends/native/meta-kms-impl-device-simple.h" - -#include "backends/native/meta-backend-native-private.h" -#include "backends/native/meta-drm-buffer-gbm.h" -#include "backends/native/meta-kms-connector-private.h" -#include "backends/native/meta-kms-crtc-private.h" -#include "backends/native/meta-kms-device-private.h" -#include "backends/native/meta-kms-mode-private.h" -#include "backends/native/meta-kms-plane-private.h" -#include "backends/native/meta-kms-private.h" -#include "backends/native/meta-kms-update-private.h" -#include "backends/native/meta-kms-utils.h" - -typedef gboolean (* MetaKmsSimpleProcessFunc) (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - gpointer entry_data, - GError **error); - -typedef struct _CachedModeSet -{ - GList *connectors; - drmModeModeInfo *drm_mode; -} CachedModeSet; - -struct _MetaKmsImplDeviceSimple -{ - MetaKmsImplDevice parent; - - GSource *mode_set_fallback_feedback_source; - GList *mode_set_fallback_page_flip_datas; - - GList *pending_page_flip_retries; - GSource *retry_page_flips_source; - - GList *postponed_page_flip_datas; - GList *postponed_mode_set_fallback_datas; - - GList *posted_page_flip_datas; - - GHashTable *cached_mode_sets; -}; - -static GInitableIface *initable_parent_iface; - -static void -initable_iface_init (GInitableIface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaKmsImplDeviceSimple, meta_kms_impl_device_simple, - META_TYPE_KMS_IMPL_DEVICE, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - initable_iface_init)) - -static void -flush_postponed_page_flip_datas (MetaKmsImplDeviceSimple *impl_device_simple); - -static gboolean -get_connector_property (MetaKmsImplDevice *impl_device, - MetaKmsConnector *connector, - MetaKmsConnectorProp prop, - uint64_t *value, - GError **error) -{ - uint32_t prop_id; - int fd; - drmModeConnector *drm_connector; - int i; - gboolean found; - - prop_id = meta_kms_connector_get_prop_id (connector, prop); - if (!prop_id) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - "Property (%s) not found on connector %u", - meta_kms_connector_get_prop_name (connector, prop), - meta_kms_connector_get_id (connector)); - return FALSE; - } - - fd = meta_kms_impl_device_get_fd (impl_device); - - drm_connector = drmModeGetConnector (fd, - meta_kms_connector_get_id (connector)); - if (!drm_connector) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "Failed to get connector %u resources: %s", - meta_kms_connector_get_id (connector), - g_strerror (errno)); - return FALSE; - } - - found = FALSE; - for (i = 0; i < drm_connector->count_props; i++) - { - if (drm_connector->props[i] == prop_id) - { - *value = drm_connector->prop_values[i]; - found = TRUE; - break; - } - } - - drmModeFreeConnector (drm_connector); - - if (!found) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, - "Connector property %u not found", prop_id); - return FALSE; - } - - return TRUE; -} - -static gboolean -set_connector_property (MetaKmsImplDevice *impl_device, - MetaKmsConnector *connector, - MetaKmsConnectorProp prop, - uint64_t value, - GError **error) -{ - uint32_t prop_id; - int fd; - int ret; - - prop_id = meta_kms_connector_get_prop_id (connector, prop); - if (!prop_id) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - "Property (%s) not found on connector %u", - meta_kms_connector_get_prop_name (connector, prop), - meta_kms_connector_get_id (connector)); - return FALSE; - } - - fd = meta_kms_impl_device_get_fd (impl_device); - - ret = drmModeObjectSetProperty (fd, - meta_kms_connector_get_id (connector), - DRM_MODE_OBJECT_CONNECTOR, - prop_id, - value); - if (ret != 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "Failed to set connector %u property %u: %s", - meta_kms_connector_get_id (connector), - prop_id, - g_strerror (-ret)); - return FALSE; - } - - return TRUE; -} - -static gboolean -process_power_save (MetaKmsImplDevice *impl_device, - GError **error) -{ - GList *l; - - for (l = meta_kms_impl_device_peek_connectors (impl_device); l; l = l->next) - { - MetaKmsConnector *connector = l->data; - - meta_topic (META_DEBUG_KMS, - "[simple] Setting DPMS of connector %u (%s) to OFF", - meta_kms_connector_get_id (connector), - meta_kms_impl_device_get_path (impl_device)); - - if (!set_connector_property (impl_device, - connector, - META_KMS_CONNECTOR_PROP_DPMS, - DRM_MODE_DPMS_OFF, - error)) - return FALSE; - } - - return TRUE; -} - -static gboolean -process_connector_update (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - gpointer update_entry, - GError **error) -{ - MetaKmsConnectorUpdate *connector_update = update_entry; - MetaKmsConnector *connector = connector_update->connector; - - if (connector_update->underscanning.has_update && - connector_update->underscanning.is_active) - { - meta_topic (META_DEBUG_KMS, - "[simple] Setting underscanning on connector %u (%s) to " - "%" G_GUINT64_FORMAT "x%" G_GUINT64_FORMAT, - meta_kms_connector_get_id (connector), - meta_kms_impl_device_get_path (impl_device), - connector_update->underscanning.hborder, - connector_update->underscanning.vborder); - - if (!set_connector_property (impl_device, - connector, - META_KMS_CONNECTOR_PROP_UNDERSCAN, - 1, - error)) - return FALSE; - if (!set_connector_property (impl_device, - connector, - META_KMS_CONNECTOR_PROP_UNDERSCAN_HBORDER, - connector_update->underscanning.hborder, - error)) - return FALSE; - if (!set_connector_property (impl_device, - connector, - META_KMS_CONNECTOR_PROP_UNDERSCAN_VBORDER, - connector_update->underscanning.vborder, - error)) - return FALSE; - } - else if (connector_update->underscanning.has_update) - { - meta_topic (META_DEBUG_KMS, - "[simple] Unsetting underscanning on connector %u (%s)", - meta_kms_connector_get_id (connector), - meta_kms_impl_device_get_path (impl_device)); - - if (!set_connector_property (impl_device, - connector, - META_KMS_CONNECTOR_PROP_UNDERSCAN, - 0, - error)) - return FALSE; - } - - return TRUE; -} - -static CachedModeSet * -cached_mode_set_new (GList *connectors, - const drmModeModeInfo *drm_mode) -{ - CachedModeSet *cached_mode_set; - - cached_mode_set = g_new0 (CachedModeSet, 1); - *cached_mode_set = (CachedModeSet) { - .connectors = g_list_copy (connectors), - .drm_mode = g_memdup2 (drm_mode, sizeof *drm_mode), - }; - - return cached_mode_set; -} - -static void -cached_mode_set_free (CachedModeSet *cached_mode_set) -{ - g_list_free (cached_mode_set->connectors); - g_free (cached_mode_set->drm_mode); - g_free (cached_mode_set); -} - -static void -fill_connector_ids_array (GList *connectors, - uint32_t **out_connectors, - int *out_n_connectors) -{ - GList *l; - int i; - - *out_n_connectors = g_list_length (connectors); - *out_connectors = g_new0 (uint32_t, *out_n_connectors); - i = 0; - for (l = connectors; l; l = l->next) - { - MetaKmsConnector *connector = l->data; - - (*out_connectors)[i++] = meta_kms_connector_get_id (connector); - } -} - -static gboolean -set_plane_rotation (MetaKmsImplDevice *impl_device, - MetaKmsPlane *plane, - uint64_t rotation, - GError **error) -{ - int fd; - uint32_t rotation_prop_id; - int ret; - - fd = meta_kms_impl_device_get_fd (impl_device); - - rotation_prop_id = meta_kms_plane_get_prop_id (plane, - META_KMS_PLANE_PROP_ROTATION); - - meta_topic (META_DEBUG_KMS, - "[simple] Setting plane %u (%s) rotation to %" G_GUINT64_FORMAT, - meta_kms_plane_get_id (plane), - meta_kms_impl_device_get_path (impl_device), - rotation); - - ret = drmModeObjectSetProperty (fd, - meta_kms_plane_get_id (plane), - DRM_MODE_OBJECT_PLANE, - rotation_prop_id, - rotation); - if (ret != 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "Failed to rotation property (%u) to %" G_GUINT64_FORMAT - " on plane %u: %s", - rotation_prop_id, - rotation, - meta_kms_plane_get_id (plane), - g_strerror (-ret)); - return FALSE; - } - - return TRUE; -} - -static gboolean -process_mode_set (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - gpointer update_entry, - GError **error) -{ - MetaKmsImplDeviceSimple *impl_device_simple = - META_KMS_IMPL_DEVICE_SIMPLE (impl_device); - MetaKmsModeSet *mode_set = update_entry; - MetaKmsCrtc *crtc = mode_set->crtc; - g_autofree uint32_t *connectors = NULL; - int n_connectors; - MetaKmsPlaneAssignment *plane_assignment; - drmModeModeInfo *drm_mode; - uint32_t x, y; - uint32_t fb_id; - int fd; - int ret; - - crtc = mode_set->crtc; - - if (mode_set->mode) - { - MetaDrmBuffer *buffer; - GList *l; - - drm_mode = g_alloca (sizeof *drm_mode); - *drm_mode = *meta_kms_mode_get_drm_mode (mode_set->mode); - - fill_connector_ids_array (mode_set->connectors, - &connectors, - &n_connectors); - - plane_assignment = meta_kms_update_get_primary_plane_assignment (update, - crtc); - if (!plane_assignment) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Missing primary plane assignment for legacy mode set on CRTC %u", - meta_kms_crtc_get_id (crtc)); - return FALSE; - } - - x = meta_fixed_16_to_int (plane_assignment->src_rect.x); - y = meta_fixed_16_to_int (plane_assignment->src_rect.y); - - if (plane_assignment->rotation) - { - if (!set_plane_rotation (impl_device, - plane_assignment->plane, - plane_assignment->rotation, - error)) - return FALSE; - } - - buffer = plane_assignment->buffer; - fb_id = meta_drm_buffer_get_fb_id (buffer); - - for (l = mode_set->connectors; l; l = l->next) - { - MetaKmsConnector *connector = l->data; - uint64_t dpms_value; - - if (!get_connector_property (impl_device, - connector, - META_KMS_CONNECTOR_PROP_DPMS, - &dpms_value, - error)) - return FALSE; - - if (dpms_value != DRM_MODE_DPMS_ON) - { - meta_topic (META_DEBUG_KMS, - "[simple] Setting DPMS of connector %u (%s) to ON", - meta_kms_connector_get_id (connector), - meta_kms_impl_device_get_path (impl_device)); - - if (!set_connector_property (impl_device, - connector, - META_KMS_CONNECTOR_PROP_DPMS, - DRM_MODE_DPMS_ON, - error)) - return FALSE; - } - } - - meta_topic (META_DEBUG_KMS, - "[simple] Setting mode of CRTC %u (%s) to %s", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device), - drm_mode->name); - } - else - { - drm_mode = NULL; - x = y = 0; - n_connectors = 0; - connectors = NULL; - fb_id = 0; - - meta_topic (META_DEBUG_KMS, - "[simple] Unsetting mode of CRTC %u (%s)", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device)); - } - - fd = meta_kms_impl_device_get_fd (impl_device); - ret = drmModeSetCrtc (fd, - meta_kms_crtc_get_id (crtc), - fb_id, - x, y, - connectors, n_connectors, - drm_mode); - if (ret != 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "Failed to set mode %s on CRTC %u: %s", - drm_mode ? drm_mode->name : "off", - meta_kms_crtc_get_id (crtc), - g_strerror (-ret)); - return FALSE; - } - - if (drm_mode) - { - g_hash_table_replace (impl_device_simple->cached_mode_sets, - crtc, - cached_mode_set_new (mode_set->connectors, - drm_mode)); - } - else - { - g_hash_table_remove (impl_device_simple->cached_mode_sets, crtc); - } - - return TRUE; -} - -static gboolean -process_crtc_gamma (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - gpointer update_entry, - GError **error) -{ - MetaKmsCrtcGamma *gamma = update_entry; - MetaKmsCrtc *crtc = gamma->crtc; - int fd; - int ret; - - meta_topic (META_DEBUG_KMS, - "[simple] Setting CRTC %u (%s) gamma, size: %d", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device), - gamma->size); - - fd = meta_kms_impl_device_get_fd (impl_device); - ret = drmModeCrtcSetGamma (fd, meta_kms_crtc_get_id (crtc), - gamma->size, - gamma->red, - gamma->green, - gamma->blue); - if (ret != 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModeCrtcSetGamma on CRTC %u failed: %s", - meta_kms_crtc_get_id (crtc), - g_strerror (-ret)); - return FALSE; - } - - return TRUE; -} - -static gboolean -is_timestamp_earlier_than (uint64_t ts1, - uint64_t ts2) -{ - if (ts1 == ts2) - return FALSE; - else - return ts2 - ts1 < UINT64_MAX / 2; -} - -typedef struct _RetryPageFlipData -{ - MetaKmsCrtc *crtc; - uint32_t fb_id; - MetaKmsPageFlipData *page_flip_data; - float refresh_rate; - uint64_t retry_time_us; - MetaKmsCustomPageFlip *custom_page_flip; -} RetryPageFlipData; - -static void -retry_page_flip_data_free (RetryPageFlipData *retry_page_flip_data) -{ - g_assert (!retry_page_flip_data->page_flip_data); - g_clear_pointer (&retry_page_flip_data->custom_page_flip, - meta_kms_custom_page_flip_free); - g_free (retry_page_flip_data); -} - -static CachedModeSet * -get_cached_mode_set (MetaKmsImplDeviceSimple *impl_device_simple, - MetaKmsCrtc *crtc) -{ - return g_hash_table_lookup (impl_device_simple->cached_mode_sets, crtc); -} - -static float -get_cached_crtc_refresh_rate (MetaKmsImplDeviceSimple *impl_device_simple, - MetaKmsCrtc *crtc) -{ - CachedModeSet *cached_mode_set; - - cached_mode_set = g_hash_table_lookup (impl_device_simple->cached_mode_sets, - crtc); - g_assert (cached_mode_set); - - return meta_calculate_drm_mode_refresh_rate (cached_mode_set->drm_mode); -} - -#define meta_assert_in_kms_impl(kms) \ - g_assert (meta_kms_in_impl_task (kms)) - -static gboolean -retry_page_flips (gpointer user_data) -{ - MetaKmsImplDeviceSimple *impl_device_simple = - META_KMS_IMPL_DEVICE_SIMPLE (user_data); - MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (impl_device_simple); - uint64_t now_us; - GList *l; - - now_us = g_source_get_time (impl_device_simple->retry_page_flips_source); - - l = impl_device_simple->pending_page_flip_retries; - while (l) - { - RetryPageFlipData *retry_page_flip_data = l->data; - MetaKmsCrtc *crtc = retry_page_flip_data->crtc; - GList *l_next = l->next; - int fd; - int ret; - MetaKmsPageFlipData *page_flip_data; - MetaKmsCustomPageFlip *custom_page_flip; - - if (is_timestamp_earlier_than (now_us, - retry_page_flip_data->retry_time_us)) - { - l = l_next; - continue; - } - - custom_page_flip = retry_page_flip_data->custom_page_flip; - if (custom_page_flip) - { - meta_topic (META_DEBUG_KMS, - "[simple] Retrying custom page flip on CRTC %u (%s)", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device)); - ret = custom_page_flip->func (custom_page_flip->user_data, - retry_page_flip_data->page_flip_data); - } - else - { - meta_topic (META_DEBUG_KMS, - "[simple] Retrying page flip on CRTC %u (%s) with %u", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device), - retry_page_flip_data->fb_id); - - fd = meta_kms_impl_device_get_fd (impl_device); - ret = drmModePageFlip (fd, - meta_kms_crtc_get_id (crtc), - retry_page_flip_data->fb_id, - DRM_MODE_PAGE_FLIP_EVENT, - retry_page_flip_data->page_flip_data); - } - - if (ret == -EBUSY) - { - float refresh_rate; - - meta_topic (META_DEBUG_KMS, - "[simple] Rescheduling page flip retry on CRTC %u (%s)", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device)); - - refresh_rate = - get_cached_crtc_refresh_rate (impl_device_simple, crtc); - retry_page_flip_data->retry_time_us += - (uint64_t) (G_USEC_PER_SEC / refresh_rate); - l = l_next; - continue; - } - - impl_device_simple->pending_page_flip_retries = - g_list_remove_link (impl_device_simple->pending_page_flip_retries, l); - - page_flip_data = g_steal_pointer (&retry_page_flip_data->page_flip_data); - if (ret != 0) - { - g_autoptr (GError) error = NULL; - - g_set_error (&error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModePageFlip on CRTC %u failed: %s", - meta_kms_crtc_get_id (crtc), - g_strerror (-ret)); - if (!g_error_matches (error, - G_IO_ERROR, - G_IO_ERROR_PERMISSION_DENIED)) - g_critical ("Failed to page flip: %s", error->message); - - meta_kms_page_flip_data_discard_in_impl (page_flip_data, error); - meta_kms_impl_device_unhold_fd (impl_device); - } - else - { - impl_device_simple->posted_page_flip_datas = - g_list_prepend (impl_device_simple->posted_page_flip_datas, - page_flip_data); - } - - retry_page_flip_data_free (retry_page_flip_data); - - l = l_next; - } - - if (impl_device_simple->pending_page_flip_retries) - { - GList *l; - uint64_t earliest_retry_time_us = 0; - - for (l = impl_device_simple->pending_page_flip_retries; l; l = l->next) - { - RetryPageFlipData *retry_page_flip_data = l->data; - - if (l == impl_device_simple->pending_page_flip_retries || - is_timestamp_earlier_than (retry_page_flip_data->retry_time_us, - earliest_retry_time_us)) - earliest_retry_time_us = retry_page_flip_data->retry_time_us; - } - - g_source_set_ready_time (impl_device_simple->retry_page_flips_source, - earliest_retry_time_us); - return G_SOURCE_CONTINUE; - } - else - { - g_clear_pointer (&impl_device_simple->retry_page_flips_source, - g_source_unref); - - flush_postponed_page_flip_datas (impl_device_simple); - - return G_SOURCE_REMOVE; - } -} - -static void -schedule_retry_page_flip (MetaKmsImplDeviceSimple *impl_device_simple, - MetaKmsCrtc *crtc, - uint32_t fb_id, - float refresh_rate, - MetaKmsPageFlipData *page_flip_data, - MetaKmsCustomPageFlip *custom_page_flip) -{ - RetryPageFlipData *retry_page_flip_data; - uint64_t now_us; - uint64_t retry_time_us; - - now_us = g_get_monotonic_time (); - retry_time_us = now_us + (uint64_t) (G_USEC_PER_SEC / refresh_rate); - - retry_page_flip_data = g_new0 (RetryPageFlipData, 1); - *retry_page_flip_data = (RetryPageFlipData) { - .crtc = crtc, - .fb_id = fb_id, - .page_flip_data = page_flip_data, - .refresh_rate = refresh_rate, - .retry_time_us = retry_time_us, - .custom_page_flip = custom_page_flip, - }; - - if (!impl_device_simple->retry_page_flips_source) - { - MetaKmsImplDevice *impl_device = - META_KMS_IMPL_DEVICE (impl_device_simple); - MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device); - MetaKms *kms = meta_kms_device_get_kms (device); - GSource *source; - - source = meta_kms_add_source_in_impl (kms, retry_page_flips, - impl_device_simple, NULL); - g_source_set_ready_time (source, retry_time_us); - - impl_device_simple->retry_page_flips_source = source; - } - else - { - GList *l; - - for (l = impl_device_simple->pending_page_flip_retries; l; l = l->next) - { - RetryPageFlipData *pending_retry_page_flip_data = l->data; - uint64_t pending_retry_time_us = - pending_retry_page_flip_data->retry_time_us; - - if (is_timestamp_earlier_than (retry_time_us, pending_retry_time_us)) - { - g_source_set_ready_time (impl_device_simple->retry_page_flips_source, - retry_time_us); - break; - } - } - } - - impl_device_simple->pending_page_flip_retries = - g_list_append (impl_device_simple->pending_page_flip_retries, - retry_page_flip_data); -} - -static void -dispatch_page_flip_datas (GList **page_flip_datas, - GFunc func, - gpointer user_data) -{ - g_list_foreach (*page_flip_datas, func, user_data); - g_clear_pointer (page_flip_datas, g_list_free); -} - -static gboolean -mode_set_fallback_feedback_idle (gpointer user_data) -{ - MetaKmsImplDeviceSimple *impl_device_simple = user_data; - - g_clear_pointer (&impl_device_simple->mode_set_fallback_feedback_source, - g_source_unref); - - if (impl_device_simple->pending_page_flip_retries) - { - impl_device_simple->postponed_mode_set_fallback_datas = - g_steal_pointer (&impl_device_simple->mode_set_fallback_page_flip_datas); - } - else - { - dispatch_page_flip_datas (&impl_device_simple->mode_set_fallback_page_flip_datas, - (GFunc) meta_kms_page_flip_data_mode_set_fallback_in_impl, - NULL); - } - - return G_SOURCE_REMOVE; -} - -static gboolean -mode_set_fallback (MetaKmsImplDeviceSimple *impl_device_simple, - MetaKmsUpdate *update, - MetaKmsPlaneAssignment *plane_assignment, - MetaKmsPageFlipData *page_flip_data, - GError **error) -{ - MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (impl_device_simple); - MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device); - MetaKms *kms = meta_kms_device_get_kms (device); - MetaKmsCrtc *crtc = meta_kms_page_flip_data_get_crtc (page_flip_data); - CachedModeSet *cached_mode_set; - g_autofree uint32_t *connectors = NULL; - int n_connectors; - uint32_t fb_id; - uint32_t x, y; - int fd; - int ret; - - cached_mode_set = g_hash_table_lookup (impl_device_simple->cached_mode_sets, - crtc); - if (!cached_mode_set) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Missing mode set for page flip fallback"); - return FALSE; - } - - fill_connector_ids_array (cached_mode_set->connectors, - &connectors, - &n_connectors); - - fb_id = meta_drm_buffer_get_fb_id (plane_assignment->buffer); - - x = meta_fixed_16_to_int (plane_assignment->src_rect.x); - y = meta_fixed_16_to_int (plane_assignment->src_rect.y); - - fd = meta_kms_impl_device_get_fd (impl_device); - ret = drmModeSetCrtc (fd, - meta_kms_crtc_get_id (crtc), - fb_id, - x, y, - connectors, n_connectors, - cached_mode_set->drm_mode); - if (ret != 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModeSetCrtc mode '%s' on CRTC %u failed: %s", - cached_mode_set->drm_mode->name, - meta_kms_crtc_get_id (crtc), - g_strerror (-ret)); - return FALSE; - } - - if (!impl_device_simple->mode_set_fallback_feedback_source) - { - GSource *source; - - source = meta_kms_add_source_in_impl (kms, - mode_set_fallback_feedback_idle, - impl_device_simple, - NULL); - impl_device_simple->mode_set_fallback_feedback_source = source; - } - - impl_device_simple->mode_set_fallback_page_flip_datas = - g_list_prepend (impl_device_simple->mode_set_fallback_page_flip_datas, - page_flip_data); - - return TRUE; -} - -static gboolean -symbolic_page_flip_idle (gpointer user_data) -{ - MetaKmsPageFlipData *page_flip_data = user_data; - MetaKmsImplDevice *impl_device; - MetaKmsCrtc *crtc; - - impl_device = meta_kms_page_flip_data_get_impl_device (page_flip_data); - crtc = meta_kms_page_flip_data_get_crtc (page_flip_data); - - meta_topic (META_DEBUG_KMS, - "[simple] Handling symbolic page flip callback from %s, data: %p, CRTC: %u", - meta_kms_impl_device_get_path (impl_device), - page_flip_data, - meta_kms_crtc_get_id (crtc)); - - meta_kms_impl_device_handle_page_flip_callback (impl_device, page_flip_data); - - return G_SOURCE_REMOVE; -} - -static gboolean -dispatch_page_flip (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - MetaKmsPageFlipData *page_flip_data, - GError **error) -{ - MetaKmsImplDeviceSimple *impl_device_simple = - META_KMS_IMPL_DEVICE_SIMPLE (impl_device); - MetaKmsCrtc *crtc; - MetaKmsPlaneAssignment *plane_assignment; - g_autoptr (MetaKmsCustomPageFlip) custom_page_flip = NULL; - int fd; - int ret; - - crtc = meta_kms_page_flip_data_get_crtc (page_flip_data); - plane_assignment = meta_kms_update_get_primary_plane_assignment (update, - crtc); - - custom_page_flip = meta_kms_update_take_custom_page_flip_func (update); - - if (!plane_assignment && !custom_page_flip) - { - MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device); - MetaKms *kms = meta_kms_device_get_kms (device); - GSource *source; - - meta_kms_page_flip_data_make_symbolic (page_flip_data); - - source = meta_kms_add_source_in_impl (kms, - symbolic_page_flip_idle, - page_flip_data, - NULL); - - g_source_set_ready_time (source, 0); - g_source_unref (source); - - return TRUE; - } - - fd = meta_kms_impl_device_get_fd (impl_device); - if (custom_page_flip) - { - meta_topic (META_DEBUG_KMS, - "[simple] Invoking custom page flip on CRTC %u (%s)", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device)); - ret = custom_page_flip->func (custom_page_flip->user_data, - page_flip_data); - } - else - { - uint32_t fb_id; - - fb_id = meta_drm_buffer_get_fb_id (plane_assignment->buffer); - - meta_topic (META_DEBUG_KMS, - "[simple] Page flipping CRTC %u (%s) with %u, data: %p", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device), - fb_id, - page_flip_data); - - ret = drmModePageFlip (fd, - meta_kms_crtc_get_id (crtc), - fb_id, - DRM_MODE_PAGE_FLIP_EVENT, - page_flip_data); - } - - if (ret == -EBUSY) - { - CachedModeSet *cached_mode_set; - - meta_topic (META_DEBUG_KMS, - "[simple] Scheduling page flip retry on CRTC %u (%s)", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device)); - - cached_mode_set = get_cached_mode_set (impl_device_simple, crtc); - if (cached_mode_set) - { - uint32_t fb_id; - drmModeModeInfo *drm_mode; - float refresh_rate; - - if (plane_assignment) - fb_id = meta_drm_buffer_get_fb_id (plane_assignment->buffer); - else - fb_id = 0; - drm_mode = cached_mode_set->drm_mode; - refresh_rate = meta_calculate_drm_mode_refresh_rate (drm_mode); - meta_kms_impl_device_hold_fd (impl_device); - schedule_retry_page_flip (impl_device_simple, - crtc, - fb_id, - refresh_rate, - page_flip_data, - g_steal_pointer (&custom_page_flip)); - return TRUE; - } - else - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Page flip of %u failed, and no mode set available", - meta_kms_crtc_get_id (crtc)); - return FALSE; - } - } - else if (ret == -EINVAL) - { - meta_topic (META_DEBUG_KMS, - "[simple] Falling back to mode set on CRTC %u (%s)", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device)); - - return mode_set_fallback (impl_device_simple, - update, - plane_assignment, - page_flip_data, - error); - } - else if (ret != 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModePageFlip on CRTC %u failed: %s", - meta_kms_crtc_get_id (crtc), - g_strerror (-ret)); - return FALSE; - } - else - { - meta_kms_impl_device_hold_fd (impl_device); - - impl_device_simple->posted_page_flip_datas = - g_list_prepend (impl_device_simple->posted_page_flip_datas, - page_flip_data); - - return TRUE; - } -} - -static GList * -generate_page_flip_datas (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update) -{ - GList *listeners; - GList *page_flip_datas = NULL; - - listeners = g_list_copy (meta_kms_update_get_page_flip_listeners (update)); - - while (listeners) - { - MetaKmsPageFlipListener *listener = listeners->data; - MetaKmsCrtc *crtc = listener->crtc; - MetaKmsPageFlipData *page_flip_data; - gpointer user_data; - GDestroyNotify destroy_notify; - GList *l; - - page_flip_data = meta_kms_page_flip_data_new (impl_device, crtc); - page_flip_datas = g_list_append (page_flip_datas, page_flip_data); - - user_data = g_steal_pointer (&listener->user_data); - destroy_notify = g_steal_pointer (&listener->destroy_notify); - meta_kms_page_flip_data_add_listener (page_flip_data, - listener->vtable, - listener->flags, - user_data, - destroy_notify); - - listeners = g_list_delete_link (listeners, listeners); - - l = listeners; - while (l) - { - MetaKmsPageFlipListener *other_listener = l->data; - GList *l_next = l->next; - - if (other_listener->crtc == crtc) - { - gpointer other_user_data; - GDestroyNotify other_destroy_notify; - - other_user_data = g_steal_pointer (&other_listener->user_data); - other_destroy_notify = - g_steal_pointer (&other_listener->destroy_notify); - meta_kms_page_flip_data_add_listener (page_flip_data, - other_listener->vtable, - other_listener->flags, - other_user_data, - other_destroy_notify); - listeners = g_list_delete_link (listeners, l); - } - - l = l_next; - } - } - - return page_flip_datas; -} - -static gboolean -maybe_dispatch_page_flips (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - GList **failed_planes, - MetaKmsUpdateFlag flags, - GError **error) -{ - g_autoptr (GList) page_flip_datas = NULL; - GList *l; - - page_flip_datas = generate_page_flip_datas (impl_device, update); - - while (page_flip_datas) - { - g_autoptr (GList) l = NULL; - MetaKmsPageFlipData *page_flip_data; - - l = page_flip_datas; - page_flip_datas = g_list_remove_link (page_flip_datas, l); - page_flip_data = g_steal_pointer (&l->data); - - if (!dispatch_page_flip (impl_device, update, page_flip_data, error)) - { - if (!g_error_matches (*error, - G_IO_ERROR, - G_IO_ERROR_PERMISSION_DENIED)) - { - MetaKmsCrtc *crtc = - meta_kms_page_flip_data_get_crtc (page_flip_data); - MetaKmsPlaneAssignment *plane_assignment; - MetaKmsPlaneFeedback *plane_feedback; - - plane_assignment = - meta_kms_update_get_primary_plane_assignment (update, crtc); - - plane_feedback = - meta_kms_plane_feedback_new_take_error (plane_assignment->plane, - plane_assignment->crtc, - g_error_copy (*error)); - *failed_planes = g_list_prepend (*failed_planes, plane_feedback); - } - - if (!(flags & META_KMS_UPDATE_FLAG_PRESERVE_ON_ERROR)) - meta_kms_page_flip_data_discard_in_impl (page_flip_data, *error); - - goto err; - } - } - - return TRUE; - -err: - if (!(flags & META_KMS_UPDATE_FLAG_PRESERVE_ON_ERROR)) - { - for (l = page_flip_datas; l; l = l->next) - { - MetaKmsPageFlipData *page_flip_data = l->data; - - meta_kms_page_flip_data_discard_in_impl (page_flip_data, *error); - } - } - g_list_free (page_flip_datas); - - return FALSE; -} - -static gboolean -process_entries (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - GList *entries, - MetaKmsSimpleProcessFunc func, - GError **error) -{ - GList *l; - - for (l = entries; l; l = l->next) - { - if (!func (impl_device, update, l->data, error)) - return FALSE; - } - - return TRUE; -} - -static gboolean -process_cursor_plane_assignment (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - MetaKmsPlaneAssignment *plane_assignment, - GError **error) -{ - uint32_t crtc_id; - int fd; - - crtc_id = meta_kms_crtc_get_id (plane_assignment->crtc), - fd = meta_kms_impl_device_get_fd (impl_device); - - if (!(plane_assignment->flags & META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED)) - { - int width, height; - int ret = -1; - uint32_t handle_u32; - - width = plane_assignment->dst_rect.width; - height = plane_assignment->dst_rect.height; - - if (plane_assignment->buffer) - { - MetaDrmBufferGbm *buffer_gbm = - META_DRM_BUFFER_GBM (plane_assignment->buffer); - struct gbm_bo *bo; - union gbm_bo_handle handle; - - bo = meta_drm_buffer_gbm_get_bo (buffer_gbm); - handle = gbm_bo_get_handle (bo); - handle_u32 = handle.u32; - } - else - { - handle_u32 = 0; - } - - meta_topic (META_DEBUG_KMS, - "[simple] Setting HW cursor of CRTC %u (%s) to %u " - "(size: %dx%d, hot: (%d, %d))", - crtc_id, - meta_kms_impl_device_get_path (impl_device), - handle_u32, - width, height, - plane_assignment->cursor_hotspot.x, - plane_assignment->cursor_hotspot.y); - - if (plane_assignment->cursor_hotspot.is_valid) - { - ret = drmModeSetCursor2 (fd, - crtc_id, - handle_u32, - width, height, - plane_assignment->cursor_hotspot.x, - plane_assignment->cursor_hotspot.y); - } - - if (ret != 0) - { - ret = drmModeSetCursor (fd, crtc_id, - handle_u32, - width, height); - } - - if (ret != 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModeSetCursor failed: %s", g_strerror (-ret)); - return FALSE; - } - } - - meta_topic (META_DEBUG_KMS, - "[simple] Moving HW cursor of CRTC %u (%s) to (%d, %d)", - crtc_id, - meta_kms_impl_device_get_path (impl_device), - plane_assignment->dst_rect.x, - plane_assignment->dst_rect.y); - - drmModeMoveCursor (fd, - crtc_id, - plane_assignment->dst_rect.x, - plane_assignment->dst_rect.y); - - return TRUE; -} - -static gboolean -process_plane_assignment (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - MetaKmsPlaneAssignment *plane_assignment, - MetaKmsPlaneFeedback **plane_feedback) -{ - MetaKmsPlane *plane; - MetaKmsPlaneType plane_type; - GError *error = NULL; - - plane = plane_assignment->plane; - plane_type = meta_kms_plane_get_plane_type (plane); - switch (plane_type) - { - case META_KMS_PLANE_TYPE_PRIMARY: - /* Handled as part of the mode-set and page flip. */ - return TRUE; - case META_KMS_PLANE_TYPE_CURSOR: - if (!process_cursor_plane_assignment (impl_device, update, - plane_assignment, - &error)) - { - *plane_feedback = - meta_kms_plane_feedback_new_take_error (plane, - plane_assignment->crtc, - g_steal_pointer (&error)); - return FALSE; - } - else - { - return TRUE; - } - case META_KMS_PLANE_TYPE_OVERLAY: - error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED, - "Overlay planes cannot be assigned"); - *plane_feedback = - meta_kms_plane_feedback_new_take_error (plane, - plane_assignment->crtc, - g_steal_pointer (&error)); - return TRUE; - } - - g_assert_not_reached (); -} - -static gboolean -process_plane_assignments (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - GList **failed_planes, - GError **error) -{ - GList *l; - - for (l = meta_kms_update_get_plane_assignments (update); l; l = l->next) - { - MetaKmsPlaneAssignment *plane_assignment = l->data; - MetaKmsPlaneFeedback *plane_feedback; - - if (!process_plane_assignment (impl_device, update, plane_assignment, - &plane_feedback)) - { - if (g_error_matches (plane_feedback->error, - G_IO_ERROR, - G_IO_ERROR_PERMISSION_DENIED)) - { - g_propagate_error (error, - g_steal_pointer (&plane_feedback->error)); - meta_kms_plane_feedback_free (plane_feedback); - return FALSE; - } - - *failed_planes = g_list_prepend (*failed_planes, plane_feedback); - if (plane_assignment->flags & META_KMS_ASSIGN_PLANE_FLAG_ALLOW_FAIL) - { - continue; - } - else - { - g_propagate_error (error, g_error_copy (plane_feedback->error)); - return FALSE; - } - } - } - - return TRUE; -} - -static void -page_flip_handler (int fd, - unsigned int sequence, - unsigned int tv_sec, - unsigned int tv_usec, - void *user_data) -{ - MetaKmsPageFlipData *page_flip_data = user_data; - MetaKmsImplDevice *impl_device; - MetaKmsImplDeviceSimple *impl_device_simple; - MetaKmsCrtc *crtc; - - meta_kms_page_flip_data_set_timings_in_impl (page_flip_data, - sequence, tv_sec, tv_usec); - - impl_device = meta_kms_page_flip_data_get_impl_device (page_flip_data); - impl_device_simple = META_KMS_IMPL_DEVICE_SIMPLE (impl_device); - crtc = meta_kms_page_flip_data_get_crtc (page_flip_data); - - meta_topic (META_DEBUG_KMS, - "[simple] Handling page flip callback from %s, data: %p, CRTC: %u", - meta_kms_impl_device_get_path (impl_device), - page_flip_data, - meta_kms_crtc_get_id (crtc)); - - meta_kms_impl_device_unhold_fd (impl_device); - - meta_kms_impl_device_handle_page_flip_callback (impl_device, page_flip_data); - impl_device_simple->posted_page_flip_datas = - g_list_remove (impl_device_simple->posted_page_flip_datas, - page_flip_data); -} - -static void -meta_kms_impl_device_simple_setup_drm_event_context (MetaKmsImplDevice *impl_device, - drmEventContext *drm_event_context) -{ - drm_event_context->version = 2; - drm_event_context->page_flip_handler = page_flip_handler; -} - -static MetaKmsFeedback * -meta_kms_impl_device_simple_process_update (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - MetaKmsUpdateFlag flags) -{ - GError *error = NULL; - GList *failed_planes = NULL; - - meta_topic (META_DEBUG_KMS, - "[simple] Processing update %" G_GUINT64_FORMAT, - meta_kms_update_get_sequence_number (update)); - - if (meta_kms_update_is_power_save (update)) - { - if (!process_power_save (impl_device, &error)) - goto err; - goto out; - } - - if (!process_entries (impl_device, - update, - meta_kms_update_get_mode_sets (update), - process_mode_set, - &error)) - goto err; - - if (!process_entries (impl_device, - update, - meta_kms_update_get_connector_updates (update), - process_connector_update, - &error)) - goto err; - - if (!process_entries (impl_device, - update, - meta_kms_update_get_crtc_gammas (update), - process_crtc_gamma, - &error)) - goto err; - - if (!process_plane_assignments (impl_device, update, &failed_planes, &error)) - goto err; - - if (!maybe_dispatch_page_flips (impl_device, update, &failed_planes, flags, - &error)) - goto err; - -out: - return meta_kms_feedback_new_passed (failed_planes); - -err: - return meta_kms_feedback_new_failed (failed_planes, error); -} - -static void -flush_postponed_page_flip_datas (MetaKmsImplDeviceSimple *impl_device_simple) -{ - dispatch_page_flip_datas (&impl_device_simple->postponed_page_flip_datas, - (GFunc) meta_kms_page_flip_data_flipped_in_impl, - NULL); - dispatch_page_flip_datas (&impl_device_simple->postponed_mode_set_fallback_datas, - (GFunc) meta_kms_page_flip_data_mode_set_fallback_in_impl, - NULL); -} - -static void -meta_kms_impl_device_simple_handle_page_flip_callback (MetaKmsImplDevice *impl_device, - MetaKmsPageFlipData *page_flip_data) -{ - MetaKmsImplDeviceSimple *impl_device_simple = - META_KMS_IMPL_DEVICE_SIMPLE (impl_device); - - if (impl_device_simple->pending_page_flip_retries) - { - impl_device_simple->postponed_page_flip_datas = - g_list_append (impl_device_simple->postponed_page_flip_datas, - page_flip_data); - } - else - { - meta_kms_page_flip_data_flipped_in_impl (page_flip_data); - } -} - -static void -dispose_page_flip_data (MetaKmsPageFlipData *page_flip_data, - MetaKmsImplDevice *impl_device) -{ - meta_kms_page_flip_data_discard_in_impl (page_flip_data, NULL); - meta_kms_impl_device_unhold_fd (impl_device); -} - -static void -meta_kms_impl_device_simple_discard_pending_page_flips (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDeviceSimple *impl_device_simple = - META_KMS_IMPL_DEVICE_SIMPLE (impl_device); - GList *l; - - if (!impl_device_simple->pending_page_flip_retries) - return; - - for (l = impl_device_simple->pending_page_flip_retries; l; l = l->next) - { - RetryPageFlipData *retry_page_flip_data = l->data; - MetaKmsPageFlipData *page_flip_data; - - page_flip_data = g_steal_pointer (&retry_page_flip_data->page_flip_data); - - meta_topic (META_DEBUG_KMS, - "[simple] Discarding page flip retry for CRTC %u (%s)", - meta_kms_crtc_get_id ( - meta_kms_page_flip_data_get_crtc (page_flip_data)), - meta_kms_impl_device_get_path ( - meta_kms_page_flip_data_get_impl_device (page_flip_data))); - - dispose_page_flip_data (page_flip_data, impl_device); - retry_page_flip_data_free (retry_page_flip_data); - } - g_clear_pointer (&impl_device_simple->pending_page_flip_retries, g_list_free); - - g_clear_pointer (&impl_device_simple->retry_page_flips_source, - g_source_destroy); -} - -static void -meta_kms_impl_device_simple_prepare_shutdown (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDeviceSimple *impl_device_simple = - META_KMS_IMPL_DEVICE_SIMPLE (impl_device); - - g_list_foreach (impl_device_simple->posted_page_flip_datas, - (GFunc) dispose_page_flip_data, - impl_device); - g_clear_list (&impl_device_simple->posted_page_flip_datas, NULL); -} - -static void -meta_kms_impl_device_simple_finalize (GObject *object) -{ - MetaKmsImplDeviceSimple *impl_device_simple = - META_KMS_IMPL_DEVICE_SIMPLE (object); - MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (impl_device_simple); - - g_list_free_full (impl_device_simple->pending_page_flip_retries, - (GDestroyNotify) retry_page_flip_data_free); - dispatch_page_flip_datas (&impl_device_simple->postponed_page_flip_datas, - (GFunc) dispose_page_flip_data, - impl_device); - dispatch_page_flip_datas (&impl_device_simple->postponed_mode_set_fallback_datas, - (GFunc) dispose_page_flip_data, - impl_device); - - g_assert (!impl_device_simple->posted_page_flip_datas); - - g_clear_pointer (&impl_device_simple->mode_set_fallback_feedback_source, - g_source_destroy); - g_hash_table_destroy (impl_device_simple->cached_mode_sets); - - G_OBJECT_CLASS (meta_kms_impl_device_simple_parent_class)->finalize (object); -} - -static MetaDeviceFile * -meta_kms_impl_device_simple_open_device_file (MetaKmsImplDevice *impl_device, - const char *path, - GError **error) -{ - MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device); - MetaKms *kms = meta_kms_device_get_kms (device); - MetaBackend *backend = meta_kms_get_backend (kms); - MetaDevicePool *device_pool = - meta_backend_native_get_device_pool (META_BACKEND_NATIVE (backend)); - g_autoptr (MetaDeviceFile) device_file = NULL; - - device_file = meta_device_pool_open (device_pool, path, - META_DEVICE_FILE_FLAG_TAKE_CONTROL, - error); - if (!device_file) - return NULL; - - if (!meta_device_file_has_tag (device_file, - META_DEVICE_FILE_TAG_KMS, - META_KMS_DEVICE_FILE_TAG_SIMPLE)) - { - int fd = meta_device_file_get_fd (device_file); - - g_warn_if_fail (!meta_device_file_has_tag (device_file, - META_DEVICE_FILE_TAG_KMS, - META_KMS_DEVICE_FILE_TAG_ATOMIC)); - - if (drmSetClientCap (fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) != 0) - { - g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_NOT_SUPPORTED, - "DRM_CLIENT_CAP_UNIVERSAL_PLANES not supported"); - return NULL; - } - - meta_device_file_tag (device_file, - META_DEVICE_FILE_TAG_KMS, - META_KMS_DEVICE_FILE_TAG_SIMPLE); - } - - return g_steal_pointer (&device_file); -} - -static gboolean -meta_kms_impl_device_simple_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - MetaKmsImplDeviceSimple *impl_device_simple = - META_KMS_IMPL_DEVICE_SIMPLE (initable); - MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (impl_device_simple); - MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device); - GList *l; - - if (!initable_parent_iface->init (initable, cancellable, error)) - return FALSE; - - if (!meta_kms_impl_device_init_mode_setting (impl_device, error)) - return FALSE; - - impl_device_simple->cached_mode_sets = - g_hash_table_new_full (NULL, - NULL, - NULL, - (GDestroyNotify) cached_mode_set_free); - - for (l = meta_kms_device_get_crtcs (device); l; l = l->next) - { - MetaKmsCrtc *crtc = l->data; - MetaKmsPlane *plane; - - plane = meta_kms_device_get_cursor_plane_for (device, crtc); - if (plane) - continue; - - meta_topic (META_DEBUG_KMS, - "[simple] Adding fake cursor plane for CRTC %u (%s)", - meta_kms_crtc_get_id (crtc), - meta_kms_impl_device_get_path (impl_device)); - - meta_kms_device_add_fake_plane_in_impl (device, - META_KMS_PLANE_TYPE_CURSOR, - crtc); - } - - g_message ("Added device '%s' (%s) using non-atomic mode setting.", - meta_kms_impl_device_get_path (impl_device), - meta_kms_impl_device_get_driver_name (impl_device)); - - return TRUE; -} - -static void -meta_kms_impl_device_simple_init (MetaKmsImplDeviceSimple *impl_device_simple) -{ -} - -static void -initable_iface_init (GInitableIface *iface) -{ - initable_parent_iface = g_type_interface_peek_parent (iface); - - iface->init = meta_kms_impl_device_simple_initable_init; -} - -static void -meta_kms_impl_device_simple_class_init (MetaKmsImplDeviceSimpleClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaKmsImplDeviceClass *impl_device_class = - META_KMS_IMPL_DEVICE_CLASS (klass); - - object_class->finalize = meta_kms_impl_device_simple_finalize; - - impl_device_class->open_device_file = - meta_kms_impl_device_simple_open_device_file; - impl_device_class->setup_drm_event_context = - meta_kms_impl_device_simple_setup_drm_event_context; - impl_device_class->process_update = - meta_kms_impl_device_simple_process_update; - impl_device_class->handle_page_flip_callback = - meta_kms_impl_device_simple_handle_page_flip_callback; - impl_device_class->discard_pending_page_flips = - meta_kms_impl_device_simple_discard_pending_page_flips; - impl_device_class->prepare_shutdown = - meta_kms_impl_device_simple_prepare_shutdown; -} diff --git a/src/backends/native/meta-kms-impl-device-simple.h b/src/backends/native/meta-kms-impl-device-simple.h deleted file mode 100644 index 7be5f0a83..000000000 --- a/src/backends/native/meta-kms-impl-device-simple.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2018-2020 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_KMS_IMPL_DEVICE_SIMPLE_H -#define META_KMS_IMPL_DEVICE_SIMPLE_H - -#include "backends/native/meta-kms-impl-device.h" - -#define META_TYPE_KMS_IMPL_DEVICE_SIMPLE (meta_kms_impl_device_simple_get_type ()) -G_DECLARE_FINAL_TYPE (MetaKmsImplDeviceSimple, meta_kms_impl_device_simple, - META, KMS_IMPL_DEVICE_SIMPLE, MetaKmsImplDevice) - -#endif /* META_KMS_IMPL_DEVICE_SIMPLE_H */ diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c deleted file mode 100644 index e08e672e5..000000000 --- a/src/backends/native/meta-kms-impl-device.c +++ /dev/null @@ -1,1070 +0,0 @@ -/* - * 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. - */ - -#include "config.h" - -#include "backends/native/meta-kms-impl-device.h" - -#include -#include - -#include "backends/native/meta-backend-native.h" -#include "backends/native/meta-device-pool.h" -#include "backends/native/meta-kms-connector-private.h" -#include "backends/native/meta-kms-connector.h" -#include "backends/native/meta-kms-crtc-private.h" -#include "backends/native/meta-kms-crtc.h" -#include "backends/native/meta-kms-impl.h" -#include "backends/native/meta-kms-mode-private.h" -#include "backends/native/meta-kms-page-flip-private.h" -#include "backends/native/meta-kms-plane-private.h" -#include "backends/native/meta-kms-plane.h" -#include "backends/native/meta-kms-private.h" -#include "backends/native/meta-kms-update-private.h" - -#include "meta-default-modes.h" -#include "meta-private-enum-types.h" - -enum -{ - PROP_0, - - PROP_DEVICE, - PROP_IMPL, - PROP_PATH, - PROP_FLAGS, - - N_PROPS -}; - -static GParamSpec *obj_props[N_PROPS]; - -typedef struct _MetaKmsImplDevicePrivate -{ - MetaKmsDevice *device; - MetaKmsImpl *impl; - - int fd_hold_count; - MetaDeviceFile *device_file; - GSource *fd_source; - char *path; - MetaKmsDeviceFlag flags; - gboolean has_latched_fd_hold; - - char *driver_name; - char *driver_description; - - GList *crtcs; - GList *connectors; - GList *planes; - - MetaKmsDeviceCaps caps; - - GList *fallback_modes; -} MetaKmsImplDevicePrivate; - -static void -initable_iface_init (GInitableIface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaKmsImplDevice, meta_kms_impl_device, - G_TYPE_OBJECT, - G_ADD_PRIVATE (MetaKmsImplDevice) - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - initable_iface_init)) - -G_DEFINE_QUARK (-meta-kms-error-quark, meta_kms_error) - -MetaKmsDevice * -meta_kms_impl_device_get_device (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - return priv->device; -} - -GList * -meta_kms_impl_device_copy_connectors (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - return g_list_copy (priv->connectors); -} - -GList * -meta_kms_impl_device_copy_crtcs (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - return g_list_copy (priv->crtcs); -} - -GList * -meta_kms_impl_device_copy_planes (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - return g_list_copy (priv->planes); -} - -GList * -meta_kms_impl_device_peek_connectors (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - return priv->connectors; -} - -GList * -meta_kms_impl_device_peek_crtcs (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - return priv->crtcs; -} - -GList * -meta_kms_impl_device_peek_planes (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - return priv->planes; -} - -const MetaKmsDeviceCaps * -meta_kms_impl_device_get_caps (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - return &priv->caps; -} - -GList * -meta_kms_impl_device_copy_fallback_modes (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - return g_list_copy (priv->fallback_modes); -} - -const char * -meta_kms_impl_device_get_driver_name (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - return priv->driver_name; -} - -const char * -meta_kms_impl_device_get_driver_description (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - return priv->driver_description; -} - -const char * -meta_kms_impl_device_get_path (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - return priv->path; -} - -gboolean -meta_kms_impl_device_dispatch (MetaKmsImplDevice *impl_device, - GError **error) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device); - int fd; - - drmEventContext drm_event_context; - - meta_assert_in_kms_impl (meta_kms_impl_get_kms (priv->impl)); - - drm_event_context = (drmEventContext) { 0 }; - klass->setup_drm_event_context (impl_device, &drm_event_context); - - fd = meta_device_file_get_fd (priv->device_file); - - while (TRUE) - { - if (drmHandleEvent (fd, &drm_event_context) != 0) - { - struct pollfd pfd; - int ret; - - if (errno != EAGAIN) - { - g_set_error_literal (error, G_IO_ERROR, - g_io_error_from_errno (errno), - strerror (errno)); - return FALSE; - } - - pfd.fd = fd; - pfd.events = POLL_IN | POLL_ERR; - do - { - ret = poll (&pfd, 1, -1); - } - while (ret == -1 && errno == EINTR); - } - else - { - break; - } - } - - return TRUE; -} - -static gpointer -kms_event_dispatch_in_impl (MetaKmsImpl *impl, - gpointer user_data, - GError **error) -{ - MetaKmsImplDevice *impl_device = user_data; - gboolean ret; - - ret = meta_kms_impl_device_dispatch (impl_device, error); - return GINT_TO_POINTER (ret); -} - -drmModePropertyPtr -meta_kms_impl_device_find_property (MetaKmsImplDevice *impl_device, - drmModeObjectProperties *props, - const char *prop_name, - int *out_idx) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - int fd; - unsigned int i; - - meta_assert_in_kms_impl (meta_kms_impl_get_kms (priv->impl)); - - fd = meta_device_file_get_fd (priv->device_file); - - for (i = 0; i < props->count_props; i++) - { - drmModePropertyPtr prop; - - prop = drmModeGetProperty (fd, props->props[i]); - if (!prop) - continue; - - if (strcmp (prop->name, prop_name) == 0) - { - *out_idx = i; - return prop; - } - - drmModeFreeProperty (prop); - } - - return NULL; -} - -static void -init_caps (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - int fd; - uint64_t cursor_width, cursor_height; - uint64_t prefer_shadow; - uint64_t uses_monotonic_clock; - - fd = meta_device_file_get_fd (priv->device_file); - if (drmGetCap (fd, DRM_CAP_CURSOR_WIDTH, &cursor_width) == 0 && - drmGetCap (fd, DRM_CAP_CURSOR_HEIGHT, &cursor_height) == 0) - { - priv->caps.has_cursor_size = TRUE; - priv->caps.cursor_width = cursor_width; - priv->caps.cursor_height = cursor_height; - } - - if (drmGetCap (fd, DRM_CAP_DUMB_PREFER_SHADOW, &prefer_shadow) == 0) - { - if (prefer_shadow) - g_message ("Device '%s' prefers shadow buffer", priv->path); - - priv->caps.prefers_shadow_buffer = prefer_shadow; - } - - if (drmGetCap (fd, DRM_CAP_TIMESTAMP_MONOTONIC, &uses_monotonic_clock) == 0) - { - priv->caps.uses_monotonic_clock = uses_monotonic_clock; - } -} - -static void -init_crtcs (MetaKmsImplDevice *impl_device, - drmModeRes *drm_resources) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - int idx; - int fd; - - fd = meta_device_file_get_fd (priv->device_file); - - for (idx = 0; idx < drm_resources->count_crtcs; idx++) - { - uint32_t crtc_id; - drmModeCrtc *drm_crtc; - MetaKmsCrtc *crtc; - g_autoptr (GError) error = NULL; - - crtc_id = drm_resources->crtcs[idx]; - drm_crtc = drmModeGetCrtc (fd, crtc_id); - if (!drm_crtc) - { - g_warning ("Failed to get CRTC %u info on '%s': %s", - crtc_id, priv->path, error->message); - continue; - } - - crtc = meta_kms_crtc_new (impl_device, drm_crtc, idx, &error); - - drmModeFreeCrtc (drm_crtc); - - if (!crtc) - { - g_warning ("Failed to create CRTC for %u on '%s': %s", - crtc_id, priv->path, error->message); - continue; - } - - priv->crtcs = g_list_prepend (priv->crtcs, crtc); - } - priv->crtcs = g_list_reverse (priv->crtcs); -} - -static MetaKmsConnector * -find_existing_connector (MetaKmsImplDevice *impl_device, - drmModeConnector *drm_connector) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - GList *l; - - for (l = priv->connectors; l; l = l->next) - { - MetaKmsConnector *connector = l->data; - - if (meta_kms_connector_is_same_as (connector, drm_connector)) - return connector; - } - - return NULL; -} - -static void -update_connectors (MetaKmsImplDevice *impl_device, - drmModeRes *drm_resources) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - GList *connectors = NULL; - unsigned int i; - int fd; - - fd = meta_device_file_get_fd (priv->device_file); - - for (i = 0; i < drm_resources->count_connectors; i++) - { - drmModeConnector *drm_connector; - MetaKmsConnector *connector; - - drm_connector = drmModeGetConnector (fd, drm_resources->connectors[i]); - if (!drm_connector) - continue; - - connector = find_existing_connector (impl_device, drm_connector); - if (connector) - connector = g_object_ref (connector); - else - connector = meta_kms_connector_new (impl_device, drm_connector, - drm_resources); - drmModeFreeConnector (drm_connector); - - connectors = g_list_prepend (connectors, connector); - } - - g_list_free_full (priv->connectors, g_object_unref); - priv->connectors = g_list_reverse (connectors); -} - -static MetaKmsPlaneType -get_plane_type (MetaKmsImplDevice *impl_device, - drmModeObjectProperties *props) -{ - drmModePropertyPtr prop; - int idx; - - prop = meta_kms_impl_device_find_property (impl_device, props, "type", &idx); - if (!prop) - return FALSE; - drmModeFreeProperty (prop); - - switch (props->prop_values[idx]) - { - case DRM_PLANE_TYPE_PRIMARY: - return META_KMS_PLANE_TYPE_PRIMARY; - case DRM_PLANE_TYPE_CURSOR: - return META_KMS_PLANE_TYPE_CURSOR; - case DRM_PLANE_TYPE_OVERLAY: - return META_KMS_PLANE_TYPE_OVERLAY; - default: - g_warning ("Unhandled plane type %" G_GUINT64_FORMAT, - props->prop_values[idx]); - return -1; - } -} - -MetaKmsPlane * -meta_kms_impl_device_add_fake_plane (MetaKmsImplDevice *impl_device, - MetaKmsPlaneType plane_type, - MetaKmsCrtc *crtc) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - MetaKmsPlane *plane; - - plane = meta_kms_plane_new_fake (plane_type, crtc); - priv->planes = g_list_append (priv->planes, plane); - - return plane; -} - -static MetaKmsProp * -find_prop (MetaKmsProp *props, - int n_props, - const char *name) -{ - int i; - - for (i = 0; i < n_props; i++) - { - MetaKmsProp *prop = &props[i]; - - g_warn_if_fail (prop->name); - - if (g_strcmp0 (prop->name, name) == 0) - return prop; - } - - return NULL; -} - -void -meta_kms_impl_device_init_prop_table (MetaKmsImplDevice *impl_device, - uint32_t *drm_props, - uint64_t *drm_prop_values, - int n_drm_props, - MetaKmsProp *props, - int n_props, - gpointer user_data) -{ - int fd; - uint32_t i; - - fd = meta_kms_impl_device_get_fd (impl_device); - - for (i = 0; i < n_drm_props; i++) - { - drmModePropertyRes *drm_prop; - MetaKmsProp *prop; - - drm_prop = drmModeGetProperty (fd, drm_props[i]); - if (!drm_prop) - continue; - - prop = find_prop (props, n_props, drm_prop->name); - if (!prop) - { - drmModeFreeProperty (drm_prop); - continue; - } - - if (!(drm_prop->flags & prop->type)) - { - g_warning ("DRM property '%s' (%u) had unexpected flags (0x%x), " - "ignoring", - drm_prop->name, drm_props[i], drm_prop->flags); - drmModeFreeProperty (drm_prop); - continue; - } - - prop->prop_id = drm_props[i]; - - if (prop->parse) - { - prop->parse (impl_device, prop, - drm_prop, drm_prop_values[i], - user_data); - } - - drmModeFreeProperty (drm_prop); - } -} - -static void -init_planes (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - int fd; - drmModePlaneRes *drm_planes; - unsigned int i; - - fd = meta_device_file_get_fd (priv->device_file); - - drm_planes = drmModeGetPlaneResources (fd); - if (!drm_planes) - return; - - for (i = 0; i < drm_planes->count_planes; i++) - { - drmModePlane *drm_plane; - drmModeObjectProperties *props; - - drm_plane = drmModeGetPlane (fd, drm_planes->planes[i]); - if (!drm_plane) - continue; - - props = drmModeObjectGetProperties (fd, - drm_plane->plane_id, - DRM_MODE_OBJECT_PLANE); - if (props) - { - MetaKmsPlaneType plane_type; - - plane_type = get_plane_type (impl_device, props); - if (plane_type != -1) - { - MetaKmsPlane *plane; - - plane = meta_kms_plane_new (plane_type, - impl_device, - drm_plane, props); - - priv->planes = g_list_prepend (priv->planes, plane); - } - } - - g_clear_pointer (&props, drmModeFreeObjectProperties); - drmModeFreePlane (drm_plane); - } - priv->planes = g_list_reverse (priv->planes); -} - -static void -init_fallback_modes (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - GList *modes = NULL; - int i; - - for (i = 0; i < G_N_ELEMENTS (meta_default_landscape_drm_mode_infos); i++) - { - MetaKmsMode *mode; - - mode = meta_kms_mode_new (impl_device, - &meta_default_landscape_drm_mode_infos[i], - META_KMS_MODE_FLAG_FALLBACK_LANDSCAPE); - modes = g_list_prepend (modes, mode); - } - - for (i = 0; i < G_N_ELEMENTS (meta_default_portrait_drm_mode_infos); i++) - { - MetaKmsMode *mode; - - mode = meta_kms_mode_new (impl_device, - &meta_default_portrait_drm_mode_infos[i], - META_KMS_MODE_FLAG_FALLBACK_PORTRAIT); - modes = g_list_prepend (modes, mode); - } - - priv->fallback_modes = g_list_reverse (modes); -} - -static MetaDeviceFile * -meta_kms_impl_device_open_device_file (MetaKmsImplDevice *impl_device, - const char *path, - GError **error) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device); - - return klass->open_device_file (impl_device, priv->path, error); -} - -static gboolean -ensure_device_file (MetaKmsImplDevice *impl_device, - GError **error) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - MetaDeviceFile *device_file; - - if (priv->device_file) - return TRUE; - - device_file = meta_kms_impl_device_open_device_file (impl_device, - priv->path, - error); - if (!device_file) - return FALSE; - - priv->device_file = device_file; - - if (!(priv->flags & META_KMS_DEVICE_FLAG_NO_MODE_SETTING)) - { - priv->fd_source = - meta_kms_register_fd_in_impl (meta_kms_impl_get_kms (priv->impl), - meta_device_file_get_fd (device_file), - kms_event_dispatch_in_impl, - impl_device); - } - - return TRUE; -} - -static void -ensure_latched_fd_hold (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - if (!priv->has_latched_fd_hold) - { - meta_kms_impl_device_hold_fd (impl_device); - priv->has_latched_fd_hold = TRUE; - } -} - -static void -clear_latched_fd_hold (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - if (priv->has_latched_fd_hold) - { - meta_kms_impl_device_unhold_fd (impl_device); - priv->has_latched_fd_hold = FALSE; - } -} - -void -meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - g_autoptr (GError) error = NULL; - int fd; - drmModeRes *drm_resources; - - meta_assert_in_kms_impl (meta_kms_impl_get_kms (priv->impl)); - - meta_topic (META_DEBUG_KMS, "Updating device state for %s", priv->path); - - if (!ensure_device_file (impl_device, &error)) - { - g_warning ("Failed to reopen '%s': %s", priv->path, error->message); - goto err; - } - - ensure_latched_fd_hold (impl_device); - - fd = meta_device_file_get_fd (priv->device_file); - drm_resources = drmModeGetResources (fd); - if (!drm_resources) - { - meta_topic (META_DEBUG_KMS, "Device '%s' didn't return any resources", - priv->path); - goto err; - } - - update_connectors (impl_device, drm_resources); - - g_list_foreach (priv->crtcs, (GFunc) meta_kms_crtc_update_state, - NULL); - g_list_foreach (priv->connectors, (GFunc) meta_kms_connector_update_state, - drm_resources); - drmModeFreeResources (drm_resources); - - return; - -err: - g_clear_list (&priv->planes, g_object_unref); - g_clear_list (&priv->crtcs, g_object_unref); - g_clear_list (&priv->connectors, g_object_unref); -} - -void -meta_kms_impl_device_predict_states (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - g_list_foreach (priv->crtcs, (GFunc) meta_kms_crtc_predict_state, - update); - g_list_foreach (priv->connectors, (GFunc) meta_kms_connector_predict_state, - update); -} - -void -meta_kms_impl_device_notify_modes_set (MetaKmsImplDevice *impl_device) -{ - clear_latched_fd_hold (impl_device); -} - -int -meta_kms_impl_device_get_fd (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - meta_assert_in_kms_impl (meta_kms_impl_get_kms (priv->impl)); - - return meta_device_file_get_fd (priv->device_file); -} - -MetaKmsFeedback * -meta_kms_impl_device_process_update (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - MetaKmsUpdateFlag flags) -{ - MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device); - MetaKmsFeedback *feedback; - g_autoptr (GError) error = NULL; - - if (!ensure_device_file (impl_device, &error)) - return meta_kms_feedback_new_failed (NULL, g_steal_pointer (&error)); - - meta_kms_impl_device_hold_fd (impl_device); - feedback = klass->process_update (impl_device, update, flags); - meta_kms_impl_device_unhold_fd (impl_device); - - return feedback; -} - -void -meta_kms_impl_device_handle_page_flip_callback (MetaKmsImplDevice *impl_device, - MetaKmsPageFlipData *page_flip_data) -{ - MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device); - - klass->handle_page_flip_callback (impl_device, page_flip_data); -} - -void -meta_kms_impl_device_discard_pending_page_flips (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device); - - klass->discard_pending_page_flips (impl_device); -} - -void -meta_kms_impl_device_hold_fd (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - MetaKms *kms = meta_kms_device_get_kms (priv->device); - - meta_assert_in_kms_impl (kms); - - g_assert (priv->device_file); - - priv->fd_hold_count++; -} - -void -meta_kms_impl_device_unhold_fd (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - MetaKms *kms = meta_kms_device_get_kms (priv->device); - - meta_assert_in_kms_impl (kms); - - g_return_if_fail (priv->fd_hold_count > 0); - - priv->fd_hold_count--; - if (priv->fd_hold_count == 0) - { - g_clear_pointer (&priv->device_file, meta_device_file_release); - - if (priv->fd_source) - { - g_source_destroy (priv->fd_source); - g_clear_pointer (&priv->fd_source, g_source_unref); - } - } -} - -static void -meta_kms_impl_device_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (object); - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - switch (prop_id) - { - case PROP_DEVICE: - g_value_set_object (value, priv->device); - break; - case PROP_IMPL: - g_value_set_object (value, priv->impl); - break; - case PROP_FLAGS: - g_value_set_flags (value, priv->flags); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_kms_impl_device_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (object); - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - switch (prop_id) - { - case PROP_DEVICE: - priv->device = g_value_get_object (value); - break; - case PROP_IMPL: - priv->impl = g_value_get_object (value); - break; - case PROP_PATH: - priv->path = g_value_dup_string (value); - break; - case PROP_FLAGS: - priv->flags = g_value_get_flags (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_kms_impl_device_finalize (GObject *object) -{ - MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (object); - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - - meta_kms_impl_remove_impl_device (priv->impl, impl_device); - - g_list_free_full (priv->planes, g_object_unref); - g_list_free_full (priv->crtcs, g_object_unref); - g_list_free_full (priv->connectors, g_object_unref); - g_list_free_full (priv->fallback_modes, - (GDestroyNotify) meta_kms_mode_free); - - clear_latched_fd_hold (impl_device); - g_warn_if_fail (!priv->device_file); - - g_free (priv->driver_name); - g_free (priv->driver_description); - g_free (priv->path); - - G_OBJECT_CLASS (meta_kms_impl_device_parent_class)->finalize (object); -} - -gboolean -meta_kms_impl_device_init_mode_setting (MetaKmsImplDevice *impl_device, - GError **error) -{ - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - int fd; - drmModeRes *drm_resources; - - fd = meta_device_file_get_fd (priv->device_file); - - drm_resources = drmModeGetResources (fd); - if (!drm_resources) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "Failed to activate universal planes: %s", - g_strerror (errno)); - return FALSE; - } - - init_caps (impl_device); - - init_crtcs (impl_device, drm_resources); - init_planes (impl_device); - - init_fallback_modes (impl_device); - - update_connectors (impl_device, drm_resources); - - drmModeFreeResources (drm_resources); - - return TRUE; -} - -void -meta_kms_impl_device_prepare_shutdown (MetaKmsImplDevice *impl_device) -{ - MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device); - - if (klass->prepare_shutdown) - klass->prepare_shutdown (impl_device); -} - -static gboolean -get_driver_info (int fd, - char **name, - char **description) -{ - drmVersion *drm_version; - - drm_version = drmGetVersion (fd); - if (!drm_version) - return FALSE; - - *name = g_strndup (drm_version->name, - drm_version->name_len); - *description = g_strndup (drm_version->desc, - drm_version->desc_len); - drmFreeVersion (drm_version); - - return TRUE; -} - -static gboolean -meta_kms_impl_device_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (initable); - MetaKmsImplDevicePrivate *priv = - meta_kms_impl_device_get_instance_private (impl_device); - int fd; - - if (!ensure_device_file (impl_device, error)) - return FALSE; - - ensure_latched_fd_hold (impl_device); - - g_clear_pointer (&priv->path, g_free); - priv->path = g_strdup (meta_device_file_get_path (priv->device_file)); - - fd = meta_device_file_get_fd (priv->device_file); - if (!get_driver_info (fd, &priv->driver_name, &priv->driver_description)) - { - priv->driver_name = g_strdup ("unknown"); - priv->driver_description = g_strdup ("Unknown"); - } - - return TRUE; -} - -static void -meta_kms_impl_device_init (MetaKmsImplDevice *impl_device) -{ -} - -static void -initable_iface_init (GInitableIface *iface) -{ - iface->init = meta_kms_impl_device_initable_init; -} - -static void -meta_kms_impl_device_class_init (MetaKmsImplDeviceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->get_property = meta_kms_impl_device_get_property; - object_class->set_property = meta_kms_impl_device_set_property; - object_class->finalize = meta_kms_impl_device_finalize; - - obj_props[PROP_DEVICE] = - g_param_spec_object ("device", - "device", - "MetaKmsDevice", - META_TYPE_KMS_DEVICE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - obj_props[PROP_IMPL] = - g_param_spec_object ("impl", - "impl", - "MetaKmsImpl", - META_TYPE_KMS_IMPL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - obj_props[PROP_PATH] = - g_param_spec_string ("path", - "path", - "Device path", - NULL, - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - obj_props[PROP_FLAGS] = - g_param_spec_flags ("flags", - "flags", - "KMS impl device flags", - META_TYPE_KMS_DEVICE_FLAG, - META_KMS_DEVICE_FLAG_NONE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, N_PROPS, obj_props); -} diff --git a/src/backends/native/meta-kms-impl-device.h b/src/backends/native/meta-kms-impl-device.h deleted file mode 100644 index e77024ecd..000000000 --- a/src/backends/native/meta-kms-impl-device.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * 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_KMS_IMPL_DEVICE_H -#define META_KMS_IMPL_DEVICE_H - -#include -#include -#include -#include - -#include "backends/native/meta-device-pool.h" -#include "backends/native/meta-kms-device.h" -#include "backends/native/meta-kms-page-flip-private.h" -#include "backends/native/meta-kms-types.h" -#include "backends/native/meta-kms-update.h" -#include "backends/native/meta-kms.h" - -typedef struct _MetaKmsDeviceCaps -{ - gboolean has_cursor_size; - uint64_t cursor_width; - uint64_t cursor_height; - - gboolean prefers_shadow_buffer; - gboolean uses_monotonic_clock; -} MetaKmsDeviceCaps; - -typedef struct _MetaKmsProp MetaKmsProp; - -struct _MetaKmsProp -{ - const char *name; - uint32_t type; - MetaKmsPropType internal_type; - void (* parse) (MetaKmsImplDevice *impl_device, - MetaKmsProp *prop, - drmModePropertyPtr drm_prop, - uint64_t value, - gpointer user_data); - - uint32_t prop_id; -}; - -#define META_TYPE_KMS_IMPL_DEVICE (meta_kms_impl_device_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaKmsImplDevice, meta_kms_impl_device, - META, KMS_IMPL_DEVICE, - GObject) - -struct _MetaKmsImplDeviceClass -{ - GObjectClass parent_class; - - MetaDeviceFile * (* open_device_file) (MetaKmsImplDevice *impl_device, - const char *path, - GError **error); - void (* setup_drm_event_context) (MetaKmsImplDevice *impl_device, - drmEventContext *drm_event_context); - MetaKmsFeedback * (* process_update) (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - MetaKmsUpdateFlag flags); - void (* handle_page_flip_callback) (MetaKmsImplDevice *impl_device, - MetaKmsPageFlipData *page_flip_data); - void (* discard_pending_page_flips) (MetaKmsImplDevice *impl_device); - void (* prepare_shutdown) (MetaKmsImplDevice *impl_device); -}; - -enum -{ - META_KMS_ERROR_USER_INHIBITED, - META_KMS_ERROR_DENY_LISTED, - META_KMS_ERROR_NOT_SUPPORTED, -}; - -enum -{ - META_KMS_DEVICE_FILE_TAG_ATOMIC = 1 << 0, - META_KMS_DEVICE_FILE_TAG_SIMPLE = 1 << 1, -}; - -#define META_KMS_ERROR meta_kms_error_quark () -GQuark meta_kms_error_quark (void); - -MetaKmsDevice * meta_kms_impl_device_get_device (MetaKmsImplDevice *impl_device); - -GList * meta_kms_impl_device_copy_connectors (MetaKmsImplDevice *impl_device); - -GList * meta_kms_impl_device_copy_crtcs (MetaKmsImplDevice *impl_device); - -GList * meta_kms_impl_device_copy_planes (MetaKmsImplDevice *impl_device); - -GList * meta_kms_impl_device_peek_connectors (MetaKmsImplDevice *impl_device); - -GList * meta_kms_impl_device_peek_crtcs (MetaKmsImplDevice *impl_device); - -GList * meta_kms_impl_device_peek_planes (MetaKmsImplDevice *impl_device); - -const MetaKmsDeviceCaps * meta_kms_impl_device_get_caps (MetaKmsImplDevice *impl_device); - -GList * meta_kms_impl_device_copy_fallback_modes (MetaKmsImplDevice *impl_device); - -const char * meta_kms_impl_device_get_driver_name (MetaKmsImplDevice *impl_device); - -const char * meta_kms_impl_device_get_driver_description (MetaKmsImplDevice *impl_device); - -const char * meta_kms_impl_device_get_path (MetaKmsImplDevice *impl_device); - -gboolean meta_kms_impl_device_dispatch (MetaKmsImplDevice *impl_device, - GError **error); - -drmModePropertyPtr meta_kms_impl_device_find_property (MetaKmsImplDevice *impl_device, - drmModeObjectProperties *props, - const char *prop_name, - int *idx); - -int meta_kms_impl_device_get_fd (MetaKmsImplDevice *impl_device); - -void meta_kms_impl_device_hold_fd (MetaKmsImplDevice *impl_device); - -void meta_kms_impl_device_unhold_fd (MetaKmsImplDevice *impl_device); - -void meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device); - -void meta_kms_impl_device_predict_states (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update); - -void meta_kms_impl_device_notify_modes_set (MetaKmsImplDevice *impl_device); - -MetaKmsPlane * meta_kms_impl_device_add_fake_plane (MetaKmsImplDevice *impl_device, - MetaKmsPlaneType plane_type, - MetaKmsCrtc *crtc); - -void meta_kms_impl_device_init_prop_table (MetaKmsImplDevice *impl_device, - uint32_t *drm_props, - uint64_t *drm_props_values, - int n_drm_props, - MetaKmsProp *props, - int n_props, - gpointer user_data); - -void meta_kms_impl_device_reload_prop_values (MetaKmsImplDevice *impl_device, - uint32_t *drm_props, - uint64_t *drm_prop_values, - int n_drm_props, - gpointer user_data, - ...); - -MetaKmsFeedback * meta_kms_impl_device_process_update (MetaKmsImplDevice *impl_device, - MetaKmsUpdate *update, - MetaKmsUpdateFlag flags); - -void meta_kms_impl_device_handle_page_flip_callback (MetaKmsImplDevice *impl_device, - MetaKmsPageFlipData *page_flip_data); - -void meta_kms_impl_device_discard_pending_page_flips (MetaKmsImplDevice *impl_device); - -gboolean meta_kms_impl_device_init_mode_setting (MetaKmsImplDevice *impl_device, - GError **error); - -void meta_kms_impl_device_prepare_shutdown (MetaKmsImplDevice *impl_device); - -#endif /* META_KMS_IMPL_DEVICE_H */ diff --git a/src/backends/native/meta-kms-impl.c b/src/backends/native/meta-kms-impl.c deleted file mode 100644 index 0ad76e085..000000000 --- a/src/backends/native/meta-kms-impl.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2018 Red Hat - * Copyright (C) 2019 DisplayLink (UK) Ltd. - * - * 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 "backends/native/meta-kms-impl.h" - -#include "backends/native/meta-kms-private.h" -#include "backends/native/meta-kms-device-private.h" -#include "backends/native/meta-kms-update-private.h" - -enum -{ - PROP_0, - - PROP_KMS, -}; - -struct _MetaKmsImpl -{ - GObject parent; -}; - -typedef struct _MetaKmsImplPrivate -{ - MetaKms *kms; - - GList *impl_devices; -} MetaKmsImplPrivate; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaKmsImpl, meta_kms_impl, G_TYPE_OBJECT) - -MetaKms * -meta_kms_impl_get_kms (MetaKmsImpl *impl) -{ - MetaKmsImplPrivate *priv = meta_kms_impl_get_instance_private (impl); - - return priv->kms; -} - -void -meta_kms_impl_add_impl_device (MetaKmsImpl *impl, - MetaKmsImplDevice *impl_device) -{ - MetaKmsImplPrivate *priv = meta_kms_impl_get_instance_private (impl); - - meta_assert_in_kms_impl (priv->kms); - - priv->impl_devices = g_list_append (priv->impl_devices, impl_device); -} - -void -meta_kms_impl_remove_impl_device (MetaKmsImpl *impl, - MetaKmsImplDevice *impl_device) -{ - MetaKmsImplPrivate *priv = meta_kms_impl_get_instance_private (impl); - - meta_assert_in_kms_impl (priv->kms); - - priv->impl_devices = g_list_remove (priv->impl_devices, impl_device); -} - -MetaKmsFeedback * -meta_kms_impl_process_update (MetaKmsImpl *impl, - MetaKmsUpdate *update, - MetaKmsUpdateFlag flags) -{ - MetaKmsImplPrivate *priv = meta_kms_impl_get_instance_private (impl); - MetaKmsDevice *device; - MetaKmsImplDevice *impl_device; - - meta_assert_in_kms_impl (priv->kms); - - device = meta_kms_update_get_device (update); - impl_device = meta_kms_device_get_impl_device (device); - - return meta_kms_impl_device_process_update (impl_device, update, flags); -} - -void -meta_kms_impl_discard_pending_page_flips (MetaKmsImpl *impl) -{ - MetaKmsImplPrivate *priv = meta_kms_impl_get_instance_private (impl); - - g_list_foreach (priv->impl_devices, - (GFunc) meta_kms_impl_device_discard_pending_page_flips, - NULL); -} - -void -meta_kms_impl_prepare_shutdown (MetaKmsImpl *impl) -{ - MetaKmsImplPrivate *priv = meta_kms_impl_get_instance_private (impl); - GList *l; - - for (l = priv->impl_devices; l; l = l->next) - { - MetaKmsImplDevice *impl_device = l->data; - - meta_kms_impl_device_discard_pending_page_flips (impl_device); - meta_kms_impl_device_prepare_shutdown (impl_device); - } -} - -void -meta_kms_impl_notify_modes_set (MetaKmsImpl *impl) -{ - MetaKmsImplPrivate *priv = meta_kms_impl_get_instance_private (impl); - - g_list_foreach (priv->impl_devices, - (GFunc) meta_kms_impl_device_notify_modes_set, - NULL); -} - -MetaKmsImpl * -meta_kms_impl_new (MetaKms *kms) -{ - return g_object_new (META_TYPE_KMS_IMPL, - "kms", kms, - NULL); -} - -static void -meta_kms_impl_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaKmsImpl *impl = META_KMS_IMPL (object); - MetaKmsImplPrivate *priv = meta_kms_impl_get_instance_private (impl); - - switch (prop_id) - { - case PROP_KMS: - priv->kms = g_value_get_object (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_kms_impl_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaKmsImpl *impl = META_KMS_IMPL (object); - MetaKmsImplPrivate *priv = meta_kms_impl_get_instance_private (impl); - - switch (prop_id) - { - case PROP_KMS: - g_value_set_object (value, priv->kms); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_kms_impl_init (MetaKmsImpl *kms_impl) -{ -} - -static void -meta_kms_impl_class_init (MetaKmsImplClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GParamSpec *pspec; - - object_class->set_property = meta_kms_impl_set_property; - object_class->get_property = meta_kms_impl_get_property; - - pspec = g_param_spec_object ("kms", - "kms", - "MetaKms", - META_TYPE_KMS, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS | - G_PARAM_CONSTRUCT_ONLY); - g_object_class_install_property (object_class, - PROP_KMS, - pspec); -} diff --git a/src/backends/native/meta-kms-impl.h b/src/backends/native/meta-kms-impl.h deleted file mode 100644 index 58f03f81a..000000000 --- a/src/backends/native/meta-kms-impl.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2018 Red Hat - * Copyright (C) 2019 DisplayLink (UK) Ltd. - * - * 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_KMS_IMPL_H -#define META_KMS_IMPL_H - -#include "backends/native/meta-kms-impl-device.h" -#include "backends/native/meta-kms-page-flip-private.h" -#include "backends/native/meta-kms.h" - -#define META_TYPE_KMS_IMPL (meta_kms_impl_get_type ()) -G_DECLARE_FINAL_TYPE (MetaKmsImpl, meta_kms_impl, - META, KMS_IMPL, GObject) - -MetaKms * meta_kms_impl_get_kms (MetaKmsImpl *impl); - -MetaKmsFeedback * meta_kms_impl_process_update (MetaKmsImpl *impl, - MetaKmsUpdate *update, - MetaKmsUpdateFlag flags); - -void meta_kms_impl_add_impl_device (MetaKmsImpl *impl, - MetaKmsImplDevice *impl_device); - -void meta_kms_impl_remove_impl_device (MetaKmsImpl *impl, - MetaKmsImplDevice *impl_device); - -void meta_kms_impl_discard_pending_page_flips (MetaKmsImpl *impl); - -void meta_kms_impl_prepare_shutdown (MetaKmsImpl *impl); - -void meta_kms_impl_notify_modes_set (MetaKmsImpl *impl); - -MetaKmsImpl * meta_kms_impl_new (MetaKms *kms); - -#endif /* META_KMS_IMPL_H */ diff --git a/src/backends/native/meta-kms-mode-private.h b/src/backends/native/meta-kms-mode-private.h deleted file mode 100644 index ded03c52e..000000000 --- a/src/backends/native/meta-kms-mode-private.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2020 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_KMS_MODE_PRIVATE_H -#define META_KMS_MODE_PRIVATE_H - -#include "backends/native/meta-kms-mode.h" - -uint32_t meta_kms_mode_create_blob_id (MetaKmsMode *mode, - GError **error); - -void meta_kms_mode_free (MetaKmsMode *mode); - -MetaKmsMode * meta_kms_mode_new (MetaKmsImplDevice *impl_device, - const drmModeModeInfo *drm_mode, - MetaKmsModeFlag flags); - -#endif /* META_KMS_MODE_PRIVATE_H */ diff --git a/src/backends/native/meta-kms-mode.c b/src/backends/native/meta-kms-mode.c deleted file mode 100644 index 7094cd0da..000000000 --- a/src/backends/native/meta-kms-mode.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2020 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. - */ - -#include "config.h" - -#include "backends/native/meta-kms-mode-private.h" - -#include "backends/native/meta-kms-impl-device.h" - -struct _MetaKmsMode -{ - MetaKmsImplDevice *impl_device; - MetaKmsModeFlag flags; - drmModeModeInfo drm_mode; -}; - -uint32_t -meta_kms_mode_create_blob_id (MetaKmsMode *mode, - GError **error) -{ - int fd; - int ret; - uint32_t blob_id; - - fd = meta_kms_impl_device_get_fd (mode->impl_device); - - ret = drmModeCreatePropertyBlob (fd, - &mode->drm_mode, - sizeof (mode->drm_mode), - &blob_id); - if (ret < 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret), - "drmModeCreatePropertyBlob: %s", - g_strerror (-ret)); - return 0; - } - - return blob_id; -} - -const char * -meta_kms_mode_get_name (MetaKmsMode *mode) -{ - return mode->drm_mode.name; -} - -MetaKmsModeFlag -meta_kms_mode_get_flags (MetaKmsMode *mode) -{ - return mode->flags; -} - -const drmModeModeInfo * -meta_kms_mode_get_drm_mode (MetaKmsMode *mode) -{ - return &mode->drm_mode; -} - -static gboolean -meta_drm_mode_equal (const drmModeModeInfo *one, - const drmModeModeInfo *two) -{ - return (one->clock == two->clock && - one->hdisplay == two->hdisplay && - one->hsync_start == two->hsync_start && - one->hsync_end == two->hsync_end && - one->htotal == two->htotal && - one->hskew == two->hskew && - one->vdisplay == two->vdisplay && - one->vsync_start == two->vsync_start && - one->vsync_end == two->vsync_end && - one->vtotal == two->vtotal && - one->vscan == two->vscan && - one->vrefresh == two->vrefresh && - one->flags == two->flags && - one->type == two->type && - strncmp (one->name, two->name, DRM_DISPLAY_MODE_LEN) == 0); -} - -gboolean -meta_kms_mode_equal (MetaKmsMode *mode, - MetaKmsMode *other_mode) -{ - return meta_drm_mode_equal (&mode->drm_mode, &other_mode->drm_mode); -} - -unsigned int -meta_kms_mode_hash (MetaKmsMode *mode) -{ - const drmModeModeInfo *drm_mode = &mode->drm_mode; - unsigned int hash = 0; - - /* - * We don't include the name in the hash because it's generally - * derived from the other fields (hdisplay, vdisplay and flags) - */ - - hash ^= drm_mode->clock; - hash ^= drm_mode->hdisplay ^ drm_mode->hsync_start ^ drm_mode->hsync_end; - hash ^= drm_mode->vdisplay ^ drm_mode->vsync_start ^ drm_mode->vsync_end; - hash ^= drm_mode->vrefresh; - hash ^= drm_mode->flags ^ drm_mode->type; - - return hash; -} - -void -meta_kms_mode_free (MetaKmsMode *mode) -{ - g_free (mode); -} - -MetaKmsMode * -meta_kms_mode_new (MetaKmsImplDevice *impl_device, - const drmModeModeInfo *drm_mode, - MetaKmsModeFlag flags) -{ - MetaKmsMode *mode; - - mode = g_new0 (MetaKmsMode, 1); - mode->impl_device = impl_device; - mode->flags = flags; - mode->drm_mode = *drm_mode; - - return mode; -} diff --git a/src/backends/native/meta-kms-mode.h b/src/backends/native/meta-kms-mode.h deleted file mode 100644 index 40e844796..000000000 --- a/src/backends/native/meta-kms-mode.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2020 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_KMS_MODE_H -#define META_KMS_MODE_H - -#include -#include -#include - -#include "backends/native/meta-kms-types.h" - -typedef enum _MetaKmsModeFlag -{ - META_KMS_MODE_FLAG_NONE = 0, - META_KMS_MODE_FLAG_FALLBACK_LANDSCAPE = 1 << 0, - META_KMS_MODE_FLAG_FALLBACK_PORTRAIT = 1 << 1, -} MetaKmsModeFlag; - -const char * meta_kms_mode_get_name (MetaKmsMode *mode); - -MetaKmsModeFlag meta_kms_mode_get_flags (MetaKmsMode *mode); - -const drmModeModeInfo * meta_kms_mode_get_drm_mode (MetaKmsMode *mode); - -gboolean meta_kms_mode_equal (MetaKmsMode *mode, - MetaKmsMode *other_mode); - -unsigned int meta_kms_mode_hash (MetaKmsMode *mode); - -#endif /* META_KMS_MODE_H */ diff --git a/src/backends/native/meta-kms-page-flip-private.h b/src/backends/native/meta-kms-page-flip-private.h deleted file mode 100644 index b23272ad9..000000000 --- a/src/backends/native/meta-kms-page-flip-private.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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_KMS_PAGE_FLIP_H -#define META_KMS_PAGE_FLIP_H - -#include - -#include "backends/native/meta-kms-types.h" - -typedef struct _MetaKmsPageFlipData MetaKmsPageFlipData; - -typedef void (* MetaPageFlipDataFeedbackFunc) (MetaKmsPageFlipData *page_flip_data); - -MetaKmsPageFlipData * meta_kms_page_flip_data_new (MetaKmsImplDevice *impl_device, - MetaKmsCrtc *crtc); - -MetaKmsPageFlipData * meta_kms_page_flip_data_ref (MetaKmsPageFlipData *page_flip_data); - -void meta_kms_page_flip_data_unref (MetaKmsPageFlipData *page_flip_data); - -void meta_kms_page_flip_data_add_listener (MetaKmsPageFlipData *page_flip_data, - const MetaKmsPageFlipListenerVtable *vtable, - MetaKmsPageFlipListenerFlag flags, - gpointer user_data, - GDestroyNotify destroy_notify); - -MetaKmsImplDevice * meta_kms_page_flip_data_get_impl_device (MetaKmsPageFlipData *page_flip_data); - -MetaKmsCrtc * meta_kms_page_flip_data_get_crtc (MetaKmsPageFlipData *page_flip_data); - -void meta_kms_page_flip_data_set_timings_in_impl (MetaKmsPageFlipData *page_flip_data, - unsigned int sequence, - unsigned int sec, - unsigned int usec); - -void meta_kms_page_flip_data_flipped_in_impl (MetaKmsPageFlipData *page_flip_data); - -void meta_kms_page_flip_data_mode_set_fallback_in_impl (MetaKmsPageFlipData *page_flip_data); - -void meta_kms_page_flip_data_discard_in_impl (MetaKmsPageFlipData *page_flip_data, - const GError *error); - -void meta_kms_page_flip_data_take_error (MetaKmsPageFlipData *page_flip_data, - GError *error); - -void meta_kms_page_flip_data_make_symbolic (MetaKmsPageFlipData *page_flip_data); - -#endif /* META_KMS_PAGE_FLIP_H */ diff --git a/src/backends/native/meta-kms-page-flip.c b/src/backends/native/meta-kms-page-flip.c deleted file mode 100644 index 817f4e7c8..000000000 --- a/src/backends/native/meta-kms-page-flip.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * 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. - */ - -#include "config.h" - -#include "backends/native/meta-kms-page-flip-private.h" - -#include "backends/native/meta-kms-impl.h" -#include "backends/native/meta-kms-private.h" -#include "backends/native/meta-kms-update.h" - -typedef struct _MetaKmsPageFlipClosure -{ - const MetaKmsPageFlipListenerVtable *vtable; - MetaKmsPageFlipListenerFlag flags; - gpointer user_data; - GDestroyNotify destroy_notify; -} MetaKmsPageFlipClosure; - -struct _MetaKmsPageFlipData -{ - gatomicrefcount ref_count; - - MetaKmsImplDevice *impl_device; - MetaKmsCrtc *crtc; - - GList *closures; - - unsigned int sequence; - unsigned int sec; - unsigned int usec; - - gboolean is_symbolic; - - GError *error; -}; - -static MetaKmsPageFlipClosure * -meta_kms_page_flip_closure_new (const MetaKmsPageFlipListenerVtable *vtable, - MetaKmsPageFlipListenerFlag flags, - gpointer user_data, - GDestroyNotify destroy_notify) -{ - MetaKmsPageFlipClosure *closure; - - closure = g_new0 (MetaKmsPageFlipClosure, 1); - *closure = (MetaKmsPageFlipClosure) { - .vtable = vtable, - .flags = flags, - .user_data = user_data, - .destroy_notify = destroy_notify, - }; - - return closure; -} - -static void -meta_kms_page_flip_closure_free (MetaKmsPageFlipClosure *closure) -{ - g_clear_pointer (&closure->user_data, closure->destroy_notify); - g_free (closure); -} - -MetaKmsPageFlipData * -meta_kms_page_flip_data_new (MetaKmsImplDevice *impl_device, - MetaKmsCrtc *crtc) -{ - MetaKmsPageFlipData *page_flip_data; - - page_flip_data = g_new0 (MetaKmsPageFlipData , 1); - *page_flip_data = (MetaKmsPageFlipData) { - .impl_device = impl_device, - .crtc = crtc, - }; - g_atomic_ref_count_init (&page_flip_data->ref_count); - - return page_flip_data; -} - -MetaKmsPageFlipData * -meta_kms_page_flip_data_ref (MetaKmsPageFlipData *page_flip_data) -{ - g_atomic_ref_count_inc (&page_flip_data->ref_count); - - return page_flip_data; -} - -void -meta_kms_page_flip_data_unref (MetaKmsPageFlipData *page_flip_data) -{ - if (g_atomic_ref_count_dec (&page_flip_data->ref_count)) - { - g_list_free_full (page_flip_data->closures, - (GDestroyNotify) meta_kms_page_flip_closure_free); - g_clear_error (&page_flip_data->error); - g_free (page_flip_data); - } -} - -void -meta_kms_page_flip_data_add_listener (MetaKmsPageFlipData *page_flip_data, - const MetaKmsPageFlipListenerVtable *vtable, - MetaKmsPageFlipListenerFlag flags, - gpointer user_data, - GDestroyNotify destroy_notify) -{ - MetaKmsPageFlipClosure *closure; - - closure = meta_kms_page_flip_closure_new (vtable, flags, - user_data, - destroy_notify); - page_flip_data->closures = g_list_append (page_flip_data->closures, closure); -} - -MetaKmsImplDevice * -meta_kms_page_flip_data_get_impl_device (MetaKmsPageFlipData *page_flip_data) -{ - return page_flip_data->impl_device; -} - -MetaKmsCrtc * -meta_kms_page_flip_data_get_crtc (MetaKmsPageFlipData *page_flip_data) -{ - return page_flip_data->crtc; -} - -static void -meta_kms_page_flip_data_flipped (MetaKms *kms, - gpointer user_data) -{ - MetaKmsPageFlipData *page_flip_data = user_data; - GList *l; - - meta_assert_not_in_kms_impl (kms); - - for (l = page_flip_data->closures; l; l = l->next) - { - MetaKmsPageFlipClosure *closure = l->data; - - if (page_flip_data->is_symbolic) - { - closure->vtable->ready (page_flip_data->crtc, - closure->user_data); - } - else - { - closure->vtable->flipped (page_flip_data->crtc, - page_flip_data->sequence, - page_flip_data->sec, - page_flip_data->usec, - closure->user_data); - } - } -} - -static MetaKms * -meta_kms_from_impl_device (MetaKmsImplDevice *impl_device) -{ - MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device); - - return meta_kms_device_get_kms (device); -} - -void -meta_kms_page_flip_data_set_timings_in_impl (MetaKmsPageFlipData *page_flip_data, - unsigned int sequence, - unsigned int sec, - unsigned int usec) -{ - MetaKms *kms = meta_kms_from_impl_device (page_flip_data->impl_device); - - meta_assert_in_kms_impl (kms); - - page_flip_data->sequence = sequence; - page_flip_data->sec = sec; - page_flip_data->usec = usec; -} - -void -meta_kms_page_flip_data_make_symbolic (MetaKmsPageFlipData *page_flip_data) -{ - page_flip_data->is_symbolic = TRUE; -} - -void -meta_kms_page_flip_data_flipped_in_impl (MetaKmsPageFlipData *page_flip_data) -{ - MetaKms *kms = meta_kms_from_impl_device (page_flip_data->impl_device); - - meta_assert_in_kms_impl (kms); - - meta_kms_queue_callback (kms, - meta_kms_page_flip_data_flipped, - page_flip_data, - (GDestroyNotify) meta_kms_page_flip_data_unref); -} - -static void -meta_kms_page_flip_data_mode_set_fallback (MetaKms *kms, - gpointer user_data) -{ - MetaKmsPageFlipData *page_flip_data = user_data; - GList *l; - - meta_assert_not_in_kms_impl (kms); - - for (l = page_flip_data->closures; l; l = l->next) - { - MetaKmsPageFlipClosure *closure = l->data; - - closure->vtable->mode_set_fallback (page_flip_data->crtc, - closure->user_data); - } -} - -void -meta_kms_page_flip_data_mode_set_fallback_in_impl (MetaKmsPageFlipData *page_flip_data) -{ - MetaKms *kms = meta_kms_from_impl_device (page_flip_data->impl_device); - - meta_assert_in_kms_impl (kms); - - meta_kms_queue_callback (kms, - meta_kms_page_flip_data_mode_set_fallback, - page_flip_data, - (GDestroyNotify) meta_kms_page_flip_data_unref); -} - -static void -meta_kms_page_flip_data_discard (MetaKms *kms, - gpointer user_data) -{ - MetaKmsPageFlipData *page_flip_data = user_data; - GList *l; - - meta_assert_not_in_kms_impl (kms); - - for (l = page_flip_data->closures; l; l = l->next) - { - MetaKmsPageFlipClosure *closure = l->data; - - closure->vtable->discarded (page_flip_data->crtc, - closure->user_data, - page_flip_data->error); - } -} - -void -meta_kms_page_flip_data_take_error (MetaKmsPageFlipData *page_flip_data, - GError *error) -{ - g_assert (!page_flip_data->error); - - page_flip_data->error = error; -} - -void -meta_kms_page_flip_data_discard_in_impl (MetaKmsPageFlipData *page_flip_data, - const GError *error) -{ - MetaKms *kms = meta_kms_from_impl_device (page_flip_data->impl_device); - - meta_assert_in_kms_impl (kms); - - if (error) - meta_kms_page_flip_data_take_error (page_flip_data, g_error_copy (error)); - - meta_kms_queue_callback (kms, - meta_kms_page_flip_data_discard, - page_flip_data, - (GDestroyNotify) meta_kms_page_flip_data_unref); -} diff --git a/src/backends/native/meta-kms-plane-private.h b/src/backends/native/meta-kms-plane-private.h deleted file mode 100644 index 92f9cfcc9..000000000 --- a/src/backends/native/meta-kms-plane-private.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2018-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_KMS_PLANE_PRIVATE_H -#define META_KMS_PLANE_PRIVATE_H - -#include -#include - -#include "backends/native/meta-kms-plane.h" -#include "backends/native/meta-kms-types.h" - -typedef enum _MetaKmsPlaneProp -{ - META_KMS_PLANE_PROP_TYPE = 0, - META_KMS_PLANE_PROP_ROTATION, - META_KMS_PLANE_PROP_IN_FORMATS, - META_KMS_PLANE_PROP_SRC_X, - META_KMS_PLANE_PROP_SRC_Y, - META_KMS_PLANE_PROP_SRC_W, - META_KMS_PLANE_PROP_SRC_H, - META_KMS_PLANE_PROP_CRTC_X, - META_KMS_PLANE_PROP_CRTC_Y, - META_KMS_PLANE_PROP_CRTC_W, - META_KMS_PLANE_PROP_CRTC_H, - META_KMS_PLANE_PROP_FB_ID, - META_KMS_PLANE_PROP_CRTC_ID, - META_KMS_PLANE_N_PROPS -} MetaKmsPlaneProp; - -MetaKmsPlane * meta_kms_plane_new (MetaKmsPlaneType type, - MetaKmsImplDevice *impl_device, - drmModePlane *drm_plane, - drmModeObjectProperties *drm_plane_props); - -MetaKmsPlane * meta_kms_plane_new_fake (MetaKmsPlaneType type, - MetaKmsCrtc *crtc); - -uint32_t meta_kms_plane_get_prop_id (MetaKmsPlane *plane, - MetaKmsPlaneProp prop); - -const char * meta_kms_plane_get_prop_name (MetaKmsPlane *plane, - MetaKmsPlaneProp prop); - -MetaKmsPropType meta_kms_plane_get_prop_internal_type (MetaKmsPlane *plane, - MetaKmsPlaneProp prop); - -#endif /* META_KMS_PLANE_PRIVATE_H */ diff --git a/src/backends/native/meta-kms-plane.c b/src/backends/native/meta-kms-plane.c deleted file mode 100644 index 73fab7d8f..000000000 --- a/src/backends/native/meta-kms-plane.c +++ /dev/null @@ -1,537 +0,0 @@ -/* - * Copyright (C) 2013-2019 Red Hat - * Copyright (C) 2018 DisplayLink (UK) Ltd. - * - * 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 "backends/native/meta-kms-plane-private.h" - -#include -#include - -#include "backends/meta-monitor-transform.h" -#include "backends/native/meta-kms-crtc.h" -#include "backends/native/meta-kms-impl-device.h" -#include "backends/native/meta-kms-update-private.h" - -typedef struct _MetaKmsPlanePropTable -{ - MetaKmsProp props[META_KMS_PLANE_N_PROPS]; -} MetaKmsPlanePropTable; - -struct _MetaKmsPlane -{ - GObject parent; - - MetaKmsPlaneType type; - gboolean is_fake; - - uint32_t id; - - uint32_t possible_crtcs; - - uint32_t rotation_map[META_MONITOR_N_TRANSFORMS]; - uint32_t all_hw_transforms; - - /* - * primary plane's supported formats and maybe modifiers - * key: GUINT_TO_POINTER (format) - * value: owned GArray* (uint64_t modifier), or NULL - */ - GHashTable *formats_modifiers; - - MetaKmsPlanePropTable prop_table; - - MetaKmsDevice *device; -}; - -G_DEFINE_TYPE (MetaKmsPlane, meta_kms_plane, G_TYPE_OBJECT) - -MetaKmsDevice * -meta_kms_plane_get_device (MetaKmsPlane *plane) -{ - return plane->device; -} - -uint32_t -meta_kms_plane_get_id (MetaKmsPlane *plane) -{ - g_return_val_if_fail (!plane->is_fake, 0); - - return plane->id; -} - -MetaKmsPlaneType -meta_kms_plane_get_plane_type (MetaKmsPlane *plane) -{ - return plane->type; -} - -uint32_t -meta_kms_plane_get_prop_id (MetaKmsPlane *plane, - MetaKmsPlaneProp prop) -{ - return plane->prop_table.props[prop].prop_id; -} - -const char * -meta_kms_plane_get_prop_name (MetaKmsPlane *plane, - MetaKmsPlaneProp prop) -{ - return plane->prop_table.props[prop].name; -} - -MetaKmsPropType -meta_kms_plane_get_prop_internal_type (MetaKmsPlane *plane, - MetaKmsPlaneProp prop) -{ - return plane->prop_table.props[prop].internal_type; -} - -void -meta_kms_plane_update_set_rotation (MetaKmsPlane *plane, - MetaKmsPlaneAssignment *plane_assignment, - MetaMonitorTransform transform) -{ - g_return_if_fail (meta_kms_plane_is_transform_handled (plane, transform)); - - meta_kms_plane_assignment_set_rotation (plane_assignment, - plane->rotation_map[transform]); -} - -gboolean -meta_kms_plane_is_transform_handled (MetaKmsPlane *plane, - MetaMonitorTransform transform) -{ - switch (transform) - { - case META_MONITOR_TRANSFORM_NORMAL: - case META_MONITOR_TRANSFORM_180: - case META_MONITOR_TRANSFORM_FLIPPED: - case META_MONITOR_TRANSFORM_FLIPPED_180: - break; - case META_MONITOR_TRANSFORM_90: - case META_MONITOR_TRANSFORM_270: - case META_MONITOR_TRANSFORM_FLIPPED_90: - case META_MONITOR_TRANSFORM_FLIPPED_270: - /* - * Blacklist these transforms as testing shows that they don't work - * anyway, e.g. due to the wrong buffer modifiers. They might as well be - * less optimal due to the complexity dealing with rotation at scan-out, - * potentially resulting in higher power consumption. - */ - return FALSE; - } - return plane->all_hw_transforms & (1 << transform); -} - -GArray * -meta_kms_plane_get_modifiers_for_format (MetaKmsPlane *plane, - uint32_t format) -{ - return g_hash_table_lookup (plane->formats_modifiers, - GUINT_TO_POINTER (format)); -} - -GArray * -meta_kms_plane_copy_drm_format_list (MetaKmsPlane *plane) -{ - GArray *formats; - GHashTableIter it; - gpointer key; - unsigned int n_formats_modifiers; - - n_formats_modifiers = g_hash_table_size (plane->formats_modifiers); - formats = g_array_sized_new (FALSE, FALSE, - sizeof (uint32_t), - n_formats_modifiers); - g_hash_table_iter_init (&it, plane->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; -} - -gboolean -meta_kms_plane_is_format_supported (MetaKmsPlane *plane, - uint32_t drm_format) -{ - return g_hash_table_lookup_extended (plane->formats_modifiers, - GUINT_TO_POINTER (drm_format), - NULL, NULL); -} - -gboolean -meta_kms_plane_is_usable_with (MetaKmsPlane *plane, - MetaKmsCrtc *crtc) -{ - return !!(plane->possible_crtcs & (1 << meta_kms_crtc_get_idx (crtc))); -} - -static void -parse_rotations (MetaKmsImplDevice *impl_device, - MetaKmsProp *prop, - drmModePropertyPtr drm_prop, - uint64_t drm_prop_value, - gpointer user_data) -{ - MetaKmsPlane *plane = user_data; - int i; - - for (i = 0; i < drm_prop->count_enums; i++) - { - MetaMonitorTransform transform = -1; - - if (strcmp (drm_prop->enums[i].name, "rotate-0") == 0) - transform = META_MONITOR_TRANSFORM_NORMAL; - else if (strcmp (drm_prop->enums[i].name, "rotate-90") == 0) - transform = META_MONITOR_TRANSFORM_90; - else if (strcmp (drm_prop->enums[i].name, "rotate-180") == 0) - transform = META_MONITOR_TRANSFORM_180; - else if (strcmp (drm_prop->enums[i].name, "rotate-270") == 0) - transform = META_MONITOR_TRANSFORM_270; - - if (transform != -1) - { - plane->all_hw_transforms |= 1 << transform; - plane->rotation_map[transform] = 1 << drm_prop->enums[i].value; - } - } -} - -static inline uint32_t * -drm_formats_ptr (struct drm_format_modifier_blob *blob) -{ - return (uint32_t *) (((char *) blob) + blob->formats_offset); -} - -static inline struct drm_format_modifier * -drm_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); -} - -static void -parse_formats (MetaKmsImplDevice *impl_device, - MetaKmsProp *prop, - drmModePropertyPtr drm_prop, - uint64_t drm_prop_value, - gpointer user_data) -{ - MetaKmsPlane *plane = user_data; - uint64_t blob_id; - int fd; - drmModePropertyBlobPtr blob; - struct drm_format_modifier_blob *blob_fmt; - uint32_t *formats; - struct drm_format_modifier *drm_modifiers; - unsigned int fmt_i, mod_i; - - g_return_if_fail (g_hash_table_size (plane->formats_modifiers) == 0); - - blob_id = drm_prop_value; - if (blob_id == 0) - return; - - fd = meta_kms_impl_device_get_fd (impl_device); - blob = drmModeGetPropertyBlob (fd, blob_id); - if (!blob) - return; - - if (blob->length < sizeof (struct drm_format_modifier_blob)) - { - drmModeFreePropertyBlob (blob); - return; - } - - blob_fmt = blob->data; - - formats = drm_formats_ptr (blob_fmt); - drm_modifiers = drm_modifiers_ptr (blob_fmt); - - for (fmt_i = 0; fmt_i < blob_fmt->count_formats; fmt_i++) - { - GArray *modifiers = g_array_new (FALSE, FALSE, sizeof (uint64_t)); - - for (mod_i = 0; mod_i < blob_fmt->count_modifiers; mod_i++) - { - struct drm_format_modifier *drm_modifier = &drm_modifiers[mod_i]; - - /* - * The modifier advertisement blob is partitioned into groups of - * 64 formats. - */ - if (fmt_i < drm_modifier->offset || fmt_i > drm_modifier->offset + 63) - continue; - - if (!(drm_modifier->formats & (1 << (fmt_i - drm_modifier->offset)))) - continue; - - g_array_append_val (modifiers, drm_modifier->modifier); - } - - if (modifiers->len == 0) - { - free_modifier_array (modifiers); - modifiers = NULL; - } - - g_hash_table_insert (plane->formats_modifiers, - GUINT_TO_POINTER (formats[fmt_i]), - modifiers); - } - - drmModeFreePropertyBlob (blob); -} - -static void -set_formats_from_array (MetaKmsPlane *plane, - const uint32_t *formats, - size_t n_formats) -{ - size_t i; - - for (i = 0; i < n_formats; i++) - { - g_hash_table_insert (plane->formats_modifiers, - GUINT_TO_POINTER (formats[i]), NULL); - } -} - -/* - * 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[] = - { - /* The format everything should always support by convention */ - DRM_FORMAT_XRGB8888, -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - /* OpenGL GL_RGBA, GL_UNSIGNED_BYTE format, hopefully supported */ - DRM_FORMAT_XBGR8888 -#endif - }; - -static void -init_legacy_formats (MetaKmsPlane *plane, - MetaKmsImplDevice *impl_device, - drmModePlane *drm_plane, - drmModeObjectProperties *drm_plane_props) -{ - if (g_hash_table_size (plane->formats_modifiers) == 0) - { - set_formats_from_array (plane, - drm_plane->formats, - drm_plane->count_formats); - } - - /* final formats fallback to something hardcoded */ - if (g_hash_table_size (plane->formats_modifiers) == 0) - { - set_formats_from_array (plane, - drm_default_formats, - G_N_ELEMENTS (drm_default_formats)); - } -} - -static void -init_properties (MetaKmsPlane *plane, - MetaKmsImplDevice *impl_device, - drmModePlane *drm_plane, - drmModeObjectProperties *drm_plane_props) -{ - MetaKmsPlanePropTable *prop_table = &plane->prop_table; - - *prop_table = (MetaKmsPlanePropTable) { - .props = { - [META_KMS_PLANE_PROP_TYPE] = - { - .name = "type", - .type = DRM_MODE_PROP_ENUM, - }, - [META_KMS_PLANE_PROP_ROTATION] = - { - .name = "rotation", - .type = DRM_MODE_PROP_BITMASK, - .parse = parse_rotations, - }, - [META_KMS_PLANE_PROP_IN_FORMATS] = - { - .name = "IN_FORMATS", - .type = DRM_MODE_PROP_BLOB, - .parse = parse_formats, - }, - [META_KMS_PLANE_PROP_SRC_X] = - { - .name = "SRC_X", - .type = DRM_MODE_PROP_RANGE, - .internal_type = META_KMS_PROP_TYPE_FIXED_16, - }, - [META_KMS_PLANE_PROP_SRC_Y] = - { - .name = "SRC_Y", - .type = DRM_MODE_PROP_RANGE, - .internal_type = META_KMS_PROP_TYPE_FIXED_16, - }, - [META_KMS_PLANE_PROP_SRC_W] = - { - .name = "SRC_W", - .type = DRM_MODE_PROP_RANGE, - .internal_type = META_KMS_PROP_TYPE_FIXED_16, - }, - [META_KMS_PLANE_PROP_SRC_H] = - { - .name = "SRC_H", - .type = DRM_MODE_PROP_RANGE, - .internal_type = META_KMS_PROP_TYPE_FIXED_16, - }, - [META_KMS_PLANE_PROP_CRTC_X] = - { - .name = "CRTC_X", - .type = DRM_MODE_PROP_SIGNED_RANGE, - }, - [META_KMS_PLANE_PROP_CRTC_Y] = - { - .name = "CRTC_Y", - .type = DRM_MODE_PROP_SIGNED_RANGE, - }, - [META_KMS_PLANE_PROP_CRTC_W] = - { - .name = "CRTC_W", - .type = DRM_MODE_PROP_RANGE, - }, - [META_KMS_PLANE_PROP_CRTC_H] = - { - .name = "CRTC_H", - .type = DRM_MODE_PROP_RANGE, - }, - [META_KMS_PLANE_PROP_FB_ID] = - { - .name = "FB_ID", - .type = DRM_MODE_PROP_OBJECT, - }, - [META_KMS_PLANE_PROP_CRTC_ID] = - { - .name = "CRTC_ID", - .type = DRM_MODE_PROP_OBJECT, - }, - } - }; - - meta_kms_impl_device_init_prop_table (impl_device, - drm_plane_props->props, - drm_plane_props->prop_values, - drm_plane_props->count_props, - plane->prop_table.props, - META_KMS_PLANE_N_PROPS, - plane); -} - -MetaKmsPlane * -meta_kms_plane_new (MetaKmsPlaneType type, - MetaKmsImplDevice *impl_device, - drmModePlane *drm_plane, - drmModeObjectProperties *drm_plane_props) -{ - MetaKmsPlane *plane; - - plane = g_object_new (META_TYPE_KMS_PLANE, NULL); - plane->type = type; - plane->id = drm_plane->plane_id; - plane->possible_crtcs = drm_plane->possible_crtcs; - plane->device = meta_kms_impl_device_get_device (impl_device); - - init_properties (plane, impl_device, drm_plane, drm_plane_props); - init_legacy_formats (plane, impl_device, drm_plane, drm_plane_props); - - return plane; -} - -MetaKmsPlane * -meta_kms_plane_new_fake (MetaKmsPlaneType type, - MetaKmsCrtc *crtc) -{ - MetaKmsPlane *plane; - - static const uint32_t fake_plane_drm_formats[] = - { - DRM_FORMAT_XRGB8888, - DRM_FORMAT_ARGB8888, -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - /* OpenGL GL_RGBA, GL_UNSIGNED_BYTE format, hopefully supported */ - DRM_FORMAT_XBGR8888, - DRM_FORMAT_ABGR8888 -#endif - }; - - plane = g_object_new (META_TYPE_KMS_PLANE, NULL); - plane->type = type; - plane->is_fake = TRUE; - plane->possible_crtcs = 1 << meta_kms_crtc_get_idx (crtc); - plane->device = meta_kms_crtc_get_device (crtc); - - set_formats_from_array (plane, - fake_plane_drm_formats, - G_N_ELEMENTS (fake_plane_drm_formats)); - - return plane; -} - -static void -meta_kms_plane_finalize (GObject *object) -{ - MetaKmsPlane *plane = META_KMS_PLANE (object); - - g_hash_table_destroy (plane->formats_modifiers); - - G_OBJECT_CLASS (meta_kms_plane_parent_class)->finalize (object); -} - -static void -meta_kms_plane_init (MetaKmsPlane *plane) -{ - plane->formats_modifiers = - g_hash_table_new_full (g_direct_hash, - g_direct_equal, - NULL, - (GDestroyNotify) free_modifier_array); -} - -static void -meta_kms_plane_class_init (MetaKmsPlaneClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_kms_plane_finalize; -} diff --git a/src/backends/native/meta-kms-plane.h b/src/backends/native/meta-kms-plane.h deleted file mode 100644 index 941c16680..000000000 --- a/src/backends/native/meta-kms-plane.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2018 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_KMS_PLANE_H -#define META_KMS_PLANE_H - -#include -#include -#include - -#include "backends/native/meta-kms-types.h" -#include "backends/meta-monitor-transform.h" - -enum _MetaKmsPlaneType -{ - META_KMS_PLANE_TYPE_PRIMARY, - META_KMS_PLANE_TYPE_CURSOR, - META_KMS_PLANE_TYPE_OVERLAY, -}; - -#define META_TYPE_KMS_PLANE meta_kms_plane_get_type () -G_DECLARE_FINAL_TYPE (MetaKmsPlane, meta_kms_plane, - META, KMS_PLANE, GObject) - -MetaKmsDevice * meta_kms_plane_get_device (MetaKmsPlane *plane); - -uint32_t meta_kms_plane_get_id (MetaKmsPlane *plane); - -MetaKmsPlaneType meta_kms_plane_get_plane_type (MetaKmsPlane *plane); - -gboolean meta_kms_plane_is_transform_handled (MetaKmsPlane *plane, - MetaMonitorTransform transform); - -GArray * meta_kms_plane_get_modifiers_for_format (MetaKmsPlane *plane, - uint32_t format); - -GArray * meta_kms_plane_copy_drm_format_list (MetaKmsPlane *plane); - -gboolean meta_kms_plane_is_format_supported (MetaKmsPlane *plane, - uint32_t format); - -gboolean meta_kms_plane_is_usable_with (MetaKmsPlane *plane, - MetaKmsCrtc *crtc); - -void meta_kms_plane_update_set_rotation (MetaKmsPlane *plane, - MetaKmsPlaneAssignment *plane_assignment, - MetaMonitorTransform transform); - -#endif /* META_KMS_PLANE_H */ diff --git a/src/backends/native/meta-kms-private.h b/src/backends/native/meta-kms-private.h deleted file mode 100644 index 8d0954c72..000000000 --- a/src/backends/native/meta-kms-private.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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_KMS_PRIVATE_H -#define META_KMS_PRIVATE_H - -#include "backends/native/meta-kms.h" - -#include "backends/native/meta-kms-types.h" - -typedef void (* MetaKmsCallback) (MetaKms *kms, - gpointer user_data); - -typedef gpointer (* MetaKmsImplTaskFunc) (MetaKmsImpl *impl, - gpointer user_data, - GError **error); - -void meta_kms_queue_callback (MetaKms *kms, - MetaKmsCallback callback, - gpointer user_data, - GDestroyNotify user_data_destroy); - -gpointer meta_kms_run_impl_task_sync (MetaKms *kms, - MetaKmsImplTaskFunc func, - gpointer user_data, - GError **error); - -GSource * meta_kms_add_source_in_impl (MetaKms *kms, - GSourceFunc func, - gpointer user_data, - GDestroyNotify user_data_destroy); - -GSource * meta_kms_register_fd_in_impl (MetaKms *kms, - int fd, - MetaKmsImplTaskFunc dispatch, - gpointer user_data); - -gboolean meta_kms_in_impl_task (MetaKms *kms); - -gboolean meta_kms_is_waiting_for_impl_task (MetaKms *kms); - -#define meta_assert_in_kms_impl(kms) \ - g_assert (meta_kms_in_impl_task (kms)) -#define meta_assert_not_in_kms_impl(kms) \ - g_assert (!meta_kms_in_impl_task (kms)) -#define meta_assert_is_waiting_for_kms_impl_task(kms) \ - g_assert (meta_kms_is_waiting_for_impl_task (kms)) - -#endif /* META_KMS_PRIVATE_H */ diff --git a/src/backends/native/meta-kms-types.h b/src/backends/native/meta-kms-types.h deleted file mode 100644 index 5786ff51f..000000000 --- a/src/backends/native/meta-kms-types.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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_KMS_IMPL_TYPES_H -#define META_KMS_IMPL_TYPES_H - -#include - -typedef struct _MetaKms MetaKms; -typedef struct _MetaKmsDevice MetaKmsDevice; - -typedef struct _MetaKmsPlane MetaKmsPlane; -typedef struct _MetaKmsCrtc MetaKmsCrtc; -typedef struct _MetaKmsConnector MetaKmsConnector; - -typedef struct _MetaKmsUpdate MetaKmsUpdate; -typedef struct _MetaKmsPlaneAssignment MetaKmsPlaneAssignment; -typedef struct _MetaKmsModeSet MetaKmsModeSet; - -typedef struct _MetaKmsMode MetaKmsMode; - -typedef struct _MetaKmsFeedback MetaKmsFeedback; - -typedef struct _MetaKmsPageFlipListenerVtable MetaKmsPageFlipListenerVtable; -typedef enum _MetaKmsPageFlipListenerFlag MetaKmsPageFlipListenerFlag; - -typedef struct _MetaKmsImpl MetaKmsImpl; -typedef struct _MetaKmsImplDevice MetaKmsImplDevice; - -/* 16:16 fixed point */ -typedef int32_t MetaFixed16; - -typedef struct _MetaFixed16Rectangle -{ - MetaFixed16 x; - MetaFixed16 y; - MetaFixed16 width; - MetaFixed16 height; -} MetaFixed16Rectangle; - -typedef enum _MetaKmsDeviceFlag -{ - META_KMS_DEVICE_FLAG_NONE = 0, - META_KMS_DEVICE_FLAG_BOOT_VGA = 1 << 0, - META_KMS_DEVICE_FLAG_PLATFORM_DEVICE = 1 << 1, - META_KMS_DEVICE_FLAG_DISABLE_MODIFIERS = 1 << 2, - META_KMS_DEVICE_FLAG_PREFERRED_PRIMARY = 1 << 3, - META_KMS_DEVICE_FLAG_NO_MODE_SETTING = 1 << 4, -} MetaKmsDeviceFlag; - -typedef enum _MetaKmsPlaneType MetaKmsPlaneType; - -typedef enum _MetaKmsPropType -{ - META_KMS_PROP_TYPE_RAW = 0, - META_KMS_PROP_TYPE_FIXED_16, -} MetaKmsPropType; - -#endif /* META_KMS_IMPL_TYPES_H */ diff --git a/src/backends/native/meta-kms-update-private.h b/src/backends/native/meta-kms-update-private.h deleted file mode 100644 index 22491ece2..000000000 --- a/src/backends/native/meta-kms-update-private.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * 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_KMS_UPDATE_PRIVATE_H -#define META_KMS_UPDATE_PRIVATE_H - -#include -#include - -#include "backends/native/meta-kms-types.h" -#include "backends/native/meta-kms-update.h" - -typedef struct _MetaKmsFeedback -{ - MetaKmsFeedbackResult result; - - GList *failed_planes; - GError *error; -} MetaKmsFeedback; - -typedef struct _MetaKmsPlaneAssignment -{ - MetaKmsUpdate *update; - MetaKmsCrtc *crtc; - MetaKmsPlane *plane; - MetaDrmBuffer *buffer; - MetaFixed16Rectangle src_rect; - MetaRectangle dst_rect; - MetaKmsAssignPlaneFlag flags; - - uint64_t rotation; - - struct { - gboolean is_valid; - int x; - int y; - } cursor_hotspot; -} MetaKmsPlaneAssignment; - -typedef struct _MetaKmsModeSet -{ - MetaKmsCrtc *crtc; - GList *connectors; - MetaKmsMode *mode; -} MetaKmsModeSet; - -typedef struct _MetaKmsConnectorUpdate -{ - MetaKmsConnector *connector; - - struct { - gboolean has_update; - gboolean is_active; - uint64_t hborder; - uint64_t vborder; - } underscanning; -} MetaKmsConnectorUpdate; - -typedef struct _MetaKmsPageFlipListener -{ - MetaKmsCrtc *crtc; - const MetaKmsPageFlipListenerVtable *vtable; - MetaKmsPageFlipListenerFlag flags; - gpointer user_data; - GDestroyNotify destroy_notify; -} MetaKmsPageFlipListener; - -typedef struct _MetaKmsResultListener -{ - MetaKmsResultListenerFunc func; - gpointer user_data; -} MetaKmsResultListener; - -typedef struct _MetaKmsCustomPageFlip -{ - MetaKmsCustomPageFlipFunc func; - gpointer user_data; -} MetaKmsCustomPageFlip; - -void meta_kms_plane_feedback_free (MetaKmsPlaneFeedback *plane_feedback); - -MetaKmsPlaneFeedback * meta_kms_plane_feedback_new_take_error (MetaKmsPlane *plane, - MetaKmsCrtc *crtc, - GError *error); - -MetaKmsFeedback * meta_kms_feedback_new_passed (GList *failed_planes); - -MetaKmsFeedback * meta_kms_feedback_new_failed (GList *failed_planes, - GError *error); - -void meta_kms_update_lock (MetaKmsUpdate *update); - -void meta_kms_update_unlock (MetaKmsUpdate *update); - -gboolean meta_kms_update_is_locked (MetaKmsUpdate *update); - -uint64_t meta_kms_update_get_sequence_number (MetaKmsUpdate *update); - -MetaKmsDevice * meta_kms_update_get_device (MetaKmsUpdate *update); - -void meta_kms_plane_assignment_set_rotation (MetaKmsPlaneAssignment *plane_assignment, - uint64_t rotation); - -MetaKmsPlaneAssignment * meta_kms_update_get_primary_plane_assignment (MetaKmsUpdate *update, - MetaKmsCrtc *crtc); - -GList * meta_kms_update_get_plane_assignments (MetaKmsUpdate *update); - -GList * meta_kms_update_get_mode_sets (MetaKmsUpdate *update); - -GList * meta_kms_update_get_page_flip_listeners (MetaKmsUpdate *update); - -void meta_kms_update_drop_defunct_page_flip_listeners (MetaKmsUpdate *update); - -GList * meta_kms_update_get_connector_updates (MetaKmsUpdate *update); - -GList * meta_kms_update_get_crtc_gammas (MetaKmsUpdate *update); - -gboolean meta_kms_update_is_power_save (MetaKmsUpdate *update); - -MetaKmsCustomPageFlip * meta_kms_update_take_custom_page_flip_func (MetaKmsUpdate *update); - -void meta_kms_update_drop_plane_assignment (MetaKmsUpdate *update, - MetaKmsPlane *plane); - -GList * meta_kms_update_take_result_listeners (MetaKmsUpdate *update); - -void meta_kms_result_listener_notify (MetaKmsResultListener *listener, - const MetaKmsFeedback *feedback); - -void meta_kms_result_listener_free (MetaKmsResultListener *listener); - -void meta_kms_custom_page_flip_free (MetaKmsCustomPageFlip *custom_page_flip); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaKmsPlaneFeedback, - meta_kms_plane_feedback_free) - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaKmsCustomPageFlip, - meta_kms_custom_page_flip_free) - -#endif /* META_KMS_UPDATE_PRIVATE_H */ diff --git a/src/backends/native/meta-kms-update.c b/src/backends/native/meta-kms-update.c deleted file mode 100644 index be6eaefcc..000000000 --- a/src/backends/native/meta-kms-update.c +++ /dev/null @@ -1,645 +0,0 @@ -/* - * Copyright (C) 2018 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. - */ - -#include "config.h" - -#include "backends/native/meta-kms-update.h" -#include "backends/native/meta-kms-update-private.h" - -#include "backends/meta-display-config-shared.h" -#include "backends/native/meta-kms-connector.h" -#include "backends/native/meta-kms-crtc.h" -#include "backends/native/meta-kms-mode-private.h" -#include "backends/native/meta-kms-plane.h" - -struct _MetaKmsUpdate -{ - MetaKmsDevice *device; - - gboolean is_locked; - uint64_t sequence_number; - - gboolean power_save; - - GList *mode_sets; - GList *plane_assignments; - GList *connector_updates; - GList *crtc_gammas; - - MetaKmsCustomPageFlip *custom_page_flip; - - GList *page_flip_listeners; - GList *result_listeners; -}; - -void -meta_kms_plane_feedback_free (MetaKmsPlaneFeedback *plane_feedback) -{ - g_error_free (plane_feedback->error); - g_free (plane_feedback); -} - -MetaKmsPlaneFeedback * -meta_kms_plane_feedback_new_take_error (MetaKmsPlane *plane, - MetaKmsCrtc *crtc, - GError *error) -{ - MetaKmsPlaneFeedback *plane_feedback; - - plane_feedback = g_new0 (MetaKmsPlaneFeedback, 1); - *plane_feedback = (MetaKmsPlaneFeedback) { - .plane = plane, - .crtc = crtc, - .error = error, - }; - - return plane_feedback; -} - -MetaKmsFeedback * -meta_kms_feedback_new_passed (GList *failed_planes) -{ - MetaKmsFeedback *feedback; - - feedback = g_new0 (MetaKmsFeedback, 1); - *feedback = (MetaKmsFeedback) { - .result = META_KMS_FEEDBACK_PASSED, - .failed_planes = failed_planes, - }; - - return feedback; -} - -MetaKmsFeedback * -meta_kms_feedback_new_failed (GList *failed_planes, - GError *error) -{ - MetaKmsFeedback *feedback; - - feedback = g_new0 (MetaKmsFeedback, 1); - *feedback = (MetaKmsFeedback) { - .result = META_KMS_FEEDBACK_FAILED, - .error = error, - .failed_planes = failed_planes, - }; - - return feedback; -} - -void -meta_kms_feedback_free (MetaKmsFeedback *feedback) -{ - g_list_free_full (feedback->failed_planes, - (GDestroyNotify) meta_kms_plane_feedback_free); - g_clear_error (&feedback->error); - g_free (feedback); -} - -MetaKmsFeedbackResult -meta_kms_feedback_get_result (const MetaKmsFeedback *feedback) -{ - return feedback->result; -} - -GList * -meta_kms_feedback_get_failed_planes (const MetaKmsFeedback *feedback) -{ - return feedback->failed_planes; -} - -const GError * -meta_kms_feedback_get_error (const MetaKmsFeedback *feedback) -{ - return feedback->error; -} - -static void -meta_kms_plane_assignment_free (MetaKmsPlaneAssignment *plane_assignment) -{ - g_free (plane_assignment); -} - -static void -meta_kms_mode_set_free (MetaKmsModeSet *mode_set) -{ - g_list_free (mode_set->connectors); - g_free (mode_set); -} - -static void -meta_kms_page_flip_listener_free (MetaKmsPageFlipListener *listener) -{ - g_clear_pointer (&listener->user_data, listener->destroy_notify); - g_free (listener); -} - -static gboolean -drop_plane_assignment (MetaKmsUpdate *update, - MetaKmsPlane *plane, - MetaKmsAssignPlaneFlag *out_flags) -{ - GList *l; - - for (l = update->plane_assignments; l; l = l->next) - { - MetaKmsPlaneAssignment *plane_assignment = l->data; - - if (plane_assignment->plane == plane) - { - update->plane_assignments = - g_list_delete_link (update->plane_assignments, l); - if (out_flags) - *out_flags = plane_assignment->flags; - meta_kms_plane_assignment_free (plane_assignment); - return TRUE; - } - } - - return FALSE; -} - -void -meta_kms_update_drop_plane_assignment (MetaKmsUpdate *update, - MetaKmsPlane *plane) -{ - drop_plane_assignment (update, plane, NULL); -} - -MetaKmsPlaneAssignment * -meta_kms_update_assign_plane (MetaKmsUpdate *update, - MetaKmsCrtc *crtc, - MetaKmsPlane *plane, - MetaDrmBuffer *buffer, - MetaFixed16Rectangle src_rect, - MetaRectangle dst_rect, - MetaKmsAssignPlaneFlag flags) -{ - MetaKmsPlaneAssignment *plane_assignment; - MetaKmsAssignPlaneFlag old_flags; - - g_assert (!meta_kms_update_is_locked (update)); - g_assert (meta_kms_crtc_get_device (crtc) == update->device); - g_assert (!update->power_save); - g_assert (meta_kms_plane_get_device (plane) == update->device); - g_assert (meta_kms_plane_get_plane_type (plane) != - META_KMS_PLANE_TYPE_PRIMARY || - !(flags & META_KMS_ASSIGN_PLANE_FLAG_ALLOW_FAIL)); - - if (drop_plane_assignment (update, plane, &old_flags)) - { - if (!(old_flags & META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED)) - flags &= ~META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED; - } - - plane_assignment = g_new0 (MetaKmsPlaneAssignment, 1); - *plane_assignment = (MetaKmsPlaneAssignment) { - .update = update, - .crtc = crtc, - .plane = plane, - .buffer = buffer, - .src_rect = src_rect, - .dst_rect = dst_rect, - .flags = flags, - }; - - update->plane_assignments = g_list_prepend (update->plane_assignments, - plane_assignment); - - return plane_assignment; -} - -MetaKmsPlaneAssignment * -meta_kms_update_unassign_plane (MetaKmsUpdate *update, - MetaKmsCrtc *crtc, - MetaKmsPlane *plane) -{ - MetaKmsPlaneAssignment *plane_assignment; - - g_assert (!meta_kms_update_is_locked (update)); - g_assert (meta_kms_crtc_get_device (crtc) == update->device); - g_assert (meta_kms_plane_get_device (plane) == update->device); - g_assert (!update->power_save); - - plane_assignment = g_new0 (MetaKmsPlaneAssignment, 1); - *plane_assignment = (MetaKmsPlaneAssignment) { - .update = update, - .crtc = crtc, - .plane = plane, - .buffer = NULL, - }; - - update->plane_assignments = g_list_prepend (update->plane_assignments, - plane_assignment); - - return plane_assignment; -} - -void -meta_kms_update_mode_set (MetaKmsUpdate *update, - MetaKmsCrtc *crtc, - GList *connectors, - MetaKmsMode *mode) -{ - MetaKmsModeSet *mode_set; - - g_assert (!meta_kms_update_is_locked (update)); - g_assert (meta_kms_crtc_get_device (crtc) == update->device); - g_assert (!update->power_save); - - mode_set = g_new0 (MetaKmsModeSet, 1); - *mode_set = (MetaKmsModeSet) { - .crtc = crtc, - .connectors = connectors, - .mode = mode, - }; - - update->mode_sets = g_list_prepend (update->mode_sets, mode_set); -} - -static MetaKmsConnectorUpdate * -ensure_connector_update (MetaKmsUpdate *update, - MetaKmsConnector *connector) -{ - GList *l; - MetaKmsConnectorUpdate *connector_update; - - for (l = update->connector_updates; l; l = l->next) - { - connector_update = l->data; - - if (connector_update->connector == connector) - return connector_update; - } - - connector_update = g_new0 (MetaKmsConnectorUpdate, 1); - connector_update->connector = connector; - - update->connector_updates = g_list_prepend (update->connector_updates, - connector_update); - - return connector_update; -} - -void -meta_kms_update_set_underscanning (MetaKmsUpdate *update, - MetaKmsConnector *connector, - uint64_t hborder, - uint64_t vborder) -{ - MetaKmsConnectorUpdate *connector_update; - - g_assert (!meta_kms_update_is_locked (update)); - g_assert (meta_kms_connector_get_device (connector) == update->device); - g_assert (!update->power_save); - - connector_update = ensure_connector_update (update, connector); - connector_update->underscanning.has_update = TRUE; - connector_update->underscanning.is_active = TRUE; - connector_update->underscanning.hborder = hborder; - connector_update->underscanning.vborder = vborder; -} - -void -meta_kms_update_unset_underscanning (MetaKmsUpdate *update, - MetaKmsConnector *connector) -{ - MetaKmsConnectorUpdate *connector_update; - - g_assert (!meta_kms_update_is_locked (update)); - g_assert (meta_kms_connector_get_device (connector) == update->device); - g_assert (!update->power_save); - - connector_update = ensure_connector_update (update, connector); - connector_update->underscanning.has_update = TRUE; - connector_update->underscanning.is_active = FALSE; -} - -void -meta_kms_update_set_power_save (MetaKmsUpdate *update) -{ - g_assert (!meta_kms_update_is_locked (update)); - g_assert (!update->mode_sets); - g_assert (!update->plane_assignments); - g_assert (!update->connector_updates); - g_assert (!update->crtc_gammas); - - update->power_save = TRUE; -} - -void -meta_kms_crtc_gamma_free (MetaKmsCrtcGamma *gamma) -{ - g_free (gamma->red); - g_free (gamma->green); - g_free (gamma->blue); - g_free (gamma); -} - -MetaKmsCrtcGamma * -meta_kms_crtc_gamma_new (MetaKmsCrtc *crtc, - int size, - const uint16_t *red, - const uint16_t *green, - const uint16_t *blue) -{ - MetaKmsCrtcGamma *gamma; - - gamma = g_new0 (MetaKmsCrtcGamma, 1); - *gamma = (MetaKmsCrtcGamma) { - .crtc = crtc, - .size = size, - .red = g_memdup2 (red, size * sizeof (*red)), - .green = g_memdup2 (green, size * sizeof (*green)), - .blue = g_memdup2 (blue, size * sizeof (*blue)), - }; - - return gamma; -} - -void -meta_kms_update_set_crtc_gamma (MetaKmsUpdate *update, - MetaKmsCrtc *crtc, - int size, - const uint16_t *red, - const uint16_t *green, - const uint16_t *blue) -{ - MetaKmsCrtcGamma *gamma; - - g_assert (!meta_kms_update_is_locked (update)); - g_assert (meta_kms_crtc_get_device (crtc) == update->device); - g_assert (!update->power_save); - - gamma = meta_kms_crtc_gamma_new (crtc, size, red, green, blue); - - update->crtc_gammas = g_list_prepend (update->crtc_gammas, gamma); -} - -void -meta_kms_update_add_page_flip_listener (MetaKmsUpdate *update, - MetaKmsCrtc *crtc, - const MetaKmsPageFlipListenerVtable *vtable, - MetaKmsPageFlipListenerFlag flags, - gpointer user_data, - GDestroyNotify destroy_notify) -{ - MetaKmsPageFlipListener *listener; - - g_assert (!meta_kms_update_is_locked (update)); - g_assert (meta_kms_crtc_get_device (crtc) == update->device); - - listener = g_new0 (MetaKmsPageFlipListener, 1); - *listener = (MetaKmsPageFlipListener) { - .crtc = crtc, - .vtable = vtable, - .flags = flags, - .user_data = user_data, - .destroy_notify = destroy_notify, - }; - - update->page_flip_listeners = g_list_prepend (update->page_flip_listeners, - listener); -} - -void -meta_kms_update_drop_defunct_page_flip_listeners (MetaKmsUpdate *update) -{ - GList *l; - - l = update->page_flip_listeners; - while (l) - { - MetaKmsPageFlipListener *listener = l->data; - GList *l_next = l->next; - - if (listener->flags & META_KMS_PAGE_FLIP_LISTENER_FLAG_DROP_ON_ERROR) - { - meta_kms_page_flip_listener_free (listener); - update->page_flip_listeners = - g_list_delete_link (update->page_flip_listeners, l); - } - - l = l_next; - } -} - -void -meta_kms_update_set_custom_page_flip (MetaKmsUpdate *update, - MetaKmsCustomPageFlipFunc func, - gpointer user_data) -{ - MetaKmsCustomPageFlip *custom_page_flip; - - g_assert (!meta_kms_update_is_locked (update)); - g_assert (!update->power_save); - - custom_page_flip = g_new0 (MetaKmsCustomPageFlip, 1); - custom_page_flip->func = func; - custom_page_flip->user_data = user_data; - - update->custom_page_flip = custom_page_flip; -} - -void -meta_kms_plane_assignment_set_rotation (MetaKmsPlaneAssignment *plane_assignment, - uint64_t rotation) -{ - g_assert (!meta_kms_update_is_locked (plane_assignment->update)); - g_warn_if_fail (rotation); - - plane_assignment->rotation = rotation; -} - -void -meta_kms_plane_assignment_set_cursor_hotspot (MetaKmsPlaneAssignment *plane_assignment, - int x, - int y) -{ - plane_assignment->cursor_hotspot.is_valid = TRUE; - plane_assignment->cursor_hotspot.x = x; - plane_assignment->cursor_hotspot.y = y; -} - -void -meta_kms_update_add_result_listener (MetaKmsUpdate *update, - MetaKmsResultListenerFunc func, - gpointer user_data) -{ - MetaKmsResultListener *listener; - - listener = g_new0 (MetaKmsResultListener, 1); - *listener = (MetaKmsResultListener) { - .func = func, - .user_data = user_data, - }; - - update->result_listeners = g_list_append (update->result_listeners, - listener); -} - -GList * -meta_kms_update_take_result_listeners (MetaKmsUpdate *update) -{ - return g_steal_pointer (&update->result_listeners); -} - -void -meta_kms_result_listener_notify (MetaKmsResultListener *listener, - const MetaKmsFeedback *feedback) -{ - listener->func (feedback, listener->user_data); -} - -void -meta_kms_result_listener_free (MetaKmsResultListener *listener) -{ - g_free (listener); -} - -MetaKmsPlaneAssignment * -meta_kms_update_get_primary_plane_assignment (MetaKmsUpdate *update, - MetaKmsCrtc *crtc) -{ - GList *l; - - for (l = meta_kms_update_get_plane_assignments (update); l; l = l->next) - { - MetaKmsPlaneAssignment *plane_assignment = l->data; - - if (meta_kms_plane_get_plane_type (plane_assignment->plane) != - META_KMS_PLANE_TYPE_PRIMARY) - continue; - - if (plane_assignment->crtc != crtc) - continue; - - return plane_assignment; - } - - return NULL; -} - -GList * -meta_kms_update_get_plane_assignments (MetaKmsUpdate *update) -{ - return update->plane_assignments; -} - -GList * -meta_kms_update_get_mode_sets (MetaKmsUpdate *update) -{ - return update->mode_sets; -} - -GList * -meta_kms_update_get_page_flip_listeners (MetaKmsUpdate *update) -{ - return update->page_flip_listeners; -} - -GList * -meta_kms_update_get_connector_updates (MetaKmsUpdate *update) -{ - return update->connector_updates; -} - -GList * -meta_kms_update_get_crtc_gammas (MetaKmsUpdate *update) -{ - return update->crtc_gammas; -} - -gboolean -meta_kms_update_is_power_save (MetaKmsUpdate *update) -{ - return update->power_save; -} - -void -meta_kms_update_lock (MetaKmsUpdate *update) -{ - update->is_locked = TRUE; -} - -void -meta_kms_update_unlock (MetaKmsUpdate *update) -{ - update->is_locked = FALSE; -} - -gboolean -meta_kms_update_is_locked (MetaKmsUpdate *update) -{ - return update->is_locked; -} - -MetaKmsDevice * -meta_kms_update_get_device (MetaKmsUpdate *update) -{ - return update->device; -} - -MetaKmsCustomPageFlip * -meta_kms_update_take_custom_page_flip_func (MetaKmsUpdate *update) -{ - return g_steal_pointer (&update->custom_page_flip); -} - -void -meta_kms_custom_page_flip_free (MetaKmsCustomPageFlip *custom_page_flip) -{ - g_free (custom_page_flip); -} - -uint64_t -meta_kms_update_get_sequence_number (MetaKmsUpdate *update) -{ - return update->sequence_number; -} - -MetaKmsUpdate * -meta_kms_update_new (MetaKmsDevice *device) -{ - MetaKmsUpdate *update; - static uint64_t sequence_number = 0; - - update = g_new0 (MetaKmsUpdate, 1); - update->device = device; - update->sequence_number = sequence_number++; - - return update; -} - -void -meta_kms_update_free (MetaKmsUpdate *update) -{ - g_list_free_full (update->result_listeners, - (GDestroyNotify) meta_kms_result_listener_free); - g_list_free_full (update->plane_assignments, - (GDestroyNotify) meta_kms_plane_assignment_free); - g_list_free_full (update->mode_sets, - (GDestroyNotify) meta_kms_mode_set_free); - g_list_free_full (update->page_flip_listeners, - (GDestroyNotify) meta_kms_page_flip_listener_free); - g_list_free_full (update->connector_updates, g_free); - g_list_free_full (update->crtc_gammas, (GDestroyNotify) meta_kms_crtc_gamma_free); - g_clear_pointer (&update->custom_page_flip, meta_kms_custom_page_flip_free); - - g_free (update); -} diff --git a/src/backends/native/meta-kms-update.h b/src/backends/native/meta-kms-update.h deleted file mode 100644 index 4a6a8bb43..000000000 --- a/src/backends/native/meta-kms-update.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2018 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_KMS_UPDATE_H -#define META_KMS_UPDATE_H - -#include -#include -#include -#include - -#include "backends/meta-monitor-transform.h" -#include "backends/native/meta-drm-buffer.h" -#include "backends/native/meta-kms-types.h" -#include "meta/boxes.h" - -typedef enum _MetaKmsFeedbackResult -{ - META_KMS_FEEDBACK_PASSED, - META_KMS_FEEDBACK_FAILED, -} MetaKmsFeedbackResult; - -typedef enum _MetaKmsAssignPlaneFlag -{ - META_KMS_ASSIGN_PLANE_FLAG_NONE = 0, - META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED = 1 << 0, - META_KMS_ASSIGN_PLANE_FLAG_ALLOW_FAIL = 1 << 1, -} MetaKmsAssignPlaneFlag; - -enum _MetaKmsPageFlipListenerFlag -{ - META_KMS_PAGE_FLIP_LISTENER_FLAG_NONE = 0, - META_KMS_PAGE_FLIP_LISTENER_FLAG_DROP_ON_ERROR = 1 << 0, -}; - -struct _MetaKmsPageFlipListenerVtable -{ - void (* flipped) (MetaKmsCrtc *crtc, - unsigned int sequence, - unsigned int tv_sec, - unsigned int tv_usec, - gpointer user_data); - - void (* ready) (MetaKmsCrtc *crtc, - gpointer user_data); - - void (* mode_set_fallback) (MetaKmsCrtc *crtc, - gpointer user_data); - - void (* discarded) (MetaKmsCrtc *crtc, - gpointer user_data, - const GError *error); -}; - -typedef int (* MetaKmsCustomPageFlipFunc) (gpointer custom_page_flip_data, - gpointer user_data); - -typedef struct _MetaKmsPlaneFeedback -{ - MetaKmsPlane *plane; - MetaKmsCrtc *crtc; - GError *error; -} MetaKmsPlaneFeedback; - -typedef void (* MetaKmsResultListenerFunc) (const MetaKmsFeedback *feedback, - gpointer user_data); - -void meta_kms_feedback_free (MetaKmsFeedback *feedback); - -MetaKmsFeedbackResult meta_kms_feedback_get_result (const MetaKmsFeedback *feedback); - -GList * meta_kms_feedback_get_failed_planes (const MetaKmsFeedback *feedback); - -const GError * meta_kms_feedback_get_error (const MetaKmsFeedback *feedback); - -MetaKmsUpdate * meta_kms_update_new (MetaKmsDevice *device); - -void meta_kms_update_free (MetaKmsUpdate *update); - -void meta_kms_update_set_underscanning (MetaKmsUpdate *update, - MetaKmsConnector *connector, - uint64_t hborder, - uint64_t vborder); - -void meta_kms_update_unset_underscanning (MetaKmsUpdate *update, - MetaKmsConnector *connector); - -void meta_kms_update_set_power_save (MetaKmsUpdate *update); - -void meta_kms_update_mode_set (MetaKmsUpdate *update, - MetaKmsCrtc *crtc, - GList *connectors, - MetaKmsMode *mode); - -void meta_kms_update_set_crtc_gamma (MetaKmsUpdate *update, - MetaKmsCrtc *crtc, - int size, - const uint16_t *red, - const uint16_t *green, - const uint16_t *blue); - -MetaKmsPlaneAssignment * meta_kms_update_assign_plane (MetaKmsUpdate *update, - MetaKmsCrtc *crtc, - MetaKmsPlane *plane, - MetaDrmBuffer *buffer, - MetaFixed16Rectangle src_rect, - MetaRectangle dst_rect, - MetaKmsAssignPlaneFlag flags); - -MetaKmsPlaneAssignment * meta_kms_update_unassign_plane (MetaKmsUpdate *update, - MetaKmsCrtc *crtc, - MetaKmsPlane *plane); - -void meta_kms_update_add_page_flip_listener (MetaKmsUpdate *update, - MetaKmsCrtc *crtc, - const MetaKmsPageFlipListenerVtable *vtable, - MetaKmsPageFlipListenerFlag flags, - gpointer user_data, - GDestroyNotify destroy_notify); - -void meta_kms_update_set_custom_page_flip (MetaKmsUpdate *update, - MetaKmsCustomPageFlipFunc func, - gpointer user_data); - -void meta_kms_plane_assignment_set_cursor_hotspot (MetaKmsPlaneAssignment *plane_assignment, - int x, - int y); - -void meta_kms_update_add_result_listener (MetaKmsUpdate *update, - MetaKmsResultListenerFunc func, - gpointer user_data); - -static inline MetaFixed16 -meta_fixed_16_from_int (int16_t d) -{ - return d * 65536; -} - -static inline int16_t -meta_fixed_16_to_int (MetaFixed16 fixed) -{ - return fixed / 65536; -} - -static inline double -meta_fixed_16_to_double (MetaFixed16 fixed) -{ - return fixed / 65536.0; -} - -static inline MetaRectangle -meta_fixed_16_rectangle_to_rectangle (MetaFixed16Rectangle fixed_rect) -{ - return (MetaRectangle) { - .x = meta_fixed_16_to_int (fixed_rect.x), - .y = meta_fixed_16_to_int (fixed_rect.y), - .width = meta_fixed_16_to_int (fixed_rect.width), - .height = meta_fixed_16_to_int (fixed_rect.height), - }; -} - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaKmsFeedback, meta_kms_feedback_free) -G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaKmsUpdate, meta_kms_update_free) - -#endif /* META_KMS_UPDATE_H */ diff --git a/src/backends/native/meta-kms-utils.c b/src/backends/native/meta-kms-utils.c deleted file mode 100644 index 2289cfa91..000000000 --- a/src/backends/native/meta-kms-utils.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2013-2019 Red Hat - * Copyright (c) 2018 DisplayLink (UK) Ltd. - * - * 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 "backends/native/meta-kms-utils.h" - -#include -#include - -/* added in libdrm 2.4.95 */ -#ifndef DRM_FORMAT_INVALID -#define DRM_FORMAT_INVALID 0 -#endif - -float -meta_calculate_drm_mode_refresh_rate (const drmModeModeInfo *drm_mode) -{ - double numerator; - double denominator; - - if (drm_mode->htotal <= 0 || drm_mode->vtotal <= 0) - return 0.0; - - numerator = drm_mode->clock * 1000.0; - denominator = (double) drm_mode->vtotal * drm_mode->htotal; - if (drm_mode->vscan > 1) - denominator *= drm_mode->vscan; - - return numerator / denominator; -} - -int64_t -meta_calculate_drm_mode_vblank_duration_us (const drmModeModeInfo *drm_mode) -{ - int64_t value; - - if (drm_mode->htotal <= 0 || drm_mode->vtotal <= 0) - return 0; - - /* Convert to int64_t early. */ - value = drm_mode->vtotal - drm_mode->vdisplay; - value *= drm_mode->htotal; - - if (drm_mode->flags & DRM_MODE_FLAG_DBLSCAN) - value *= 2; - - /* Round the duration up as it is used for buffer swap deadline computation. */ - value = (value * 1000 + drm_mode->clock - 1) / drm_mode->clock; - - return value; -} - -/** - * 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; -} - diff --git a/src/backends/native/meta-kms-utils.h b/src/backends/native/meta-kms-utils.h deleted file mode 100644 index 2f2bad1f9..000000000 --- a/src/backends/native/meta-kms-utils.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2018 DisplayLink (UK) Ltd. - * - * 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_KMS_UTILS_H -#define META_KMS_UTILS_H - -#include -#include -#include - -#include "core/util-private.h" - -typedef struct _MetaDrmFormatBuf -{ - char s[5]; -} MetaDrmFormatBuf; - -META_EXPORT_TEST -float meta_calculate_drm_mode_refresh_rate (const drmModeModeInfo *drm_mode); - -META_EXPORT_TEST -int64_t meta_calculate_drm_mode_vblank_duration_us (const drmModeModeInfo *drm_mode); - -const char * meta_drm_format_to_string (MetaDrmFormatBuf *tmp, - uint32_t drm_format); - -#endif /* META_KMS_UTILS_H */ diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c deleted file mode 100644 index 70feccc22..000000000 --- a/src/backends/native/meta-kms.c +++ /dev/null @@ -1,754 +0,0 @@ -/* - * Copyright (C) 2018 Red Hat - * Copyright 2020 DisplayLink (UK) Ltd. - * - * 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 "backends/native/meta-kms-private.h" - -#include "backends/native/meta-backend-native.h" -#include "backends/native/meta-kms-device-private.h" -#include "backends/native/meta-kms-impl.h" -#include "backends/native/meta-kms-update-private.h" -#include "backends/native/meta-udev.h" -#include "cogl/cogl.h" - -/** - * SECTION:kms - * @short description: KMS abstraction - * @title: KMS abstraction - * - * The KMS abstraction consists of various building blocks for helping out with - * interacting with the various drm API's, enabling users to use a - * transactional API, aiming to hide all interaction with the underlying APIs. - * - * The subsystem defines two separate contexts, the "main" context, and the - * "impl" context. The main context is the context of which mutter as a whole - * runs in. It uses the main GLib main loop and main context and always runs in - * the main thread. - * - * The impl context is where all underlying API is being executed. While in the - * current state, it always runs in the main thread, the aim is to be able to - * execute the impl context in a dedicated thread. - * - * The public facing MetaKms API is always assumed to be executed from the main - * context. - * - * The KMS abstraction consists of the following public components: - * - * #MetaKms: - * - * Main entry point; used by the native backend to create devices, post updates - * etc. - * - * #MetaKmsDevice: - * - * A device (usually /dev/dri/cardN, where N being a number). Used to get KMS - * objects, such as connectors, CRTCs, planes, as well as basic meta data such - * as device path etc. - * - * #MetaKmsCrtc: - * - * Represents a CRTC. It manages a representation of the current CRTC state, - * including current mode, coordinates, possible clones. - * - * #MetaKmsConnector: - * - * Represents a connector, e.g. a display port connection. It also manages a - * representation of the current state, including meta data such as physical - * dimension of the connected, available modes, EDID, tile info etc. It also - * contains helper functions for configuration, as well as methods for adding - * configuration to a transaction (See #MetaKmsUpdate). - * - * #MetaKmsPlane: - * - * Represents a hardware plane. A plane is used to define the content of what - * should be presented on a CRTC. Planes can either be primary planes, used as - * a backdrop for CRTCs, overlay planes, and cursor planes. - * - * #MetaKmsMode: - * - * Represents a mode a CRTC and connector can be configured with. - * Represents both modes directly derived from the devices, as well as - * fall back modes when the CRTC supports scaling. - * - * #MetaKmsUpdate: - * - * A KMS transaction object, meant to be processed potentially atomically when - * posted. An update consists of plane assignments, mode sets and KMS object - * property entries. The user adds updates to the object, and then posts it via - * MetaKms. It will then be processed by the MetaKms backend (See - * #MetaKmsImpl), potentially atomically. Each #MetaKmsUpdate deals with - * updating a single device. - * - * - * There are also these private objects, without public facing API: - * - * #MetaKmsImpl: - * - * The KMS impl context object, managing things in the impl context. - * - * #MetaKmsImplDevice: - * - * An object linked to a #MetaKmsDevice, but where it is executed in the impl - * context. It takes care of the updating of the various KMS object (CRTC, - * connector, ..) states. - * - * This is an abstract type, with currently #MetaKmsImplDeviceSimple, - * implementing mode setting and page flipping using legacy DRM API. - * - * #MetaKmsPageFlip: - * - * A object representing a page flip. It's created when a page flip is queued, - * and contains information necessary to provide feedback to the one requesting - * the page flip. - * - */ - -enum -{ - RESOURCES_CHANGED, - - N_SIGNALS -}; - -static int signals[N_SIGNALS]; - -typedef struct _MetaKmsCallbackData -{ - MetaKmsCallback callback; - gpointer user_data; - GDestroyNotify user_data_destroy; -} MetaKmsCallbackData; - -typedef struct _MetaKmsSimpleImplSource -{ - GSource source; - MetaKms *kms; -} MetaKmsSimpleImplSource; - -typedef struct _MetaKmsFdImplSource -{ - GSource source; - - gpointer fd_tag; - MetaKms *kms; - - MetaKmsImplTaskFunc dispatch; - gpointer user_data; -} MetaKmsFdImplSource; - -struct _MetaKms -{ - GObject parent; - - MetaKmsFlags flags; - - MetaBackend *backend; - - gulong hotplug_handler_id; - gulong removed_handler_id; - - MetaKmsImpl *impl; - gboolean in_impl_task; - gboolean waiting_for_impl_task; - - GList *devices; - - GList *pending_updates; - - GList *pending_callbacks; - guint callback_source_id; -}; - -G_DEFINE_TYPE (MetaKms, meta_kms, G_TYPE_OBJECT) - -static void -meta_kms_add_pending_update (MetaKms *kms, - MetaKmsUpdate *update) -{ - kms->pending_updates = g_list_prepend (kms->pending_updates, update); -} - -MetaKmsUpdate * -meta_kms_ensure_pending_update (MetaKms *kms, - MetaKmsDevice *device) -{ - MetaKmsUpdate *update; - - update = meta_kms_get_pending_update (kms, device); - if (update) - return update; - - update = meta_kms_update_new (device); - meta_kms_add_pending_update (kms, update); - - return update; -} - -MetaKmsUpdate * -meta_kms_get_pending_update (MetaKms *kms, - MetaKmsDevice *device) -{ - GList *l; - - for (l = kms->pending_updates; l; l = l->next) - { - MetaKmsUpdate *update = l->data; - - if (meta_kms_update_get_device (update) == device) - return update; - } - - return NULL; -} - -static MetaKmsUpdate * -meta_kms_take_pending_update (MetaKms *kms, - MetaKmsDevice *device) -{ - GList *l; - - for (l = kms->pending_updates; l; l = l->next) - { - MetaKmsUpdate *update = l->data; - - if (meta_kms_update_get_device (update) == device) - { - kms->pending_updates = g_list_delete_link (kms->pending_updates, l); - return update; - } - } - - return NULL; -} - -typedef struct -{ - MetaKmsUpdate *update; - MetaKmsUpdateFlag flags; -} PostUpdateData; - -static gpointer -meta_kms_process_update_in_impl (MetaKmsImpl *impl, - gpointer user_data, - GError **error) -{ - PostUpdateData *data = user_data; - MetaKmsUpdate *update = data->update; - MetaKmsFeedback *feedback; - - feedback = meta_kms_impl_process_update (impl, data->update, data->flags); - meta_kms_device_predict_states_in_impl (meta_kms_update_get_device (update), - update); - - return feedback; -} - -MetaKmsFeedback * -meta_kms_post_pending_update_sync (MetaKms *kms, - MetaKmsDevice *device, - MetaKmsUpdateFlag flags) -{ - MetaKmsUpdate *update; - PostUpdateData data; - MetaKmsFeedback *feedback; - GList *result_listeners; - GList *l; - - COGL_TRACE_BEGIN_SCOPED (MetaKmsPostUpdateSync, - "KMS (post update)"); - - update = meta_kms_take_pending_update (kms, device); - if (!update) - return NULL; - - meta_kms_update_lock (update); - - data = (PostUpdateData) { - .update = update, - .flags = flags, - }; - feedback = meta_kms_run_impl_task_sync (kms, - meta_kms_process_update_in_impl, - &data, - NULL); - - result_listeners = meta_kms_update_take_result_listeners (update); - - if (feedback->error && - flags & META_KMS_UPDATE_FLAG_PRESERVE_ON_ERROR) - { - GList *l; - - meta_kms_update_unlock (update); - - for (l = feedback->failed_planes; l; l = l->next) - { - MetaKmsPlane *plane = l->data; - - meta_kms_update_drop_plane_assignment (update, plane); - } - - meta_kms_update_drop_defunct_page_flip_listeners (update); - - meta_kms_add_pending_update (kms, update); - } - else - { - meta_kms_update_free (update); - } - - for (l = result_listeners; l; l = l->next) - { - MetaKmsResultListener *listener = l->data; - - meta_kms_result_listener_notify (listener, feedback); - meta_kms_result_listener_free (listener); - } - g_list_free (result_listeners); - - return feedback; -} - -static gpointer -meta_kms_discard_pending_page_flips_in_impl (MetaKmsImpl *impl, - gpointer user_data, - GError **error) -{ - meta_kms_impl_discard_pending_page_flips (impl); - return GINT_TO_POINTER (TRUE); -} - -void -meta_kms_discard_pending_page_flips (MetaKms *kms) -{ - meta_kms_run_impl_task_sync (kms, - meta_kms_discard_pending_page_flips_in_impl, - NULL, - NULL); -} - -static gpointer -meta_kms_notify_modes_set_in_impl (MetaKmsImpl *impl, - gpointer user_data, - GError **error) -{ - meta_kms_impl_notify_modes_set (impl); - return GINT_TO_POINTER (TRUE); -} - -void -meta_kms_notify_modes_set (MetaKms *kms) -{ - meta_kms_run_impl_task_sync (kms, - meta_kms_notify_modes_set_in_impl, - NULL, - NULL); -} - -static void -meta_kms_callback_data_free (MetaKmsCallbackData *callback_data) -{ - if (callback_data->user_data_destroy) - callback_data->user_data_destroy (callback_data->user_data); - g_free (callback_data); -} - -static int -flush_callbacks (MetaKms *kms) -{ - GList *l; - int callback_count = 0; - - meta_assert_not_in_kms_impl (kms); - - g_clear_handle_id (&kms->callback_source_id, g_source_remove); - - for (l = kms->pending_callbacks; l; l = l->next) - { - MetaKmsCallbackData *callback_data = l->data; - - callback_data->callback (kms, callback_data->user_data); - meta_kms_callback_data_free (callback_data); - callback_count++; - } - - g_list_free (kms->pending_callbacks); - kms->pending_callbacks = NULL; - - return callback_count; -} - -static gboolean -callback_idle (gpointer user_data) -{ - MetaKms *kms = user_data; - - flush_callbacks (kms); - - kms->callback_source_id = 0; - return G_SOURCE_REMOVE; -} - -void -meta_kms_queue_callback (MetaKms *kms, - MetaKmsCallback callback, - gpointer user_data, - GDestroyNotify user_data_destroy) -{ - MetaKmsCallbackData *callback_data; - - callback_data = g_new0 (MetaKmsCallbackData, 1); - *callback_data = (MetaKmsCallbackData) { - .callback = callback, - .user_data = user_data, - .user_data_destroy = user_data_destroy, - }; - kms->pending_callbacks = g_list_append (kms->pending_callbacks, - callback_data); - if (!kms->callback_source_id) - kms->callback_source_id = g_idle_add (callback_idle, kms); -} - -gpointer -meta_kms_run_impl_task_sync (MetaKms *kms, - MetaKmsImplTaskFunc func, - gpointer user_data, - GError **error) -{ - gpointer ret; - - kms->in_impl_task = TRUE; - kms->waiting_for_impl_task = TRUE; - ret = func (kms->impl, user_data, error); - kms->waiting_for_impl_task = FALSE; - kms->in_impl_task = FALSE; - - return ret; -} - -static gboolean -simple_impl_source_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data) -{ - MetaKmsSimpleImplSource *simple_impl_source = - (MetaKmsSimpleImplSource *) source; - MetaKms *kms = simple_impl_source->kms; - gboolean ret; - - kms->in_impl_task = TRUE; - ret = callback (user_data); - kms->in_impl_task = FALSE; - - return ret; -} - -static GSourceFuncs simple_impl_source_funcs = { - .dispatch = simple_impl_source_dispatch, -}; - -GSource * -meta_kms_add_source_in_impl (MetaKms *kms, - GSourceFunc func, - gpointer user_data, - GDestroyNotify user_data_destroy) -{ - GSource *source; - MetaKmsSimpleImplSource *simple_impl_source; - - meta_assert_in_kms_impl (kms); - - source = g_source_new (&simple_impl_source_funcs, - sizeof (MetaKmsSimpleImplSource)); - simple_impl_source = (MetaKmsSimpleImplSource *) source; - simple_impl_source->kms = kms; - - g_source_set_callback (source, func, user_data, user_data_destroy); - g_source_set_ready_time (source, 0); - g_source_attach (source, g_main_context_get_thread_default ()); - - return source; -} - -static gboolean -meta_kms_fd_impl_source_check (GSource *source) -{ - MetaKmsFdImplSource *fd_impl_source = (MetaKmsFdImplSource *) source; - - return g_source_query_unix_fd (source, fd_impl_source->fd_tag) & G_IO_IN; -} - -static gboolean -meta_kms_fd_impl_source_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data) -{ - MetaKmsFdImplSource *fd_impl_source = (MetaKmsFdImplSource *) source; - MetaKms *kms = fd_impl_source->kms; - gpointer ret; - GError *error = NULL; - - kms->in_impl_task = TRUE; - ret = fd_impl_source->dispatch (kms->impl, - fd_impl_source->user_data, - &error); - kms->in_impl_task = FALSE; - - if (!GPOINTER_TO_INT (ret)) - { - g_warning ("Failed to dispatch fd source: %s", error->message); - g_error_free (error); - } - - return G_SOURCE_CONTINUE; -} - -static GSourceFuncs fd_impl_source_funcs = { - NULL, - meta_kms_fd_impl_source_check, - meta_kms_fd_impl_source_dispatch -}; - -GSource * -meta_kms_register_fd_in_impl (MetaKms *kms, - int fd, - MetaKmsImplTaskFunc dispatch, - gpointer user_data) -{ - GSource *source; - MetaKmsFdImplSource *fd_impl_source; - - meta_assert_in_kms_impl (kms); - - source = g_source_new (&fd_impl_source_funcs, sizeof (MetaKmsFdImplSource)); - fd_impl_source = (MetaKmsFdImplSource *) source; - fd_impl_source->dispatch = dispatch; - fd_impl_source->user_data = user_data; - fd_impl_source->kms = kms; - fd_impl_source->fd_tag = g_source_add_unix_fd (source, fd, - G_IO_IN | G_IO_ERR); - - g_source_attach (source, g_main_context_get_thread_default ()); - - return source; -} - -gboolean -meta_kms_in_impl_task (MetaKms *kms) -{ - return kms->in_impl_task; -} - -gboolean -meta_kms_is_waiting_for_impl_task (MetaKms *kms) -{ - return kms->waiting_for_impl_task; -} - -static void -meta_kms_update_states_in_impl (MetaKms *kms) -{ - COGL_TRACE_BEGIN_SCOPED (MetaKmsUpdateStates, - "KMS (update states)"); - - meta_assert_in_kms_impl (kms); - - g_list_foreach (kms->devices, - (GFunc) meta_kms_device_update_states_in_impl, - NULL); -} - -static gpointer -update_states_in_impl (MetaKmsImpl *impl, - gpointer user_data, - GError **error) -{ - MetaKms *kms = meta_kms_impl_get_kms (impl); - - meta_kms_update_states_in_impl (kms); - - return GINT_TO_POINTER (TRUE); -} - -static gboolean -meta_kms_update_states_sync (MetaKms *kms, - GError **error) -{ - gpointer ret; - - ret = meta_kms_run_impl_task_sync (kms, update_states_in_impl, NULL, error); - return GPOINTER_TO_INT (ret); -} - -static void -handle_hotplug_event (MetaKms *kms) -{ - g_autoptr (GError) error = NULL; - - if (!meta_kms_update_states_sync (kms, &error)) - g_warning ("Updating KMS state failed: %s", error->message); - - g_signal_emit (kms, signals[RESOURCES_CHANGED], 0); -} - -void -meta_kms_resume (MetaKms *kms) -{ - handle_hotplug_event (kms); -} - -static void -on_udev_hotplug (MetaUdev *udev, - MetaKms *kms) -{ - handle_hotplug_event (kms); -} - -static void -on_udev_device_removed (MetaUdev *udev, - GUdevDevice *device, - MetaKms *kms) -{ - handle_hotplug_event (kms); -} - -MetaBackend * -meta_kms_get_backend (MetaKms *kms) -{ - return kms->backend; -} - -GList * -meta_kms_get_devices (MetaKms *kms) -{ - return kms->devices; -} - -MetaKmsDevice * -meta_kms_create_device (MetaKms *kms, - const char *path, - MetaKmsDeviceFlag flags, - GError **error) -{ - MetaKmsDevice *device; - - if (kms->flags & META_KMS_FLAG_NO_MODE_SETTING) - flags |= META_KMS_DEVICE_FLAG_NO_MODE_SETTING; - - device = meta_kms_device_new (kms, path, flags, error); - if (!device) - return NULL; - - kms->devices = g_list_append (kms->devices, device); - - return device; -} - -MetaKms * -meta_kms_new (MetaBackend *backend, - MetaKmsFlags flags, - GError **error) -{ - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - MetaUdev *udev = meta_backend_native_get_udev (backend_native); - MetaKms *kms; - - kms = g_object_new (META_TYPE_KMS, NULL); - kms->flags = flags; - kms->backend = backend; - kms->impl = meta_kms_impl_new (kms); - if (!kms->impl) - { - g_object_unref (kms); - return NULL; - } - - if (!(flags & META_KMS_FLAG_NO_MODE_SETTING)) - { - kms->hotplug_handler_id = - g_signal_connect (udev, "hotplug", G_CALLBACK (on_udev_hotplug), kms); - } - - kms->removed_handler_id = - g_signal_connect (udev, "device-removed", - G_CALLBACK (on_udev_device_removed), kms); - - return kms; -} - -static gpointer -prepare_shutdown_in_impl (MetaKmsImpl *impl, - gpointer user_data, - GError **error) -{ - meta_kms_impl_prepare_shutdown (impl); - return GINT_TO_POINTER (TRUE); -} - -void -meta_kms_prepare_shutdown (MetaKms *kms) -{ - meta_kms_run_impl_task_sync (kms, prepare_shutdown_in_impl, NULL, NULL); - flush_callbacks (kms); -} - -static void -meta_kms_finalize (GObject *object) -{ - MetaKms *kms = META_KMS (object); - MetaBackendNative *backend_native = META_BACKEND_NATIVE (kms->backend); - MetaUdev *udev = meta_backend_native_get_udev (backend_native); - GList *l; - - for (l = kms->pending_callbacks; l; l = l->next) - meta_kms_callback_data_free (l->data); - g_list_free (kms->pending_callbacks); - - g_clear_handle_id (&kms->callback_source_id, g_source_remove); - - g_list_free_full (kms->devices, g_object_unref); - - g_clear_signal_handler (&kms->hotplug_handler_id, udev); - g_clear_signal_handler (&kms->removed_handler_id, udev); - - G_OBJECT_CLASS (meta_kms_parent_class)->finalize (object); -} - -static void -meta_kms_init (MetaKms *kms) -{ -} - -static void -meta_kms_class_init (MetaKmsClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_kms_finalize; - - signals[RESOURCES_CHANGED] = - g_signal_new ("resources-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); -} diff --git a/src/backends/native/meta-kms.h b/src/backends/native/meta-kms.h deleted file mode 100644 index 9eae80e3f..000000000 --- a/src/backends/native/meta-kms.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2018 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_KMS_H -#define META_KMS_H - -#include - -#include "backends/meta-backend-private.h" -#include "backends/native/meta-kms-types.h" - -typedef enum _MetaKmsFlags -{ - META_KMS_FLAG_NONE = 0, - META_KMS_FLAG_NO_MODE_SETTING = 1 << 0, -} MetaKmsFlags; - -typedef enum _MetaKmsUpdateFlag -{ - META_KMS_UPDATE_FLAG_NONE = 0, - META_KMS_UPDATE_FLAG_PRESERVE_ON_ERROR = 1 << 0, -} MetaKmsUpdateFlag; - -#define META_TYPE_KMS (meta_kms_get_type ()) -G_DECLARE_FINAL_TYPE (MetaKms, meta_kms, META, KMS, GObject) - -MetaKmsUpdate * meta_kms_ensure_pending_update (MetaKms *kms, - MetaKmsDevice *device); - -MetaKmsUpdate * meta_kms_get_pending_update (MetaKms *kms, - MetaKmsDevice *device); - -MetaKmsFeedback * meta_kms_post_pending_update_sync (MetaKms *kms, - MetaKmsDevice *device, - MetaKmsUpdateFlag flags); - -void meta_kms_discard_pending_page_flips (MetaKms *kms); - -void meta_kms_notify_modes_set (MetaKms *kms); - -MetaBackend * meta_kms_get_backend (MetaKms *kms); - -GList * meta_kms_get_devices (MetaKms *kms); - -void meta_kms_resume (MetaKms *kms); - -MetaKmsDevice * meta_kms_create_device (MetaKms *kms, - const char *path, - MetaKmsDeviceFlag flags, - GError **error); - -void meta_kms_prepare_shutdown (MetaKms *kms); - -MetaKms * meta_kms_new (MetaBackend *backend, - MetaKmsFlags flags, - GError **error); - -#endif /* META_KMS_H */ diff --git a/src/backends/native/meta-launcher.c b/src/backends/native/meta-launcher.c deleted file mode 100644 index 4a63d2feb..000000000 --- a/src/backends/native/meta-launcher.c +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Copyright (C) 2013 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include "config.h" - -#include "backends/native/meta-launcher.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/native/dbus-utils.h" -#include "backends/native/meta-backend-native.h" -#include "backends/native/meta-clutter-backend-native.h" -#include "backends/native/meta-cursor-renderer-native.h" -#include "backends/native/meta-input-thread.h" -#include "backends/native/meta-renderer-native.h" -#include "clutter/clutter.h" - -#include "meta-dbus-login1.h" - -struct _MetaLauncher -{ - MetaDbusLogin1Session *session_proxy; - MetaDbusLogin1Seat *seat_proxy; - char *seat_id; - - gboolean session_active; -}; - -const char * -meta_launcher_get_seat_id (MetaLauncher *launcher) -{ - return launcher->seat_id; -} - -static gboolean -find_systemd_session (gchar **session_id, - GError **error) -{ - const gchar * const graphical_session_types[] = { "wayland", "x11", "mir", NULL }; - const gchar * const active_states[] = { "active", "online", NULL }; - g_autofree gchar *class = NULL; - g_autofree gchar *local_session_id = NULL; - g_autofree gchar *type = NULL; - g_autofree gchar *state = NULL; - g_auto (GStrv) sessions = NULL; - int n_sessions; - int saved_errno; - - g_assert (session_id != NULL); - g_assert (error == NULL || *error == NULL); - - /* if we are in a logind session, we can trust that value, so use it. This - * happens for example when you run mutter directly from a VT but when - * systemd starts us we will not be in a logind session. */ - saved_errno = sd_pid_get_session (0, &local_session_id); - if (saved_errno < 0) - { - if (saved_errno != -ENODATA) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - "Failed to get session by pid for user %d (%s)", - getuid (), - g_strerror (-saved_errno)); - return FALSE; - } - } - else - { - *session_id = g_steal_pointer (&local_session_id); - return TRUE; - } - - saved_errno = sd_uid_get_display (getuid (), &local_session_id); - if (saved_errno < 0) - { - /* no session, maybe there's a greeter session */ - if (saved_errno == -ENODATA) - { - n_sessions = sd_uid_get_sessions (getuid (), 1, &sessions); - if (n_sessions < 0) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - "Failed to get all sessions for user %d (%m)", - getuid ()); - return FALSE; - } - - if (n_sessions == 0) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - "User %d has no sessions", - getuid ()); - return FALSE; - } - - for (int i = 0; i < n_sessions; ++i) - { - saved_errno = sd_session_get_class (sessions[i], &class); - if (saved_errno < 0) - { - g_warning ("Couldn't get class for session '%d': %s", - i, - g_strerror (-saved_errno)); - continue; - } - - if (g_strcmp0 (class, "greeter") == 0) - { - local_session_id = g_strdup (sessions[i]); - break; - } - } - - if (!local_session_id) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - "Couldn't find a session or a greeter session for user %d", - getuid ()); - return FALSE; - } - } - else - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - "Couldn't get display for user %d: %s", - getuid (), - g_strerror (-saved_errno)); - return FALSE; - } - } - - /* sd_uid_get_display will return any session if there is no graphical - * one, so let's check it really is graphical. */ - saved_errno = sd_session_get_type (local_session_id, &type); - if (saved_errno < 0) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - "Couldn't get type for session '%s': %s", - local_session_id, - g_strerror (-saved_errno)); - return FALSE; - } - - if (!g_strv_contains (graphical_session_types, type)) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - "Session '%s' is not a graphical session (type: '%s')", - local_session_id, - type); - return FALSE; - } - - /* and display sessions can be 'closing' if they are logged out but - * some processes are lingering; we shouldn't consider these */ - saved_errno = sd_session_get_state (local_session_id, &state); - if (saved_errno < 0) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - "Couldn't get state for session '%s': %s", - local_session_id, - g_strerror (-saved_errno)); - return FALSE; - } - - if (!g_strv_contains (active_states, state)) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - "Session '%s' is not active", - local_session_id); - return FALSE; - } - - *session_id = g_steal_pointer (&local_session_id); - - return TRUE; -} - -static MetaDbusLogin1Session * -get_session_proxy (GCancellable *cancellable, - GError **error) -{ - g_autofree char *proxy_path = NULL; - g_autofree char *session_id = NULL; - g_autoptr (GError) local_error = NULL; - GDBusProxyFlags flags; - MetaDbusLogin1Session *session_proxy; - - if (!find_systemd_session (&session_id, &local_error)) - { - g_propagate_prefixed_error (error, - g_steal_pointer (&local_error), - "Could not get session ID: "); - return NULL; - } - - proxy_path = get_escaped_dbus_path ("/org/freedesktop/login1/session", session_id); - - flags = G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START; - session_proxy = - meta_dbus_login1_session_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - flags, - "org.freedesktop.login1", - proxy_path, - cancellable, error); - if (!session_proxy) - g_prefix_error(error, "Could not get session proxy: "); - - return session_proxy; -} - -static MetaDbusLogin1Seat * -get_seat_proxy (gchar *seat_id, - GCancellable *cancellable, - GError **error) -{ - g_autofree char *seat_proxy_path = get_escaped_dbus_path ("/org/freedesktop/login1/seat", seat_id); - GDBusProxyFlags flags; - MetaDbusLogin1Seat *seat; - - flags = G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START; - seat = - meta_dbus_login1_seat_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - flags, - "org.freedesktop.login1", - seat_proxy_path, - cancellable, error); - if (!seat) - g_prefix_error(error, "Could not get seat proxy: "); - - return seat; -} - -static void -sync_active (MetaLauncher *self) -{ - MetaBackend *backend = meta_get_backend (); - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - MetaDbusLogin1Session *session_proxy = self->session_proxy; - gboolean active; - - active = meta_dbus_login1_session_get_active (session_proxy); - if (active == self->session_active) - return; - - self->session_active = active; - - if (active) - meta_backend_native_resume (backend_native); - else - meta_backend_native_pause (backend_native); -} - -static void -on_active_changed (MetaDbusLogin1Session *session, - GParamSpec *pspec, - gpointer user_data) -{ - MetaLauncher *self = user_data; - sync_active (self); -} - -static gchar * -get_seat_id (GError **error) -{ - g_autoptr (GError) local_error = NULL; - g_autofree char *session_id = NULL; - char *seat_id = NULL; - int r; - - if (!find_systemd_session (&session_id, &local_error)) - { - g_propagate_prefixed_error (error, - g_steal_pointer (&local_error), - "Could not get session ID: "); - return NULL; - } - - r = sd_session_get_seat (session_id, &seat_id); - if (r < 0) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - "Could not get seat for session: %s", g_strerror (-r)); - return NULL; - } - - return seat_id; -} - -MetaDbusLogin1Session * -meta_launcher_get_session_proxy (MetaLauncher *launcher) -{ - return launcher->session_proxy; -} - -MetaLauncher * -meta_launcher_new (GError **error) -{ - MetaLauncher *self = NULL; - g_autoptr (MetaDbusLogin1Session) session_proxy = NULL; - g_autoptr (MetaDbusLogin1Seat) seat_proxy = NULL; - g_autofree char *seat_id = NULL; - gboolean have_control = FALSE; - - session_proxy = get_session_proxy (NULL, error); - if (!session_proxy) - goto fail; - - if (!meta_dbus_login1_session_call_take_control_sync (session_proxy, - FALSE, - NULL, - error)) - { - g_prefix_error (error, "Could not take control: "); - goto fail; - } - - have_control = TRUE; - - seat_id = get_seat_id (error); - if (!seat_id) - goto fail; - - seat_proxy = get_seat_proxy (seat_id, NULL, error); - if (!seat_proxy) - goto fail; - - self = g_new0 (MetaLauncher, 1); - self->session_proxy = g_object_ref (session_proxy); - self->seat_proxy = g_object_ref (seat_proxy); - self->seat_id = g_steal_pointer (&seat_id); - self->session_active = TRUE; - - g_signal_connect (self->session_proxy, "notify::active", G_CALLBACK (on_active_changed), self); - - return self; - - fail: - if (have_control) - { - meta_dbus_login1_session_call_release_control_sync (session_proxy, - NULL, NULL); - } - return NULL; -} - -void -meta_launcher_free (MetaLauncher *self) -{ - g_free (self->seat_id); - g_object_unref (self->seat_proxy); - g_object_unref (self->session_proxy); - g_free (self); -} - -gboolean -meta_launcher_activate_vt (MetaLauncher *launcher, - signed char vt, - GError **error) -{ - return meta_dbus_login1_seat_call_switch_to_sync (launcher->seat_proxy, vt, - NULL, error); -} diff --git a/src/backends/native/meta-launcher.h b/src/backends/native/meta-launcher.h deleted file mode 100644 index 267b68337..000000000 --- a/src/backends/native/meta-launcher.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2013 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_LAUNCHER_H -#define META_LAUNCHER_H - -#include - -typedef struct _MetaLauncher MetaLauncher; -typedef struct _MetaDbusLogin1Session MetaDbusLogin1Session; - -MetaLauncher *meta_launcher_new (GError **error); -void meta_launcher_free (MetaLauncher *self); - -gboolean meta_launcher_activate_vt (MetaLauncher *self, - signed char vt, - GError **error); - -const char * meta_launcher_get_seat_id (MetaLauncher *launcher); - -MetaDbusLogin1Session * meta_launcher_get_session_proxy (MetaLauncher *launcher); - - -#endif /* META_LAUNCHER_H */ diff --git a/src/backends/native/meta-monitor-manager-native.c b/src/backends/native/meta-monitor-manager-native.c deleted file mode 100644 index fd5e7784f..000000000 --- a/src/backends/native/meta-monitor-manager-native.c +++ /dev/null @@ -1,825 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2013 Red Hat Inc. - * Copyright (C) 2018 DisplayLink (UK) Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Author: Giovanni Campagna - */ - -/** - * SECTION:meta-monitor-manager-native - * @title: MetaMonitorManagerNative - * @short_description: A subclass of #MetaMonitorManager using Linux DRM - * - * #MetaMonitorManagerNative is a subclass of #MetaMonitorManager which - * implements its functionality "natively": it uses the appropriate - * functions of the Linux DRM kernel module and using a udev client. - * - * See also #MetaMonitorManagerXrandr for an implementation using XRandR. - */ - -#include "config.h" - -#include "backends/native/meta-monitor-manager-native.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-crtc.h" -#include "backends/meta-monitor-config-manager.h" -#include "backends/meta-output.h" -#include "backends/native/meta-backend-native.h" -#include "backends/native/meta-crtc-kms.h" -#include "backends/native/meta-gpu-kms.h" -#include "backends/native/meta-kms-update.h" -#include "backends/native/meta-kms.h" -#include "backends/native/meta-launcher.h" -#include "backends/native/meta-output-kms.h" -#include "backends/native/meta-renderer-native.h" -#include "backends/native/meta-virtual-monitor-native.h" -#include "clutter/clutter.h" -#include "meta/main.h" -#include "meta/meta-x11-errors.h" - -enum -{ - PROP_0, - - PROP_NEED_OUTPUTS, - - N_PROPS -}; - -static GParamSpec *obj_props[N_PROPS]; - -struct _MetaMonitorManagerNative -{ - MetaMonitorManager parent_instance; - - gulong kms_resources_changed_handler_id; - - GHashTable *crtc_gamma_cache; - - gboolean needs_outputs; -}; - -struct _MetaMonitorManagerNativeClass -{ - MetaMonitorManagerClass parent_class; -}; - -#define VIRTUAL_OUTPUT_ID_BIT (((uint64_t) 1) << 63) - -static void -initable_iface_init (GInitableIface *initable_iface); - -G_DEFINE_TYPE_WITH_CODE (MetaMonitorManagerNative, meta_monitor_manager_native, - META_TYPE_MONITOR_MANAGER, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - initable_iface_init)) - -static GBytes * -meta_monitor_manager_native_read_edid (MetaMonitorManager *manager, - MetaOutput *output) -{ - return meta_output_native_read_edid (META_OUTPUT_NATIVE (output)); -} - -static void -meta_monitor_manager_native_read_current_state (MetaMonitorManager *manager) -{ - MetaMonitorManagerClass *parent_class = - META_MONITOR_MANAGER_CLASS (meta_monitor_manager_native_parent_class); - MetaPowerSave power_save_mode; - - power_save_mode = meta_monitor_manager_get_power_save_mode (manager); - if (power_save_mode != META_POWER_SAVE_ON) - meta_monitor_manager_power_save_mode_changed (manager, - META_POWER_SAVE_ON); - - parent_class->read_current_state (manager); -} - -uint64_t -meta_power_save_to_dpms_state (MetaPowerSave power_save) -{ - switch (power_save) - { - case META_POWER_SAVE_ON: - return DRM_MODE_DPMS_ON; - case META_POWER_SAVE_STANDBY: - return DRM_MODE_DPMS_STANDBY; - case META_POWER_SAVE_SUSPEND: - return DRM_MODE_DPMS_SUSPEND; - case META_POWER_SAVE_OFF: - return DRM_MODE_DPMS_OFF; - case META_POWER_SAVE_UNSUPPORTED: - return DRM_MODE_DPMS_ON; - } - - g_warn_if_reached (); - return DRM_MODE_DPMS_ON; -} - -static void -meta_monitor_manager_native_set_power_save_mode (MetaMonitorManager *manager, - MetaPowerSave mode) -{ - MetaBackend *backend = meta_monitor_manager_get_backend (manager); - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - MetaKms *kms = meta_backend_native_get_kms (backend_native); - GList *l; - - for (l = meta_backend_get_gpus (backend); l; l = l->next) - { - MetaGpuKms *gpu_kms = l->data; - - switch (mode) - { - case META_POWER_SAVE_ON: - case META_POWER_SAVE_UNSUPPORTED: - { - g_list_foreach (meta_gpu_get_crtcs (META_GPU (gpu_kms)), - (GFunc) meta_crtc_kms_invalidate_gamma, - NULL); - break; - } - case META_POWER_SAVE_STANDBY: - case META_POWER_SAVE_SUSPEND: - case META_POWER_SAVE_OFF: - { - MetaKmsDevice *kms_device = meta_gpu_kms_get_kms_device (gpu_kms); - MetaKmsUpdate *kms_update; - MetaKmsUpdateFlag flags; - g_autoptr (MetaKmsFeedback) kms_feedback = NULL; - - kms_update = meta_kms_ensure_pending_update (kms, kms_device); - meta_kms_update_set_power_save (kms_update); - - flags = META_KMS_UPDATE_FLAG_NONE; - kms_feedback = meta_kms_post_pending_update_sync (kms, - kms_device, - flags); - if (meta_kms_feedback_get_result (kms_feedback) != - META_KMS_FEEDBACK_PASSED) - { - g_warning ("Failed to enter power saving mode: %s", - meta_kms_feedback_get_error (kms_feedback)->message); - } - break; - } - } - } -} - -static void -meta_monitor_manager_native_ensure_initial_config (MetaMonitorManager *manager) -{ - MetaMonitorsConfig *config; - - config = meta_monitor_manager_ensure_configured (manager); - - meta_monitor_manager_update_logical_state (manager, config); -} - -static void -apply_crtc_assignments (MetaMonitorManager *manager, - MetaCrtcAssignment **crtcs, - unsigned int n_crtcs, - MetaOutputAssignment **outputs, - unsigned int n_outputs) -{ - MetaBackend *backend = meta_monitor_manager_get_backend (manager); - g_autoptr (GList) to_configure_outputs = NULL; - g_autoptr (GList) to_configure_crtcs = NULL; - unsigned i; - GList *gpus; - GList *l; - - gpus = meta_backend_get_gpus (backend); - for (l = gpus; l; l = l->next) - { - MetaGpu *gpu = l->data; - GList *crtcs; - GList *outputs; - - outputs = g_list_copy (meta_gpu_get_outputs (gpu)); - to_configure_outputs = g_list_concat (to_configure_outputs, outputs); - - crtcs = g_list_copy (meta_gpu_get_crtcs (gpu)); - to_configure_crtcs = g_list_concat (to_configure_crtcs, crtcs); - } - - for (l = meta_monitor_manager_get_virtual_monitors (manager); l; l = l->next) - { - MetaVirtualMonitor *virtual_monitor = l->data; - MetaOutput *output = meta_virtual_monitor_get_output (virtual_monitor); - MetaCrtc *crtc = meta_virtual_monitor_get_crtc (virtual_monitor); - - to_configure_outputs = g_list_append (to_configure_outputs, output); - to_configure_crtcs = g_list_append (to_configure_crtcs, crtc); - } - - for (i = 0; i < n_crtcs; i++) - { - MetaCrtcAssignment *crtc_assignment = crtcs[i]; - MetaCrtc *crtc = crtc_assignment->crtc; - - to_configure_crtcs = g_list_remove (to_configure_crtcs, crtc); - - if (crtc_assignment->mode == NULL) - { - meta_crtc_unset_config (crtc); - } - else - { - unsigned int j; - - meta_crtc_set_config (crtc, - &crtc_assignment->layout, - crtc_assignment->mode, - crtc_assignment->transform); - - for (j = 0; j < crtc_assignment->outputs->len; j++) - { - MetaOutput *output = g_ptr_array_index (crtc_assignment->outputs, - j); - MetaOutputAssignment *output_assignment; - - to_configure_outputs = g_list_remove (to_configure_outputs, - output); - - output_assignment = meta_find_output_assignment (outputs, - n_outputs, - output); - meta_output_assign_crtc (output, crtc, output_assignment); - } - } - } - - g_list_foreach (to_configure_crtcs, - (GFunc) meta_crtc_unset_config, - NULL); - g_list_foreach (to_configure_outputs, - (GFunc) meta_output_unassign_crtc, - NULL); -} - -static void -update_screen_size (MetaMonitorManager *manager, - MetaMonitorsConfig *config) -{ - GList *l; - int screen_width = 0; - int screen_height = 0; - - for (l = config->logical_monitor_configs; l; l = l->next) - { - MetaLogicalMonitorConfig *logical_monitor_config = l->data; - int right_edge; - int bottom_edge; - - right_edge = (logical_monitor_config->layout.width + - logical_monitor_config->layout.x); - if (right_edge > screen_width) - screen_width = right_edge; - - bottom_edge = (logical_monitor_config->layout.height + - logical_monitor_config->layout.y); - if (bottom_edge > screen_height) - screen_height = bottom_edge; - } - - manager->screen_width = screen_width; - manager->screen_height = screen_height; -} - -static gboolean -meta_monitor_manager_native_apply_monitors_config (MetaMonitorManager *manager, - MetaMonitorsConfig *config, - MetaMonitorsConfigMethod method, - GError **error) -{ - GPtrArray *crtc_assignments; - GPtrArray *output_assignments; - - if (!config) - { - if (!manager->in_init) - { - MetaBackend *backend = meta_get_backend (); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - - meta_renderer_native_reset_modes (META_RENDERER_NATIVE (renderer)); - } - - manager->screen_width = META_MONITOR_MANAGER_MIN_SCREEN_WIDTH; - manager->screen_height = META_MONITOR_MANAGER_MIN_SCREEN_HEIGHT; - meta_monitor_manager_rebuild (manager, NULL); - return TRUE; - } - - if (!meta_monitor_config_manager_assign (manager, config, - &crtc_assignments, - &output_assignments, - error)) - return FALSE; - - if (method == META_MONITORS_CONFIG_METHOD_VERIFY) - { - g_ptr_array_free (crtc_assignments, TRUE); - g_ptr_array_free (output_assignments, TRUE); - return TRUE; - } - - apply_crtc_assignments (manager, - (MetaCrtcAssignment **) crtc_assignments->pdata, - crtc_assignments->len, - (MetaOutputAssignment **) output_assignments->pdata, - output_assignments->len); - - g_ptr_array_free (crtc_assignments, TRUE); - g_ptr_array_free (output_assignments, TRUE); - - update_screen_size (manager, config); - meta_monitor_manager_rebuild (manager, config); - - return TRUE; -} - -static void -meta_monitor_manager_native_get_crtc_gamma (MetaMonitorManager *manager, - MetaCrtc *crtc, - gsize *size, - unsigned short **red, - unsigned short **green, - unsigned short **blue) -{ - MetaKmsCrtc *kms_crtc; - const MetaKmsCrtcState *crtc_state; - - g_return_if_fail (META_IS_CRTC_KMS (crtc)); - - kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc)); - crtc_state = meta_kms_crtc_get_current_state (kms_crtc); - - *size = crtc_state->gamma.size; - *red = g_memdup2 (crtc_state->gamma.red, *size * sizeof **red); - *green = g_memdup2 (crtc_state->gamma.green, *size * sizeof **green); - *blue = g_memdup2 (crtc_state->gamma.blue, *size * sizeof **blue); -} - -static char * -generate_gamma_ramp_string (size_t size, - unsigned short *red, - unsigned short *green, - unsigned short *blue) -{ - GString *string; - int color; - - string = g_string_new ("["); - for (color = 0; color < 3; color++) - { - unsigned short **color_ptr = NULL; - char color_char; - size_t i; - - switch (color) - { - case 0: - color_ptr = &red; - color_char = 'r'; - break; - case 1: - color_ptr = &green; - color_char = 'g'; - break; - case 2: - color_ptr = &blue; - color_char = 'b'; - break; - } - - g_assert (color_ptr); - g_string_append_printf (string, " %c: ", color_char); - for (i = 0; i < MIN (4, size); i++) - { - int j; - - if (size > 4) - { - if (i == 2) - g_string_append (string, ",..."); - - if (i >= 2) - j = i + (size - 4); - else - j = i; - } - else - { - j = i; - } - g_string_append_printf (string, "%s%hu", - j == 0 ? "" : ",", - (*color_ptr)[i]); - } - } - - g_string_append (string, " ]"); - - return g_string_free (string, FALSE); -} - -MetaKmsCrtcGamma * -meta_monitor_manager_native_get_cached_crtc_gamma (MetaMonitorManagerNative *manager_native, - MetaCrtcKms *crtc_kms) -{ - uint64_t crtc_id; - - crtc_id = meta_crtc_get_id (META_CRTC (crtc_kms)); - return g_hash_table_lookup (manager_native->crtc_gamma_cache, - GUINT_TO_POINTER (crtc_id)); -} - -static void -meta_monitor_manager_native_set_crtc_gamma (MetaMonitorManager *manager, - MetaCrtc *crtc, - gsize size, - unsigned short *red, - unsigned short *green, - unsigned short *blue) -{ - MetaMonitorManagerNative *manager_native = - META_MONITOR_MANAGER_NATIVE (manager); - MetaCrtcKms *crtc_kms; - MetaKmsCrtc *kms_crtc; - g_autofree char *gamma_ramp_string = NULL; - MetaBackend *backend = meta_monitor_manager_get_backend (manager); - ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend)); - - g_return_if_fail (META_IS_CRTC_KMS (crtc)); - - crtc_kms = META_CRTC_KMS (crtc); - kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc)); - - g_hash_table_replace (manager_native->crtc_gamma_cache, - GUINT_TO_POINTER (meta_crtc_get_id (crtc)), - meta_kms_crtc_gamma_new (kms_crtc, size, - red, green, blue)); - - gamma_ramp_string = generate_gamma_ramp_string (size, red, green, blue); - g_debug ("Setting CRTC (%" G_GUINT64_FORMAT ") gamma to %s", - meta_crtc_get_id (crtc), gamma_ramp_string); - - meta_crtc_kms_invalidate_gamma (crtc_kms); - clutter_stage_schedule_update (stage); -} - -static void -handle_hotplug_event (MetaMonitorManager *manager) -{ - meta_monitor_manager_reload (manager); -} - -static void -on_kms_resources_changed (MetaKms *kms, - MetaMonitorManager *manager) -{ - handle_hotplug_event (manager); -} - -static void -meta_monitor_manager_native_connect_hotplug_handler (MetaMonitorManagerNative *manager_native) -{ - MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_native); - MetaBackend *backend = meta_monitor_manager_get_backend (manager); - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - MetaKms *kms = meta_backend_native_get_kms (backend_native); - - manager_native->kms_resources_changed_handler_id = - g_signal_connect (kms, "resources-changed", - G_CALLBACK (on_kms_resources_changed), manager); -} - -static void -meta_monitor_manager_native_disconnect_hotplug_handler (MetaMonitorManagerNative *manager_native) -{ - MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_native); - MetaBackend *backend = meta_monitor_manager_get_backend (manager); - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - MetaKms *kms = meta_backend_native_get_kms (backend_native); - - g_clear_signal_handler (&manager_native->kms_resources_changed_handler_id, kms); -} - -void -meta_monitor_manager_native_pause (MetaMonitorManagerNative *manager_native) -{ - meta_monitor_manager_native_disconnect_hotplug_handler (manager_native); -} - -void -meta_monitor_manager_native_resume (MetaMonitorManagerNative *manager_native) -{ - MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_native); - MetaBackend *backend = meta_monitor_manager_get_backend (manager); - GList *l; - - meta_monitor_manager_native_connect_hotplug_handler (manager_native); - - for (l = meta_backend_get_gpus (backend); l; l = l->next) - { - MetaGpu *gpu = l->data; - - g_list_foreach (meta_gpu_get_crtcs (gpu), - (GFunc) meta_crtc_kms_invalidate_gamma, - NULL); - } -} - -static gboolean -meta_monitor_manager_native_is_transform_handled (MetaMonitorManager *manager, - MetaCrtc *crtc, - MetaMonitorTransform transform) -{ - return meta_crtc_native_is_transform_handled (META_CRTC_NATIVE (crtc), - transform); -} - -static float -meta_monitor_manager_native_calculate_monitor_mode_scale (MetaMonitorManager *manager, - MetaMonitor *monitor, - MetaMonitorMode *monitor_mode) -{ - return meta_monitor_calculate_mode_scale (monitor, monitor_mode); -} - -static float * -meta_monitor_manager_native_calculate_supported_scales (MetaMonitorManager *manager, - MetaLogicalMonitorLayoutMode layout_mode, - MetaMonitor *monitor, - MetaMonitorMode *monitor_mode, - int *n_supported_scales) -{ - MetaMonitorScalesConstraint constraints = - META_MONITOR_SCALES_CONSTRAINT_NONE; - - switch (layout_mode) - { - case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL: - break; - case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL: - constraints |= META_MONITOR_SCALES_CONSTRAINT_NO_FRAC; - break; - } - - return meta_monitor_calculate_supported_scales (monitor, monitor_mode, - constraints, - n_supported_scales); -} - -static MetaMonitorManagerCapability -meta_monitor_manager_native_get_capabilities (MetaMonitorManager *manager) -{ - MetaBackend *backend = meta_monitor_manager_get_backend (manager); - MetaSettings *settings = meta_backend_get_settings (backend); - MetaMonitorManagerCapability capabilities = - META_MONITOR_MANAGER_CAPABILITY_NONE; - - if (meta_settings_is_experimental_feature_enabled ( - settings, - META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER)) - capabilities |= META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE; - - return capabilities; -} - -static gboolean -meta_monitor_manager_native_get_max_screen_size (MetaMonitorManager *manager, - int *max_width, - int *max_height) -{ - return FALSE; -} - -static MetaLogicalMonitorLayoutMode -meta_monitor_manager_native_get_default_layout_mode (MetaMonitorManager *manager) -{ - MetaBackend *backend = meta_monitor_manager_get_backend (manager); - MetaSettings *settings = meta_backend_get_settings (backend); - - if (meta_settings_is_experimental_feature_enabled ( - settings, - META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER)) - return META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL; - else - return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL; -} - -static MetaVirtualMonitorNative * -find_virtual_monitor (MetaMonitorManagerNative *manager_native, - uint64_t id) -{ - MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_native); - GList *l; - - for (l = meta_monitor_manager_get_virtual_monitors (manager); l; l = l->next) - { - MetaVirtualMonitorNative *virtual_monitor_native = l->data; - - if (meta_virtual_monitor_native_get_id (virtual_monitor_native) == id) - return virtual_monitor_native; - } - - return NULL; -} - -static uint64_t -allocate_virtual_monitor_id (MetaMonitorManagerNative *manager_native) -{ - uint64_t id; - - id = 0; - - while (TRUE) - { - if (!find_virtual_monitor (manager_native, id)) - return id; - - id++; - } -} - -static MetaVirtualMonitor * -meta_monitor_manager_native_create_virtual_monitor (MetaMonitorManager *manager, - const MetaVirtualMonitorInfo *info, - GError **error) -{ - MetaMonitorManagerNative *manager_native = - META_MONITOR_MANAGER_NATIVE (manager); - MetaVirtualMonitorNative *virtual_monitor_native; - uint64_t id; - - id = allocate_virtual_monitor_id (manager_native); - virtual_monitor_native = meta_virtual_monitor_native_new (id, info); - return META_VIRTUAL_MONITOR (virtual_monitor_native); -} - -static void -meta_monitor_manager_native_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaMonitorManagerNative *manager_native = - META_MONITOR_MANAGER_NATIVE (object); - - switch (prop_id) - { - case PROP_NEED_OUTPUTS: - manager_native->needs_outputs = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_monitor_manager_native_dispose (GObject *object) -{ - MetaMonitorManagerNative *manager_native = - META_MONITOR_MANAGER_NATIVE (object); - - g_clear_pointer (&manager_native->crtc_gamma_cache, - g_hash_table_unref); - - G_OBJECT_CLASS (meta_monitor_manager_native_parent_class)->dispose (object); -} - -static gboolean -meta_monitor_manager_native_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - MetaMonitorManagerNative *manager_native = - META_MONITOR_MANAGER_NATIVE (initable); - MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_native); - MetaBackend *backend = meta_monitor_manager_get_backend (manager); - gboolean can_have_outputs; - GList *l; - - meta_monitor_manager_native_connect_hotplug_handler (manager_native); - - can_have_outputs = FALSE; - for (l = meta_backend_get_gpus (backend); l; l = l->next) - { - MetaGpuKms *gpu_kms = l->data; - - if (meta_gpu_kms_can_have_outputs (gpu_kms)) - { - can_have_outputs = TRUE; - break; - } - } - - if (manager_native->needs_outputs && !can_have_outputs) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, - "No GPUs with outputs found"); - return FALSE; - } - - manager_native->crtc_gamma_cache = - g_hash_table_new_full (NULL, NULL, - NULL, - (GDestroyNotify) meta_kms_crtc_gamma_free); - - return TRUE; -} - -static void -initable_iface_init (GInitableIface *initable_iface) -{ - initable_iface->init = meta_monitor_manager_native_initable_init; -} - -static void -meta_monitor_manager_native_init (MetaMonitorManagerNative *manager_native) -{ - manager_native->needs_outputs = TRUE; -} - -static void -meta_monitor_manager_native_class_init (MetaMonitorManagerNativeClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass); - - object_class->set_property = meta_monitor_manager_native_set_property; - object_class->dispose = meta_monitor_manager_native_dispose; - - manager_class->read_edid = - meta_monitor_manager_native_read_edid; - manager_class->read_current_state = - meta_monitor_manager_native_read_current_state; - manager_class->ensure_initial_config = - meta_monitor_manager_native_ensure_initial_config; - manager_class->apply_monitors_config = - meta_monitor_manager_native_apply_monitors_config; - manager_class->set_power_save_mode = - meta_monitor_manager_native_set_power_save_mode; - manager_class->get_crtc_gamma = - meta_monitor_manager_native_get_crtc_gamma; - manager_class->set_crtc_gamma = - meta_monitor_manager_native_set_crtc_gamma; - manager_class->is_transform_handled = - meta_monitor_manager_native_is_transform_handled; - manager_class->calculate_monitor_mode_scale = - meta_monitor_manager_native_calculate_monitor_mode_scale; - manager_class->calculate_supported_scales = - meta_monitor_manager_native_calculate_supported_scales; - manager_class->get_capabilities = - meta_monitor_manager_native_get_capabilities; - manager_class->get_max_screen_size = - meta_monitor_manager_native_get_max_screen_size; - manager_class->get_default_layout_mode = - meta_monitor_manager_native_get_default_layout_mode; - manager_class->create_virtual_monitor = - meta_monitor_manager_native_create_virtual_monitor; - - obj_props[PROP_NEED_OUTPUTS] = - g_param_spec_boolean ("needs-outputs", - "needs-outputs", - "Whether any outputs are needed for operation", - TRUE, - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, N_PROPS, obj_props); -} diff --git a/src/backends/native/meta-monitor-manager-native.h b/src/backends/native/meta-monitor-manager-native.h deleted file mode 100644 index 60f899734..000000000 --- a/src/backends/native/meta-monitor-manager-native.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * Copyright (C) 2013 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#ifndef META_MONITOR_MANAGER_NATIVE_H -#define META_MONITOR_MANAGER_NATIVE_H - -#include -#include - -#include "backends/meta-monitor-manager-private.h" -#include "backends/native/meta-crtc-kms.h" -#include "backends/native/meta-kms-crtc.h" - -typedef struct _MetaGpuKms MetaGpuKms; - -#define META_TYPE_MONITOR_MANAGER_NATIVE (meta_monitor_manager_native_get_type ()) -G_DECLARE_FINAL_TYPE (MetaMonitorManagerNative, meta_monitor_manager_native, - META, MONITOR_MANAGER_NATIVE, - MetaMonitorManager) - -void meta_monitor_manager_native_pause (MetaMonitorManagerNative *manager_native); - -void meta_monitor_manager_native_resume (MetaMonitorManagerNative *manager_native); - -uint64_t meta_power_save_to_dpms_state (MetaPowerSave power_save); - -MetaKmsCrtcGamma * meta_monitor_manager_native_get_cached_crtc_gamma (MetaMonitorManagerNative *manager_native, - MetaCrtcKms *crtc_kms); - -#endif /* META_MONITOR_MANAGER_NATIVE_H */ diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c deleted file mode 100644 index 77e5309e1..000000000 --- a/src/backends/native/meta-onscreen-native.c +++ /dev/null @@ -1,2137 +0,0 @@ -/* - * Copyright (C) 2011 Intel Corporation. - * Copyright (C) 2016-2020 Red Hat - * Copyright (c) 2018,2019 DisplayLink (UK) Ltd. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#include "config.h" - -#include "backends/native/meta-onscreen-native.h" - -#include - -#include "backends/meta-egl-ext.h" -#include "backends/native/meta-cogl-utils.h" -#include "backends/native/meta-crtc-kms.h" -#include "backends/native/meta-device-pool.h" -#include "backends/native/meta-drm-buffer-dumb.h" -#include "backends/native/meta-drm-buffer-gbm.h" -#include "backends/native/meta-drm-buffer-import.h" -#include "backends/native/meta-drm-buffer.h" -#include "backends/native/meta-kms-device.h" -#include "backends/native/meta-kms-utils.h" -#include "backends/native/meta-kms.h" -#include "backends/native/meta-output-kms.h" -#include "backends/native/meta-renderer-native-gles3.h" -#include "backends/native/meta-renderer-native-private.h" - -typedef enum _MetaSharedFramebufferImportStatus -{ - /* Not tried importing yet. */ - META_SHARED_FRAMEBUFFER_IMPORT_STATUS_NONE, - /* Tried before and failed. */ - META_SHARED_FRAMEBUFFER_IMPORT_STATUS_FAILED, - /* Tried before and succeeded. */ - META_SHARED_FRAMEBUFFER_IMPORT_STATUS_OK -} MetaSharedFramebufferImportStatus; - -typedef struct _MetaOnscreenNativeSecondaryGpuState -{ - MetaGpuKms *gpu_kms; - MetaRendererNativeGpuData *renderer_gpu_data; - - EGLSurface egl_surface; - - struct { - struct gbm_surface *surface; - MetaDrmBuffer *current_fb; - MetaDrmBuffer *next_fb; - } gbm; - - struct { - MetaDrmBufferDumb *current_dumb_fb; - MetaDrmBufferDumb *dumb_fbs[2]; - } cpu; - - gboolean noted_primary_gpu_copy_ok; - gboolean noted_primary_gpu_copy_failed; - MetaSharedFramebufferImportStatus import_status; -} MetaOnscreenNativeSecondaryGpuState; - -struct _MetaOnscreenNative -{ - CoglOnscreenEgl parent; - - MetaRendererNative *renderer_native; - MetaGpuKms *render_gpu; - MetaOutput *output; - MetaCrtc *crtc; - - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state; - - struct { - struct gbm_surface *surface; - MetaDrmBuffer *current_fb; - MetaDrmBuffer *next_fb; - } gbm; - -#ifdef HAVE_EGL_DEVICE - struct { - EGLStreamKHR stream; - - MetaDrmBufferDumb *dumb_fb; - } egl; -#endif - - MetaRendererView *view; -}; - -G_DEFINE_TYPE (MetaOnscreenNative, meta_onscreen_native, - COGL_TYPE_ONSCREEN_EGL) - -static gboolean -init_secondary_gpu_state (MetaRendererNative *renderer_native, - CoglOnscreen *onscreen, - GError **error); - -static void -swap_secondary_drm_fb (CoglOnscreen *onscreen) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state; - - secondary_gpu_state = onscreen_native->secondary_gpu_state; - if (!secondary_gpu_state) - return; - - g_set_object (&secondary_gpu_state->gbm.current_fb, - secondary_gpu_state->gbm.next_fb); - g_clear_object (&secondary_gpu_state->gbm.next_fb); -} - -static void -free_current_secondary_bo (CoglOnscreen *onscreen) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state; - - secondary_gpu_state = onscreen_native->secondary_gpu_state; - if (!secondary_gpu_state) - return; - - g_clear_object (&secondary_gpu_state->gbm.current_fb); -} - -static void -free_current_bo (CoglOnscreen *onscreen) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - - g_clear_object (&onscreen_native->gbm.current_fb); - free_current_secondary_bo (onscreen); -} - -static void -meta_onscreen_native_swap_drm_fb (CoglOnscreen *onscreen) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - - if (!onscreen_native->gbm.next_fb) - return; - - free_current_bo (onscreen); - - g_set_object (&onscreen_native->gbm.current_fb, onscreen_native->gbm.next_fb); - g_clear_object (&onscreen_native->gbm.next_fb); - - swap_secondary_drm_fb (onscreen); -} - -static void -maybe_update_frame_info (MetaCrtc *crtc, - CoglFrameInfo *frame_info, - int64_t time_us, - CoglFrameInfoFlag flags, - unsigned int sequence) -{ - const MetaCrtcConfig *crtc_config; - const MetaCrtcModeInfo *crtc_mode_info; - float refresh_rate; - - g_return_if_fail (crtc); - - crtc_config = meta_crtc_get_config (crtc); - if (!crtc_config) - return; - - crtc_mode_info = meta_crtc_mode_get_info (crtc_config->mode); - refresh_rate = crtc_mode_info->refresh_rate; - if (refresh_rate >= frame_info->refresh_rate) - { - frame_info->presentation_time_us = time_us; - frame_info->refresh_rate = refresh_rate; - frame_info->flags |= flags; - frame_info->sequence = sequence; - } -} - -static void -meta_onscreen_native_notify_frame_complete (CoglOnscreen *onscreen) -{ - CoglFrameInfo *info; - - info = cogl_onscreen_pop_head_frame_info (onscreen); - - g_assert (!cogl_onscreen_peek_head_frame_info (onscreen)); - - _cogl_onscreen_notify_frame_sync (onscreen, info); - _cogl_onscreen_notify_complete (onscreen, info); - cogl_object_unref (info); -} - -static void -notify_view_crtc_presented (MetaRendererView *view, - MetaKmsCrtc *kms_crtc, - int64_t time_us, - CoglFrameInfoFlag flags, - unsigned int sequence) -{ - ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (view); - CoglFramebuffer *framebuffer = - clutter_stage_view_get_onscreen (stage_view); - CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); - CoglFrameInfo *frame_info; - MetaCrtc *crtc; - - frame_info = cogl_onscreen_peek_head_frame_info (onscreen); - - crtc = META_CRTC (meta_crtc_kms_from_kms_crtc (kms_crtc)); - maybe_update_frame_info (crtc, frame_info, time_us, flags, sequence); - - meta_onscreen_native_notify_frame_complete (onscreen); - meta_onscreen_native_swap_drm_fb (onscreen); -} - -static int64_t -timeval_to_microseconds (const struct timeval *tv) -{ - return ((int64_t) tv->tv_sec) * G_USEC_PER_SEC + tv->tv_usec; -} - -static void -page_flip_feedback_flipped (MetaKmsCrtc *kms_crtc, - unsigned int sequence, - unsigned int tv_sec, - unsigned int tv_usec, - gpointer user_data) -{ - MetaRendererView *view = user_data; - struct timeval page_flip_time; - MetaKmsDevice *kms_device; - int64_t presentation_time_us; - CoglFrameInfoFlag flags = COGL_FRAME_INFO_FLAG_VSYNC; - - page_flip_time = (struct timeval) { - .tv_sec = tv_sec, - .tv_usec = tv_usec, - }; - - kms_device = meta_kms_crtc_get_device (kms_crtc); - if (meta_kms_device_uses_monotonic_clock (kms_device)) - { - presentation_time_us = timeval_to_microseconds (&page_flip_time); - flags |= COGL_FRAME_INFO_FLAG_HW_CLOCK; - } - else - { - /* - * Other parts of the code assume MONOTONIC timestamps. So, if the device - * timestamp isn't MONOTONIC, don't use it. - */ - presentation_time_us = g_get_monotonic_time (); - } - - notify_view_crtc_presented (view, kms_crtc, - presentation_time_us, - flags, - sequence); -} - -static void -page_flip_feedback_ready (MetaKmsCrtc *kms_crtc, - gpointer user_data) -{ - MetaRendererView *view = user_data; - CoglFramebuffer *framebuffer = - clutter_stage_view_get_onscreen (CLUTTER_STAGE_VIEW (view)); - CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); - CoglFrameInfo *frame_info; - - frame_info = cogl_onscreen_peek_head_frame_info (onscreen); - frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; - - meta_onscreen_native_notify_frame_complete (onscreen); -} - -static void -page_flip_feedback_mode_set_fallback (MetaKmsCrtc *kms_crtc, - gpointer user_data) -{ - MetaRendererView *view = user_data; - int64_t now_us; - - /* - * We ended up not page flipping, thus we don't have a presentation time to - * use. Lets use the next best thing: the current time. - */ - - now_us = g_get_monotonic_time (); - - notify_view_crtc_presented (view, - kms_crtc, - now_us, - COGL_FRAME_INFO_FLAG_NONE, - 0); -} - -static void -page_flip_feedback_discarded (MetaKmsCrtc *kms_crtc, - gpointer user_data, - const GError *error) -{ - MetaRendererView *view = user_data; - CoglFramebuffer *framebuffer = - clutter_stage_view_get_onscreen (CLUTTER_STAGE_VIEW (view)); - CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); - CoglFrameInfo *frame_info; - - /* - * Page flipping failed, but we want to fail gracefully, so to avoid freezing - * the frame clock, emit a symbolic flip. - */ - - if (error && - !g_error_matches (error, - G_IO_ERROR, - G_IO_ERROR_PERMISSION_DENIED)) - g_warning ("Page flip discarded: %s", error->message); - - frame_info = cogl_onscreen_peek_head_frame_info (onscreen); - frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; - - meta_onscreen_native_notify_frame_complete (onscreen); - meta_onscreen_native_swap_drm_fb (onscreen); -} - -static const MetaKmsPageFlipListenerVtable page_flip_listener_vtable = { - .flipped = page_flip_feedback_flipped, - .ready = page_flip_feedback_ready, - .mode_set_fallback = page_flip_feedback_mode_set_fallback, - .discarded = page_flip_feedback_discarded, -}; - -static MetaEgl * -meta_onscreen_native_get_egl (MetaOnscreenNative *onscreen_native) -{ - MetaRendererNative *renderer_native = onscreen_native->renderer_native; - - return meta_renderer_native_get_egl (renderer_native); -} - -#ifdef HAVE_EGL_DEVICE -static int -custom_egl_stream_page_flip (gpointer custom_page_flip_data, - gpointer user_data) -{ - CoglOnscreen *onscreen = custom_page_flip_data; - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaRendererView *view = user_data; - MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native); - MetaRendererNativeGpuData *renderer_gpu_data; - EGLDisplay *egl_display; - EGLAttrib *acquire_attribs; - g_autoptr (GError) error = NULL; - - acquire_attribs = (EGLAttrib[]) { - EGL_DRM_FLIP_EVENT_DATA_NV, - (EGLAttrib) view, - EGL_NONE - }; - - renderer_gpu_data = - meta_renderer_native_get_gpu_data (onscreen_native->renderer_native, - onscreen_native->render_gpu); - - egl_display = renderer_gpu_data->egl_display; - if (!meta_egl_stream_consumer_acquire_attrib (egl, - egl_display, - onscreen_native->egl.stream, - acquire_attribs, - &error)) - { - if (g_error_matches (error, META_EGL_ERROR, EGL_RESOURCE_BUSY_EXT)) - return -EBUSY; - else - return -EINVAL; - } - - return 0; -} -#endif /* HAVE_EGL_DEVICE */ - -void -meta_onscreen_native_dummy_power_save_page_flip (CoglOnscreen *onscreen) -{ - CoglFrameInfo *frame_info; - - meta_onscreen_native_swap_drm_fb (onscreen); - - frame_info = cogl_onscreen_peek_tail_frame_info (onscreen); - frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; - meta_onscreen_native_notify_frame_complete (onscreen); -} - -static void -meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, - MetaRendererView *view, - MetaCrtc *crtc, - MetaKmsPageFlipListenerFlag flags) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaRendererNative *renderer_native = onscreen_native->renderer_native; - MetaGpuKms *render_gpu = onscreen_native->render_gpu; - MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc); - MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); - MetaRendererNativeGpuData *renderer_gpu_data; - MetaGpuKms *gpu_kms; - MetaKmsDevice *kms_device; - MetaKms *kms; - MetaKmsUpdate *kms_update; - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state = NULL; - MetaDrmBuffer *buffer; - - COGL_TRACE_BEGIN_SCOPED (MetaOnscreenNativeFlipCrtcs, - "Onscreen (flip CRTCs)"); - - gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc)); - kms_device = meta_gpu_kms_get_kms_device (gpu_kms); - kms = meta_kms_device_get_kms (kms_device); - kms_update = meta_kms_ensure_pending_update (kms, kms_device); - - g_assert (meta_gpu_kms_is_crtc_active (gpu_kms, crtc)); - - renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, - render_gpu); - switch (renderer_gpu_data->mode) - { - case META_RENDERER_NATIVE_MODE_GBM: - if (gpu_kms == render_gpu) - { - buffer = onscreen_native->gbm.next_fb; - } - else - { - secondary_gpu_state = onscreen_native->secondary_gpu_state; - buffer = secondary_gpu_state->gbm.next_fb; - } - - meta_crtc_kms_assign_primary_plane (crtc_kms, buffer, kms_update); - - break; - case META_RENDERER_NATIVE_MODE_SURFACELESS: - g_assert_not_reached (); - break; -#ifdef HAVE_EGL_DEVICE - case META_RENDERER_NATIVE_MODE_EGL_DEVICE: - meta_kms_update_set_custom_page_flip (kms_update, - custom_egl_stream_page_flip, - onscreen_native); - break; -#endif - } - - meta_kms_update_add_page_flip_listener (kms_update, - kms_crtc, - &page_flip_listener_vtable, - flags, - g_object_ref (view), - g_object_unref); -} - -static void -meta_onscreen_native_set_crtc_mode (CoglOnscreen *onscreen, - MetaRendererNativeGpuData *renderer_gpu_data) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc); - MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); - MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); - MetaKms *kms = meta_kms_device_get_kms (kms_device); - MetaKmsUpdate *kms_update; - - COGL_TRACE_BEGIN_SCOPED (MetaOnscreenNativeSetCrtcModes, - "Onscreen (set CRTC modes)"); - - kms_update = meta_kms_ensure_pending_update (kms, kms_device); - - switch (renderer_gpu_data->mode) - { - case META_RENDERER_NATIVE_MODE_GBM: - break; - case META_RENDERER_NATIVE_MODE_SURFACELESS: - g_assert_not_reached (); - break; -#ifdef HAVE_EGL_DEVICE - case META_RENDERER_NATIVE_MODE_EGL_DEVICE: - { - MetaDrmBuffer *buffer; - - buffer = META_DRM_BUFFER (onscreen_native->egl.dumb_fb); - meta_crtc_kms_assign_primary_plane (crtc_kms, buffer, kms_update); - break; - } -#endif - } - - meta_crtc_kms_set_mode (crtc_kms, kms_update); - meta_output_kms_set_underscan (META_OUTPUT_KMS (onscreen_native->output), - kms_update); -} - -static void -secondary_gpu_release_dumb (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state) -{ - unsigned i; - - for (i = 0; i < G_N_ELEMENTS (secondary_gpu_state->cpu.dumb_fbs); i++) - g_clear_object (&secondary_gpu_state->cpu.dumb_fbs[i]); -} - -static void -secondary_gpu_state_free (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state) -{ - MetaGpu *gpu = META_GPU (secondary_gpu_state->gpu_kms); - MetaBackend *backend = meta_gpu_get_backend (gpu); - MetaEgl *egl = meta_backend_get_egl (backend); - - if (secondary_gpu_state->egl_surface != EGL_NO_SURFACE) - { - MetaRendererNativeGpuData *renderer_gpu_data; - - renderer_gpu_data = secondary_gpu_state->renderer_gpu_data; - meta_egl_destroy_surface (egl, - renderer_gpu_data->egl_display, - secondary_gpu_state->egl_surface, - NULL); - } - - g_clear_object (&secondary_gpu_state->gbm.current_fb); - g_clear_object (&secondary_gpu_state->gbm.next_fb); - g_clear_pointer (&secondary_gpu_state->gbm.surface, gbm_surface_destroy); - - secondary_gpu_release_dumb (secondary_gpu_state); - - g_free (secondary_gpu_state); -} - -static gboolean -import_shared_framebuffer (CoglOnscreen *onscreen, - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaGpuKms *gpu_kms; - MetaDeviceFile *device_file; - struct gbm_device *gbm_device; - MetaDrmBufferGbm *buffer_gbm; - MetaDrmBufferImport *buffer_import; - g_autoptr (GError) error = NULL; - - buffer_gbm = META_DRM_BUFFER_GBM (onscreen_native->gbm.next_fb); - - gpu_kms = secondary_gpu_state->gpu_kms; - device_file = secondary_gpu_state->renderer_gpu_data->device_file; - gbm_device = meta_gbm_device_from_gpu (gpu_kms); - buffer_import = meta_drm_buffer_import_new (device_file, - gbm_device, - buffer_gbm, - &error); - if (!buffer_import) - { - meta_topic (META_DEBUG_KMS, - "Zero-copy disabled for %s, " - "meta_drm_buffer_import_new failed: %s", - meta_device_file_get_path (device_file), - error->message); - - g_warn_if_fail (secondary_gpu_state->import_status == - META_SHARED_FRAMEBUFFER_IMPORT_STATUS_NONE); - - /* - * Fall back. If META_SHARED_FRAMEBUFFER_IMPORT_STATUS_NONE is - * in effect, we have COPY_MODE_PRIMARY prepared already, so we - * simply retry with that path. Import status cannot be FAILED, - * because we should not retry if failed once. - * - * If import status is OK, that is unexpected and we do not - * have the fallback path prepared which means this output cannot - * work anymore. - */ - secondary_gpu_state->renderer_gpu_data->secondary.copy_mode = - META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY; - - secondary_gpu_state->import_status = - META_SHARED_FRAMEBUFFER_IMPORT_STATUS_FAILED; - return FALSE; - } - - /* - * next_fb may already contain a fallback buffer, so clear it only - * when we are sure to succeed. - */ - g_clear_object (&secondary_gpu_state->gbm.next_fb); - secondary_gpu_state->gbm.next_fb = META_DRM_BUFFER (buffer_import); - - if (secondary_gpu_state->import_status == - META_SHARED_FRAMEBUFFER_IMPORT_STATUS_NONE) - { - /* - * Clean up the cpu-copy part of - * init_secondary_gpu_state_cpu_copy_mode () - */ - secondary_gpu_release_dumb (secondary_gpu_state); - - meta_topic (META_DEBUG_KMS, - "Using zero-copy for %s succeeded once.", - meta_device_file_get_path (device_file)); - } - - secondary_gpu_state->import_status = - META_SHARED_FRAMEBUFFER_IMPORT_STATUS_OK; - return TRUE; -} - -static void -copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state, - MetaRendererNativeGpuData *renderer_gpu_data, - gboolean *egl_context_changed) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; - MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); - MetaGles3 *gles3 = meta_renderer_native_get_gles3 (renderer_native); - GError *error = NULL; - gboolean use_modifiers; - MetaDeviceFile *device_file; - MetaDrmBufferGbm *buffer_gbm; - struct gbm_bo *bo; - - COGL_TRACE_BEGIN_SCOPED (CopySharedFramebufferSecondaryGpu, - "FB Copy (secondary GPU)"); - - g_warn_if_fail (secondary_gpu_state->gbm.next_fb == NULL); - g_clear_object (&secondary_gpu_state->gbm.next_fb); - - if (!meta_egl_make_current (egl, - renderer_gpu_data->egl_display, - secondary_gpu_state->egl_surface, - secondary_gpu_state->egl_surface, - renderer_gpu_data->secondary.egl_context, - &error)) - { - g_warning ("Failed to make current: %s", error->message); - g_error_free (error); - return; - } - - *egl_context_changed = TRUE; - - - buffer_gbm = META_DRM_BUFFER_GBM (onscreen_native->gbm.next_fb); - bo = meta_drm_buffer_gbm_get_bo (buffer_gbm); - if (!meta_renderer_native_gles3_blit_shared_bo (egl, - gles3, - renderer_gpu_data->egl_display, - renderer_gpu_data->secondary.egl_context, - secondary_gpu_state->egl_surface, - bo, - &error)) - { - g_warning ("Failed to blit shared framebuffer: %s", error->message); - g_error_free (error); - return; - } - - if (!meta_egl_swap_buffers (egl, - renderer_gpu_data->egl_display, - secondary_gpu_state->egl_surface, - &error)) - { - g_warning ("Failed to swap buffers: %s", error->message); - g_error_free (error); - return; - } - - use_modifiers = meta_renderer_native_use_modifiers (renderer_native); - device_file = secondary_gpu_state->renderer_gpu_data->device_file; - buffer_gbm = - meta_drm_buffer_gbm_new_lock_front (device_file, - secondary_gpu_state->gbm.surface, - use_modifiers, - &error); - if (!buffer_gbm) - { - g_warning ("meta_drm_buffer_gbm_new_lock_front failed: %s", - error->message); - g_error_free (error); - return; - } - - secondary_gpu_state->gbm.next_fb = META_DRM_BUFFER (buffer_gbm); -} - -static MetaDrmBufferDumb * -secondary_gpu_get_next_dumb_buffer (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state) -{ - MetaDrmBufferDumb *current_dumb_fb; - - current_dumb_fb = secondary_gpu_state->cpu.current_dumb_fb; - if (current_dumb_fb == secondary_gpu_state->cpu.dumb_fbs[0]) - return secondary_gpu_state->cpu.dumb_fbs[1]; - else - return secondary_gpu_state->cpu.dumb_fbs[0]; -} - -static gboolean -copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscreen, - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state) -{ - CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaRendererNative *renderer_native = onscreen_native->renderer_native; - MetaGpuKms *primary_gpu; - MetaRendererNativeGpuData *primary_gpu_data; - MetaDrmBufferDumb *buffer_dumb; - MetaDrmBuffer *buffer; - int width, height, stride; - uint32_t drm_format; - CoglFramebuffer *dmabuf_fb; - int dmabuf_fd; - g_autoptr (GError) error = NULL; - CoglPixelFormat cogl_format; - int ret; - - COGL_TRACE_BEGIN_SCOPED (CopySharedFramebufferPrimaryGpu, - "FB Copy (primary GPU)"); - - primary_gpu = meta_renderer_native_get_primary_gpu (renderer_native); - primary_gpu_data = - meta_renderer_native_get_gpu_data (renderer_native, primary_gpu); - if (!primary_gpu_data->secondary.has_EGL_EXT_image_dma_buf_import_modifiers) - return FALSE; - - buffer_dumb = secondary_gpu_get_next_dumb_buffer (secondary_gpu_state); - buffer = META_DRM_BUFFER (buffer_dumb); - - width = meta_drm_buffer_get_width (buffer); - height = meta_drm_buffer_get_height (buffer); - stride = meta_drm_buffer_get_stride (buffer); - drm_format = meta_drm_buffer_get_format (buffer); - - g_assert (cogl_framebuffer_get_width (framebuffer) == width); - g_assert (cogl_framebuffer_get_height (framebuffer) == height); - - ret = meta_cogl_pixel_format_from_drm_format (drm_format, - &cogl_format, - NULL); - g_assert (ret); - - dmabuf_fd = meta_drm_buffer_dumb_ensure_dmabuf_fd (buffer_dumb, &error); - if (!dmabuf_fd) - { - meta_topic (META_DEBUG_KMS, - "Failed to create DMA buffer: %s", error->message); - return FALSE; - } - - dmabuf_fb = - meta_renderer_native_create_dma_buf_framebuffer (renderer_native, - dmabuf_fd, - width, - height, - stride, - 0, DRM_FORMAT_MOD_LINEAR, - drm_format, - &error); - - if (error) - { - meta_topic (META_DEBUG_KMS, - "Failed to create DMA buffer for blitting: %s", - error->message); - return FALSE; - } - - if (!cogl_blit_framebuffer (framebuffer, COGL_FRAMEBUFFER (dmabuf_fb), - 0, 0, 0, 0, - width, height, - &error)) - { - g_object_unref (dmabuf_fb); - return FALSE; - } - - g_object_unref (dmabuf_fb); - - g_set_object (&secondary_gpu_state->gbm.next_fb, buffer); - secondary_gpu_state->cpu.current_dumb_fb = buffer_dumb; - - return TRUE; -} - -static void -copy_shared_framebuffer_cpu (CoglOnscreen *onscreen, - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state, - MetaRendererNativeGpuData *renderer_gpu_data) -{ - CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); - CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer); - MetaDrmBufferDumb *buffer_dumb; - MetaDrmBuffer *buffer; - int width, height, stride; - uint32_t drm_format; - void *buffer_data; - CoglBitmap *dumb_bitmap; - CoglPixelFormat cogl_format; - gboolean ret; - - COGL_TRACE_BEGIN_SCOPED (CopySharedFramebufferCpu, - "FB Copy (CPU)"); - - buffer_dumb = secondary_gpu_get_next_dumb_buffer (secondary_gpu_state); - buffer = META_DRM_BUFFER (buffer_dumb); - - width = meta_drm_buffer_get_width (buffer); - height = meta_drm_buffer_get_height (buffer); - stride = meta_drm_buffer_get_stride (buffer); - drm_format = meta_drm_buffer_get_format (buffer); - buffer_data = meta_drm_buffer_dumb_get_data (buffer_dumb); - - g_assert (cogl_framebuffer_get_width (framebuffer) == width); - g_assert (cogl_framebuffer_get_height (framebuffer) == height); - - ret = meta_cogl_pixel_format_from_drm_format (drm_format, - &cogl_format, - NULL); - g_assert (ret); - - dumb_bitmap = cogl_bitmap_new_for_data (cogl_context, - width, - height, - cogl_format, - stride, - buffer_data); - - if (!cogl_framebuffer_read_pixels_into_bitmap (framebuffer, - 0 /* x */, - 0 /* y */, - COGL_READ_PIXELS_COLOR_BUFFER, - dumb_bitmap)) - g_warning ("Failed to CPU-copy to a secondary GPU output"); - - cogl_object_unref (dumb_bitmap); - - g_clear_object (&secondary_gpu_state->gbm.next_fb); - secondary_gpu_state->gbm.next_fb = buffer; - secondary_gpu_state->cpu.current_dumb_fb = buffer_dumb; -} - -static void -update_secondary_gpu_state_pre_swap_buffers (CoglOnscreen *onscreen) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state; - - COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeGpuStatePreSwapBuffers, - "Onscreen (secondary gpu pre-swap-buffers)"); - - secondary_gpu_state = onscreen_native->secondary_gpu_state; - if (secondary_gpu_state) - { - MetaRendererNativeGpuData *renderer_gpu_data; - MetaDeviceFile *device_file; - - renderer_gpu_data = secondary_gpu_state->renderer_gpu_data; - device_file = renderer_gpu_data->device_file; - switch (renderer_gpu_data->secondary.copy_mode) - { - case META_SHARED_FRAMEBUFFER_COPY_MODE_SECONDARY_GPU: - /* Done after eglSwapBuffers. */ - break; - case META_SHARED_FRAMEBUFFER_COPY_MODE_ZERO: - /* Done after eglSwapBuffers. */ - if (secondary_gpu_state->import_status == - META_SHARED_FRAMEBUFFER_IMPORT_STATUS_OK) - break; - /* prepare fallback */ - G_GNUC_FALLTHROUGH; - case META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY: - if (!copy_shared_framebuffer_primary_gpu (onscreen, - secondary_gpu_state)) - { - if (!secondary_gpu_state->noted_primary_gpu_copy_failed) - { - meta_topic (META_DEBUG_KMS, - "Using primary GPU to copy for %s failed once.", - meta_device_file_get_path (device_file)); - secondary_gpu_state->noted_primary_gpu_copy_failed = TRUE; - } - - copy_shared_framebuffer_cpu (onscreen, - secondary_gpu_state, - renderer_gpu_data); - } - else if (!secondary_gpu_state->noted_primary_gpu_copy_ok) - { - meta_topic (META_DEBUG_KMS, - "Using primary GPU to copy for %s succeeded once.", - meta_device_file_get_path (device_file)); - secondary_gpu_state->noted_primary_gpu_copy_ok = TRUE; - } - break; - } - } -} - -static void -update_secondary_gpu_state_post_swap_buffers (CoglOnscreen *onscreen, - gboolean *egl_context_changed) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaRendererNative *renderer_native = onscreen_native->renderer_native; - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state; - - COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeGpuStatePostSwapBuffers, - "Onscreen (secondary gpu post-swap-buffers)"); - - secondary_gpu_state = onscreen_native->secondary_gpu_state; - if (secondary_gpu_state) - { - MetaRendererNativeGpuData *renderer_gpu_data; - - renderer_gpu_data = - meta_renderer_native_get_gpu_data (renderer_native, - secondary_gpu_state->gpu_kms); -retry: - switch (renderer_gpu_data->secondary.copy_mode) - { - case META_SHARED_FRAMEBUFFER_COPY_MODE_ZERO: - if (!import_shared_framebuffer (onscreen, - secondary_gpu_state)) - goto retry; - break; - case META_SHARED_FRAMEBUFFER_COPY_MODE_SECONDARY_GPU: - copy_shared_framebuffer_gpu (onscreen, - secondary_gpu_state, - renderer_gpu_data, - egl_context_changed); - break; - case META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY: - /* Done before eglSwapBuffers. */ - break; - } - } -} - -static void -ensure_crtc_modes (CoglOnscreen *onscreen) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); - CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer); - CoglRenderer *cogl_renderer = cogl_context->display->renderer; - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; - MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; - - if (meta_renderer_native_pop_pending_mode_set (renderer_native, - onscreen_native->view)) - meta_onscreen_native_set_crtc_mode (onscreen, renderer_gpu_data); -} - -static void -meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, - const int *rectangles, - int n_rectangles, - CoglFrameInfo *frame_info, - gpointer user_data) -{ - CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); - CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer); - CoglDisplay *cogl_display = cogl_context_get_display (cogl_context); - CoglRenderer *cogl_renderer = cogl_context->display->renderer; - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; - MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaKms *kms = meta_backend_native_get_kms (backend_native); - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaGpuKms *render_gpu = onscreen_native->render_gpu; - MetaDeviceFile *render_device_file; - ClutterFrame *frame = user_data; - CoglOnscreenClass *parent_class; - gboolean egl_context_changed = FALSE; - gboolean use_modifiers; - MetaPowerSave power_save_mode; - g_autoptr (GError) error = NULL; - MetaDrmBufferGbm *buffer_gbm; - MetaKmsCrtc *kms_crtc; - MetaKmsDevice *kms_device; - MetaKmsUpdateFlag flags; - g_autoptr (MetaKmsFeedback) kms_feedback = NULL; - const GError *feedback_error; - - COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeSwapBuffers, - "Onscreen (swap-buffers)"); - - update_secondary_gpu_state_pre_swap_buffers (onscreen); - - parent_class = COGL_ONSCREEN_CLASS (meta_onscreen_native_parent_class); - parent_class->swap_buffers_with_damage (onscreen, - rectangles, - n_rectangles, - frame_info, - user_data); - - renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, - render_gpu); - render_device_file = renderer_gpu_data->device_file; - switch (renderer_gpu_data->mode) - { - case META_RENDERER_NATIVE_MODE_GBM: - g_warn_if_fail (onscreen_native->gbm.next_fb == NULL); - g_clear_object (&onscreen_native->gbm.next_fb); - - use_modifiers = meta_renderer_native_use_modifiers (renderer_native); - buffer_gbm = - meta_drm_buffer_gbm_new_lock_front (render_device_file, - onscreen_native->gbm.surface, - use_modifiers, - &error); - if (!buffer_gbm) - { - g_warning ("Failed to lock front buffer on %s: %s", - meta_device_file_get_path (render_device_file), - error->message); - return; - } - - onscreen_native->gbm.next_fb = META_DRM_BUFFER (buffer_gbm); - - break; - case META_RENDERER_NATIVE_MODE_SURFACELESS: - g_assert_not_reached (); - break; -#ifdef HAVE_EGL_DEVICE - case META_RENDERER_NATIVE_MODE_EGL_DEVICE: - break; -#endif - } - - update_secondary_gpu_state_post_swap_buffers (onscreen, &egl_context_changed); - - /* - * If we changed EGL context, cogl will have the wrong idea about what is - * current, making it fail to set it when it needs to. Avoid that by making - * EGL_NO_CONTEXT current now, making cogl eventually set the correct - * context. - */ - if (egl_context_changed) - _cogl_winsys_egl_ensure_current (cogl_display); - - power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager); - if (power_save_mode == META_POWER_SAVE_ON) - { - ensure_crtc_modes (onscreen); - meta_onscreen_native_flip_crtc (onscreen, - onscreen_native->view, - onscreen_native->crtc, - META_KMS_PAGE_FLIP_LISTENER_FLAG_NONE); - } - else - { - meta_renderer_native_queue_power_save_page_flip (renderer_native, - onscreen); - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - return; - } - - COGL_TRACE_BEGIN_SCOPED (MetaRendererNativePostKmsUpdate, - "Onscreen (post pending update)"); - kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (onscreen_native->crtc)); - kms_device = meta_kms_crtc_get_device (kms_crtc); - - switch (renderer_gpu_data->mode) - { - case META_RENDERER_NATIVE_MODE_GBM: - if (meta_renderer_native_has_pending_mode_sets (renderer_native)) - { - meta_topic (META_DEBUG_KMS, - "Postponing primary plane composite update for CRTC %u (%s)", - meta_kms_crtc_get_id (kms_crtc), - meta_kms_device_get_path (kms_device)); - - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - return; - } - else if (meta_renderer_native_has_pending_mode_set (renderer_native)) - { - meta_topic (META_DEBUG_KMS, "Posting global mode set updates on %s", - meta_kms_device_get_path (kms_device)); - - meta_renderer_native_notify_mode_sets_reset (renderer_native); - meta_renderer_native_post_mode_set_updates (renderer_native); - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - return; - } - break; - case META_RENDERER_NATIVE_MODE_SURFACELESS: - g_assert_not_reached (); - break; -#ifdef HAVE_EGL_DEVICE - case META_RENDERER_NATIVE_MODE_EGL_DEVICE: - if (meta_renderer_native_has_pending_mode_set (renderer_native)) - { - meta_renderer_native_notify_mode_sets_reset (renderer_native); - meta_renderer_native_post_mode_set_updates (renderer_native); - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - return; - } - break; -#endif - } - - meta_topic (META_DEBUG_KMS, - "Posting primary plane composite update for CRTC %u (%s)", - meta_kms_crtc_get_id (kms_crtc), - meta_kms_device_get_path (kms_device)); - - flags = META_KMS_UPDATE_FLAG_NONE; - kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device, flags); - - switch (meta_kms_feedback_get_result (kms_feedback)) - { - case META_KMS_FEEDBACK_PASSED: - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - break; - case META_KMS_FEEDBACK_FAILED: - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - - feedback_error = meta_kms_feedback_get_error (kms_feedback); - if (!g_error_matches (feedback_error, - G_IO_ERROR, - G_IO_ERROR_PERMISSION_DENIED)) - g_warning ("Failed to post KMS update: %s", feedback_error->message); - break; - } -} - -gboolean -meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen, - uint32_t drm_format, - uint64_t drm_modifier, - uint32_t stride) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - const MetaCrtcConfig *crtc_config; - MetaDrmBuffer *fb; - struct gbm_bo *gbm_bo; - - crtc_config = meta_crtc_get_config (onscreen_native->crtc); - if (crtc_config->transform != META_MONITOR_TRANSFORM_NORMAL) - return FALSE; - - if (onscreen_native->secondary_gpu_state) - return FALSE; - - if (!onscreen_native->gbm.surface) - return FALSE; - - fb = onscreen_native->gbm.current_fb ? onscreen_native->gbm.current_fb - : onscreen_native->gbm.next_fb; - if (!fb) - return FALSE; - - if (!META_IS_DRM_BUFFER_GBM (fb)) - return FALSE; - - gbm_bo = meta_drm_buffer_gbm_get_bo (META_DRM_BUFFER_GBM (fb)); - - if (gbm_bo_get_format (gbm_bo) != drm_format) - return FALSE; - - if (gbm_bo_get_modifier (gbm_bo) != drm_modifier) - return FALSE; - - if (gbm_bo_get_stride (gbm_bo) != stride) - return FALSE; - - return TRUE; -} - -static gboolean -meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, - CoglScanout *scanout, - CoglFrameInfo *frame_info, - gpointer user_data, - GError **error) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaGpuKms *render_gpu = onscreen_native->render_gpu; - CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); - CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer); - CoglRenderer *cogl_renderer = cogl_context->display->renderer; - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; - MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - MetaKms *kms = meta_backend_native_get_kms (backend_native); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaPowerSave power_save_mode; - ClutterFrame *frame = user_data; - MetaDrmBuffer *scanout_buffer; - GError *fill_timings_error = NULL; - MetaKmsCrtc *kms_crtc; - MetaKmsDevice *kms_device; - MetaKmsUpdateFlag flags; - g_autoptr (MetaKmsFeedback) kms_feedback = NULL; - const GError *feedback_error; - - power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager); - if (power_save_mode != META_POWER_SAVE_ON) - { - g_set_error_literal (error, - COGL_SCANOUT_ERROR, - COGL_SCANOUT_ERROR_INHIBITED, - "Direct scanout is inhibited during power saving mode"); - return FALSE; - } - - if (meta_renderer_native_has_pending_mode_set (renderer_native)) - { - g_set_error_literal (error, - COGL_SCANOUT_ERROR, - COGL_SCANOUT_ERROR_INHIBITED, - "Direct scanout is inhibited when a mode set is pending"); - return FALSE; - } - - renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, - render_gpu); - - g_warn_if_fail (renderer_gpu_data->mode == META_RENDERER_NATIVE_MODE_GBM); - g_warn_if_fail (!onscreen_native->gbm.next_fb); - - g_set_object (&onscreen_native->gbm.next_fb, META_DRM_BUFFER (scanout)); - - /* Try to get a measurement of GPU rendering time on the scanout buffer. - * - * The successful operation here adds ~0.4 ms to a ~0.1 ms total frame clock - * dispatch duration when displaying an unredirected client, thus - * unfortunately bringing it more in line with duration of the regular - * non-unredirected frame clock dispatch. However, measuring GPU rendering - * time is important for computing accurate max render time without - * underestimating. Also this operation should be optimizable by caching - * EGLImage for each buffer instead of re-creating it every time it's needed. - * This should also help all other cases which convert the buffer to a - * EGLImage. - */ - if (META_IS_DRM_BUFFER (scanout)) - { - scanout_buffer = META_DRM_BUFFER (scanout); - if (meta_drm_buffer_supports_fill_timings (scanout_buffer)) - { - if (!meta_drm_buffer_fill_timings (scanout_buffer, frame_info, - &fill_timings_error)) - { - g_warning ("Failed to fill timings for a scanout buffer: %s", - fill_timings_error->message); - g_error_free (fill_timings_error); - } - } - } - - ensure_crtc_modes (onscreen); - meta_onscreen_native_flip_crtc (onscreen, - onscreen_native->view, - onscreen_native->crtc, - META_KMS_PAGE_FLIP_LISTENER_FLAG_DROP_ON_ERROR); - - kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (onscreen_native->crtc)); - kms_device = meta_kms_crtc_get_device (kms_crtc); - - meta_topic (META_DEBUG_KMS, - "Posting direct scanout update for CRTC %u (%s)", - meta_kms_crtc_get_id (kms_crtc), - meta_kms_device_get_path (kms_device)); - - flags = META_KMS_UPDATE_FLAG_PRESERVE_ON_ERROR; - kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device, flags); - switch (meta_kms_feedback_get_result (kms_feedback)) - { - case META_KMS_FEEDBACK_PASSED: - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - break; - case META_KMS_FEEDBACK_FAILED: - feedback_error = meta_kms_feedback_get_error (kms_feedback); - - if (g_error_matches (feedback_error, - G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED)) - break; - - g_clear_object (&onscreen_native->gbm.next_fb); - g_propagate_error (error, g_error_copy (feedback_error)); - return FALSE; - } - - return TRUE; -} - -static void -add_onscreen_frame_info (MetaCrtc *crtc) -{ - MetaGpu *gpu = meta_crtc_get_gpu (crtc); - MetaBackend *backend = meta_gpu_get_backend (gpu); - ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend)); - ClutterStageWindow *stage_window = _clutter_stage_get_window (stage); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - MetaRendererView *view = meta_renderer_get_view_for_crtc (renderer, crtc); - - meta_stage_impl_add_onscreen_frame_info (META_STAGE_IMPL (stage_window), - CLUTTER_STAGE_VIEW (view)); -} - -void -meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, - ClutterFrame *frame) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaCrtc *crtc = onscreen_native->crtc; - MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc)); - MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc);; - MetaKms *kms = meta_kms_device_get_kms (kms_device); - MetaKmsUpdateFlag flags; - MetaKmsUpdate *kms_update; - g_autoptr (MetaKmsFeedback) kms_feedback = NULL; - const GError *error; - - kms_update = meta_kms_get_pending_update (kms, kms_device); - if (!kms_update) - { - clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_IDLE); - return; - } - - meta_kms_update_add_page_flip_listener (kms_update, - kms_crtc, - &page_flip_listener_vtable, - META_KMS_PAGE_FLIP_LISTENER_FLAG_NONE, - g_object_ref (onscreen_native->view), - g_object_unref); - - flags = META_KMS_UPDATE_FLAG_NONE; - kms_feedback = meta_kms_post_pending_update_sync (kms, - kms_device, - flags); - switch (meta_kms_feedback_get_result (kms_feedback)) - { - case META_KMS_FEEDBACK_PASSED: - add_onscreen_frame_info (crtc); - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - break; - case META_KMS_FEEDBACK_FAILED: - add_onscreen_frame_info (crtc); - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - - error = meta_kms_feedback_get_error (kms_feedback); - if (!g_error_matches (error, - G_IO_ERROR, - G_IO_ERROR_PERMISSION_DENIED)) - g_warning ("Failed to post KMS update: %s", error->message); - break; - } -} - -static gboolean -should_surface_be_sharable (CoglOnscreen *onscreen) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - - if (META_GPU_KMS (meta_crtc_get_gpu (onscreen_native->crtc)) == - onscreen_native->render_gpu) - return FALSE; - else - return TRUE; -} - -static uint32_t -get_gbm_format_from_egl (MetaEgl *egl, - EGLDisplay egl_display, - EGLConfig egl_config) -{ - uint32_t gbm_format; - EGLint native_visual_id; - - if (meta_egl_get_config_attrib (egl, - egl_display, - egl_config, - EGL_NATIVE_VISUAL_ID, - &native_visual_id, - NULL)) - gbm_format = (uint32_t) native_visual_id; - else - g_assert_not_reached (); - - return gbm_format; -} - -static GArray * -get_supported_kms_modifiers (MetaCrtcKms *crtc_kms, - uint32_t format) -{ - GArray *modifiers; - GArray *crtc_mods; - unsigned int i; - - crtc_mods = meta_crtc_kms_get_modifiers (crtc_kms, format); - if (!crtc_mods) - return NULL; - - modifiers = g_array_new (FALSE, FALSE, sizeof (uint64_t)); - - /* - * For each modifier from base_crtc, check if it's available on all other - * CRTCs. - */ - for (i = 0; i < crtc_mods->len; i++) - { - uint64_t modifier = g_array_index (crtc_mods, uint64_t, i); - - g_array_append_val (modifiers, modifier); - } - - if (modifiers->len == 0) - { - g_array_free (modifiers, TRUE); - return NULL; - } - - return modifiers; -} - -static GArray * -get_supported_egl_modifiers (CoglOnscreen *onscreen, - MetaCrtcKms *crtc_kms, - uint32_t format) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaRendererNative *renderer_native = onscreen_native->renderer_native; - MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native); - MetaGpu *gpu; - MetaRendererNativeGpuData *renderer_gpu_data; - EGLint num_modifiers; - GArray *modifiers; - GError *error = NULL; - gboolean ret; - - gpu = meta_crtc_get_gpu (META_CRTC (crtc_kms)); - renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, - META_GPU_KMS (gpu)); - - if (!meta_egl_has_extensions (egl, renderer_gpu_data->egl_display, NULL, - "EGL_EXT_image_dma_buf_import_modifiers", - NULL)) - return NULL; - - ret = meta_egl_query_dma_buf_modifiers (egl, renderer_gpu_data->egl_display, - format, 0, NULL, NULL, - &num_modifiers, NULL); - if (!ret || num_modifiers == 0) - return NULL; - - modifiers = g_array_sized_new (FALSE, FALSE, sizeof (uint64_t), - num_modifiers); - ret = meta_egl_query_dma_buf_modifiers (egl, renderer_gpu_data->egl_display, - format, num_modifiers, - (EGLuint64KHR *) modifiers->data, NULL, - &num_modifiers, &error); - - if (!ret) - { - g_warning ("Failed to query DMABUF modifiers: %s", error->message); - g_error_free (error); - g_array_free (modifiers, TRUE); - return NULL; - } - - return modifiers; -} - -static GArray * -get_supported_modifiers (CoglOnscreen *onscreen, - uint32_t format) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc); - MetaGpu *gpu; - g_autoptr (GArray) modifiers = NULL; - - gpu = meta_crtc_get_gpu (META_CRTC (crtc_kms)); - if (gpu == META_GPU (onscreen_native->render_gpu)) - modifiers = get_supported_kms_modifiers (crtc_kms, format); - else - modifiers = get_supported_egl_modifiers (onscreen, crtc_kms, format); - - return g_steal_pointer (&modifiers); -} - -static GArray * -get_supported_kms_formats (CoglOnscreen *onscreen) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc); - - return meta_crtc_kms_copy_drm_format_list (crtc_kms); -} - -static gboolean -create_surfaces_gbm (CoglOnscreen *onscreen, - int width, - int height, - struct gbm_surface **gbm_surface, - EGLSurface *egl_surface, - GError **error) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaRendererNative *renderer_native = onscreen_native->renderer_native; - MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native); - CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); - CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer); - CoglDisplay *cogl_display = cogl_context->display; - CoglDisplayEGL *cogl_display_egl = cogl_display->winsys; - CoglRenderer *cogl_renderer = cogl_display->renderer; - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; - struct gbm_surface *new_gbm_surface = NULL; - EGLNativeWindowType egl_native_window; - EGLSurface new_egl_surface; - uint32_t format; - GArray *modifiers; - - renderer_gpu_data = - meta_renderer_native_get_gpu_data (renderer_native, - onscreen_native->render_gpu); - - format = get_gbm_format_from_egl (egl, - cogl_renderer_egl->edpy, - cogl_display_egl->egl_config); - - if (meta_renderer_native_use_modifiers (renderer_native)) - modifiers = get_supported_modifiers (onscreen, format); - else - modifiers = NULL; - - if (modifiers) - { - new_gbm_surface = - gbm_surface_create_with_modifiers (renderer_gpu_data->gbm.device, - width, height, format, - (uint64_t *) modifiers->data, - modifiers->len); - g_array_free (modifiers, TRUE); - } - - if (!new_gbm_surface) - { - uint32_t flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING; - - if (should_surface_be_sharable (onscreen)) - flags |= GBM_BO_USE_LINEAR; - - new_gbm_surface = gbm_surface_create (renderer_gpu_data->gbm.device, - width, height, - format, - flags); - } - - if (!new_gbm_surface) - { - g_set_error (error, COGL_WINSYS_ERROR, - COGL_WINSYS_ERROR_CREATE_ONSCREEN, - "Failed to allocate surface"); - return FALSE; - } - - egl_native_window = (EGLNativeWindowType) new_gbm_surface; - new_egl_surface = - meta_egl_create_window_surface (egl, - cogl_renderer_egl->edpy, - cogl_display_egl->egl_config, - egl_native_window, - NULL, - error); - if (new_egl_surface == EGL_NO_SURFACE) - { - gbm_surface_destroy (new_gbm_surface); - return FALSE; - } - - *gbm_surface = new_gbm_surface; - *egl_surface = new_egl_surface; - - return TRUE; -} - -#ifdef HAVE_EGL_DEVICE -static gboolean -create_surfaces_egl_device (CoglOnscreen *onscreen, - int width, - int height, - EGLStreamKHR *out_egl_stream, - EGLSurface *out_egl_surface, - GError **error) -{ - CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer); - CoglDisplay *cogl_display = cogl_context->display; - CoglDisplayEGL *cogl_display_egl = cogl_display->winsys; - CoglRenderer *cogl_renderer = cogl_display->renderer; - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; - MetaEgl *egl = - meta_renderer_native_get_egl (renderer_gpu_data->renderer_native); - EGLDisplay egl_display = renderer_gpu_data->egl_display; - EGLConfig egl_config; - EGLStreamKHR egl_stream; - EGLSurface egl_surface; - EGLint num_layers; - EGLOutputLayerEXT output_layer; - EGLAttrib output_attribs[3]; - EGLint stream_attribs[] = { - EGL_STREAM_FIFO_LENGTH_KHR, 0, - EGL_CONSUMER_AUTO_ACQUIRE_EXT, EGL_FALSE, - EGL_NONE - }; - EGLint stream_producer_attribs[] = { - EGL_WIDTH, width, - EGL_HEIGHT, height, - EGL_NONE - }; - - egl_stream = meta_egl_create_stream (egl, egl_display, stream_attribs, error); - if (egl_stream == EGL_NO_STREAM_KHR) - return FALSE; - - output_attribs[0] = EGL_DRM_CRTC_EXT; - output_attribs[1] = meta_crtc_get_id (onscreen_native->crtc); - output_attribs[2] = EGL_NONE; - - if (!meta_egl_get_output_layers (egl, egl_display, - output_attribs, - &output_layer, 1, &num_layers, - error)) - { - meta_egl_destroy_stream (egl, egl_display, egl_stream, NULL); - return FALSE; - } - - if (num_layers < 1) - { - meta_egl_destroy_stream (egl, egl_display, egl_stream, NULL); - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Unable to find output layers."); - return FALSE; - } - - if (!meta_egl_stream_consumer_output (egl, egl_display, - egl_stream, output_layer, - error)) - { - meta_egl_destroy_stream (egl, egl_display, egl_stream, NULL); - return FALSE; - } - - egl_config = cogl_display_egl->egl_config; - egl_surface = meta_egl_create_stream_producer_surface (egl, - egl_display, - egl_config, - egl_stream, - stream_producer_attribs, - error); - if (egl_surface == EGL_NO_SURFACE) - { - meta_egl_destroy_stream (egl, egl_display, egl_stream, NULL); - return FALSE; - } - - *out_egl_stream = egl_stream; - *out_egl_surface = egl_surface; - - return TRUE; -} -#endif /* HAVE_EGL_DEVICE */ - -void -meta_onscreen_native_set_view (CoglOnscreen *onscreen, - MetaRendererView *view) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - onscreen_native->view = view; -} - -static gboolean -meta_onscreen_native_allocate (CoglFramebuffer *framebuffer, - GError **error) -{ - CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - CoglOnscreenEgl *onscreen_egl = COGL_ONSCREEN_EGL (onscreen); - MetaRendererNativeGpuData *renderer_gpu_data; - struct gbm_surface *gbm_surface; - EGLSurface egl_surface; - int width; - int height; -#ifdef HAVE_EGL_DEVICE - MetaDeviceFile *render_device_file; - EGLStreamKHR egl_stream; -#endif - CoglFramebufferClass *parent_class; - - if (META_GPU_KMS (meta_crtc_get_gpu (onscreen_native->crtc)) != - onscreen_native->render_gpu) - { - if (!init_secondary_gpu_state (onscreen_native->renderer_native, - onscreen, error)) - return FALSE; - } - - width = cogl_framebuffer_get_width (framebuffer); - height = cogl_framebuffer_get_height (framebuffer); - - renderer_gpu_data = - meta_renderer_native_get_gpu_data (onscreen_native->renderer_native, - onscreen_native->render_gpu); - switch (renderer_gpu_data->mode) - { - case META_RENDERER_NATIVE_MODE_GBM: - if (!create_surfaces_gbm (onscreen, - width, height, - &gbm_surface, - &egl_surface, - error)) - return FALSE; - - onscreen_native->gbm.surface = gbm_surface; - cogl_onscreen_egl_set_egl_surface (onscreen_egl, egl_surface); - break; - case META_RENDERER_NATIVE_MODE_SURFACELESS: - g_assert_not_reached (); - break; -#ifdef HAVE_EGL_DEVICE - case META_RENDERER_NATIVE_MODE_EGL_DEVICE: - render_device_file = renderer_gpu_data->device_file; - onscreen_native->egl.dumb_fb = - meta_drm_buffer_dumb_new (render_device_file, - width, height, - DRM_FORMAT_XRGB8888, - error); - if (!onscreen_native->egl.dumb_fb) - return FALSE; - - if (!create_surfaces_egl_device (onscreen, - width, height, - &egl_stream, - &egl_surface, - error)) - return FALSE; - - onscreen_native->egl.stream = egl_stream; - cogl_onscreen_egl_set_egl_surface (onscreen_egl, egl_surface); - break; -#endif /* HAVE_EGL_DEVICE */ - } - - parent_class = COGL_FRAMEBUFFER_CLASS (meta_onscreen_native_parent_class); - return parent_class->allocate (framebuffer, error); -} - -static gboolean -init_secondary_gpu_state_gpu_copy_mode (MetaRendererNative *renderer_native, - CoglOnscreen *onscreen, - MetaRendererNativeGpuData *renderer_gpu_data, - GError **error) -{ - CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native); - int width, height; - EGLNativeWindowType egl_native_window; - struct gbm_surface *gbm_surface; - EGLSurface egl_surface; - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state; - MetaGpuKms *gpu_kms; - uint32_t format; - - width = cogl_framebuffer_get_width (framebuffer); - height = cogl_framebuffer_get_height (framebuffer); - format = get_gbm_format_from_egl (egl, - renderer_gpu_data->egl_display, - renderer_gpu_data->secondary.egl_config); - - gbm_surface = gbm_surface_create (renderer_gpu_data->gbm.device, - width, height, - format, - GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); - if (!gbm_surface) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to create gbm_surface: %s", strerror (errno)); - return FALSE; - } - - egl_native_window = (EGLNativeWindowType) gbm_surface; - egl_surface = - meta_egl_create_window_surface (egl, - renderer_gpu_data->egl_display, - renderer_gpu_data->secondary.egl_config, - egl_native_window, - NULL, - error); - if (egl_surface == EGL_NO_SURFACE) - { - gbm_surface_destroy (gbm_surface); - return FALSE; - } - - secondary_gpu_state = g_new0 (MetaOnscreenNativeSecondaryGpuState, 1); - - gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (onscreen_native->crtc)); - secondary_gpu_state->gpu_kms = gpu_kms; - secondary_gpu_state->renderer_gpu_data = renderer_gpu_data; - secondary_gpu_state->gbm.surface = gbm_surface; - secondary_gpu_state->egl_surface = egl_surface; - - onscreen_native->secondary_gpu_state = secondary_gpu_state; - - return TRUE; -} - -static uint32_t -pick_secondary_gpu_framebuffer_format_for_cpu (CoglOnscreen *onscreen) -{ - /* - * cogl_framebuffer_read_pixels_into_bitmap () supported formats in - * preference order. Ideally these should depend on the render buffer - * format copy_shared_framebuffer_cpu () will be reading from but - * alpha channel ignored. - */ - static const uint32_t preferred_formats[] = - { - /* - * DRM_FORMAT_XBGR8888 a.k.a GL_RGBA, GL_UNSIGNED_BYTE on - * little-endian is possibly the most optimized glReadPixels - * output format. glReadPixels cannot avoid manufacturing an alpha - * channel if the render buffer does not have one and converting - * to ABGR8888 may be more optimized than ARGB8888. - */ - DRM_FORMAT_XBGR8888, - /* The rest are other fairly commonly used formats in OpenGL. */ - DRM_FORMAT_XRGB8888, - }; - g_autoptr (GArray) formats = NULL; - size_t k; - unsigned int i; - uint32_t drm_format; - - formats = get_supported_kms_formats (onscreen); - - /* Check if any of our preferred formats are supported. */ - for (k = 0; k < G_N_ELEMENTS (preferred_formats); k++) - { - g_assert (meta_cogl_pixel_format_from_drm_format (preferred_formats[k], - NULL, - NULL)); - - for (i = 0; i < formats->len; i++) - { - drm_format = g_array_index (formats, uint32_t, i); - - if (drm_format == preferred_formats[k]) - return drm_format; - } - } - - /* - * Otherwise just pick an arbitrary format we recognize. The formats - * list is not in any specific order and we don't know any better - * either. - */ - for (i = 0; i < formats->len; i++) - { - drm_format = g_array_index (formats, uint32_t, i); - - if (meta_cogl_pixel_format_from_drm_format (drm_format, NULL, NULL)) - return drm_format; - } - - return DRM_FORMAT_INVALID; -} - -static gboolean -init_secondary_gpu_state_cpu_copy_mode (MetaRendererNative *renderer_native, - CoglOnscreen *onscreen, - MetaRendererNativeGpuData *renderer_gpu_data, - GError **error) -{ - CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state; - MetaGpuKms *gpu_kms; - MetaDeviceFile *device_file; - int width, height; - unsigned int i; - uint32_t drm_format; - MetaDrmFormatBuf tmp; - - drm_format = pick_secondary_gpu_framebuffer_format_for_cpu (onscreen); - if (drm_format == DRM_FORMAT_INVALID) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Could not find a suitable pixel format in CPU copy mode"); - return FALSE; - } - - width = cogl_framebuffer_get_width (framebuffer); - height = cogl_framebuffer_get_height (framebuffer); - - gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (onscreen_native->crtc)); - device_file = renderer_gpu_data->device_file; - meta_topic (META_DEBUG_KMS, - "Secondary GPU %s using DRM format '%s' (0x%x) for a %dx%d output.", - meta_device_file_get_path (device_file), - meta_drm_format_to_string (&tmp, drm_format), - drm_format, - width, height); - - secondary_gpu_state = g_new0 (MetaOnscreenNativeSecondaryGpuState, 1); - secondary_gpu_state->renderer_gpu_data = renderer_gpu_data; - secondary_gpu_state->gpu_kms = gpu_kms; - secondary_gpu_state->egl_surface = EGL_NO_SURFACE; - - for (i = 0; i < G_N_ELEMENTS (secondary_gpu_state->cpu.dumb_fbs); i++) - { - secondary_gpu_state->cpu.dumb_fbs[i] = - meta_drm_buffer_dumb_new (device_file, - width, height, - drm_format, - error); - if (!secondary_gpu_state->cpu.dumb_fbs[i]) - { - secondary_gpu_state_free (secondary_gpu_state); - return FALSE; - } - } - - /* - * This function initializes everything needed for - * META_SHARED_FRAMEBUFFER_COPY_MODE_ZERO as well. - */ - secondary_gpu_state->import_status = - META_SHARED_FRAMEBUFFER_IMPORT_STATUS_NONE; - - onscreen_native->secondary_gpu_state = secondary_gpu_state; - - return TRUE; -} - -static gboolean -init_secondary_gpu_state (MetaRendererNative *renderer_native, - CoglOnscreen *onscreen, - GError **error) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaGpu *gpu = meta_crtc_get_gpu (onscreen_native->crtc); - MetaRendererNativeGpuData *renderer_gpu_data; - - renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, - META_GPU_KMS (gpu)); - - switch (renderer_gpu_data->secondary.copy_mode) - { - case META_SHARED_FRAMEBUFFER_COPY_MODE_SECONDARY_GPU: - if (!init_secondary_gpu_state_gpu_copy_mode (renderer_native, - onscreen, - renderer_gpu_data, - error)) - return FALSE; - break; - case META_SHARED_FRAMEBUFFER_COPY_MODE_ZERO: - /* - * Initialize also the primary copy mode, so that if zero-copy - * path fails, which is quite likely, we can simply continue - * with the primary copy path on the very first frame. - */ - G_GNUC_FALLTHROUGH; - case META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY: - if (!init_secondary_gpu_state_cpu_copy_mode (renderer_native, - onscreen, - renderer_gpu_data, - error)) - return FALSE; - break; - } - - return TRUE; -} - -MetaOnscreenNative * -meta_onscreen_native_new (MetaRendererNative *renderer_native, - MetaGpuKms *render_gpu, - MetaOutput *output, - MetaCrtc *crtc, - CoglContext *cogl_context, - int width, - int height) -{ - MetaOnscreenNative *onscreen_native; - CoglFramebufferDriverConfig driver_config; - - driver_config = (CoglFramebufferDriverConfig) { - .type = COGL_FRAMEBUFFER_DRIVER_TYPE_BACK, - }; - onscreen_native = g_object_new (META_TYPE_ONSCREEN_NATIVE, - "context", cogl_context, - "driver-config", &driver_config, - "width", width, - "height", height, - NULL); - - onscreen_native->renderer_native = renderer_native; - onscreen_native->render_gpu = render_gpu; - onscreen_native->output = output; - onscreen_native->crtc = crtc; - - return onscreen_native; -} - -static void -meta_onscreen_native_dispose (GObject *object) -{ - CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (object); - CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaRendererNative *renderer_native = onscreen_native->renderer_native; - MetaRendererNativeGpuData *renderer_gpu_data; - - renderer_gpu_data = - meta_renderer_native_get_gpu_data (renderer_native, - onscreen_native->render_gpu); - switch (renderer_gpu_data->mode) - { - case META_RENDERER_NATIVE_MODE_GBM: - /* flip state takes a reference on the onscreen so there should - * never be outstanding flips when we reach here. */ - g_warn_if_fail (onscreen_native->gbm.next_fb == NULL); - - free_current_bo (onscreen); - break; - case META_RENDERER_NATIVE_MODE_SURFACELESS: - g_assert_not_reached (); - break; -#ifdef HAVE_EGL_DEVICE - case META_RENDERER_NATIVE_MODE_EGL_DEVICE: - g_clear_object (&onscreen_native->egl.dumb_fb); - - if (onscreen_native->egl.stream != EGL_NO_STREAM_KHR) - { - MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native); - CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer); - CoglRenderer *cogl_renderer = cogl_context->display->renderer; - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - - meta_egl_destroy_stream (egl, - cogl_renderer_egl->edpy, - onscreen_native->egl.stream, - NULL); - onscreen_native->egl.stream = EGL_NO_STREAM_KHR; - } - break; -#endif /* HAVE_EGL_DEVICE */ - } - - G_OBJECT_CLASS (meta_onscreen_native_parent_class)->dispose (object); - - g_clear_pointer (&onscreen_native->gbm.surface, gbm_surface_destroy); - g_clear_pointer (&onscreen_native->secondary_gpu_state, - secondary_gpu_state_free); -} - -static void -meta_onscreen_native_init (MetaOnscreenNative *onscreen_native) -{ -} - -static void -meta_onscreen_native_class_init (MetaOnscreenNativeClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - CoglFramebufferClass *framebuffer_class = COGL_FRAMEBUFFER_CLASS (klass); - CoglOnscreenClass *onscreen_class = COGL_ONSCREEN_CLASS (klass); - - object_class->dispose = meta_onscreen_native_dispose; - - framebuffer_class->allocate = meta_onscreen_native_allocate; - - onscreen_class->swap_buffers_with_damage = - meta_onscreen_native_swap_buffers_with_damage; - onscreen_class->direct_scanout = meta_onscreen_native_direct_scanout; -} diff --git a/src/backends/native/meta-onscreen-native.h b/src/backends/native/meta-onscreen-native.h deleted file mode 100644 index 020fc8a14..000000000 --- a/src/backends/native/meta-onscreen-native.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2016-2020 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_ONSCREEN_NATIVE_H -#define META_ONSCREEN_NATIVE_H - -#include - -#include "backends/meta-backend-types.h" -#include "backends/native/meta-backend-native-types.h" -#include "clutter/clutter.h" -#include "cogl/cogl.h" - -#define META_TYPE_ONSCREEN_NATIVE (meta_onscreen_native_get_type ()) -G_DECLARE_FINAL_TYPE (MetaOnscreenNative, meta_onscreen_native, - META, ONSCREEN_NATIVE, - CoglOnscreenEgl) - -void meta_renderer_native_release_onscreen (CoglOnscreen *onscreen); - -void meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, - ClutterFrame *frame); - -void meta_onscreen_native_dummy_power_save_page_flip (CoglOnscreen *onscreen); - -gboolean meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen, - uint32_t drm_format, - uint64_t drm_modifier, - uint32_t stride); - -void meta_onscreen_native_set_view (CoglOnscreen *onscreen, - MetaRendererView *view); - -MetaOnscreenNative * meta_onscreen_native_new (MetaRendererNative *renderer_native, - MetaGpuKms *render_gpu, - MetaOutput *output, - MetaCrtc *crtc, - CoglContext *cogl_context, - int width, - int height); - -#endif /* META_ONSCREEN_NATIVE_H */ diff --git a/src/backends/native/meta-output-kms.c b/src/backends/native/meta-output-kms.c deleted file mode 100644 index f35cdf04e..000000000 --- a/src/backends/native/meta-output-kms.c +++ /dev/null @@ -1,414 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2013-2017 Red Hat - * Copyright (C) 2018 DisplayLink (UK) Ltd. - * - * 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 "backends/native/meta-output-kms.h" - -#include -#include -#include - -#include "backends/meta-crtc.h" -#include "backends/native/meta-kms-connector.h" -#include "backends/native/meta-kms-device.h" -#include "backends/native/meta-kms-mode.h" -#include "backends/native/meta-kms-update.h" -#include "backends/native/meta-kms-utils.h" -#include "backends/native/meta-crtc-kms.h" -#include "backends/native/meta-crtc-mode-kms.h" - -#define SYNC_TOLERANCE 0.01 /* 1 percent */ - -struct _MetaOutputKms -{ - MetaOutputNative parent; - - MetaKmsConnector *kms_connector; -}; - -G_DEFINE_TYPE (MetaOutputKms, meta_output_kms, META_TYPE_OUTPUT_NATIVE) - -MetaKmsConnector * -meta_output_kms_get_kms_connector (MetaOutputKms *output_kms) -{ - return output_kms->kms_connector; -} - -void -meta_output_kms_set_underscan (MetaOutputKms *output_kms, - MetaKmsUpdate *kms_update) -{ - MetaOutput *output = META_OUTPUT (output_kms); - const MetaOutputInfo *output_info = meta_output_get_info (output); - - if (!output_info->supports_underscanning) - return; - - if (meta_output_is_underscanning (output)) - { - MetaCrtc *crtc; - const MetaCrtcConfig *crtc_config; - const MetaCrtcModeInfo *crtc_mode_info; - uint64_t hborder, vborder; - - crtc = meta_output_get_assigned_crtc (output); - crtc_config = meta_crtc_get_config (crtc); - crtc_mode_info = meta_crtc_mode_get_info (crtc_config->mode); - - hborder = MIN (128, (uint64_t) round (crtc_mode_info->width * 0.05)); - vborder = MIN (128, (uint64_t) round (crtc_mode_info->height * 0.05)); - - g_debug ("Setting underscan of connector %s to %" G_GUINT64_FORMAT " x %" G_GUINT64_FORMAT, - meta_kms_connector_get_name (output_kms->kms_connector), - hborder, vborder); - - meta_kms_update_set_underscanning (kms_update, - output_kms->kms_connector, - hborder, vborder); - } - else - { - g_debug ("Unsetting underscan of connector %s", - meta_kms_connector_get_name (output_kms->kms_connector)); - - meta_kms_update_unset_underscanning (kms_update, - output_kms->kms_connector); - } -} - -uint32_t -meta_output_kms_get_connector_id (MetaOutputKms *output_kms) -{ - return meta_kms_connector_get_id (output_kms->kms_connector); -} - -gboolean -meta_output_kms_can_clone (MetaOutputKms *output_kms, - MetaOutputKms *other_output_kms) -{ - return meta_kms_connector_can_clone (output_kms->kms_connector, - other_output_kms->kms_connector); -} - -static GBytes * -meta_output_kms_read_edid (MetaOutputNative *output_native) -{ - MetaOutputKms *output_kms = META_OUTPUT_KMS (output_native); - const MetaKmsConnectorState *connector_state; - GBytes *edid_data; - - connector_state = - meta_kms_connector_get_current_state (output_kms->kms_connector); - edid_data = connector_state->edid_data; - if (!edid_data) - return NULL; - - return g_bytes_new_from_bytes (edid_data, 0, g_bytes_get_size (edid_data)); -} - -static void -add_common_modes (MetaOutputInfo *output_info, - MetaGpuKms *gpu_kms) -{ - MetaCrtcMode *crtc_mode; - GPtrArray *array; - float refresh_rate; - unsigned i; - unsigned max_hdisplay = 0; - unsigned max_vdisplay = 0; - float max_refresh_rate = 0.0; - float max_bandwidth = 0.0; - MetaKmsDevice *kms_device; - MetaKmsModeFlag flag_filter; - GList *l; - - for (i = 0; i < output_info->n_modes; i++) - { - MetaCrtcMode *crtc_mode = output_info->modes[i]; - MetaCrtcModeKms *crtc_mode_kms = META_CRTC_MODE_KMS (crtc_mode); - MetaKmsMode *kms_mode = meta_crtc_mode_kms_get_kms_mode (crtc_mode_kms); - const drmModeModeInfo *drm_mode = meta_kms_mode_get_drm_mode (kms_mode); - float bandwidth; - - refresh_rate = meta_calculate_drm_mode_refresh_rate (drm_mode); - bandwidth = refresh_rate * drm_mode->hdisplay * drm_mode->vdisplay; - max_hdisplay = MAX (max_hdisplay, drm_mode->hdisplay); - max_vdisplay = MAX (max_vdisplay, drm_mode->vdisplay); - max_refresh_rate = MAX (max_refresh_rate, refresh_rate); - max_bandwidth = MAX (max_bandwidth, bandwidth); - } - - max_refresh_rate = MAX (max_refresh_rate, 60.0); - max_refresh_rate *= (1 + SYNC_TOLERANCE); - - kms_device = meta_gpu_kms_get_kms_device (gpu_kms); - - array = g_ptr_array_new (); - - if (max_hdisplay > max_vdisplay) - flag_filter = META_KMS_MODE_FLAG_FALLBACK_LANDSCAPE; - else - flag_filter = META_KMS_MODE_FLAG_FALLBACK_PORTRAIT; - - for (l = meta_kms_device_get_fallback_modes (kms_device); l; l = l->next) - { - MetaKmsMode *fallback_mode = l->data; - const drmModeModeInfo *drm_mode; - float bandwidth; - - if (!(meta_kms_mode_get_flags (fallback_mode) & flag_filter)) - continue; - - drm_mode = meta_kms_mode_get_drm_mode (fallback_mode); - refresh_rate = meta_calculate_drm_mode_refresh_rate (drm_mode); - bandwidth = refresh_rate * drm_mode->hdisplay * drm_mode->vdisplay; - if (drm_mode->hdisplay > max_hdisplay || - drm_mode->vdisplay > max_vdisplay || - refresh_rate > max_refresh_rate || - bandwidth > max_bandwidth) - continue; - - crtc_mode = meta_gpu_kms_get_mode_from_kms_mode (gpu_kms, fallback_mode); - g_ptr_array_add (array, crtc_mode); - } - - output_info->modes = g_renew (MetaCrtcMode *, output_info->modes, - output_info->n_modes + array->len); - memcpy (output_info->modes + output_info->n_modes, array->pdata, - array->len * sizeof (MetaCrtcMode *)); - output_info->n_modes += array->len; - - g_ptr_array_free (array, TRUE); -} - -static int -compare_modes (const void *one, - const void *two) -{ - MetaCrtcMode *crtc_mode_one = *(MetaCrtcMode **) one; - MetaCrtcMode *crtc_mode_two = *(MetaCrtcMode **) two; - const MetaCrtcModeInfo *crtc_mode_info_one = - meta_crtc_mode_get_info (crtc_mode_one); - const MetaCrtcModeInfo *crtc_mode_info_two = - meta_crtc_mode_get_info (crtc_mode_two); - - if (crtc_mode_info_one->width != crtc_mode_info_two->width) - return crtc_mode_info_one->width > crtc_mode_info_two->width ? -1 : 1; - if (crtc_mode_info_one->height != crtc_mode_info_two->height) - return crtc_mode_info_one->height > crtc_mode_info_two->height ? -1 : 1; - if (crtc_mode_info_one->refresh_rate != crtc_mode_info_two->refresh_rate) - return (crtc_mode_info_one->refresh_rate > crtc_mode_info_two->refresh_rate - ? -1 : 1); - - return g_strcmp0 (meta_crtc_mode_get_name (crtc_mode_one), - meta_crtc_mode_get_name (crtc_mode_two)); -} - -static gboolean -init_output_modes (MetaOutputInfo *output_info, - MetaGpuKms *gpu_kms, - MetaKmsConnector *kms_connector, - GError **error) -{ - const MetaKmsConnectorState *connector_state; - GList *l; - int i; - - connector_state = meta_kms_connector_get_current_state (kms_connector); - - output_info->preferred_mode = NULL; - - output_info->n_modes = g_list_length (connector_state->modes); - output_info->modes = g_new0 (MetaCrtcMode *, output_info->n_modes); - for (l = connector_state->modes, i = 0; l; l = l->next, i++) - { - MetaKmsMode *kms_mode = l->data; - const drmModeModeInfo *drm_mode = meta_kms_mode_get_drm_mode (kms_mode); - MetaCrtcMode *crtc_mode; - - crtc_mode = meta_gpu_kms_get_mode_from_kms_mode (gpu_kms, kms_mode); - output_info->modes[i] = crtc_mode; - if (drm_mode->type & DRM_MODE_TYPE_PREFERRED) - output_info->preferred_mode = output_info->modes[i]; - } - - if (connector_state->has_scaling) - { - meta_topic (META_DEBUG_KMS, "Adding common modes to connector %u on %s", - meta_kms_connector_get_id (kms_connector), - meta_gpu_kms_get_file_path (gpu_kms)); - add_common_modes (output_info, gpu_kms); - } - - if (!output_info->modes) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "No modes available"); - return FALSE; - } - - qsort (output_info->modes, output_info->n_modes, - sizeof (MetaCrtcMode *), compare_modes); - - if (!output_info->preferred_mode) - output_info->preferred_mode = output_info->modes[0]; - - return TRUE; -} - -static MetaConnectorType -meta_kms_connector_type_from_drm (uint32_t drm_connector_type) -{ - g_warn_if_fail (drm_connector_type < META_CONNECTOR_TYPE_META); - - return (MetaConnectorType) drm_connector_type; -} - -MetaOutputKms * -meta_output_kms_new (MetaGpuKms *gpu_kms, - MetaKmsConnector *kms_connector, - MetaOutput *old_output, - GError **error) -{ - MetaGpu *gpu = META_GPU (gpu_kms); - uint32_t connector_id; - uint32_t gpu_id; - g_autoptr (MetaOutputInfo) output_info = NULL; - MetaOutput *output; - MetaOutputKms *output_kms; - uint32_t drm_connector_type; - const MetaKmsConnectorState *connector_state; - GArray *crtcs; - GList *l; - - gpu_id = meta_gpu_kms_get_id (gpu_kms); - connector_id = meta_kms_connector_get_id (kms_connector); - - output_info = meta_output_info_new (); - output_info->name = g_strdup (meta_kms_connector_get_name (kms_connector)); - - connector_state = meta_kms_connector_get_current_state (kms_connector); - - output_info->panel_orientation_transform = - connector_state->panel_orientation_transform; - if (meta_monitor_transform_is_rotated (output_info->panel_orientation_transform)) - { - output_info->width_mm = connector_state->height_mm; - output_info->height_mm = connector_state->width_mm; - } - else - { - output_info->width_mm = connector_state->width_mm; - output_info->height_mm = connector_state->height_mm; - } - - if (!init_output_modes (output_info, gpu_kms, kms_connector, error)) - return NULL; - - crtcs = g_array_new (FALSE, FALSE, sizeof (MetaCrtc *)); - - for (l = meta_gpu_get_crtcs (gpu); l; l = l->next) - { - MetaCrtcKms *crtc_kms = META_CRTC_KMS (l->data); - MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); - uint32_t crtc_idx; - - crtc_idx = meta_kms_crtc_get_idx (kms_crtc); - if (connector_state->common_possible_crtcs & (1 << crtc_idx)) - g_array_append_val (crtcs, crtc_kms); - } - - output_info->n_possible_crtcs = crtcs->len; - output_info->possible_crtcs = (MetaCrtc **) g_array_free (crtcs, FALSE); - - output_info->suggested_x = connector_state->suggested_x; - output_info->suggested_y = connector_state->suggested_y; - output_info->hotplug_mode_update = connector_state->hotplug_mode_update; - output_info->supports_underscanning = - meta_kms_connector_is_underscanning_supported (kms_connector); - - meta_output_info_parse_edid (output_info, connector_state->edid_data); - - drm_connector_type = meta_kms_connector_get_connector_type (kms_connector); - output_info->connector_type = - meta_kms_connector_type_from_drm (drm_connector_type); - - output_info->tile_info = connector_state->tile_info; - - output = g_object_new (META_TYPE_OUTPUT_KMS, - "id", ((uint64_t) gpu_id << 32) | connector_id, - "gpu", gpu, - "info", output_info, - NULL); - output_kms = META_OUTPUT_KMS (output); - output_kms->kms_connector = kms_connector; - - if (connector_state->current_crtc_id) - { - for (l = meta_gpu_get_crtcs (gpu); l; l = l->next) - { - MetaCrtc *crtc = l->data; - - if (meta_crtc_get_id (crtc) == connector_state->current_crtc_id) - { - MetaOutputAssignment output_assignment; - - if (old_output) - { - output_assignment = (MetaOutputAssignment) { - .is_primary = meta_output_is_primary (old_output), - .is_presentation = meta_output_is_presentation (old_output), - }; - } - else - { - output_assignment = (MetaOutputAssignment) { - .is_primary = FALSE, - .is_presentation = FALSE, - }; - } - meta_output_assign_crtc (output, crtc, &output_assignment); - break; - } - } - } - else - { - meta_output_unassign_crtc (output); - } - - return output_kms; -} - -static void -meta_output_kms_init (MetaOutputKms *output_kms) -{ -} - -static void -meta_output_kms_class_init (MetaOutputKmsClass *klass) -{ - MetaOutputNativeClass *output_native_class = META_OUTPUT_NATIVE_CLASS (klass); - - output_native_class->read_edid = meta_output_kms_read_edid; -} diff --git a/src/backends/native/meta-output-kms.h b/src/backends/native/meta-output-kms.h deleted file mode 100644 index 52acc6032..000000000 --- a/src/backends/native/meta-output-kms.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 Red Hat - * Copyright (C) 2018 DisplayLink (UK) Ltd. - * - * 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_OUTPUT_KMS_H -#define META_OUTPUT_KMS_H - -#include "backends/meta-output.h" -#include "backends/native/meta-gpu-kms.h" -#include "backends/native/meta-kms-types.h" -#include "backends/native/meta-output-native.h" - -#define META_TYPE_OUTPUT_KMS (meta_output_kms_get_type ()) -G_DECLARE_FINAL_TYPE (MetaOutputKms, meta_output_kms, - META, OUTPUT_KMS, - MetaOutputNative) - -void meta_output_kms_set_power_save_mode (MetaOutputKms *output_kms, - uint64_t dpms_state, - MetaKmsUpdate *kms_update); - -void meta_output_kms_set_underscan (MetaOutputKms *output_kms, - MetaKmsUpdate *kms_update); - -gboolean meta_output_kms_can_clone (MetaOutputKms *output_kms, - MetaOutputKms *other_output_kms); - -MetaKmsConnector * meta_output_kms_get_kms_connector (MetaOutputKms *output_kms); - -uint32_t meta_output_kms_get_connector_id (MetaOutputKms *output_kms); - -MetaOutputKms * meta_output_kms_new (MetaGpuKms *gpu_kms, - MetaKmsConnector *kms_connector, - MetaOutput *old_output, - GError **error); - -#endif /* META_OUTPUT_KMS_H */ diff --git a/src/backends/native/meta-output-native.c b/src/backends/native/meta-output-native.c deleted file mode 100644 index f21b2ebc6..000000000 --- a/src/backends/native/meta-output-native.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2020 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. - */ - -#include "config.h" - -#include "backends/native/meta-output-native.h" - -G_DEFINE_ABSTRACT_TYPE (MetaOutputNative, meta_output_native, - META_TYPE_OUTPUT) - -GBytes * -meta_output_native_read_edid (MetaOutputNative *output_native) -{ - MetaOutputNativeClass *klass = META_OUTPUT_NATIVE_GET_CLASS (output_native); - - return klass->read_edid (output_native); -} - -static void -meta_output_native_init (MetaOutputNative *output_native) -{ -} - -static void -meta_output_native_class_init (MetaOutputNativeClass *klass) -{ -} diff --git a/src/backends/native/meta-output-native.h b/src/backends/native/meta-output-native.h deleted file mode 100644 index f0475ae3b..000000000 --- a/src/backends/native/meta-output-native.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2020 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_OUTPUT_NATIVE_H -#define META_OUTPUT_NATIVE_H - -#include "backends/meta-output.h" - -#define META_TYPE_OUTPUT_NATIVE (meta_output_native_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaOutputNative, meta_output_native, - META, OUTPUT_NATIVE, - MetaOutput) - -struct _MetaOutputNativeClass -{ - MetaOutputClass parent_class; - - GBytes * (* read_edid) (MetaOutputNative *output_native); -}; - -GBytes * meta_output_native_read_edid (MetaOutputNative *output_native); - -#endif /* META_OUTPUT_NATIVE_H */ diff --git a/src/backends/native/meta-output-virtual.c b/src/backends/native/meta-output-virtual.c deleted file mode 100644 index 12efb3338..000000000 --- a/src/backends/native/meta-output-virtual.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2021 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. - */ - -#include "config.h" - -#include "backends/native/meta-output-virtual.h" - -#include "backends/native/meta-crtc-mode-virtual.h" -#include "backends/native/meta-crtc-virtual.h" -#include "backends/meta-virtual-monitor.h" - -struct _MetaOutputVirtual -{ - MetaOutputNative parent; -}; - -#define META_OUTPUT_VIRTUAL_ID_BIT (((uint64_t) 1) << 63) - -G_DEFINE_TYPE (MetaOutputVirtual, meta_output_virtual, META_TYPE_OUTPUT_NATIVE) - -MetaOutputVirtual * -meta_output_virtual_new (uint64_t id, - const MetaVirtualMonitorInfo *info, - MetaCrtcVirtual *crtc_virtual, - MetaCrtcModeVirtual *crtc_mode_virtual) -{ - g_autoptr (MetaOutputInfo) output_info = NULL; - - output_info = meta_output_info_new (); - output_info->name = g_strdup_printf ("Meta-%" G_GUINT64_FORMAT, id); - - output_info->n_possible_crtcs = 1; - output_info->possible_crtcs = g_new0 (MetaCrtc *, 1); - output_info->possible_crtcs[0] = META_CRTC (crtc_virtual); - - output_info->hotplug_mode_update = FALSE; - output_info->suggested_x = -1; - output_info->suggested_y = -1; - - output_info->connector_type = META_CONNECTOR_TYPE_META; - output_info->vendor = g_strdup (info->vendor); - output_info->product = g_strdup (info->product); - output_info->serial = g_strdup (info->serial); - - output_info->n_modes = 1; - output_info->modes = g_new0 (MetaCrtcMode *, 1); - output_info->modes[0] = META_CRTC_MODE (crtc_mode_virtual); - output_info->preferred_mode = output_info->modes[0]; - - return g_object_new (META_TYPE_OUTPUT_VIRTUAL, - "id", META_OUTPUT_VIRTUAL_ID_BIT | id, - "info", output_info, - NULL); -} - -static void -meta_output_virtual_init (MetaOutputVirtual *output_virtual) -{ -} - -static void -meta_output_virtual_class_init (MetaOutputVirtualClass *klass) -{ -} diff --git a/src/backends/native/meta-output-virtual.h b/src/backends/native/meta-output-virtual.h deleted file mode 100644 index b04579f0d..000000000 --- a/src/backends/native/meta-output-virtual.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2021 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_OUTPUT_VIRTUAL_H -#define META_OUTPUT_VIRTUAL_H - -#include "backends/native/meta-backend-native-types.h" -#include "backends/native/meta-output-native.h" - -#define META_TYPE_OUTPUT_VIRTUAL (meta_output_virtual_get_type ()) -G_DECLARE_FINAL_TYPE (MetaOutputVirtual, meta_output_virtual, - META, OUTPUT_VIRTUAL, - MetaOutputNative) - -MetaOutputVirtual * meta_output_virtual_new (uint64_t id, - const MetaVirtualMonitorInfo *info, - MetaCrtcVirtual *crtc_virtual, - MetaCrtcModeVirtual *crtc_mode_virtual); - -#endif /* META_OUTPUT_VIRTUAL_H */ diff --git a/src/backends/native/meta-pointer-constraint-native.c b/src/backends/native/meta-pointer-constraint-native.c deleted file mode 100644 index 6a1c066ad..000000000 --- a/src/backends/native/meta-pointer-constraint-native.c +++ /dev/null @@ -1,694 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015-2020 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#include "config.h" - -#include -#include - -#include "core/meta-border.h" -#include "meta-pointer-constraint-native.h" - -struct _MetaPointerConstraintImplNative -{ - MetaPointerConstraintImpl parent; - MetaPointerConstraint *constraint; - cairo_region_t *region; -}; - -G_DEFINE_TYPE (MetaPointerConstraintImplNative, - meta_pointer_constraint_impl_native, - META_TYPE_POINTER_CONSTRAINT_IMPL); - -typedef struct _MetaBox -{ - int x1; - int y1; - int x2; - int y2; -} MetaBox; - -static MetaBorder * -add_border (GArray *borders, - float x1, - float y1, - float x2, - float y2, - MetaBorderMotionDirection blocking_directions) -{ - MetaBorder border; - - border = (MetaBorder) { - .line = (MetaLine2) { - .a = (MetaVector2) { - .x = x1, - .y = y1, - }, - .b = (MetaVector2) { - .x = x2, - .y = y2, - }, - }, - .blocking_directions = blocking_directions, - }; - - g_array_append_val (borders, border); - - return &g_array_index (borders, MetaBorder, borders->len - 1); -} - -static gint -compare_lines_x (gconstpointer a, - gconstpointer b) -{ - const MetaBorder *border_a = a; - const MetaBorder *border_b = b; - - if (border_a->line.a.x == border_b->line.a.x) - return border_a->line.b.x < border_b->line.b.x; - else - return border_a->line.a.x > border_b->line.a.x; -} - -static void -add_non_overlapping_edges (MetaBox *boxes, - unsigned int band_above_start, - unsigned int band_below_start, - unsigned int band_below_end, - GArray *borders) -{ - unsigned int i; - GArray *band_merge; - MetaBorder *border; - MetaBorder *prev_border; - MetaBorder *new_border; - - band_merge = g_array_new (FALSE, FALSE, sizeof *border); - - /* Add bottom band of previous row, and top band of current row, and - * sort them so lower left x coordinate comes first. If there are two - * borders with the same left x coordinate, the wider one comes first. - */ - for (i = band_above_start; i < band_below_start; i++) - { - MetaBox *box = &boxes[i]; - add_border (band_merge, box->x1, box->y2, box->x2, box->y2, - META_BORDER_MOTION_DIRECTION_POSITIVE_Y); - } - for (i = band_below_start; i < band_below_end; i++) - { - MetaBox *box= &boxes[i]; - add_border (band_merge, box->x1, box->y1, box->x2, box->y1, - META_BORDER_MOTION_DIRECTION_NEGATIVE_Y); - } - g_array_sort (band_merge, compare_lines_x); - - /* Combine the two combined bands so that any overlapping border is - * eliminated. */ - prev_border = NULL; - for (i = 0; i < band_merge->len; i++) - { - border = &g_array_index (band_merge, MetaBorder, i); - - g_assert (border->line.a.y == border->line.b.y); - g_assert (!prev_border || - prev_border->line.a.y == border->line.a.y); - g_assert (!prev_border || - (prev_border->line.a.x != border->line.a.x || - prev_border->line.b.x != border->line.b.x)); - g_assert (!prev_border || - prev_border->line.a.x <= border->line.a.x); - - if (prev_border && - prev_border->line.a.x == border->line.a.x) - { - /* - * ------------ + - * ------- = - * [ ]----- - */ - prev_border->line.a.x = border->line.b.x; - } - else if (prev_border && - prev_border->line.b.x == border->line.b.x) - { - /* - * ------------ + - * ------ = - * ------[ ] - */ - prev_border->line.b.x = border->line.a.x; - } - else if (prev_border && - prev_border->line.b.x == border->line.a.x) - { - /* - * -------- + - * ------ = - * -------------- - */ - prev_border->line.b.x = border->line.b.x; - } - else if (prev_border && - prev_border->line.b.x >= border->line.a.x) - { - /* - * --------------- + - * ------ = - * -----[ ]---- - */ - new_border = add_border (borders, - border->line.b.x, - border->line.b.y, - prev_border->line.b.x, - prev_border->line.b.y, - prev_border->blocking_directions); - prev_border->line.b.x = border->line.a.x; - prev_border = new_border; - } - else - { - g_assert (!prev_border || - prev_border->line.b.x < border->line.a.x); - /* - * First border or non-overlapping. - * - * ----- + - * ----- = - * ----- ----- - */ - g_array_append_val (borders, *border); - prev_border = &g_array_index (borders, MetaBorder, borders->len - 1); - } - } - - g_array_free (band_merge, FALSE); -} - -static void -add_band_bottom_edges (MetaBox *boxes, - int band_start, - int band_end, - GArray *borders) -{ - int i; - - for (i = band_start; i < band_end; i++) - { - add_border (borders, - boxes[i].x1, boxes[i].y2, - boxes[i].x2, boxes[i].y2, - META_BORDER_MOTION_DIRECTION_POSITIVE_Y); - } -} - -static void -region_to_outline (cairo_region_t *region, - GArray *borders) -{ - MetaBox *boxes; - int num_boxes; - int i; - int top_most, bottom_most; - int current_roof; - int prev_top; - int band_start, prev_band_start; - - /* - * Remove any overlapping lines from the set of rectangles. Note that - * pixman regions are grouped as rows of rectangles, where rectangles - * in one row never touch or overlap and are all of the same height. - * - * -------- --- -------- --- - * | | | | | | | | - * ----------====---- --- ----------- ----- --- - * | | => | | - * ----==========--------- ----- ---------- - * | | | | - * ------------------- ------------------- - * - */ - - num_boxes = cairo_region_num_rectangles (region); - boxes = g_new (MetaBox, num_boxes); - for (i = 0; i < num_boxes; i++) - { - cairo_rectangle_int_t rect; - cairo_region_get_rectangle (region, i, &rect); - boxes[i] = (MetaBox) { - .x1 = rect.x, - .y1 = rect.y, - .x2 = rect.x + rect.width, - .y2 = rect.y + rect.height, - }; - } - prev_top = 0; - top_most = boxes[0].y1; - current_roof = top_most; - bottom_most = boxes[num_boxes - 1].y2; - band_start = 0; - prev_band_start = 0; - for (i = 0; i < num_boxes; i++) - { - /* Detect if there is a vertical empty space, and add the lower - * level of the previous band if so was the case. */ - if (i > 0 && - boxes[i].y1 != prev_top && - boxes[i].y1 != boxes[i - 1].y2) - { - current_roof = boxes[i].y1; - add_band_bottom_edges (boxes, - band_start, - i, - borders); - } - - /* Special case adding the last band, since it won't be handled - * by the band change detection below. */ - if (boxes[i].y1 != current_roof && i == num_boxes - 1) - { - if (boxes[i].y1 != prev_top) - { - /* The last band is a single box, so we don't - * have a prev_band_start to tell us when the - * previous band started. */ - add_non_overlapping_edges (boxes, - band_start, - i, - i + 1, - borders); - } - else - { - add_non_overlapping_edges (boxes, - prev_band_start, - band_start, - i + 1, - borders); - } - } - - /* Detect when passing a band and combine the top border of the - * just passed band with the bottom band of the previous band. - */ - if (boxes[i].y1 != top_most && boxes[i].y1 != prev_top) - { - /* Combine the two passed bands. */ - if (prev_top != current_roof) - { - add_non_overlapping_edges (boxes, - prev_band_start, - band_start, - i, - borders); - } - - prev_band_start = band_start; - band_start = i; - } - - /* Add the top border if the box is part of the current roof. */ - if (boxes[i].y1 == current_roof) - { - add_border (borders, - boxes[i].x1, boxes[i].y1, - boxes[i].x2, boxes[i].y1, - META_BORDER_MOTION_DIRECTION_NEGATIVE_Y); - } - - /* Add the bottom border of the last band. */ - if (boxes[i].y2 == bottom_most) - { - add_border (borders, - boxes[i].x1, boxes[i].y2, - boxes[i].x2, boxes[i].y2, - META_BORDER_MOTION_DIRECTION_POSITIVE_Y); - } - - /* Always add the left border. */ - add_border (borders, - boxes[i].x1, boxes[i].y1, - boxes[i].x1, boxes[i].y2, - META_BORDER_MOTION_DIRECTION_NEGATIVE_X); - - /* Always add the right border. */ - add_border (borders, - boxes[i].x2, boxes[i].y1, - boxes[i].x2, boxes[i].y2, - META_BORDER_MOTION_DIRECTION_POSITIVE_X); - - prev_top = boxes[i].y1; - } - - g_free (boxes); -} - -static MetaBorder * -get_closest_border (GArray *borders, - MetaLine2 *motion, - uint32_t directions) -{ - MetaBorder *border; - MetaVector2 intersection; - MetaVector2 delta; - float distance_2; - MetaBorder *closest_border = NULL; - float closest_distance_2 = DBL_MAX; - unsigned int i; - - for (i = 0; i < borders->len; i++) - { - border = &g_array_index (borders, MetaBorder, i); - - if (!meta_border_is_blocking_directions (border, directions)) - continue; - - if (!meta_line2_intersects_with (&border->line, motion, &intersection)) - continue; - - delta = meta_vector2_subtract (intersection, motion->a); - distance_2 = delta.x*delta.x + delta.y*delta.y; - if (distance_2 < closest_distance_2) - { - closest_border = border; - closest_distance_2 = distance_2; - } - } - - return closest_border; -} - -static void -clamp_to_border (MetaBorder *border, - MetaLine2 *motion, - uint32_t *motion_dir) -{ - /* - * When clamping either rightward or downward motions, the motion needs to be - * clamped so that the destination coordinate does not end up on the border - * (see weston_pointer_clamp_event_to_region). Do this by clamping such - * motions to the border minus the smallest possible wl_fixed_t value. - * - * When clamping in either leftward or upward motion, the resulting coordinate - * needs to be clamped so that it is enough on the inside to avoid the - * inaccuracies of clutter's stage to actor transformation algorithm (the one - * used in clutter_actor_transform_stage_point) to make it end up outside the - * next motion. It also needs to be clamped so that to the wl_fixed_t - * coordinate may still be right on the border (i.e. at .0). Testing shows - * that the smallest wl_fixed_t value divided by 10 is small enough to make - * the wl_fixed_t coordinate .0 and large enough to avoid the inaccuracies of - * clutters transform algorithm. - */ - if (meta_border_is_horizontal (border)) - { - if (*motion_dir & META_BORDER_MOTION_DIRECTION_POSITIVE_Y) - motion->b.y = border->line.a.y - wl_fixed_to_double (1); - else - motion->b.y = border->line.a.y + wl_fixed_to_double (1) / 10; - *motion_dir &= ~(META_BORDER_MOTION_DIRECTION_POSITIVE_Y | - META_BORDER_MOTION_DIRECTION_NEGATIVE_Y); - } - else - { - if (*motion_dir & META_BORDER_MOTION_DIRECTION_POSITIVE_X) - motion->b.x = border->line.a.x - wl_fixed_to_double (1); - else - motion->b.x = border->line.a.x + wl_fixed_to_double (1) / 10; - *motion_dir &= ~(META_BORDER_MOTION_DIRECTION_POSITIVE_X | - META_BORDER_MOTION_DIRECTION_NEGATIVE_X); - } -} - -static uint32_t -get_motion_directions (MetaLine2 *motion) -{ - uint32_t directions = 0; - - if (motion->a.x < motion->b.x) - directions |= META_BORDER_MOTION_DIRECTION_POSITIVE_X; - else if (motion->a.x > motion->b.x) - directions |= META_BORDER_MOTION_DIRECTION_NEGATIVE_X; - if (motion->a.y < motion->b.y) - directions |= META_BORDER_MOTION_DIRECTION_POSITIVE_Y; - else if (motion->a.y > motion->b.y) - directions |= META_BORDER_MOTION_DIRECTION_NEGATIVE_Y; - - return directions; -} - -static void -meta_pointer_constraint_impl_native_constraint (MetaPointerConstraintImpl *constraint_impl, - ClutterInputDevice *device, - uint32_t time, - float prev_x, - float prev_y, - float *x_inout, - float *y_inout) -{ - MetaPointerConstraintImplNative *constraint_impl_native; - cairo_region_t *region; - float x, y; - GArray *borders; - MetaLine2 motion; - MetaBorder *closest_border; - uint32_t directions; - - constraint_impl_native = META_POINTER_CONSTRAINT_IMPL_NATIVE (constraint_impl); - - region = cairo_region_reference (constraint_impl_native->region); - x = *x_inout; - y = *y_inout; - - /* For motions in a positive direction on any axis, append the smallest - * possible value representable in a Wayland absolute coordinate. This is - * in order to avoid not clamping motion that as a floating point number - * won't be clamped, but will be rounded up to be outside of the range - * of wl_fixed_t. */ - if (x > prev_x) - x += (float) wl_fixed_to_double(1); - if (y > prev_y) - y += (float) wl_fixed_to_double(1); - - borders = g_array_new (FALSE, FALSE, sizeof (MetaBorder)); - - /* - * Generate borders given the confine region we are to use. The borders - * are defined to be the outer region of the allowed area. This means - * top/left borders are "within" the allowed area, while bottom/right - * borders are outside. This needs to be considered when clamping - * confined motion vectors. - */ - region_to_outline (region, borders); - cairo_region_destroy (region); - - motion = (MetaLine2) { - .a = (MetaVector2) { - .x = prev_x, - .y = prev_y, - }, - .b = (MetaVector2) { - .x = x, - .y = y, - }, - }; - directions = get_motion_directions (&motion); - - while (directions) - { - closest_border = get_closest_border (borders, - &motion, - directions); - if (closest_border) - clamp_to_border (closest_border, &motion, &directions); - else - break; - } - - *x_inout = motion.b.x; - *y_inout = motion.b.y; - g_array_free (borders, FALSE); -} - -static float -point_to_border_distance_2 (MetaBorder *border, - float x, - float y) -{ - float orig_x, orig_y; - float dx, dy; - - if (meta_border_is_horizontal (border)) - { - if (x < border->line.a.x) - orig_x = border->line.a.x; - else if (x > border->line.b.x) - orig_x = border->line.b.x; - else - orig_x = x; - orig_y = border->line.a.y; - } - else - { - if (y < border->line.a.y) - orig_y = border->line.a.y; - else if (y > border->line.b.y) - orig_y = border->line.b.y; - else - orig_y = y; - orig_x = border->line.a.x; - } - - dx = fabsf (orig_x - x); - dy = fabsf (orig_y - y); - return dx*dx + dy*dy; -} - -static void -closest_point_behind_border (MetaBorder *border, - float *sx, - float *sy) -{ - switch (border->blocking_directions) - { - case META_BORDER_MOTION_DIRECTION_POSITIVE_X: - case META_BORDER_MOTION_DIRECTION_NEGATIVE_X: - if (border->blocking_directions == META_BORDER_MOTION_DIRECTION_POSITIVE_X) - *sx = border->line.a.x - wl_fixed_to_double (1); - else - *sx = border->line.a.x + wl_fixed_to_double (1); - if (*sy < border->line.a.y) - *sy = border->line.a.y + wl_fixed_to_double (1); - else if (*sy > border->line.b.y) - *sy = border->line.b.y - wl_fixed_to_double (1); - break; - case META_BORDER_MOTION_DIRECTION_POSITIVE_Y: - case META_BORDER_MOTION_DIRECTION_NEGATIVE_Y: - if (border->blocking_directions == META_BORDER_MOTION_DIRECTION_POSITIVE_Y) - *sy = border->line.a.y - wl_fixed_to_double (1); - else - *sy = border->line.a.y + wl_fixed_to_double (1); - if (*sx < border->line.a.x) - *sx = border->line.a.x + wl_fixed_to_double (1); - else if (*sx > (border->line.b.x)) - *sx = border->line.b.x - wl_fixed_to_double (1); - break; - } -} - -static void -meta_pointer_constraint_impl_native_ensure_constrained (MetaPointerConstraintImpl *constraint_impl, - ClutterInputDevice *device) -{ - MetaPointerConstraintImplNative *constraint_impl_native; - graphene_point_t point; - cairo_region_t *region; - float x; - float y; - - constraint_impl_native = META_POINTER_CONSTRAINT_IMPL_NATIVE (constraint_impl); - region = cairo_region_reference (constraint_impl_native->region); - - clutter_seat_query_state (clutter_input_device_get_seat (device), - device, NULL, &point, NULL); - x = point.x; - y = point.y; - - if (!cairo_region_contains_point (region, (int) x, (int) y)) - { - GArray *borders; - float closest_distance_2 = FLT_MAX; - MetaBorder *closest_border = NULL; - ClutterSeat *seat; - unsigned int i; - - borders = g_array_new (FALSE, FALSE, sizeof (MetaBorder)); - - region_to_outline (region, borders); - - for (i = 0; i < borders->len; i++) - { - MetaBorder *border = &g_array_index (borders, MetaBorder, i); - float distance_2; - - distance_2 = point_to_border_distance_2 (border, x, y); - if (distance_2 < closest_distance_2) - { - closest_border = border; - closest_distance_2 = distance_2; - } - } - - closest_point_behind_border (closest_border, &x, &y); - - seat = clutter_backend_get_default_seat (clutter_get_default_backend ()); - clutter_seat_warp_pointer (seat, x, y); - } - - cairo_region_destroy (region); -} - -static void -meta_pointer_constraint_impl_native_finalize (GObject *object) -{ - MetaPointerConstraintImplNative *constraint_impl_native; - - constraint_impl_native = META_POINTER_CONSTRAINT_IMPL_NATIVE (object); - g_clear_pointer (&constraint_impl_native->region, cairo_region_destroy); - - G_OBJECT_CLASS (meta_pointer_constraint_impl_native_parent_class)->finalize (object); -} - -static void -meta_pointer_constraint_impl_native_init (MetaPointerConstraintImplNative *constraint_impl_native) -{ -} - -static void -meta_pointer_constraint_impl_native_class_init (MetaPointerConstraintImplNativeClass *klass) -{ - MetaPointerConstraintImplClass *constraint_impl_class; - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_pointer_constraint_impl_native_finalize; - - constraint_impl_class = META_POINTER_CONSTRAINT_IMPL_CLASS (klass); - constraint_impl_class->constrain = meta_pointer_constraint_impl_native_constraint; - constraint_impl_class->ensure_constrained = - meta_pointer_constraint_impl_native_ensure_constrained; -} - - -MetaPointerConstraintImpl * -meta_pointer_constraint_impl_native_new (MetaPointerConstraint *constraint, - const cairo_region_t *region) -{ - MetaPointerConstraintImplNative *constraint_impl; - - constraint_impl = g_object_new (META_TYPE_POINTER_CONSTRAINT_IMPL_NATIVE, - NULL); - constraint_impl->constraint = constraint; - constraint_impl->region = cairo_region_copy (region); - - return META_POINTER_CONSTRAINT_IMPL (constraint_impl); -} diff --git a/src/backends/native/meta-pointer-constraint-native.h b/src/backends/native/meta-pointer-constraint-native.h deleted file mode 100644 index 83a2e575d..000000000 --- a/src/backends/native/meta-pointer-constraint-native.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2020 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Carlos Garnacho - */ - -#ifndef META_POINTER_CONSTRAINT_NATIVE_H -#define META_POINTER_CONSTRAINT_NATIVE_H - -#include - -#include "clutter/clutter.h" -#include "backends/meta-pointer-constraint.h" - -G_BEGIN_DECLS - -#define META_TYPE_POINTER_CONSTRAINT_IMPL_NATIVE (meta_pointer_constraint_impl_native_get_type ()) -G_DECLARE_FINAL_TYPE (MetaPointerConstraintImplNative, - meta_pointer_constraint_impl_native, - META, POINTER_CONSTRAINT_IMPL_NATIVE, - MetaPointerConstraintImpl) - -MetaPointerConstraintImpl * meta_pointer_constraint_impl_native_new (MetaPointerConstraint *constraint_impl, - const cairo_region_t *region); - -G_END_DECLS - -#endif /* META_POINTER_CONSTRAINT_NATIVE_H */ diff --git a/src/backends/native/meta-renderer-native-gles3.c b/src/backends/native/meta-renderer-native-gles3.c deleted file mode 100644 index c0eb77554..000000000 --- a/src/backends/native/meta-renderer-native-gles3.c +++ /dev/null @@ -1,160 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 Red Hat - * Copyright (c) 2018 DisplayLink (UK) Ltd. - * - * 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" - -#define GL_GLEXT_PROTOTYPES - -#include "backends/native/meta-renderer-native-gles3.h" - -#include -#include -#include -#include -#include - -#include "backends/meta-egl-ext.h" -#include "backends/meta-gles3.h" -#include "backends/meta-gles3-table.h" - -/* - * GL/gl.h being included may conflict with gl3.h on some architectures. - * Make sure that hasn't happened on any architecture. - */ -#ifdef GL_VERSION_1_1 -#error "Somehow included OpenGL headers when we shouldn't have" -#endif - -static void -paint_egl_image (MetaGles3 *gles3, - EGLImageKHR egl_image, - int width, - int height) -{ - GLuint texture; - GLuint framebuffer; - - meta_gles3_clear_error (gles3); - - GLBAS (gles3, glGenFramebuffers, (1, &framebuffer)); - GLBAS (gles3, glBindFramebuffer, (GL_READ_FRAMEBUFFER, framebuffer)); - - GLBAS (gles3, glActiveTexture, (GL_TEXTURE0)); - GLBAS (gles3, glGenTextures, (1, &texture)); - GLBAS (gles3, glBindTexture, (GL_TEXTURE_2D, texture)); - GLEXT (gles3, glEGLImageTargetTexture2DOES, (GL_TEXTURE_2D, egl_image)); - GLBAS (gles3, glTexParameteri, (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, - GL_NEAREST)); - GLBAS (gles3, glTexParameteri, (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, - GL_NEAREST)); - GLBAS (gles3, glTexParameteri, (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, - GL_CLAMP_TO_EDGE)); - GLBAS (gles3, glTexParameteri, (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, - GL_CLAMP_TO_EDGE)); - GLBAS (gles3, glTexParameteri, (GL_TEXTURE_2D, GL_TEXTURE_WRAP_R_OES, - GL_CLAMP_TO_EDGE)); - - GLBAS (gles3, glFramebufferTexture2D, (GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, texture, 0)); - - GLBAS (gles3, glBindFramebuffer, (GL_READ_FRAMEBUFFER, framebuffer)); - GLBAS (gles3, glBlitFramebuffer, (0, height, width, 0, - 0, 0, width, height, - GL_COLOR_BUFFER_BIT, - GL_NEAREST)); - - GLBAS (gles3, glDeleteTextures, (1, &texture)); - GLBAS (gles3, glDeleteFramebuffers, (1, &framebuffer)); -} - -gboolean -meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, - MetaGles3 *gles3, - EGLDisplay egl_display, - EGLContext egl_context, - EGLSurface egl_surface, - struct gbm_bo *shared_bo, - GError **error) -{ - int shared_bo_fd; - unsigned int width; - unsigned int height; - uint32_t i, n_planes; - uint32_t strides[4] = { 0 }; - uint32_t offsets[4] = { 0 }; - uint64_t modifiers[4] = { 0 }; - int fds[4] = { -1, -1, -1, -1 }; - uint32_t format; - EGLImageKHR egl_image; - gboolean use_modifiers; - - shared_bo_fd = gbm_bo_get_fd (shared_bo); - if (shared_bo_fd < 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to export gbm_bo: %s", strerror (errno)); - return FALSE; - } - - width = gbm_bo_get_width (shared_bo); - height = gbm_bo_get_height (shared_bo); - format = gbm_bo_get_format (shared_bo); - - n_planes = gbm_bo_get_plane_count (shared_bo); - for (i = 0; i < n_planes; i++) - { - strides[i] = gbm_bo_get_stride_for_plane (shared_bo, i); - offsets[i] = gbm_bo_get_offset (shared_bo, i); - modifiers[i] = gbm_bo_get_modifier (shared_bo); - fds[i] = shared_bo_fd; - } - - /* Workaround for https://gitlab.gnome.org/GNOME/mutter/issues/18 */ - if (modifiers[0] == DRM_FORMAT_MOD_LINEAR || - modifiers[0] == DRM_FORMAT_MOD_INVALID) - use_modifiers = FALSE; - else - use_modifiers = TRUE; - - egl_image = meta_egl_create_dmabuf_image (egl, - egl_display, - width, - height, - format, - n_planes, - fds, - strides, - offsets, - use_modifiers ? modifiers : NULL, - error); - close (shared_bo_fd); - - if (!egl_image) - return FALSE; - - paint_egl_image (gles3, egl_image, width, height); - - meta_egl_destroy_image (egl, egl_display, egl_image, NULL); - - return TRUE; -} diff --git a/src/backends/native/meta-renderer-native-gles3.h b/src/backends/native/meta-renderer-native-gles3.h deleted file mode 100644 index 4e7324c8d..000000000 --- a/src/backends/native/meta-renderer-native-gles3.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 Red Hat - * Copyright (c) 2018 DisplayLink (UK) Ltd. - * - * 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_RENDERER_NATIVE_GLES3_H -#define META_RENDERER_NATIVE_GLES3_H - -#include - -#include "backends/meta-egl.h" -#include "backends/meta-gles3.h" - -gboolean meta_renderer_native_gles3_blit_shared_bo (MetaEgl *egl, - MetaGles3 *gles3, - EGLDisplay egl_display, - EGLContext egl_context, - EGLSurface egl_surface, - struct gbm_bo *shared_bo, - GError **error); - -#endif /* META_RENDERER_NATIVE_GLES3_H */ diff --git a/src/backends/native/meta-renderer-native-private.h b/src/backends/native/meta-renderer-native-private.h deleted file mode 100644 index acadb3fff..000000000 --- a/src/backends/native/meta-renderer-native-private.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2011 Intel Corporation. - * Copyright (C) 2016-2020 Red Hat - * Copyright (c) 2018,2019 DisplayLink (UK) Ltd. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#ifndef META_RENDERER_NATIVE_PRIVATE_H -#define META_RENDERER_NATIVE_PRIVATE_H - -#include "backends/meta-gles3.h" -#include "backends/native/meta-renderer-native.h" - -typedef enum _MetaSharedFramebufferCopyMode -{ - /* Zero-copy: primary GPU exports, secondary GPU imports as KMS FB */ - META_SHARED_FRAMEBUFFER_COPY_MODE_ZERO, - /* the secondary GPU will make the copy */ - META_SHARED_FRAMEBUFFER_COPY_MODE_SECONDARY_GPU, - /* - * The copy is made in the primary GPU rendering context, either - * as a CPU copy through Cogl read-pixels or as primary GPU copy - * using glBlitFramebuffer. - */ - META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY -} MetaSharedFramebufferCopyMode; - -typedef struct _MetaRendererNativeGpuData -{ - MetaRendererNative *renderer_native; - - MetaDeviceFile *device_file; - - struct { - struct gbm_device *device; - } gbm; - -#ifdef HAVE_EGL_DEVICE - struct { - EGLDeviceEXT device; - } egl; -#endif - - MetaRendererNativeMode mode; - - EGLDisplay egl_display; - - /* - * Fields used for blitting iGPU framebuffer content onto dGPU framebuffers. - */ - struct { - MetaSharedFramebufferCopyMode copy_mode; - gboolean is_hardware_rendering; - gboolean has_EGL_EXT_image_dma_buf_import_modifiers; - - /* For GPU blit mode */ - EGLContext egl_context; - EGLConfig egl_config; - } secondary; -} MetaRendererNativeGpuData; - -MetaEgl * meta_renderer_native_get_egl (MetaRendererNative *renderer_native); - -MetaGles3 * meta_renderer_native_get_gles3 (MetaRendererNative *renderer_native); - -MetaRendererNativeGpuData * meta_renderer_native_get_gpu_data (MetaRendererNative *renderer_native, - MetaGpuKms *gpu_kms); - -gboolean meta_renderer_native_has_pending_mode_sets (MetaRendererNative *renderer_native); - -gboolean meta_renderer_native_has_pending_mode_set (MetaRendererNative *renderer_native); - -void meta_renderer_native_notify_mode_sets_reset (MetaRendererNative *renderer_native); - -void meta_renderer_native_post_mode_set_updates (MetaRendererNative *renderer_native); - -void meta_renderer_native_queue_power_save_page_flip (MetaRendererNative *renderer_native, - CoglOnscreen *onscreen); - -CoglFramebuffer * meta_renderer_native_create_dma_buf_framebuffer (MetaRendererNative *renderer_native, - int dmabuf_fd, - uint32_t width, - uint32_t height, - uint32_t stride, - uint32_t offset, - uint64_t modifier, - uint32_t drm_format, - GError **error); - -gboolean meta_renderer_native_pop_pending_mode_set (MetaRendererNative *renderer_native, - MetaRendererView *view); - -const CoglWinsysVtable * meta_get_renderer_native_parent_vtable (void); - -#endif /* META_RENDERER_NATIVE_PRIVATE_H */ diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c deleted file mode 100644 index eb6771b80..000000000 --- a/src/backends/native/meta-renderer-native.c +++ /dev/null @@ -1,2264 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2011 Intel Corporation. - * Copyright (C) 2016 Red Hat - * Copyright (c) 2018,2019 DisplayLink (UK) Ltd. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * Authors: - * Rob Bradford (from cogl-winsys-egl-kms.c) - * Kristian Høgsberg (from eglkms.c) - * Benjamin Franzke (from eglkms.c) - * Robert Bragg (from cogl-winsys-egl-kms.c) - * Neil Roberts (from cogl-winsys-egl-kms.c) - * Jonas Ådahl - * - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "backends/meta-gles3.h" -#include "backends/meta-logical-monitor.h" -#include "backends/native/meta-backend-native-private.h" -#include "backends/native/meta-cogl-utils.h" -#include "backends/native/meta-crtc-kms.h" -#include "backends/native/meta-crtc-virtual.h" -#include "backends/native/meta-device-pool.h" -#include "backends/native/meta-kms-device.h" -#include "backends/native/meta-kms.h" -#include "backends/native/meta-onscreen-native.h" -#include "backends/native/meta-renderer-native-private.h" -#include "cogl/cogl.h" -#include "core/boxes-private.h" - -#ifndef EGL_DRM_MASTER_FD_EXT -#define EGL_DRM_MASTER_FD_EXT 0x333C -#endif - -/* added in libdrm 2.4.95 */ -#ifndef DRM_FORMAT_INVALID -#define DRM_FORMAT_INVALID 0 -#endif - -struct _MetaRendererNative -{ - MetaRenderer parent; - - MetaGpuKms *primary_gpu_kms; - - MetaGles3 *gles3; - - gboolean use_modifiers; - - GHashTable *gpu_datas; - - GList *pending_mode_set_views; - gboolean pending_mode_set; - - GList *kept_alive_onscreens; - - GList *power_save_page_flip_onscreens; - guint power_save_page_flip_source_id; -}; - -static void -initable_iface_init (GInitableIface *initable_iface); - -G_DEFINE_TYPE_WITH_CODE (MetaRendererNative, - meta_renderer_native, - META_TYPE_RENDERER, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - initable_iface_init)) - -static const CoglWinsysEGLVtable _cogl_winsys_egl_vtable; -static const CoglWinsysVtable *parent_vtable; - -static gboolean -meta_renderer_native_ensure_gpu_data (MetaRendererNative *renderer_native, - MetaGpuKms *gpu_kms, - GError **error); - -static void -meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native); - -const CoglWinsysVtable * -meta_get_renderer_native_parent_vtable (void) -{ - return parent_vtable; -} - -static void -meta_renderer_native_gpu_data_free (MetaRendererNativeGpuData *renderer_gpu_data) -{ - MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; - MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); - - if (renderer_gpu_data->secondary.egl_context != EGL_NO_CONTEXT) - { - meta_egl_destroy_context (egl, - renderer_gpu_data->egl_display, - renderer_gpu_data->secondary.egl_context, - NULL); - } - - if (renderer_gpu_data->egl_display != EGL_NO_DISPLAY) - meta_egl_terminate (egl, renderer_gpu_data->egl_display, NULL); - - g_clear_pointer (&renderer_gpu_data->gbm.device, gbm_device_destroy); - g_clear_pointer (&renderer_gpu_data->device_file, meta_device_file_release); - g_free (renderer_gpu_data); -} - -MetaRendererNativeGpuData * -meta_renderer_native_get_gpu_data (MetaRendererNative *renderer_native, - MetaGpuKms *gpu_kms) -{ - return g_hash_table_lookup (renderer_native->gpu_datas, gpu_kms); -} - -static MetaRendererNative * -meta_renderer_native_from_gpu (MetaGpuKms *gpu_kms) -{ - MetaBackend *backend = meta_gpu_get_backend (META_GPU (gpu_kms)); - - return META_RENDERER_NATIVE (meta_backend_get_renderer (backend)); -} - -struct gbm_device * -meta_gbm_device_from_gpu (MetaGpuKms *gpu_kms) -{ - MetaRendererNative *renderer_native = meta_renderer_native_from_gpu (gpu_kms); - MetaRendererNativeGpuData *renderer_gpu_data; - - renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, - gpu_kms); - - return renderer_gpu_data->gbm.device; -} - -MetaGpuKms * -meta_renderer_native_get_primary_gpu (MetaRendererNative *renderer_native) -{ - return renderer_native->primary_gpu_kms; -} - -MetaDeviceFile * -meta_renderer_native_get_primary_device_file (MetaRendererNative *renderer_native) -{ - MetaGpuKms *gpu_kms = renderer_native->primary_gpu_kms; - MetaRendererNativeGpuData *renderer_gpu_data; - - renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, - gpu_kms); - return renderer_gpu_data->device_file; -} - -static MetaRendererNativeGpuData * -meta_create_renderer_native_gpu_data (void) -{ - return g_new0 (MetaRendererNativeGpuData, 1); -} - -MetaEgl * -meta_renderer_native_get_egl (MetaRendererNative *renderer_native) -{ - MetaRenderer *renderer = META_RENDERER (renderer_native); - - return meta_backend_get_egl (meta_renderer_get_backend (renderer)); -} - -gboolean -meta_renderer_native_use_modifiers (MetaRendererNative *renderer_native) -{ - return renderer_native->use_modifiers; -} - -MetaGles3 * -meta_renderer_native_get_gles3 (MetaRendererNative *renderer_native) -{ - return renderer_native->gles3; -} - -gboolean -meta_renderer_native_has_pending_mode_sets (MetaRendererNative *renderer_native) -{ - return !!renderer_native->pending_mode_set_views; -} - -gboolean -meta_renderer_native_has_pending_mode_set (MetaRendererNative *renderer_native) -{ - return renderer_native->pending_mode_set; -} - -static void -meta_renderer_native_disconnect (CoglRenderer *cogl_renderer) -{ - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - - g_free (cogl_renderer_egl); -} - -static gboolean -meta_renderer_native_connect (CoglRenderer *cogl_renderer, - GError **error) -{ - CoglRendererEGL *cogl_renderer_egl; - MetaRendererNative *renderer_native = cogl_renderer->custom_winsys_user_data; - MetaGpuKms *gpu_kms; - MetaRendererNativeGpuData *renderer_gpu_data; - - cogl_renderer->winsys = g_new0 (CoglRendererEGL, 1); - cogl_renderer_egl = cogl_renderer->winsys; - - gpu_kms = meta_renderer_native_get_primary_gpu (renderer_native); - renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, - gpu_kms); - - cogl_renderer_egl->platform_vtable = &_cogl_winsys_egl_vtable; - cogl_renderer_egl->platform = renderer_gpu_data; - cogl_renderer_egl->edpy = renderer_gpu_data->egl_display; - - if (!_cogl_winsys_egl_renderer_connect_common (cogl_renderer, error)) - goto fail; - - return TRUE; - -fail: - meta_renderer_native_disconnect (cogl_renderer); - - return FALSE; -} - -static int -meta_renderer_native_add_egl_config_attributes (CoglDisplay *cogl_display, - const CoglFramebufferConfig *config, - EGLint *attributes) -{ - CoglRendererEGL *cogl_renderer_egl = cogl_display->renderer->winsys; - MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; - int i = 0; - - switch (renderer_gpu_data->mode) - { - case META_RENDERER_NATIVE_MODE_GBM: - attributes[i++] = EGL_SURFACE_TYPE; - attributes[i++] = EGL_WINDOW_BIT; - break; - case META_RENDERER_NATIVE_MODE_SURFACELESS: - attributes[i++] = EGL_SURFACE_TYPE; - attributes[i++] = EGL_PBUFFER_BIT; - break; -#ifdef HAVE_EGL_DEVICE - case META_RENDERER_NATIVE_MODE_EGL_DEVICE: - attributes[i++] = EGL_SURFACE_TYPE; - attributes[i++] = EGL_STREAM_BIT_KHR; - break; -#endif - } - - return i; -} - -static gboolean -choose_egl_config_from_gbm_format (MetaEgl *egl, - EGLDisplay egl_display, - const EGLint *attributes, - uint32_t gbm_format, - EGLConfig *out_config, - GError **error) -{ - EGLConfig *egl_configs; - EGLint n_configs; - EGLint i; - - egl_configs = meta_egl_choose_all_configs (egl, egl_display, - attributes, - &n_configs, - error); - if (!egl_configs) - return FALSE; - - for (i = 0; i < n_configs; i++) - { - EGLint visual_id; - - if (!meta_egl_get_config_attrib (egl, egl_display, - egl_configs[i], - EGL_NATIVE_VISUAL_ID, - &visual_id, - error)) - { - g_free (egl_configs); - return FALSE; - } - - if ((uint32_t) visual_id == gbm_format) - { - *out_config = egl_configs[i]; - g_free (egl_configs); - return TRUE; - } - } - - g_free (egl_configs); - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "No EGL config matching supported GBM format found"); - return FALSE; -} - -static gboolean -meta_renderer_native_choose_egl_config (CoglDisplay *cogl_display, - EGLint *attributes, - EGLConfig *out_config, - GError **error) -{ - CoglRenderer *cogl_renderer = cogl_display->renderer; - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - MetaBackend *backend = meta_get_backend (); - MetaEgl *egl = meta_backend_get_egl (backend); - MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; - EGLDisplay egl_display = cogl_renderer_egl->edpy; - - switch (renderer_gpu_data->mode) - { - case META_RENDERER_NATIVE_MODE_GBM: - return choose_egl_config_from_gbm_format (egl, - egl_display, - attributes, - GBM_FORMAT_XRGB8888, - out_config, - error); - case META_RENDERER_NATIVE_MODE_SURFACELESS: - *out_config = EGL_NO_CONFIG_KHR; - return TRUE; -#ifdef HAVE_EGL_DEVICE - case META_RENDERER_NATIVE_MODE_EGL_DEVICE: - return meta_egl_choose_first_config (egl, - egl_display, - attributes, - out_config, - error); -#endif - } - - return FALSE; -} - -static gboolean -meta_renderer_native_setup_egl_display (CoglDisplay *cogl_display, - GError **error) -{ - CoglDisplayEGL *cogl_display_egl = cogl_display->winsys; - CoglRendererEGL *cogl_renderer_egl = cogl_display->renderer->winsys; - MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; - MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; - - cogl_display_egl->platform = renderer_native; - - /* Force a full modeset / drmModeSetCrtc on - * the first swap buffers call. - */ - meta_renderer_native_queue_modes_reset (renderer_native); - - return TRUE; -} - -static void -meta_renderer_native_destroy_egl_display (CoglDisplay *cogl_display) -{ -} - -static EGLSurface -create_dummy_pbuffer_surface (EGLDisplay egl_display, - GError **error) -{ - MetaBackend *backend = meta_get_backend (); - MetaEgl *egl = meta_backend_get_egl (backend); - EGLConfig pbuffer_config; - static const EGLint pbuffer_config_attribs[] = { - EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, - EGL_RED_SIZE, 1, - EGL_GREEN_SIZE, 1, - EGL_BLUE_SIZE, 1, - EGL_ALPHA_SIZE, 0, - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_NONE - }; - static const EGLint pbuffer_attribs[] = { - EGL_WIDTH, 16, - EGL_HEIGHT, 16, - EGL_NONE - }; - - if (!meta_egl_choose_first_config (egl, egl_display, pbuffer_config_attribs, - &pbuffer_config, error)) - return EGL_NO_SURFACE; - - return meta_egl_create_pbuffer_surface (egl, egl_display, - pbuffer_config, pbuffer_attribs, - error); -} - -static gboolean -meta_renderer_native_egl_context_created (CoglDisplay *cogl_display, - GError **error) -{ - CoglDisplayEGL *cogl_display_egl = cogl_display->winsys; - CoglRenderer *cogl_renderer = cogl_display->renderer; - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - - if ((cogl_renderer_egl->private_features & - COGL_EGL_WINSYS_FEATURE_SURFACELESS_CONTEXT) == 0) - { - cogl_display_egl->dummy_surface = - create_dummy_pbuffer_surface (cogl_renderer_egl->edpy, error); - if (cogl_display_egl->dummy_surface == EGL_NO_SURFACE) - return FALSE; - } - - if (!_cogl_winsys_egl_make_current (cogl_display, - cogl_display_egl->dummy_surface, - cogl_display_egl->dummy_surface, - cogl_display_egl->egl_context)) - { - g_set_error (error, COGL_WINSYS_ERROR, - COGL_WINSYS_ERROR_CREATE_CONTEXT, - "Failed to make context current"); - return FALSE; - } - - return TRUE; -} - -static void -meta_renderer_native_egl_cleanup_context (CoglDisplay *cogl_display) -{ - CoglDisplayEGL *cogl_display_egl = cogl_display->winsys; - CoglRenderer *cogl_renderer = cogl_display->renderer; - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; - MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; - MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); - - if (cogl_display_egl->dummy_surface != EGL_NO_SURFACE) - { - meta_egl_destroy_surface (egl, - cogl_renderer_egl->edpy, - cogl_display_egl->dummy_surface, - NULL); - cogl_display_egl->dummy_surface = EGL_NO_SURFACE; - } -} - -static CoglContext * -cogl_context_from_renderer_native (MetaRendererNative *renderer_native) -{ - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - - return clutter_backend_get_cogl_context (clutter_backend); -} - -CoglFramebuffer * -meta_renderer_native_create_dma_buf_framebuffer (MetaRendererNative *renderer_native, - int dmabuf_fd, - uint32_t width, - uint32_t height, - uint32_t stride, - uint32_t offset, - uint64_t modifier, - uint32_t drm_format, - GError **error) -{ - CoglContext *cogl_context = - cogl_context_from_renderer_native (renderer_native); - CoglDisplay *cogl_display = cogl_context->display; - CoglRenderer *cogl_renderer = cogl_display->renderer; - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - EGLDisplay egl_display = cogl_renderer_egl->edpy; - MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); - EGLImageKHR egl_image; - uint32_t strides[1]; - uint32_t offsets[1]; - uint64_t modifiers[1]; - CoglPixelFormat cogl_format; - CoglEglImageFlags flags; - CoglTexture2D *cogl_tex; - CoglOffscreen *cogl_fbo; - int ret; - - ret = meta_cogl_pixel_format_from_drm_format (drm_format, - &cogl_format, - NULL); - g_assert (ret); - - strides[0] = stride; - offsets[0] = offset; - modifiers[0] = modifier; - egl_image = meta_egl_create_dmabuf_image (egl, - egl_display, - width, - height, - drm_format, - 1 /* n_planes */, - &dmabuf_fd, - strides, - offsets, - modifiers, - error); - if (egl_image == EGL_NO_IMAGE_KHR) - return NULL; - - flags = COGL_EGL_IMAGE_FLAG_NO_GET_DATA; - cogl_tex = cogl_egl_texture_2d_new_from_image (cogl_context, - width, - height, - cogl_format, - egl_image, - flags, - error); - - meta_egl_destroy_image (egl, egl_display, egl_image, NULL); - - if (!cogl_tex) - return NULL; - - cogl_fbo = cogl_offscreen_new_with_texture (COGL_TEXTURE (cogl_tex)); - cogl_object_unref (cogl_tex); - - if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (cogl_fbo), error)) - { - g_object_unref (cogl_fbo); - return NULL; - } - - return COGL_FRAMEBUFFER (cogl_fbo); -} - -static void -configure_disabled_crtcs (MetaKmsDevice *kms_device) -{ - MetaKms *kms = meta_kms_device_get_kms (kms_device); - GList *l; - - for (l = meta_kms_device_get_crtcs (kms_device); l; l = l->next) - { - MetaKmsCrtc *kms_crtc = l->data; - MetaCrtcKms *crtc_kms = meta_crtc_kms_from_kms_crtc (kms_crtc); - MetaKmsUpdate *kms_update; - - if (meta_crtc_get_config (META_CRTC (crtc_kms))) - continue; - - if (!meta_kms_crtc_is_active (kms_crtc)) - continue; - - kms_update = meta_kms_ensure_pending_update (kms, kms_device); - meta_kms_update_mode_set (kms_update, kms_crtc, NULL, NULL); - } -} - -static gboolean -dummy_power_save_page_flip_cb (gpointer user_data) -{ - MetaRendererNative *renderer_native = user_data; - - g_list_foreach (renderer_native->power_save_page_flip_onscreens, - (GFunc) meta_onscreen_native_dummy_power_save_page_flip, - NULL); - g_clear_list (&renderer_native->power_save_page_flip_onscreens, - g_object_unref); - renderer_native->power_save_page_flip_source_id = 0; - - return G_SOURCE_REMOVE; -} - -void -meta_renderer_native_queue_power_save_page_flip (MetaRendererNative *renderer_native, - CoglOnscreen *onscreen) -{ - const unsigned int timeout_ms = 100; - - if (!renderer_native->power_save_page_flip_source_id) - { - renderer_native->power_save_page_flip_source_id = - g_timeout_add (timeout_ms, - dummy_power_save_page_flip_cb, - renderer_native); - } - - renderer_native->power_save_page_flip_onscreens = - g_list_prepend (renderer_native->power_save_page_flip_onscreens, - g_object_ref (onscreen)); -} - -static void -clear_kept_alive_onscreens (MetaRendererNative *renderer_native) -{ - g_clear_list (&renderer_native->kept_alive_onscreens, - g_object_unref); -} - -static gboolean -is_gpu_unused (gpointer key, - gpointer value, - gpointer user_data) -{ - GHashTable *used_gpus = user_data; - - return !g_hash_table_contains (used_gpus, key); -} - -static void -free_unused_gpu_datas (MetaRendererNative *renderer_native) -{ - MetaRenderer *renderer = META_RENDERER (renderer_native); - g_autoptr (GHashTable) used_gpus = NULL; - GList *l; - - used_gpus = g_hash_table_new (NULL, NULL); - g_hash_table_add (used_gpus, renderer_native->primary_gpu_kms); - - for (l = meta_renderer_get_views (renderer); l; l = l->next) - { - MetaRendererView *view = l->data; - MetaCrtc *crtc = meta_renderer_view_get_crtc (view); - MetaGpu *gpu; - - gpu = meta_crtc_get_gpu (crtc); - if (!gpu) - continue; - - g_hash_table_add (used_gpus, gpu); - } - - g_hash_table_foreach_remove (renderer_native->gpu_datas, - is_gpu_unused, - used_gpus); -} - -void -meta_renderer_native_post_mode_set_updates (MetaRendererNative *renderer_native) -{ - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaKms *kms = meta_backend_native_get_kms (META_BACKEND_NATIVE (backend)); - GList *l; - - for (l = meta_kms_get_devices (kms); l; l = l->next) - { - MetaKmsDevice *kms_device = l->data; - MetaKmsUpdate *kms_update; - MetaKmsUpdateFlag flags; - g_autoptr (MetaKmsFeedback) kms_feedback = NULL; - const GError *feedback_error; - - configure_disabled_crtcs (kms_device); - - kms_update = meta_kms_get_pending_update (kms, kms_device); - if (!kms_update) - continue; - - flags = META_KMS_UPDATE_FLAG_NONE; - kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device, flags); - - switch (meta_kms_feedback_get_result (kms_feedback)) - { - case META_KMS_FEEDBACK_PASSED: - break; - case META_KMS_FEEDBACK_FAILED: - feedback_error = meta_kms_feedback_get_error (kms_feedback); - if (!g_error_matches (feedback_error, - G_IO_ERROR, - G_IO_ERROR_PERMISSION_DENIED)) - g_warning ("Failed to post KMS update: %s", feedback_error->message); - break; - } - } - - clear_kept_alive_onscreens (renderer_native); - - meta_kms_notify_modes_set (kms); - - free_unused_gpu_datas (renderer_native); -} - -static void -unset_disabled_crtcs (MetaBackend *backend, - MetaKms *kms) -{ - GList *l; - - meta_topic (META_DEBUG_KMS, "Disabling all disabled CRTCs"); - - for (l = meta_backend_get_gpus (backend); l; l = l->next) - { - MetaGpu *gpu = l->data; - MetaKmsDevice *kms_device = - meta_gpu_kms_get_kms_device (META_GPU_KMS (gpu)); - GList *k; - gboolean did_mode_set = FALSE; - MetaKmsUpdateFlag flags; - g_autoptr (MetaKmsFeedback) kms_feedback = NULL; - - for (k = meta_gpu_get_crtcs (gpu); k; k = k->next) - { - MetaCrtc *crtc = k->data; - MetaKmsUpdate *kms_update; - - if (meta_crtc_get_config (crtc)) - continue; - - kms_update = meta_kms_ensure_pending_update (kms, kms_device); - meta_crtc_kms_set_mode (META_CRTC_KMS (crtc), kms_update); - - did_mode_set = TRUE; - } - - if (!did_mode_set) - continue; - - flags = META_KMS_UPDATE_FLAG_NONE; - kms_feedback = meta_kms_post_pending_update_sync (kms, - kms_device, - flags); - if (meta_kms_feedback_get_result (kms_feedback) != - META_KMS_FEEDBACK_PASSED) - { - const GError *error = meta_kms_feedback_get_error (kms_feedback); - - if (!g_error_matches (error, G_IO_ERROR, - G_IO_ERROR_PERMISSION_DENIED)) - g_warning ("Failed to post KMS update: %s", error->message); - } - } -} - -static CoglDmaBufHandle * -meta_renderer_native_create_dma_buf (CoglRenderer *cogl_renderer, - int width, - int height, - GError **error) -{ - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; - MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; - - switch (renderer_gpu_data->mode) - { - case META_RENDERER_NATIVE_MODE_GBM: - { - CoglFramebuffer *dmabuf_fb; - CoglDmaBufHandle *dmabuf_handle; - struct gbm_bo *new_bo; - int stride; - int offset; - int bpp; - int dmabuf_fd = -1; - - new_bo = gbm_bo_create (renderer_gpu_data->gbm.device, - width, height, DRM_FORMAT_XRGB8888, - GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR); - - if (!new_bo) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to allocate buffer"); - return NULL; - } - - dmabuf_fd = gbm_bo_get_fd (new_bo); - - if (dmabuf_fd == -1) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS, - "Failed to export buffer's DMA fd: %s", - g_strerror (errno)); - return NULL; - } - - stride = gbm_bo_get_stride (new_bo); - offset = gbm_bo_get_offset (new_bo, 0); - bpp = 4; - dmabuf_fb = - meta_renderer_native_create_dma_buf_framebuffer (renderer_native, - dmabuf_fd, - width, height, - stride, - offset, - DRM_FORMAT_MOD_LINEAR, - DRM_FORMAT_XRGB8888, - error); - - if (!dmabuf_fb) - return NULL; - - dmabuf_handle = - cogl_dma_buf_handle_new (dmabuf_fb, dmabuf_fd, - width, height, stride, offset, bpp, - new_bo, - (GDestroyNotify) gbm_bo_destroy); - g_object_unref (dmabuf_fb); - return dmabuf_handle; - } - break; - case META_RENDERER_NATIVE_MODE_SURFACELESS: -#ifdef HAVE_EGL_DEVICE - case META_RENDERER_NATIVE_MODE_EGL_DEVICE: -#endif - break; - } - - g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, - "Current mode does not support exporting DMA buffers"); - - return NULL; -} - -static gboolean -meta_renderer_native_init_egl_context (CoglContext *cogl_context, - GError **error) -{ -#ifdef HAVE_EGL_DEVICE - CoglRenderer *cogl_renderer = cogl_context->display->renderer; - CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; - MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; -#endif - - COGL_FLAGS_SET (cogl_context->winsys_features, - COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT, - TRUE); - COGL_FLAGS_SET (cogl_context->winsys_features, - COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT, - TRUE); - COGL_FLAGS_SET (cogl_context->winsys_features, - COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN, - TRUE); - -#ifdef HAVE_EGL_DEVICE - if (renderer_gpu_data->mode == META_RENDERER_NATIVE_MODE_EGL_DEVICE) - COGL_FLAGS_SET (cogl_context->features, - COGL_FEATURE_ID_TEXTURE_EGL_IMAGE_EXTERNAL, TRUE); -#endif - - return TRUE; -} - -static const CoglWinsysEGLVtable -_cogl_winsys_egl_vtable = { - .add_config_attributes = meta_renderer_native_add_egl_config_attributes, - .choose_config = meta_renderer_native_choose_egl_config, - .display_setup = meta_renderer_native_setup_egl_display, - .display_destroy = meta_renderer_native_destroy_egl_display, - .context_created = meta_renderer_native_egl_context_created, - .cleanup_context = meta_renderer_native_egl_cleanup_context, - .context_init = meta_renderer_native_init_egl_context -}; - -static void -meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native) -{ - MetaRenderer *renderer = META_RENDERER (renderer_native); - GList *l; - - g_clear_list (&renderer_native->pending_mode_set_views, NULL); - for (l = meta_renderer_get_views (renderer); l; l = l->next) - { - ClutterStageView *stage_view = l->data; - CoglFramebuffer *framebuffer = - clutter_stage_view_get_onscreen (stage_view); - - if (COGL_IS_ONSCREEN (framebuffer)) - { - renderer_native->pending_mode_set_views = - g_list_prepend (renderer_native->pending_mode_set_views, - stage_view); - } - } - renderer_native->pending_mode_set = TRUE; - - meta_topic (META_DEBUG_KMS, "Queue mode set"); -} - -void -meta_renderer_native_notify_mode_sets_reset (MetaRendererNative *renderer_native) -{ - renderer_native->pending_mode_set = FALSE; -} - -gboolean -meta_renderer_native_pop_pending_mode_set (MetaRendererNative *renderer_native, - MetaRendererView *view) -{ - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaPowerSave power_save_mode; - GList *link; - - g_assert (META_IS_RENDERER_VIEW (view)); - - power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager); - if (power_save_mode != META_POWER_SAVE_ON) - return FALSE; - - link = g_list_find (renderer_native->pending_mode_set_views, view); - if (!link) - return FALSE; - - renderer_native->pending_mode_set_views = - g_list_delete_link (renderer_native->pending_mode_set_views, link); - return TRUE; -} - -static CoglOffscreen * -meta_renderer_native_create_offscreen (MetaRendererNative *renderer, - CoglContext *context, - gint view_width, - gint view_height, - GError **error) -{ - CoglOffscreen *fb; - CoglTexture2D *tex; - - tex = cogl_texture_2d_new_with_size (context, view_width, view_height); - cogl_primitive_texture_set_auto_mipmap (COGL_PRIMITIVE_TEXTURE (tex), FALSE); - - if (!cogl_texture_allocate (COGL_TEXTURE (tex), error)) - { - cogl_object_unref (tex); - return FALSE; - } - - fb = cogl_offscreen_new_with_texture (COGL_TEXTURE (tex)); - cogl_object_unref (tex); - if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (fb), error)) - { - g_object_unref (fb); - return FALSE; - } - - return fb; -} - -static const CoglWinsysVtable * -get_native_cogl_winsys_vtable (CoglRenderer *cogl_renderer) -{ - static gboolean vtable_inited = FALSE; - static CoglWinsysVtable vtable; - - if (!vtable_inited) - { - /* The this winsys is a subclass of the EGL winsys so we - start by copying its vtable */ - - parent_vtable = _cogl_winsys_egl_get_vtable (); - vtable = *parent_vtable; - - vtable.id = COGL_WINSYS_ID_CUSTOM; - vtable.name = "EGL_KMS"; - - vtable.renderer_connect = meta_renderer_native_connect; - vtable.renderer_disconnect = meta_renderer_native_disconnect; - vtable.renderer_create_dma_buf = meta_renderer_native_create_dma_buf; - - vtable_inited = TRUE; - } - - return &vtable; -} - -static CoglRenderer * -meta_renderer_native_create_cogl_renderer (MetaRenderer *renderer) -{ - CoglRenderer *cogl_renderer; - - cogl_renderer = cogl_renderer_new (); - cogl_renderer_set_custom_winsys (cogl_renderer, - get_native_cogl_winsys_vtable, - renderer); - return cogl_renderer; -} - -static MetaMonitorTransform -calculate_view_transform (MetaMonitorManager *monitor_manager, - MetaLogicalMonitor *logical_monitor, - MetaOutput *output, - MetaCrtc *crtc) -{ - MetaMonitorTransform crtc_transform; - - crtc = meta_output_get_assigned_crtc (output); - crtc_transform = - meta_output_logical_to_crtc_transform (output, logical_monitor->transform); - - if (meta_monitor_manager_is_transform_handled (monitor_manager, - crtc, - crtc_transform)) - return META_MONITOR_TRANSFORM_NORMAL; - else - return crtc_transform; -} - -static gboolean -should_force_shadow_fb (MetaRendererNative *renderer_native, - MetaGpuKms *primary_gpu) -{ - MetaRenderer *renderer = META_RENDERER (renderer_native); - CoglContext *cogl_context = - cogl_context_from_renderer_native (renderer_native); - MetaKmsDevice *kms_device = meta_gpu_kms_get_kms_device (primary_gpu); - - if (meta_renderer_is_hardware_accelerated (renderer)) - return FALSE; - - if (!cogl_has_feature (cogl_context, COGL_FEATURE_ID_BLIT_FRAMEBUFFER)) - return FALSE; - - return meta_kms_device_prefers_shadow_buffer (kms_device); -} - -static CoglFramebuffer * -create_fallback_offscreen (MetaRendererNative *renderer_native, - CoglContext *cogl_context, - int width, - int height) -{ - CoglOffscreen *fallback_offscreen; - GError *error = NULL; - - fallback_offscreen = meta_renderer_native_create_offscreen (renderer_native, - cogl_context, - width, - height, - &error); - if (!fallback_offscreen) - { - g_error ("Failed to create fallback offscreen framebuffer: %s", - error->message); - } - - return COGL_FRAMEBUFFER (fallback_offscreen); -} - -static MetaRendererView * -meta_renderer_native_create_view (MetaRenderer *renderer, - MetaLogicalMonitor *logical_monitor, - MetaOutput *output, - MetaCrtc *crtc) -{ - MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer); - MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - CoglContext *cogl_context = - cogl_context_from_renderer_native (renderer_native); - CoglDisplay *cogl_display = cogl_context_get_display (cogl_context); - const MetaCrtcConfig *crtc_config; - const MetaCrtcModeInfo *crtc_mode_info; - MetaMonitorTransform view_transform; - g_autoptr (CoglFramebuffer) framebuffer = NULL; - g_autoptr (CoglOffscreen) offscreen = NULL; - gboolean use_shadowfb; - float scale; - int onscreen_width; - int onscreen_height; - MetaRectangle view_layout; - MetaRendererView *view; - EGLSurface egl_surface; - GError *error = NULL; - - crtc_config = meta_crtc_get_config (crtc); - crtc_mode_info = meta_crtc_mode_get_info (crtc_config->mode); - onscreen_width = crtc_mode_info->width; - onscreen_height = crtc_mode_info->height; - - if (META_IS_CRTC_KMS (crtc)) - { - MetaGpuKms *gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc)); - MetaOnscreenNative *onscreen_native; - - if (!meta_renderer_native_ensure_gpu_data (renderer_native, - gpu_kms, - &error)) - { - g_warning ("Failed to create secondary GPU data for %s: %s", - meta_gpu_kms_get_file_path (gpu_kms), - error->message); - use_shadowfb = FALSE; - framebuffer = create_fallback_offscreen (renderer_native, - cogl_context, - onscreen_width, - onscreen_height); - } - else - { - MetaGpuKms *primary_gpu_kms = renderer_native->primary_gpu_kms; - - onscreen_native = meta_onscreen_native_new (renderer_native, - primary_gpu_kms, - output, - crtc, - cogl_context, - onscreen_width, - onscreen_height); - - if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (onscreen_native), &error)) - { - g_warning ("Failed to allocate onscreen framebuffer for %s: %s", - meta_gpu_kms_get_file_path (gpu_kms), - error->message); - use_shadowfb = FALSE; - framebuffer = create_fallback_offscreen (renderer_native, - cogl_context, - onscreen_width, - onscreen_height); - } - else - { - use_shadowfb = should_force_shadow_fb (renderer_native, - primary_gpu_kms); - framebuffer = COGL_FRAMEBUFFER (onscreen_native); - } - } - } - else - { - CoglOffscreen *virtual_onscreen; - - g_assert (META_IS_CRTC_VIRTUAL (crtc)); - - virtual_onscreen = meta_renderer_native_create_offscreen (renderer_native, - cogl_context, - onscreen_width, - onscreen_height, - &error); - if (!virtual_onscreen) - g_error ("Failed to allocate back buffer texture: %s", error->message); - use_shadowfb = FALSE; - framebuffer = COGL_FRAMEBUFFER (virtual_onscreen); - } - - view_transform = calculate_view_transform (monitor_manager, - logical_monitor, - output, - crtc); - if (view_transform != META_MONITOR_TRANSFORM_NORMAL) - { - int offscreen_width; - int offscreen_height; - - if (meta_monitor_transform_is_rotated (view_transform)) - { - offscreen_width = onscreen_height; - offscreen_height = onscreen_width; - } - else - { - offscreen_width = onscreen_width; - offscreen_height = onscreen_height; - } - - offscreen = meta_renderer_native_create_offscreen (renderer_native, - cogl_context, - offscreen_width, - offscreen_height, - &error); - if (!offscreen) - g_error ("Failed to allocate back buffer texture: %s", error->message); - } - - if (meta_is_stage_views_scaled ()) - scale = meta_logical_monitor_get_scale (logical_monitor); - else - scale = 1.0; - - meta_rectangle_from_graphene_rect (&crtc_config->layout, - META_ROUNDING_STRATEGY_ROUND, - &view_layout); - view = g_object_new (META_TYPE_RENDERER_VIEW, - "name", meta_output_get_name (output), - "stage", meta_backend_get_stage (backend), - "layout", &view_layout, - "crtc", crtc, - "scale", scale, - "framebuffer", framebuffer, - "offscreen", offscreen, - "use-shadowfb", use_shadowfb, - "transform", view_transform, - "refresh-rate", crtc_mode_info->refresh_rate, - "vblank-duration-us", crtc_mode_info->vblank_duration_us, - NULL); - - if (META_IS_ONSCREEN_NATIVE (framebuffer)) - { - CoglDisplayEGL *cogl_display_egl; - CoglOnscreenEgl *onscreen_egl; - - meta_onscreen_native_set_view (COGL_ONSCREEN (framebuffer), view); - - /* Ensure we don't point to stale surfaces when creating the offscreen */ - cogl_display_egl = cogl_display->winsys; - onscreen_egl = COGL_ONSCREEN_EGL (framebuffer); - egl_surface = cogl_onscreen_egl_get_egl_surface (onscreen_egl); - _cogl_winsys_egl_make_current (cogl_display, - egl_surface, - egl_surface, - cogl_display_egl->egl_context); - } - - return view; -} - -static void -keep_current_onscreens_alive (MetaRenderer *renderer) -{ - MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer); - GList *views; - GList *l; - - views = meta_renderer_get_views (renderer); - for (l = views; l; l = l->next) - { - ClutterStageView *stage_view = l->data; - CoglFramebuffer *onscreen = clutter_stage_view_get_onscreen (stage_view); - - renderer_native->kept_alive_onscreens = - g_list_prepend (renderer_native->kept_alive_onscreens, - g_object_ref (onscreen)); - } -} - -static void -meta_renderer_native_rebuild_views (MetaRenderer *renderer) -{ - MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - MetaKms *kms = meta_backend_native_get_kms (backend_native); - MetaRendererClass *parent_renderer_class = - META_RENDERER_CLASS (meta_renderer_native_parent_class); - - meta_kms_discard_pending_page_flips (kms); - - keep_current_onscreens_alive (renderer); - - parent_renderer_class->rebuild_views (renderer); - - meta_renderer_native_queue_modes_reset (META_RENDERER_NATIVE (renderer)); -} - -void -meta_renderer_native_prepare_frame (MetaRendererNative *renderer_native, - MetaRendererView *view, - ClutterFrame *frame) -{ - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaCrtc *crtc = meta_renderer_view_get_crtc (view); - MetaPowerSave power_save_mode; - MetaCrtcKms *crtc_kms; - MetaKmsCrtc *kms_crtc; - MetaKmsDevice *kms_device; - - if (!META_IS_CRTC_KMS (crtc)) - return; - - power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager); - if (power_save_mode != META_POWER_SAVE_ON) - return; - - crtc_kms = META_CRTC_KMS (crtc); - kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc)); - kms_device = meta_kms_crtc_get_device (kms_crtc); - - meta_crtc_kms_maybe_set_gamma (crtc_kms, kms_device); -} - -void -meta_renderer_native_finish_frame (MetaRendererNative *renderer_native, - MetaRendererView *view, - ClutterFrame *frame) -{ - if (!clutter_frame_has_result (frame)) - { - CoglFramebuffer *framebuffer = - clutter_stage_view_get_onscreen (CLUTTER_STAGE_VIEW (view)); - - if (COGL_IS_ONSCREEN (framebuffer)) - { - CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); - - meta_onscreen_native_finish_frame (onscreen, frame); - } - } -} - -static gboolean -create_secondary_egl_config (MetaEgl *egl, - MetaRendererNativeMode mode, - EGLDisplay egl_display, - EGLConfig *egl_config, - GError **error) -{ - EGLint attributes[] = { - EGL_RED_SIZE, 1, - EGL_GREEN_SIZE, 1, - EGL_BLUE_SIZE, 1, - EGL_ALPHA_SIZE, EGL_DONT_CARE, - EGL_BUFFER_SIZE, EGL_DONT_CARE, - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_NONE - }; - - switch (mode) - { - case META_RENDERER_NATIVE_MODE_GBM: - case META_RENDERER_NATIVE_MODE_SURFACELESS: - return choose_egl_config_from_gbm_format (egl, - egl_display, - attributes, - GBM_FORMAT_XRGB8888, - egl_config, - error); -#ifdef HAVE_EGL_DEVICE - case META_RENDERER_NATIVE_MODE_EGL_DEVICE: - return meta_egl_choose_first_config (egl, - egl_display, - attributes, - egl_config, - error); -#endif - } - - return FALSE; -} - -static EGLContext -create_secondary_egl_context (MetaEgl *egl, - EGLDisplay egl_display, - EGLConfig egl_config, - GError **error) -{ - EGLint attributes[] = { - EGL_CONTEXT_CLIENT_VERSION, 3, - EGL_NONE - }; - - return meta_egl_create_context (egl, - egl_display, - egl_config, - EGL_NO_CONTEXT, - attributes, - error); -} - -static void -meta_renderer_native_ensure_gles3 (MetaRendererNative *renderer_native) -{ - MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); - - if (renderer_native->gles3) - return; - - renderer_native->gles3 = meta_gles3_new (egl); -} - -static void -maybe_restore_cogl_egl_api (MetaRendererNative *renderer_native) -{ - CoglContext *cogl_context; - CoglDisplay *cogl_display; - CoglRenderer *cogl_renderer; - - cogl_context = cogl_context_from_renderer_native (renderer_native); - if (!cogl_context) - return; - - cogl_display = cogl_context_get_display (cogl_context); - cogl_renderer = cogl_display_get_renderer (cogl_display); - cogl_renderer_bind_api (cogl_renderer); -} - -static gboolean -init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data, - GError **error) -{ - MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; - MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); - EGLDisplay egl_display = renderer_gpu_data->egl_display; - EGLConfig egl_config; - EGLContext egl_context; - const char **missing_gl_extensions; - const char *renderer_str; - - meta_egl_bind_api (egl, EGL_OPENGL_ES_API, NULL); - - if (!create_secondary_egl_config (egl, renderer_gpu_data->mode, egl_display, - &egl_config, error)) - goto err; - - egl_context = create_secondary_egl_context (egl, egl_display, egl_config, error); - if (egl_context == EGL_NO_CONTEXT) - goto err; - - meta_renderer_native_ensure_gles3 (renderer_native); - - if (!meta_egl_make_current (egl, - egl_display, - EGL_NO_SURFACE, - EGL_NO_SURFACE, - egl_context, - error)) - { - meta_egl_destroy_context (egl, egl_display, egl_context, NULL); - goto err; - } - - renderer_str = (const char *) glGetString (GL_RENDERER); - if (g_str_has_prefix (renderer_str, "llvmpipe") || - g_str_has_prefix (renderer_str, "softpipe") || - g_str_has_prefix (renderer_str, "swrast")) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Do not want to use software renderer (%s), falling back to CPU copy path", - renderer_str); - goto err_fail_with_context; - } - - if (!meta_gles3_has_extensions (renderer_native->gles3, - &missing_gl_extensions, - "GL_OES_EGL_image_external", - NULL)) - { - char *missing_gl_extensions_str; - - missing_gl_extensions_str = g_strjoinv (", ", - (char **) missing_gl_extensions); - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Missing OpenGL ES extensions: %s", - missing_gl_extensions_str); - g_free (missing_gl_extensions_str); - g_free (missing_gl_extensions); - - goto err_fail_with_context; - } - - renderer_gpu_data->secondary.is_hardware_rendering = TRUE; - renderer_gpu_data->secondary.egl_context = egl_context; - renderer_gpu_data->secondary.egl_config = egl_config; - renderer_gpu_data->secondary.copy_mode = META_SHARED_FRAMEBUFFER_COPY_MODE_SECONDARY_GPU; - - renderer_gpu_data->secondary.has_EGL_EXT_image_dma_buf_import_modifiers = - meta_egl_has_extensions (egl, egl_display, NULL, - "EGL_EXT_image_dma_buf_import_modifiers", - NULL); - - maybe_restore_cogl_egl_api (renderer_native); - - return TRUE; - -err_fail_with_context: - meta_egl_make_current (egl, - egl_display, - EGL_NO_SURFACE, - EGL_NO_SURFACE, - EGL_NO_CONTEXT, - NULL); - meta_egl_destroy_context (egl, egl_display, egl_context, NULL); - -err: - maybe_restore_cogl_egl_api (renderer_native); - - return FALSE; -} - -static void -init_secondary_gpu_data_cpu (MetaRendererNativeGpuData *renderer_gpu_data) -{ - renderer_gpu_data->secondary.is_hardware_rendering = FALSE; - - /* First try ZERO, it automatically falls back to PRIMARY as needed */ - renderer_gpu_data->secondary.copy_mode = - META_SHARED_FRAMEBUFFER_COPY_MODE_ZERO; -} - -static void -init_secondary_gpu_data (MetaRendererNativeGpuData *renderer_gpu_data) -{ - GError *error = NULL; - - if (init_secondary_gpu_data_gpu (renderer_gpu_data, &error)) - return; - - g_message ("Failed to initialize accelerated iGPU/dGPU framebuffer sharing: %s", - error->message); - g_error_free (error); - - init_secondary_gpu_data_cpu (renderer_gpu_data); -} - -static gboolean -gpu_kms_is_hardware_rendering (MetaRendererNative *renderer_native, - MetaGpuKms *gpu_kms) -{ - MetaRendererNativeGpuData *data; - - data = meta_renderer_native_get_gpu_data (renderer_native, gpu_kms); - return data->secondary.is_hardware_rendering; -} - -static EGLDisplay -init_gbm_egl_display (MetaRendererNative *renderer_native, - struct gbm_device *gbm_device, - GError **error) -{ - MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); - EGLDisplay egl_display; - - if (!meta_egl_has_extensions (egl, EGL_NO_DISPLAY, NULL, - "EGL_MESA_platform_gbm", - NULL) && - !meta_egl_has_extensions (egl, EGL_NO_DISPLAY, NULL, - "EGL_KHR_platform_gbm", - NULL)) - { - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Missing extension for GBM renderer: EGL_KHR_platform_gbm"); - return EGL_NO_DISPLAY; - } - - egl_display = meta_egl_get_platform_display (egl, - EGL_PLATFORM_GBM_KHR, - gbm_device, NULL, error); - if (egl_display == EGL_NO_DISPLAY) - return EGL_NO_DISPLAY; - - if (!meta_egl_initialize (egl, egl_display, error)) - return EGL_NO_DISPLAY; - - return egl_display; -} - -static MetaRendererNativeGpuData * -create_renderer_gpu_data_gbm (MetaRendererNative *renderer_native, - MetaDeviceFile *device_file, - GError **error) -{ - struct gbm_device *gbm_device; - MetaRendererNativeGpuData *renderer_gpu_data; - g_autoptr (GError) local_error = NULL; - - gbm_device = gbm_create_device (meta_device_file_get_fd (device_file)); - if (!gbm_device) - { - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Failed to create gbm device: %s", g_strerror (errno)); - return NULL; - } - - renderer_gpu_data = meta_create_renderer_native_gpu_data (); - renderer_gpu_data->device_file = meta_device_file_acquire (device_file); - renderer_gpu_data->renderer_native = renderer_native; - renderer_gpu_data->gbm.device = gbm_device; - renderer_gpu_data->mode = META_RENDERER_NATIVE_MODE_GBM; - - renderer_gpu_data->egl_display = init_gbm_egl_display (renderer_native, - gbm_device, - &local_error); - if (renderer_gpu_data->egl_display == EGL_NO_DISPLAY) - { - g_debug ("GBM EGL init for %s failed: %s", - meta_device_file_get_path (device_file), - local_error->message); - - init_secondary_gpu_data_cpu (renderer_gpu_data); - return renderer_gpu_data; - } - - init_secondary_gpu_data (renderer_gpu_data); - return renderer_gpu_data; -} - -static EGLDisplay -init_surfaceless_egl_display (MetaRendererNative *renderer_native, - GError **error) -{ - MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); - EGLDisplay egl_display; - - if (!meta_egl_has_extensions (egl, EGL_NO_DISPLAY, NULL, - "EGL_MESA_platform_surfaceless", - NULL)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Missing EGL platform required for surfaceless context: " - "EGL_MESA_platform_surfaceless"); - return EGL_NO_DISPLAY; - } - - egl_display = meta_egl_get_platform_display (egl, - EGL_PLATFORM_SURFACELESS_MESA, - EGL_DEFAULT_DISPLAY, - NULL, error); - if (egl_display == EGL_NO_DISPLAY) - return EGL_NO_DISPLAY; - - if (!meta_egl_initialize (egl, egl_display, error)) - return EGL_NO_DISPLAY; - - if (!meta_egl_has_extensions (egl, egl_display, NULL, - "EGL_KHR_no_config_context", - NULL)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Missing EGL extension required for surfaceless context: " - "EGL_KHR_no_config_context"); - return EGL_NO_DISPLAY; - } - - return egl_display; -} - -static MetaRendererNativeGpuData * -create_renderer_gpu_data_surfaceless (MetaRendererNative *renderer_native, - GError **error) -{ - MetaRendererNativeGpuData *renderer_gpu_data; - EGLDisplay egl_display; - - egl_display = init_surfaceless_egl_display (renderer_native, error); - if (egl_display == EGL_NO_DISPLAY) - return NULL; - - renderer_gpu_data = meta_create_renderer_native_gpu_data (); - renderer_gpu_data->renderer_native = renderer_native; - renderer_gpu_data->mode = META_RENDERER_NATIVE_MODE_SURFACELESS; - renderer_gpu_data->egl_display = egl_display; - - return renderer_gpu_data; -} - -#ifdef HAVE_EGL_DEVICE -static const char * -get_drm_device_file (MetaEgl *egl, - EGLDeviceEXT device, - GError **error) -{ - if (!meta_egl_egl_device_has_extensions (egl, device, - NULL, - "EGL_EXT_device_drm", - NULL)) - { - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Missing required EGLDevice extension EGL_EXT_device_drm"); - return NULL; - } - - return meta_egl_query_device_string (egl, device, - EGL_DRM_DEVICE_FILE_EXT, - error); -} - -static EGLDeviceEXT -find_egl_device (MetaRendererNative *renderer_native, - MetaDeviceFile *device_file, - GError **error) -{ - MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); - const char **missing_extensions; - EGLint num_devices; - EGLDeviceEXT *devices; - const char *kms_file_path; - EGLDeviceEXT device; - EGLint i; - - if (!meta_egl_has_extensions (egl, - EGL_NO_DISPLAY, - &missing_extensions, - "EGL_EXT_device_base", - NULL)) - { - char *missing_extensions_str; - - missing_extensions_str = g_strjoinv (", ", (char **) missing_extensions); - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Missing EGL extensions required for EGLDevice renderer: %s", - missing_extensions_str); - g_free (missing_extensions_str); - g_free (missing_extensions); - return EGL_NO_DEVICE_EXT; - } - - if (!meta_egl_query_devices (egl, 0, NULL, &num_devices, error)) - return EGL_NO_DEVICE_EXT; - - devices = g_new0 (EGLDeviceEXT, num_devices); - if (!meta_egl_query_devices (egl, num_devices, devices, &num_devices, - error)) - { - g_free (devices); - return EGL_NO_DEVICE_EXT; - } - - kms_file_path = meta_device_file_get_path (device_file); - - device = EGL_NO_DEVICE_EXT; - for (i = 0; i < num_devices; i++) - { - const char *egl_device_drm_path; - - g_clear_error (error); - - egl_device_drm_path = get_drm_device_file (egl, devices[i], error); - if (!egl_device_drm_path) - continue; - - if (g_str_equal (egl_device_drm_path, kms_file_path)) - { - device = devices[i]; - break; - } - } - g_free (devices); - - if (device == EGL_NO_DEVICE_EXT) - { - if (!*error) - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Failed to find matching EGLDeviceEXT"); - return EGL_NO_DEVICE_EXT; - } - - return device; -} - -static EGLDisplay -get_egl_device_display (MetaRendererNative *renderer_native, - MetaDeviceFile *device_file, - EGLDeviceEXT egl_device, - GError **error) -{ - MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); - int kms_fd = meta_device_file_get_fd (device_file); - EGLint platform_attribs[] = { - EGL_DRM_MASTER_FD_EXT, kms_fd, - EGL_NONE - }; - - return meta_egl_get_platform_display (egl, EGL_PLATFORM_DEVICE_EXT, - (void *) egl_device, - platform_attribs, - error); -} - -static int -count_drm_devices (MetaRendererNative *renderer_native) -{ - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - - return g_list_length (meta_backend_get_gpus (backend)); -} - -static MetaRendererNativeGpuData * -create_renderer_gpu_data_egl_device (MetaRendererNative *renderer_native, - MetaDeviceFile *device_file, - GError **error) -{ - MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); - const char **missing_extensions; - EGLDeviceEXT egl_device; - EGLDisplay egl_display; - MetaRendererNativeGpuData *renderer_gpu_data; - - if (count_drm_devices (renderer_native) != 1) - { - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "EGLDevice currently only works with single GPU systems"); - return NULL; - } - - egl_device = find_egl_device (renderer_native, device_file, error); - if (egl_device == EGL_NO_DEVICE_EXT) - return NULL; - - egl_display = get_egl_device_display (renderer_native, device_file, - egl_device, error); - if (egl_display == EGL_NO_DISPLAY) - return NULL; - - if (!meta_egl_initialize (egl, egl_display, error)) - return NULL; - - if (!meta_egl_has_extensions (egl, - egl_display, - &missing_extensions, - "EGL_NV_output_drm_flip_event", - "EGL_EXT_output_base", - "EGL_EXT_output_drm", - "EGL_KHR_stream", - "EGL_KHR_stream_producer_eglsurface", - "EGL_EXT_stream_consumer_egloutput", - "EGL_EXT_stream_acquire_mode", - NULL)) - { - char *missing_extensions_str; - - missing_extensions_str = g_strjoinv (", ", (char **) missing_extensions); - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Missing EGL extensions required for EGLDevice renderer: %s", - missing_extensions_str); - meta_egl_terminate (egl, egl_display, NULL); - g_free (missing_extensions_str); - g_free (missing_extensions); - return NULL; - } - - renderer_gpu_data = meta_create_renderer_native_gpu_data (); - renderer_gpu_data->device_file = meta_device_file_acquire (device_file); - renderer_gpu_data->renderer_native = renderer_native; - renderer_gpu_data->egl.device = egl_device; - renderer_gpu_data->mode = META_RENDERER_NATIVE_MODE_EGL_DEVICE; - renderer_gpu_data->egl_display = egl_display; - - return renderer_gpu_data; -} -#endif /* HAVE_EGL_DEVICE */ - -static MetaRendererNativeGpuData * -meta_renderer_native_create_renderer_gpu_data (MetaRendererNative *renderer_native, - MetaGpuKms *gpu_kms, - GError **error) -{ - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaDevicePool *device_pool = - meta_backend_native_get_device_pool (META_BACKEND_NATIVE (backend)); - MetaRendererNativeGpuData *renderer_gpu_data; - MetaDeviceFileFlags device_file_flags = META_DEVICE_FILE_FLAG_NONE; - g_autoptr (MetaDeviceFile) device_file = NULL; - GError *gbm_error = NULL; -#ifdef HAVE_EGL_DEVICE - GError *egl_device_error = NULL; -#endif - - if (!gpu_kms) - return create_renderer_gpu_data_surfaceless (renderer_native, error); - - if (!(meta_kms_device_get_flags (meta_gpu_kms_get_kms_device (gpu_kms)) & - META_KMS_DEVICE_FLAG_NO_MODE_SETTING)) - device_file_flags = META_DEVICE_FILE_FLAG_TAKE_CONTROL; - - device_file = meta_device_pool_open (device_pool, - meta_gpu_kms_get_file_path (gpu_kms), - device_file_flags, - error); - if (!device_file) - return NULL; - -#ifdef HAVE_EGL_DEVICE - /* Try to initialize the EGLDevice backend first. Whenever we use a - * non-NVIDIA GPU, the EGLDevice enumeration function won't find a match, and - * we'll fall back to GBM (which will always succeed as it has a software - * rendering fallback) - */ - renderer_gpu_data = create_renderer_gpu_data_egl_device (renderer_native, - device_file, - &egl_device_error); - if (renderer_gpu_data) - return renderer_gpu_data; -#endif - - renderer_gpu_data = create_renderer_gpu_data_gbm (renderer_native, - device_file, - &gbm_error); - if (renderer_gpu_data) - { -#ifdef HAVE_EGL_DEVICE - g_error_free (egl_device_error); -#endif - return renderer_gpu_data; - } - - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Failed to initialize renderer: " - "%s" -#ifdef HAVE_EGL_DEVICE - ", %s" -#endif - , gbm_error->message -#ifdef HAVE_EGL_DEVICE - , egl_device_error->message -#endif - ); - - g_error_free (gbm_error); -#ifdef HAVE_EGL_DEVICE - g_error_free (egl_device_error); -#endif - - return NULL; -} - -static gboolean -create_renderer_gpu_data (MetaRendererNative *renderer_native, - MetaGpuKms *gpu_kms, - GError **error) -{ - MetaRendererNativeGpuData *renderer_gpu_data; - - renderer_gpu_data = - meta_renderer_native_create_renderer_gpu_data (renderer_native, - gpu_kms, - error); - if (!renderer_gpu_data) - return FALSE; - - g_hash_table_insert (renderer_native->gpu_datas, - gpu_kms, - renderer_gpu_data); - - return TRUE; -} - -static gboolean -meta_renderer_native_ensure_gpu_data (MetaRendererNative *renderer_native, - MetaGpuKms *gpu_kms, - GError **error) -{ - MetaRendererNativeGpuData *renderer_gpu_data; - - renderer_gpu_data = g_hash_table_lookup (renderer_native->gpu_datas, gpu_kms); - if (renderer_gpu_data) - return TRUE; - - return create_renderer_gpu_data (renderer_native, gpu_kms, error); -} - -static void -on_gpu_added (MetaBackendNative *backend_native, - MetaGpuKms *gpu_kms, - MetaRendererNative *renderer_native) -{ - MetaBackend *backend = META_BACKEND (backend_native); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); - CoglDisplay *cogl_display = cogl_context_get_display (cogl_context); - GError *error = NULL; - - if (!create_renderer_gpu_data (renderer_native, gpu_kms, &error)) - { - g_warning ("on_gpu_added: could not create gpu_data for gpu %s: %s", - meta_gpu_kms_get_file_path (gpu_kms), error->message); - g_clear_error (&error); - } - - _cogl_winsys_egl_ensure_current (cogl_display); -} - -static void -on_power_save_mode_changed (MetaMonitorManager *monitor_manager, - MetaRendererNative *renderer_native) -{ - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - MetaKms *kms = meta_backend_native_get_kms (backend_native); - MetaPowerSave power_save_mode; - - power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager); - if (power_save_mode == META_POWER_SAVE_ON) - meta_renderer_native_queue_modes_reset (renderer_native); - else - meta_kms_discard_pending_page_flips (kms); -} - -void -meta_renderer_native_reset_modes (MetaRendererNative *renderer_native) -{ - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - MetaKms *kms = meta_backend_native_get_kms (backend_native); - - unset_disabled_crtcs (backend, kms); -} - -static MetaGpuKms * -choose_primary_gpu_unchecked (MetaBackend *backend, - MetaRendererNative *renderer_native) -{ - GList *gpus = meta_backend_get_gpus (backend); - GList *l; - int allow_sw; - - /* - * Check first hardware rendering devices, and if none found, - * then software rendering devices. - */ - for (allow_sw = 0; allow_sw < 2; allow_sw++) - { - /* First check if one was explicitly configured. */ - for (l = gpus; l; l = l->next) - { - MetaGpuKms *gpu_kms = META_GPU_KMS (l->data); - MetaKmsDevice *kms_device = meta_gpu_kms_get_kms_device (gpu_kms); - - if (meta_kms_device_get_flags (kms_device) & - META_KMS_DEVICE_FLAG_PREFERRED_PRIMARY) - { - g_message ("GPU %s selected primary given udev rule", - meta_gpu_kms_get_file_path (gpu_kms)); - return gpu_kms; - } - } - - /* Prefer a platform device */ - for (l = gpus; l; l = l->next) - { - MetaGpuKms *gpu_kms = META_GPU_KMS (l->data); - - if (meta_gpu_kms_is_platform_device (gpu_kms) && - (allow_sw == 1 || - gpu_kms_is_hardware_rendering (renderer_native, gpu_kms))) - { - g_message ("Integrated GPU %s selected as primary", - meta_gpu_kms_get_file_path (gpu_kms)); - return gpu_kms; - } - } - - /* Otherwise a device we booted with */ - for (l = gpus; l; l = l->next) - { - MetaGpuKms *gpu_kms = META_GPU_KMS (l->data); - - if (meta_gpu_kms_is_boot_vga (gpu_kms) && - (allow_sw == 1 || - gpu_kms_is_hardware_rendering (renderer_native, gpu_kms))) - { - g_message ("Boot VGA GPU %s selected as primary", - meta_gpu_kms_get_file_path (gpu_kms)); - return gpu_kms; - } - } - - /* Fall back to any device */ - for (l = gpus; l; l = l->next) - { - MetaGpuKms *gpu_kms = META_GPU_KMS (l->data); - - if (allow_sw == 1 || - gpu_kms_is_hardware_rendering (renderer_native, gpu_kms)) - { - g_message ("GPU %s selected as primary", - meta_gpu_kms_get_file_path (gpu_kms)); - return gpu_kms; - } - } - } - - g_assert_not_reached (); - return NULL; -} - -static MetaGpuKms * -choose_primary_gpu (MetaBackend *backend, - MetaRendererNative *renderer_native, - GError **error) -{ - MetaGpuKms *gpu_kms; - MetaRendererNativeGpuData *renderer_gpu_data; - - gpu_kms = choose_primary_gpu_unchecked (backend, renderer_native); - renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, - gpu_kms); - if (renderer_gpu_data->egl_display == EGL_NO_DISPLAY) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "The GPU %s chosen as primary is not supported by EGL.", - meta_gpu_kms_get_file_path (gpu_kms)); - return NULL; - } - - return gpu_kms; -} - -static gboolean -meta_renderer_native_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - MetaRendererNative *renderer_native = META_RENDERER_NATIVE (initable); - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - GList *gpus; - GList *l; - - gpus = meta_backend_get_gpus (backend); - if (gpus) - { - const char *use_kms_modifiers_debug_env; - - for (l = gpus; l; l = l->next) - { - MetaGpuKms *gpu_kms = META_GPU_KMS (l->data); - - if (!create_renderer_gpu_data (renderer_native, gpu_kms, error)) - return FALSE; - } - - renderer_native->primary_gpu_kms = choose_primary_gpu (backend, - renderer_native, - error); - if (!renderer_native->primary_gpu_kms) - return FALSE; - - use_kms_modifiers_debug_env = g_getenv ("MUTTER_DEBUG_USE_KMS_MODIFIERS"); - if (use_kms_modifiers_debug_env) - { - renderer_native->use_modifiers = - g_strcmp0 (use_kms_modifiers_debug_env, "1") == 0; - } - else - { - renderer_native->use_modifiers = - !meta_gpu_kms_disable_modifiers (renderer_native->primary_gpu_kms); - } - - meta_topic (META_DEBUG_KMS, "Usage of KMS modifiers is %s", - renderer_native->use_modifiers ? "enabled" : "disabled"); - } - else - { - if (!create_renderer_gpu_data (renderer_native, NULL, error)) - return FALSE; - } - - return TRUE; -} - -static void -initable_iface_init (GInitableIface *initable_iface) -{ - initable_iface->init = meta_renderer_native_initable_init; -} - -static void -meta_renderer_native_finalize (GObject *object) -{ - MetaRendererNative *renderer_native = META_RENDERER_NATIVE (object); - - clear_kept_alive_onscreens (renderer_native); - - g_clear_list (&renderer_native->power_save_page_flip_onscreens, - g_object_unref); - g_clear_handle_id (&renderer_native->power_save_page_flip_source_id, - g_source_remove); - - g_list_free (renderer_native->pending_mode_set_views); - - g_hash_table_destroy (renderer_native->gpu_datas); - g_clear_object (&renderer_native->gles3); - - G_OBJECT_CLASS (meta_renderer_native_parent_class)->finalize (object); -} - -static void -meta_renderer_native_constructed (GObject *object) -{ - MetaRendererNative *renderer_native = META_RENDERER_NATIVE (object); - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaSettings *settings = meta_backend_get_settings (backend); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - - if (meta_settings_is_experimental_feature_enabled ( - settings, META_EXPERIMENTAL_FEATURE_KMS_MODIFIERS)) - renderer_native->use_modifiers = TRUE; - - g_signal_connect (backend, "gpu-added", - G_CALLBACK (on_gpu_added), renderer_native); - g_signal_connect (monitor_manager, "power-save-mode-changed", - G_CALLBACK (on_power_save_mode_changed), renderer_native); - - G_OBJECT_CLASS (meta_renderer_native_parent_class)->constructed (object); -} - -static void -meta_renderer_native_init (MetaRendererNative *renderer_native) -{ - renderer_native->gpu_datas = - g_hash_table_new_full (NULL, NULL, - NULL, - (GDestroyNotify) meta_renderer_native_gpu_data_free); -} - -static void -meta_renderer_native_class_init (MetaRendererNativeClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaRendererClass *renderer_class = META_RENDERER_CLASS (klass); - - object_class->finalize = meta_renderer_native_finalize; - object_class->constructed = meta_renderer_native_constructed; - - renderer_class->create_cogl_renderer = meta_renderer_native_create_cogl_renderer; - renderer_class->create_view = meta_renderer_native_create_view; - renderer_class->rebuild_views = meta_renderer_native_rebuild_views; -} - -MetaRendererNative * -meta_renderer_native_new (MetaBackendNative *backend_native, - GError **error) -{ - return g_initable_new (META_TYPE_RENDERER_NATIVE, - NULL, - error, - "backend", backend_native, - NULL); -} diff --git a/src/backends/native/meta-renderer-native.h b/src/backends/native/meta-renderer-native.h deleted file mode 100644 index 2c23c651a..000000000 --- a/src/backends/native/meta-renderer-native.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#ifndef META_RENDERER_NATIVE_H -#define META_RENDERER_NATIVE_H - -#include -#include -#include - -#include "backends/meta-renderer.h" -#include "backends/native/meta-gpu-kms.h" -#include "backends/native/meta-monitor-manager-native.h" - -#define META_TYPE_RENDERER_NATIVE (meta_renderer_native_get_type ()) -G_DECLARE_FINAL_TYPE (MetaRendererNative, meta_renderer_native, - META, RENDERER_NATIVE, - MetaRenderer) - -typedef enum _MetaRendererNativeMode -{ - META_RENDERER_NATIVE_MODE_GBM, - META_RENDERER_NATIVE_MODE_SURFACELESS, -#ifdef HAVE_EGL_DEVICE - META_RENDERER_NATIVE_MODE_EGL_DEVICE -#endif -} MetaRendererNativeMode; - -MetaRendererNative * meta_renderer_native_new (MetaBackendNative *backend_native, - GError **error); - -struct gbm_device * meta_gbm_device_from_gpu (MetaGpuKms *gpu_kms); - -MetaGpuKms * meta_renderer_native_get_primary_gpu (MetaRendererNative *renderer_native); - -MetaDeviceFile * meta_renderer_native_get_primary_device_file (MetaRendererNative *renderer_native); - -void meta_renderer_native_prepare_frame (MetaRendererNative *renderer_native, - MetaRendererView *view, - ClutterFrame *frame); - -void meta_renderer_native_finish_frame (MetaRendererNative *renderer_native, - MetaRendererView *view, - ClutterFrame *frame); - -void meta_renderer_native_reset_modes (MetaRendererNative *renderer_native); - -gboolean meta_renderer_native_use_modifiers (MetaRendererNative *renderer_native); - -#endif /* META_RENDERER_NATIVE_H */ diff --git a/src/backends/native/meta-seat-impl.c b/src/backends/native/meta-seat-impl.c deleted file mode 100644 index 26db30bd4..000000000 --- a/src/backends/native/meta-seat-impl.c +++ /dev/null @@ -1,3542 +0,0 @@ -/* - * Clutter. - * - * An OpenGL based 'interactive canvas' library. - * - * Copyright (C) 2010 Intel Corp. - * Copyright (C) 2014 Jonas Ådahl - * Copyright (C) 2016 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 . - * - * Author: Damien Lespiau - * Author: Jonas Ådahl - * Author: Carlos Garnacho - */ - -#include "config.h" - -#include -#include -#include -#include -#include - -#include "backends/meta-cursor-tracker-private.h" -#include "backends/native/meta-backend-native-private.h" -#include "backends/native/meta-barrier-native.h" -#include "backends/native/meta-device-pool.h" -#include "backends/native/meta-input-thread.h" -#include "backends/native/meta-virtual-input-device-native.h" -#include "clutter/clutter-mutter.h" -#include "core/bell.h" - -#include "meta-private-enum-types.h" - -/* - * Clutter makes the assumption that two core devices have ID's 2 and 3 (core - * pointer and core keyboard). - * - * Since the two first devices that will ever be created will be the virtual - * pointer and virtual keyboard of the first seat, we fulfill the made - * assumptions by having the first device having ID 2 and following 3. - */ -#define INITIAL_DEVICE_ID 2 - -/* Try to keep the pointer inside the stage. Hopefully no one is using - * this backend with stages smaller than this. */ -#define INITIAL_POINTER_X 16 -#define INITIAL_POINTER_Y 16 - -#define AUTOREPEAT_VALUE 2 - -#define DISCRETE_SCROLL_STEP 10.0 - -#ifndef BTN_STYLUS3 -#define BTN_STYLUS3 0x149 /* Linux 4.15 */ -#endif - -struct _MetaEventSource -{ - GSource source; - - MetaSeatImpl *seat_impl; - GPollFD event_poll_fd; -}; - -enum -{ - PROP_0, - PROP_SEAT, - PROP_SEAT_ID, - PROP_FLAGS, - N_PROPS, -}; - -static GParamSpec *props[N_PROPS] = { NULL }; - -enum -{ - KBD_A11Y_FLAGS_CHANGED, - KBD_A11Y_MODS_STATE_CHANGED, - TOUCH_MODE, - BELL, - MODS_STATE_CHANGED, - N_SIGNALS -}; - -static guint signals[N_SIGNALS] = { 0 }; - -typedef struct _MetaSeatImplPrivate -{ - GHashTable *device_files; -} MetaSeatImplPrivate; - -static void meta_seat_impl_initable_iface_init (GInitableIface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaSeatImpl, meta_seat_impl, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - meta_seat_impl_initable_iface_init) - G_ADD_PRIVATE (MetaSeatImpl)) - -static void process_events (MetaSeatImpl *seat_impl); -void meta_seat_impl_constrain_pointer (MetaSeatImpl *seat_impl, - ClutterInputDevice *core_pointer, - uint64_t time_us, - float x, - float y, - float *new_x, - float *new_y); -void meta_seat_impl_filter_relative_motion (MetaSeatImpl *seat_impl, - ClutterInputDevice *device, - float x, - float y, - float *dx, - float *dy); -void meta_seat_impl_clear_repeat_source (MetaSeatImpl *seat_impl); - -void -meta_seat_impl_run_input_task (MetaSeatImpl *seat_impl, - GTask *task, - GSourceFunc dispatch_func) -{ - GSource *source; - - source = g_idle_source_new (); - g_source_set_priority (source, G_PRIORITY_HIGH); - g_source_set_callback (source, - dispatch_func, - g_object_ref (task), - g_object_unref); - g_source_attach (source, seat_impl->input_context); - g_source_unref (source); -} - -void -meta_seat_impl_sync_leds_in_impl (MetaSeatImpl *seat_impl) -{ - GSList *iter; - MetaInputDeviceNative *device_native; - int caps_lock, num_lock, scroll_lock; - enum libinput_led leds = 0; - - caps_lock = xkb_state_led_index_is_active (seat_impl->xkb, - seat_impl->caps_lock_led); - num_lock = xkb_state_led_index_is_active (seat_impl->xkb, - seat_impl->num_lock_led); - scroll_lock = xkb_state_led_index_is_active (seat_impl->xkb, - seat_impl->scroll_lock_led); - - if (caps_lock) - leds |= LIBINPUT_LED_CAPS_LOCK; - if (num_lock) - leds |= LIBINPUT_LED_NUM_LOCK; - if (scroll_lock) - leds |= LIBINPUT_LED_SCROLL_LOCK; - - for (iter = seat_impl->devices; iter; iter = iter->next) - { - device_native = iter->data; - meta_input_device_native_update_leds_in_impl (device_native, leds); - } -} - -MetaTouchState * -meta_seat_impl_lookup_touch_state_in_impl (MetaSeatImpl *seat_impl, - int seat_slot) -{ - if (!seat_impl->touch_states) - return NULL; - - return g_hash_table_lookup (seat_impl->touch_states, - GINT_TO_POINTER (seat_slot)); -} - -static void -meta_touch_state_free (MetaTouchState *state) -{ - g_free (state); -} - -MetaTouchState * -meta_seat_impl_acquire_touch_state_in_impl (MetaSeatImpl *seat_impl, - int seat_slot) -{ - MetaTouchState *touch_state; - - if (!seat_impl->touch_states) - { - seat_impl->touch_states = - g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) meta_touch_state_free); - } - - g_assert (!g_hash_table_contains (seat_impl->touch_states, - GINT_TO_POINTER (seat_slot))); - - touch_state = g_new0 (MetaTouchState, 1); - *touch_state = (MetaTouchState) { - .seat_impl = seat_impl, - .seat_slot = seat_slot, - }; - - g_hash_table_insert (seat_impl->touch_states, GINT_TO_POINTER (seat_slot), - touch_state); - - return touch_state; -} - -void -meta_seat_impl_release_touch_state_in_impl (MetaSeatImpl *seat_impl, - int seat_slot) -{ - if (!seat_impl->touch_states) - return; - g_hash_table_remove (seat_impl->touch_states, GINT_TO_POINTER (seat_slot)); -} - -void -meta_seat_impl_clear_repeat_source (MetaSeatImpl *seat_impl) -{ - if (seat_impl->repeat_source) - { - g_source_destroy (seat_impl->repeat_source); - g_clear_pointer (&seat_impl->repeat_source, g_source_unref); - } - - g_clear_object (&seat_impl->repeat_device); -} - -static void -dispatch_libinput (MetaSeatImpl *seat_impl) -{ - libinput_dispatch (seat_impl->libinput); - process_events (seat_impl); -} - -static gboolean -keyboard_repeat (gpointer data) -{ - MetaSeatImpl *seat_impl = data; - - /* There might be events queued in libinput that could cancel the - repeat timer. */ - if (seat_impl->libinput) - { - dispatch_libinput (seat_impl); - if (!seat_impl->repeat_source) - return G_SOURCE_REMOVE; - } - - g_return_val_if_fail (seat_impl->repeat_device != NULL, G_SOURCE_REMOVE); - - meta_seat_impl_notify_key_in_impl (seat_impl, - seat_impl->repeat_device, - g_source_get_time (seat_impl->repeat_source), - seat_impl->repeat_key, - AUTOREPEAT_VALUE, - FALSE); - - return G_SOURCE_CONTINUE; -} - -static void -queue_event (MetaSeatImpl *seat_impl, - ClutterEvent *event) -{ - _clutter_event_push (event, FALSE); -} - -static int -update_button_count (MetaSeatImpl *seat_impl, - uint32_t button, - uint32_t state) -{ - if (state) - { - return ++seat_impl->button_count[button]; - } - else - { - /* Handle cases where we newer saw the initial pressed event. */ - if (seat_impl->button_count[button] == 0) - { - meta_topic (META_DEBUG_INPUT, - "Counting release of key 0x%x and count is already 0", - button); - return 0; - } - - return --seat_impl->button_count[button]; - } -} - -void -meta_seat_impl_queue_main_thread_idle (MetaSeatImpl *seat_impl, - GSourceFunc func, - gpointer user_data, - GDestroyNotify destroy_notify) -{ - GSource *source; - - source = g_idle_source_new (); - g_source_set_priority (source, G_PRIORITY_HIGH); - g_source_set_callback (source, func, user_data, destroy_notify); - - g_source_attach (source, seat_impl->main_context); - g_source_unref (source); -} - -typedef struct -{ - MetaSeatImpl *seat_impl; - guint signal_id; - GArray *args; -} MetaSeatSignalData; - -static gboolean -emit_signal_in_main (MetaSeatSignalData *data) -{ - g_signal_emitv ((GValue *) data->args->data, - data->signal_id, - 0, NULL); - - return G_SOURCE_REMOVE; -} - -static void -signal_data_free (MetaSeatSignalData *data) -{ - g_array_unref (data->args); - g_free (data); -} - -static void -emit_signal (MetaSeatImpl *seat_impl, - guint signal_id, - GValue *args, - int n_args) -{ - MetaSeatSignalData *emit_signal_data; - GArray *array; - GValue self = G_VALUE_INIT; - - g_value_init (&self, META_TYPE_SEAT_IMPL); - g_value_set_object (&self, seat_impl); - - array = g_array_new (FALSE, FALSE, sizeof (GValue)); - g_array_append_val (array, self); - if (args && n_args > 0) - g_array_append_vals (array, args, n_args); - - emit_signal_data = g_new0 (MetaSeatSignalData, 1); - emit_signal_data->seat_impl = seat_impl; - emit_signal_data->signal_id = signal_id; - emit_signal_data->args = array; - - meta_seat_impl_queue_main_thread_idle (seat_impl, - (GSourceFunc) emit_signal_in_main, - emit_signal_data, - (GDestroyNotify) signal_data_free); -} - -void -meta_seat_impl_notify_key_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *device, - uint64_t time_us, - uint32_t key, - uint32_t state, - gboolean update_keys) -{ - ClutterEvent *event = NULL; - enum xkb_state_component changed_state; - uint32_t keycode; - - if (state != AUTOREPEAT_VALUE) - { - /* Drop any repeated button press (for example from virtual devices. */ - int count = update_button_count (seat_impl, key, state); - if ((state && count > 1) || - (!state && count != 0)) - { - meta_topic (META_DEBUG_INPUT, - "Dropping repeated %s of key 0x%x, count %d, state %d", - state ? "press" : "release", key, count, state); - return; - } - } - - event = meta_key_event_new_from_evdev (device, - seat_impl->core_keyboard, - seat_impl->xkb, - seat_impl->button_state, - us2ms (time_us), key, state); - event->key.evdev_code = key; - - keycode = meta_xkb_evdev_to_keycode (key); - - /* We must be careful and not pass multiple releases to xkb, otherwise it gets - confused and locks the modifiers */ - if (state != AUTOREPEAT_VALUE) - { - changed_state = xkb_state_update_key (seat_impl->xkb, keycode, - state ? XKB_KEY_DOWN : XKB_KEY_UP); - } - else - { - changed_state = 0; - clutter_event_set_flags (event, CLUTTER_EVENT_FLAG_REPEATED); - } - - if (!meta_input_device_native_process_kbd_a11y_event_in_impl (seat_impl->core_keyboard, - event)) - queue_event (seat_impl, event); - else - clutter_event_free (event); - - if (update_keys && (changed_state & XKB_STATE_LEDS)) - { - MetaInputDeviceNative *keyboard_native; - gboolean numlock_active; - - meta_keymap_native_update_in_impl (seat_impl->keymap, - seat_impl, - seat_impl->xkb); - meta_seat_impl_sync_leds_in_impl (seat_impl); - - numlock_active = - xkb_state_mod_name_is_active (seat_impl->xkb, XKB_MOD_NAME_NUM, - XKB_STATE_MODS_LATCHED | - XKB_STATE_MODS_LOCKED); - meta_input_settings_maybe_save_numlock_state (seat_impl->input_settings, - numlock_active); - - keyboard_native = META_INPUT_DEVICE_NATIVE (seat_impl->core_keyboard); - meta_input_device_native_a11y_maybe_notify_toggle_keys_in_impl (keyboard_native); - } - - if (state == 0 || /* key release */ - !seat_impl->repeat || - !xkb_keymap_key_repeats (xkb_state_get_keymap (seat_impl->xkb), - keycode)) - { - seat_impl->repeat_count = 0; - meta_seat_impl_clear_repeat_source (seat_impl); - return; - } - - if (state == 1) /* key press */ - seat_impl->repeat_count = 0; - - seat_impl->repeat_count += 1; - seat_impl->repeat_key = key; - - switch (seat_impl->repeat_count) - { - case 1: - case 2: - { - uint32_t interval; - - meta_seat_impl_clear_repeat_source (seat_impl); - seat_impl->repeat_device = g_object_ref (device); - - if (seat_impl->repeat_count == 1) - interval = seat_impl->repeat_delay; - else - interval = seat_impl->repeat_interval; - - seat_impl->repeat_source = g_timeout_source_new (interval); - g_source_set_priority (seat_impl->repeat_source, CLUTTER_PRIORITY_EVENTS); - g_source_set_callback (seat_impl->repeat_source, - keyboard_repeat, seat_impl, NULL); - g_source_attach (seat_impl->repeat_source, seat_impl->input_context); - return; - } - default: - return; - } -} - -static ClutterEvent * -new_absolute_motion_event (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - uint64_t time_us, - float x, - float y, - double *axes) -{ - ClutterEvent *event; - - event = clutter_event_new (CLUTTER_MOTION); - - if (clutter_input_device_get_device_type (input_device) != CLUTTER_TABLET_DEVICE) - { - meta_seat_impl_constrain_pointer (seat_impl, - seat_impl->core_pointer, - time_us, - seat_impl->pointer_x, - seat_impl->pointer_y, - &x, &y); - } - else - { - /* This may happen early at startup */ - if (seat_impl->viewports) - { - meta_input_device_native_translate_coordinates_in_impl (input_device, - seat_impl->viewports, - &x, - &y); - } - } - - event->motion.time_us = time_us; - event->motion.time = us2ms (time_us); - meta_xkb_translate_state (event, seat_impl->xkb, seat_impl->button_state); - event->motion.x = x; - event->motion.y = y; - - event->motion.axes = axes; - clutter_event_set_device (event, seat_impl->core_pointer); - clutter_event_set_source_device (event, input_device); - - g_rw_lock_writer_lock (&seat_impl->state_lock); - - if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE) - { - MetaInputDeviceNative *device_native = - META_INPUT_DEVICE_NATIVE (input_device); - - clutter_event_set_device_tool (event, device_native->last_tool); - clutter_event_set_device (event, input_device); - meta_input_device_native_set_coords_in_impl (META_INPUT_DEVICE_NATIVE (input_device), - x, y); - } - else - { - clutter_event_set_device (event, seat_impl->core_pointer); - meta_input_device_native_set_coords_in_impl (META_INPUT_DEVICE_NATIVE (seat_impl->core_pointer), - x, y); - } - - if (clutter_input_device_get_device_type (input_device) != CLUTTER_TABLET_DEVICE) - { - seat_impl->pointer_x = x; - seat_impl->pointer_y = y; - } - - g_rw_lock_writer_unlock (&seat_impl->state_lock); - - return event; -} - -void -meta_seat_impl_notify_relative_motion_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - uint64_t time_us, - float dx, - float dy, - float dx_unaccel, - float dy_unaccel) -{ - float new_x, new_y; - ClutterEvent *event; - - meta_seat_impl_filter_relative_motion (seat_impl, - input_device, - seat_impl->pointer_x, - seat_impl->pointer_y, - &dx, - &dy); - - new_x = seat_impl->pointer_x + dx; - new_y = seat_impl->pointer_y + dy; - event = new_absolute_motion_event (seat_impl, input_device, - time_us, new_x, new_y, NULL); - - event->motion.flags |= CLUTTER_EVENT_FLAG_RELATIVE_MOTION; - event->motion.dx = dx; - event->motion.dy = dy; - event->motion.dx_unaccel = dx_unaccel; - event->motion.dy_unaccel = dy_unaccel; - - queue_event (seat_impl, event); -} - -void -meta_seat_impl_notify_absolute_motion_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - uint64_t time_us, - float x, - float y, - double *axes) -{ - ClutterEvent *event; - - event = new_absolute_motion_event (seat_impl, input_device, time_us, x, y, axes); - - queue_event (seat_impl, event); -} - -void -meta_seat_impl_notify_button_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - uint64_t time_us, - uint32_t button, - uint32_t state) -{ - MetaInputDeviceNative *device_native = (MetaInputDeviceNative *) input_device; - ClutterEvent *event = NULL; - int button_nr; - static int maskmap[8] = - { - CLUTTER_BUTTON1_MASK, CLUTTER_BUTTON3_MASK, CLUTTER_BUTTON2_MASK, - CLUTTER_BUTTON4_MASK, CLUTTER_BUTTON5_MASK, 0, 0, 0 - }; - int button_count; - - /* Drop any repeated button press (for example from virtual devices. */ - button_count = update_button_count (seat_impl, button, state); - if ((state && button_count > 1) || - (!state && button_count != 0)) - { - meta_topic (META_DEBUG_INPUT, - "Dropping repeated %s of button 0x%x, count %d", - state ? "press" : "release", button, button_count); - return; - } - - /* The evdev button numbers don't map sequentially to clutter button - * numbers (the right and middle mouse buttons are in the opposite - * order) so we'll map them directly with a switch statement */ - switch (button) - { - case BTN_LEFT: - case BTN_TOUCH: - button_nr = CLUTTER_BUTTON_PRIMARY; - break; - - case BTN_RIGHT: - case BTN_STYLUS: - button_nr = CLUTTER_BUTTON_SECONDARY; - break; - - case BTN_MIDDLE: - case BTN_STYLUS2: - button_nr = CLUTTER_BUTTON_MIDDLE; - break; - - case 0x149: /* BTN_STYLUS3 */ - button_nr = 8; - break; - - default: - /* For compatibility reasons, all additional buttons go after the old 4-7 scroll ones */ - if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE) - button_nr = button - BTN_TOOL_PEN + 4; - else - button_nr = button - (BTN_LEFT - 1) + 4; - break; - } - - if (button_nr < 1 || button_nr > 12) - { - g_warning ("Unhandled button event 0x%x", button); - return; - } - - if (state) - event = clutter_event_new (CLUTTER_BUTTON_PRESS); - else - event = clutter_event_new (CLUTTER_BUTTON_RELEASE); - - if (button_nr < G_N_ELEMENTS (maskmap)) - { - /* Update the modifiers */ - if (state) - seat_impl->button_state |= maskmap[button_nr - 1]; - else - seat_impl->button_state &= ~maskmap[button_nr - 1]; - } - - event->button.time = us2ms (time_us); - meta_xkb_translate_state (event, seat_impl->xkb, seat_impl->button_state); - event->button.button = button_nr; - - if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE) - { - meta_input_device_native_get_coords_in_impl (device_native, - &event->button.x, - &event->button.y); - } - else - { - meta_input_device_native_get_coords_in_impl (META_INPUT_DEVICE_NATIVE (seat_impl->core_pointer), - &event->button.x, - &event->button.y); - } - - clutter_event_set_device (event, seat_impl->core_pointer); - clutter_event_set_source_device (event, input_device); - - if (device_native->last_tool) - { - /* Apply the button event code as per the tool mapping */ - uint32_t mapped_button; - - mapped_button = meta_input_device_tool_native_get_button_code_in_impl (device_native->last_tool, - button_nr); - if (mapped_button != 0) - button = mapped_button; - } - - event->button.evdev_code = button; - - if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE) - { - clutter_event_set_device_tool (event, device_native->last_tool); - clutter_event_set_device (event, input_device); - } - else - { - clutter_event_set_device (event, seat_impl->core_pointer); - } - - queue_event (seat_impl, event); -} - -static MetaSeatImpl * -seat_impl_from_device (ClutterInputDevice *device) -{ - MetaInputDeviceNative *device_native = META_INPUT_DEVICE_NATIVE (device); - - return meta_input_device_native_get_seat_impl (device_native); -} - -static void -notify_scroll (ClutterInputDevice *input_device, - uint64_t time_us, - double dx, - double dy, - ClutterScrollSource scroll_source, - ClutterScrollFinishFlags flags, - gboolean emulated) -{ - MetaSeatImpl *seat_impl; - ClutterEvent *event = NULL; - double scroll_factor; - - seat_impl = seat_impl_from_device (input_device); - - event = clutter_event_new (CLUTTER_SCROLL); - - event->scroll.time = us2ms (time_us); - meta_xkb_translate_state (event, seat_impl->xkb, seat_impl->button_state); - - /* libinput pointer axis events are in pointer motion coordinate space. - * To convert to Xi2 discrete step coordinate space, multiply the factor - * 1/10. */ - event->scroll.direction = CLUTTER_SCROLL_SMOOTH; - scroll_factor = 1.0 / DISCRETE_SCROLL_STEP; - clutter_event_set_scroll_delta (event, - scroll_factor * dx, - scroll_factor * dy); - - event->scroll.x = seat_impl->pointer_x; - event->scroll.y = seat_impl->pointer_y; - clutter_event_set_device (event, seat_impl->core_pointer); - clutter_event_set_source_device (event, input_device); - event->scroll.scroll_source = scroll_source; - event->scroll.finish_flags = flags; - - _clutter_event_set_pointer_emulated (event, emulated); - - queue_event (seat_impl, event); -} - -static void -notify_discrete_scroll (ClutterInputDevice *input_device, - uint64_t time_us, - ClutterScrollDirection direction, - ClutterScrollSource scroll_source, - gboolean emulated) -{ - MetaSeatImpl *seat_impl; - ClutterEvent *event = NULL; - - if (direction == CLUTTER_SCROLL_SMOOTH) - return; - - seat_impl = seat_impl_from_device (input_device); - - event = clutter_event_new (CLUTTER_SCROLL); - - event->scroll.time = us2ms (time_us); - meta_xkb_translate_state (event, seat_impl->xkb, seat_impl->button_state); - - event->scroll.direction = direction; - - event->scroll.x = seat_impl->pointer_x; - event->scroll.y = seat_impl->pointer_y; - clutter_event_set_device (event, seat_impl->core_pointer); - clutter_event_set_source_device (event, input_device); - event->scroll.scroll_source = scroll_source; - - _clutter_event_set_pointer_emulated (event, emulated); - - queue_event (seat_impl, event); -} - -static void -check_notify_discrete_scroll (MetaSeatImpl *seat_impl, - ClutterInputDevice *device, - uint64_t time_us, - ClutterScrollSource scroll_source) -{ - int i, n_xscrolls, n_yscrolls; - - n_xscrolls = floor ((fabs (seat_impl->accum_scroll_dx) + DBL_EPSILON) / - DISCRETE_SCROLL_STEP); - n_yscrolls = floor ((fabs (seat_impl->accum_scroll_dy) + DBL_EPSILON) / - DISCRETE_SCROLL_STEP); - - for (i = 0; i < n_xscrolls; i++) - { - notify_discrete_scroll (device, time_us, - seat_impl->accum_scroll_dx > 0 ? - CLUTTER_SCROLL_RIGHT : CLUTTER_SCROLL_LEFT, - scroll_source, TRUE); - } - - for (i = 0; i < n_yscrolls; i++) - { - notify_discrete_scroll (device, time_us, - seat_impl->accum_scroll_dy > 0 ? - CLUTTER_SCROLL_DOWN : CLUTTER_SCROLL_UP, - scroll_source, TRUE); - } - - seat_impl->accum_scroll_dx = - fmodf (seat_impl->accum_scroll_dx, DISCRETE_SCROLL_STEP); - seat_impl->accum_scroll_dy = - fmodf (seat_impl->accum_scroll_dy, DISCRETE_SCROLL_STEP); -} - -void -meta_seat_impl_notify_scroll_continuous_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - uint64_t time_us, - double dx, - double dy, - ClutterScrollSource scroll_source, - ClutterScrollFinishFlags finish_flags) -{ - if (finish_flags & CLUTTER_SCROLL_FINISHED_HORIZONTAL) - seat_impl->accum_scroll_dx = 0; - else - seat_impl->accum_scroll_dx += dx; - - if (finish_flags & CLUTTER_SCROLL_FINISHED_VERTICAL) - seat_impl->accum_scroll_dy = 0; - else - seat_impl->accum_scroll_dy += dy; - - notify_scroll (input_device, time_us, dx, dy, scroll_source, - finish_flags, FALSE); - check_notify_discrete_scroll (seat_impl, input_device, time_us, scroll_source); -} - -static ClutterScrollDirection -discrete_to_direction (double discrete_dx, - double discrete_dy) -{ - if (discrete_dx > 0) - return CLUTTER_SCROLL_RIGHT; - else if (discrete_dx < 0) - return CLUTTER_SCROLL_LEFT; - else if (discrete_dy > 0) - return CLUTTER_SCROLL_DOWN; - else if (discrete_dy < 0) - return CLUTTER_SCROLL_UP; - else - g_assert_not_reached (); - return 0; -} - -void -meta_seat_impl_notify_discrete_scroll_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - uint64_t time_us, - double discrete_dx, - double discrete_dy, - ClutterScrollSource scroll_source) -{ - notify_scroll (input_device, time_us, - discrete_dx * DISCRETE_SCROLL_STEP, - discrete_dy * DISCRETE_SCROLL_STEP, - scroll_source, CLUTTER_SCROLL_FINISHED_NONE, - TRUE); - notify_discrete_scroll (input_device, time_us, - discrete_to_direction (discrete_dx, discrete_dy), - scroll_source, FALSE); - -} - -void -meta_seat_impl_notify_touch_event_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - ClutterEventType evtype, - uint64_t time_us, - int slot, - double x, - double y) -{ - ClutterEvent *event = NULL; - - event = clutter_event_new (evtype); - - event->touch.time = us2ms (time_us); - event->touch.x = x; - event->touch.y = y; - meta_input_device_native_translate_coordinates_in_impl (input_device, - seat_impl->viewports, - &event->touch.x, - &event->touch.y); - - /* "NULL" sequences are special cased in clutter */ - event->touch.sequence = GINT_TO_POINTER (MAX (1, slot + 1)); - meta_xkb_translate_state (event, seat_impl->xkb, seat_impl->button_state); - - if (evtype == CLUTTER_TOUCH_BEGIN || - evtype == CLUTTER_TOUCH_UPDATE) - event->touch.modifier_state |= CLUTTER_BUTTON1_MASK; - - clutter_event_set_device (event, seat_impl->core_pointer); - clutter_event_set_source_device (event, input_device); - - queue_event (seat_impl, event); -} - -/* - * MetaEventSource for reading input devices - */ - -static gboolean -meta_event_prepare (GSource *g_source, - int *timeout_ms) -{ - MetaEventSource *source = (MetaEventSource *) g_source; - MetaSeatImpl *seat_impl = source->seat_impl; - - *timeout_ms = -1; - - switch (libinput_next_event_type (seat_impl->libinput)) - { - case LIBINPUT_EVENT_NONE: - return FALSE; - default: - return TRUE; - } -} - -static gboolean -meta_event_check (GSource *source) -{ - MetaEventSource *event_source = (MetaEventSource *) source; - gboolean retval; - - retval = !!(event_source->event_poll_fd.revents & G_IO_IN); - - return retval; -} - -static void -constrain_to_barriers (MetaSeatImpl *seat_impl, - ClutterInputDevice *device, - uint32_t time, - float *new_x, - float *new_y) -{ - meta_barrier_manager_native_process_in_impl (seat_impl->barrier_manager, - device, - time, - new_x, new_y); -} - -/* - * The pointer constrain code is mostly a rip-off of the XRandR code from Xorg. - * (from xserver/randr/rrcrtc.c, RRConstrainCursorHarder) - * - * Copyright © 2006 Keith Packard - * Copyright 2010 Red Hat, Inc - * - */ - -static void -constrain_all_screen_monitors (ClutterInputDevice *device, - MetaViewportInfo *viewports, - float *x, - float *y) -{ - float cx, cy; - int i, n_views; - - meta_input_device_native_get_coords_in_impl (META_INPUT_DEVICE_NATIVE (device), - &cx, &cy); - - /* if we're trying to escape, clamp to the CRTC we're coming from */ - - n_views = meta_viewport_info_get_num_views (viewports); - - for (i = 0; i < n_views; i++) - { - int left, right, top, bottom; - cairo_rectangle_int_t rect; - - meta_viewport_info_get_view_info (viewports, i, &rect, NULL); - - left = rect.x; - right = left + rect.width; - top = rect.y; - bottom = top + rect.height; - - if ((cx >= left) && (cx < right) && (cy >= top) && (cy < bottom)) - { - if (*x < left) - *x = left; - if (*x >= right) - *x = right - 1; - if (*y < top) - *y = top; - if (*y >= bottom) - *y = bottom - 1; - - return; - } - } -} - -void -meta_seat_impl_constrain_pointer (MetaSeatImpl *seat_impl, - ClutterInputDevice *core_pointer, - uint64_t time_us, - float x, - float y, - float *new_x, - float *new_y) -{ - /* Constrain to barriers */ - constrain_to_barriers (seat_impl, core_pointer, - us2ms (time_us), - new_x, new_y); - - /* Bar to constraints */ - if (seat_impl->pointer_constraint) - { - meta_pointer_constraint_impl_constrain (seat_impl->pointer_constraint, - core_pointer, - us2ms (time_us), - x, y, - new_x, new_y); - } - - if (seat_impl->viewports) - { - /* if we're moving inside a monitor, we're fine */ - if (meta_viewport_info_get_view_at (seat_impl->viewports, - *new_x, *new_y) >= 0) - return; - - /* if we're trying to escape, clamp to the CRTC we're coming from */ - constrain_all_screen_monitors (core_pointer, seat_impl->viewports, - new_x, new_y); - } -} - -static void -relative_motion_across_outputs (MetaViewportInfo *viewports, - int view, - float cur_x, - float cur_y, - float *dx_inout, - float *dy_inout) -{ - int cur_view = view; - float x = cur_x, y = cur_y; - float target_x = cur_x, target_y = cur_y; - float dx = *dx_inout, dy = *dy_inout; - MetaDisplayDirection direction = -1; - - while (cur_view >= 0) - { - MetaLine2 left, right, top, bottom, motion; - MetaVector2 intersection; - cairo_rectangle_int_t rect; - float scale; - - meta_viewport_info_get_view_info (viewports, cur_view, &rect, &scale); - - motion = (MetaLine2) { - .a = { x, y }, - .b = { x + (dx * scale), y + (dy * scale) } - }; - left = (MetaLine2) { - { rect.x, rect.y }, - { rect.x, rect.y + rect.height } - }; - right = (MetaLine2) { - { rect.x + rect.width, rect.y }, - { rect.x + rect.width, rect.y + rect.height } - }; - top = (MetaLine2) { - { rect.x, rect.y }, - { rect.x + rect.width, rect.y } - }; - bottom = (MetaLine2) { - { rect.x, rect.y + rect.height }, - { rect.x + rect.width, rect.y + rect.height } - }; - - target_x = motion.b.x; - target_y = motion.b.y; - - if (direction != META_DISPLAY_RIGHT && - meta_line2_intersects_with (&motion, &left, &intersection)) - direction = META_DISPLAY_LEFT; - else if (direction != META_DISPLAY_LEFT && - meta_line2_intersects_with (&motion, &right, &intersection)) - direction = META_DISPLAY_RIGHT; - else if (direction != META_DISPLAY_DOWN && - meta_line2_intersects_with (&motion, &top, &intersection)) - direction = META_DISPLAY_UP; - else if (direction != META_DISPLAY_UP && - meta_line2_intersects_with (&motion, &bottom, &intersection)) - direction = META_DISPLAY_DOWN; - else - /* We reached the dest logical monitor */ - break; - - x = intersection.x; - y = intersection.y; - dx -= intersection.x - motion.a.x; - dy -= intersection.y - motion.a.y; - - cur_view = meta_viewport_info_get_neighbor (viewports, cur_view, - direction); - } - - *dx_inout = target_x - cur_x; - *dy_inout = target_y - cur_y; -} - -void -meta_seat_impl_filter_relative_motion (MetaSeatImpl *seat_impl, - ClutterInputDevice *device, - float x, - float y, - float *dx, - float *dy) -{ - int view, dest_view; - float new_dx, new_dy, scale; - - if (!seat_impl->viewports) - return; - if (meta_viewport_info_is_views_scaled (seat_impl->viewports)) - return; - - view = meta_viewport_info_get_view_at (seat_impl->viewports, x, y); - if (view < 0) - return; - - meta_viewport_info_get_view_info (seat_impl->viewports, view, NULL, &scale); - new_dx = (*dx) * scale; - new_dy = (*dy) * scale; - - dest_view = meta_viewport_info_get_view_at (seat_impl->viewports, - x + new_dx, - y + new_dy); - if (dest_view >= 0 && dest_view != view) - { - /* If we are crossing monitors, attempt to bisect the distance on each - * axis and apply the relative scale for each of them. - */ - new_dx = *dx; - new_dy = *dy; - relative_motion_across_outputs (seat_impl->viewports, view, - x, y, &new_dx, &new_dy); - } - - *dx = new_dx; - *dy = new_dy; -} - -static void -notify_absolute_motion_in_impl (ClutterInputDevice *input_device, - uint64_t time_us, - float x, - float y, - double *axes) -{ - MetaSeatImpl *seat_impl; - ClutterEvent *event; - - seat_impl = seat_impl_from_device (input_device); - event = new_absolute_motion_event (seat_impl, input_device, time_us, x, y, axes); - - queue_event (seat_impl, event); -} - -static void -notify_relative_tool_motion_in_impl (ClutterInputDevice *input_device, - uint64_t time_us, - float dx, - float dy, - double *axes) -{ - MetaInputDeviceNative *device_native; - ClutterEvent *event; - MetaSeatImpl *seat_impl; - float x, y; - - device_native = META_INPUT_DEVICE_NATIVE (input_device); - seat_impl = seat_impl_from_device (input_device); - x = device_native->pointer_x + dx; - y = device_native->pointer_y + dy; - - meta_seat_impl_filter_relative_motion (seat_impl, - input_device, - seat_impl->pointer_x, - seat_impl->pointer_y, - &dx, - &dy); - - event = new_absolute_motion_event (seat_impl, input_device, time_us, - x, y, axes); - - event->motion.flags |= CLUTTER_EVENT_FLAG_RELATIVE_MOTION; - event->motion.dx = dx; - event->motion.dy = dy; - - queue_event (seat_impl, event); -} - -static void -notify_pinch_gesture_event (ClutterInputDevice *input_device, - ClutterTouchpadGesturePhase phase, - uint64_t time_us, - double dx, - double dy, - double dx_unaccel, - double dy_unaccel, - double angle_delta, - double scale, - uint32_t n_fingers) -{ - MetaSeatImpl *seat_impl; - ClutterEvent *event = NULL; - - seat_impl = seat_impl_from_device (input_device); - - event = clutter_event_new (CLUTTER_TOUCHPAD_PINCH); - - meta_input_device_native_get_coords_in_impl (META_INPUT_DEVICE_NATIVE (seat_impl->core_pointer), - &event->touchpad_pinch.x, - &event->touchpad_pinch.y); - - event->touchpad_pinch.phase = phase; - event->touchpad_pinch.time = us2ms (time_us); - event->touchpad_pinch.dx = dx; - event->touchpad_pinch.dy = dy; - event->touchpad_pinch.dx_unaccel = dx_unaccel; - event->touchpad_pinch.dy_unaccel = dy_unaccel; - event->touchpad_pinch.angle_delta = angle_delta; - event->touchpad_pinch.scale = scale; - event->touchpad_pinch.n_fingers = n_fingers; - - meta_xkb_translate_state (event, seat_impl->xkb, seat_impl->button_state); - - clutter_event_set_device (event, seat_impl->core_pointer); - clutter_event_set_source_device (event, input_device); - - queue_event (seat_impl, event); -} - -static void -notify_swipe_gesture_event (ClutterInputDevice *input_device, - ClutterTouchpadGesturePhase phase, - uint64_t time_us, - uint32_t n_fingers, - double dx, - double dy, - double dx_unaccel, - double dy_unaccel) -{ - MetaSeatImpl *seat_impl; - ClutterEvent *event = NULL; - - seat_impl = seat_impl_from_device (input_device); - - event = clutter_event_new (CLUTTER_TOUCHPAD_SWIPE); - - event->touchpad_swipe.phase = phase; - event->touchpad_swipe.time = us2ms (time_us); - - meta_input_device_native_get_coords_in_impl (META_INPUT_DEVICE_NATIVE (seat_impl->core_pointer), - &event->touchpad_swipe.x, - &event->touchpad_swipe.y); - event->touchpad_swipe.dx = dx; - event->touchpad_swipe.dy = dy; - event->touchpad_swipe.dx_unaccel = dx_unaccel; - event->touchpad_swipe.dy_unaccel = dy_unaccel; - event->touchpad_swipe.n_fingers = n_fingers; - - meta_xkb_translate_state (event, seat_impl->xkb, seat_impl->button_state); - - clutter_event_set_device (event, seat_impl->core_pointer); - clutter_event_set_source_device (event, input_device); - - queue_event (seat_impl, event); -} - -static void -notify_proximity (ClutterInputDevice *input_device, - uint64_t time_us, - gboolean in) -{ - MetaInputDeviceNative *device_native; - MetaSeatImpl *seat_impl; - ClutterEvent *event = NULL; - - device_native = META_INPUT_DEVICE_NATIVE (input_device); - seat_impl = seat_impl_from_device (input_device); - - if (in) - event = clutter_event_new (CLUTTER_PROXIMITY_IN); - else - event = clutter_event_new (CLUTTER_PROXIMITY_OUT); - - event->proximity.time = us2ms (time_us); - clutter_event_set_device_tool (event, device_native->last_tool); - clutter_event_set_device (event, seat_impl->core_pointer); - clutter_event_set_source_device (event, input_device); - - queue_event (seat_impl, event); -} - -static void -notify_pad_button (ClutterInputDevice *input_device, - uint64_t time_us, - uint32_t button, - uint32_t mode_group, - uint32_t mode, - uint32_t pressed) -{ - MetaSeatImpl *seat_impl; - ClutterEvent *event; - - seat_impl = seat_impl_from_device (input_device); - - if (pressed) - event = clutter_event_new (CLUTTER_PAD_BUTTON_PRESS); - else - event = clutter_event_new (CLUTTER_PAD_BUTTON_RELEASE); - - event->pad_button.button = button; - event->pad_button.group = mode_group; - event->pad_button.mode = mode; - clutter_event_set_device (event, input_device); - clutter_event_set_source_device (event, input_device); - clutter_event_set_time (event, us2ms (time_us)); - - queue_event (seat_impl, event); -} - -static void -notify_pad_strip (ClutterInputDevice *input_device, - uint64_t time_us, - uint32_t strip_number, - uint32_t strip_source, - uint32_t mode_group, - uint32_t mode, - double value) -{ - ClutterInputDevicePadSource source; - MetaSeatImpl *seat_impl; - ClutterEvent *event; - - seat_impl = seat_impl_from_device (input_device); - - if (strip_source == LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER) - source = CLUTTER_INPUT_DEVICE_PAD_SOURCE_FINGER; - else - source = CLUTTER_INPUT_DEVICE_PAD_SOURCE_UNKNOWN; - - event = clutter_event_new (CLUTTER_PAD_STRIP); - event->pad_strip.strip_source = source; - event->pad_strip.strip_number = strip_number; - event->pad_strip.value = value; - event->pad_strip.group = mode_group; - event->pad_strip.mode = mode; - clutter_event_set_device (event, input_device); - clutter_event_set_source_device (event, input_device); - clutter_event_set_time (event, us2ms (time_us)); - - queue_event (seat_impl, event); -} - -static void -notify_pad_ring (ClutterInputDevice *input_device, - uint64_t time_us, - uint32_t ring_number, - uint32_t ring_source, - uint32_t mode_group, - uint32_t mode, - double angle) -{ - ClutterInputDevicePadSource source; - MetaSeatImpl *seat_impl; - ClutterEvent *event; - - seat_impl = seat_impl_from_device (input_device); - - if (ring_source == LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER) - source = CLUTTER_INPUT_DEVICE_PAD_SOURCE_FINGER; - else - source = CLUTTER_INPUT_DEVICE_PAD_SOURCE_UNKNOWN; - - event = clutter_event_new (CLUTTER_PAD_RING); - event->pad_ring.ring_source = source; - event->pad_ring.ring_number = ring_number; - event->pad_ring.angle = angle; - event->pad_ring.group = mode_group; - event->pad_ring.mode = mode; - clutter_event_set_device (event, input_device); - clutter_event_set_source_device (event, input_device); - clutter_event_set_time (event, us2ms (time_us)); - - queue_event (seat_impl, event); -} - -static gboolean -meta_event_dispatch (GSource *g_source, - GSourceFunc callback, - gpointer user_data) -{ - MetaEventSource *source = (MetaEventSource *) g_source; - MetaSeatImpl *seat_impl; - - seat_impl = source->seat_impl; - - dispatch_libinput (seat_impl); - - return TRUE; -} - -static GSourceFuncs event_funcs = { - meta_event_prepare, - meta_event_check, - meta_event_dispatch, - NULL -}; - -static MetaEventSource * -meta_event_source_new (MetaSeatImpl *seat_impl) -{ - GSource *source; - MetaEventSource *event_source; - int fd; - - source = g_source_new (&event_funcs, sizeof (MetaEventSource)); - event_source = (MetaEventSource *) source; - - /* setup the source */ - event_source->seat_impl = seat_impl; - - fd = libinput_get_fd (seat_impl->libinput); - event_source->event_poll_fd.fd = fd; - event_source->event_poll_fd.events = G_IO_IN; - - /* and finally configure and attach the GSource */ - g_source_set_priority (source, CLUTTER_PRIORITY_EVENTS); - g_source_add_poll (source, &event_source->event_poll_fd); - g_source_set_can_recurse (source, TRUE); - g_source_attach (source, seat_impl->input_context); - - return event_source; -} - -static void -meta_event_source_free (MetaEventSource *source) -{ - GSource *g_source = (GSource *) source; - - /* ignore the return value of close, it's not like we can do something - * about it */ - close (source->event_poll_fd.fd); - - g_source_destroy (g_source); - g_source_unref (g_source); -} - -static gboolean -has_touchscreen (MetaSeatImpl *seat_impl) -{ - GSList *l; - - for (l = seat_impl->devices; l; l = l->next) - { - ClutterInputDeviceType device_type; - - device_type = clutter_input_device_get_device_type (l->data); - - if (device_type == CLUTTER_TOUCHSCREEN_DEVICE) - return TRUE; - } - - return FALSE; -} - -static inline gboolean -device_type_is_pointer (ClutterInputDeviceType device_type) -{ - return device_type == CLUTTER_POINTER_DEVICE || - device_type == CLUTTER_TOUCHPAD_DEVICE; -} - -static gboolean -has_pointer (MetaSeatImpl *seat_impl) -{ - GSList *l; - - for (l = seat_impl->devices; l; l = l->next) - { - ClutterInputDeviceType device_type; - - device_type = clutter_input_device_get_device_type (l->data); - if (device_type_is_pointer (device_type)) - return TRUE; - } - - return FALSE; -} - -static gboolean -device_is_tablet_switch (MetaInputDeviceNative *device_native) -{ - if (libinput_device_has_capability (device_native->libinput_device, - LIBINPUT_DEVICE_CAP_SWITCH) && - libinput_device_switch_has_switch (device_native->libinput_device, - LIBINPUT_SWITCH_TABLET_MODE)) - return TRUE; - - return FALSE; -} - -static gboolean -has_tablet_switch (MetaSeatImpl *seat_impl) -{ - GSList *l; - - for (l = seat_impl->devices; l; l = l->next) - { - MetaInputDeviceNative *device_native = META_INPUT_DEVICE_NATIVE (l->data); - - if (device_is_tablet_switch (device_native)) - return TRUE; - } - - return FALSE; -} - -static void -update_touch_mode (MetaSeatImpl *seat_impl) -{ - gboolean touch_mode; - - /* No touch mode if we don't have a touchscreen, easy */ - if (!seat_impl->has_touchscreen) - touch_mode = FALSE; - /* If we have a tablet mode switch, honor it being unset */ - else if (seat_impl->has_tablet_switch && !seat_impl->tablet_mode_switch_state) - touch_mode = FALSE; - /* If tablet mode is enabled, go for it */ - else if (seat_impl->has_tablet_switch && seat_impl->tablet_mode_switch_state) - touch_mode = TRUE; - /* If there is no tablet mode switch (eg. kiosk machines), - * assume touch-mode is mutually exclusive with pointers. - */ - else - touch_mode = !seat_impl->has_pointer; - - if (seat_impl->touch_mode != touch_mode) - { - GValue value = G_VALUE_INIT; - - g_value_init (&value, G_TYPE_BOOLEAN); - g_value_set_boolean (&value, touch_mode); - seat_impl->touch_mode = touch_mode; - emit_signal (seat_impl, signals[TOUCH_MODE], &value, 1); - g_value_unset (&value); - } -} - -static ClutterInputDevice * -evdev_add_device (MetaSeatImpl *seat_impl, - struct libinput_device *libinput_device) -{ - ClutterInputDeviceType type; - ClutterInputDevice *device; - gboolean is_touchscreen, is_tablet_switch, is_pointer; - - device = meta_input_device_native_new_in_impl (seat_impl, libinput_device); - - seat_impl->devices = g_slist_prepend (seat_impl->devices, device); - meta_seat_impl_sync_leds_in_impl (seat_impl); - - /* Clutter assumes that device types are exclusive in the - * ClutterInputDevice API */ - type = meta_input_device_native_determine_type_in_impl (libinput_device); - - is_touchscreen = type == CLUTTER_TOUCHSCREEN_DEVICE; - is_tablet_switch = - device_is_tablet_switch (META_INPUT_DEVICE_NATIVE (device)); - is_pointer = device_type_is_pointer (type); - - seat_impl->has_touchscreen |= is_touchscreen; - seat_impl->has_tablet_switch |= is_tablet_switch; - seat_impl->has_pointer |= is_pointer; - - if (is_touchscreen || is_tablet_switch || is_pointer) - update_touch_mode (seat_impl); - - return device; -} - -static void -evdev_remove_device (MetaSeatImpl *seat_impl, - MetaInputDeviceNative *device_native) -{ - ClutterInputDevice *device; - ClutterInputDeviceType device_type; - gboolean is_touchscreen, is_tablet_switch, is_pointer; - - device = CLUTTER_INPUT_DEVICE (device_native); - seat_impl->devices = g_slist_remove (seat_impl->devices, device); - - device_type = clutter_input_device_get_device_type (device); - - is_touchscreen = device_type == CLUTTER_TOUCHSCREEN_DEVICE; - is_tablet_switch = device_is_tablet_switch (device_native); - is_pointer = device_type_is_pointer (device_type); - - if (is_touchscreen) - seat_impl->has_touchscreen = has_touchscreen (seat_impl); - if (is_tablet_switch) - seat_impl->has_tablet_switch = has_tablet_switch (seat_impl); - if (is_pointer) - seat_impl->has_pointer = has_pointer (seat_impl); - - if (is_touchscreen || is_tablet_switch || is_pointer) - update_touch_mode (seat_impl); - - if (seat_impl->repeat_source && seat_impl->repeat_device == device) - meta_seat_impl_clear_repeat_source (seat_impl); - - meta_input_device_native_detach_libinput_in_impl (device_native); - - g_object_unref (device); -} - -static gboolean -process_base_event (MetaSeatImpl *seat_impl, - struct libinput_event *event) -{ - ClutterInputDevice *device; - ClutterEvent *device_event = NULL; - struct libinput_device *libinput_device; - MetaInputSettings *input_settings; - - input_settings = seat_impl->input_settings; - - switch (libinput_event_get_type (event)) - { - case LIBINPUT_EVENT_DEVICE_ADDED: - libinput_device = libinput_event_get_device (event); - - device = evdev_add_device (seat_impl, libinput_device); - device_event = clutter_event_new (CLUTTER_DEVICE_ADDED); - clutter_event_set_device (device_event, device); - meta_input_settings_add_device (input_settings, device); - break; - - case LIBINPUT_EVENT_DEVICE_REMOVED: - libinput_device = libinput_event_get_device (event); - - device = libinput_device_get_user_data (libinput_device); - device_event = clutter_event_new (CLUTTER_DEVICE_REMOVED); - clutter_event_set_device (device_event, device); - meta_input_settings_remove_device (input_settings, device); - evdev_remove_device (seat_impl, - META_INPUT_DEVICE_NATIVE (device)); - break; - - default: - break; - } - - if (device_event) - { - queue_event (seat_impl, device_event); - return TRUE; - } - - return FALSE; -} - -static ClutterScrollSource -translate_scroll_source (enum libinput_pointer_axis_source source) -{ - switch (source) - { - case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL: - return CLUTTER_SCROLL_SOURCE_WHEEL; - case LIBINPUT_POINTER_AXIS_SOURCE_FINGER: - return CLUTTER_SCROLL_SOURCE_FINGER; - case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS: - return CLUTTER_SCROLL_SOURCE_CONTINUOUS; - default: - return CLUTTER_SCROLL_SOURCE_UNKNOWN; - } -} - -static ClutterInputDeviceToolType -translate_tool_type (struct libinput_tablet_tool *libinput_tool) -{ - enum libinput_tablet_tool_type tool; - - tool = libinput_tablet_tool_get_type (libinput_tool); - - switch (tool) - { - case LIBINPUT_TABLET_TOOL_TYPE_PEN: - return CLUTTER_INPUT_DEVICE_TOOL_PEN; - case LIBINPUT_TABLET_TOOL_TYPE_ERASER: - return CLUTTER_INPUT_DEVICE_TOOL_ERASER; - case LIBINPUT_TABLET_TOOL_TYPE_BRUSH: - return CLUTTER_INPUT_DEVICE_TOOL_BRUSH; - case LIBINPUT_TABLET_TOOL_TYPE_PENCIL: - return CLUTTER_INPUT_DEVICE_TOOL_PENCIL; - case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH: - return CLUTTER_INPUT_DEVICE_TOOL_AIRBRUSH; - case LIBINPUT_TABLET_TOOL_TYPE_MOUSE: - return CLUTTER_INPUT_DEVICE_TOOL_MOUSE; - case LIBINPUT_TABLET_TOOL_TYPE_LENS: - return CLUTTER_INPUT_DEVICE_TOOL_LENS; - default: - return CLUTTER_INPUT_DEVICE_TOOL_NONE; - } -} - -static void -input_device_update_tool (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - struct libinput_tablet_tool *libinput_tool) -{ - MetaInputDeviceNative *evdev_device = META_INPUT_DEVICE_NATIVE (input_device); - ClutterInputDeviceTool *tool = NULL; - MetaInputSettings *input_settings; - - if (libinput_tool) - { - if (!seat_impl->tools) - { - seat_impl->tools = - g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) g_object_unref); - } - - tool = g_hash_table_lookup (seat_impl->tools, libinput_tool); - - if (!tool) - { - ClutterInputDeviceToolType tool_type; - uint64_t tool_serial; - - tool_serial = libinput_tablet_tool_get_serial (libinput_tool); - tool_type = translate_tool_type (libinput_tool); - tool = meta_input_device_tool_native_new (libinput_tool, - tool_serial, tool_type); - g_hash_table_insert (seat_impl->tools, libinput_tool, tool); - } - } - - if (evdev_device->last_tool != tool) - { - evdev_device->last_tool = tool; - input_settings = seat_impl->input_settings; - meta_input_settings_notify_tool_change (input_settings, input_device, tool); - } -} - -static double * -translate_tablet_axes (struct libinput_event_tablet_tool *tablet_event, - ClutterInputDeviceTool *tool) -{ - double *axes = g_new0 (double, CLUTTER_INPUT_AXIS_LAST); - struct libinput_tablet_tool *libinput_tool; - double value; - - libinput_tool = libinput_event_tablet_tool_get_tool (tablet_event); - - value = libinput_event_tablet_tool_get_x (tablet_event); - axes[CLUTTER_INPUT_AXIS_X] = value; - value = libinput_event_tablet_tool_get_y (tablet_event); - axes[CLUTTER_INPUT_AXIS_Y] = value; - - if (libinput_tablet_tool_has_distance (libinput_tool)) - { - value = libinput_event_tablet_tool_get_distance (tablet_event); - axes[CLUTTER_INPUT_AXIS_DISTANCE] = value; - } - - if (libinput_tablet_tool_has_pressure (libinput_tool)) - { - value = libinput_event_tablet_tool_get_pressure (tablet_event); - value = meta_input_device_tool_native_translate_pressure_in_impl (tool, value); - axes[CLUTTER_INPUT_AXIS_PRESSURE] = value; - } - - if (libinput_tablet_tool_has_tilt (libinput_tool)) - { - value = libinput_event_tablet_tool_get_tilt_x (tablet_event); - axes[CLUTTER_INPUT_AXIS_XTILT] = value; - value = libinput_event_tablet_tool_get_tilt_y (tablet_event); - axes[CLUTTER_INPUT_AXIS_YTILT] = value; - } - - if (libinput_tablet_tool_has_rotation (libinput_tool)) - { - value = libinput_event_tablet_tool_get_rotation (tablet_event); - axes[CLUTTER_INPUT_AXIS_ROTATION] = value; - } - - if (libinput_tablet_tool_has_slider (libinput_tool)) - { - value = libinput_event_tablet_tool_get_slider_position (tablet_event); - axes[CLUTTER_INPUT_AXIS_SLIDER] = value; - } - - if (libinput_tablet_tool_has_wheel (libinput_tool)) - { - value = libinput_event_tablet_tool_get_wheel_delta (tablet_event); - axes[CLUTTER_INPUT_AXIS_WHEEL] = value; - } - - return axes; -} - -static void -notify_continuous_axis (MetaSeatImpl *seat_impl, - ClutterInputDevice *device, - uint64_t time_us, - ClutterScrollSource scroll_source, - struct libinput_event_pointer *axis_event) -{ - double dx = 0.0, dy = 0.0; - ClutterScrollFinishFlags finish_flags = CLUTTER_SCROLL_FINISHED_NONE; - - if (libinput_event_pointer_has_axis (axis_event, - LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) - { - dx = libinput_event_pointer_get_axis_value ( - axis_event, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); - - if (fabs (dx) < DBL_EPSILON) - finish_flags |= CLUTTER_SCROLL_FINISHED_HORIZONTAL; - } - if (libinput_event_pointer_has_axis (axis_event, - LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) - { - dy = libinput_event_pointer_get_axis_value ( - axis_event, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); - - if (fabs (dy) < DBL_EPSILON) - finish_flags |= CLUTTER_SCROLL_FINISHED_VERTICAL; - } - - meta_seat_impl_notify_scroll_continuous_in_impl (seat_impl, device, time_us, - dx, dy, - scroll_source, finish_flags); -} - -static void -notify_discrete_axis (MetaSeatImpl *seat_impl, - ClutterInputDevice *device, - uint64_t time_us, - ClutterScrollSource scroll_source, - struct libinput_event_pointer *axis_event) -{ - double discrete_dx = 0.0, discrete_dy = 0.0; - - if (libinput_event_pointer_has_axis (axis_event, - LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) - { - discrete_dx = libinput_event_pointer_get_axis_value_discrete ( - axis_event, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); - } - if (libinput_event_pointer_has_axis (axis_event, - LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) - { - discrete_dy = libinput_event_pointer_get_axis_value_discrete ( - axis_event, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); - } - - meta_seat_impl_notify_discrete_scroll_in_impl (seat_impl, device, - time_us, - discrete_dx, discrete_dy, - scroll_source); -} - -static void -process_tablet_axis (MetaSeatImpl *seat_impl, - struct libinput_event *event) -{ - struct libinput_device *libinput_device = libinput_event_get_device (event); - uint64_t time; - double x, y, dx, dy, *axes; - float stage_width, stage_height; - ClutterInputDevice *device; - struct libinput_event_tablet_tool *tablet_event = - libinput_event_get_tablet_tool_event (event); - MetaInputDeviceNative *evdev_device; - - device = libinput_device_get_user_data (libinput_device); - evdev_device = META_INPUT_DEVICE_NATIVE (device); - - axes = translate_tablet_axes (tablet_event, - evdev_device->last_tool); - - meta_viewport_info_get_extents (seat_impl->viewports, - &stage_width, &stage_height); - - time = libinput_event_tablet_tool_get_time_usec (tablet_event); - - if (meta_input_device_native_get_mapping_mode_in_impl (device) == META_INPUT_DEVICE_MAPPING_RELATIVE || - clutter_input_device_tool_get_tool_type (evdev_device->last_tool) == CLUTTER_INPUT_DEVICE_TOOL_MOUSE || - clutter_input_device_tool_get_tool_type (evdev_device->last_tool) == CLUTTER_INPUT_DEVICE_TOOL_LENS) - { - dx = libinput_event_tablet_tool_get_dx (tablet_event); - dy = libinput_event_tablet_tool_get_dy (tablet_event); - notify_relative_tool_motion_in_impl (device, time, dx, dy, axes); - } - else - { - x = libinput_event_tablet_tool_get_x_transformed (tablet_event, stage_width); - y = libinput_event_tablet_tool_get_y_transformed (tablet_event, stage_height); - notify_absolute_motion_in_impl (device, time, x, y, axes); - } -} - -static gboolean -process_device_event (MetaSeatImpl *seat_impl, - struct libinput_event *event) -{ - gboolean handled = TRUE; - struct libinput_device *libinput_device = libinput_event_get_device(event); - ClutterInputDevice *device; - MetaInputDeviceNative *device_native; - - switch (libinput_event_get_type (event)) - { - case LIBINPUT_EVENT_KEYBOARD_KEY: - { - uint32_t key, key_state, seat_key_count; - uint64_t time_us; - struct libinput_event_keyboard *key_event = - libinput_event_get_keyboard_event (event); - - device = libinput_device_get_user_data (libinput_device); - time_us = libinput_event_keyboard_get_time_usec (key_event); - key = libinput_event_keyboard_get_key (key_event); - key_state = libinput_event_keyboard_get_key_state (key_event) == - LIBINPUT_KEY_STATE_PRESSED; - seat_key_count = - libinput_event_keyboard_get_seat_key_count (key_event); - - /* Ignore key events that are not seat wide state changes. */ - if ((key_state == LIBINPUT_KEY_STATE_PRESSED && - seat_key_count != 1) || - (key_state == LIBINPUT_KEY_STATE_RELEASED && - seat_key_count != 0)) - { - meta_topic (META_DEBUG_INPUT, - "Dropping key-%s of key 0x%x because seat-wide " - "key count is %d", - key_state == LIBINPUT_KEY_STATE_PRESSED ? "press" : "release", - key, seat_key_count); - break; - } - - meta_seat_impl_notify_key_in_impl (seat_impl, - device, - time_us, key, key_state, TRUE); - - break; - } - - case LIBINPUT_EVENT_POINTER_MOTION: - { - struct libinput_event_pointer *pointer_event = - libinput_event_get_pointer_event (event); - uint64_t time_us; - double dx; - double dy; - double dx_unaccel; - double dy_unaccel; - - device = libinput_device_get_user_data (libinput_device); - time_us = libinput_event_pointer_get_time_usec (pointer_event); - dx = libinput_event_pointer_get_dx (pointer_event); - dy = libinput_event_pointer_get_dy (pointer_event); - dx_unaccel = libinput_event_pointer_get_dx_unaccelerated (pointer_event); - dy_unaccel = libinput_event_pointer_get_dy_unaccelerated (pointer_event); - - meta_seat_impl_notify_relative_motion_in_impl (seat_impl, - device, - time_us, - dx, dy, - dx_unaccel, dy_unaccel); - - break; - } - - case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: - { - uint64_t time_us; - double x, y; - float stage_width, stage_height; - struct libinput_event_pointer *motion_event = - libinput_event_get_pointer_event (event); - device = libinput_device_get_user_data (libinput_device); - - meta_viewport_info_get_extents (seat_impl->viewports, - &stage_width, &stage_height); - - time_us = libinput_event_pointer_get_time_usec (motion_event); - x = libinput_event_pointer_get_absolute_x_transformed (motion_event, - stage_width); - y = libinput_event_pointer_get_absolute_y_transformed (motion_event, - stage_height); - - meta_seat_impl_notify_absolute_motion_in_impl (seat_impl, - device, - time_us, - x, y, - NULL); - - break; - } - - case LIBINPUT_EVENT_POINTER_BUTTON: - { - uint32_t button, button_state, seat_button_count; - uint64_t time_us; - struct libinput_event_pointer *button_event = - libinput_event_get_pointer_event (event); - device = libinput_device_get_user_data (libinput_device); - - time_us = libinput_event_pointer_get_time_usec (button_event); - button = libinput_event_pointer_get_button (button_event); - button_state = libinput_event_pointer_get_button_state (button_event) == - LIBINPUT_BUTTON_STATE_PRESSED; - seat_button_count = - libinput_event_pointer_get_seat_button_count (button_event); - - /* Ignore button events that are not seat wide state changes. */ - if ((button_state == LIBINPUT_BUTTON_STATE_PRESSED && - seat_button_count != 1) || - (button_state == LIBINPUT_BUTTON_STATE_RELEASED && - seat_button_count != 0)) - { - meta_topic (META_DEBUG_INPUT, - "Dropping button-%s of button 0x%x because seat-wide " - "button count is %d", - button_state == LIBINPUT_BUTTON_STATE_PRESSED ? "press" : "release", - button, seat_button_count); - break; - } - - meta_seat_impl_notify_button_in_impl (seat_impl, device, - time_us, button, button_state); - break; - } - - case LIBINPUT_EVENT_POINTER_AXIS: - { - uint64_t time_us; - enum libinput_pointer_axis_source source; - struct libinput_event_pointer *axis_event = - libinput_event_get_pointer_event (event); - ClutterScrollSource scroll_source; - - device = libinput_device_get_user_data (libinput_device); - - time_us = libinput_event_pointer_get_time_usec (axis_event); - source = libinput_event_pointer_get_axis_source (axis_event); - scroll_source = translate_scroll_source (source); - - /* libinput < 0.8 sent wheel click events with value 10. Since 0.8 - the value is the angle of the click in degrees. To keep - backwards-compat with existing clients, we just send multiples of - the click count. */ - - switch (scroll_source) - { - case CLUTTER_SCROLL_SOURCE_WHEEL: - notify_discrete_axis (seat_impl, device, time_us, scroll_source, - axis_event); - break; - case CLUTTER_SCROLL_SOURCE_FINGER: - case CLUTTER_SCROLL_SOURCE_CONTINUOUS: - case CLUTTER_SCROLL_SOURCE_UNKNOWN: - notify_continuous_axis (seat_impl, device, time_us, scroll_source, - axis_event); - break; - } - break; - } - - case LIBINPUT_EVENT_TOUCH_DOWN: - { - int seat_slot; - uint64_t time_us; - double x, y; - float stage_width, stage_height; - MetaTouchState *touch_state; - struct libinput_event_touch *touch_event = - libinput_event_get_touch_event (event); - - device = libinput_device_get_user_data (libinput_device); - device_native = META_INPUT_DEVICE_NATIVE (device); - - meta_viewport_info_get_extents (seat_impl->viewports, - &stage_width, &stage_height); - - seat_slot = libinput_event_touch_get_seat_slot (touch_event); - time_us = libinput_event_touch_get_time_usec (touch_event); - x = libinput_event_touch_get_x_transformed (touch_event, - stage_width); - y = libinput_event_touch_get_y_transformed (touch_event, - stage_height); - - g_rw_lock_writer_lock (&seat_impl->state_lock); - - touch_state = meta_seat_impl_acquire_touch_state_in_impl (seat_impl, seat_slot); - touch_state->coords.x = x; - touch_state->coords.y = y; - - g_rw_lock_writer_unlock (&seat_impl->state_lock); - - meta_seat_impl_notify_touch_event_in_impl (seat_impl, device, - CLUTTER_TOUCH_BEGIN, - time_us, - touch_state->seat_slot, - touch_state->coords.x, - touch_state->coords.y); - break; - } - - case LIBINPUT_EVENT_TOUCH_UP: - { - int seat_slot; - uint64_t time_us; - MetaTouchState *touch_state; - struct libinput_event_touch *touch_event = - libinput_event_get_touch_event (event); - - device = libinput_device_get_user_data (libinput_device); - device_native = META_INPUT_DEVICE_NATIVE (device); - - seat_slot = libinput_event_touch_get_seat_slot (touch_event); - time_us = libinput_event_touch_get_time_usec (touch_event); - touch_state = meta_seat_impl_lookup_touch_state_in_impl (seat_impl, seat_slot); - if (!touch_state) - break; - - meta_seat_impl_notify_touch_event_in_impl (seat_impl, device, - CLUTTER_TOUCH_END, time_us, - touch_state->seat_slot, - touch_state->coords.x, - touch_state->coords.y); - - g_rw_lock_writer_lock (&seat_impl->state_lock); - meta_seat_impl_release_touch_state_in_impl (seat_impl, seat_slot); - g_rw_lock_writer_unlock (&seat_impl->state_lock); - break; - } - - case LIBINPUT_EVENT_TOUCH_MOTION: - { - int seat_slot; - uint64_t time_us; - double x, y; - float stage_width, stage_height; - MetaTouchState *touch_state; - struct libinput_event_touch *touch_event = - libinput_event_get_touch_event (event); - - device = libinput_device_get_user_data (libinput_device); - device_native = META_INPUT_DEVICE_NATIVE (device); - - meta_viewport_info_get_extents (seat_impl->viewports, - &stage_width, &stage_height); - - seat_slot = libinput_event_touch_get_seat_slot (touch_event); - time_us = libinput_event_touch_get_time_usec (touch_event); - x = libinput_event_touch_get_x_transformed (touch_event, - stage_width); - y = libinput_event_touch_get_y_transformed (touch_event, - stage_height); - - g_rw_lock_writer_lock (&seat_impl->state_lock); - touch_state = meta_seat_impl_lookup_touch_state_in_impl (seat_impl, seat_slot); - if (touch_state) - { - touch_state->coords.x = x; - touch_state->coords.y = y; - } - g_rw_lock_writer_unlock (&seat_impl->state_lock); - - if (!touch_state) - break; - - meta_seat_impl_notify_touch_event_in_impl (seat_impl, device, - CLUTTER_TOUCH_UPDATE, - time_us, - touch_state->seat_slot, - touch_state->coords.x, - touch_state->coords.y); - break; - } - case LIBINPUT_EVENT_TOUCH_CANCEL: - { - int seat_slot; - MetaTouchState *touch_state; - uint64_t time_us; - struct libinput_event_touch *touch_event = - libinput_event_get_touch_event (event); - - device = libinput_device_get_user_data (libinput_device); - device_native = META_INPUT_DEVICE_NATIVE (device); - time_us = libinput_event_touch_get_time_usec (touch_event); - - seat_slot = libinput_event_touch_get_seat_slot (touch_event); - touch_state = meta_seat_impl_lookup_touch_state_in_impl (seat_impl, seat_slot); - if (!touch_state) - break; - - meta_seat_impl_notify_touch_event_in_impl (touch_state->seat_impl, - CLUTTER_INPUT_DEVICE (device_native), - CLUTTER_TOUCH_CANCEL, - time_us, - touch_state->seat_slot, - touch_state->coords.x, - touch_state->coords.y); - - meta_seat_impl_release_touch_state_in_impl (seat_impl, seat_slot); - break; - } - case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN: - case LIBINPUT_EVENT_GESTURE_PINCH_END: - { - struct libinput_event_gesture *gesture_event = - libinput_event_get_gesture_event (event); - ClutterTouchpadGesturePhase phase; - uint32_t n_fingers; - uint64_t time_us; - - if (libinput_event_get_type (event) == LIBINPUT_EVENT_GESTURE_PINCH_BEGIN) - phase = CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN; - else - phase = libinput_event_gesture_get_cancelled (gesture_event) ? - CLUTTER_TOUCHPAD_GESTURE_PHASE_CANCEL : CLUTTER_TOUCHPAD_GESTURE_PHASE_END; - - n_fingers = libinput_event_gesture_get_finger_count (gesture_event); - device = libinput_device_get_user_data (libinput_device); - time_us = libinput_event_gesture_get_time_usec (gesture_event); - notify_pinch_gesture_event (device, phase, time_us, 0, 0, 0, 0, 0, 0, n_fingers); - break; - } - case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE: - { - struct libinput_event_gesture *gesture_event = - libinput_event_get_gesture_event (event); - double angle_delta, scale, dx, dy, dx_unaccel, dy_unaccel; - uint32_t n_fingers; - uint64_t time_us; - - n_fingers = libinput_event_gesture_get_finger_count (gesture_event); - device = libinput_device_get_user_data (libinput_device); - time_us = libinput_event_gesture_get_time_usec (gesture_event); - angle_delta = libinput_event_gesture_get_angle_delta (gesture_event); - scale = libinput_event_gesture_get_scale (gesture_event); - dx = libinput_event_gesture_get_dx (gesture_event); - dy = libinput_event_gesture_get_dy (gesture_event); - dx_unaccel = libinput_event_gesture_get_dx_unaccelerated (gesture_event); - dy_unaccel = libinput_event_gesture_get_dy_unaccelerated (gesture_event); - - notify_pinch_gesture_event (device, - CLUTTER_TOUCHPAD_GESTURE_PHASE_UPDATE, - time_us, dx, dy, dx_unaccel, dy_unaccel, - angle_delta, scale, n_fingers); - break; - } - case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN: - case LIBINPUT_EVENT_GESTURE_SWIPE_END: - { - struct libinput_event_gesture *gesture_event = - libinput_event_get_gesture_event (event); - ClutterTouchpadGesturePhase phase; - uint32_t n_fingers; - uint64_t time_us; - - device = libinput_device_get_user_data (libinput_device); - time_us = libinput_event_gesture_get_time_usec (gesture_event); - n_fingers = libinput_event_gesture_get_finger_count (gesture_event); - - if (libinput_event_get_type (event) == LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN) - phase = CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN; - else - phase = libinput_event_gesture_get_cancelled (gesture_event) ? - CLUTTER_TOUCHPAD_GESTURE_PHASE_CANCEL : CLUTTER_TOUCHPAD_GESTURE_PHASE_END; - - notify_swipe_gesture_event (device, phase, time_us, n_fingers, 0, 0, 0, 0); - break; - } - case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE: - { - struct libinput_event_gesture *gesture_event = - libinput_event_get_gesture_event (event); - uint32_t n_fingers; - uint64_t time_us; - double dx, dy, dx_unaccel, dy_unaccel; - - device = libinput_device_get_user_data (libinput_device); - time_us = libinput_event_gesture_get_time_usec (gesture_event); - n_fingers = libinput_event_gesture_get_finger_count (gesture_event); - dx = libinput_event_gesture_get_dx (gesture_event); - dy = libinput_event_gesture_get_dy (gesture_event); - dx_unaccel = libinput_event_gesture_get_dx_unaccelerated (gesture_event); - dy_unaccel = libinput_event_gesture_get_dy_unaccelerated (gesture_event); - - notify_swipe_gesture_event (device, - CLUTTER_TOUCHPAD_GESTURE_PHASE_UPDATE, - time_us, n_fingers, dx, dy, dx_unaccel, dy_unaccel); - break; - } - case LIBINPUT_EVENT_TABLET_TOOL_AXIS: - { - process_tablet_axis (seat_impl, event); - break; - } - case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY: - { - uint64_t time; - struct libinput_event_tablet_tool *tablet_event = - libinput_event_get_tablet_tool_event (event); - struct libinput_tablet_tool *libinput_tool = NULL; - enum libinput_tablet_tool_proximity_state state; - gboolean in; - - state = libinput_event_tablet_tool_get_proximity_state (tablet_event); - time = libinput_event_tablet_tool_get_time_usec (tablet_event); - device = libinput_device_get_user_data (libinput_device); - in = state == LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN; - - libinput_tool = libinput_event_tablet_tool_get_tool (tablet_event); - - if (in) - input_device_update_tool (seat_impl, device, libinput_tool); - notify_proximity (device, time, in); - if (!in) - input_device_update_tool (seat_impl, device, NULL); - - break; - } - case LIBINPUT_EVENT_TABLET_TOOL_BUTTON: - { - uint64_t time_us; - uint32_t button_state; - struct libinput_event_tablet_tool *tablet_event = - libinput_event_get_tablet_tool_event (event); - uint32_t tablet_button; - - process_tablet_axis (seat_impl, event); - - device = libinput_device_get_user_data (libinput_device); - time_us = libinput_event_tablet_tool_get_time_usec (tablet_event); - tablet_button = libinput_event_tablet_tool_get_button (tablet_event); - - button_state = libinput_event_tablet_tool_get_button_state (tablet_event) == - LIBINPUT_BUTTON_STATE_PRESSED; - - meta_seat_impl_notify_button_in_impl (seat_impl, device, - time_us, tablet_button, button_state); - break; - } - case LIBINPUT_EVENT_TABLET_TOOL_TIP: - { - uint64_t time_us; - uint32_t button_state; - struct libinput_event_tablet_tool *tablet_event = - libinput_event_get_tablet_tool_event (event); - - device = libinput_device_get_user_data (libinput_device); - time_us = libinput_event_tablet_tool_get_time_usec (tablet_event); - - button_state = libinput_event_tablet_tool_get_tip_state (tablet_event) == - LIBINPUT_TABLET_TOOL_TIP_DOWN; - - /* To avoid jumps on tip, notify axes before the tip down event - but after the tip up event */ - if (button_state) - process_tablet_axis (seat_impl, event); - - meta_seat_impl_notify_button_in_impl (seat_impl, device, - time_us, BTN_TOUCH, button_state); - if (!button_state) - process_tablet_axis (seat_impl, event); - break; - } - case LIBINPUT_EVENT_TABLET_PAD_BUTTON: - { - uint64_t time; - uint32_t button_state, button, group, mode; - struct libinput_tablet_pad_mode_group *mode_group; - struct libinput_event_tablet_pad *pad_event = - libinput_event_get_tablet_pad_event (event); - - device = libinput_device_get_user_data (libinput_device); - time = libinput_event_tablet_pad_get_time_usec (pad_event); - - mode_group = libinput_event_tablet_pad_get_mode_group (pad_event); - group = libinput_tablet_pad_mode_group_get_index (mode_group); - mode = libinput_event_tablet_pad_get_mode (pad_event); - - button = libinput_event_tablet_pad_get_button_number (pad_event); - button_state = libinput_event_tablet_pad_get_button_state (pad_event) == - LIBINPUT_BUTTON_STATE_PRESSED; - notify_pad_button (device, time, button, group, mode, button_state); - break; - } - case LIBINPUT_EVENT_TABLET_PAD_STRIP: - { - uint64_t time; - uint32_t number, source, group, mode; - struct libinput_tablet_pad_mode_group *mode_group; - struct libinput_event_tablet_pad *pad_event = - libinput_event_get_tablet_pad_event (event); - double value; - - device = libinput_device_get_user_data (libinput_device); - time = libinput_event_tablet_pad_get_time_usec (pad_event); - number = libinput_event_tablet_pad_get_strip_number (pad_event); - value = libinput_event_tablet_pad_get_strip_position (pad_event); - source = libinput_event_tablet_pad_get_strip_source (pad_event); - - mode_group = libinput_event_tablet_pad_get_mode_group (pad_event); - group = libinput_tablet_pad_mode_group_get_index (mode_group); - mode = libinput_event_tablet_pad_get_mode (pad_event); - - notify_pad_strip (device, time, number, source, group, mode, value); - break; - } - case LIBINPUT_EVENT_TABLET_PAD_RING: - { - uint64_t time; - uint32_t number, source, group, mode; - struct libinput_tablet_pad_mode_group *mode_group; - struct libinput_event_tablet_pad *pad_event = - libinput_event_get_tablet_pad_event (event); - double angle; - - device = libinput_device_get_user_data (libinput_device); - time = libinput_event_tablet_pad_get_time_usec (pad_event); - number = libinput_event_tablet_pad_get_ring_number (pad_event); - angle = libinput_event_tablet_pad_get_ring_position (pad_event); - source = libinput_event_tablet_pad_get_ring_source (pad_event); - - mode_group = libinput_event_tablet_pad_get_mode_group (pad_event); - group = libinput_tablet_pad_mode_group_get_index (mode_group); - mode = libinput_event_tablet_pad_get_mode (pad_event); - - notify_pad_ring (device, time, number, source, group, mode, angle); - break; - } - case LIBINPUT_EVENT_SWITCH_TOGGLE: - { - struct libinput_event_switch *switch_event = - libinput_event_get_switch_event (event); - enum libinput_switch sw = - libinput_event_switch_get_switch (switch_event); - enum libinput_switch_state state = - libinput_event_switch_get_switch_state (switch_event); - - if (sw == LIBINPUT_SWITCH_TABLET_MODE) - { - seat_impl->tablet_mode_switch_state = (state == LIBINPUT_SWITCH_STATE_ON); - update_touch_mode (seat_impl); - } - break; - } - default: - handled = FALSE; - } - - return handled; -} - -static void -process_event (MetaSeatImpl *seat_impl, - struct libinput_event *event) -{ - if (process_base_event (seat_impl, event)) - return; - if (process_device_event (seat_impl, event)) - return; -} - -static void -process_events (MetaSeatImpl *seat_impl) -{ - struct libinput_event *event; - - while ((event = libinput_get_event (seat_impl->libinput))) - { - process_event(seat_impl, event); - libinput_event_destroy(event); - } -} - -static int -open_restricted (const char *path, - int open_flags, - void *user_data) -{ - MetaSeatImpl *seat_impl = user_data; - MetaSeatImplPrivate *priv = meta_seat_impl_get_instance_private (seat_impl); - MetaBackend *backend = meta_seat_native_get_backend (seat_impl->seat_native); - MetaDevicePool *device_pool = - meta_backend_native_get_device_pool (META_BACKEND_NATIVE (backend)); - MetaDeviceFileFlags flags; - g_autoptr (GError) error = NULL; - MetaDeviceFile *device_file; - int fd; - - flags = META_DEVICE_FILE_FLAG_NONE; - if (!(open_flags & (O_RDWR | O_WRONLY))) - flags |= META_DEVICE_FILE_FLAG_READ_ONLY; - - if (!g_str_has_prefix (path, "/sys/")) - flags |= META_DEVICE_FILE_FLAG_TAKE_CONTROL; - - device_file = meta_device_pool_open (device_pool, path, flags, &error); - if (!device_file) - { - g_warning ("Could not open device %s: %s", path, error->message); - return -1; - } - - fd = meta_device_file_get_fd (device_file); - g_hash_table_insert (priv->device_files, GINT_TO_POINTER (fd), device_file); - - return fd; -} - -static void -close_restricted (int fd, - void *user_data) -{ - MetaSeatImpl *seat_impl = user_data; - MetaSeatImplPrivate *priv = meta_seat_impl_get_instance_private (seat_impl); - - g_hash_table_remove (priv->device_files, GINT_TO_POINTER (fd)); -} - -static const struct libinput_interface libinput_interface = { - open_restricted, - close_restricted -}; - -static void -kbd_a11y_changed_cb (MetaInputSettings *input_settings, - MetaKbdA11ySettings *a11y_settings, - MetaSeatImpl *seat_impl) -{ - MetaInputDeviceNative *keyboard; - - keyboard = META_INPUT_DEVICE_NATIVE (seat_impl->core_keyboard); - meta_input_device_native_apply_kbd_a11y_settings_in_impl (keyboard, a11y_settings); -} - -static void -meta_seat_impl_set_keyboard_numlock_in_impl (MetaSeatImpl *seat_impl, - gboolean numlock_state) -{ - xkb_mod_mask_t depressed_mods; - xkb_mod_mask_t latched_mods; - xkb_mod_mask_t locked_mods; - xkb_mod_mask_t group_mods; - xkb_mod_mask_t numlock; - struct xkb_keymap *xkb_keymap; - MetaKeymapNative *keymap; - - keymap = seat_impl->keymap; - xkb_keymap = meta_keymap_native_get_keyboard_map_in_impl (keymap); - - numlock = (1 << xkb_keymap_mod_get_index (xkb_keymap, "Mod2")); - - depressed_mods = - xkb_state_serialize_mods (seat_impl->xkb, XKB_STATE_MODS_DEPRESSED); - latched_mods = - xkb_state_serialize_mods (seat_impl->xkb, XKB_STATE_MODS_LATCHED); - locked_mods = - xkb_state_serialize_mods (seat_impl->xkb, XKB_STATE_MODS_LOCKED); - group_mods = - xkb_state_serialize_layout (seat_impl->xkb, XKB_STATE_LAYOUT_EFFECTIVE); - - if (numlock_state) - locked_mods |= numlock; - else - locked_mods &= ~numlock; - - xkb_state_update_mask (seat_impl->xkb, - depressed_mods, - latched_mods, - locked_mods, - 0, 0, - group_mods); - - meta_seat_impl_sync_leds_in_impl (seat_impl); - meta_keymap_native_update_in_impl (seat_impl->keymap, - seat_impl, - seat_impl->xkb); -} - -static gboolean -init_libinput (MetaSeatImpl *seat_impl, - GError **error) -{ - MetaEventSource *source; - struct udev *udev; - struct libinput *libinput; - - udev = udev_new (); - if (G_UNLIKELY (udev == NULL)) - { - g_warning ("Failed to create udev object"); - seat_impl->input_thread_initialized = TRUE; - return FALSE; - } - - libinput = libinput_udev_create_context (&libinput_interface, - seat_impl, udev); - udev_unref (udev); - - if (libinput == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to create the libinput object."); - return FALSE; - } - - if (libinput_udev_assign_seat (libinput, seat_impl->seat_id) == -1) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to assign a seat to the libinput object."); - libinput_unref (seat_impl->libinput); - return FALSE; - } - - seat_impl->libinput = libinput; - source = meta_event_source_new (seat_impl); - seat_impl->event_source = source; - - return TRUE; -} - -static gpointer -input_thread (MetaSeatImpl *seat_impl) -{ - MetaSeatImplPrivate *priv = meta_seat_impl_get_instance_private (seat_impl); - struct xkb_keymap *xkb_keymap; - - g_main_context_push_thread_default (seat_impl->input_context); - - priv->device_files = - g_hash_table_new_full (NULL, NULL, - NULL, - (GDestroyNotify) meta_device_file_release); - - if (!(seat_impl->flags & META_SEAT_NATIVE_FLAG_NO_LIBINPUT)) - { - g_autoptr (GError) error = NULL; - - if (!init_libinput (seat_impl, &error)) - { - g_critical ("Failed to initialize seat: %s", error->message); - seat_impl->input_thread_initialized = TRUE; - return NULL; - } - } - - seat_impl->input_settings = meta_input_settings_native_new_in_impl (seat_impl); - g_signal_connect_object (seat_impl->input_settings, "kbd-a11y-changed", - G_CALLBACK (kbd_a11y_changed_cb), seat_impl, 0); - - seat_impl->keymap = g_object_new (META_TYPE_KEYMAP_NATIVE, NULL); - - xkb_keymap = meta_keymap_native_get_keyboard_map_in_impl (seat_impl->keymap); - - if (xkb_keymap) - { - seat_impl->xkb = xkb_state_new (xkb_keymap); - - seat_impl->caps_lock_led = - xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_CAPS); - seat_impl->num_lock_led = - xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_NUM); - seat_impl->scroll_lock_led = - xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_SCROLL); - } - - if (meta_input_settings_maybe_restore_numlock_state (seat_impl->input_settings)) - meta_seat_impl_set_keyboard_numlock_in_impl (seat_impl, TRUE); - - seat_impl->has_touchscreen = has_touchscreen (seat_impl); - seat_impl->has_tablet_switch = has_tablet_switch (seat_impl); - update_touch_mode (seat_impl); - - g_mutex_lock (&seat_impl->init_mutex); - seat_impl->input_thread_initialized = TRUE; - g_cond_signal (&seat_impl->init_cond); - g_mutex_unlock (&seat_impl->init_mutex); - - seat_impl->input_loop = g_main_loop_new (seat_impl->input_context, FALSE); - g_main_loop_run (seat_impl->input_loop); - g_main_loop_unref (seat_impl->input_loop); - - g_main_context_pop_thread_default (seat_impl->input_context); - - return NULL; -} - -static gboolean -meta_seat_impl_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - MetaSeatImpl *seat_impl = META_SEAT_IMPL (initable); - - seat_impl->input_context = g_main_context_new (); - seat_impl->main_context = g_main_context_ref_thread_default (); - g_assert (seat_impl->main_context == g_main_context_default ()); - - seat_impl->input_thread = - g_thread_try_new ("Mutter Input Thread", - (GThreadFunc) input_thread, - initable, - error); - if (!seat_impl->input_thread) - return FALSE; - - /* Initialize thread synchronously */ - g_mutex_lock (&seat_impl->init_mutex); - while (!seat_impl->input_thread_initialized) - g_cond_wait (&seat_impl->init_cond, &seat_impl->init_mutex); - g_mutex_unlock (&seat_impl->init_mutex); - - return TRUE; -} - -static void -meta_seat_impl_constructed (GObject *object) -{ - MetaSeatImpl *seat_impl = META_SEAT_IMPL (object); - ClutterInputDevice *device; - - device = meta_input_device_native_new_virtual ( - seat_impl, CLUTTER_POINTER_DEVICE, - CLUTTER_INPUT_MODE_LOGICAL); - seat_impl->pointer_x = INITIAL_POINTER_X; - seat_impl->pointer_y = INITIAL_POINTER_Y; - meta_input_device_native_set_coords_in_impl (META_INPUT_DEVICE_NATIVE (device), - seat_impl->pointer_x, - seat_impl->pointer_y); - seat_impl->core_pointer = device; - - device = meta_input_device_native_new_virtual ( - seat_impl, CLUTTER_KEYBOARD_DEVICE, - CLUTTER_INPUT_MODE_LOGICAL); - seat_impl->core_keyboard = device; - - if (G_OBJECT_CLASS (meta_seat_impl_parent_class)->constructed) - G_OBJECT_CLASS (meta_seat_impl_parent_class)->constructed (object); -} - -static void -meta_seat_impl_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaSeatImpl *seat_impl = META_SEAT_IMPL (object); - - switch (prop_id) - { - case PROP_SEAT: - seat_impl->seat_native = g_value_get_object (value); - break; - case PROP_SEAT_ID: - seat_impl->seat_id = g_value_dup_string (value); - break; - case PROP_FLAGS: - seat_impl->flags = g_value_get_flags (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_seat_impl_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaSeatImpl *seat_impl = META_SEAT_IMPL (object); - - switch (prop_id) - { - case PROP_SEAT: - g_value_set_object (value, seat_impl->seat_native); - break; - case PROP_SEAT_ID: - g_value_set_string (value, seat_impl->seat_id); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static gboolean -destroy_in_impl (GTask *task) -{ - MetaSeatImpl *seat_impl = g_task_get_source_object (task); - MetaSeatImplPrivate *priv = meta_seat_impl_get_instance_private (seat_impl); - gboolean numlock_active; - - g_slist_foreach (seat_impl->devices, - (GFunc) meta_input_device_native_detach_libinput_in_impl, - NULL); - g_slist_free_full (seat_impl->devices, g_object_unref); - seat_impl->devices = NULL; - - g_clear_pointer (&seat_impl->libinput, libinput_unref); - g_clear_pointer (&seat_impl->tools, g_hash_table_unref); - g_clear_pointer (&seat_impl->touch_states, g_hash_table_destroy); - g_clear_pointer (&seat_impl->event_source, meta_event_source_free); - - numlock_active = - xkb_state_mod_name_is_active (seat_impl->xkb, XKB_MOD_NAME_NUM, - XKB_STATE_MODS_LATCHED | - XKB_STATE_MODS_LOCKED); - meta_input_settings_maybe_save_numlock_state (seat_impl->input_settings, - numlock_active); - - g_clear_pointer (&seat_impl->xkb, xkb_state_unref); - - meta_seat_impl_clear_repeat_source (seat_impl); - - g_clear_pointer (&priv->device_files, g_hash_table_destroy); - - g_main_loop_quit (seat_impl->input_loop); - g_task_return_boolean (task, TRUE); - - return G_SOURCE_REMOVE; -} - -void -meta_seat_impl_destroy (MetaSeatImpl *seat_impl) -{ - if (seat_impl->libinput) - { - GTask *task; - - task = g_task_new (seat_impl, NULL, NULL, NULL); - meta_seat_impl_run_input_task (seat_impl, task, - (GSourceFunc) destroy_in_impl); - g_object_unref (task); - - g_thread_join (seat_impl->input_thread); - g_assert (!seat_impl->libinput); - } - - g_object_unref (seat_impl); -} - -static void -meta_seat_impl_finalize (GObject *object) -{ - MetaSeatImpl *seat_impl = META_SEAT_IMPL (object); - - g_assert (!seat_impl->libinput); - g_assert (!seat_impl->tools); - g_assert (!seat_impl->event_source); - - g_free (seat_impl->seat_id); - - g_rw_lock_clear (&seat_impl->state_lock); - - G_OBJECT_CLASS (meta_seat_impl_parent_class)->finalize (object); -} - -ClutterInputDevice * -meta_seat_impl_get_pointer (MetaSeatImpl *seat_impl) -{ - return seat_impl->core_pointer; -} - -ClutterInputDevice * -meta_seat_impl_get_keyboard (MetaSeatImpl *seat_impl) -{ - return seat_impl->core_keyboard; -} - -GSList * -meta_seat_impl_get_devices_in_impl (MetaSeatImpl *seat_impl) -{ - return g_slist_copy_deep (seat_impl->devices, - (GCopyFunc) g_object_ref, - NULL); -} - -MetaKeymapNative * -meta_seat_impl_get_keymap (MetaSeatImpl *seat_impl) -{ - return g_object_ref (seat_impl->keymap); -} - -static gboolean -warp_pointer_in_impl (GTask *task) -{ - MetaSeatImpl *seat_impl = g_task_get_source_object (task); - graphene_point_t *point; - - point = g_task_get_task_data (task); - notify_absolute_motion_in_impl (seat_impl->core_pointer, 0, - point->x, point->y, NULL); - g_task_return_boolean (task, TRUE); - - return G_SOURCE_REMOVE; -} - -void -meta_seat_impl_warp_pointer (MetaSeatImpl *seat_impl, - int x, - int y) -{ - graphene_point_t *point; - GTask *task; - - point = graphene_point_alloc (); - point->x = x; - point->y = y; - - task = g_task_new (seat_impl, NULL, NULL, NULL); - g_task_set_task_data (task, point, (GDestroyNotify) graphene_point_free); - meta_seat_impl_run_input_task (seat_impl, task, - (GSourceFunc) warp_pointer_in_impl); - g_object_unref (task); -} - -gboolean -meta_seat_impl_query_state (MetaSeatImpl *seat_impl, - ClutterInputDevice *device, - ClutterEventSequence *sequence, - graphene_point_t *coords, - ClutterModifierType *modifiers) -{ - MetaInputDeviceNative *device_native = META_INPUT_DEVICE_NATIVE (device); - gboolean retval = FALSE; - ClutterModifierType mods = 0; - - g_rw_lock_reader_lock (&seat_impl->state_lock); - - if (sequence) - { - MetaTouchState *touch_state; - int slot; - - slot = clutter_event_sequence_get_slot (sequence); - touch_state = meta_seat_impl_lookup_touch_state_in_impl (seat_impl, slot); - if (!touch_state) - goto out; - - if (coords) - { - coords->x = touch_state->coords.x; - coords->y = touch_state->coords.y; - } - - if (seat_impl->xkb) - mods = meta_xkb_translate_modifiers (seat_impl->xkb, 0); - - retval = TRUE; - } - else - { - if (coords) - { - coords->x = device_native->pointer_x; - coords->y = device_native->pointer_y; - } - - if (seat_impl->xkb) - { - mods = meta_xkb_translate_modifiers (seat_impl->xkb, - seat_impl->button_state); - } - - retval = TRUE; - } - - if (modifiers) - *modifiers = mods; - - out: - g_rw_lock_reader_unlock (&seat_impl->state_lock); - return retval; -} - -static void -meta_seat_impl_initable_iface_init (GInitableIface *iface) -{ - iface->init = meta_seat_impl_initable_init; -} - -static void -meta_seat_impl_class_init (MetaSeatImplClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->constructed = meta_seat_impl_constructed; - object_class->set_property = meta_seat_impl_set_property; - object_class->get_property = meta_seat_impl_get_property; - object_class->finalize = meta_seat_impl_finalize; - - props[PROP_SEAT] = - g_param_spec_object ("seat", - "Seat", - "Seat", - META_TYPE_SEAT_NATIVE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - - props[PROP_SEAT_ID] = - g_param_spec_string ("seat-id", - "Seat ID", - "Seat ID", - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - - props[PROP_FLAGS] = - g_param_spec_flags ("flags", - "Flags", - "Flags", - META_TYPE_SEAT_NATIVE_FLAG, - META_SEAT_NATIVE_FLAG_NONE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - - signals[KBD_A11Y_FLAGS_CHANGED] = - g_signal_new ("kbd-a11y-flags-changed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 2, - G_TYPE_UINT, G_TYPE_UINT); - signals[KBD_A11Y_MODS_STATE_CHANGED] = - g_signal_new ("kbd-a11y-mods-state-changed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 2, - G_TYPE_UINT, G_TYPE_UINT); - signals[TOUCH_MODE] = - g_signal_new ("touch-mode", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__BOOLEAN, - G_TYPE_NONE, 1, G_TYPE_BOOLEAN); - signals[BELL] = - g_signal_new ("bell", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); - signals[MODS_STATE_CHANGED] = - g_signal_new ("mods-state-changed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); - - g_object_class_install_properties (object_class, N_PROPS, props); -} - -static void -meta_seat_impl_init (MetaSeatImpl *seat_impl) -{ - g_rw_lock_init (&seat_impl->state_lock); - - seat_impl->repeat = TRUE; - seat_impl->repeat_delay = 250; /* ms */ - seat_impl->repeat_interval = 33; /* ms */ - - g_mutex_init (&seat_impl->init_mutex); - g_cond_init (&seat_impl->init_cond); - - seat_impl->barrier_manager = meta_barrier_manager_native_new (); -} - -void -meta_seat_impl_update_xkb_state_in_impl (MetaSeatImpl *seat_impl) -{ - xkb_mod_mask_t latched_mods = 0; - xkb_mod_mask_t locked_mods = 0; - struct xkb_keymap *xkb_keymap; - - g_rw_lock_writer_lock (&seat_impl->state_lock); - - xkb_keymap = meta_keymap_native_get_keyboard_map_in_impl (seat_impl->keymap); - - if (seat_impl->xkb) - { - latched_mods = xkb_state_serialize_mods (seat_impl->xkb, - XKB_STATE_MODS_LATCHED); - locked_mods = xkb_state_serialize_mods (seat_impl->xkb, - XKB_STATE_MODS_LOCKED); - xkb_state_unref (seat_impl->xkb); - } - - seat_impl->xkb = xkb_state_new (xkb_keymap); - - xkb_state_update_mask (seat_impl->xkb, - 0, /* depressed */ - latched_mods, - locked_mods, - 0, 0, seat_impl->layout_idx); - - seat_impl->caps_lock_led = - xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_CAPS); - seat_impl->num_lock_led = - xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_NUM); - seat_impl->scroll_lock_led = - xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_SCROLL); - - meta_seat_impl_sync_leds_in_impl (seat_impl); - meta_keymap_native_update_in_impl (seat_impl->keymap, - seat_impl, - seat_impl->xkb); - - g_rw_lock_writer_unlock (&seat_impl->state_lock); -} - -static gboolean -release_devices (GTask *task) -{ - MetaSeatImpl *seat_impl = g_task_get_source_object (task); - - if (seat_impl->released) - { - g_warning ("meta_seat_impl_release_devices() shouldn't be called " - "multiple times without a corresponding call to " - "meta_seat_impl_reclaim_devices() first"); - } - else - { - libinput_suspend (seat_impl->libinput); - process_events (seat_impl); - - seat_impl->released = TRUE; - } - - g_task_return_boolean (task, TRUE); - - return G_SOURCE_REMOVE; -} - -/** - * meta_seat_impl_release_devices: - * - * Releases all the evdev devices that Clutter is currently managing. This api - * is typically used when switching away from the Clutter application when - * switching tty. The devices can be reclaimed later with a call to - * meta_seat_impl_reclaim_devices(). - * - * This function should only be called after clutter has been initialized. - */ -void -meta_seat_impl_release_devices (MetaSeatImpl *seat_impl) -{ - GTask *task; - - g_return_if_fail (META_IS_SEAT_IMPL (seat_impl)); - - task = g_task_new (seat_impl, NULL, NULL, NULL); - meta_seat_impl_run_input_task (seat_impl, task, - (GSourceFunc) release_devices); - g_object_unref (task); -} - -static gboolean -reclaim_devices (GTask *task) -{ - MetaSeatImpl *seat_impl = g_task_get_source_object (task); - - if (seat_impl->released) - { - libinput_resume (seat_impl->libinput); - meta_seat_impl_update_xkb_state_in_impl (seat_impl); - process_events (seat_impl); - - seat_impl->released = FALSE; - } - else - { - g_warning ("Spurious call to meta_seat_impl_reclaim_devices() without " - "previous call to meta_seat_impl_release_devices"); - } - - g_task_return_boolean (task, TRUE); - - return G_SOURCE_REMOVE; -} - -/** - * meta_seat_impl_reclaim_devices: - * - * This causes Clutter to re-probe for evdev devices. This is must only be - * called after a corresponding call to meta_seat_impl_release_devices() - * was previously used to release all evdev devices. This API is typically - * used when a clutter application using evdev has regained focus due to - * switching ttys. - * - * This function should only be called after clutter has been initialized. - */ -void -meta_seat_impl_reclaim_devices (MetaSeatImpl *seat_impl) -{ - GTask *task; - - g_return_if_fail (META_IS_SEAT_IMPL (seat_impl)); - - task = g_task_new (seat_impl, NULL, NULL, NULL); - meta_seat_impl_run_input_task (seat_impl, task, (GSourceFunc) reclaim_devices); - g_object_unref (task); -} - -static gboolean -set_keyboard_map (GTask *task) -{ - MetaSeatImpl *seat_impl = g_task_get_source_object (task); - struct xkb_keymap *xkb_keymap = g_task_get_task_data (task); - MetaKeymapNative *keymap; - - keymap = seat_impl->keymap; - meta_keymap_native_set_keyboard_map_in_impl (keymap, xkb_keymap); - - meta_seat_impl_update_xkb_state_in_impl (seat_impl); - g_task_return_boolean (task, TRUE); - - return G_SOURCE_REMOVE; -} - -/** - * meta_seat_impl_set_keyboard_map: (skip) - * @seat_impl: the #ClutterSeat created by the evdev backend - * @keymap: the new keymap - * - * Instructs @evdev to use the speficied keyboard map. This will cause - * the backend to drop the state and create a new one with the new - * map. To avoid state being lost, callers should ensure that no key - * is pressed when calling this function. - */ -void -meta_seat_impl_set_keyboard_map (MetaSeatImpl *seat_impl, - struct xkb_keymap *xkb_keymap) -{ - GTask *task; - - g_return_if_fail (META_IS_SEAT_IMPL (seat_impl)); - g_return_if_fail (xkb_keymap != NULL); - - task = g_task_new (seat_impl, NULL, NULL, NULL); - g_task_set_task_data (task, - xkb_keymap_ref (xkb_keymap), - (GDestroyNotify) xkb_keymap_unref); - meta_seat_impl_run_input_task (seat_impl, task, (GSourceFunc) set_keyboard_map); - g_object_unref (task); -} - -static gboolean -set_keyboard_layout_index (GTask *task) -{ - MetaSeatImpl *seat_impl = g_task_get_source_object (task); - xkb_layout_index_t idx = GPOINTER_TO_UINT (g_task_get_task_data (task)); - xkb_mod_mask_t depressed_mods; - xkb_mod_mask_t latched_mods; - xkb_mod_mask_t locked_mods; - struct xkb_state *state; - - g_rw_lock_writer_lock (&seat_impl->state_lock); - - state = seat_impl->xkb; - - depressed_mods = xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED); - latched_mods = xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED); - locked_mods = xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED); - - xkb_state_update_mask (state, depressed_mods, latched_mods, locked_mods, 0, 0, idx); - meta_keymap_native_update_in_impl (seat_impl->keymap, - seat_impl, - seat_impl->xkb); - - seat_impl->layout_idx = idx; - - g_rw_lock_writer_unlock (&seat_impl->state_lock); - - g_task_return_boolean (task, TRUE); - - return G_SOURCE_REMOVE; -} - -/** - * meta_seat_impl_set_keyboard_layout_index: (skip) - * @seat_impl: the #ClutterSeat created by the evdev backend - * @idx: the xkb layout index to set - * - * Sets the xkb layout index on the backend's #xkb_state . - */ -void -meta_seat_impl_set_keyboard_layout_index (MetaSeatImpl *seat_impl, - xkb_layout_index_t idx) -{ - GTask *task; - - g_return_if_fail (META_IS_SEAT_IMPL (seat_impl)); - - task = g_task_new (seat_impl, NULL, NULL, NULL); - g_task_set_task_data (task, GUINT_TO_POINTER (idx), NULL); - meta_seat_impl_run_input_task (seat_impl, task, - (GSourceFunc) set_keyboard_layout_index); - g_object_unref (task); -} - -/** - * meta_seat_impl_set_keyboard_repeat_in_impl: - * @seat_impl: the #ClutterSeat created by the evdev backend - * @repeat: whether to enable or disable keyboard repeat events - * @delay: the delay in ms between the hardware key press event and - * the first synthetic event - * @interval: the period in ms between consecutive synthetic key - * press events - * - * Enables or disables sythetic key press events, allowing for initial - * delay and interval period to be specified. - */ -void -meta_seat_impl_set_keyboard_repeat_in_impl (MetaSeatImpl *seat_impl, - gboolean repeat, - uint32_t delay, - uint32_t interval) -{ - g_return_if_fail (META_IS_SEAT_IMPL (seat_impl)); - - seat_impl->repeat = repeat; - seat_impl->repeat_delay = delay; - seat_impl->repeat_interval = interval; -} - -struct xkb_state * -meta_seat_impl_get_xkb_state_in_impl (MetaSeatImpl *seat_impl) -{ - return seat_impl->xkb; -} - -MetaBarrierManagerNative * -meta_seat_impl_get_barrier_manager (MetaSeatImpl *seat_impl) -{ - return seat_impl->barrier_manager; -} - -static gboolean -set_pointer_constraint (GTask *task) -{ - MetaSeatImpl *seat_impl = g_task_get_source_object (task); - MetaPointerConstraintImpl *constraint_impl = g_task_get_task_data (task); - - if (!g_set_object (&seat_impl->pointer_constraint, constraint_impl)) - return G_SOURCE_REMOVE; - - if (constraint_impl) - { - meta_pointer_constraint_impl_ensure_constrained (constraint_impl, - seat_impl->core_pointer); - } - - g_task_return_boolean (task, TRUE); - - return G_SOURCE_REMOVE; -} - -void -meta_seat_impl_set_pointer_constraint (MetaSeatImpl *seat_impl, - MetaPointerConstraintImpl *constraint_impl) -{ - GTask *task; - - g_return_if_fail (META_IS_SEAT_IMPL (seat_impl)); - - task = g_task_new (seat_impl, NULL, NULL, NULL); - if (constraint_impl) - g_task_set_task_data (task, g_object_ref (constraint_impl), g_object_unref); - meta_seat_impl_run_input_task (seat_impl, task, - (GSourceFunc) set_pointer_constraint); - g_object_unref (task); -} - -static gboolean -set_viewports (GTask *task) -{ - MetaSeatImpl *seat_impl = g_task_get_source_object (task); - MetaViewportInfo *viewports = g_task_get_task_data (task); - - g_set_object (&seat_impl->viewports, viewports); - g_task_return_boolean (task, TRUE); - - return G_SOURCE_REMOVE; -} - -void -meta_seat_impl_set_viewports (MetaSeatImpl *seat_impl, - MetaViewportInfo *viewports) -{ - GTask *task; - - g_return_if_fail (META_IS_SEAT_IMPL (seat_impl)); - - task = g_task_new (seat_impl, NULL, NULL, NULL); - g_task_set_task_data (task, g_object_ref (viewports), g_object_unref); - meta_seat_impl_run_input_task (seat_impl, task, - (GSourceFunc) set_viewports); - g_object_unref (task); -} - -MetaSeatImpl * -meta_seat_impl_new (MetaSeatNative *seat_native, - const char *seat_id, - MetaSeatNativeFlag flags) -{ - return g_initable_new (META_TYPE_SEAT_IMPL, - NULL, NULL, - "seat", seat_native, - "seat-id", seat_id, - "flags", flags, - NULL); -} - -void -meta_seat_impl_notify_kbd_a11y_flags_changed_in_impl (MetaSeatImpl *seat_impl, - MetaKeyboardA11yFlags new_flags, - MetaKeyboardA11yFlags what_changed) -{ - MetaInputSettings *input_settings; - GValue values[] = { G_VALUE_INIT, G_VALUE_INIT }; - - input_settings = seat_impl->input_settings; - meta_input_settings_notify_kbd_a11y_change (input_settings, - new_flags, what_changed); - g_value_init (&values[0], G_TYPE_UINT); - g_value_set_uint (&values[0], new_flags); - g_value_init (&values[1], G_TYPE_UINT); - g_value_set_uint (&values[1], what_changed); - - emit_signal (seat_impl, signals[KBD_A11Y_FLAGS_CHANGED], - values, G_N_ELEMENTS (values)); -} - -void -meta_seat_impl_notify_kbd_a11y_mods_state_changed_in_impl (MetaSeatImpl *seat_impl, - xkb_mod_mask_t new_latched_mods, - xkb_mod_mask_t new_locked_mods) -{ - GValue values[] = { G_VALUE_INIT, G_VALUE_INIT }; - - g_value_init (&values[0], G_TYPE_UINT); - g_value_set_uint (&values[0], new_latched_mods); - g_value_init (&values[1], G_TYPE_UINT); - g_value_set_uint (&values[1], new_locked_mods); - - emit_signal (seat_impl, signals[KBD_A11Y_MODS_STATE_CHANGED], - values, G_N_ELEMENTS (values)); -} - -void -meta_seat_impl_notify_bell_in_impl (MetaSeatImpl *seat_impl) -{ - emit_signal (seat_impl, signals[BELL], NULL, 0); -} - -MetaInputSettings * -meta_seat_impl_get_input_settings (MetaSeatImpl *seat_impl) -{ - return seat_impl->input_settings; -} diff --git a/src/backends/native/meta-seat-impl.h b/src/backends/native/meta-seat-impl.h deleted file mode 100644 index d3e2ab860..000000000 --- a/src/backends/native/meta-seat-impl.h +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (C) 2010 Intel Corp. - * Copyright (C) 2014 Jonas Ådahl - * Copyright (C) 2016 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 . - * - * Author: Damien Lespiau - * Author: Jonas Ådahl - */ - -#ifndef META_SEAT_IMPL_H -#define META_SEAT_IMPL_H - -#ifndef META_INPUT_THREAD_H_INSIDE -#error "This header cannot be included directly. Use "backends/native/meta-input-thread.h"" -#endif /* META_INPUT_THREAD_H_INSIDE */ - -#include -#include -#include - -#include "backends/meta-input-settings-private.h" -#include "backends/meta-viewport-info.h" -#include "backends/native/meta-backend-native-types.h" -#include "backends/native/meta-barrier-native.h" -#include "backends/native/meta-cursor-renderer-native.h" -#include "backends/native/meta-keymap-native.h" -#include "backends/native/meta-pointer-constraint-native.h" -#include "backends/native/meta-xkb-utils.h" -#include "clutter/clutter.h" - -typedef struct _MetaTouchState MetaTouchState; -typedef struct _MetaSeatImpl MetaSeatImpl; -typedef struct _MetaEventSource MetaEventSource; - -struct _MetaTouchState -{ - MetaSeatImpl *seat_impl; - - int device_slot; - int seat_slot; - graphene_point_t coords; -}; - -struct _MetaSeatImpl -{ - GObject parent_instance; - - GMainContext *main_context; - GMainContext *input_context; - GMainLoop *input_loop; - GThread *input_thread; - GMutex init_mutex; - GCond init_cond; - - MetaSeatNative *seat_native; - char *seat_id; - MetaSeatNativeFlag flags; - MetaEventSource *event_source; - struct libinput *libinput; - GRWLock state_lock; - - GSList *devices; - GHashTable *tools; - - ClutterInputDevice *core_pointer; - ClutterInputDevice *core_keyboard; - - GHashTable *touch_states; - GHashTable *cursor_renderers; - - struct xkb_state *xkb; - xkb_led_index_t caps_lock_led; - xkb_led_index_t num_lock_led; - xkb_led_index_t scroll_lock_led; - xkb_layout_index_t layout_idx; - uint32_t button_state; - int button_count[KEY_CNT]; - - MetaBarrierManagerNative *barrier_manager; - MetaPointerConstraintImpl *pointer_constraint; - - MetaKeymapNative *keymap; - MetaInputSettings *input_settings; - - MetaViewportInfo *viewports; - - gboolean tablet_mode_switch_state; - gboolean has_touchscreen; - gboolean has_tablet_switch; - gboolean has_pointer; - gboolean touch_mode; - gboolean input_thread_initialized; - - /* keyboard repeat */ - gboolean repeat; - uint32_t repeat_delay; - uint32_t repeat_interval; - uint32_t repeat_key; - uint32_t repeat_count; - ClutterInputDevice *repeat_device; - GSource *repeat_source; - - float pointer_x; - float pointer_y; - - /* Emulation of discrete scroll events out of smooth ones */ - float accum_scroll_dx; - float accum_scroll_dy; - - gboolean released; -}; - -#define META_TYPE_SEAT_IMPL meta_seat_impl_get_type () -G_DECLARE_FINAL_TYPE (MetaSeatImpl, meta_seat_impl, - META, SEAT_IMPL, GObject) - -MetaSeatImpl * meta_seat_impl_new (MetaSeatNative *seat_native, - const char *seat_id, - MetaSeatNativeFlag flags); - -void meta_seat_impl_destroy (MetaSeatImpl *seat_impl); - -void meta_seat_impl_run_input_task (MetaSeatImpl *seat_impl, - GTask *task, - GSourceFunc dispatch_func); - -void meta_seat_impl_notify_key_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *device, - uint64_t time_us, - uint32_t key, - uint32_t state, - gboolean update_keys); - -void meta_seat_impl_notify_relative_motion_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - uint64_t time_us, - float dx, - float dy, - float dx_unaccel, - float dy_unaccel); - -void meta_seat_impl_notify_absolute_motion_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - uint64_t time_us, - float x, - float y, - double *axes); - -void meta_seat_impl_notify_button_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - uint64_t time_us, - uint32_t button, - uint32_t state); - -void meta_seat_impl_notify_scroll_continuous_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - uint64_t time_us, - double dx, - double dy, - ClutterScrollSource source, - ClutterScrollFinishFlags flags); - -void meta_seat_impl_notify_discrete_scroll_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - uint64_t time_us, - double discrete_dx, - double discrete_dy, - ClutterScrollSource source); - -void meta_seat_impl_notify_touch_event_in_impl (MetaSeatImpl *seat_impl, - ClutterInputDevice *input_device, - ClutterEventType evtype, - uint64_t time_us, - int slot, - double x, - double y); - -void meta_seat_impl_sync_leds_in_impl (MetaSeatImpl *seat_impl); - -MetaTouchState * meta_seat_impl_acquire_touch_state_in_impl (MetaSeatImpl *seat_impl, - int seat_slot); -MetaTouchState * meta_seat_impl_lookup_touch_state_in_impl (MetaSeatImpl *seat_impl, - int seat_slot); -void meta_seat_impl_release_touch_state_in_impl (MetaSeatImpl *seat_impl, - int seat_slot); - -void meta_seat_impl_update_xkb_state_in_impl (MetaSeatImpl *seat_impl); - -void meta_seat_impl_release_devices (MetaSeatImpl *seat_impl); -void meta_seat_impl_reclaim_devices (MetaSeatImpl *seat_impl); - -struct xkb_state * meta_seat_impl_get_xkb_state_in_impl (MetaSeatImpl *seat_impl); - -void meta_seat_impl_set_keyboard_map (MetaSeatImpl *seat_impl, - struct xkb_keymap *keymap); - -void meta_seat_impl_set_keyboard_layout_index (MetaSeatImpl *seat_impl, - xkb_layout_index_t idx); - -void meta_seat_impl_set_keyboard_repeat_in_impl (MetaSeatImpl *seat_impl, - gboolean repeat, - uint32_t delay, - uint32_t interval); - -MetaBarrierManagerNative * meta_seat_impl_get_barrier_manager (MetaSeatImpl *seat_impl); - -void meta_seat_impl_set_pointer_constraint (MetaSeatImpl *seat_impl, - MetaPointerConstraintImpl *constraint_impl); -void meta_seat_impl_set_viewports (MetaSeatImpl *seat_impl, - MetaViewportInfo *viewports); - -void meta_seat_impl_warp_pointer (MetaSeatImpl *seat_impl, - int x, - int y); -gboolean meta_seat_impl_query_state (MetaSeatImpl *seat_impl, - ClutterInputDevice *device, - ClutterEventSequence *sequence, - graphene_point_t *coords, - ClutterModifierType *modifiers); -ClutterInputDevice * meta_seat_impl_get_pointer (MetaSeatImpl *seat_impl); -ClutterInputDevice * meta_seat_impl_get_keyboard (MetaSeatImpl *seat_impl); -GSList * meta_seat_impl_get_devices_in_impl (MetaSeatImpl *seat_impl); - -MetaKeymapNative * meta_seat_impl_get_keymap (MetaSeatImpl *seat_impl); - -void meta_seat_impl_notify_kbd_a11y_flags_changed_in_impl (MetaSeatImpl *seat_impl, - MetaKeyboardA11yFlags new_flags, - MetaKeyboardA11yFlags what_changed); -void meta_seat_impl_notify_kbd_a11y_mods_state_changed_in_impl (MetaSeatImpl *seat_impl, - xkb_mod_mask_t new_latched_mods, - xkb_mod_mask_t new_locked_mods); -void meta_seat_impl_notify_bell_in_impl (MetaSeatImpl *seat_impl); - -MetaInputSettings * meta_seat_impl_get_input_settings (MetaSeatImpl *seat_impl); - -void meta_seat_impl_queue_main_thread_idle (MetaSeatImpl *seat_impl, - GSourceFunc func, - gpointer user_data, - GDestroyNotify destroy_notify); - -#endif /* META_SEAT_IMPL_H */ diff --git a/src/backends/native/meta-seat-native.c b/src/backends/native/meta-seat-native.c deleted file mode 100644 index 12fead1fb..000000000 --- a/src/backends/native/meta-seat-native.c +++ /dev/null @@ -1,634 +0,0 @@ -/* - * Clutter. - * - * An OpenGL based 'interactive canvas' library. - * - * Copyright (C) 2010 Intel Corp. - * Copyright (C) 2014 Jonas Ådahl - * Copyright (C) 2016 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 . - * - * Author: Damien Lespiau - * Author: Jonas Ådahl - */ - -#include "config.h" - -#include "backends/native/meta-seat-native.h" - -#include "backends/meta-cursor-tracker-private.h" -#include "backends/meta-keymap-utils.h" -#include "backends/native/meta-barrier-native.h" -#include "backends/native/meta-input-thread.h" -#include "backends/native/meta-keymap-native.h" -#include "backends/native/meta-virtual-input-device-native.h" -#include "clutter/clutter-mutter.h" -#include "core/bell.h" - -#include "meta-private-enum-types.h" - -enum -{ - PROP_0, - PROP_SEAT_ID, - PROP_FLAGS, - PROP_BACKEND, - N_PROPS, - - /* This property is overridden */ - PROP_TOUCH_MODE, -}; - -static GParamSpec *props[N_PROPS] = { NULL }; - -G_DEFINE_TYPE (MetaSeatNative, meta_seat_native, CLUTTER_TYPE_SEAT) - -static gboolean -meta_seat_native_handle_event_post (ClutterSeat *seat, - const ClutterEvent *event) -{ - MetaSeatNative *seat_native = META_SEAT_NATIVE (seat); - ClutterInputDevice *device = clutter_event_get_source_device (event); - ClutterEventType event_type = event->type; - - if (event_type == CLUTTER_PROXIMITY_IN) - { - MetaCursorRenderer *cursor_renderer; - - if (!seat_native->tablet_cursors) - { - seat_native->tablet_cursors = g_hash_table_new_full (NULL, NULL, NULL, - g_object_unref); - } - - cursor_renderer = meta_cursor_renderer_new (meta_get_backend (), device); - g_hash_table_insert (seat_native->tablet_cursors, - device, cursor_renderer); - return TRUE; - } - else if (event_type == CLUTTER_PROXIMITY_OUT) - { - if (seat_native->tablet_cursors) - g_hash_table_remove (seat_native->tablet_cursors, device); - return TRUE; - } - else if (event_type == CLUTTER_DEVICE_ADDED) - { - if (clutter_input_device_get_device_mode (device) != CLUTTER_INPUT_MODE_LOGICAL) - seat_native->devices = g_list_prepend (seat_native->devices, g_object_ref (device)); - } - else if (event_type == CLUTTER_DEVICE_REMOVED) - { - GList *l = g_list_find (seat_native->devices, device); - - if (l) - { - seat_native->devices = g_list_delete_link (seat_native->devices, l); - g_object_unref (device); - } - } - - return FALSE; -} - -static void -proxy_kbd_a11y_flags_changed (MetaSeatImpl *seat_impl, - MetaKeyboardA11yFlags new_flags, - MetaKeyboardA11yFlags what_changed, - MetaSeatNative *seat_native) -{ - g_signal_emit_by_name (seat_native, - "kbd-a11y-flags-changed", - new_flags, what_changed); -} - -static void -proxy_kbd_a11y_mods_state_changed (MetaSeatImpl *seat_impl, - xkb_mod_mask_t new_latched_mods, - xkb_mod_mask_t new_locked_mods, - MetaSeatNative *seat_native) -{ - g_signal_emit_by_name (seat_native, - "kbd-a11y-mods-state-changed", - new_latched_mods, - new_locked_mods); -} - -static void -proxy_touch_mode_changed (MetaSeatImpl *seat_impl, - gboolean enabled, - MetaSeatNative *seat_native) -{ - seat_native->touch_mode = enabled; - g_object_notify (G_OBJECT (seat_native), "touch-mode"); -} - -static void -proxy_bell (MetaSeatImpl *seat_impl, - MetaSeatNative *seat_native) -{ - clutter_seat_bell_notify (CLUTTER_SEAT (seat_native)); -} - -static void -proxy_mods_state_changed (MetaSeatImpl *seat_impl, - ClutterSeat *seat) -{ - ClutterKeymap *keymap; - - keymap = clutter_seat_get_keymap (seat); - g_signal_emit_by_name (keymap, "state-changed"); -} - -static void -meta_seat_native_constructed (GObject *object) -{ - MetaSeatNative *seat = META_SEAT_NATIVE (object); - - seat->impl = meta_seat_impl_new (seat, seat->seat_id, seat->flags); - g_signal_connect (seat->impl, "kbd-a11y-flags-changed", - G_CALLBACK (proxy_kbd_a11y_flags_changed), seat); - g_signal_connect (seat->impl, "kbd-a11y-mods-state-changed", - G_CALLBACK (proxy_kbd_a11y_mods_state_changed), seat); - g_signal_connect (seat->impl, "touch-mode", - G_CALLBACK (proxy_touch_mode_changed), seat); - g_signal_connect (seat->impl, "bell", - G_CALLBACK (proxy_bell), seat); - g_signal_connect (seat->impl, "mods-state-changed", - G_CALLBACK (proxy_mods_state_changed), seat); - - seat->core_pointer = meta_seat_impl_get_pointer (seat->impl); - seat->core_keyboard = meta_seat_impl_get_keyboard (seat->impl); - - meta_seat_native_set_keyboard_map (seat, "us", "", ""); - - if (G_OBJECT_CLASS (meta_seat_native_parent_class)->constructed) - G_OBJECT_CLASS (meta_seat_native_parent_class)->constructed (object); -} - -static void -meta_seat_native_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaSeatNative *seat_native = META_SEAT_NATIVE (object); - - switch (prop_id) - { - case PROP_SEAT_ID: - seat_native->seat_id = g_value_dup_string (value); - break; - case PROP_FLAGS: - seat_native->flags = g_value_get_flags (value); - break; - case PROP_BACKEND: - seat_native->backend = g_value_get_object (value); - break; - case PROP_TOUCH_MODE: - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_seat_native_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaSeatNative *seat_native = META_SEAT_NATIVE (object); - - switch (prop_id) - { - case PROP_SEAT_ID: - g_value_set_string (value, seat_native->seat_id); - break; - case PROP_TOUCH_MODE: - g_value_set_boolean (value, seat_native->touch_mode); - break; - case PROP_FLAGS: - g_value_set_flags (value, seat_native->flags); - break; - case PROP_BACKEND: - g_value_set_object (value, seat_native->backend); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_seat_native_dispose (GObject *object) -{ - MetaSeatNative *seat = META_SEAT_NATIVE (object); - - g_clear_pointer (&seat->xkb_keymap, xkb_keymap_unref); - g_clear_object (&seat->core_pointer); - g_clear_object (&seat->core_keyboard); - g_clear_pointer (&seat->impl, meta_seat_impl_destroy); - g_list_free_full (g_steal_pointer (&seat->devices), g_object_unref); - g_clear_pointer (&seat->reserved_virtual_slots, g_hash_table_destroy); - g_clear_pointer (&seat->tablet_cursors, g_hash_table_unref); - g_clear_object (&seat->cursor_renderer); - - g_clear_pointer (&seat->seat_id, g_free); - - G_OBJECT_CLASS (meta_seat_native_parent_class)->dispose (object); -} - -static ClutterInputDevice * -meta_seat_native_get_pointer (ClutterSeat *seat) -{ - MetaSeatNative *seat_native = META_SEAT_NATIVE (seat); - - return seat_native->core_pointer; -} - -static ClutterInputDevice * -meta_seat_native_get_keyboard (ClutterSeat *seat) -{ - MetaSeatNative *seat_native = META_SEAT_NATIVE (seat); - - return seat_native->core_keyboard; -} - -static const GList * -meta_seat_native_peek_devices (ClutterSeat *seat) -{ - MetaSeatNative *seat_native = META_SEAT_NATIVE (seat); - - return (const GList *) seat_native->devices; -} - -static void -meta_seat_native_bell_notify (ClutterSeat *seat) -{ - MetaDisplay *display = meta_get_display (); - - meta_bell_notify (display, NULL); -} - -static ClutterKeymap * -meta_seat_native_get_keymap (ClutterSeat *seat) -{ - MetaSeatNative *seat_native = META_SEAT_NATIVE (seat); - - if (!seat_native->keymap) - seat_native->keymap = meta_seat_impl_get_keymap (seat_native->impl); - - return CLUTTER_KEYMAP (seat_native->keymap); -} - -static guint -bump_virtual_touch_slot_base (MetaSeatNative *seat_native) -{ - while (TRUE) - { - if (seat_native->virtual_touch_slot_base < 0x100) - seat_native->virtual_touch_slot_base = 0x100; - - seat_native->virtual_touch_slot_base += - CLUTTER_VIRTUAL_INPUT_DEVICE_MAX_TOUCH_SLOTS; - - if (!g_hash_table_lookup (seat_native->reserved_virtual_slots, - GUINT_TO_POINTER (seat_native->virtual_touch_slot_base))) - break; - } - - return seat_native->virtual_touch_slot_base; -} - -static ClutterVirtualInputDevice * -meta_seat_native_create_virtual_device (ClutterSeat *seat, - ClutterInputDeviceType device_type) -{ - MetaSeatNative *seat_native = META_SEAT_NATIVE (seat); - guint slot_base; - - slot_base = bump_virtual_touch_slot_base (seat_native); - g_hash_table_add (seat_native->reserved_virtual_slots, - GUINT_TO_POINTER (slot_base)); - - return g_object_new (META_TYPE_VIRTUAL_INPUT_DEVICE_NATIVE, - "seat", seat, - "slot-base", slot_base, - "device-type", device_type, - NULL); -} - -void -meta_seat_native_release_touch_slots (MetaSeatNative *seat, - guint base_slot) -{ - g_hash_table_remove (seat->reserved_virtual_slots, - GUINT_TO_POINTER (base_slot)); -} - -static ClutterVirtualDeviceType -meta_seat_native_get_supported_virtual_device_types (ClutterSeat *seat) -{ - return (CLUTTER_VIRTUAL_DEVICE_TYPE_KEYBOARD | - CLUTTER_VIRTUAL_DEVICE_TYPE_POINTER | - CLUTTER_VIRTUAL_DEVICE_TYPE_TOUCHSCREEN); -} - -static void -meta_seat_native_warp_pointer (ClutterSeat *seat, - int x, - int y) -{ - MetaSeatNative *seat_native = META_SEAT_NATIVE (seat); - - meta_seat_impl_warp_pointer (seat_native->impl, x, y); -} - -static gboolean -meta_seat_native_query_state (ClutterSeat *seat, - ClutterInputDevice *device, - ClutterEventSequence *sequence, - graphene_point_t *coords, - ClutterModifierType *modifiers) -{ - MetaSeatNative *seat_native = META_SEAT_NATIVE (seat); - - return meta_seat_impl_query_state (seat_native->impl, device, sequence, - coords, modifiers); -} - -static void -meta_seat_native_class_init (MetaSeatNativeClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - ClutterSeatClass *seat_class = CLUTTER_SEAT_CLASS (klass); - - object_class->constructed = meta_seat_native_constructed; - object_class->set_property = meta_seat_native_set_property; - object_class->get_property = meta_seat_native_get_property; - object_class->dispose = meta_seat_native_dispose; - - seat_class->get_pointer = meta_seat_native_get_pointer; - seat_class->get_keyboard = meta_seat_native_get_keyboard; - seat_class->peek_devices = meta_seat_native_peek_devices; - seat_class->bell_notify = meta_seat_native_bell_notify; - seat_class->get_keymap = meta_seat_native_get_keymap; - seat_class->create_virtual_device = meta_seat_native_create_virtual_device; - seat_class->get_supported_virtual_device_types = meta_seat_native_get_supported_virtual_device_types; - seat_class->warp_pointer = meta_seat_native_warp_pointer; - seat_class->handle_event_post = meta_seat_native_handle_event_post; - seat_class->query_state = meta_seat_native_query_state; - - props[PROP_SEAT_ID] = - g_param_spec_string ("seat-id", - "Seat ID", - "Seat ID", - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - - props[PROP_FLAGS] = - g_param_spec_flags ("flags", - "Flags", - "Flags", - META_TYPE_SEAT_NATIVE_FLAG, - META_SEAT_NATIVE_FLAG_NONE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - - props[PROP_BACKEND] = - g_param_spec_object ("backend", - "Backend", - "Backend", - META_TYPE_BACKEND, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - - g_object_class_install_properties (object_class, N_PROPS, props); - - g_object_class_override_property (object_class, PROP_TOUCH_MODE, - "touch-mode"); -} - -static void -meta_seat_native_init (MetaSeatNative *seat) -{ - seat->reserved_virtual_slots = g_hash_table_new (NULL, NULL); -} - -/** - * meta_seat_native_release_devices: - * - * Releases all the evdev devices that Clutter is currently managing. This api - * is typically used when switching away from the Clutter application when - * switching tty. The devices can be reclaimed later with a call to - * meta_seat_native_reclaim_devices(). - * - * This function should only be called after clutter has been initialized. - */ -void -meta_seat_native_release_devices (MetaSeatNative *seat) -{ - g_return_if_fail (META_IS_SEAT_NATIVE (seat)); - - if (seat->released) - { - g_warning ("meta_seat_native_release_devices() shouldn't be called " - "multiple times without a corresponding call to " - "meta_seat_native_reclaim_devices() first"); - return; - } - - meta_seat_impl_release_devices (seat->impl); - seat->released = TRUE; -} - -/** - * meta_seat_native_reclaim_devices: - * - * This causes Clutter to re-probe for evdev devices. This is must only be - * called after a corresponding call to meta_seat_native_release_devices() - * was previously used to release all evdev devices. This API is typically - * used when a clutter application using evdev has regained focus due to - * switching ttys. - * - * This function should only be called after clutter has been initialized. - */ -void -meta_seat_native_reclaim_devices (MetaSeatNative *seat) -{ - if (!seat->released) - { - g_warning ("Spurious call to meta_seat_native_reclaim_devices() without " - "previous call to meta_seat_native_release_devices"); - return; - } - - meta_seat_impl_reclaim_devices (seat->impl); - seat->released = FALSE; -} - -static struct xkb_keymap * -create_keymap (const char *layouts, - const char *variants, - const char *options) -{ - struct xkb_rule_names names; - struct xkb_keymap *keymap; - struct xkb_context *context; - - names.rules = DEFAULT_XKB_RULES_FILE; - names.model = DEFAULT_XKB_MODEL; - names.layout = layouts; - names.variant = variants; - names.options = options; - - context = meta_create_xkb_context (); - keymap = xkb_keymap_new_from_names (context, &names, XKB_KEYMAP_COMPILE_NO_FLAGS); - xkb_context_unref (context); - - return keymap; -} - -/** - * meta_seat_native_set_keyboard_map: (skip) - * @seat: the #ClutterSeat created by the evdev backend - * @keymap: the new keymap - * - * Instructs @evdev to use the specified keyboard map. This will cause - * the backend to drop the state and create a new one with the new - * map. To avoid state being lost, callers should ensure that no key - * is pressed when calling this function. - */ -void -meta_seat_native_set_keyboard_map (MetaSeatNative *seat, - const char *layouts, - const char *variants, - const char *options) -{ - struct xkb_keymap *keymap, *impl_keymap; - - keymap = create_keymap (layouts, variants, options); - impl_keymap = create_keymap (layouts, variants, options); - - if (keymap == NULL) - { - g_warning ("Unable to load configured keymap: rules=%s, model=%s, layout=%s, variant=%s, options=%s", - DEFAULT_XKB_RULES_FILE, DEFAULT_XKB_MODEL, layouts, - variants, options); - return; - } - - if (seat->xkb_keymap) - xkb_keymap_unref (seat->xkb_keymap); - seat->xkb_keymap = keymap; - - meta_seat_impl_set_keyboard_map (seat->impl, impl_keymap); - xkb_keymap_unref (impl_keymap); -} - -/** - * meta_seat_native_get_keyboard_map: (skip) - * @seat: the #ClutterSeat created by the evdev backend - * - * Retrieves the #xkb_keymap in use by the evdev backend. - * - * Return value: the #xkb_keymap. - */ -struct xkb_keymap * -meta_seat_native_get_keyboard_map (MetaSeatNative *seat) -{ - g_return_val_if_fail (META_IS_SEAT_NATIVE (seat), NULL); - - return seat->xkb_keymap; -} - -/** - * meta_seat_native_set_keyboard_layout_index: (skip) - * @seat: the #ClutterSeat created by the evdev backend - * @idx: the xkb layout index to set - * - * Sets the xkb layout index on the backend's #xkb_state . - */ -void -meta_seat_native_set_keyboard_layout_index (MetaSeatNative *seat, - xkb_layout_index_t idx) -{ - g_return_if_fail (META_IS_SEAT_NATIVE (seat)); - - seat->xkb_layout_index = idx; - meta_seat_impl_set_keyboard_layout_index (seat->impl, idx); -} - -/** - * meta_seat_native_get_keyboard_layout_index: (skip) - */ -xkb_layout_index_t -meta_seat_native_get_keyboard_layout_index (MetaSeatNative *seat) -{ - return seat->xkb_layout_index; -} - -MetaBarrierManagerNative * -meta_seat_native_get_barrier_manager (MetaSeatNative *seat) -{ - return meta_seat_impl_get_barrier_manager (seat->impl); -} - -MetaBackend * -meta_seat_native_get_backend (MetaSeatNative *seat_native) -{ - return seat_native->backend; -} - -void -meta_seat_native_set_pointer_constraint (MetaSeatNative *seat, - MetaPointerConstraintImpl *constraint_impl) -{ - meta_seat_impl_set_pointer_constraint (seat->impl, constraint_impl); -} - -MetaCursorRenderer * -meta_seat_native_maybe_ensure_cursor_renderer (MetaSeatNative *seat_native, - ClutterInputDevice *device) -{ - if (device == seat_native->core_pointer) - { - if (!seat_native->cursor_renderer) - { - MetaCursorRendererNative *cursor_renderer_native; - - cursor_renderer_native = - meta_cursor_renderer_native_new (meta_get_backend (), - seat_native->core_pointer); - seat_native->cursor_renderer = - META_CURSOR_RENDERER (cursor_renderer_native); - } - - return seat_native->cursor_renderer; - } - - if (seat_native->tablet_cursors && - clutter_input_device_get_device_type (device) == CLUTTER_TABLET_DEVICE) - return g_hash_table_lookup (seat_native->tablet_cursors, device); - - return NULL; -} - -void -meta_seat_native_set_viewports (MetaSeatNative *seat, - MetaViewportInfo *viewports) -{ - meta_seat_impl_set_viewports (seat->impl, viewports); -} diff --git a/src/backends/native/meta-seat-native.h b/src/backends/native/meta-seat-native.h deleted file mode 100644 index 53ba00f51..000000000 --- a/src/backends/native/meta-seat-native.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2010 Intel Corp. - * Copyright (C) 2014 Jonas Ådahl - * Copyright (C) 2016 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 . - * - * Author: Damien Lespiau - * Author: Jonas Ådahl - */ - -#ifndef META_SEAT_NATIVE_H -#define META_SEAT_NATIVE_H - -#include -#include -#include - -#include "backends/meta-input-settings-private.h" -#include "backends/meta-viewport-info.h" -#include "backends/native/meta-backend-native-types.h" -#include "backends/native/meta-barrier-native.h" -#include "backends/native/meta-cursor-renderer-native.h" -#include "backends/native/meta-pointer-constraint-native.h" -#include "backends/native/meta-xkb-utils.h" -#include "clutter/clutter.h" - -typedef struct _MetaSeatNative MetaSeatNative; - -struct _MetaSeatNative -{ - ClutterSeat parent_instance; - - MetaBackend *backend; - - MetaSeatImpl *impl; - char *seat_id; - MetaSeatNativeFlag flags; - - GList *devices; - struct xkb_keymap *xkb_keymap; - xkb_layout_index_t xkb_layout_index; - - ClutterInputDevice *core_pointer; - ClutterInputDevice *core_keyboard; - - guint virtual_touch_slot_base; - GHashTable *reserved_virtual_slots; - - MetaKeymapNative *keymap; - MetaCursorRenderer *cursor_renderer; - GHashTable *tablet_cursors; - - gboolean released; - gboolean touch_mode; -}; - -#define META_TYPE_SEAT_NATIVE meta_seat_native_get_type () -G_DECLARE_FINAL_TYPE (MetaSeatNative, meta_seat_native, - META, SEAT_NATIVE, ClutterSeat) - -void meta_seat_native_set_libinput_seat (MetaSeatNative *seat, - struct libinput_seat *libinput_seat); - -void meta_seat_native_sync_leds (MetaSeatNative *seat); - -/** - * MetaOpenDeviceCallback: - * @path: the device path - * @flags: flags to be passed to open - * - * This callback will be called when Clutter needs to access an input - * device. It should return an open file descriptor for the file at @path, - * or -1 if opening failed. - */ -typedef int (* MetaOpenDeviceCallback) (const char *path, - int flags, - gpointer user_data, - GError **error); -typedef void (* MetaCloseDeviceCallback) (int fd, - gpointer user_data); - -void meta_seat_native_set_device_callbacks (MetaOpenDeviceCallback open_callback, - MetaCloseDeviceCallback close_callback, - gpointer user_data); - -void meta_seat_native_release_devices (MetaSeatNative *seat); -void meta_seat_native_reclaim_devices (MetaSeatNative *seat); - -void meta_seat_native_set_keyboard_map (MetaSeatNative *seat, - const char *layouts, - const char *variants, - const char *options); - -struct xkb_keymap * meta_seat_native_get_keyboard_map (MetaSeatNative *seat); - -void meta_seat_native_set_keyboard_layout_index (MetaSeatNative *seat, - xkb_layout_index_t idx); - -xkb_layout_index_t meta_seat_native_get_keyboard_layout_index (MetaSeatNative *seat); - -void meta_seat_native_set_keyboard_repeat (MetaSeatNative *seat, - gboolean repeat, - uint32_t delay, - uint32_t interval); - -void meta_seat_native_release_touch_slots (MetaSeatNative *seat, - guint base_slot); - -MetaBarrierManagerNative * meta_seat_native_get_barrier_manager (MetaSeatNative *seat); - -MetaBackend * meta_seat_native_get_backend (MetaSeatNative *seat); - -void meta_seat_native_set_pointer_constraint (MetaSeatNative *seat, - MetaPointerConstraintImpl *constraint_impl); -MetaCursorRenderer * meta_seat_native_maybe_ensure_cursor_renderer (MetaSeatNative *seat, - ClutterInputDevice *device); - -void meta_seat_native_set_viewports (MetaSeatNative *seat, - MetaViewportInfo *viewports); - -#endif /* META_SEAT_NATIVE_H */ diff --git a/src/backends/native/meta-stage-native.c b/src/backends/native/meta-stage-native.c deleted file mode 100644 index e1f9fedb2..000000000 --- a/src/backends/native/meta-stage-native.c +++ /dev/null @@ -1,191 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#include "config.h" - -#include "backends/native/meta-stage-native.h" - -#include "backends/meta-backend-private.h" -#include "backends/native/meta-crtc-virtual.h" -#include "backends/native/meta-cursor-renderer-native.h" -#include "backends/native/meta-renderer-native.h" -#include "meta/meta-backend.h" -#include "meta/meta-monitor-manager.h" -#include "meta/util.h" - -static GQuark quark_view_frame_closure = 0; - -struct _MetaStageNative -{ - MetaStageImpl parent; - - CoglClosure *frame_closure; - - int64_t presented_frame_counter_sync; - int64_t presented_frame_counter_complete; -}; - -static ClutterStageWindowInterface *clutter_stage_window_parent_iface = NULL; - -static void -clutter_stage_window_iface_init (ClutterStageWindowInterface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaStageNative, meta_stage_native, - META_TYPE_STAGE_IMPL, - G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW, - clutter_stage_window_iface_init)) - -void -meta_stage_native_rebuild_views (MetaStageNative *stage_native) -{ - MetaBackend *backend = meta_get_backend (); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - ClutterActor *stage = meta_backend_get_stage (backend); - - meta_renderer_rebuild_views (renderer); - clutter_stage_clear_stage_views (CLUTTER_STAGE (stage)); -} - -static gboolean -meta_stage_native_can_clip_redraws (ClutterStageWindow *stage_window) -{ - return TRUE; -} - -static void -meta_stage_native_get_geometry (ClutterStageWindow *stage_window, - cairo_rectangle_int_t *geometry) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - - if (monitor_manager) - { - int width, height; - - meta_monitor_manager_get_screen_size (monitor_manager, &width, &height); - *geometry = (cairo_rectangle_int_t) { - .width = width, - .height = height, - }; - } - else - { - *geometry = (cairo_rectangle_int_t) { - .width = 1, - .height = 1, - }; - } -} - -static GList * -meta_stage_native_get_views (ClutterStageWindow *stage_window) -{ - MetaBackend *backend = meta_get_backend (); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - - return meta_renderer_get_views (renderer); -} - -static void -meta_stage_native_prepare_frame (ClutterStageWindow *stage_window, - ClutterStageView *stage_view, - ClutterFrame *frame) -{ - MetaBackend *backend = meta_get_backend (); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer); - MetaCursorRenderer *cursor_renderer = - meta_backend_get_cursor_renderer (backend); - MetaCursorRendererNative *cursor_renderer_native = - META_CURSOR_RENDERER_NATIVE (cursor_renderer); - - meta_renderer_native_prepare_frame (renderer_native, - META_RENDERER_VIEW (stage_view), - frame); - meta_cursor_renderer_native_prepare_frame (cursor_renderer_native, - META_RENDERER_VIEW (stage_view)); -} - -static void -meta_stage_native_redraw_view (ClutterStageWindow *stage_window, - ClutterStageView *view, - ClutterFrame *frame) -{ - MetaCrtc *crtc; - - clutter_stage_window_parent_iface->redraw_view (stage_window, view, frame); - - crtc = meta_renderer_view_get_crtc (META_RENDERER_VIEW (view)); - if (META_IS_CRTC_VIRTUAL (crtc)) - { - g_warn_if_fail (!clutter_frame_has_result (frame)); - - clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - } -} - -static void -meta_stage_native_finish_frame (ClutterStageWindow *stage_window, - ClutterStageView *stage_view, - ClutterFrame *frame) -{ - MetaBackend *backend = meta_get_backend (); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - - meta_renderer_native_finish_frame (META_RENDERER_NATIVE (renderer), - META_RENDERER_VIEW (stage_view), - frame); - - if (!clutter_frame_has_result (frame)) - clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_IDLE); -} - -static void -meta_stage_native_init (MetaStageNative *stage_native) -{ - stage_native->presented_frame_counter_sync = -1; - stage_native->presented_frame_counter_complete = -1; -} - -static void -meta_stage_native_class_init (MetaStageNativeClass *klass) -{ - quark_view_frame_closure = - g_quark_from_static_string ("-meta-native-stage-view-frame-closure"); -} - -static void -clutter_stage_window_iface_init (ClutterStageWindowInterface *iface) -{ - clutter_stage_window_parent_iface = g_type_interface_peek_parent (iface); - - iface->can_clip_redraws = meta_stage_native_can_clip_redraws; - iface->get_geometry = meta_stage_native_get_geometry; - iface->get_views = meta_stage_native_get_views; - iface->prepare_frame = meta_stage_native_prepare_frame; - iface->redraw_view = meta_stage_native_redraw_view; - iface->finish_frame = meta_stage_native_finish_frame; -} diff --git a/src/backends/native/meta-stage-native.h b/src/backends/native/meta-stage-native.h deleted file mode 100644 index 5f33e1f9a..000000000 --- a/src/backends/native/meta-stage-native.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#ifndef META_STAGE_NATIVE_H -#define META_STAGE_NATIVE_H - -#include "backends/meta-stage-impl-private.h" -#include "clutter/clutter-mutter.h" - -#define META_TYPE_STAGE_NATIVE (meta_stage_native_get_type ()) -G_DECLARE_FINAL_TYPE (MetaStageNative, meta_stage_native, - META, STAGE_NATIVE, MetaStageImpl) - -void meta_stage_native_rebuild_views (MetaStageNative *stage_native); - -#endif /* META_STAGE_NATIVE_H */ diff --git a/src/backends/native/meta-udev.c b/src/backends/native/meta-udev.c deleted file mode 100644 index 9fd84e98b..000000000 --- a/src/backends/native/meta-udev.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright (C) 2018 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. - * - */ - -#include "config.h" - -#include "backends/native/meta-udev.h" - -#include "backends/native/meta-backend-native.h" -#include "backends/native/meta-launcher.h" - -#define DRM_CARD_UDEV_DEVICE_TYPE "drm_minor" - -enum -{ - HOTPLUG, - DEVICE_ADDED, - DEVICE_REMOVED, - - N_SIGNALS -}; - -static guint signals[N_SIGNALS]; - -struct _MetaUdev -{ - GObject parent; - - MetaBackendNative *backend_native; - - GUdevClient *gudev_client; - - gulong uevent_handler_id; -}; - -G_DEFINE_TYPE (MetaUdev, meta_udev, G_TYPE_OBJECT) - -gboolean -meta_is_udev_device_platform_device (GUdevDevice *device) -{ - g_autoptr (GUdevDevice) platform_device = NULL; - - platform_device = g_udev_device_get_parent_with_subsystem (device, - "platform", - NULL); - return !!platform_device; -} - -gboolean -meta_is_udev_device_boot_vga (GUdevDevice *device) -{ - g_autoptr (GUdevDevice) pci_device = NULL; - - pci_device = g_udev_device_get_parent_with_subsystem (device, "pci", NULL); - if (!pci_device) - return FALSE; - - return g_udev_device_get_sysfs_attr_as_int (pci_device, "boot_vga") == 1; -} - -static gboolean -meta_has_udev_device_tag (GUdevDevice *device, - const char *tag) -{ - const char * const * tags; - g_autoptr (GUdevDevice) platform_device = NULL; - - tags = g_udev_device_get_tags (device); - if (tags && g_strv_contains (tags, tag)) - return TRUE; - - platform_device = g_udev_device_get_parent_with_subsystem (device, - "platform", - NULL); - - if (platform_device) - return meta_has_udev_device_tag (platform_device, tag); - else - return FALSE; -} - -gboolean -meta_is_udev_device_disable_modifiers (GUdevDevice *device) -{ - return meta_has_udev_device_tag (device, - "mutter-device-disable-kms-modifiers"); -} - -gboolean -meta_is_udev_device_ignore (GUdevDevice *device) -{ - return meta_has_udev_device_tag (device, "mutter-device-ignore"); -} - -gboolean -meta_is_udev_device_preferred_primary (GUdevDevice *device) -{ - const char * const * tags; - - tags = g_udev_device_get_tags (device); - if (!tags) - return FALSE; - - return g_strv_contains (tags, "mutter-device-preferred-primary"); -} - -gboolean -meta_udev_is_drm_device (MetaUdev *udev, - GUdevDevice *device) -{ - const char *seat_id; - const char *device_type; - const char *device_seat; - - /* Filter out devices that are not character device, like card0-VGA-1. */ - if (g_udev_device_get_device_type (device) != G_UDEV_DEVICE_TYPE_CHAR) - return FALSE; - - device_type = g_udev_device_get_property (device, "DEVTYPE"); - if (g_strcmp0 (device_type, DRM_CARD_UDEV_DEVICE_TYPE) != 0) - return FALSE; - - device_seat = g_udev_device_get_property (device, "ID_SEAT"); - if (!device_seat) - { - /* When ID_SEAT is not set, it means seat0. */ - device_seat = "seat0"; - } - - /* Skip devices that do not belong to our seat. */ - seat_id = meta_backend_native_get_seat_id (udev->backend_native); - if (g_strcmp0 (seat_id, device_seat)) - return FALSE; - - return TRUE; -} - -GList * -meta_udev_list_drm_devices (MetaUdev *udev, - GError **error) -{ - g_autoptr (GUdevEnumerator) enumerator = NULL; - GList *devices; - GList *l; - - enumerator = g_udev_enumerator_new (udev->gudev_client); - - g_udev_enumerator_add_match_name (enumerator, "card*"); - g_udev_enumerator_add_match_tag (enumerator, "seat"); - - /* - * We need to explicitly match the subsystem for now. - * https://bugzilla.gnome.org/show_bug.cgi?id=773224 - */ - g_udev_enumerator_add_match_subsystem (enumerator, "drm"); - - devices = g_udev_enumerator_execute (enumerator); - if (!devices) - return NULL; - - for (l = devices; l;) - { - GUdevDevice *device = l->data; - GList *l_next = l->next; - - if (!meta_udev_is_drm_device (udev, device)) - { - g_object_unref (device); - devices = g_list_delete_link (devices, l); - } - - l = l_next; - } - - return devices; -} - -static void -on_uevent (GUdevClient *client, - const char *action, - GUdevDevice *device, - gpointer user_data) -{ - MetaUdev *udev = META_UDEV (user_data); - - if (!g_udev_device_get_device_file (device)) - return; - - if (g_str_equal (action, "add")) - g_signal_emit (udev, signals[DEVICE_ADDED], 0, device); - else if (g_str_equal (action, "remove")) - g_signal_emit (udev, signals[DEVICE_REMOVED], 0, device); - - if (g_udev_device_get_property_as_boolean (device, "HOTPLUG")) - g_signal_emit (udev, signals[HOTPLUG], 0); -} - -MetaUdev * -meta_udev_new (MetaBackendNative *backend_native) -{ - MetaUdev *udev; - - udev = g_object_new (META_TYPE_UDEV, NULL); - udev->backend_native = backend_native; - - return udev; -} - -static void -meta_udev_finalize (GObject *object) -{ - MetaUdev *udev = META_UDEV (object); - - g_clear_signal_handler (&udev->uevent_handler_id, udev->gudev_client); - g_clear_object (&udev->gudev_client); - - G_OBJECT_CLASS (meta_udev_parent_class)->finalize (object); -} - -static void -meta_udev_init (MetaUdev *udev) -{ - const char *subsystems[] = { "drm", NULL }; - - udev->gudev_client = g_udev_client_new (subsystems); - udev->uevent_handler_id = g_signal_connect (udev->gudev_client, - "uevent", - G_CALLBACK (on_uevent), udev); -} - -static void -meta_udev_class_init (MetaUdevClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_udev_finalize; - - signals[HOTPLUG] = - g_signal_new ("hotplug", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); - signals[DEVICE_ADDED] = - g_signal_new ("device-added", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 1, - G_UDEV_TYPE_DEVICE); - signals[DEVICE_REMOVED] = - g_signal_new ("device-removed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 1, - G_UDEV_TYPE_DEVICE); -} diff --git a/src/backends/native/meta-udev.h b/src/backends/native/meta-udev.h deleted file mode 100644 index 7b179329e..000000000 --- a/src/backends/native/meta-udev.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2018 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_UDEV_H -#define META_UDEV_H - -#include - -#include "backends/native/meta-backend-native-types.h" - -#define META_TYPE_UDEV (meta_udev_get_type ()) -G_DECLARE_FINAL_TYPE (MetaUdev, meta_udev, META, UDEV, GObject) - -gboolean meta_is_udev_device_platform_device (GUdevDevice *device); - -gboolean meta_is_udev_device_boot_vga (GUdevDevice *device); - -gboolean meta_is_udev_device_disable_modifiers (GUdevDevice *device); - -gboolean meta_is_udev_device_ignore (GUdevDevice *device); - -gboolean meta_is_udev_device_preferred_primary (GUdevDevice *device); - -gboolean meta_udev_is_drm_device (MetaUdev *udev, - GUdevDevice *device); - -GList * meta_udev_list_drm_devices (MetaUdev *udev, - GError **error); - -MetaUdev * meta_udev_new (MetaBackendNative *backend_native); - -#endif /* META_UDEV_H */ diff --git a/src/backends/native/meta-virtual-input-device-native.c b/src/backends/native/meta-virtual-input-device-native.c deleted file mode 100644 index d2d13748a..000000000 --- a/src/backends/native/meta-virtual-input-device-native.c +++ /dev/null @@ -1,1110 +0,0 @@ -/* - * Copyright (C) 2016 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 . - * - * Author: Jonas Ådahl - */ - -#include "config.h" - -#include -#include - -#include "backends/native/meta-input-thread.h" -#include "backends/native/meta-seat-native.h" -#include "backends/native/meta-virtual-input-device-native.h" -#include "clutter/clutter-mutter.h" -#include "meta/util.h" - -enum -{ - PROP_0, - - PROP_SEAT, - PROP_SLOT_BASE, - - PROP_LAST -}; - -static GParamSpec *obj_props[PROP_LAST]; - -typedef struct _ImplState ImplState; - -struct _ImplState -{ - ClutterInputDevice *device; - int button_count[KEY_CNT]; -}; - -struct _MetaVirtualInputDeviceNative -{ - ClutterVirtualInputDevice parent; - - MetaSeatNative *seat; - guint slot_base; - ImplState *impl_state; -}; - -typedef struct -{ - uint64_t time_us; - double x; - double y; -} MetaVirtualEventMotion; - -typedef struct -{ - uint64_t time_us; - uint32_t button; - ClutterButtonState button_state; -} MetaVirtualEventButton; - -typedef struct -{ - uint64_t time_us; - double dx; - double dy; - ClutterScrollDirection direction; - ClutterScrollSource scroll_source; - ClutterScrollFinishFlags finish_flags; -} MetaVirtualEventScroll; - -typedef struct -{ - uint64_t time_us; - uint32_t key; - ClutterKeyState key_state; -} MetaVirtualEventKey; - -typedef struct -{ - uint64_t time_us; - int device_slot; - double x; - double y; -} MetaVirtualEventTouch; - -G_DEFINE_TYPE (MetaVirtualInputDeviceNative, - meta_virtual_input_device_native, - CLUTTER_TYPE_VIRTUAL_INPUT_DEVICE) - -typedef enum _EvdevButtonType -{ - EVDEV_BUTTON_TYPE_NONE, - EVDEV_BUTTON_TYPE_KEY, - EVDEV_BUTTON_TYPE_BUTTON, -} EvdevButtonType; - -static int -update_button_count_in_impl (MetaVirtualInputDeviceNative *virtual_evdev, - uint32_t button, - uint32_t state) -{ - if (state) - return ++virtual_evdev->impl_state->button_count[button]; - else - return --virtual_evdev->impl_state->button_count[button]; -} - -static EvdevButtonType -get_button_type (uint16_t code) -{ - switch (code) - { - case BTN_TOOL_PEN: - case BTN_TOOL_RUBBER: - case BTN_TOOL_BRUSH: - case BTN_TOOL_PENCIL: - case BTN_TOOL_AIRBRUSH: - case BTN_TOOL_MOUSE: - case BTN_TOOL_LENS: - case BTN_TOOL_QUINTTAP: - case BTN_TOOL_DOUBLETAP: - case BTN_TOOL_TRIPLETAP: - case BTN_TOOL_QUADTAP: - case BTN_TOOL_FINGER: - case BTN_TOUCH: - return EVDEV_BUTTON_TYPE_NONE; - } - - if (code >= KEY_ESC && code <= KEY_MICMUTE) - return EVDEV_BUTTON_TYPE_KEY; - if (code >= BTN_MISC && code <= BTN_GEAR_UP) - return EVDEV_BUTTON_TYPE_BUTTON; - if (code >= KEY_OK && code <= KEY_LIGHTS_TOGGLE) - return EVDEV_BUTTON_TYPE_KEY; - if (code >= BTN_DPAD_UP && code <= BTN_DPAD_RIGHT) - return EVDEV_BUTTON_TYPE_BUTTON; - if (code >= KEY_ALS_TOGGLE && code <= KEY_KBDINPUTASSIST_CANCEL) - return EVDEV_BUTTON_TYPE_KEY; - if (code >= BTN_TRIGGER_HAPPY && code <= BTN_TRIGGER_HAPPY40) - return EVDEV_BUTTON_TYPE_BUTTON; - return EVDEV_BUTTON_TYPE_NONE; -} - -static gboolean -release_device_in_impl (GTask *task) -{ - ImplState *impl_state = g_task_get_task_data (task); - MetaInputDeviceNative *device_native; - MetaSeatImpl *seat_impl; - int code; - uint64_t time_us; - ClutterEvent *device_event; - - device_native = META_INPUT_DEVICE_NATIVE (impl_state->device); - seat_impl = meta_input_device_native_get_seat_impl (device_native); - time_us = g_get_monotonic_time (); - - meta_topic (META_DEBUG_INPUT, - "Releasing pressed buttons while destroying virtual input device " - "(device %p)", device_native); - - for (code = 0; code < G_N_ELEMENTS (impl_state->button_count); code++) - { - if (impl_state->button_count[code] == 0) - continue; - - switch (get_button_type (code)) - { - case EVDEV_BUTTON_TYPE_KEY: - meta_seat_impl_notify_key_in_impl (seat_impl, - impl_state->device, - time_us, - code, - CLUTTER_KEY_STATE_RELEASED, - TRUE); - break; - case EVDEV_BUTTON_TYPE_BUTTON: - meta_seat_impl_notify_button_in_impl (seat_impl, - impl_state->device, - time_us, - code, - CLUTTER_BUTTON_STATE_RELEASED); - break; - case EVDEV_BUTTON_TYPE_NONE: - g_assert_not_reached (); - } - } - - device_event = clutter_event_new (CLUTTER_DEVICE_REMOVED); - clutter_event_set_device (device_event, impl_state->device); - _clutter_event_push (device_event, FALSE); - - g_clear_object (&impl_state->device); - g_task_return_boolean (task, TRUE); - - return G_SOURCE_REMOVE; -} - -static gboolean -notify_relative_motion_in_impl (GTask *task) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - g_task_get_source_object (task); - MetaSeatImpl *seat = virtual_evdev->seat->impl; - MetaVirtualEventMotion *event = g_task_get_task_data (task); - - if (event->time_us == CLUTTER_CURRENT_TIME) - event->time_us = g_get_monotonic_time (); - - meta_seat_impl_notify_relative_motion_in_impl (seat, - virtual_evdev->impl_state->device, - event->time_us, - event->x, event->y, - event->x, event->y); - g_task_return_boolean (task, TRUE); - return G_SOURCE_REMOVE; -} - -static void -meta_virtual_input_device_native_notify_relative_motion (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - double dx, - double dy) -{ - MetaVirtualEventMotion *event; - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); - GTask *task; - - g_return_if_fail (virtual_evdev->impl_state->device != NULL); - - event = g_new0 (MetaVirtualEventMotion, 1); - event->time_us = time_us; - event->x = dx; - event->y = dy; - - task = g_task_new (virtual_device, NULL, NULL, NULL); - g_task_set_task_data (task, event, g_free); - meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task, - (GSourceFunc) notify_relative_motion_in_impl); - g_object_unref (task); -} - -static gboolean -notify_absolute_motion_in_impl (GTask *task) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - g_task_get_source_object (task); - MetaSeatImpl *seat = virtual_evdev->seat->impl; - MetaVirtualEventMotion *event = g_task_get_task_data (task); - - if (event->time_us == CLUTTER_CURRENT_TIME) - event->time_us = g_get_monotonic_time (); - - meta_seat_impl_notify_absolute_motion_in_impl (seat, - virtual_evdev->impl_state->device, - event->time_us, - event->x, event->y, - NULL); - g_task_return_boolean (task, TRUE); - return G_SOURCE_REMOVE; -} - -static void -meta_virtual_input_device_native_notify_absolute_motion (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - double x, - double y) -{ - MetaVirtualEventMotion *event; - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); - GTask *task; - - g_return_if_fail (virtual_evdev->impl_state->device != NULL); - - event = g_new0 (MetaVirtualEventMotion, 1); - event->time_us = time_us; - event->x = x; - event->y = y; - - task = g_task_new (virtual_device, NULL, NULL, NULL); - g_task_set_task_data (task, event, g_free); - meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task, - (GSourceFunc) notify_absolute_motion_in_impl); - g_object_unref (task); -} - -static int -translate_to_evdev_button (int clutter_button) -{ - switch (clutter_button) - { - case CLUTTER_BUTTON_PRIMARY: - return BTN_LEFT; - case CLUTTER_BUTTON_SECONDARY: - return BTN_RIGHT; - case CLUTTER_BUTTON_MIDDLE: - return BTN_MIDDLE; - default: - /* - * For compatibility reasons, all additional buttons go after the old - * 4-7 scroll ones. - */ - return clutter_button + (BTN_LEFT - 1) - 4; - } -} - -static gboolean -notify_button_in_impl (GTask *task) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - g_task_get_source_object (task); - MetaSeatImpl *seat = virtual_evdev->seat->impl; - MetaVirtualEventButton *event = g_task_get_task_data (task); - int button_count; - int evdev_button; - - if (event->time_us == CLUTTER_CURRENT_TIME) - event->time_us = g_get_monotonic_time (); - - evdev_button = translate_to_evdev_button (event->button); - - if (get_button_type (evdev_button) != EVDEV_BUTTON_TYPE_BUTTON) - { - g_warning ("Unknown/invalid virtual device button 0x%x pressed", - evdev_button); - goto out; - } - - button_count = update_button_count_in_impl (virtual_evdev, evdev_button, - event->button_state); - if (button_count < 0 || button_count > 1) - { - g_warning ("Received multiple virtual 0x%x button %s (ignoring)", evdev_button, - event->button_state == CLUTTER_BUTTON_STATE_PRESSED ? - "presses" : "releases"); - update_button_count_in_impl (virtual_evdev, evdev_button, 1 - event->button_state); - goto out; - } - - meta_topic (META_DEBUG_INPUT, - "Emitting virtual button-%s of button 0x%x (device %p)", - event->button_state == CLUTTER_BUTTON_STATE_PRESSED ? - "press" : "release", - evdev_button, virtual_evdev); - - meta_seat_impl_notify_button_in_impl (seat, - virtual_evdev->impl_state->device, - event->time_us, - evdev_button, - event->button_state); - out: - g_task_return_boolean (task, TRUE); - return G_SOURCE_REMOVE; -} - -static void -meta_virtual_input_device_native_notify_button (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - uint32_t button, - ClutterButtonState button_state) -{ - MetaVirtualEventButton *event; - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); - GTask *task; - - g_return_if_fail (virtual_evdev->impl_state->device != NULL); - - event = g_new0 (MetaVirtualEventButton, 1); - event->time_us = time_us; - event->button = button; - event->button_state = button_state; - - task = g_task_new (virtual_device, NULL, NULL, NULL); - g_task_set_task_data (task, event, g_free); - meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task, - (GSourceFunc) notify_button_in_impl); - g_object_unref (task); -} - -static gboolean -notify_key_in_impl (GTask *task) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - g_task_get_source_object (task); - MetaSeatImpl *seat = virtual_evdev->seat->impl; - MetaVirtualEventKey *event = g_task_get_task_data (task); - int key_count; - - if (event->time_us == CLUTTER_CURRENT_TIME) - event->time_us = g_get_monotonic_time (); - - if (get_button_type (event->key) != EVDEV_BUTTON_TYPE_KEY) - { - g_warning ("Unknown/invalid virtual device key 0x%x pressed", event->key); - goto out; - } - - key_count = update_button_count_in_impl (virtual_evdev, event->key, event->key_state); - if (key_count < 0 || key_count > 1) - { - g_warning ("Received multiple virtual 0x%x key %s (ignoring)", event->key, - event->key_state == CLUTTER_KEY_STATE_PRESSED ? - "presses" : "releases"); - update_button_count_in_impl (virtual_evdev, event->key, 1 - event->key_state); - goto out; - } - - meta_topic (META_DEBUG_INPUT, - "Emitting virtual key-%s of key 0x%x (device %p)", - event->key_state == CLUTTER_KEY_STATE_PRESSED ? "press" : "release", - event->key, virtual_evdev); - - meta_seat_impl_notify_key_in_impl (seat, - virtual_evdev->impl_state->device, - event->time_us, - event->key, - event->key_state, - TRUE); - - out: - g_task_return_boolean (task, TRUE); - return G_SOURCE_REMOVE; -} - -static void -meta_virtual_input_device_native_notify_key (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - uint32_t key, - ClutterKeyState key_state) -{ - MetaVirtualEventKey *event; - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); - GTask *task; - - g_return_if_fail (virtual_evdev->impl_state->device != NULL); - - event = g_new0 (MetaVirtualEventKey, 1); - event->time_us = time_us; - event->key = key; - event->key_state = key_state; - - task = g_task_new (virtual_device, NULL, NULL, NULL); - g_task_set_task_data (task, event, g_free); - meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task, - (GSourceFunc) notify_key_in_impl); - g_object_unref (task); -} - -static gboolean -pick_keycode_for_keyval_in_current_group_in_impl (ClutterVirtualInputDevice *virtual_device, - guint keyval, - guint *keycode_out, - guint *level_out) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); - ClutterBackend *backend; - ClutterKeymap *keymap; - struct xkb_keymap *xkb_keymap; - struct xkb_state *state; - guint keycode, layout; - xkb_keycode_t min_keycode, max_keycode; - - backend = clutter_get_default_backend (); - keymap = clutter_seat_get_keymap (clutter_backend_get_default_seat (backend)); - xkb_keymap = meta_keymap_native_get_keyboard_map_in_impl (META_KEYMAP_NATIVE (keymap)); - state = meta_seat_impl_get_xkb_state_in_impl (virtual_evdev->seat->impl); - - layout = xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE); - min_keycode = xkb_keymap_min_keycode (xkb_keymap); - max_keycode = xkb_keymap_max_keycode (xkb_keymap); - for (keycode = min_keycode; keycode < max_keycode; keycode++) - { - gint num_levels, level; - num_levels = xkb_keymap_num_levels_for_key (xkb_keymap, keycode, layout); - for (level = 0; level < num_levels; level++) - { - const xkb_keysym_t *syms; - gint num_syms, sym; - num_syms = xkb_keymap_key_get_syms_by_level (xkb_keymap, keycode, layout, level, &syms); - for (sym = 0; sym < num_syms; sym++) - { - if (syms[sym] == keyval) - { - *keycode_out = keycode; - if (level_out) - *level_out = level; - return TRUE; - } - } - } - } - - return FALSE; -} - -static void -apply_level_modifiers_in_impl (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - uint32_t level, - uint32_t key_state) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); - guint keysym, keycode, evcode; - - if (level == 0) - return; - - if (level == 1) - { - keysym = XKB_KEY_Shift_L; - } - else if (level == 2) - { - keysym = XKB_KEY_ISO_Level3_Shift; - } - else - { - g_warning ("Unhandled level: %d", level); - return; - } - - if (!pick_keycode_for_keyval_in_current_group_in_impl (virtual_device, keysym, - &keycode, NULL)) - return; - - evcode = meta_xkb_keycode_to_evdev (keycode); - - meta_topic (META_DEBUG_INPUT, - "Emitting virtual key-%s of modifier key 0x%x (device %p)", - key_state == CLUTTER_KEY_STATE_PRESSED ? "press" : "release", - evcode, virtual_device); - - meta_seat_impl_notify_key_in_impl (virtual_evdev->seat->impl, - virtual_evdev->impl_state->device, - time_us, - evcode, - key_state, - TRUE); -} - -static gboolean -notify_keyval_in_impl (GTask *task) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - g_task_get_source_object (task); - ClutterVirtualInputDevice *virtual_device = - CLUTTER_VIRTUAL_INPUT_DEVICE (virtual_evdev); - MetaSeatImpl *seat = virtual_evdev->seat->impl; - MetaVirtualEventKey *event = g_task_get_task_data (task); - int key_count; - guint keycode = 0, level = 0, evcode = 0; - - if (event->time_us == CLUTTER_CURRENT_TIME) - event->time_us = g_get_monotonic_time (); - - if (!pick_keycode_for_keyval_in_current_group_in_impl (virtual_device, - event->key, - &keycode, &level)) - { - g_warning ("No keycode found for keyval %x in current group", event->key); - goto out; - } - - evcode = meta_xkb_keycode_to_evdev (keycode); - - if (get_button_type (evcode) != EVDEV_BUTTON_TYPE_KEY) - { - g_warning ("Unknown/invalid virtual device key 0x%x pressed", evcode); - goto out; - } - - key_count = update_button_count_in_impl (virtual_evdev, evcode, event->key_state); - if (key_count < 0 || key_count > 1) - { - g_warning ("Received multiple virtual 0x%x key %s (ignoring)", evcode, - event->key_state == CLUTTER_KEY_STATE_PRESSED ? - "presses" : "releases"); - update_button_count_in_impl (virtual_evdev, evcode, 1 - event->key_state); - goto out; - } - - meta_topic (META_DEBUG_INPUT, - "Emitting virtual key-%s of key 0x%x with modifier level %d, " - "press count %d (device %p)", - event->key_state == CLUTTER_KEY_STATE_PRESSED ? "press" : "release", - evcode, level, key_count, virtual_evdev); - - if (event->key_state) - { - apply_level_modifiers_in_impl (virtual_device, event->time_us, - level, event->key_state); - } - - meta_seat_impl_notify_key_in_impl (seat, - virtual_evdev->impl_state->device, - event->time_us, - evcode, - event->key_state, - TRUE); - - if (!event->key_state) - { - apply_level_modifiers_in_impl (virtual_device, event->time_us, - level, event->key_state); - } - - out: - g_task_return_boolean (task, TRUE); - return G_SOURCE_REMOVE; -} - -static void -meta_virtual_input_device_native_notify_keyval (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - uint32_t keyval, - ClutterKeyState key_state) -{ - MetaVirtualEventKey *event; - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); - GTask *task; - - g_return_if_fail (virtual_evdev->impl_state->device != NULL); - - event = g_new0 (MetaVirtualEventKey, 1); - event->time_us = time_us; - event->key = keyval; - event->key_state = key_state; - - task = g_task_new (virtual_device, NULL, NULL, NULL); - g_task_set_task_data (task, event, g_free); - meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task, - (GSourceFunc) notify_keyval_in_impl); - g_object_unref (task); -} - -static void -direction_to_discrete (ClutterScrollDirection direction, - double *discrete_dx, - double *discrete_dy) -{ - switch (direction) - { - case CLUTTER_SCROLL_UP: - *discrete_dx = 0.0; - *discrete_dy = -1.0; - break; - case CLUTTER_SCROLL_DOWN: - *discrete_dx = 0.0; - *discrete_dy = 1.0; - break; - case CLUTTER_SCROLL_LEFT: - *discrete_dx = -1.0; - *discrete_dy = 0.0; - break; - case CLUTTER_SCROLL_RIGHT: - *discrete_dx = 1.0; - *discrete_dy = 0.0; - break; - case CLUTTER_SCROLL_SMOOTH: - g_assert_not_reached (); - break; - } -} - -static gboolean -notify_discrete_scroll_in_impl (GTask *task) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - g_task_get_source_object (task); - MetaSeatImpl *seat = virtual_evdev->seat->impl; - MetaVirtualEventScroll *event = g_task_get_task_data (task); - double discrete_dx = 0.0, discrete_dy = 0.0; - - if (event->time_us == CLUTTER_CURRENT_TIME) - event->time_us = g_get_monotonic_time (); - - direction_to_discrete (event->direction, &discrete_dx, &discrete_dy); - - meta_seat_impl_notify_discrete_scroll_in_impl (seat, - virtual_evdev->impl_state->device, - event->time_us, - discrete_dx, discrete_dy, - event->scroll_source); - - g_task_return_boolean (task, TRUE); - return G_SOURCE_REMOVE; -} - -static void -meta_virtual_input_device_native_notify_discrete_scroll (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - ClutterScrollDirection direction, - ClutterScrollSource scroll_source) -{ - MetaVirtualEventScroll *event; - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); - GTask *task; - - g_return_if_fail (virtual_evdev->impl_state->device != NULL); - - event = g_new0 (MetaVirtualEventScroll, 1); - event->time_us = time_us; - event->direction = direction; - event->scroll_source = scroll_source; - - task = g_task_new (virtual_device, NULL, NULL, NULL); - g_task_set_task_data (task, event, g_free); - meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task, - (GSourceFunc) notify_discrete_scroll_in_impl); - g_object_unref (task); -} - -static gboolean -notify_scroll_continuous_in_impl (GTask *task) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - g_task_get_source_object (task); - MetaSeatImpl *seat = virtual_evdev->seat->impl; - MetaVirtualEventScroll *event = g_task_get_task_data (task); - - if (event->time_us == CLUTTER_CURRENT_TIME) - event->time_us = g_get_monotonic_time (); - - meta_seat_impl_notify_scroll_continuous_in_impl (seat, - virtual_evdev->impl_state->device, - event->time_us, - event->dx, event->dy, - event->scroll_source, - CLUTTER_SCROLL_FINISHED_NONE); - g_task_return_boolean (task, TRUE); - return G_SOURCE_REMOVE; -} - -static void -meta_virtual_input_device_native_notify_scroll_continuous (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - double dx, - double dy, - ClutterScrollSource scroll_source, - ClutterScrollFinishFlags finish_flags) -{ - MetaVirtualEventScroll *event; - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); - GTask *task; - - g_return_if_fail (virtual_evdev->impl_state->device != NULL); - - event = g_new0 (MetaVirtualEventScroll, 1); - event->time_us = time_us; - event->dx = dx; - event->dy = dy; - event->scroll_source = scroll_source; - event->finish_flags = finish_flags; - - task = g_task_new (virtual_device, NULL, NULL, NULL); - g_task_set_task_data (task, event, g_free); - meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task, - (GSourceFunc) notify_scroll_continuous_in_impl); - g_object_unref (task); -} - -static gboolean -notify_touch_down_in_impl (GTask *task) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - g_task_get_source_object (task); - MetaSeatImpl *seat = virtual_evdev->seat->impl; - MetaVirtualEventTouch *event = g_task_get_task_data (task); - MetaTouchState *touch_state; - - if (event->time_us == CLUTTER_CURRENT_TIME) - event->time_us = g_get_monotonic_time (); - - touch_state = meta_seat_impl_acquire_touch_state_in_impl (seat, - event->device_slot); - if (!touch_state) - goto out; - - touch_state->coords.x = event->x; - touch_state->coords.y = event->y; - - meta_seat_impl_notify_touch_event_in_impl (seat, - virtual_evdev->impl_state->device, - CLUTTER_TOUCH_BEGIN, - event->time_us, - touch_state->seat_slot, - touch_state->coords.x, - touch_state->coords.y); - - out: - g_task_return_boolean (task, TRUE); - return G_SOURCE_REMOVE; -} - -static void -meta_virtual_input_device_native_notify_touch_down (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - int device_slot, - double x, - double y) -{ - MetaVirtualEventTouch *event; - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); - GTask *task; - - g_return_if_fail (virtual_evdev->impl_state->device != NULL); - - event = g_new0 (MetaVirtualEventTouch, 1); - event->time_us = time_us; - event->device_slot = virtual_evdev->slot_base + (guint) device_slot; - event->x = x; - event->y = y; - - task = g_task_new (virtual_device, NULL, NULL, NULL); - g_task_set_task_data (task, event, g_free); - meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task, - (GSourceFunc) notify_touch_down_in_impl); - g_object_unref (task); -} - -static gboolean -notify_touch_motion_in_impl (GTask *task) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - g_task_get_source_object (task); - MetaSeatImpl *seat = virtual_evdev->seat->impl; - MetaVirtualEventTouch *event = g_task_get_task_data (task); - MetaTouchState *touch_state; - - if (event->time_us == CLUTTER_CURRENT_TIME) - event->time_us = g_get_monotonic_time (); - - touch_state = meta_seat_impl_lookup_touch_state_in_impl (seat, - event->device_slot); - if (!touch_state) - goto out; - - touch_state->coords.x = event->x; - touch_state->coords.y = event->y; - - meta_seat_impl_notify_touch_event_in_impl (seat, - virtual_evdev->impl_state->device, - CLUTTER_TOUCH_UPDATE, - event->time_us, - touch_state->seat_slot, - touch_state->coords.x, - touch_state->coords.y); - - out: - g_task_return_boolean (task, TRUE); - return G_SOURCE_REMOVE; -} - -static void -meta_virtual_input_device_native_notify_touch_motion (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - int device_slot, - double x, - double y) -{ - MetaVirtualEventTouch *event; - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); - GTask *task; - - g_return_if_fail (virtual_evdev->impl_state->device != NULL); - - event = g_new0 (MetaVirtualEventTouch, 1); - event->time_us = time_us; - event->device_slot = virtual_evdev->slot_base + (guint) device_slot; - event->x = x; - event->y = y; - - task = g_task_new (virtual_device, NULL, NULL, NULL); - g_task_set_task_data (task, event, g_free); - meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task, - (GSourceFunc) notify_touch_motion_in_impl); - g_object_unref (task); -} - -static gboolean -notify_touch_up_in_impl (GTask *task) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - g_task_get_source_object (task); - MetaSeatImpl *seat = virtual_evdev->seat->impl; - MetaVirtualEventTouch *event = g_task_get_task_data (task); - MetaTouchState *touch_state; - - if (event->time_us == CLUTTER_CURRENT_TIME) - event->time_us = g_get_monotonic_time (); - - touch_state = meta_seat_impl_lookup_touch_state_in_impl (seat, - event->device_slot); - if (!touch_state) - goto out; - - meta_seat_impl_notify_touch_event_in_impl (seat, - virtual_evdev->impl_state->device, - CLUTTER_TOUCH_END, - event->time_us, - touch_state->seat_slot, - touch_state->coords.x, - touch_state->coords.y); - - meta_seat_impl_release_touch_state_in_impl (virtual_evdev->seat->impl, - touch_state->seat_slot); - - out: - g_task_return_boolean (task, TRUE); - return G_SOURCE_REMOVE; -} - -static void -meta_virtual_input_device_native_notify_touch_up (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - int device_slot) -{ - MetaVirtualEventTouch *event; - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device); - GTask *task; - - g_return_if_fail (virtual_evdev->impl_state->device != NULL); - - event = g_new0 (MetaVirtualEventTouch, 1); - event->time_us = time_us; - event->device_slot = virtual_evdev->slot_base + (guint) device_slot; - - task = g_task_new (virtual_device, NULL, NULL, NULL); - g_task_set_task_data (task, event, g_free); - meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task, - (GSourceFunc) notify_touch_up_in_impl); - g_object_unref (task); -} - -static void -meta_virtual_input_device_native_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (object); - - switch (prop_id) - { - case PROP_SEAT: - g_value_set_pointer (value, virtual_evdev->seat); - break; - case PROP_SLOT_BASE: - g_value_set_uint (value, virtual_evdev->slot_base); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_virtual_input_device_native_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (object); - - switch (prop_id) - { - case PROP_SEAT: - virtual_evdev->seat = g_value_get_pointer (value); - break; - case PROP_SLOT_BASE: - virtual_evdev->slot_base = g_value_get_uint (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_virtual_input_device_native_constructed (GObject *object) -{ - ClutterVirtualInputDevice *virtual_device = - CLUTTER_VIRTUAL_INPUT_DEVICE (object); - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (object); - ClutterInputDeviceType device_type; - ClutterEvent *device_event = NULL; - - device_type = clutter_virtual_input_device_get_device_type (virtual_device); - - meta_topic (META_DEBUG_INPUT, - "Creating new virtual input device of type %d (%p)", - device_type, virtual_device); - - virtual_evdev->impl_state = g_new0 (ImplState, 1); - virtual_evdev->impl_state->device = - meta_input_device_native_new_virtual (virtual_evdev->seat->impl, - device_type, - CLUTTER_INPUT_MODE_PHYSICAL); - - device_event = clutter_event_new (CLUTTER_DEVICE_ADDED); - clutter_event_set_device (device_event, virtual_evdev->impl_state->device); - _clutter_event_push (device_event, FALSE); -} - -static void -impl_state_free (ImplState *impl_state) -{ - g_warn_if_fail (!impl_state->device); - g_free (impl_state); -} - -static void -meta_virtual_input_device_native_dispose (GObject *object) -{ - ClutterVirtualInputDevice *virtual_device = - CLUTTER_VIRTUAL_INPUT_DEVICE (object); - MetaVirtualInputDeviceNative *virtual_evdev = - META_VIRTUAL_INPUT_DEVICE_NATIVE (object); - GObjectClass *object_class = - G_OBJECT_CLASS (meta_virtual_input_device_native_parent_class); - - if (virtual_evdev->impl_state) - { - GTask *task; - - task = g_task_new (virtual_device, NULL, NULL, NULL); - g_task_set_task_data (task, virtual_evdev->impl_state, - (GDestroyNotify) impl_state_free); - meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task, - (GSourceFunc) release_device_in_impl); - g_object_unref (task); - - virtual_evdev->impl_state = NULL; - } - - meta_seat_native_release_touch_slots (virtual_evdev->seat, - virtual_evdev->slot_base); - - object_class->dispose (object); -} - -static void -meta_virtual_input_device_native_init (MetaVirtualInputDeviceNative *virtual_device_evdev) -{ -} - -static void -meta_virtual_input_device_native_class_init (MetaVirtualInputDeviceNativeClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - ClutterVirtualInputDeviceClass *virtual_input_device_class = - CLUTTER_VIRTUAL_INPUT_DEVICE_CLASS (klass); - - object_class->get_property = meta_virtual_input_device_native_get_property; - object_class->set_property = meta_virtual_input_device_native_set_property; - object_class->constructed = meta_virtual_input_device_native_constructed; - object_class->dispose = meta_virtual_input_device_native_dispose; - - virtual_input_device_class->notify_relative_motion = meta_virtual_input_device_native_notify_relative_motion; - virtual_input_device_class->notify_absolute_motion = meta_virtual_input_device_native_notify_absolute_motion; - virtual_input_device_class->notify_button = meta_virtual_input_device_native_notify_button; - virtual_input_device_class->notify_key = meta_virtual_input_device_native_notify_key; - virtual_input_device_class->notify_keyval = meta_virtual_input_device_native_notify_keyval; - virtual_input_device_class->notify_discrete_scroll = meta_virtual_input_device_native_notify_discrete_scroll; - virtual_input_device_class->notify_scroll_continuous = meta_virtual_input_device_native_notify_scroll_continuous; - virtual_input_device_class->notify_touch_down = meta_virtual_input_device_native_notify_touch_down; - virtual_input_device_class->notify_touch_motion = meta_virtual_input_device_native_notify_touch_motion; - virtual_input_device_class->notify_touch_up = meta_virtual_input_device_native_notify_touch_up; - - obj_props[PROP_SEAT] = g_param_spec_pointer ("seat", - "Seat", - "Seat", - CLUTTER_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - obj_props[PROP_SLOT_BASE] = g_param_spec_uint ("slot-base", - "Slot base", - "Base for touch slots", - 0, G_MAXUINT, 0, - CLUTTER_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - g_object_class_install_properties (object_class, PROP_LAST, obj_props); -} diff --git a/src/backends/native/meta-virtual-input-device-native.h b/src/backends/native/meta-virtual-input-device-native.h deleted file mode 100644 index 28d218abb..000000000 --- a/src/backends/native/meta-virtual-input-device-native.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2016 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 . - * - * Author: Jonas Ådahl - */ - -#ifndef META_VIRTUAL_INPUT_DEVICE_NATIVE_H -#define META_VIRTUAL_INPUT_DEVICE_NATIVE_H - -#include "clutter/clutter-virtual-input-device.h" - -#define META_TYPE_VIRTUAL_INPUT_DEVICE_NATIVE (meta_virtual_input_device_native_get_type ()) -G_DECLARE_FINAL_TYPE (MetaVirtualInputDeviceNative, - meta_virtual_input_device_native, - META, VIRTUAL_INPUT_DEVICE_NATIVE, - ClutterVirtualInputDevice) - -#endif /* META_VIRTUAL_INPUT_DEVICE_NATIVE_H */ diff --git a/src/backends/native/meta-virtual-monitor-native.c b/src/backends/native/meta-virtual-monitor-native.c deleted file mode 100644 index 3f81f4180..000000000 --- a/src/backends/native/meta-virtual-monitor-native.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2021 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "backends/native/meta-virtual-monitor-native.h" - -#include "backends/native/meta-crtc-mode-virtual.h" -#include "backends/native/meta-crtc-virtual.h" -#include "backends/native/meta-output-virtual.h" - -struct _MetaVirtualMonitorNative -{ - MetaVirtualMonitor parent; - - uint64_t id; -}; - -#define VIRTUAL_OUTPUT_ID_BIT (((uint64_t) 1) << 63) - -G_DEFINE_TYPE (MetaVirtualMonitorNative, meta_virtual_monitor_native, - META_TYPE_VIRTUAL_MONITOR) - -uint64_t -meta_virtual_monitor_native_get_id (MetaVirtualMonitorNative *virtual_monitor_native) -{ - return virtual_monitor_native->id; -} - -MetaVirtualMonitorNative * -meta_virtual_monitor_native_new (uint64_t id, - const MetaVirtualMonitorInfo *info) -{ - MetaVirtualMonitorNative *virtual_monitor_native; - MetaCrtcVirtual *crtc_virtual; - MetaCrtcModeVirtual *crtc_mode_virtual; - MetaOutputVirtual *output_virtual; - - crtc_virtual = meta_crtc_virtual_new (id); - crtc_mode_virtual = meta_crtc_mode_virtual_new (id, info); - output_virtual = meta_output_virtual_new (id, info, - crtc_virtual, - crtc_mode_virtual); - - virtual_monitor_native = g_object_new (META_TYPE_VIRTUAL_MONITOR_NATIVE, - "crtc", crtc_virtual, - "crtc-mode", crtc_mode_virtual, - "output", output_virtual, - NULL); - virtual_monitor_native->id = id; - - return virtual_monitor_native; -} - -static void -meta_virtual_monitor_native_init (MetaVirtualMonitorNative *virtual_monitor_native) -{ -} - -static void -meta_virtual_monitor_native_class_init (MetaVirtualMonitorNativeClass *klass) -{ -} diff --git a/src/backends/native/meta-virtual-monitor-native.h b/src/backends/native/meta-virtual-monitor-native.h deleted file mode 100644 index d1a0ced64..000000000 --- a/src/backends/native/meta-virtual-monitor-native.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2021 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_VIRTUAL_MONITOR_NATIVE_H -#define META_VIRTUAL_MONITOR_NATIVE_H - -#include - -#include "backends/meta-virtual-monitor.h" -#include "backends/meta-backend-types.h" - -#define META_TYPE_VIRTUAL_MONITOR_NATIVE (meta_virtual_monitor_native_get_type ()) -G_DECLARE_FINAL_TYPE (MetaVirtualMonitorNative, meta_virtual_monitor_native, - META, VIRTUAL_MONITOR_NATIVE, - MetaVirtualMonitor) - -uint64_t meta_virtual_monitor_native_get_id (MetaVirtualMonitorNative *virtual_monitor_native); - -MetaCrtcMode * meta_virtual_monitor_native_get_crtc_mode (MetaVirtualMonitorNative *virtual_monitor_native); - -MetaCrtc * meta_virtual_monitor_native_get_crtc (MetaVirtualMonitorNative *virtual_monitor_native); - -MetaOutput * meta_virtual_monitor_native_get_output (MetaVirtualMonitorNative *virtual_monitor_native); - -MetaVirtualMonitorNative * meta_virtual_monitor_native_new (uint64_t id, - const MetaVirtualMonitorInfo *info); - -#endif /* META_VIRTUAL_MONITOR_NATIVE_H */ diff --git a/src/backends/native/meta-xkb-utils.c b/src/backends/native/meta-xkb-utils.c deleted file mode 100644 index 45f89bec7..000000000 --- a/src/backends/native/meta-xkb-utils.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2010 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 . - - * Authors: - * Kristian Høgsberg - * Damien Lespiau - */ - -#include "config.h" - -#include "backends/native/meta-xkb-utils.h" -#include "clutter/clutter-keysyms.h" -#include "clutter/clutter-mutter.h" - -/* - * _clutter_event_new_from_evdev: Create a new Clutter ClutterKeyEvent - * @device: a ClutterInputDevice - * @xkb: XKB rules to translate the event - * @_time: timestamp of the event - * @key: a key code coming from a Linux input device - * @state: TRUE if a press event, FALSE if a release event - * @modifer_state: in/out - * - * Translate @key to a #ClutterKeyEvent using rules from xbbcommon. - * - * Return value: the new #ClutterEvent - */ -ClutterEvent * -meta_key_event_new_from_evdev (ClutterInputDevice *device, - ClutterInputDevice *core_device, - struct xkb_state *xkb_state, - uint32_t button_state, - uint32_t _time, - xkb_keycode_t key, - uint32_t state) -{ - ClutterEvent *event; - xkb_keysym_t sym; - const xkb_keysym_t *syms; - char buffer[8]; - int n; - - if (state) - event = clutter_event_new (CLUTTER_KEY_PRESS); - else - event = clutter_event_new (CLUTTER_KEY_RELEASE); - - /* We use a fixed offset of 8 because evdev starts KEY_* numbering from - * 0, whereas X11's minimum keycode, for really stupid reasons, is 8. - * So the evdev XKB rules are based on the keycodes all being shifted - * upwards by 8. */ - key = meta_xkb_evdev_to_keycode (key); - - n = xkb_key_get_syms (xkb_state, key, &syms); - if (n == 1) - sym = syms[0]; - else - sym = XKB_KEY_NoSymbol; - - event->key.time = _time; - meta_xkb_translate_state (event, xkb_state, button_state); - event->key.hardware_keycode = key; - event->key.keyval = sym; - clutter_event_set_device (event, core_device); - clutter_event_set_source_device (event, device); - - n = xkb_keysym_to_utf8 (sym, buffer, sizeof (buffer)); - - if (n == 0) - { - /* not printable */ - event->key.unicode_value = (gunichar) '\0'; - } - else - { - event->key.unicode_value = g_utf8_get_char_validated (buffer, n); - if (event->key.unicode_value == -1 || event->key.unicode_value == -2) - event->key.unicode_value = (gunichar) '\0'; - } - - return event; -} - -void -meta_xkb_translate_state (ClutterEvent *event, - struct xkb_state *state, - uint32_t button_state) -{ - _clutter_event_set_state_full (event, - button_state, - xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED), - xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED), - xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED), - xkb_state_serialize_mods (state, XKB_STATE_MODS_EFFECTIVE) | button_state); -} - -ClutterModifierType -meta_xkb_translate_modifiers (struct xkb_state *state, - ClutterModifierType button_state) -{ - ClutterModifierType modifiers; - - modifiers = xkb_state_serialize_mods (state, XKB_STATE_MODS_EFFECTIVE); - modifiers |= button_state; - - return modifiers; -} - -uint32_t -meta_xkb_keycode_to_evdev (uint32_t xkb_keycode) -{ - /* The keycodes from the evdev backend are almost evdev - * keycodes: we use the evdev keycode file, but xkb rules have an - * offset by 8. See the comment in _clutter_key_event_new_from_evdev() - */ - return xkb_keycode - 8; -} - -uint32_t -meta_xkb_evdev_to_keycode (uint32_t evcode) -{ - /* The inverse of meta_xkb_keycode_to_evdev */ - return evcode + 8; -} diff --git a/src/backends/native/meta-xkb-utils.h b/src/backends/native/meta-xkb-utils.h deleted file mode 100644 index d605813e6..000000000 --- a/src/backends/native/meta-xkb-utils.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2010 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 . - - * Authors: - * Damien Lespiau - */ - -#ifndef META_XKB_UTILS_H -#define META_XKB_UTILS_H - -#include - -#include "clutter/clutter.h" - -ClutterEvent * meta_key_event_new_from_evdev (ClutterInputDevice *device, - ClutterInputDevice *core_keyboard, - struct xkb_state *xkb_state, - uint32_t button_state, - uint32_t _time, - uint32_t key, - uint32_t state); -void meta_xkb_translate_state (ClutterEvent *event, - struct xkb_state *xkb_state, - uint32_t button_state); -ClutterModifierType meta_xkb_translate_modifiers (struct xkb_state *state, - ClutterModifierType button_state); -uint32_t meta_xkb_keycode_to_evdev (uint32_t hardware_keycode); -uint32_t meta_xkb_evdev_to_keycode (uint32_t evcode); - -#endif /* META_XKB_UTILS_H */ diff --git a/src/backends/x11/cm/meta-backend-x11-cm.c b/src/backends/x11/cm/meta-backend-x11-cm.c deleted file mode 100644 index ed2b7bb8b..000000000 --- a/src/backends/x11/cm/meta-backend-x11-cm.c +++ /dev/null @@ -1,550 +0,0 @@ -/* - * Copyright (C) 2017 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. - */ - -#include "config.h" - -#include "backends/x11/cm/meta-backend-x11-cm.h" - -#include -#include -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-dnd-private.h" -#include "backends/x11/meta-cursor-renderer-x11.h" -#include "backends/x11/meta-cursor-tracker-x11.h" -#include "backends/x11/meta-gpu-xrandr.h" -#include "backends/x11/meta-input-settings-x11.h" -#include "backends/x11/meta-monitor-manager-xrandr.h" -#include "backends/x11/cm/meta-renderer-x11-cm.h" -#include "compositor/meta-compositor-x11.h" -#include "core/display-private.h" - -enum -{ - PROP_0, - - PROP_DISPLAY_NAME, - - N_PROPS -}; - -static GParamSpec *obj_props[N_PROPS]; - -struct _MetaBackendX11Cm -{ - MetaBackendX11 parent; - - char *display_name; - - MetaCursorRenderer *cursor_renderer; - char *keymap_layouts; - char *keymap_variants; - char *keymap_options; - int locked_group; - - MetaInputSettings *input_settings; -}; - -G_DEFINE_TYPE (MetaBackendX11Cm, meta_backend_x11_cm, META_TYPE_BACKEND_X11) - -static void -apply_keymap (MetaBackendX11 *x11); - -static void -take_touch_grab (MetaBackend *backend) -{ - MetaBackendX11 *x11 = META_BACKEND_X11 (backend); - Display *xdisplay = meta_backend_x11_get_xdisplay (x11); - unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 }; - XIEventMask mask = { META_VIRTUAL_CORE_POINTER_ID, sizeof (mask_bits), mask_bits }; - XIGrabModifiers mods = { XIAnyModifier, 0 }; - - XISetMask (mask.mask, XI_TouchBegin); - XISetMask (mask.mask, XI_TouchUpdate); - XISetMask (mask.mask, XI_TouchEnd); - - XIGrabTouchBegin (xdisplay, META_VIRTUAL_CORE_POINTER_ID, - DefaultRootWindow (xdisplay), - False, &mask, 1, &mods); -} - -static void -on_device_added (ClutterSeat *seat, - ClutterInputDevice *device, - gpointer user_data) -{ - MetaBackendX11 *x11 = META_BACKEND_X11 (user_data); - - if (clutter_input_device_get_device_type (device) == CLUTTER_KEYBOARD_DEVICE) - apply_keymap (x11); -} - -static void -meta_backend_x11_cm_post_init (MetaBackend *backend) -{ - MetaBackendClass *parent_backend_class = - META_BACKEND_CLASS (meta_backend_x11_cm_parent_class); - MetaBackendX11Cm *x11_cm = META_BACKEND_X11_CM (backend); - ClutterSeat *seat; - - seat = clutter_backend_get_default_seat (clutter_get_default_backend ()); - g_signal_connect_object (seat, "device-added", - G_CALLBACK (on_device_added), backend, 0); - - x11_cm->input_settings = g_object_new (META_TYPE_INPUT_SETTINGS_X11, NULL); - - parent_backend_class->post_init (backend); - take_touch_grab (backend); -} - -static MetaRenderer * -meta_backend_x11_cm_create_renderer (MetaBackend *backend, - GError **error) -{ - return g_object_new (META_TYPE_RENDERER_X11_CM, - "backend", backend, - NULL); -} - -static MetaMonitorManager * -meta_backend_x11_cm_create_monitor_manager (MetaBackend *backend, - GError **error) -{ - return g_object_new (META_TYPE_MONITOR_MANAGER_XRANDR, - "backend", backend, - NULL); -} - -static MetaCursorRenderer * -meta_backend_x11_cm_get_cursor_renderer (MetaBackend *backend, - ClutterInputDevice *device) -{ - MetaBackendX11Cm *x11_cm = META_BACKEND_X11_CM (backend); - - if (!x11_cm->cursor_renderer) - { - x11_cm->cursor_renderer = - g_object_new (META_TYPE_CURSOR_RENDERER_X11, - "backend", backend, - "device", device, - NULL); - } - - return x11_cm->cursor_renderer; -} - -static MetaCursorTracker * -meta_backend_x11_cm_create_cursor_tracker (MetaBackend *backend) -{ - return g_object_new (META_TYPE_CURSOR_TRACKER_X11, - "backend", backend, - NULL); -} - -static MetaInputSettings * -meta_backend_x11_cm_get_input_settings (MetaBackend *backend) -{ - MetaBackendX11Cm *x11_cm = META_BACKEND_X11_CM (backend); - - return x11_cm->input_settings; -} - -static void -meta_backend_x11_cm_update_screen_size (MetaBackend *backend, - int width, - int height) -{ - MetaBackendX11 *x11 = META_BACKEND_X11 (backend); - Display *xdisplay = meta_backend_x11_get_xdisplay (x11); - Window xwin = meta_backend_x11_get_xwindow (x11); - - XResizeWindow (xdisplay, xwin, width, height); -} - -static void -meta_backend_x11_cm_select_stage_events (MetaBackend *backend) -{ - MetaBackendX11 *x11 = META_BACKEND_X11 (backend); - Display *xdisplay = meta_backend_x11_get_xdisplay (x11); - Window xwin = meta_backend_x11_get_xwindow (x11); - unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 }; - XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits }; - - XISetMask (mask.mask, XI_KeyPress); - XISetMask (mask.mask, XI_KeyRelease); - XISetMask (mask.mask, XI_ButtonPress); - XISetMask (mask.mask, XI_ButtonRelease); - XISetMask (mask.mask, XI_Enter); - XISetMask (mask.mask, XI_Leave); - XISetMask (mask.mask, XI_FocusIn); - XISetMask (mask.mask, XI_FocusOut); - XISetMask (mask.mask, XI_Motion); - - XISelectEvents (xdisplay, xwin, &mask, 1); -} - -static void -get_xkbrf_var_defs (Display *xdisplay, - const char *layouts, - const char *variants, - const char *options, - char **rules_p, - XkbRF_VarDefsRec *var_defs) -{ - char *rules = NULL; - - /* Get it from the X property or fallback on defaults */ - if (!XkbRF_GetNamesProp (xdisplay, &rules, var_defs) || !rules) - { - rules = strdup (DEFAULT_XKB_RULES_FILE); - var_defs->model = strdup (DEFAULT_XKB_MODEL); - var_defs->layout = NULL; - var_defs->variant = NULL; - var_defs->options = NULL; - } - - /* Swap in our new options... */ - free (var_defs->layout); - var_defs->layout = strdup (layouts); - free (var_defs->variant); - var_defs->variant = strdup (variants); - free (var_defs->options); - var_defs->options = strdup (options); - - /* Sometimes, the property is a file path, and sometimes it's - not. Normalize it so it's always a file path. */ - if (rules[0] == '/') - *rules_p = g_strdup (rules); - else - *rules_p = g_build_filename (XKB_BASE, "rules", rules, NULL); - - free (rules); -} - -static void -free_xkbrf_var_defs (XkbRF_VarDefsRec *var_defs) -{ - free (var_defs->model); - free (var_defs->layout); - free (var_defs->variant); - free (var_defs->options); -} - -static void -free_xkb_component_names (XkbComponentNamesRec *p) -{ - free (p->keymap); - free (p->keycodes); - free (p->types); - free (p->compat); - free (p->symbols); - free (p->geometry); -} - -static void -upload_xkb_description (Display *xdisplay, - const gchar *rules_file_path, - XkbRF_VarDefsRec *var_defs, - XkbComponentNamesRec *comp_names) -{ - XkbDescRec *xkb_desc; - gchar *rules_file; - - /* Upload it to the X server using the same method as setxkbmap */ - xkb_desc = XkbGetKeyboardByName (xdisplay, - XkbUseCoreKbd, - comp_names, - XkbGBN_AllComponentsMask, - XkbGBN_AllComponentsMask & - (~XkbGBN_GeometryMask), True); - if (!xkb_desc) - { - g_warning ("Couldn't upload new XKB keyboard description"); - return; - } - - XkbFreeKeyboard (xkb_desc, 0, True); - - rules_file = g_path_get_basename (rules_file_path); - - if (!XkbRF_SetNamesProp (xdisplay, rules_file, var_defs)) - g_warning ("Couldn't update the XKB root window property"); - - g_free (rules_file); -} - -static void -apply_keymap (MetaBackendX11 *x11) -{ - MetaBackendX11Cm *x11_cm = META_BACKEND_X11_CM (x11); - Display *xdisplay = meta_backend_x11_get_xdisplay (x11); - XkbRF_RulesRec *xkb_rules; - XkbRF_VarDefsRec xkb_var_defs = { 0 }; - char *rules_file_path; - - if (!x11_cm->keymap_layouts || - !x11_cm->keymap_variants || - !x11_cm->keymap_options) - return; - - get_xkbrf_var_defs (xdisplay, - x11_cm->keymap_layouts, - x11_cm->keymap_variants, - x11_cm->keymap_options, - &rules_file_path, - &xkb_var_defs); - - xkb_rules = XkbRF_Load (rules_file_path, NULL, True, True); - if (xkb_rules) - { - XkbComponentNamesRec xkb_comp_names = { 0 }; - - XkbRF_GetComponents (xkb_rules, &xkb_var_defs, &xkb_comp_names); - upload_xkb_description (xdisplay, rules_file_path, &xkb_var_defs, &xkb_comp_names); - - free_xkb_component_names (&xkb_comp_names); - XkbRF_Free (xkb_rules, True); - } - else - { - g_warning ("Couldn't load XKB rules"); - } - - free_xkbrf_var_defs (&xkb_var_defs); - g_free (rules_file_path); -} - -static void -meta_backend_x11_cm_set_keymap (MetaBackend *backend, - const char *layouts, - const char *variants, - const char *options) -{ - MetaBackendX11 *x11 = META_BACKEND_X11 (backend); - MetaBackendX11Cm *x11_cm = META_BACKEND_X11_CM (x11); - - g_free (x11_cm->keymap_layouts); - x11_cm->keymap_layouts = g_strdup (layouts); - g_free (x11_cm->keymap_variants); - x11_cm->keymap_variants = g_strdup (variants); - g_free (x11_cm->keymap_options); - x11_cm->keymap_options = g_strdup (options); - - apply_keymap (x11); -} - -static void -meta_backend_x11_cm_lock_layout_group (MetaBackend *backend, - guint idx) -{ - MetaBackendX11 *x11 = META_BACKEND_X11 (backend); - MetaBackendX11Cm *x11_cm = META_BACKEND_X11_CM (x11); - Display *xdisplay = meta_backend_x11_get_xdisplay (x11); - - x11_cm->locked_group = idx; - XkbLockGroup (xdisplay, XkbUseCoreKbd, idx); -} - -static gboolean -meta_backend_x11_cm_handle_host_xevent (MetaBackendX11 *backend_x11, - XEvent *event) -{ - MetaBackend *backend = META_BACKEND (backend_x11); - MetaBackendX11 *x11 = META_BACKEND_X11 (backend); - MetaBackendX11Cm *x11_cm = META_BACKEND_X11_CM (x11); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerXrandr *monitor_manager_xrandr = - META_MONITOR_MANAGER_XRANDR (monitor_manager); - Display *xdisplay = meta_backend_x11_get_xdisplay (x11); - gboolean bypass_clutter = FALSE; - MetaDisplay *display; - - display = meta_get_display (); - if (display) - { - MetaCompositor *compositor = display->compositor; - MetaCompositorX11 *compositor_x11 = META_COMPOSITOR_X11 (compositor); - Display *xdisplay = meta_backend_x11_get_xdisplay (x11); - - if (meta_dnd_handle_xdnd_event (backend, compositor_x11, - xdisplay, event)) - bypass_clutter = TRUE; - } - - if (event->type == meta_backend_x11_get_xkb_event_base (x11)) - { - XkbEvent *xkb_ev = (XkbEvent *) event; - - if (xkb_ev->any.device == META_VIRTUAL_CORE_KEYBOARD_ID) - { - switch (xkb_ev->any.xkb_type) - { - case XkbStateNotify: - if (xkb_ev->state.changed & XkbGroupLockMask) - { - if (x11_cm->locked_group != xkb_ev->state.locked_group) - XkbLockGroup (xdisplay, XkbUseCoreKbd, - x11_cm->locked_group); - } - break; - default: - break; - } - } - } - - bypass_clutter |= - meta_monitor_manager_xrandr_handle_xevent (monitor_manager_xrandr, event); - - return bypass_clutter; -} - -static void -meta_backend_x11_cm_translate_device_event (MetaBackendX11 *x11, - XIDeviceEvent *device_event) -{ - Window stage_window = meta_backend_x11_get_xwindow (x11); - - if (device_event->event != stage_window) - { - device_event->event = stage_window; - - /* As an X11 compositor, the stage window is always at 0,0, so - * using root coordinates will give us correct stage coordinates - * as well... */ - device_event->event_x = device_event->root_x; - device_event->event_y = device_event->root_y; - } -} - -static void -meta_backend_x11_cm_translate_crossing_event (MetaBackendX11 *x11, - XIEnterEvent *enter_event) -{ - Window stage_window = meta_backend_x11_get_xwindow (x11); - - if (enter_event->event != stage_window) - { - enter_event->event = stage_window; - enter_event->event_x = enter_event->root_x; - enter_event->event_y = enter_event->root_y; - } -} - -static void -meta_backend_x11_cm_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaBackendX11Cm *backend_x11_cm = META_BACKEND_X11_CM (object); - - switch (prop_id) - { - case PROP_DISPLAY_NAME: - backend_x11_cm->display_name = g_value_dup_string (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_backend_x11_cm_finalize (GObject *object) -{ - MetaBackendX11Cm *x11_cm = META_BACKEND_X11_CM (object); - - g_clear_pointer (&x11_cm->display_name, g_free); - - G_OBJECT_CLASS (meta_backend_x11_cm_parent_class)->finalize (object); -} - -static void -meta_backend_x11_cm_constructed (GObject *object) -{ - MetaBackendX11Cm *x11_cm = META_BACKEND_X11_CM (object); - const char *display_name; - - if (x11_cm->display_name) - display_name = (const char *) x11_cm->display_name; - else - display_name = g_getenv ("MUTTER_DISPLAY"); - - if (display_name) - g_setenv ("DISPLAY", display_name, TRUE); - - G_OBJECT_CLASS (meta_backend_x11_cm_parent_class)->constructed (object); -} - -static void -meta_backend_x11_cm_init (MetaBackendX11Cm *backend_x11_cm) -{ - MetaGpuXrandr *gpu_xrandr; - - /* - * The X server deals with multiple GPUs for us, so we just see what the X - * server gives us as one single GPU, even though it may actually be backed - * by multiple. - */ - gpu_xrandr = meta_gpu_xrandr_new (META_BACKEND_X11 (backend_x11_cm)); - meta_backend_add_gpu (META_BACKEND (backend_x11_cm), - META_GPU (gpu_xrandr)); -} - -static void -meta_backend_x11_cm_class_init (MetaBackendX11CmClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaBackendClass *backend_class = META_BACKEND_CLASS (klass); - MetaBackendX11Class *backend_x11_class = META_BACKEND_X11_CLASS (klass); - - object_class->set_property = meta_backend_x11_cm_set_property; - object_class->finalize = meta_backend_x11_cm_finalize; - object_class->constructed = meta_backend_x11_cm_constructed; - - backend_class->post_init = meta_backend_x11_cm_post_init; - backend_class->create_renderer = meta_backend_x11_cm_create_renderer; - backend_class->create_monitor_manager = meta_backend_x11_cm_create_monitor_manager; - backend_class->get_cursor_renderer = meta_backend_x11_cm_get_cursor_renderer; - backend_class->create_cursor_tracker = meta_backend_x11_cm_create_cursor_tracker; - backend_class->get_input_settings = meta_backend_x11_cm_get_input_settings; - backend_class->update_screen_size = meta_backend_x11_cm_update_screen_size; - backend_class->select_stage_events = meta_backend_x11_cm_select_stage_events; - backend_class->lock_layout_group = meta_backend_x11_cm_lock_layout_group; - backend_class->set_keymap = meta_backend_x11_cm_set_keymap; - - backend_x11_class->handle_host_xevent = meta_backend_x11_cm_handle_host_xevent; - backend_x11_class->translate_device_event = meta_backend_x11_cm_translate_device_event; - backend_x11_class->translate_crossing_event = meta_backend_x11_cm_translate_crossing_event; - - obj_props[PROP_DISPLAY_NAME] = - g_param_spec_string ("display-name", - "display name", - "X11 display name", - NULL, - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, N_PROPS, obj_props); -} - diff --git a/src/backends/x11/cm/meta-backend-x11-cm.h b/src/backends/x11/cm/meta-backend-x11-cm.h deleted file mode 100644 index 5332da13d..000000000 --- a/src/backends/x11/cm/meta-backend-x11-cm.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2017 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_X11_CM_H -#define META_BACKEND_X11_CM_H - -#include - -#include "backends/x11/meta-backend-x11.h" - -#define META_TYPE_BACKEND_X11_CM (meta_backend_x11_cm_get_type ()) -G_DECLARE_FINAL_TYPE (MetaBackendX11Cm, meta_backend_x11_cm, - META, BACKEND_X11_CM, MetaBackendX11) - -#endif /* META_BACKEND_X11_CM_H */ diff --git a/src/backends/x11/cm/meta-cursor-sprite-xfixes.c b/src/backends/x11/cm/meta-cursor-sprite-xfixes.c deleted file mode 100644 index 0c524668e..000000000 --- a/src/backends/x11/cm/meta-cursor-sprite-xfixes.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright 2013, 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 . - * - */ - -#include "config.h" - -#include "backends/x11/cm/meta-cursor-sprite-xfixes.h" - -#include - -#include "core/display-private.h" -#include "meta/meta-x11-display.h" - -enum -{ - PROP_0, - - PROP_DISPLAY, - - N_PROPS -}; - -static GParamSpec *obj_props[N_PROPS]; - -struct _MetaCursorSpriteXfixes -{ - MetaCursorSprite parent; - - MetaDisplay *display; -}; - -static void -meta_screen_cast_xfixes_init_initable_iface (GInitableIface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaCursorSpriteXfixes, - meta_cursor_sprite_xfixes, - META_TYPE_CURSOR_SPRITE, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - meta_screen_cast_xfixes_init_initable_iface)) - -static void -meta_cursor_sprite_xfixes_realize_texture (MetaCursorSprite *sprite) -{ -} - -static gboolean -meta_cursor_sprite_xfixes_is_animated (MetaCursorSprite *sprite) -{ - return FALSE; -} - -static void -meta_cursor_sprite_xfixes_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaCursorSpriteXfixes *sprite_xfixes = META_CURSOR_SPRITE_XFIXES (object); - - switch (prop_id) - { - case PROP_DISPLAY: - g_value_set_object (value, sprite_xfixes->display); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_cursor_sprite_xfixes_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaCursorSpriteXfixes *sprite_xfixes = META_CURSOR_SPRITE_XFIXES (object); - - switch (prop_id) - { - case PROP_DISPLAY: - sprite_xfixes->display = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -MetaCursorSpriteXfixes * -meta_cursor_sprite_xfixes_new (MetaDisplay *display, - GError **error) -{ - return g_initable_new (META_TYPE_CURSOR_SPRITE_XFIXES, - NULL, error, - "display", display, - NULL); -} - -static gboolean -meta_cursor_sprite_xfixes_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - MetaCursorSpriteXfixes *sprite_xfixes = - META_CURSOR_SPRITE_XFIXES (initable); - MetaCursorSprite *sprite = META_CURSOR_SPRITE (sprite_xfixes); - MetaX11Display *x11_display; - Display *xdisplay; - XFixesCursorImage *cursor_image; - CoglTexture2D *texture; - uint8_t *cursor_data; - gboolean free_cursor_data; - ClutterBackend *clutter_backend; - CoglContext *cogl_context; - - x11_display = meta_display_get_x11_display (sprite_xfixes->display); - xdisplay = meta_x11_display_get_xdisplay (x11_display); - cursor_image = XFixesGetCursorImage (xdisplay); - if (!cursor_image) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to get cursor image"); - return FALSE; - } - - /* - * Like all X APIs, XFixesGetCursorImage() returns arrays of 32-bit - * quantities as arrays of long; we need to convert on 64 bit - */ - if (sizeof (long) == 4) - { - cursor_data = (uint8_t *) cursor_image->pixels; - free_cursor_data = FALSE; - } - else - { - int i, j; - uint32_t *cursor_words; - unsigned long *p; - uint32_t *q; - - cursor_words = g_new (uint32_t, - cursor_image->width * cursor_image->height); - cursor_data = (uint8_t *) cursor_words; - - p = cursor_image->pixels; - q = cursor_words; - for (j = 0; j < cursor_image->height; j++) - { - for (i = 0; i < cursor_image->width; i++) - *(q++) = *(p++); - } - - free_cursor_data = TRUE; - } - - clutter_backend = clutter_get_default_backend (); - cogl_context = clutter_backend_get_cogl_context (clutter_backend); - texture = cogl_texture_2d_new_from_data (cogl_context, - cursor_image->width, - cursor_image->height, - CLUTTER_CAIRO_FORMAT_ARGB32, - cursor_image->width * 4, /* stride */ - cursor_data, - error); - - if (free_cursor_data) - g_free (cursor_data); - - if (!sprite) - return FALSE; - - meta_cursor_sprite_set_texture (sprite, - COGL_TEXTURE (texture), - cursor_image->xhot, - cursor_image->yhot); - cogl_object_unref (texture); - XFree (cursor_image); - - return TRUE; -} - -static void -meta_screen_cast_xfixes_init_initable_iface (GInitableIface *iface) -{ - iface->init = meta_cursor_sprite_xfixes_initable_init; -} - -static void -meta_cursor_sprite_xfixes_init (MetaCursorSpriteXfixes *sprite_xfixes) -{ -} - -static void -meta_cursor_sprite_xfixes_class_init (MetaCursorSpriteXfixesClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaCursorSpriteClass *cursor_sprite_class = META_CURSOR_SPRITE_CLASS (klass); - - object_class->get_property = meta_cursor_sprite_xfixes_get_property; - object_class->set_property = meta_cursor_sprite_xfixes_set_property; - - cursor_sprite_class->realize_texture = - meta_cursor_sprite_xfixes_realize_texture; - cursor_sprite_class->is_animated = meta_cursor_sprite_xfixes_is_animated; - - obj_props[PROP_DISPLAY] = - g_param_spec_object ("display", - "display", - "MetaDisplay", - META_TYPE_DISPLAY, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, N_PROPS, obj_props); -} diff --git a/src/backends/x11/cm/meta-cursor-sprite-xfixes.h b/src/backends/x11/cm/meta-cursor-sprite-xfixes.h deleted file mode 100644 index c7073fc2c..000000000 --- a/src/backends/x11/cm/meta-cursor-sprite-xfixes.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2013, 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 . - * - */ - -#ifndef META_CURSOR_SPRITE_XFIXES_H -#define META_CURSOR_SPRITE_XFIXES_H - -#include - -#include "backends/meta-cursor.h" -#include "meta/types.h" - -#define META_TYPE_CURSOR_SPRITE_XFIXES (meta_cursor_sprite_xfixes_get_type ()) -G_DECLARE_FINAL_TYPE (MetaCursorSpriteXfixes, - meta_cursor_sprite_xfixes, - META, CURSOR_SPRITE_XFIXES, - MetaCursorSprite) - -MetaCursorSpriteXfixes * meta_cursor_sprite_xfixes_new (MetaDisplay *display, - GError **error); - -#endif /* META_CURSOR_SPRITE_XFIXES_H */ diff --git a/src/backends/x11/cm/meta-renderer-x11-cm.c b/src/backends/x11/cm/meta-renderer-x11-cm.c deleted file mode 100644 index afed2e377..000000000 --- a/src/backends/x11/cm/meta-renderer-x11-cm.c +++ /dev/null @@ -1,113 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 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. - * - */ - -#include "config.h" - -#include "backends/x11/cm/meta-renderer-x11-cm.h" - -#include "backends/meta-renderer-view.h" - -struct _MetaRendererX11Cm -{ - MetaRendererX11 parent; - - MetaRendererView *screen_view; -}; - -G_DEFINE_TYPE (MetaRendererX11Cm, meta_renderer_x11_cm, - META_TYPE_RENDERER_X11) - -void -meta_renderer_x11_cm_init_screen_view (MetaRendererX11Cm *renderer_x11_cm, - CoglOnscreen *onscreen, - int width, - int height) -{ - MetaRenderer *renderer = META_RENDERER (renderer_x11_cm); - MetaBackend *backend = meta_renderer_get_backend (renderer); - ClutterActor *stage = meta_backend_get_stage (backend); - cairo_rectangle_int_t view_layout; - - g_return_if_fail (!renderer_x11_cm->screen_view); - - view_layout = (cairo_rectangle_int_t) { - .width = width, - .height = height, - }; - renderer_x11_cm->screen_view = g_object_new (META_TYPE_RENDERER_VIEW, - "name", "X11 screen", - "stage", stage, - "layout", &view_layout, - "framebuffer", onscreen, - NULL); - meta_renderer_add_view (META_RENDERER (renderer_x11_cm), - renderer_x11_cm->screen_view); -} - -void -meta_renderer_x11_cm_resize (MetaRendererX11Cm *renderer_x11_cm, - int width, - int height) -{ - cairo_rectangle_int_t view_layout; - - view_layout = (cairo_rectangle_int_t) { - .width = width, - .height = height, - }; - - g_object_set (G_OBJECT (renderer_x11_cm->screen_view), - "layout", &view_layout, - NULL); -} - -static void -meta_renderer_x11_cm_rebuild_views (MetaRenderer *renderer) -{ - MetaRendererX11Cm *renderer_x11_cm = META_RENDERER_X11_CM (renderer); - - g_return_if_fail (!meta_renderer_get_views (renderer)); - - meta_renderer_add_view (renderer, renderer_x11_cm->screen_view); -} - -static GList * -meta_renderer_x11_cm_get_views_for_monitor (MetaRenderer *renderer, - MetaMonitor *monitor) -{ - return g_list_prepend (NULL, meta_renderer_get_views (renderer)->data); -} - -static void -meta_renderer_x11_cm_init (MetaRendererX11Cm *renderer_x11_cm) -{ -} - -static void -meta_renderer_x11_cm_class_init (MetaRendererX11CmClass *klass) -{ - MetaRendererClass *renderer_class = META_RENDERER_CLASS (klass); - - renderer_class->rebuild_views = meta_renderer_x11_cm_rebuild_views; - renderer_class->get_views_for_monitor = - meta_renderer_x11_cm_get_views_for_monitor; -} diff --git a/src/backends/x11/cm/meta-renderer-x11-cm.h b/src/backends/x11/cm/meta-renderer-x11-cm.h deleted file mode 100644 index 7ddb3445d..000000000 --- a/src/backends/x11/cm/meta-renderer-x11-cm.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 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_RENDERER_X11_CM_H -#define META_RENDERER_X11_CM_H - -#include "backends/x11/meta-renderer-x11.h" - -#define META_TYPE_RENDERER_X11_CM (meta_renderer_x11_cm_get_type ()) -G_DECLARE_FINAL_TYPE (MetaRendererX11Cm, meta_renderer_x11_cm, - META, RENDERER_X11_CM, - MetaRendererX11) - -void meta_renderer_x11_cm_init_screen_view (MetaRendererX11Cm *renderer_x11_cm, - CoglOnscreen *onscreen, - int width, - int height); - -void meta_renderer_x11_cm_resize (MetaRendererX11Cm *renderer_x11_cm, - int width, - int height); - -#endif /* META_RENDERER_X11_CM_H */ diff --git a/src/backends/x11/meta-backend-x11.c b/src/backends/x11/meta-backend-x11.c deleted file mode 100644 index 09a13505d..000000000 --- a/src/backends/x11/meta-backend-x11.c +++ /dev/null @@ -1,996 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -/** - * SECTION:meta-backend-x11 - * @title: MetaBackendX11 - * @short_description: A X11 MetaBackend - * - * MetaBackendX11 is an implementation of #MetaBackend using X and X - * extensions, like XInput and XKB. - */ - -#include "config.h" - -#include "backends/x11/meta-backend-x11.h" - -#include -#include -#include -#include -#include -#include - -#include "backends/meta-idle-monitor-private.h" -#include "backends/meta-keymap-utils.h" -#include "backends/meta-stage-private.h" -#include "backends/x11/meta-clutter-backend-x11.h" -#include "backends/x11/meta-event-x11.h" -#include "backends/x11/meta-seat-x11.h" -#include "backends/x11/meta-stage-x11.h" -#include "backends/x11/meta-renderer-x11.h" -#include "backends/x11/meta-xkb-a11y-x11.h" -#include "clutter/clutter.h" -#include "compositor/compositor-private.h" -#include "core/display-private.h" -#include "meta/meta-cursor-tracker.h" -#include "meta/util.h" - -struct _MetaBackendX11Private -{ - /* The host X11 display */ - Display *xdisplay; - xcb_connection_t *xcb; - GSource *source; - - int xsync_event_base; - int xsync_error_base; - XSyncAlarm user_active_alarm; - XSyncCounter counter; - - int current_touch_replay_sync_serial; - int pending_touch_replay_sync_serial; - Atom touch_replay_sync_atom; - - int xinput_opcode; - int xinput_event_base; - int xinput_error_base; - Time latest_evtime; - - uint8_t xkb_event_base; - uint8_t xkb_error_base; - - gulong keymap_state_changed_id; - - struct xkb_keymap *keymap; - xkb_layout_index_t keymap_layout_group; - - MetaLogicalMonitor *cached_current_logical_monitor; -}; -typedef struct _MetaBackendX11Private MetaBackendX11Private; - -static GInitableIface *initable_parent_iface; - -static void -initable_iface_init (GInitableIface *initable_iface); - -G_DEFINE_TYPE_WITH_CODE (MetaBackendX11, meta_backend_x11, META_TYPE_BACKEND, - G_ADD_PRIVATE (MetaBackendX11) - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - initable_iface_init)); - - -static void -uint64_to_xsync_value (uint64_t value, - XSyncValue *xsync_value) -{ - XSyncIntsToValue (xsync_value, value & 0xffffffff, value >> 32); -} - -static XSyncAlarm -xsync_user_active_alarm_set (MetaBackendX11Private *priv) -{ - XSyncAlarmAttributes attr; - XSyncValue delta; - unsigned long flags; - - flags = (XSyncCACounter | XSyncCAValueType | XSyncCATestType | - XSyncCAValue | XSyncCADelta | XSyncCAEvents); - - XSyncIntToValue (&delta, 0); - attr.trigger.counter = priv->counter; - attr.trigger.value_type = XSyncAbsolute; - attr.delta = delta; - attr.events = TRUE; - - uint64_to_xsync_value (1, &attr.trigger.wait_value); - - attr.trigger.test_type = XSyncNegativeTransition; - return XSyncCreateAlarm (priv->xdisplay, flags, &attr); -} - -static XSyncCounter -find_idletime_counter (MetaBackendX11Private *priv) -{ - int i; - int n_counters; - XSyncSystemCounter *counters; - XSyncCounter counter = None; - - counters = XSyncListSystemCounters (priv->xdisplay, &n_counters); - for (i = 0; i < n_counters; i++) - { - if (g_strcmp0 (counters[i].name, "IDLETIME") == 0) - { - counter = counters[i].counter; - break; - } - } - XSyncFreeSystemCounterList (counters); - - return counter; -} - -static void -handle_alarm_notify (MetaBackend *backend, - XSyncAlarmNotifyEvent *alarm_event) -{ - MetaBackendX11 *x11 = META_BACKEND_X11 (backend); - MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); - MetaIdleMonitor *idle_monitor; - XSyncAlarmAttributes attr; - ClutterBackend *clutter_backend; - ClutterSeat *seat; - ClutterInputDevice *pointer; - - if (alarm_event->state != XSyncAlarmActive || - alarm_event->alarm != priv->user_active_alarm) - return; - - attr.events = TRUE; - XSyncChangeAlarm (priv->xdisplay, priv->user_active_alarm, - XSyncCAEvents, &attr); - - clutter_backend = meta_backend_get_clutter_backend (backend); - seat = clutter_backend_get_default_seat (clutter_backend); - pointer = clutter_seat_get_pointer (seat); - idle_monitor = meta_backend_get_idle_monitor (backend, pointer); - meta_idle_monitor_reset_idletime (idle_monitor); -} - -static void -meta_backend_x11_translate_device_event (MetaBackendX11 *x11, - XIDeviceEvent *device_event) -{ - MetaBackendX11Class *backend_x11_class = - META_BACKEND_X11_GET_CLASS (x11); - - backend_x11_class->translate_device_event (x11, device_event); -} - -static void -maybe_translate_touch_replay_pointer_event (MetaBackendX11 *x11, - XIDeviceEvent *device_event) -{ - MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); - - if (!device_event->send_event && - device_event->time != META_CURRENT_TIME && - priv->current_touch_replay_sync_serial != - priv->pending_touch_replay_sync_serial && - XSERVER_TIME_IS_BEFORE (device_event->time, priv->latest_evtime)) - { - /* Emulated pointer events received after XIRejectTouch is received - * on a passive touch grab will contain older timestamps, update those - * so we dont get InvalidTime at grabs. - */ - device_event->time = priv->latest_evtime; - } -} - -static void -translate_device_event (MetaBackendX11 *x11, - XIDeviceEvent *device_event) -{ - MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); - - meta_backend_x11_translate_device_event (x11, device_event); - - if (!device_event->send_event && device_event->time != META_CURRENT_TIME) - priv->latest_evtime = device_event->time; -} - -static void -meta_backend_x11_translate_crossing_event (MetaBackendX11 *x11, - XIEnterEvent *enter_event) -{ - MetaBackendX11Class *backend_x11_class = - META_BACKEND_X11_GET_CLASS (x11); - - if (backend_x11_class->translate_crossing_event) - backend_x11_class->translate_crossing_event (x11, enter_event); -} - -static void -translate_crossing_event (MetaBackendX11 *x11, - XIEnterEvent *enter_event) -{ - /* Throw out weird events generated by grabs. */ - if (enter_event->mode == XINotifyGrab || - enter_event->mode == XINotifyUngrab) - { - enter_event->event = None; - return; - } - - meta_backend_x11_translate_crossing_event (x11, enter_event); -} - -static void -handle_device_change (MetaBackendX11 *x11, - XIEvent *event) -{ - XIDeviceChangedEvent *device_changed; - ClutterInputDevice *device; - ClutterBackend *backend; - ClutterSeat *seat; - - if (event->evtype != XI_DeviceChanged) - return; - - device_changed = (XIDeviceChangedEvent *) event; - - if (device_changed->reason != XISlaveSwitch) - return; - - backend = meta_backend_get_clutter_backend (META_BACKEND (x11)); - seat = clutter_backend_get_default_seat (backend); - device = meta_seat_x11_lookup_device_id (META_SEAT_X11 (seat), - device_changed->sourceid); - meta_backend_update_last_device (META_BACKEND (x11), device); -} - -/* Clutter makes the assumption that there is only one X window - * per stage, which is a valid assumption to make for a generic - * application toolkit. As such, it will ignore any events sent - * to the a stage that isn't its X window. - * - * When running as an X window manager, we need to respond to - * events from lots of windows. Trick Clutter into translating - * these events by pretending we got an event on the stage window. - */ -static void -maybe_spoof_event_as_stage_event (MetaBackendX11 *x11, - XIEvent *input_event) -{ - switch (input_event->evtype) - { - case XI_Motion: - case XI_ButtonPress: - case XI_ButtonRelease: - maybe_translate_touch_replay_pointer_event (x11, - (XIDeviceEvent *) input_event); - G_GNUC_FALLTHROUGH; - case XI_KeyPress: - case XI_KeyRelease: - case XI_TouchBegin: - case XI_TouchUpdate: - case XI_TouchEnd: - translate_device_event (x11, (XIDeviceEvent *) input_event); - break; - case XI_Enter: - case XI_Leave: - translate_crossing_event (x11, (XIEnterEvent *) input_event); - break; - default: - break; - } -} - -static void -handle_input_event (MetaBackendX11 *x11, - XEvent *event) -{ - MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); - - if (event->type == GenericEvent && - event->xcookie.extension == priv->xinput_opcode) - { - XIEvent *input_event = (XIEvent *) event->xcookie.data; - - if (input_event->evtype == XI_DeviceChanged) - handle_device_change (x11, input_event); - else - maybe_spoof_event_as_stage_event (x11, input_event); - } -} - -static void -keymap_changed (MetaBackend *backend) -{ - MetaBackendX11 *x11 = META_BACKEND_X11 (backend); - MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); - - if (priv->keymap) - { - xkb_keymap_unref (priv->keymap); - priv->keymap = NULL; - } - - g_signal_emit_by_name (backend, "keymap-changed", 0); -} - -static gboolean -meta_backend_x11_handle_host_xevent (MetaBackendX11 *backend_x11, - XEvent *event) -{ - MetaBackendX11Class *backend_x11_class = - META_BACKEND_X11_GET_CLASS (backend_x11); - - return backend_x11_class->handle_host_xevent (backend_x11, event); -} - -static void -handle_host_xevent (MetaBackend *backend, - XEvent *event) -{ - MetaBackendX11 *x11 = META_BACKEND_X11 (backend); - MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); - gboolean bypass_clutter = FALSE; - MetaDisplay *display; - - switch (event->type) - { - case ClientMessage: - if (event->xclient.window == meta_backend_x11_get_xwindow (x11) && - event->xclient.message_type == priv->touch_replay_sync_atom) - priv->current_touch_replay_sync_serial = event->xclient.data.l[0]; - break; - default: - break; - } - - XGetEventData (priv->xdisplay, &event->xcookie); - - display = meta_get_display (); - if (display) - { - MetaCompositor *compositor = display->compositor; - MetaPluginManager *plugin_mgr = - meta_compositor_get_plugin_manager (compositor); - - if (meta_plugin_manager_xevent_filter (plugin_mgr, event)) - bypass_clutter = TRUE; - } - - bypass_clutter = (meta_backend_x11_handle_host_xevent (x11, event) || - bypass_clutter); - - if (event->type == (priv->xsync_event_base + XSyncAlarmNotify)) - handle_alarm_notify (backend, (XSyncAlarmNotifyEvent *) event); - - if (event->type == priv->xkb_event_base) - { - XkbEvent *xkb_ev = (XkbEvent *) event; - - if (xkb_ev->any.device == META_VIRTUAL_CORE_KEYBOARD_ID) - { - switch (xkb_ev->any.xkb_type) - { - case XkbNewKeyboardNotify: - case XkbMapNotify: - keymap_changed (backend); - break; - case XkbStateNotify: - if (xkb_ev->state.changed & XkbGroupLockMask) - { - int layout_group; - gboolean layout_group_changed; - - layout_group = xkb_ev->state.locked_group; - layout_group_changed = - (int) priv->keymap_layout_group != layout_group; - priv->keymap_layout_group = layout_group; - - if (layout_group_changed) - meta_backend_notify_keymap_layout_group_changed (backend, - layout_group); - } - break; - default: - break; - } - } - } - - if (!bypass_clutter) - { - handle_input_event (x11, event); - meta_x11_handle_event (event); - } - - XFreeEventData (priv->xdisplay, &event->xcookie); -} - -typedef struct { - GSource base; - GPollFD event_poll_fd; - MetaBackend *backend; -} XEventSource; - -static gboolean -x_event_source_prepare (GSource *source, - int *timeout) -{ - XEventSource *x_source = (XEventSource *) source; - MetaBackend *backend = x_source->backend; - MetaBackendX11 *x11 = META_BACKEND_X11 (backend); - MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); - - *timeout = -1; - - return XPending (priv->xdisplay); -} - -static gboolean -x_event_source_check (GSource *source) -{ - XEventSource *x_source = (XEventSource *) source; - MetaBackend *backend = x_source->backend; - MetaBackendX11 *x11 = META_BACKEND_X11 (backend); - MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); - - return XPending (priv->xdisplay); -} - -static gboolean -x_event_source_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data) -{ - XEventSource *x_source = (XEventSource *) source; - MetaBackend *backend = x_source->backend; - MetaBackendX11 *x11 = META_BACKEND_X11 (backend); - MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); - - while (XPending (priv->xdisplay)) - { - XEvent event; - - XNextEvent (priv->xdisplay, &event); - - handle_host_xevent (backend, &event); - } - - return TRUE; -} - -static GSourceFuncs x_event_funcs = { - x_event_source_prepare, - x_event_source_check, - x_event_source_dispatch, -}; - -static GSource * -x_event_source_new (MetaBackend *backend) -{ - MetaBackendX11 *x11 = META_BACKEND_X11 (backend); - MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); - GSource *source; - XEventSource *x_source; - - source = g_source_new (&x_event_funcs, sizeof (XEventSource)); - x_source = (XEventSource *) source; - x_source->backend = backend; - x_source->event_poll_fd.fd = ConnectionNumber (priv->xdisplay); - x_source->event_poll_fd.events = G_IO_IN; - g_source_add_poll (source, &x_source->event_poll_fd); - - g_source_attach (source, NULL); - return source; -} - -static void -on_monitors_changed (MetaMonitorManager *manager, - MetaBackend *backend) -{ - MetaBackendX11 *x11 = META_BACKEND_X11 (backend); - MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); - - priv->cached_current_logical_monitor = NULL; -} - -static void -on_kbd_a11y_changed (MetaInputSettings *input_settings, - MetaKbdA11ySettings *a11y_settings, - MetaBackend *backend) -{ - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - ClutterSeat *seat = clutter_backend_get_default_seat (clutter_backend); - - meta_seat_x11_apply_kbd_a11y_settings (seat, a11y_settings); -} - -static void -meta_backend_x11_post_init (MetaBackend *backend) -{ - MetaBackendX11 *x11 = META_BACKEND_X11 (backend); - MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); - MetaMonitorManager *monitor_manager; - ClutterBackend *clutter_backend; - ClutterSeat *seat; - MetaInputSettings *input_settings; - int major, minor; - gboolean has_xi = FALSE; - - priv->source = x_event_source_new (backend); - - if (!XSyncQueryExtension (priv->xdisplay, &priv->xsync_event_base, &priv->xsync_error_base) || - !XSyncInitialize (priv->xdisplay, &major, &minor)) - meta_fatal ("Could not initialize XSync"); - - priv->counter = find_idletime_counter (priv); - if (priv->counter == None) - meta_fatal ("Could not initialize XSync counter"); - - priv->user_active_alarm = xsync_user_active_alarm_set (priv); - - if (XQueryExtension (priv->xdisplay, - "XInputExtension", - &priv->xinput_opcode, - &priv->xinput_error_base, - &priv->xinput_event_base)) - { - major = 2; minor = 3; - if (XIQueryVersion (priv->xdisplay, &major, &minor) == Success) - { - int version = (major * 10) + minor; - if (version >= 22) - has_xi = TRUE; - } - } - - if (!has_xi) - meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer"); - - if (!xkb_x11_setup_xkb_extension (priv->xcb, - XKB_X11_MIN_MAJOR_XKB_VERSION, - XKB_X11_MIN_MINOR_XKB_VERSION, - XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, - NULL, NULL, - &priv->xkb_event_base, - &priv->xkb_error_base)) - meta_fatal ("X server doesn't have the XKB extension, version %d.%d or newer", - XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION); - - META_BACKEND_CLASS (meta_backend_x11_parent_class)->post_init (backend); - - monitor_manager = meta_backend_get_monitor_manager (backend); - g_signal_connect (monitor_manager, "monitors-changed-internal", - G_CALLBACK (on_monitors_changed), backend); - - priv->touch_replay_sync_atom = XInternAtom (priv->xdisplay, - "_MUTTER_TOUCH_SEQUENCE_SYNC", - False); - - clutter_backend = meta_backend_get_clutter_backend (backend); - seat = clutter_backend_get_default_seat (clutter_backend); - meta_seat_x11_notify_devices (META_SEAT_X11 (seat), - CLUTTER_STAGE (meta_backend_get_stage (backend))); - - input_settings = meta_backend_get_input_settings (backend); - - if (input_settings) - { - g_signal_connect_object (meta_backend_get_input_settings (backend), - "kbd-a11y-changed", - G_CALLBACK (on_kbd_a11y_changed), backend, 0); - - if (meta_input_settings_maybe_restore_numlock_state (input_settings)) - { - unsigned int num_mask; - - num_mask = XkbKeysymToModifiers (priv->xdisplay, XK_Num_Lock); - XkbLockModifiers (priv->xdisplay, XkbUseCoreKbd, num_mask, num_mask); - } - } -} - -static ClutterBackend * -meta_backend_x11_create_clutter_backend (MetaBackend *backend) -{ - return g_object_new (META_TYPE_CLUTTER_BACKEND_X11, NULL); -} - -static ClutterSeat * -meta_backend_x11_create_default_seat (MetaBackend *backend, - GError **error) -{ - MetaBackendX11 *x11 = META_BACKEND_X11 (backend); - MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); - int event_base, first_event, first_error; - int major, minor; - MetaSeatX11 *seat_x11; - - if (!XQueryExtension (priv->xdisplay, - "XInputExtension", - &event_base, - &first_event, - &first_error)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to query XInputExtension"); - return NULL; - } - - major = 2; - minor = 3; - if (XIQueryVersion (priv->xdisplay, &major, &minor) == BadRequest) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Incompatible XInputExtension version"); - return NULL; - } - - seat_x11 = meta_seat_x11_new (event_base, - META_VIRTUAL_CORE_POINTER_ID, - META_VIRTUAL_CORE_KEYBOARD_ID); - return CLUTTER_SEAT (seat_x11); -} - -static gboolean -meta_backend_x11_grab_device (MetaBackend *backend, - int device_id, - uint32_t timestamp) -{ - MetaBackendX11 *x11 = META_BACKEND_X11 (backend); - MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); - unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 }; - XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits }; - int ret; - - if (timestamp != META_CURRENT_TIME && - XSERVER_TIME_IS_BEFORE (timestamp, priv->latest_evtime)) - timestamp = priv->latest_evtime; - - XISetMask (mask.mask, XI_ButtonPress); - XISetMask (mask.mask, XI_ButtonRelease); - XISetMask (mask.mask, XI_Enter); - XISetMask (mask.mask, XI_Leave); - XISetMask (mask.mask, XI_Motion); - XISetMask (mask.mask, XI_KeyPress); - XISetMask (mask.mask, XI_KeyRelease); - - ret = XIGrabDevice (priv->xdisplay, device_id, - meta_backend_x11_get_xwindow (x11), - timestamp, - None, - XIGrabModeAsync, XIGrabModeAsync, - False, /* owner_events */ - &mask); - - return (ret == Success); -} - -static gboolean -meta_backend_x11_ungrab_device (MetaBackend *backend, - int device_id, - uint32_t timestamp) -{ - MetaBackendX11 *x11 = META_BACKEND_X11 (backend); - MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); - int ret; - - ret = XIUngrabDevice (priv->xdisplay, device_id, timestamp); - XFlush (priv->xdisplay); - - return (ret == Success); -} - -static void -meta_backend_x11_finish_touch_sequence (MetaBackend *backend, - ClutterEventSequence *sequence, - MetaSequenceState state) -{ - MetaBackendX11 *x11 = META_BACKEND_X11 (backend); - MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); - int event_mode; - - if (state == META_SEQUENCE_ACCEPTED) - event_mode = XIAcceptTouch; - else if (state == META_SEQUENCE_REJECTED) - event_mode = XIRejectTouch; - else - g_return_if_reached (); - - XIAllowTouchEvents (priv->xdisplay, - META_VIRTUAL_CORE_POINTER_ID, - clutter_event_sequence_get_slot (sequence), - DefaultRootWindow (priv->xdisplay), event_mode); - - if (state == META_SEQUENCE_REJECTED) - { - XClientMessageEvent ev; - - ev = (XClientMessageEvent) { - .type = ClientMessage, - .window = meta_backend_x11_get_xwindow (x11), - .message_type = priv->touch_replay_sync_atom, - .format = 32, - .data.l[0] = ++priv->pending_touch_replay_sync_serial, - }; - XSendEvent (priv->xdisplay, meta_backend_x11_get_xwindow (x11), - False, 0, (XEvent *) &ev); - } -} - -static MetaLogicalMonitor * -meta_backend_x11_get_current_logical_monitor (MetaBackend *backend) -{ - MetaBackendX11 *x11 = META_BACKEND_X11 (backend); - MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); - MetaCursorTracker *cursor_tracker; - graphene_point_t point; - MetaMonitorManager *monitor_manager; - MetaLogicalMonitor *logical_monitor; - - if (priv->cached_current_logical_monitor) - return priv->cached_current_logical_monitor; - - cursor_tracker = meta_backend_get_cursor_tracker (backend); - meta_cursor_tracker_get_pointer (cursor_tracker, &point, NULL); - monitor_manager = meta_backend_get_monitor_manager (backend); - logical_monitor = - meta_monitor_manager_get_logical_monitor_at (monitor_manager, - point.x, point.y); - - if (!logical_monitor && monitor_manager->logical_monitors) - logical_monitor = monitor_manager->logical_monitors->data; - - priv->cached_current_logical_monitor = logical_monitor; - return priv->cached_current_logical_monitor; -} - -static struct xkb_keymap * -meta_backend_x11_get_keymap (MetaBackend *backend) -{ - MetaBackendX11 *x11 = META_BACKEND_X11 (backend); - MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); - - if (priv->keymap == NULL) - { - struct xkb_context *context = meta_create_xkb_context (); - priv->keymap = xkb_x11_keymap_new_from_device (context, - priv->xcb, - xkb_x11_get_core_keyboard_device_id (priv->xcb), - XKB_KEYMAP_COMPILE_NO_FLAGS); - if (priv->keymap == NULL) - priv->keymap = xkb_keymap_new_from_names (context, NULL, XKB_KEYMAP_COMPILE_NO_FLAGS); - - xkb_context_unref (context); - } - - return priv->keymap; -} - -static xkb_layout_index_t -meta_backend_x11_get_keymap_layout_group (MetaBackend *backend) -{ - MetaBackendX11 *x11 = META_BACKEND_X11 (backend); - MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); - - return priv->keymap_layout_group; -} - -void -meta_backend_x11_handle_event (MetaBackendX11 *x11, - XEvent *xevent) -{ - MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); - - priv->cached_current_logical_monitor = NULL; -} - -uint8_t -meta_backend_x11_get_xkb_event_base (MetaBackendX11 *x11) -{ - MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); - - return priv->xkb_event_base; -} - -static void -init_xkb_state (MetaBackendX11 *x11) -{ - MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); - struct xkb_keymap *keymap; - int32_t device_id; - struct xkb_state *state; - - keymap = meta_backend_get_keymap (META_BACKEND (x11)); - - device_id = xkb_x11_get_core_keyboard_device_id (priv->xcb); - state = xkb_x11_state_new_from_device (keymap, priv->xcb, device_id); - - priv->keymap_layout_group = - xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_LOCKED); - - xkb_state_unref (state); -} - -static gboolean -meta_backend_x11_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - MetaBackendX11 *x11 = META_BACKEND_X11 (initable); - MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); - Display *xdisplay; - const char *xdisplay_name; - - xdisplay_name = g_getenv ("DISPLAY"); - if (!xdisplay_name) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Unable to open display, DISPLAY not set"); - return FALSE; - } - - xdisplay = XOpenDisplay (xdisplay_name); - if (!xdisplay) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Unable to open display '%s'", xdisplay_name); - return FALSE; - } - - priv->xdisplay = xdisplay; - priv->xcb = XGetXCBConnection (priv->xdisplay); - meta_clutter_x11_set_display (xdisplay); - - init_xkb_state (x11); - - return initable_parent_iface->init (initable, cancellable, error); -} - -static void -initable_iface_init (GInitableIface *initable_iface) -{ - initable_parent_iface = g_type_interface_peek_parent (initable_iface); - - initable_iface->init = meta_backend_x11_initable_init; -} - -static void -meta_backend_x11_dispose (GObject *object) -{ - MetaBackend *backend = META_BACKEND (object); - MetaBackendX11 *x11 = META_BACKEND_X11 (object); - MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); - - if (priv->keymap_state_changed_id) - { - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - ClutterSeat *seat = clutter_backend_get_default_seat (clutter_backend); - ClutterKeymap *keymap; - - seat = clutter_backend_get_default_seat (clutter_backend); - keymap = clutter_seat_get_keymap (seat); - g_clear_signal_handler (&priv->keymap_state_changed_id, keymap); - } - - if (priv->user_active_alarm != None) - { - XSyncDestroyAlarm (priv->xdisplay, priv->user_active_alarm); - priv->user_active_alarm = None; - } - - G_OBJECT_CLASS (meta_backend_x11_parent_class)->dispose (object); -} - -static void -meta_backend_x11_finalize (GObject *object) -{ - MetaBackendX11 *x11 = META_BACKEND_X11 (object); - MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); - - g_clear_pointer (&priv->keymap, xkb_keymap_unref); - - G_OBJECT_CLASS (meta_backend_x11_parent_class)->finalize (object); -} - -static void -meta_backend_x11_class_init (MetaBackendX11Class *klass) -{ - MetaBackendClass *backend_class = META_BACKEND_CLASS (klass); - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = meta_backend_x11_dispose; - object_class->finalize = meta_backend_x11_finalize; - backend_class->create_clutter_backend = meta_backend_x11_create_clutter_backend; - backend_class->create_default_seat = meta_backend_x11_create_default_seat; - backend_class->post_init = meta_backend_x11_post_init; - backend_class->grab_device = meta_backend_x11_grab_device; - backend_class->ungrab_device = meta_backend_x11_ungrab_device; - backend_class->finish_touch_sequence = meta_backend_x11_finish_touch_sequence; - backend_class->get_current_logical_monitor = meta_backend_x11_get_current_logical_monitor; - backend_class->get_keymap = meta_backend_x11_get_keymap; - backend_class->get_keymap_layout_group = meta_backend_x11_get_keymap_layout_group; -} - -static void -meta_backend_x11_init (MetaBackendX11 *x11) -{ - XInitThreads (); -} - -Display * -meta_backend_x11_get_xdisplay (MetaBackendX11 *x11) -{ - MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); - - return priv->xdisplay; -} - -Window -meta_backend_x11_get_xwindow (MetaBackendX11 *x11) -{ - ClutterActor *stage = meta_backend_get_stage (META_BACKEND (x11)); - return meta_x11_get_stage_window (CLUTTER_STAGE (stage)); -} - -void -meta_backend_x11_reload_cursor (MetaBackendX11 *x11) -{ - MetaBackend *backend = META_BACKEND (x11); - MetaCursorRenderer *cursor_renderer = - meta_backend_get_cursor_renderer (backend); - - meta_cursor_renderer_force_update (cursor_renderer); -} - -void -meta_backend_x11_sync_pointer (MetaBackendX11 *backend_x11) -{ - MetaBackend *backend = META_BACKEND (backend_x11); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - ClutterSeat *seat = clutter_backend_get_default_seat (clutter_backend); - ClutterInputDevice *pointer = clutter_seat_get_pointer (seat); - ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend)); - ClutterModifierType modifiers; - ClutterEvent *event; - graphene_point_t pos; - - event = clutter_event_new (CLUTTER_MOTION); - clutter_seat_query_state (seat, pointer, NULL, &pos, &modifiers); - clutter_event_set_flags (event, CLUTTER_EVENT_FLAG_SYNTHETIC); - clutter_event_set_coords (event, pos.x, pos.y); - clutter_event_set_device (event, pointer); - clutter_event_set_state (event, modifiers); - clutter_event_set_source_device (event, NULL); - clutter_event_set_stage (event, stage); - - clutter_event_put (event); - clutter_event_free (event); -} diff --git a/src/backends/x11/meta-backend-x11.h b/src/backends/x11/meta-backend-x11.h deleted file mode 100644 index 2815015d1..000000000 --- a/src/backends/x11/meta-backend-x11.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -#ifndef META_BACKEND_X11_H -#define META_BACKEND_X11_H - -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/x11/meta-clutter-backend-x11.h" - -#define META_TYPE_BACKEND_X11 (meta_backend_x11_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaBackendX11, meta_backend_x11, - META, BACKEND_X11, MetaBackend) - -struct _MetaBackendX11Class -{ - MetaBackendClass parent_class; - - gboolean (* handle_host_xevent) (MetaBackendX11 *x11, - XEvent *event); - void (* translate_device_event) (MetaBackendX11 *x11, - XIDeviceEvent *device_event); - void (* translate_crossing_event) (MetaBackendX11 *x11, - XIEnterEvent *enter_event); -}; - -Display * meta_backend_x11_get_xdisplay (MetaBackendX11 *backend); - -Window meta_backend_x11_get_xwindow (MetaBackendX11 *backend); - -void meta_backend_x11_handle_event (MetaBackendX11 *x11, - XEvent *xevent); - -uint8_t meta_backend_x11_get_xkb_event_base (MetaBackendX11 *x11); - -void meta_backend_x11_reload_cursor (MetaBackendX11 *x11); - -void meta_backend_x11_sync_pointer (MetaBackendX11 *backend_x11); - -#endif /* META_BACKEND_X11_H */ diff --git a/src/backends/x11/meta-barrier-x11.c b/src/backends/x11/meta-barrier-x11.c deleted file mode 100644 index 998aefb38..000000000 --- a/src/backends/x11/meta-barrier-x11.c +++ /dev/null @@ -1,212 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014-2015 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - * Jonas Ådahl - */ - -/** - * SECTION:barrier-x11 - * @Title: MetaBarrierImplX11 - * @Short_Description: Pointer barriers implementation for X11 - */ - -#include "config.h" - -#include -#include -#include - -#include "backends/x11/meta-barrier-x11.h" -#include "core/display-private.h" -#include "meta/barrier.h" -#include "x11/meta-x11-display-private.h" - -struct _MetaBarrierImplX11 -{ - MetaBarrierImpl parent; - - MetaBarrier *barrier; - PointerBarrier xbarrier; -}; - -G_DEFINE_TYPE (MetaBarrierImplX11, - meta_barrier_impl_x11, - META_TYPE_BARRIER_IMPL) - -static gboolean -_meta_barrier_impl_x11_is_active (MetaBarrierImpl *impl) -{ - MetaBarrierImplX11 *self = META_BARRIER_IMPL_X11 (impl); - - return self->xbarrier != 0; -} - -static void -_meta_barrier_impl_x11_release (MetaBarrierImpl *impl, - MetaBarrierEvent *event) -{ - MetaBarrierImplX11 *self = META_BARRIER_IMPL_X11 (impl); - MetaDisplay *display = self->barrier->priv->display; - Display *dpy = meta_x11_display_get_xdisplay (display->x11_display); - - if (META_X11_DISPLAY_HAS_XINPUT_23 (display->x11_display)) - { - XIBarrierReleasePointer (dpy, - META_VIRTUAL_CORE_POINTER_ID, - self->xbarrier, event->event_id); - } -} - -static void -_meta_barrier_impl_x11_destroy (MetaBarrierImpl *impl) -{ - MetaBarrierImplX11 *self = META_BARRIER_IMPL_X11 (impl); - MetaDisplay *display = self->barrier->priv->display; - Display *dpy; - - if (display == NULL) - return; - - dpy = meta_x11_display_get_xdisplay (display->x11_display); - - if (!meta_barrier_is_active (self->barrier)) - return; - - XFixesDestroyPointerBarrier (dpy, self->xbarrier); - g_hash_table_remove (display->x11_display->xids, &self->xbarrier); - self->xbarrier = 0; -} - -MetaBarrierImpl * -meta_barrier_impl_x11_new (MetaBarrier *barrier) -{ - MetaBarrierImplX11 *self; - MetaDisplay *display = barrier->priv->display; - Display *dpy; - Window root; - unsigned int allowed_motion_dirs; - - if (display == NULL) - { - g_warning ("A display must be provided when constructing a barrier."); - return NULL; - } - - self = g_object_new (META_TYPE_BARRIER_IMPL_X11, NULL); - self->barrier = barrier; - - dpy = meta_x11_display_get_xdisplay (display->x11_display); - root = DefaultRootWindow (dpy); - - allowed_motion_dirs = - meta_border_get_allows_directions (&barrier->priv->border); - self->xbarrier = XFixesCreatePointerBarrier (dpy, root, - barrier->priv->border.line.a.x, - barrier->priv->border.line.a.y, - barrier->priv->border.line.b.x, - barrier->priv->border.line.b.y, - allowed_motion_dirs, - 0, NULL); - - g_hash_table_insert (display->x11_display->xids, &self->xbarrier, barrier); - - return META_BARRIER_IMPL (self); -} - -static void -meta_barrier_fire_xevent (MetaBarrier *barrier, - XIBarrierEvent *xevent) -{ - MetaBarrierEvent *event = g_new0 (MetaBarrierEvent, 1); - - event->ref_count = 1; - event->event_id = xevent->eventid; - event->time = xevent->time; - event->dt = xevent->dtime; - - event->x = xevent->root_x; - event->y = xevent->root_y; - event->dx = xevent->dx; - event->dy = xevent->dy; - - event->released = (xevent->flags & XIBarrierPointerReleased) != 0; - event->grabbed = (xevent->flags & XIBarrierDeviceIsGrabbed) != 0; - - switch (xevent->evtype) - { - case XI_BarrierHit: - _meta_barrier_emit_hit_signal (barrier, event); - break; - case XI_BarrierLeave: - _meta_barrier_emit_left_signal (barrier, event); - break; - default: - g_assert_not_reached (); - } - - meta_barrier_event_unref (event); -} - -gboolean -meta_x11_display_process_barrier_xevent (MetaX11Display *x11_display, - XIEvent *event) -{ - MetaBarrier *barrier; - XIBarrierEvent *xev; - - if (event == NULL) - return FALSE; - - switch (event->evtype) - { - case XI_BarrierHit: - case XI_BarrierLeave: - break; - default: - return FALSE; - } - - xev = (XIBarrierEvent *) event; - barrier = g_hash_table_lookup (x11_display->xids, &xev->barrier); - if (barrier != NULL) - { - meta_barrier_fire_xevent (barrier, xev); - return TRUE; - } - - return FALSE; -} - -static void -meta_barrier_impl_x11_class_init (MetaBarrierImplX11Class *klass) -{ - MetaBarrierImplClass *impl_class = META_BARRIER_IMPL_CLASS (klass); - - impl_class->is_active = _meta_barrier_impl_x11_is_active; - impl_class->release = _meta_barrier_impl_x11_release; - impl_class->destroy = _meta_barrier_impl_x11_destroy; -} - -static void -meta_barrier_impl_x11_init (MetaBarrierImplX11 *self) -{ -} diff --git a/src/backends/x11/meta-barrier-x11.h b/src/backends/x11/meta-barrier-x11.h deleted file mode 100644 index 3562d106f..000000000 --- a/src/backends/x11/meta-barrier-x11.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#ifndef META_BARRIER_X11_H -#define META_BARRIER_X11_H - -#include "backends/meta-barrier-private.h" - -G_BEGIN_DECLS - -#define META_TYPE_BARRIER_IMPL_X11 (meta_barrier_impl_x11_get_type ()) -G_DECLARE_FINAL_TYPE (MetaBarrierImplX11, - meta_barrier_impl_x11, - META, BARRIER_IMPL_X11, - MetaBarrierImpl) - -MetaBarrierImpl *meta_barrier_impl_x11_new (MetaBarrier *barrier); - -G_END_DECLS - -#endif /* META_BARRIER_X11_H1 */ diff --git a/src/backends/x11/meta-clutter-backend-x11.c b/src/backends/x11/meta-clutter-backend-x11.c deleted file mode 100644 index d94987879..000000000 --- a/src/backends/x11/meta-clutter-backend-x11.c +++ /dev/null @@ -1,745 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#include "config.h" - -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-renderer.h" -#include "backends/x11/meta-clutter-backend-x11.h" -#include "backends/x11/meta-keymap-x11.h" -#include "backends/x11/meta-seat-x11.h" -#include "backends/x11/meta-xkb-a11y-x11.h" -#include "backends/x11/nested/meta-stage-x11-nested.h" -#include "clutter/clutter-mutter.h" -#include "clutter/clutter.h" -#include "cogl/cogl-xlib.h" -#include "core/bell.h" -#include "meta/meta-backend.h" - -typedef struct _MetaX11EventFilter MetaX11EventFilter; - -struct _MetaX11EventFilter -{ - MetaX11FilterFunc func; - gpointer data; -}; - -G_DEFINE_TYPE (MetaClutterBackendX11, meta_clutter_backend_x11, - CLUTTER_TYPE_BACKEND) - - -/* atoms; remember to add the code that assigns the atom value to - * the member of the MetaClutterBackendX11 structure if you add an - * atom name here. do not change the order! - */ -static const gchar *atom_names[] = { - "_NET_WM_PID", - "_NET_WM_PING", - "_NET_WM_STATE", - "_NET_WM_USER_TIME", - "WM_PROTOCOLS", - "WM_DELETE_WINDOW", - "_XEMBED", - "_XEMBED_INFO", - "_NET_WM_NAME", - "UTF8_STRING", -}; - -#define N_ATOM_NAMES G_N_ELEMENTS (atom_names) - -/* various flags corresponding to pre init setup calls */ -static gboolean clutter_enable_xinput = TRUE; -static gboolean clutter_enable_stereo = FALSE; -static Display *_foreign_dpy = NULL; - -/* options */ -static gchar *clutter_display_name = NULL; -static gint clutter_screen = -1; -static gboolean clutter_synchronise = FALSE; - -/* X error trap */ -static int TrappedErrorCode = 0; -static int (* old_error_handler) (Display *, XErrorEvent *); - -static MetaX11FilterReturn -cogl_xlib_filter (XEvent *xevent, - ClutterEvent *event, - gpointer data) -{ - ClutterBackend *backend = data; - MetaX11FilterReturn retval; - CoglFilterReturn ret; - - ret = cogl_xlib_renderer_handle_event (backend->cogl_renderer, xevent); - switch (ret) - { - case COGL_FILTER_REMOVE: - retval = META_X11_FILTER_REMOVE; - break; - - case COGL_FILTER_CONTINUE: - default: - retval = META_X11_FILTER_CONTINUE; - break; - } - - return retval; -} - -static gboolean -meta_clutter_backend_x11_pre_parse (ClutterBackend *backend, - GError **error) -{ - const gchar *env_string; - - /* we don't fail here if DISPLAY is not set, as the user - * might pass the --display command line switch - */ - env_string = g_getenv ("DISPLAY"); - if (env_string) - { - clutter_display_name = g_strdup (env_string); - env_string = NULL; - } - - env_string = g_getenv ("CLUTTER_DISABLE_XINPUT"); - if (env_string) - { - clutter_enable_xinput = FALSE; - env_string = NULL; - } - - return TRUE; -} - -static gboolean -meta_clutter_backend_x11_post_parse (ClutterBackend *backend, - GError **error) -{ - MetaClutterBackendX11 *backend_x11 = META_CLUTTER_BACKEND_X11 (backend); - Atom atoms[N_ATOM_NAMES]; - - if (_foreign_dpy) - backend_x11->xdisplay = _foreign_dpy; - - /* Only open connection if not already set by prior call to - * clutter_x11_set_display() - */ - if (backend_x11->xdisplay == NULL) - { - if (clutter_display_name != NULL && - *clutter_display_name != '\0') - { - g_debug ("XOpenDisplay on '%s'", clutter_display_name); - - backend_x11->xdisplay = XOpenDisplay (clutter_display_name); - if (backend_x11->xdisplay == NULL) - { - g_set_error (error, CLUTTER_INIT_ERROR, - CLUTTER_INIT_ERROR_BACKEND, - "Unable to open display '%s'", - clutter_display_name); - return FALSE; - } - } - else - { - g_set_error_literal (error, CLUTTER_INIT_ERROR, - CLUTTER_INIT_ERROR_BACKEND, - "Unable to open display. You have to set the " - "DISPLAY environment variable, or use the " - "--display command line argument"); - return FALSE; - } - } - - g_assert (backend_x11->xdisplay != NULL); - - g_debug ("Getting the X screen"); - - /* add event filter for Cogl events */ - meta_clutter_x11_add_filter (cogl_xlib_filter, backend); - - if (clutter_screen == -1) - backend_x11->xscreen = DefaultScreenOfDisplay (backend_x11->xdisplay); - else - backend_x11->xscreen = ScreenOfDisplay (backend_x11->xdisplay, - clutter_screen); - - backend_x11->xscreen_num = XScreenNumberOfScreen (backend_x11->xscreen); - backend_x11->xscreen_width = WidthOfScreen (backend_x11->xscreen); - backend_x11->xscreen_height = HeightOfScreen (backend_x11->xscreen); - - backend_x11->xwin_root = RootWindow (backend_x11->xdisplay, - backend_x11->xscreen_num); - - backend_x11->display_name = g_strdup (clutter_display_name); - - if (clutter_synchronise) - XSynchronize (backend_x11->xdisplay, True); - - XInternAtoms (backend_x11->xdisplay, - (char **) atom_names, N_ATOM_NAMES, - False, atoms); - - 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_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); - - g_debug ("X Display '%s'[%p] opened (screen:%d, root:%u, dpi:%f)", - backend_x11->display_name, - backend_x11->xdisplay, - backend_x11->xscreen_num, - (unsigned int) backend_x11->xwin_root, - clutter_backend_get_resolution (backend)); - - return TRUE; -} - -static const GOptionEntry entries[] = -{ - { - "display", 0, - G_OPTION_FLAG_IN_MAIN, - G_OPTION_ARG_STRING, &clutter_display_name, - N_("X display to use"), "DISPLAY" - }, - { - "screen", 0, - G_OPTION_FLAG_IN_MAIN, - G_OPTION_ARG_INT, &clutter_screen, - N_("X screen to use"), "SCREEN" - }, - { "synch", 0, - 0, - G_OPTION_ARG_NONE, &clutter_synchronise, - N_("Make X calls synchronous"), NULL - }, - { - "disable-xinput", 0, - G_OPTION_FLAG_REVERSE, - G_OPTION_ARG_NONE, &clutter_enable_xinput, - N_("Disable XInput support"), NULL - }, - { NULL } -}; - -static void -meta_clutter_backend_x11_add_options (ClutterBackend *backend, - GOptionGroup *group) -{ - g_option_group_add_entries (group, entries); -} - -static void -meta_clutter_backend_x11_finalize (GObject *gobject) -{ - MetaClutterBackendX11 *backend_x11 = META_CLUTTER_BACKEND_X11 (gobject); - - g_free (backend_x11->display_name); - - meta_clutter_x11_remove_filter (cogl_xlib_filter, gobject); - - XCloseDisplay (backend_x11->xdisplay); - - G_OBJECT_CLASS (meta_clutter_backend_x11_parent_class)->finalize (gobject); -} - -static ClutterFeatureFlags -meta_clutter_backend_x11_get_features (ClutterBackend *backend) -{ - ClutterFeatureFlags flags = CLUTTER_FEATURE_STAGE_CURSOR; - - flags |= - CLUTTER_BACKEND_CLASS (meta_clutter_backend_x11_parent_class)->get_features (backend); - - return flags; -} - -static void -update_last_event_time (MetaClutterBackendX11 *backend_x11, - XEvent *xevent) -{ - Time current_time = CurrentTime; - Time last_time = backend_x11->last_event_time; - - switch (xevent->type) - { - case KeyPress: - case KeyRelease: - current_time = xevent->xkey.time; - break; - - case ButtonPress: - case ButtonRelease: - current_time = xevent->xbutton.time; - break; - - case MotionNotify: - current_time = xevent->xmotion.time; - break; - - case EnterNotify: - case LeaveNotify: - current_time = xevent->xcrossing.time; - break; - - case PropertyNotify: - current_time = xevent->xproperty.time; - break; - - default: - break; - } - - /* only change the current event time if it's after the previous event - * time, or if it is at least 30 seconds earlier - in case the system - * clock was changed - */ - if ((current_time != CurrentTime) && - (current_time > last_time || (last_time - current_time > (30 * 1000)))) - backend_x11->last_event_time = current_time; -} - -static gboolean -check_onscreen_template (CoglRenderer *renderer, - CoglOnscreenTemplate *onscreen_template, - gboolean enable_stereo, - GError **error) -{ - GError *internal_error = NULL; - - cogl_onscreen_template_set_stereo_enabled (onscreen_template, - clutter_enable_stereo); - - /* cogl_renderer_check_onscreen_template() is actually just a - * shorthand for creating a CoglDisplay, and calling - * cogl_display_setup() on it, then throwing the display away. If we - * could just return that display, then it would be more efficient - * not to use cogl_renderer_check_onscreen_template(). However, the - * backend API requires that we return an CoglDisplay that has not - * yet been setup, so one way or the other we'll have to discard the - * first display and make a new fresh one. - */ - if (cogl_renderer_check_onscreen_template (renderer, onscreen_template, &internal_error)) - { - clutter_enable_stereo = enable_stereo; - - return TRUE; - } - else - { - g_set_error_literal (error, CLUTTER_INIT_ERROR, - CLUTTER_INIT_ERROR_BACKEND, - internal_error != NULL - ? internal_error->message - : "Creation of a CoglDisplay failed"); - - g_clear_error (&internal_error); - - return FALSE; - } -} - -static CoglDisplay * -meta_clutter_backend_x11_get_display (ClutterBackend *backend, - CoglRenderer *renderer, - CoglSwapChain *swap_chain, - GError **error) -{ - CoglOnscreenTemplate *onscreen_template; - CoglDisplay *display = NULL; - gboolean res = FALSE; - - onscreen_template = cogl_onscreen_template_new (swap_chain); - - /* It's possible that the current renderer doesn't support transparency - * or doesn't support stereo, so we try the different combinations. - */ - if (clutter_enable_stereo) - res = check_onscreen_template (renderer, onscreen_template, - TRUE, error); - - if (!res) - res = check_onscreen_template (renderer, onscreen_template, - FALSE, error); - - if (res) - display = cogl_display_new (renderer, onscreen_template); - - cogl_object_unref (onscreen_template); - - return display; -} - -static CoglRenderer * -meta_clutter_backend_x11_get_renderer (ClutterBackend *clutter_backend, - GError **error) -{ - MetaBackend *backend = meta_get_backend (); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - - return meta_renderer_create_cogl_renderer (renderer); -} - -static ClutterStageWindow * -meta_clutter_backend_x11_create_stage (ClutterBackend *backend, - ClutterStage *wrapper, - GError **error) -{ - ClutterStageWindow *stage; - GType stage_type; - - if (meta_is_wayland_compositor ()) - stage_type = META_TYPE_STAGE_X11_NESTED; - else - stage_type = META_TYPE_STAGE_X11; - - stage = g_object_new (stage_type, - "backend", backend, - "wrapper", wrapper, - NULL); - return stage; -} - -static gboolean -meta_clutter_backend_x11_process_event_filters (MetaClutterBackendX11 *backend_x11, - gpointer native, - ClutterEvent *event) -{ - XEvent *xevent = native; - - /* X11 filter functions have a higher priority */ - if (backend_x11->event_filters != NULL) - { - GSList *node = backend_x11->event_filters; - - while (node != NULL) - { - MetaX11EventFilter *filter = node->data; - - switch (filter->func (xevent, event, filter->data)) - { - case META_X11_FILTER_CONTINUE: - break; - - case META_X11_FILTER_TRANSLATE: - return TRUE; - - case META_X11_FILTER_REMOVE: - return FALSE; - - default: - break; - } - - node = node->next; - } - } - - return FALSE; -} - -static gboolean -meta_clutter_backend_x11_translate_event (ClutterBackend *clutter_backend, - gpointer native, - ClutterEvent *event) -{ - MetaClutterBackendX11 *backend_x11 = - META_CLUTTER_BACKEND_X11 (clutter_backend); - MetaBackend *backend = meta_get_backend (); - MetaStageX11 *stage_x11; - ClutterSeat *seat; - - if (meta_clutter_backend_x11_process_event_filters (backend_x11, - native, - event)) - return TRUE; - - /* we update the event time only for events that can - * actually reach Clutter's event queue - */ - update_last_event_time (backend_x11, native); - - stage_x11 = - META_STAGE_X11 (clutter_backend_get_stage_window (clutter_backend)); - if (meta_stage_x11_translate_event (stage_x11, native, event)) - return TRUE; - - seat = meta_backend_get_default_seat (backend); - if (meta_seat_x11_translate_event (META_SEAT_X11 (seat), native, event)) - return TRUE; - - return FALSE; -} - -static ClutterSeat * -meta_clutter_backend_x11_get_default_seat (ClutterBackend *clutter_backend) -{ - MetaBackend *backend = meta_get_backend (); - - return meta_backend_get_default_seat (backend); -} - -static gboolean -meta_clutter_backend_x11_is_display_server (ClutterBackend *backend) -{ - return meta_is_wayland_compositor (); -} - -static void -meta_clutter_backend_x11_init (MetaClutterBackendX11 *clutter_backend_x11) -{ - clutter_backend_x11->last_event_time = CurrentTime; -} - -static void -meta_clutter_backend_x11_class_init (MetaClutterBackendX11Class *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - ClutterBackendClass *clutter_backend_class = CLUTTER_BACKEND_CLASS (klass); - - gobject_class->finalize = meta_clutter_backend_x11_finalize; - - clutter_backend_class->pre_parse = meta_clutter_backend_x11_pre_parse; - clutter_backend_class->post_parse = meta_clutter_backend_x11_post_parse; - clutter_backend_class->add_options = meta_clutter_backend_x11_add_options; - clutter_backend_class->get_features = meta_clutter_backend_x11_get_features; - - clutter_backend_class->get_display = meta_clutter_backend_x11_get_display; - clutter_backend_class->get_renderer = meta_clutter_backend_x11_get_renderer; - clutter_backend_class->create_stage = meta_clutter_backend_x11_create_stage; - clutter_backend_class->translate_event = meta_clutter_backend_x11_translate_event; - clutter_backend_class->get_default_seat = meta_clutter_backend_x11_get_default_seat; - clutter_backend_class->is_display_server = meta_clutter_backend_x11_is_display_server; -} - -static int -error_handler (Display *xdisplay, - XErrorEvent *error) -{ - TrappedErrorCode = error->error_code; - return 0; -} - -void -meta_clutter_x11_trap_x_errors (void) -{ - TrappedErrorCode = 0; - old_error_handler = XSetErrorHandler (error_handler); -} - -gint -meta_clutter_x11_untrap_x_errors (void) -{ - XSetErrorHandler (old_error_handler); - - return TrappedErrorCode; -} - -Display * -meta_clutter_x11_get_default_display (void) -{ - ClutterBackend *backend = clutter_get_default_backend (); - - if (backend == NULL) - { - g_critical ("The Clutter backend has not been initialised"); - return NULL; - } - - if (!META_IS_CLUTTER_BACKEND_X11 (backend)) - { - g_critical ("The Clutter backend is not a X11 backend"); - return NULL; - } - - return META_CLUTTER_BACKEND_X11 (backend)->xdisplay; -} - -void -meta_clutter_x11_set_display (Display *xdisplay) -{ - if (_clutter_context_is_initialized ()) - { - g_warning ("%s() can only be used before calling clutter_init()", - G_STRFUNC); - return; - } - - _foreign_dpy= xdisplay; -} - -int -meta_clutter_x11_get_default_screen (void) -{ - ClutterBackend *backend = clutter_get_default_backend (); - - if (backend == NULL) - { - g_critical ("The Clutter backend has not been initialised"); - return 0; - } - - if (!META_IS_CLUTTER_BACKEND_X11 (backend)) - { - g_critical ("The Clutter backend is not a X11 backend"); - return 0; - } - - return META_CLUTTER_BACKEND_X11 (backend)->xscreen_num; -} - -Window -meta_clutter_x11_get_root_window (void) -{ - ClutterBackend *backend = clutter_get_default_backend (); - - if (backend == NULL) - { - g_critical ("The Clutter backend has not been initialised"); - return None; - } - - if (!META_IS_CLUTTER_BACKEND_X11 (backend)) - { - g_critical ("The Clutter backend is not a X11 backend"); - return None; - } - - return META_CLUTTER_BACKEND_X11 (backend)->xwin_root; -} - -void -meta_clutter_x11_add_filter (MetaX11FilterFunc func, - gpointer data) -{ - MetaX11EventFilter *filter; - ClutterBackend *backend = clutter_get_default_backend (); - MetaClutterBackendX11 *backend_x11; - - g_return_if_fail (func != NULL); - - if (backend == NULL) - { - g_critical ("The Clutter backend has not been initialised"); - return; - } - - if (!META_IS_CLUTTER_BACKEND_X11 (backend)) - { - g_critical ("The Clutter backend is not a X11 backend"); - return; - } - - backend_x11 = META_CLUTTER_BACKEND_X11 (backend); - - filter = g_new0 (MetaX11EventFilter, 1); - filter->func = func; - filter->data = data; - - backend_x11->event_filters = - g_slist_append (backend_x11->event_filters, filter); - - return; -} - -void -meta_clutter_x11_remove_filter (MetaX11FilterFunc func, - gpointer data) -{ - GSList *tmp_list, *this; - MetaX11EventFilter *filter; - ClutterBackend *backend = clutter_get_default_backend (); - MetaClutterBackendX11 *backend_x11; - - g_return_if_fail (func != NULL); - - if (backend == NULL) - { - g_critical ("The Clutter backend has not been initialised"); - return; - } - - if (!META_IS_CLUTTER_BACKEND_X11 (backend)) - { - g_critical ("The Clutter backend is not a X11 backend"); - return; - } - - backend_x11 = META_CLUTTER_BACKEND_X11 (backend); - - tmp_list = backend_x11->event_filters; - - while (tmp_list) - { - filter = tmp_list->data; - this = tmp_list; - tmp_list = tmp_list->next; - - if (filter->func == func && filter->data == data) - { - backend_x11->event_filters = - g_slist_remove_link (backend_x11->event_filters, this); - - g_slist_free_1 (this); - g_free (filter); - - return; - } - } -} - -void -meta_clutter_x11_set_use_stereo_stage (gboolean use_stereo) -{ - if (_clutter_context_is_initialized ()) - { - g_warning ("%s() can only be used before calling clutter_init()", - G_STRFUNC); - return; - } - - g_debug ("STEREO stages are %s", - use_stereo ? "enabled" : "disabled"); - - clutter_enable_stereo = use_stereo; -} - -gboolean -meta_clutter_x11_get_use_stereo_stage (void) -{ - return clutter_enable_stereo; -} diff --git a/src/backends/x11/meta-clutter-backend-x11.h b/src/backends/x11/meta-clutter-backend-x11.h deleted file mode 100644 index d91a2f3af..000000000 --- a/src/backends/x11/meta-clutter-backend-x11.h +++ /dev/null @@ -1,96 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#ifndef META_CLUTTER_BACKEND_X11_H -#define META_CLUTTER_BACKEND_X11_H - -#include - -#include "clutter/clutter-mutter.h" - -struct _MetaClutterBackendX11 -{ - ClutterBackend parent_instance; - - Display *xdisplay; - char *display_name; - - Screen *xscreen; - int xscreen_num; - int xscreen_width; - int xscreen_height; - - Window xwin_root; - - /* event source */ - GSList *event_filters; - - /* props */ - Atom atom_NET_WM_PID; - Atom atom_NET_WM_PING; - Atom atom_NET_WM_STATE; - Atom atom_NET_WM_USER_TIME; - Atom atom_WM_PROTOCOLS; - Atom atom_WM_DELETE_WINDOW; - Atom atom_XEMBED; - Atom atom_XEMBED_INFO; - Atom atom_NET_WM_NAME; - Atom atom_UTF8_STRING; - - Time last_event_time; -}; - -#define META_TYPE_CLUTTER_BACKEND_X11 (meta_clutter_backend_x11_get_type ()) -G_DECLARE_FINAL_TYPE (MetaClutterBackendX11, meta_clutter_backend_x11, - META, CLUTTER_BACKEND_X11, - ClutterBackend) - -typedef enum -{ - META_X11_FILTER_CONTINUE, - META_X11_FILTER_TRANSLATE, - META_X11_FILTER_REMOVE -} MetaX11FilterReturn; - -typedef MetaX11FilterReturn (*MetaX11FilterFunc) (XEvent *xev, - ClutterEvent *cev, - gpointer data); - -void meta_clutter_x11_trap_x_errors (void); -gint meta_clutter_x11_untrap_x_errors (void); - -Display *meta_clutter_x11_get_default_display (void); -int meta_clutter_x11_get_default_screen (void); -Window meta_clutter_x11_get_root_window (void); -void meta_clutter_x11_set_display (Display * xdpy); - -void meta_clutter_x11_add_filter (MetaX11FilterFunc func, - gpointer data); -void meta_clutter_x11_remove_filter (MetaX11FilterFunc func, - gpointer data); - -void meta_clutter_x11_set_use_stereo_stage (gboolean use_stereo); -gboolean meta_clutter_x11_get_use_stereo_stage (void); - -#endif /* META_CLUTTER_BACKEND_X11_H */ diff --git a/src/backends/x11/meta-crtc-xrandr.c b/src/backends/x11/meta-crtc-xrandr.c deleted file mode 100644 index e06448b6e..000000000 --- a/src/backends/x11/meta-crtc-xrandr.c +++ /dev/null @@ -1,308 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001, 2002 Havoc Pennington - * Copyright (C) 2001, 2002 Havoc Pennington - * Copyright (C) 2002, 2003 Red Hat Inc. - * Some ICCCM manager selection code derived from fvwm2, - * Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * Copyright (C) 2002, 2003 Red Hat Inc. - * Some ICCCM manager selection code derived from fvwm2, - * Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * Copyright (C) 2013-2017 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include "config.h" - -#include "backends/x11/meta-crtc-xrandr.h" - -#include -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-crtc.h" -#include "backends/meta-output.h" -#include "backends/x11/meta-crtc-xrandr.h" -#include "backends/x11/meta-gpu-xrandr.h" -#include "backends/x11/meta-monitor-manager-xrandr.h" - -struct _MetaCrtcXrandr -{ - MetaCrtc parent; - - MetaRectangle rect; - MetaMonitorTransform transform; - MetaCrtcMode *current_mode; -}; - -G_DEFINE_TYPE (MetaCrtcXrandr, meta_crtc_xrandr, META_TYPE_CRTC) - -gboolean -meta_crtc_xrandr_set_config (MetaCrtcXrandr *crtc_xrandr, - xcb_randr_crtc_t xrandr_crtc, - xcb_timestamp_t timestamp, - int x, - int y, - xcb_randr_mode_t mode, - xcb_randr_rotation_t rotation, - xcb_randr_output_t *outputs, - int n_outputs, - xcb_timestamp_t *out_timestamp) -{ - MetaGpu *gpu = meta_crtc_get_gpu (META_CRTC (crtc_xrandr)); - MetaGpuXrandr *gpu_xrandr = META_GPU_XRANDR (gpu); - MetaBackend *backend = meta_gpu_get_backend (gpu); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerXrandr *monitor_manager_xrandr = - META_MONITOR_MANAGER_XRANDR (monitor_manager); - Display *xdisplay; - XRRScreenResources *resources; - xcb_connection_t *xcb_conn; - xcb_timestamp_t config_timestamp; - xcb_randr_set_crtc_config_cookie_t cookie; - xcb_randr_set_crtc_config_reply_t *reply; - xcb_generic_error_t *xcb_error = NULL; - - xdisplay = meta_monitor_manager_xrandr_get_xdisplay (monitor_manager_xrandr); - xcb_conn = XGetXCBConnection (xdisplay); - resources = meta_gpu_xrandr_get_resources (gpu_xrandr); - config_timestamp = resources->configTimestamp; - cookie = xcb_randr_set_crtc_config (xcb_conn, - xrandr_crtc, - timestamp, - config_timestamp, - x, y, - mode, - rotation, - n_outputs, - outputs); - reply = xcb_randr_set_crtc_config_reply (xcb_conn, - cookie, - &xcb_error); - if (xcb_error || !reply) - { - free (xcb_error); - free (reply); - return FALSE; - } - - *out_timestamp = reply->timestamp; - free (reply); - - return TRUE; -} - -static MetaMonitorTransform -meta_monitor_transform_from_xrandr (Rotation rotation) -{ - static const MetaMonitorTransform y_reflected_map[4] = { - META_MONITOR_TRANSFORM_FLIPPED_180, - META_MONITOR_TRANSFORM_FLIPPED_90, - META_MONITOR_TRANSFORM_FLIPPED, - META_MONITOR_TRANSFORM_FLIPPED_270 - }; - MetaMonitorTransform ret; - - switch (rotation & 0x7F) - { - default: - case RR_Rotate_0: - ret = META_MONITOR_TRANSFORM_NORMAL; - break; - case RR_Rotate_90: - ret = META_MONITOR_TRANSFORM_90; - break; - case RR_Rotate_180: - ret = META_MONITOR_TRANSFORM_180; - break; - case RR_Rotate_270: - ret = META_MONITOR_TRANSFORM_270; - break; - } - - if (rotation & RR_Reflect_X) - return ret + 4; - else if (rotation & RR_Reflect_Y) - return y_reflected_map[ret]; - else - return ret; -} - -#define ALL_ROTATIONS (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270) - -static MetaMonitorTransform -meta_monitor_transform_from_xrandr_all (Rotation rotation) -{ - unsigned ret; - - /* Handle the common cases first (none or all) */ - if (rotation == 0 || rotation == RR_Rotate_0) - return (1 << META_MONITOR_TRANSFORM_NORMAL); - - /* All rotations and one reflection -> all of them by composition */ - if ((rotation & ALL_ROTATIONS) && - ((rotation & RR_Reflect_X) || (rotation & RR_Reflect_Y))) - return META_MONITOR_ALL_TRANSFORMS; - - ret = 1 << META_MONITOR_TRANSFORM_NORMAL; - if (rotation & RR_Rotate_90) - ret |= 1 << META_MONITOR_TRANSFORM_90; - if (rotation & RR_Rotate_180) - ret |= 1 << META_MONITOR_TRANSFORM_180; - if (rotation & RR_Rotate_270) - ret |= 1 << META_MONITOR_TRANSFORM_270; - if (rotation & (RR_Rotate_0 | RR_Reflect_X)) - ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED; - if (rotation & (RR_Rotate_90 | RR_Reflect_X)) - ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED_90; - if (rotation & (RR_Rotate_180 | RR_Reflect_X)) - ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED_180; - if (rotation & (RR_Rotate_270 | RR_Reflect_X)) - ret |= 1 << META_MONITOR_TRANSFORM_FLIPPED_270; - - return ret; -} - -gboolean -meta_crtc_xrandr_is_assignment_changed (MetaCrtcXrandr *crtc_xrandr, - MetaCrtcAssignment *crtc_assignment) -{ - unsigned int i; - - if (crtc_xrandr->current_mode != crtc_assignment->mode) - return TRUE; - - if (crtc_xrandr->rect.x != (int) roundf (crtc_assignment->layout.origin.x)) - return TRUE; - - if (crtc_xrandr->rect.y != (int) roundf (crtc_assignment->layout.origin.y)) - return TRUE; - - if (crtc_xrandr->transform != crtc_assignment->transform) - return TRUE; - - for (i = 0; i < crtc_assignment->outputs->len; i++) - { - MetaOutput *output = ((MetaOutput**) crtc_assignment->outputs->pdata)[i]; - MetaCrtc *assigned_crtc; - - assigned_crtc = meta_output_get_assigned_crtc (output); - if (assigned_crtc != META_CRTC (crtc_xrandr)) - return TRUE; - } - - return FALSE; -} - -MetaCrtcMode * -meta_crtc_xrandr_get_current_mode (MetaCrtcXrandr *crtc_xrandr) -{ - return crtc_xrandr->current_mode; -} - -MetaCrtcXrandr * -meta_crtc_xrandr_new (MetaGpuXrandr *gpu_xrandr, - XRRCrtcInfo *xrandr_crtc, - RRCrtc crtc_id, - XRRScreenResources *resources) -{ - MetaGpu *gpu = META_GPU (gpu_xrandr); - MetaBackend *backend = meta_gpu_get_backend (gpu); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerXrandr *monitor_manager_xrandr = - META_MONITOR_MANAGER_XRANDR (monitor_manager); - Display *xdisplay = - meta_monitor_manager_xrandr_get_xdisplay (monitor_manager_xrandr); - MetaMonitorTransform all_transforms; - MetaCrtcXrandr *crtc_xrandr; - XRRPanning *panning; - unsigned int i; - GList *modes; - - all_transforms = - meta_monitor_transform_from_xrandr_all (xrandr_crtc->rotations); - crtc_xrandr = g_object_new (META_TYPE_CRTC_XRANDR, - "id", (uint64_t) crtc_id, - "gpu", gpu, - "all-transforms", all_transforms, - NULL); - - crtc_xrandr->transform = - meta_monitor_transform_from_xrandr (xrandr_crtc->rotation); - - panning = XRRGetPanning (xdisplay, resources, crtc_id); - if (panning && panning->width > 0 && panning->height > 0) - { - crtc_xrandr->rect = (MetaRectangle) { - .x = panning->left, - .y = panning->top, - .width = panning->width, - .height = panning->height, - }; - } - else - { - crtc_xrandr->rect = (MetaRectangle) { - .x = xrandr_crtc->x, - .y = xrandr_crtc->y, - .width = xrandr_crtc->width, - .height = xrandr_crtc->height, - }; - } - XRRFreePanning (panning); - - modes = meta_gpu_get_modes (gpu); - for (i = 0; i < (unsigned int) resources->nmode; i++) - { - if (resources->modes[i].id == xrandr_crtc->mode) - { - crtc_xrandr->current_mode = g_list_nth_data (modes, i); - break; - } - } - - if (crtc_xrandr->current_mode) - { - meta_crtc_set_config (META_CRTC (crtc_xrandr), - &GRAPHENE_RECT_INIT (crtc_xrandr->rect.x, - crtc_xrandr->rect.y, - crtc_xrandr->rect.width, - crtc_xrandr->rect.height), - crtc_xrandr->current_mode, - crtc_xrandr->transform); - } - - return crtc_xrandr; -} - -static void -meta_crtc_xrandr_init (MetaCrtcXrandr *crtc_xrandr) -{ -} - -static void -meta_crtc_xrandr_class_init (MetaCrtcXrandrClass *klass) -{ -} diff --git a/src/backends/x11/meta-crtc-xrandr.h b/src/backends/x11/meta-crtc-xrandr.h deleted file mode 100644 index dbf5da0c6..000000000 --- a/src/backends/x11/meta-crtc-xrandr.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 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_CRTC_XRANDR_H -#define META_CRTC_XRANDR_H - -#include -#include - -#include "backends/meta-crtc.h" -#include "backends/x11/meta-gpu-xrandr.h" - -#define META_TYPE_CRTC_XRANDR (meta_crtc_xrandr_get_type ()) -G_DECLARE_FINAL_TYPE (MetaCrtcXrandr, meta_crtc_xrandr, - META, CRTC_XRANDR, - MetaCrtc) - -gboolean meta_crtc_xrandr_set_config (MetaCrtcXrandr *crtc_xrandr, - xcb_randr_crtc_t xrandr_crtc, - xcb_timestamp_t timestamp, - int x, - int y, - xcb_randr_mode_t mode, - xcb_randr_rotation_t rotation, - xcb_randr_output_t *outputs, - int n_outputs, - xcb_timestamp_t *out_timestamp); - -gboolean meta_crtc_xrandr_is_assignment_changed (MetaCrtcXrandr *crtc_xrandr, - MetaCrtcAssignment *crtc_assignment); - -MetaCrtcMode * meta_crtc_xrandr_get_current_mode (MetaCrtcXrandr *crtc_xrandr); - -MetaCrtcXrandr * meta_crtc_xrandr_new (MetaGpuXrandr *gpu_xrandr, - XRRCrtcInfo *xrandr_crtc, - RRCrtc crtc_id, - XRRScreenResources *resources); - -#endif /* META_CRTC_XRANDR_H */ diff --git a/src/backends/x11/meta-cursor-renderer-x11.c b/src/backends/x11/meta-cursor-renderer-x11.c deleted file mode 100644 index 4d81f8027..000000000 --- a/src/backends/x11/meta-cursor-renderer-x11.c +++ /dev/null @@ -1,114 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -#include "config.h" - -#include "backends/x11/meta-cursor-renderer-x11.h" - -#include - -#include "backends/meta-cursor-sprite-xcursor.h" -#include "backends/meta-stage-private.h" -#include "backends/x11/meta-backend-x11.h" - -struct _MetaCursorRendererX11Private -{ - gboolean server_cursor_visible; -}; -typedef struct _MetaCursorRendererX11Private MetaCursorRendererX11Private; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererX11, meta_cursor_renderer_x11, META_TYPE_CURSOR_RENDERER); - -static gboolean -meta_cursor_renderer_x11_update_cursor (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite) -{ - MetaCursorRendererX11 *x11 = META_CURSOR_RENDERER_X11 (renderer); - MetaCursorRendererX11Private *priv = meta_cursor_renderer_x11_get_instance_private (x11); - - MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ()); - Window xwindow = meta_backend_x11_get_xwindow (backend); - Display *xdisplay = meta_backend_x11_get_xdisplay (backend); - - if (xwindow == None) - { - if (cursor_sprite) - meta_cursor_sprite_realize_texture (cursor_sprite); - return FALSE; - } - - gboolean has_server_cursor = FALSE; - - if (cursor_sprite && META_IS_CURSOR_SPRITE_XCURSOR (cursor_sprite)) - { - MetaCursorSpriteXcursor *sprite_xcursor = - META_CURSOR_SPRITE_XCURSOR (cursor_sprite); - MetaCursor cursor; - - cursor = meta_cursor_sprite_xcursor_get_cursor (sprite_xcursor); - if (cursor != META_CURSOR_NONE) - { - Cursor xcursor; - - xcursor = meta_create_x_cursor (xdisplay, cursor); - XDefineCursor (xdisplay, xwindow, xcursor); - XFlush (xdisplay); - XFreeCursor (xdisplay, xcursor); - - has_server_cursor = TRUE; - } - } - - if (has_server_cursor != priv->server_cursor_visible) - { - if (has_server_cursor) - XFixesShowCursor (xdisplay, xwindow); - else - XFixesHideCursor (xdisplay, xwindow); - - priv->server_cursor_visible = has_server_cursor; - } - - if (cursor_sprite) - meta_cursor_sprite_realize_texture (cursor_sprite); - - return priv->server_cursor_visible; -} - -static void -meta_cursor_renderer_x11_class_init (MetaCursorRendererX11Class *klass) -{ - MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_CLASS (klass); - - renderer_class->update_cursor = meta_cursor_renderer_x11_update_cursor; -} - -static void -meta_cursor_renderer_x11_init (MetaCursorRendererX11 *x11) -{ - MetaCursorRendererX11Private *priv = meta_cursor_renderer_x11_get_instance_private (x11); - - /* XFixes has no way to retrieve the current cursor visibility. */ - priv->server_cursor_visible = TRUE; -} diff --git a/src/backends/x11/meta-cursor-renderer-x11.h b/src/backends/x11/meta-cursor-renderer-x11.h deleted file mode 100644 index b52834375..000000000 --- a/src/backends/x11/meta-cursor-renderer-x11.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -#ifndef META_CURSOR_RENDERER_X11_H -#define META_CURSOR_RENDERER_X11_H - -#include "backends/meta-cursor-renderer.h" - -#define META_TYPE_CURSOR_RENDERER_X11 (meta_cursor_renderer_x11_get_type ()) -#define META_CURSOR_RENDERER_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CURSOR_RENDERER_X11, MetaCursorRendererX11)) -#define META_CURSOR_RENDERER_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_CURSOR_RENDERER_X11, MetaCursorRendererX11Class)) -#define META_IS_CURSOR_RENDERER_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CURSOR_RENDERER_X11)) -#define META_IS_CURSOR_RENDERER_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_CURSOR_RENDERER_X11)) -#define META_CURSOR_RENDERER_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_CURSOR_RENDERER_X11, MetaCursorRendererX11Class)) - -typedef struct _MetaCursorRendererX11 MetaCursorRendererX11; -typedef struct _MetaCursorRendererX11Class MetaCursorRendererX11Class; - -struct _MetaCursorRendererX11 -{ - MetaCursorRenderer parent; -}; - -struct _MetaCursorRendererX11Class -{ - MetaCursorRendererClass parent_class; -}; - -GType meta_cursor_renderer_x11_get_type (void) G_GNUC_CONST; - -#endif /* META_CURSOR_RENDERER_X11_H */ diff --git a/src/backends/x11/meta-cursor-tracker-x11.c b/src/backends/x11/meta-cursor-tracker-x11.c deleted file mode 100644 index 7355f828e..000000000 --- a/src/backends/x11/meta-cursor-tracker-x11.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (C) 2020 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. - * - */ - -#include "config.h" - -#include "backends/x11/meta-cursor-tracker-x11.h" - -#include "backends/x11/cm/meta-cursor-sprite-xfixes.h" -#include "clutter/clutter-private.h" -#include "meta/meta-x11-errors.h" -#include "x11/meta-x11-display-private.h" - -#define UPDATE_POSITION_TIMEOUT_MS (ms (100)) - -struct _MetaCursorTrackerX11 -{ - MetaCursorTracker parent; - - gboolean is_force_track_position_enabled; - guint update_position_timeout_id; - - MetaCursorSpriteXfixes *xfixes_cursor; -}; - -G_DEFINE_TYPE (MetaCursorTrackerX11, meta_cursor_tracker_x11, - META_TYPE_CURSOR_TRACKER) - -static gboolean -ensure_xfixes_cursor (MetaCursorTrackerX11 *tracker_x11); - -gboolean -meta_cursor_tracker_x11_handle_xevent (MetaCursorTrackerX11 *tracker_x11, - XEvent *xevent) -{ - MetaX11Display *x11_display = meta_get_display ()->x11_display; - XFixesCursorNotifyEvent *notify_event; - - if (xevent->xany.type != x11_display->xfixes_event_base + XFixesCursorNotify) - return FALSE; - - notify_event = (XFixesCursorNotifyEvent *)xevent; - if (notify_event->subtype != XFixesDisplayCursorNotify) - return FALSE; - - g_clear_object (&tracker_x11->xfixes_cursor); - meta_cursor_tracker_notify_cursor_changed (META_CURSOR_TRACKER (tracker_x11)); - - return TRUE; -} - -static void -update_position (MetaCursorTrackerX11 *tracker_x11) -{ - MetaCursorTracker *tracker = META_CURSOR_TRACKER (tracker_x11); - - meta_cursor_tracker_invalidate_position (tracker); -} - -static gboolean -ensure_xfixes_cursor (MetaCursorTrackerX11 *tracker_x11) -{ - MetaDisplay *display = meta_get_display (); - g_autoptr (GError) error = NULL; - - if (tracker_x11->xfixes_cursor) - return FALSE; - - tracker_x11->xfixes_cursor = meta_cursor_sprite_xfixes_new (display, &error); - if (!tracker_x11->xfixes_cursor) - g_warning ("Failed to create XFIXES cursor: %s", error->message); - - return TRUE; -} - -static gboolean -update_cursor_timeout (gpointer user_data) -{ - MetaCursorTrackerX11 *tracker_x11 = user_data; - MetaCursorTracker *tracker = META_CURSOR_TRACKER (tracker_x11); - MetaBackend *backend = meta_cursor_tracker_get_backend (tracker); - MetaCursorRenderer *cursor_renderer = - meta_backend_get_cursor_renderer (backend); - gboolean cursor_changed; - MetaCursorSprite *cursor_sprite; - - update_position (tracker_x11); - - cursor_changed = ensure_xfixes_cursor (tracker_x11); - - if (tracker_x11->xfixes_cursor) - cursor_sprite = META_CURSOR_SPRITE (tracker_x11->xfixes_cursor); - else - cursor_sprite = NULL; - - meta_cursor_renderer_update_stage_overlay (cursor_renderer, cursor_sprite); - - if (cursor_changed) - meta_cursor_tracker_notify_cursor_changed (tracker); - - return G_SOURCE_CONTINUE; -} - -static void -meta_cursor_tracker_x11_set_force_track_position (MetaCursorTracker *tracker, - gboolean is_enabled) -{ - MetaCursorTrackerX11 *tracker_x11 = META_CURSOR_TRACKER_X11 (tracker); - - if (tracker_x11->is_force_track_position_enabled == is_enabled) - return; - - tracker_x11->is_force_track_position_enabled = is_enabled; - - if (is_enabled) - { - tracker_x11->update_position_timeout_id = - g_timeout_add (UPDATE_POSITION_TIMEOUT_MS, - update_cursor_timeout, - tracker_x11); - update_position (tracker_x11); - } - else - { - g_clear_handle_id (&tracker_x11->update_position_timeout_id, - g_source_remove); - } -} - -static MetaCursorSprite * -meta_cursor_tracker_x11_get_sprite (MetaCursorTracker *tracker) -{ - MetaCursorTrackerX11 *tracker_x11 = META_CURSOR_TRACKER_X11 (tracker); - - ensure_xfixes_cursor (META_CURSOR_TRACKER_X11 (tracker)); - if (tracker_x11->xfixes_cursor) - return META_CURSOR_SPRITE (tracker_x11->xfixes_cursor); - else - return NULL; -} - -static void -meta_cursor_tracker_x11_dispose (GObject *object) -{ - MetaCursorTrackerX11 *tracker_x11 = META_CURSOR_TRACKER_X11 (object); - - g_clear_handle_id (&tracker_x11->update_position_timeout_id, g_source_remove); - g_clear_object (&tracker_x11->xfixes_cursor); - - G_OBJECT_CLASS (meta_cursor_tracker_x11_parent_class)->dispose (object); -} - -static void -meta_cursor_tracker_x11_init (MetaCursorTrackerX11 *tracker_x11) -{ -} - -static void -meta_cursor_tracker_x11_class_init (MetaCursorTrackerX11Class *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaCursorTrackerClass *tracker_class = META_CURSOR_TRACKER_CLASS (klass); - - object_class->dispose = meta_cursor_tracker_x11_dispose; - - tracker_class->set_force_track_position = - meta_cursor_tracker_x11_set_force_track_position; - tracker_class->get_sprite = - meta_cursor_tracker_x11_get_sprite; -} diff --git a/src/backends/x11/meta-cursor-tracker-x11.h b/src/backends/x11/meta-cursor-tracker-x11.h deleted file mode 100644 index a4b462844..000000000 --- a/src/backends/x11/meta-cursor-tracker-x11.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2020 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_CURSOR_TRACKER_X11_H -#define META_CURSOR_TRACKER_X11_H - -#include "backends/meta-cursor-tracker-private.h" - -#define META_TYPE_CURSOR_TRACKER_X11 (meta_cursor_tracker_x11_get_type ()) -G_DECLARE_FINAL_TYPE (MetaCursorTrackerX11, meta_cursor_tracker_x11, - META, CURSOR_TRACKER_X11, - MetaCursorTracker) - -gboolean meta_cursor_tracker_x11_handle_xevent (MetaCursorTrackerX11 *tracker_x11, - XEvent *xevent); - -#endif /* META_CURSOR_TRACKER_X11_H */ diff --git a/src/backends/x11/meta-event-x11.c b/src/backends/x11/meta-event-x11.c deleted file mode 100644 index d1a94bb56..000000000 --- a/src/backends/x11/meta-event-x11.c +++ /dev/null @@ -1,114 +0,0 @@ -/* Copyright (C) 2006, 2007, 2008 OpenedHand Ltd - * Copyright (C) 2009, 2010 Intel Corp. - * - * 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 . - * - * - * - * Authored by: - * Matthew Allum - * Emmanuele Bassi - */ - -#include "config.h" - -#include -#include - -#include "backends/x11/meta-event-x11.h" -#include "clutter/clutter-mutter.h" - -/** - * meta_x11_handle_event: - * @xevent: pointer to XEvent structure - * - * This function processes a single X event; it can be used to hook - * into external X11 event processing (for example, a GDK filter - * function). - * - * Return value: #MetaX11FilterReturn. %META_X11_FILTER_REMOVE - * indicates that Clutter has internally handled the event and the - * caller should do no further processing. %META_X11_FILTER_CONTINUE - * indicates that Clutter is either not interested in the event, - * or has used the event to update internal state without taking - * any exclusive action. %META_X11_FILTER_TRANSLATE will not - * occur. - * - * Since: 0.8 - */ -MetaX11FilterReturn -meta_x11_handle_event (XEvent *xevent) -{ - MetaX11FilterReturn result; - ClutterBackend *backend; - ClutterEvent *event; - gint spin = 1; - MetaClutterBackendX11 *backend_x11; - Display *xdisplay; - gboolean allocated_event; - - /* The return values here are someone approximate; we return - * META_X11_FILTER_REMOVE if a clutter event is - * generated for the event. This mostly, but not entirely, - * corresponds to whether other event processing should be - * excluded. As long as the stage window is not shared with another - * toolkit it should be safe, and never return - * %META_X11_FILTER_REMOVE when more processing is needed. - */ - - result = META_X11_FILTER_CONTINUE; - - backend = clutter_get_default_backend (); - - event = clutter_event_new (CLUTTER_NOTHING); - - backend_x11 = META_CLUTTER_BACKEND_X11 (backend); - xdisplay = backend_x11->xdisplay; - - allocated_event = XGetEventData (xdisplay, &xevent->xcookie); - - if (_clutter_backend_translate_event (backend, xevent, event)) - { - _clutter_event_push (event, FALSE); - - result = META_X11_FILTER_REMOVE; - } - else - { - clutter_event_free (event); - goto out; - } - - /* - * Motion events can generate synthetic enter and leave events, so if we - * are processing a motion event, we need to spin the event loop at least - * two extra times to pump the enter/leave events through (otherwise they - * just get pushed down the queue and never processed). - */ - if (event->type == CLUTTER_MOTION) - spin += 2; - - while (spin > 0 && (event = clutter_event_get ())) - { - /* forward the event into clutter for emission etc. */ - _clutter_stage_queue_event (event->any.stage, event, FALSE); - --spin; - } - -out: - if (allocated_event) - XFreeEventData (xdisplay, &xevent->xcookie); - - return result; -} diff --git a/src/backends/x11/meta-event-x11.h b/src/backends/x11/meta-event-x11.h deleted file mode 100644 index 3ddd0fd5d..000000000 --- a/src/backends/x11/meta-event-x11.h +++ /dev/null @@ -1,33 +0,0 @@ -/* Copyright (C) 2006, 2007, 2008 OpenedHand Ltd - * Copyright (C) 2009, 2010 Intel Corp. - * - * 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 . - * - * - * - * Authored by: - * Matthew Allum - * Emmanuele Bassi - */ - -#ifndef META_EVENT_X11_H -#define META_EVENT_X11_H - -#include - -#include "backends/x11/meta-clutter-backend-x11.h" - -MetaX11FilterReturn meta_x11_handle_event (XEvent *xevent); - -#endif /* META_EVENT_X11_H */ diff --git a/src/backends/x11/meta-gpu-xrandr.c b/src/backends/x11/meta-gpu-xrandr.c deleted file mode 100644 index bc3292d36..000000000 --- a/src/backends/x11/meta-gpu-xrandr.c +++ /dev/null @@ -1,277 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001, 2002 Havoc Pennington - * Copyright (C) 2002, 2003 Red Hat Inc. - * Some ICCCM manager selection code derived from fvwm2, - * Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * Copyright (C) 2013-2017 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 . - */ - -#include "config.h" - -#include "backends/x11/meta-gpu-xrandr.h" - -#include -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-output.h" -#include "backends/x11/meta-backend-x11.h" -#include "backends/x11/meta-crtc-xrandr.h" -#include "backends/x11/meta-monitor-manager-xrandr.h" -#include "backends/x11/meta-output-xrandr.h" - -struct _MetaGpuXrandr -{ - MetaGpu parent; - - XRRScreenResources *resources; - - int max_screen_width; - int max_screen_height; -}; - -G_DEFINE_TYPE (MetaGpuXrandr, meta_gpu_xrandr, META_TYPE_GPU) - -XRRScreenResources * -meta_gpu_xrandr_get_resources (MetaGpuXrandr *gpu_xrandr) -{ - return gpu_xrandr->resources; -} - -void -meta_gpu_xrandr_get_max_screen_size (MetaGpuXrandr *gpu_xrandr, - int *max_width, - int *max_height) -{ - *max_width = gpu_xrandr->max_screen_width; - *max_height = gpu_xrandr->max_screen_height; -} - -static int -compare_outputs (const void *one, - const void *two) -{ - MetaOutput *o_one = (MetaOutput *) one; - MetaOutput *o_two = (MetaOutput *) two; - const MetaOutputInfo *output_info_one = meta_output_get_info (o_one); - const MetaOutputInfo *output_info_two = meta_output_get_info (o_two); - - return strcmp (output_info_one->name, output_info_two->name); -} - -static char * -get_xmode_name (XRRModeInfo *xmode) -{ - int width = xmode->width; - int height = xmode->height; - - return g_strdup_printf ("%dx%d", width, height); -} - -static gboolean -meta_gpu_xrandr_read_current (MetaGpu *gpu, - GError **error) -{ - MetaGpuXrandr *gpu_xrandr = META_GPU_XRANDR (gpu); - MetaBackend *backend = meta_gpu_get_backend (gpu); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerXrandr *monitor_manager_xrandr = - META_MONITOR_MANAGER_XRANDR (monitor_manager); - Display *xdisplay = - meta_monitor_manager_xrandr_get_xdisplay (monitor_manager_xrandr); - XRRScreenResources *resources; - RROutput primary_output; - unsigned int i, j; - GList *l; - int min_width, min_height; - Screen *screen; - GList *outputs = NULL; - GList *modes = NULL; - GList *crtcs = NULL; - - if (gpu_xrandr->resources) - XRRFreeScreenResources (gpu_xrandr->resources); - gpu_xrandr->resources = NULL; - - XRRGetScreenSizeRange (xdisplay, DefaultRootWindow (xdisplay), - &min_width, - &min_height, - &gpu_xrandr->max_screen_width, - &gpu_xrandr->max_screen_height); - - screen = ScreenOfDisplay (xdisplay, DefaultScreen (xdisplay)); - /* This is updated because we called XRRUpdateConfiguration. */ - monitor_manager->screen_width = WidthOfScreen (screen); - monitor_manager->screen_height = HeightOfScreen (screen); - - resources = XRRGetScreenResourcesCurrent (xdisplay, - DefaultRootWindow (xdisplay)); - if (!resources) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to retrieve Xrandr screen resources"); - return FALSE; - } - - gpu_xrandr->resources = resources; - - outputs = NULL; - modes = NULL; - crtcs = NULL; - - for (i = 0; i < (unsigned)resources->nmode; i++) - { - XRRModeInfo *xmode = &resources->modes[i]; - g_autofree char *crtc_mode_name = NULL; - MetaCrtcMode *mode; - g_autoptr (MetaCrtcModeInfo) crtc_mode_info = NULL; - - crtc_mode_info = meta_crtc_mode_info_new (); - crtc_mode_info->width = xmode->width; - crtc_mode_info->height = xmode->height; - crtc_mode_info->refresh_rate = (xmode->dotClock / - ((float)xmode->hTotal * xmode->vTotal)); - crtc_mode_info->flags = xmode->modeFlags; - - crtc_mode_name = get_xmode_name (xmode); - mode = g_object_new (META_TYPE_CRTC_MODE, - "id", (uint64_t) xmode->id, - "name", crtc_mode_name, - "info", crtc_mode_info, - NULL); - modes = g_list_append (modes, mode); - } - meta_gpu_take_modes (gpu, modes); - - for (i = 0; i < (unsigned)resources->ncrtc; i++) - { - XRRCrtcInfo *xrandr_crtc; - RRCrtc crtc_id; - MetaCrtcXrandr *crtc_xrandr; - - crtc_id = resources->crtcs[i]; - xrandr_crtc = XRRGetCrtcInfo (xdisplay, - resources, crtc_id); - crtc_xrandr = meta_crtc_xrandr_new (gpu_xrandr, - xrandr_crtc, crtc_id, resources); - XRRFreeCrtcInfo (xrandr_crtc); - - crtcs = g_list_append (crtcs, crtc_xrandr); - } - - meta_gpu_take_crtcs (gpu, crtcs); - - primary_output = XRRGetOutputPrimary (xdisplay, - DefaultRootWindow (xdisplay)); - - for (i = 0; i < (unsigned)resources->noutput; i++) - { - RROutput output_id; - XRROutputInfo *xrandr_output; - - output_id = resources->outputs[i]; - xrandr_output = XRRGetOutputInfo (xdisplay, - resources, output_id); - if (!xrandr_output) - continue; - - if (xrandr_output->connection != RR_Disconnected) - { - MetaOutputXrandr *output_xrandr; - - output_xrandr = meta_output_xrandr_new (gpu_xrandr, - xrandr_output, - output_id, - primary_output); - if (output_xrandr) - outputs = g_list_prepend (outputs, output_xrandr); - } - - XRRFreeOutputInfo (xrandr_output); - } - - /* Sort the outputs for easier handling in MetaMonitorConfig */ - outputs = g_list_sort (outputs, compare_outputs); - - meta_gpu_take_outputs (gpu, outputs); - - /* Now fix the clones */ - for (l = outputs; l; l = l->next) - { - MetaOutput *output = l->data; - const MetaOutputInfo *output_info = meta_output_get_info (output); - GList *k; - - for (j = 0; j < output_info->n_possible_clones; j++) - { - RROutput clone = GPOINTER_TO_INT (output_info->possible_clones[j]); - - for (k = outputs; k; k = k->next) - { - MetaOutput *possible_clone = k->data; - - if (clone == (XID) meta_output_get_id (possible_clone)) - { - output_info->possible_clones[j] = possible_clone; - break; - } - } - } - } - - return TRUE; -} - -MetaGpuXrandr * -meta_gpu_xrandr_new (MetaBackendX11 *backend_x11) -{ - return g_object_new (META_TYPE_GPU_XRANDR, - "backend", backend_x11, - NULL); -} - -static void -meta_gpu_xrandr_finalize (GObject *object) -{ - MetaGpuXrandr *gpu_xrandr = META_GPU_XRANDR (object); - - g_clear_pointer (&gpu_xrandr->resources, - XRRFreeScreenResources); - - G_OBJECT_CLASS (meta_gpu_xrandr_parent_class)->finalize (object); -} - -static void -meta_gpu_xrandr_init (MetaGpuXrandr *gpu_xrandr) -{ -} - -static void -meta_gpu_xrandr_class_init (MetaGpuXrandrClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaGpuClass *gpu_class = META_GPU_CLASS (klass); - - object_class->finalize = meta_gpu_xrandr_finalize; - - gpu_class->read_current = meta_gpu_xrandr_read_current; -} diff --git a/src/backends/x11/meta-gpu-xrandr.h b/src/backends/x11/meta-gpu-xrandr.h deleted file mode 100644 index 2086f8632..000000000 --- a/src/backends/x11/meta-gpu-xrandr.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 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_GPU_XRANDR_H -#define META_GPU_XRANDR_H - -#include -#include - -#include "backends/meta-gpu.h" -#include "backends/x11/meta-backend-x11.h" - -#define META_TYPE_GPU_XRANDR (meta_gpu_xrandr_get_type ()) -G_DECLARE_FINAL_TYPE (MetaGpuXrandr, meta_gpu_xrandr, META, GPU_XRANDR, MetaGpu) - -XRRScreenResources * meta_gpu_xrandr_get_resources (MetaGpuXrandr *gpu_xrandr); - -void meta_gpu_xrandr_get_max_screen_size (MetaGpuXrandr *gpu_xrandr, - int *max_width, - int *max_height); - -MetaGpuXrandr * meta_gpu_xrandr_new (MetaBackendX11 *backend_x11); - -#endif /* META_GPU_XRANDR_H */ diff --git a/src/backends/x11/meta-input-device-tool-x11.c b/src/backends/x11/meta-input-device-tool-x11.c deleted file mode 100644 index bec4d1fad..000000000 --- a/src/backends/x11/meta-input-device-tool-x11.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright © 2016 Red Hat - * - * 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 . - * - * Author: Carlos Garnacho - */ - -#include "config.h" - -#include "meta-input-device-tool-x11.h" - -G_DEFINE_TYPE (MetaInputDeviceToolX11, meta_input_device_tool_x11, - CLUTTER_TYPE_INPUT_DEVICE_TOOL) - -static void -meta_input_device_tool_x11_class_init (MetaInputDeviceToolX11Class *klass) -{ -} - -static void -meta_input_device_tool_x11_init (MetaInputDeviceToolX11 *tool) -{ -} - -ClutterInputDeviceTool * -meta_input_device_tool_x11_new (guint serial, - ClutterInputDeviceToolType type) -{ - ClutterInputAxisFlags axes = - CLUTTER_INPUT_AXIS_FLAG_PRESSURE | - CLUTTER_INPUT_AXIS_FLAG_DISTANCE | - CLUTTER_INPUT_AXIS_FLAG_XTILT | - CLUTTER_INPUT_AXIS_FLAG_YTILT | - CLUTTER_INPUT_AXIS_FLAG_WHEEL | - CLUTTER_INPUT_AXIS_FLAG_DISTANCE | - CLUTTER_INPUT_AXIS_FLAG_ROTATION | - CLUTTER_INPUT_AXIS_FLAG_SLIDER; - - return g_object_new (META_TYPE_INPUT_DEVICE_TOOL_X11, - "type", type, - "serial", serial, - "axes", axes, - NULL); -} diff --git a/src/backends/x11/meta-input-device-tool-x11.h b/src/backends/x11/meta-input-device-tool-x11.h deleted file mode 100644 index e52803da9..000000000 --- a/src/backends/x11/meta-input-device-tool-x11.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright © 2016 Red Hat - * - * 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 . - * - * Author: Carlos Garnacho - */ - -#ifndef META_INPUT_DEVICE_TOOL_X11_H -#define META_INPUT_DEVICE_TOOL_X11_H - -#include "clutter/clutter.h" - -#define META_TYPE_INPUT_DEVICE_TOOL_X11 (meta_input_device_tool_x11_get_type ()) - -#define META_INPUT_DEVICE_TOOL_X11(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), META_TYPE_INPUT_DEVICE_TOOL_X11, MetaInputDeviceToolX11)) -#define META_IS_INPUT_DEVICE_TOOL_X11(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), META_TYPE_INPUT_DEVICE_TOOL_X11)) -#define META_INPUT_DEVICE_TOOL_X11_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), META_TYPE_INPUT_DEVICE_TOOL_X11, MetaInputDeviceToolX11Class)) -#define META_IS_INPUT_DEVICE_TOOL_X11_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), META_TYPE_INPUT_DEVICE_TOOL_X1)) -#define META_INPUT_DEVICE_TOOL_X11_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), META_TYPE_INPUT_DEVICE_TOOL_X11, MetaInputDeviceToolX11Class)) - -typedef struct _MetaInputDeviceToolX11 MetaInputDeviceToolX11; -typedef struct _MetaInputDeviceToolX11Class MetaInputDeviceToolX11Class; - -struct _MetaInputDeviceToolX11 -{ - ClutterInputDeviceTool parent_instance; -}; - -struct _MetaInputDeviceToolX11Class -{ - ClutterInputDeviceToolClass parent_class; -}; - -GType meta_input_device_tool_x11_get_type (void) G_GNUC_CONST; - -ClutterInputDeviceTool * meta_input_device_tool_x11_new (guint serial, - ClutterInputDeviceToolType type); - -#endif /* META_INPUT_DEVICE_TOOL_X11_H */ diff --git a/src/backends/x11/meta-input-device-x11.c b/src/backends/x11/meta-input-device-x11.c deleted file mode 100644 index 81a932e93..000000000 --- a/src/backends/x11/meta-input-device-x11.c +++ /dev/null @@ -1,795 +0,0 @@ -/* - * Copyright © 2011 Intel Corp. - * - * 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 . - * - * Author: Emmanuele Bassi - */ - -#include "config.h" - -#include - -#include "clutter/clutter-mutter.h" -#include "backends/x11/meta-clutter-backend-x11.h" -#include "backends/x11/meta-input-device-x11.h" - -struct _MetaInputDeviceX11 -{ - ClutterInputDevice device; - - int32_t device_id; - ClutterInputDeviceTool *current_tool; - - int inhibit_pointer_query_timer; - gboolean query_status; - float current_x; - float current_y; - - GArray *axes; - GArray *scroll_info; - -#ifdef HAVE_LIBWACOM - GArray *group_modes; -#endif -}; - -typedef struct _MetaX11AxisInfo -{ - ClutterInputAxis axis; - - double min_axis; - double max_axis; - - double min_value; - double max_value; - - double resolution; -} MetaX11AxisInfo; - -typedef struct _MetaX11ScrollInfo -{ - guint axis_id; - ClutterScrollDirection direction; - double increment; - - double last_value; - guint last_value_valid : 1; -} MetaX11ScrollInfo; - -struct _MetaInputDeviceX11Class -{ - ClutterInputDeviceClass device_class; -}; - -#define N_BUTTONS 5 - -enum -{ - PROP_0, - PROP_ID, - N_PROPS -}; - -static GParamSpec *props[N_PROPS] = { 0 }; - -G_DEFINE_TYPE (MetaInputDeviceX11, - meta_input_device_x11, - META_TYPE_INPUT_DEVICE) - -static void -meta_input_device_x11_constructed (GObject *object) -{ - MetaInputDeviceX11 *device_xi2 = META_INPUT_DEVICE_X11 (object); - - if (G_OBJECT_CLASS (meta_input_device_x11_parent_class)->constructed) - G_OBJECT_CLASS (meta_input_device_x11_parent_class)->constructed (object); - -#ifdef HAVE_LIBWACOM - if (clutter_input_device_get_device_type (CLUTTER_INPUT_DEVICE (object)) == CLUTTER_PAD_DEVICE) - { - device_xi2->group_modes = g_array_new (FALSE, TRUE, sizeof (uint32_t)); - g_array_set_size (device_xi2->group_modes, - clutter_input_device_get_n_mode_groups (CLUTTER_INPUT_DEVICE (object))); - } -#endif -} - -static gboolean -meta_input_device_x11_is_grouped (ClutterInputDevice *device, - ClutterInputDevice *other_device) -{ -#ifdef HAVE_LIBWACOM - WacomDevice *wacom_device, *other_wacom_device; - - wacom_device = - meta_input_device_get_wacom_device (META_INPUT_DEVICE (device)); - other_wacom_device = - meta_input_device_get_wacom_device (META_INPUT_DEVICE (other_device)); - - if (wacom_device && other_wacom_device && - libwacom_compare (wacom_device, - other_wacom_device, - WCOMPARE_NORMAL) == 0) - return TRUE; -#endif - - if (clutter_input_device_get_vendor_id (device) && - clutter_input_device_get_product_id (device) && - clutter_input_device_get_vendor_id (other_device) && - clutter_input_device_get_product_id (other_device)) - { - if (strcmp (clutter_input_device_get_vendor_id (device), - clutter_input_device_get_vendor_id (other_device)) == 0 && - strcmp (clutter_input_device_get_product_id (device), - clutter_input_device_get_product_id (other_device)) == 0) - return TRUE; - } - - return FALSE; -} - -static void -meta_input_device_x11_finalize (GObject *object) -{ - MetaInputDeviceX11 *device_xi2 = META_INPUT_DEVICE_X11 (object); - - g_clear_pointer (&device_xi2->axes, g_array_unref); - g_clear_pointer (&device_xi2->scroll_info, g_array_unref); - -#ifdef HAVE_LIBWACOM - if (device_xi2->group_modes) - g_array_unref (device_xi2->group_modes); -#endif - - g_clear_handle_id (&device_xi2->inhibit_pointer_query_timer, g_source_remove); - - G_OBJECT_CLASS (meta_input_device_x11_parent_class)->finalize (object); -} - -static void -meta_input_device_x11_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaInputDeviceX11 *device_x11 = META_INPUT_DEVICE_X11 (object); - - switch (prop_id) - { - case PROP_ID: - device_x11->device_id = g_value_get_int (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_input_device_x11_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaInputDeviceX11 *device_x11 = META_INPUT_DEVICE_X11 (object); - - switch (prop_id) - { - case PROP_ID: - g_value_set_int (value, device_x11->device_id); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static int -meta_input_device_x11_get_group_n_modes (ClutterInputDevice *device, - int group) -{ -#ifdef HAVE_LIBWACOM - WacomDevice *wacom_device; - - wacom_device = meta_input_device_get_wacom_device (META_INPUT_DEVICE (device)); - - if (wacom_device) - { - if (group == 0) - { - if (libwacom_has_ring (wacom_device)) - return libwacom_get_ring_num_modes (wacom_device); - else if (libwacom_get_num_strips (wacom_device) >= 1) - return libwacom_get_strips_num_modes (wacom_device); - } - else if (group == 1) - { - if (libwacom_has_ring2 (wacom_device)) - return libwacom_get_ring2_num_modes (wacom_device); - else if (libwacom_get_num_strips (wacom_device) >= 2) - return libwacom_get_strips_num_modes (wacom_device); - } - } -#endif - - return -1; -} - -#ifdef HAVE_LIBWACOM -static int -meta_input_device_x11_get_button_group (ClutterInputDevice *device, - uint32_t button) -{ - WacomDevice *wacom_device; - - wacom_device = meta_input_device_get_wacom_device (META_INPUT_DEVICE (device)); - - if (wacom_device) - { - WacomButtonFlags flags; - - if (button >= libwacom_get_num_buttons (wacom_device)) - return -1; - - flags = libwacom_get_button_flag (wacom_device, 'A' + button); - - if (flags & - (WACOM_BUTTON_RING_MODESWITCH | - WACOM_BUTTON_TOUCHSTRIP_MODESWITCH)) - return 0; - if (flags & - (WACOM_BUTTON_RING2_MODESWITCH | - WACOM_BUTTON_TOUCHSTRIP2_MODESWITCH)) - return 1; - } - - return -1; -} -#endif - -static gboolean -meta_input_device_x11_is_mode_switch_button (ClutterInputDevice *device, - uint32_t group, - uint32_t button) -{ - int button_group = -1; - -#ifdef HAVE_LIBWACOM - button_group = meta_input_device_x11_get_button_group (device, button); -#endif - - return button_group == (int) group; -} - -static void -meta_input_device_x11_class_init (MetaInputDeviceX11Class *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - ClutterInputDeviceClass *device_class = CLUTTER_INPUT_DEVICE_CLASS (klass); - - gobject_class->constructed = meta_input_device_x11_constructed; - gobject_class->finalize = meta_input_device_x11_finalize; - gobject_class->set_property = meta_input_device_x11_set_property; - gobject_class->get_property = meta_input_device_x11_get_property; - - device_class->is_grouped = meta_input_device_x11_is_grouped; - device_class->get_group_n_modes = meta_input_device_x11_get_group_n_modes; - device_class->is_mode_switch_button = meta_input_device_x11_is_mode_switch_button; - - props[PROP_ID] = - g_param_spec_int ("id", - "Id", - "Unique identifier of the device", - -1, G_MAXINT, - 0, - CLUTTER_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - - g_object_class_install_properties (gobject_class, N_PROPS, props); -} - -static void -meta_input_device_x11_init (MetaInputDeviceX11 *self) -{ -} - -static ClutterModifierType -get_modifier_for_button (int i) -{ - switch (i) - { - case 1: - return CLUTTER_BUTTON1_MASK; - case 2: - return CLUTTER_BUTTON2_MASK; - case 3: - return CLUTTER_BUTTON3_MASK; - case 4: - return CLUTTER_BUTTON4_MASK; - case 5: - return CLUTTER_BUTTON5_MASK; - default: - return 0; - } -} - -void -meta_input_device_x11_translate_state (ClutterEvent *event, - XIModifierState *modifiers_state, - XIButtonState *buttons_state, - XIGroupState *group_state) -{ - uint32_t button = 0; - uint32_t base = 0; - uint32_t latched = 0; - uint32_t locked = 0; - uint32_t effective; - - if (modifiers_state) - { - base = (uint32_t) modifiers_state->base; - latched = (uint32_t) modifiers_state->latched; - locked = (uint32_t) modifiers_state->locked; - } - - if (buttons_state) - { - int len, i; - - len = MIN (N_BUTTONS, buttons_state->mask_len * 8); - - for (i = 0; i < len; i++) - { - if (!XIMaskIsSet (buttons_state->mask, i)) - continue; - - button |= get_modifier_for_button (i); - } - } - - /* The XIButtonState sent in the event specifies the - * state of the buttons before the event. In order to - * get the current state of the buttons, we need to - * filter out the current button. - */ - switch (event->type) - { - case CLUTTER_BUTTON_PRESS: - button |= (get_modifier_for_button (event->button.button)); - break; - case CLUTTER_BUTTON_RELEASE: - button &= ~(get_modifier_for_button (event->button.button)); - break; - default: - break; - } - - effective = button | base | latched | locked; - if (group_state) - effective |= (group_state->effective) << 13; - - _clutter_event_set_state_full (event, button, base, latched, locked, effective); -} - -void -meta_input_device_x11_update_tool (ClutterInputDevice *device, - ClutterInputDeviceTool *tool) -{ - MetaInputDeviceX11 *device_xi2 = META_INPUT_DEVICE_X11 (device); - g_set_object (&device_xi2->current_tool, tool); -} - -ClutterInputDeviceTool * -meta_input_device_x11_get_current_tool (ClutterInputDevice *device) -{ - MetaInputDeviceX11 *device_xi2 = META_INPUT_DEVICE_X11 (device); - return device_xi2->current_tool; -} - -static gboolean -meta_input_device_x11_query_pointer_location (MetaInputDeviceX11 *device_xi2) -{ - Window xroot_window, xchild_window; - double xroot_x, xroot_y, xwin_x, xwin_y; - XIButtonState button_state = { 0 }; - XIModifierState mod_state; - XIGroupState group_state; - int result; - - meta_clutter_x11_trap_x_errors (); - result = XIQueryPointer (meta_clutter_x11_get_default_display (), - device_xi2->device_id, - meta_clutter_x11_get_root_window (), - &xroot_window, - &xchild_window, - &xroot_x, &xroot_y, - &xwin_x, &xwin_y, - &button_state, - &mod_state, - &group_state); - meta_clutter_x11_untrap_x_errors (); - - g_free (button_state.mask); - - 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) -{ - MetaInputDeviceX11 *device_xi2 = META_INPUT_DEVICE_X11 (data); - - device_xi2->inhibit_pointer_query_timer = 0; - - return G_SOURCE_REMOVE; -} - -gboolean -meta_input_device_x11_get_pointer_location (ClutterInputDevice *device, - float *x, - float *y) - -{ - MetaInputDeviceX11 *device_xi2 = META_INPUT_DEVICE_X11 (device); - - g_return_val_if_fail (META_IS_INPUT_DEVICE_X11 (device), FALSE); - g_return_val_if_fail (clutter_input_device_get_device_type (device) == - 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 = - meta_input_device_x11_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; -} - -int -meta_input_device_x11_get_device_id (ClutterInputDevice *device) -{ - MetaInputDeviceX11 *device_xi2 = META_INPUT_DEVICE_X11 (device); - - g_return_val_if_fail (META_IS_INPUT_DEVICE_X11 (device), 0); - - return device_xi2->device_id; -} - -void -meta_input_device_x11_reset_axes (ClutterInputDevice *device) -{ - MetaInputDeviceX11 *device_x11 = META_INPUT_DEVICE_X11 (device); - - g_clear_pointer (&device_x11->axes, g_array_unref); -} - -int -meta_input_device_x11_add_axis (ClutterInputDevice *device, - ClutterInputAxis axis, - double minimum, - double maximum, - double resolution) -{ - MetaInputDeviceX11 *device_x11 = META_INPUT_DEVICE_X11 (device); - MetaX11AxisInfo info; - guint pos; - - if (device_x11->axes == NULL) - device_x11->axes = g_array_new (FALSE, TRUE, sizeof (MetaX11AxisInfo)); - - info.axis = axis; - info.min_value = minimum; - info.max_value = maximum; - info.resolution = resolution; - - switch (axis) - { - case CLUTTER_INPUT_AXIS_X: - case CLUTTER_INPUT_AXIS_Y: - info.min_axis = 0; - info.max_axis = 0; - break; - - case CLUTTER_INPUT_AXIS_XTILT: - case CLUTTER_INPUT_AXIS_YTILT: - info.min_axis = -1; - info.max_axis = 1; - break; - - default: - info.min_axis = 0; - info.max_axis = 1; - break; - } - - g_array_append_val (device_x11->axes, info); - pos = device_x11->axes->len - 1; - - return pos; -} - -gboolean -meta_input_device_x11_get_axis (ClutterInputDevice *device, - int idx, - ClutterInputAxis *use) -{ - MetaInputDeviceX11 *device_x11 = META_INPUT_DEVICE_X11 (device); - MetaX11AxisInfo *info; - - if (device_x11->axes == NULL) - return FALSE; - - if (idx < 0 || idx >= device_x11->axes->len) - return FALSE; - - info = &g_array_index (device_x11->axes, MetaX11AxisInfo, idx); - - if (use) - *use = info->axis; - - return TRUE; -} - -gboolean -meta_input_device_x11_translate_axis (ClutterInputDevice *device, - int idx, - double value, - double *axis_value) -{ - MetaInputDeviceX11 *device_x11 = META_INPUT_DEVICE_X11 (device); - MetaX11AxisInfo *info; - double width; - double real_value; - - if (device_x11->axes == NULL || idx < 0 || idx >= device_x11->axes->len) - return FALSE; - - info = &g_array_index (device_x11->axes, MetaX11AxisInfo, idx); - - if (info->axis == CLUTTER_INPUT_AXIS_X || - info->axis == CLUTTER_INPUT_AXIS_Y) - return FALSE; - - if (fabs (info->max_value - info->min_value) < 0.0000001) - return FALSE; - - width = info->max_value - info->min_value; - real_value = (info->max_axis * (value - info->min_value) - + info->min_axis * (info->max_value - value)) - / width; - - if (axis_value) - *axis_value = real_value; - - return TRUE; -} - -int -meta_input_device_x11_get_n_axes (ClutterInputDevice *device) -{ - MetaInputDeviceX11 *device_x11 = META_INPUT_DEVICE_X11 (device); - - return device_x11->axes->len; -} - -void -meta_input_device_x11_add_scroll_info (ClutterInputDevice *device, - int idx, - ClutterScrollDirection direction, - double increment) -{ - MetaInputDeviceX11 *device_x11 = META_INPUT_DEVICE_X11 (device); - MetaX11ScrollInfo info; - - g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); - - info.axis_id = idx; - info.direction = direction; - info.increment = increment; - info.last_value_valid = FALSE; - - if (device_x11->scroll_info == NULL) - { - device_x11->scroll_info = g_array_new (FALSE, - FALSE, - sizeof (MetaX11ScrollInfo)); - } - - g_array_append_val (device_x11->scroll_info, info); -} - -gboolean -meta_input_device_x11_get_scroll_delta (ClutterInputDevice *device, - int idx, - double value, - ClutterScrollDirection *direction_p, - double *delta_p) -{ - MetaInputDeviceX11 *device_x11 = META_INPUT_DEVICE_X11 (device); - int i; - - if (device_x11->scroll_info == NULL) - return FALSE; - - for (i = 0; i < device_x11->scroll_info->len; i++) - { - MetaX11ScrollInfo *info = &g_array_index (device_x11->scroll_info, - MetaX11ScrollInfo, - i); - - if (info->axis_id == idx) - { - if (direction_p != NULL) - *direction_p = info->direction; - - if (delta_p != NULL) - *delta_p = 0.0; - - if (info->last_value_valid) - { - if (delta_p != NULL) - { - *delta_p = (value - info->last_value) - / info->increment; - } - - info->last_value = value; - } - else - { - info->last_value = value; - info->last_value_valid = TRUE; - } - - return TRUE; - } - } - - return FALSE; -} - -void -meta_input_device_x11_reset_scroll_info (ClutterInputDevice *device) -{ - MetaInputDeviceX11 *device_x11 = META_INPUT_DEVICE_X11 (device); - int i; - - if (device_x11->scroll_info == NULL) - return; - - for (i = 0; i < device_x11->scroll_info->len; i++) - { - MetaX11ScrollInfo *info = &g_array_index (device_x11->scroll_info, - MetaX11ScrollInfo, - i); - - info->last_value_valid = FALSE; - } -} - -#ifdef HAVE_LIBWACOM -uint32_t -meta_input_device_x11_get_pad_group_mode (ClutterInputDevice *device, - uint32_t group) -{ - MetaInputDeviceX11 *device_xi2 = META_INPUT_DEVICE_X11 (device); - - if (group >= device_xi2->group_modes->len) - return 0; - - return g_array_index (device_xi2->group_modes, uint32_t, group); -} - -static gboolean -pad_switch_mode (ClutterInputDevice *device, - uint32_t button, - uint32_t group, - uint32_t *mode) -{ - MetaInputDeviceX11 *device_x11 = META_INPUT_DEVICE_X11 (device); - uint32_t n_buttons, n_modes, button_group, next_mode, i; - WacomDevice *wacom_device; - GList *switch_buttons = NULL; - - wacom_device = - meta_input_device_get_wacom_device (META_INPUT_DEVICE (device)); - n_buttons = libwacom_get_num_buttons (wacom_device); - - for (i = 0; i < n_buttons; i++) - { - button_group = meta_input_device_x11_get_button_group (device, i); - if (button_group == group) - switch_buttons = g_list_prepend (switch_buttons, GINT_TO_POINTER (button)); - } - - switch_buttons = g_list_reverse (switch_buttons); - n_modes = clutter_input_device_get_group_n_modes (device, group); - - if (g_list_length (switch_buttons) > 1) - { - /* If there's multiple switch buttons, we don't toggle but assign a mode - * to each of those buttons. - */ - next_mode = g_list_index (switch_buttons, GINT_TO_POINTER (button)); - } - else if (switch_buttons) - { - uint32_t cur_mode; - - /* If there is a single button, have it toggle across modes */ - cur_mode = g_array_index (device_x11->group_modes, uint32_t, group); - next_mode = (cur_mode + 1) % n_modes; - } - else - { - return FALSE; - } - - g_list_free (switch_buttons); - - if (next_mode < 0 || next_mode > n_modes) - return FALSE; - - *mode = next_mode; - return TRUE; -} - -void -meta_input_device_x11_update_pad_state (ClutterInputDevice *device, - uint32_t button, - uint32_t state, - uint32_t *group, - uint32_t *mode) -{ - MetaInputDeviceX11 *device_xi2 = META_INPUT_DEVICE_X11 (device); - uint32_t button_group, *group_mode; - - button_group = meta_input_device_x11_get_button_group (device, button); - - if (button_group < 0 || button_group >= device_xi2->group_modes->len) - { - if (group) - *group = 0; - if (mode) - *mode = 0; - return; - } - - group_mode = &g_array_index (device_xi2->group_modes, uint32_t, button_group); - - if (state) - { - uint32_t next_mode; - - if (pad_switch_mode (device, button, button_group, &next_mode)) - *group_mode = next_mode; - } - - if (group) - *group = button_group; - if (mode) - *mode = *group_mode; -} -#endif diff --git a/src/backends/x11/meta-input-device-x11.h b/src/backends/x11/meta-input-device-x11.h deleted file mode 100644 index 66e03f581..000000000 --- a/src/backends/x11/meta-input-device-x11.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright © 2011 Intel Corp. - * - * 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 . - * - * Author: Emmanuele Bassi - */ - -#ifndef META_INPUT_DEVICE_X11_H -#define META_INPUT_DEVICE_X11_H - -#include - -#ifdef HAVE_LIBWACOM -#include -#endif - -#include "backends/meta-input-device-private.h" -#include "clutter/clutter.h" - -G_BEGIN_DECLS - -#define META_TYPE_INPUT_DEVICE_X11 (meta_input_device_x11_get_type ()) -#define META_INPUT_DEVICE_X11(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), META_TYPE_INPUT_DEVICE_X11, MetaInputDeviceX11)) -#define META_IS_INPUT_DEVICE_X11(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), META_TYPE_INPUT_DEVICE_X11)) -#define META_INPUT_DEVICE_X11_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), META_TYPE_INPUT_DEVICE_X11, MetaInputDeviceX11Class)) -#define META_IS_INPUT_DEVICE_X11_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), META_TYPE_INPUT_DEVICE_X11)) -#define META_INPUT_DEVICE_X11_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), META_TYPE_INPUT_DEVICE_X11, MetaInputDeviceX11Class)) - -typedef struct _MetaInputDeviceX11 MetaInputDeviceX11; -typedef struct _MetaInputDeviceX11Class MetaInputDeviceX11Class; - -GType meta_input_device_x11_get_type (void) G_GNUC_CONST; - -void meta_input_device_x11_translate_state (ClutterEvent *event, - XIModifierState *modifiers_state, - XIButtonState *buttons_state, - XIGroupState *group_state); -void meta_input_device_x11_update_tool (ClutterInputDevice *device, - ClutterInputDeviceTool *tool); -ClutterInputDeviceTool * meta_input_device_x11_get_current_tool (ClutterInputDevice *device); - -#ifdef HAVE_LIBWACOM -void meta_input_device_x11_ensure_wacom_info (ClutterInputDevice *device, - WacomDeviceDatabase *wacom_db); - -uint32_t meta_input_device_x11_get_pad_group_mode (ClutterInputDevice *device, - uint32_t group); - -void meta_input_device_x11_update_pad_state (ClutterInputDevice *device, - uint32_t button, - uint32_t state, - uint32_t *group, - uint32_t *mode); - -#endif - -gboolean meta_input_device_x11_get_pointer_location (ClutterInputDevice *device, - float *x, - float *y); -int meta_input_device_x11_get_device_id (ClutterInputDevice *device); - -int meta_input_device_x11_get_n_axes (ClutterInputDevice *device); -void meta_input_device_x11_reset_axes (ClutterInputDevice *device); -int meta_input_device_x11_add_axis (ClutterInputDevice *device, - ClutterInputAxis axis, - double minimum, - double maximum, - double resolution); -gboolean meta_input_device_x11_get_axis (ClutterInputDevice *device, - int idx, - ClutterInputAxis *use); -gboolean meta_input_device_x11_translate_axis (ClutterInputDevice *device, - int idx, - double value, - double *axis_value); - -void meta_input_device_x11_add_scroll_info (ClutterInputDevice *device, - int idx, - ClutterScrollDirection direction, - double increment); -gboolean meta_input_device_x11_get_scroll_delta (ClutterInputDevice *device, - int idx, - gdouble value, - ClutterScrollDirection *direction_p, - double *delta_p); -void meta_input_device_x11_reset_scroll_info (ClutterInputDevice *device); - -G_END_DECLS - -#endif /* META_INPUT_DEVICE_X11_H */ diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c deleted file mode 100644 index 26048f803..000000000 --- a/src/backends/x11/meta-input-settings-x11.c +++ /dev/null @@ -1,948 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Author: Carlos Garnacho - */ - -#include "config.h" - -#include "backends/x11/meta-input-settings-x11.h" - -#include -#include -#include -#include -#include - -#ifdef HAVE_LIBGUDEV -#include -#endif - -#include "backends/x11/meta-backend-x11.h" -#include "backends/x11/meta-input-device-x11.h" -#include "core/display-private.h" -#include "meta/meta-x11-errors.h" - -typedef struct _MetaInputSettingsX11Private -{ -#ifdef HAVE_LIBGUDEV - GUdevClient *udev_client; -#endif -} MetaInputSettingsX11Private; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaInputSettingsX11, meta_input_settings_x11, - META_TYPE_INPUT_SETTINGS) - -typedef enum -{ - SCROLL_METHOD_FIELD_2FG, - SCROLL_METHOD_FIELD_EDGE, - SCROLL_METHOD_FIELD_BUTTON, - SCROLL_METHOD_NUM_FIELDS -} ScrollMethod; - -static void -device_free_xdevice (gpointer user_data) -{ - MetaDisplay *display = meta_get_display (); - MetaBackend *backend = meta_get_backend (); - Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); - XDevice *xdev = user_data; - - meta_x11_error_trap_push (display->x11_display); - XCloseDevice (xdisplay, xdev); - meta_x11_error_trap_pop (display->x11_display); -} - -static XDevice * -device_ensure_xdevice (ClutterInputDevice *device) -{ - MetaDisplay *display = meta_get_display (); - MetaBackend *backend = meta_get_backend (); - Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); - int device_id = meta_input_device_x11_get_device_id (device); - XDevice *xdev = NULL; - - xdev = g_object_get_data (G_OBJECT (device), "meta-input-settings-xdevice"); - if (xdev) - return xdev; - - meta_x11_error_trap_push (display->x11_display); - xdev = XOpenDevice (xdisplay, device_id); - meta_x11_error_trap_pop (display->x11_display); - - if (xdev) - { - g_object_set_data_full (G_OBJECT (device), - "meta-input-settings-xdevice", - xdev, device_free_xdevice); - } - - return xdev; -} - -static void * -get_property (ClutterInputDevice *device, - const gchar *property, - Atom type, - int format, - gulong nitems) -{ - MetaBackend *backend = meta_get_backend (); - Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); - gulong nitems_ret, bytes_after_ret; - int rc, device_id, format_ret; - Atom property_atom, type_ret; - guchar *data_ret = NULL; - - property_atom = XInternAtom (xdisplay, property, True); - if (!property_atom) - return NULL; - - device_id = meta_input_device_x11_get_device_id (device); - - meta_clutter_x11_trap_x_errors (); - rc = XIGetProperty (xdisplay, device_id, property_atom, - 0, 10, False, type, &type_ret, &format_ret, - &nitems_ret, &bytes_after_ret, &data_ret); - meta_clutter_x11_untrap_x_errors (); - - if (rc == Success && type_ret == type && format_ret == format && nitems_ret >= nitems) - { - if (nitems_ret > nitems) - g_warning ("Property '%s' for device '%s' returned %lu items, expected %lu", - property, clutter_input_device_get_device_name (device), nitems_ret, nitems); - return data_ret; - } - - meta_XFree (data_ret); - return NULL; -} - -static void -change_property (ClutterInputDevice *device, - const gchar *property, - Atom type, - int format, - void *data, - gulong nitems) -{ - MetaBackend *backend = meta_get_backend (); - Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); - int device_id; - Atom property_atom; - guchar *data_ret; - - property_atom = XInternAtom (xdisplay, property, True); - if (!property_atom) - return; - - device_id = meta_input_device_x11_get_device_id (device); - - data_ret = get_property (device, property, type, format, nitems); - if (!data_ret) - return; - - XIChangeProperty (xdisplay, device_id, property_atom, type, - format, XIPropModeReplace, data, nitems); - meta_XFree (data_ret); -} - -static void -meta_input_settings_x11_set_send_events (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopDeviceSendEvents mode) -{ - guchar values[2] = { 0 }; /* disabled, disabled-on-external-mouse */ - guchar *available; - - available = get_property (device, "libinput Send Events Modes Available", - XA_INTEGER, 8, 2); - if (!available) - return; - - switch (mode) - { - case G_DESKTOP_DEVICE_SEND_EVENTS_DISABLED: - values[0] = 1; - break; - case G_DESKTOP_DEVICE_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE: - values[1] = 1; - break; - default: - break; - } - - if ((values[0] && !available[0]) || (values[1] && !available[1])) - g_warning ("Device '%s' does not support sendevents mode %d", - clutter_input_device_get_device_name (device), mode); - else - change_property (device, "libinput Send Events Mode Enabled", - XA_INTEGER, 8, &values, 2); - - meta_XFree (available); -} - -static void -meta_input_settings_x11_set_matrix (MetaInputSettings *settings, - ClutterInputDevice *device, - const float matrix[6]) -{ - MetaBackend *backend = meta_get_backend (); - Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); - gfloat full_matrix[9] = { matrix[0], matrix[1], matrix[2], - matrix[3], matrix[4], matrix[5], - 0, 0, 1 }; - - change_property (device, "Coordinate Transformation Matrix", - XInternAtom (xdisplay, "FLOAT", False), - 32, &full_matrix, 9); -} - -static void -meta_input_settings_x11_set_speed (MetaInputSettings *settings, - ClutterInputDevice *device, - gdouble speed) -{ - MetaBackend *backend = meta_get_backend (); - Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); - gfloat value = speed; - - change_property (device, "libinput Accel Speed", - XInternAtom (xdisplay, "FLOAT", False), - 32, &value, 1); -} - -static void -meta_input_settings_x11_set_left_handed (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ - ClutterInputDeviceType device_type; - guchar value; - - device_type = clutter_input_device_get_device_type (device); - - if (device_type == CLUTTER_TABLET_DEVICE || - device_type == CLUTTER_PEN_DEVICE || - device_type == CLUTTER_ERASER_DEVICE) - { - value = enabled ? 3 : 0; - change_property (device, "Wacom Rotation", - XA_INTEGER, 8, &value, 1); - } - else - { - value = enabled ? 1 : 0; - change_property (device, "libinput Left Handed Enabled", - XA_INTEGER, 8, &value, 1); - } -} - -static void -meta_input_settings_x11_set_disable_while_typing (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ - guchar value = (enabled) ? 1 : 0; - - change_property (device, "libinput Disable While Typing Enabled", - XA_INTEGER, 8, &value, 1); -} - -static void -meta_input_settings_x11_set_tap_enabled (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ - guchar value = (enabled) ? 1 : 0; - - change_property (device, "libinput Tapping Enabled", - XA_INTEGER, 8, &value, 1); -} - -static void -meta_input_settings_x11_set_tap_and_drag_enabled (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ - guchar value = (enabled) ? 1 : 0; - - change_property (device, "libinput Tapping Drag Enabled", - XA_INTEGER, 8, &value, 1); -} - -static void -meta_input_settings_x11_set_tap_and_drag_lock_enabled (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ - guchar value = (enabled) ? 1 : 0; - - change_property (device, "libinput Tapping Drag Lock Enabled", - XA_INTEGER, 8, &value, 1); -} - -static void -meta_input_settings_x11_set_invert_scroll (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean inverted) -{ - guchar value = (inverted) ? 1 : 0; - - change_property (device, "libinput Natural Scrolling Enabled", - XA_INTEGER, 8, &value, 1); -} - -static void -change_scroll_method (ClutterInputDevice *device, - ScrollMethod method, - gboolean enabled) -{ - guchar values[SCROLL_METHOD_NUM_FIELDS] = { 0 }; /* 2fg, edge, button. The last value is unused */ - guchar *current = NULL; - guchar *available = NULL; - - available = get_property (device, "libinput Scroll Methods Available", - XA_INTEGER, 8, SCROLL_METHOD_NUM_FIELDS); - if (!available || !available[method]) - goto out; - - current = get_property (device, "libinput Scroll Method Enabled", - XA_INTEGER, 8, SCROLL_METHOD_NUM_FIELDS); - if (!current) - goto out; - - memcpy (values, current, SCROLL_METHOD_NUM_FIELDS); - - values[method] = !!enabled; - change_property (device, "libinput Scroll Method Enabled", - XA_INTEGER, 8, &values, SCROLL_METHOD_NUM_FIELDS); - out: - meta_XFree (current); - meta_XFree (available); -} - -static void -meta_input_settings_x11_set_edge_scroll (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean edge_scroll_enabled) -{ - change_scroll_method (device, SCROLL_METHOD_FIELD_EDGE, edge_scroll_enabled); -} - -static void -meta_input_settings_x11_set_two_finger_scroll (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean two_finger_scroll_enabled) -{ - change_scroll_method (device, SCROLL_METHOD_FIELD_2FG, two_finger_scroll_enabled); -} - -static gboolean -meta_input_settings_x11_has_two_finger_scroll (MetaInputSettings *settings, - ClutterInputDevice *device) -{ - guchar *available = NULL; - gboolean has_two_finger = TRUE; - - available = get_property (device, "libinput Scroll Methods Available", - XA_INTEGER, 8, SCROLL_METHOD_NUM_FIELDS); - if (!available || !available[SCROLL_METHOD_FIELD_2FG]) - has_two_finger = FALSE; - - meta_XFree (available); - return has_two_finger; -} - -static void -meta_input_settings_x11_set_scroll_button (MetaInputSettings *settings, - ClutterInputDevice *device, - guint button, - gboolean button_lock) -{ - gchar lock = button_lock; - - change_scroll_method (device, SCROLL_METHOD_FIELD_BUTTON, button != 0); - change_property (device, "libinput Button Scrolling Button", - XA_CARDINAL, 32, &button, 1); - change_property (device, "libinput Button Scrolling Button Lock Enabled", - XA_INTEGER, 8, &lock, 1); -} - -static void -meta_input_settings_x11_set_click_method (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopTouchpadClickMethod mode) -{ - guchar values[2] = { 0 }; /* buttonareas, clickfinger */ - guchar *defaults, *available; - - available = get_property (device, "libinput Click Methods Available", - XA_INTEGER, 8, 2); - if (!available) - return; - - switch (mode) - { - case G_DESKTOP_TOUCHPAD_CLICK_METHOD_DEFAULT: - defaults = get_property (device, "libinput Click Method Enabled Default", - XA_INTEGER, 8, 2); - if (!defaults) - break; - memcpy (values, defaults, 2); - meta_XFree (defaults); - break; - case G_DESKTOP_TOUCHPAD_CLICK_METHOD_NONE: - break; - case G_DESKTOP_TOUCHPAD_CLICK_METHOD_AREAS: - values[0] = 1; - break; - case G_DESKTOP_TOUCHPAD_CLICK_METHOD_FINGERS: - values[1] = 1; - break; - default: - g_assert_not_reached (); - return; - } - - if ((values[0] && !available[0]) || (values[1] && !available[1])) - g_warning ("Device '%s' does not support click method %d", - clutter_input_device_get_device_name (device), mode); - else - change_property (device, "libinput Click Method Enabled", - XA_INTEGER, 8, &values, 2); - - meta_XFree(available); -} - -static void -meta_input_settings_x11_set_tap_button_map (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopTouchpadTapButtonMap mode) -{ - guchar values[2] = { 0 }; /* lrm, lmr */ - guchar *defaults; - - switch (mode) - { - case G_DESKTOP_TOUCHPAD_BUTTON_TAP_MAP_DEFAULT: - defaults = get_property (device, "libinput Tapping Button Mapping Default", - XA_INTEGER, 8, 2); - if (!defaults) - break; - memcpy (values, defaults, 2); - meta_XFree (defaults); - break; - case G_DESKTOP_TOUCHPAD_BUTTON_TAP_MAP_LRM: - values[0] = 1; - break; - case G_DESKTOP_TOUCHPAD_BUTTON_TAP_MAP_LMR: - values[1] = 1; - break; - default: - g_assert_not_reached (); - return; - } - - if (values[0] || values[1]) - change_property (device, "libinput Tapping Button Mapping Enabled", - XA_INTEGER, 8, &values, 2); -} - -static void -meta_input_settings_x11_set_keyboard_repeat (MetaInputSettings *settings, - gboolean enabled, - guint delay, - guint interval) -{ - MetaBackend *backend = meta_get_backend (); - Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); - - if (enabled) - { - XAutoRepeatOn (xdisplay); - XkbSetAutoRepeatRate (xdisplay, XkbUseCoreKbd, delay, interval); - } - else - { - XAutoRepeatOff (xdisplay); - } -} - -static gboolean -has_udev_property (MetaInputSettings *settings, - ClutterInputDevice *device, - const char *property_name) -{ -#ifdef HAVE_LIBGUDEV - MetaInputSettingsX11 *settings_x11 = META_INPUT_SETTINGS_X11 (settings); - MetaInputSettingsX11Private *priv = - meta_input_settings_x11_get_instance_private (settings_x11); - const char *device_node; - GUdevDevice *udev_device = NULL; - GUdevDevice *parent_udev_device = NULL; - - device_node = clutter_input_device_get_device_node (device); - if (!device_node) - return FALSE; - - udev_device = g_udev_client_query_by_device_file (priv->udev_client, - device_node); - if (!udev_device) - return FALSE; - - if (NULL != g_udev_device_get_property (udev_device, property_name)) - { - g_object_unref (udev_device); - return TRUE; - } - - parent_udev_device = g_udev_device_get_parent (udev_device); - g_object_unref (udev_device); - - if (!parent_udev_device) - return FALSE; - - if (NULL != g_udev_device_get_property (parent_udev_device, property_name)) - { - g_object_unref (parent_udev_device); - return TRUE; - } - - g_object_unref (parent_udev_device); - return FALSE; -#else - static gboolean warned_once = FALSE; - - if (!warned_once) - { - g_warning ("Failed to query property: no udev support"); - warned_once = TRUE; - } - - return FALSE; -#endif -} - -static gboolean -is_mouse (MetaInputSettings *settings, - ClutterInputDevice *device) -{ - return (has_udev_property (settings, device, "ID_INPUT_MOUSE") && - !has_udev_property (settings, device, "ID_INPUT_POINTINGSTICK")); -} - -static gboolean -meta_input_settings_x11_is_touchpad_device (MetaInputSettings *settings, - ClutterInputDevice *device) -{ - return has_udev_property (settings, device, "ID_INPUT_TOUCHPAD"); -} - -static gboolean -meta_input_settings_x11_is_trackball_device (MetaInputSettings *settings, - ClutterInputDevice *device) -{ - return has_udev_property (settings, device, "ID_INPUT_TRACKBALL"); -} - -static void -set_device_accel_profile (ClutterInputDevice *device, - GDesktopPointerAccelProfile profile) -{ - guchar *defaults, *available; - guchar values[2] = { 0 }; /* adaptive, flat */ - - defaults = get_property (device, "libinput Accel Profile Enabled Default", - XA_INTEGER, 8, 2); - if (!defaults) - return; - - available = get_property (device, "libinput Accel Profiles Available", - XA_INTEGER, 8, 2); - if (!available) - goto err_available; - - switch (profile) - { - case G_DESKTOP_POINTER_ACCEL_PROFILE_FLAT: - values[0] = 0; - values[1] = 1; - break; - case G_DESKTOP_POINTER_ACCEL_PROFILE_ADAPTIVE: - values[0] = 1; - values[1] = 0; - break; - default: - g_warn_if_reached (); - case G_DESKTOP_POINTER_ACCEL_PROFILE_DEFAULT: - values[0] = defaults[0]; - values[1] = defaults[1]; - break; - } - - change_property (device, "libinput Accel Profile Enabled", - XA_INTEGER, 8, &values, 2); - - meta_XFree (available); - -err_available: - meta_XFree (defaults); -} - -static void -meta_input_settings_x11_set_mouse_accel_profile (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopPointerAccelProfile profile) -{ - if (!is_mouse (settings, device)) - return; - - set_device_accel_profile (device, profile); -} - -static void -meta_input_settings_x11_set_trackball_accel_profile (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopPointerAccelProfile profile) -{ - if (!meta_input_settings_x11_is_trackball_device (settings, device)) - return; - - set_device_accel_profile (device, profile); -} - -static void -meta_input_settings_x11_set_tablet_mapping (MetaInputSettings *settings, - ClutterInputDevice *device, - GDesktopTabletMapping mapping) -{ - MetaDisplay *display = meta_get_display (); - MetaBackend *backend = meta_get_backend (); - Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); - XDevice *xdev; - - if (!display) - return; - - /* Grab the puke bucket! */ - meta_x11_error_trap_push (display->x11_display); - xdev = device_ensure_xdevice (device); - if (xdev) - { - XSetDeviceMode (xdisplay, xdev, - mapping == G_DESKTOP_TABLET_MAPPING_ABSOLUTE ? - Absolute : Relative); - } - - if (meta_x11_error_trap_pop_with_return (display->x11_display)) - { - g_warning ("Could not set tablet mapping for %s", - clutter_input_device_get_device_name (device)); - } -} - -static gboolean -device_query_area (ClutterInputDevice *device, - gint *x, - gint *y, - gint *width, - gint *height) -{ - MetaBackend *backend = meta_get_backend (); - Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); - gint device_id, n_devices, i; - XIDeviceInfo *info; - Atom abs_x, abs_y; - - *width = *height = 0; - device_id = meta_input_device_x11_get_device_id (device); - info = XIQueryDevice (xdisplay, device_id, &n_devices); - if (n_devices <= 0 || !info) - return FALSE; - - abs_x = XInternAtom (xdisplay, "Abs X", True); - abs_y = XInternAtom (xdisplay, "Abs Y", True); - - for (i = 0; i < info->num_classes; i++) - { - XIValuatorClassInfo *valuator = (XIValuatorClassInfo *) info->classes[i]; - - if (valuator->type != XIValuatorClass) - continue; - if (valuator->label == abs_x) - { - *x = valuator->min; - *width = valuator->max - valuator->min; - } - else if (valuator->label == abs_y) - { - *y = valuator->min; - *height = valuator->max - valuator->min; - } - } - - XIFreeDeviceInfo (info); - return TRUE; -} - -static void -update_tablet_area (MetaInputSettings *settings, - ClutterInputDevice *device, - gint32 *area) -{ - change_property (device, "Wacom Tablet Area", - XA_INTEGER, 32, area, 4); -} - -static void -meta_input_settings_x11_set_tablet_area (MetaInputSettings *settings, - ClutterInputDevice *device, - gdouble padding_left, - gdouble padding_right, - gdouble padding_top, - gdouble padding_bottom) -{ - gint32 x, y, width, height, area[4] = { 0 }; - - if (!device_query_area (device, &x, &y, &width, &height)) - return; - - area[0] = (width * padding_left) + x; - area[1] = (height * padding_top) + y; - area[2] = width - (width * padding_right) + x; - area[3] = height - (height * padding_bottom) + y; - update_tablet_area (settings, device, area); -} - -static void -meta_input_settings_x11_set_tablet_aspect_ratio (MetaInputSettings *settings, - ClutterInputDevice *device, - gdouble aspect_ratio) -{ - int32_t dev_x, dev_y, dev_width, dev_height, area[4] = { 0 }; - - if (!device_query_area (device, &dev_x, &dev_y, &dev_width, &dev_height)) - return; - - if (aspect_ratio > 0) - { - double dev_aspect; - - dev_aspect = (double) dev_width / dev_height; - - if (dev_aspect > aspect_ratio) - dev_width = dev_height * aspect_ratio; - else if (dev_aspect < aspect_ratio) - dev_height = dev_width / aspect_ratio; - } - - area[0] = dev_x; - area[1] = dev_y; - area[2] = dev_width + dev_x; - area[3] = dev_height + dev_y; - update_tablet_area (settings, device, area); -} - -static void -meta_input_settings_x11_dispose (GObject *object) -{ -#ifdef HAVE_LIBGUDEV - MetaInputSettingsX11 *settings_x11 = META_INPUT_SETTINGS_X11 (object); - MetaInputSettingsX11Private *priv = - meta_input_settings_x11_get_instance_private (settings_x11); - - g_clear_object (&priv->udev_client); -#endif - - G_OBJECT_CLASS (meta_input_settings_x11_parent_class)->dispose (object); -} - -static guint -action_to_button (GDesktopStylusButtonAction action, - guint button) -{ - switch (action) - { - case G_DESKTOP_STYLUS_BUTTON_ACTION_MIDDLE: - return CLUTTER_BUTTON_MIDDLE; - case G_DESKTOP_STYLUS_BUTTON_ACTION_RIGHT: - return CLUTTER_BUTTON_SECONDARY; - case G_DESKTOP_STYLUS_BUTTON_ACTION_BACK: - return 8; - case G_DESKTOP_STYLUS_BUTTON_ACTION_FORWARD: - return 9; - case G_DESKTOP_STYLUS_BUTTON_ACTION_DEFAULT: - default: - return button; - } -} - -static void -meta_input_settings_x11_set_stylus_button_map (MetaInputSettings *settings, - ClutterInputDevice *device, - ClutterInputDeviceTool *tool, - GDesktopStylusButtonAction primary, - GDesktopStylusButtonAction secondary, - GDesktopStylusButtonAction tertiary) -{ - MetaDisplay *display = meta_get_display (); - MetaBackend *backend = meta_get_backend (); - Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); - XDevice *xdev; - - if (!display) - return; - - /* Grab the puke bucket! */ - meta_x11_error_trap_push (display->x11_display); - xdev = device_ensure_xdevice (device); - if (xdev) - { - guchar map[8] = { - CLUTTER_BUTTON_PRIMARY, - action_to_button (primary, CLUTTER_BUTTON_MIDDLE), - action_to_button (secondary, CLUTTER_BUTTON_SECONDARY), - 4, - 5, - 6, - 7, - action_to_button (tertiary, 8), /* "Back" */ - }; - - XSetDeviceButtonMapping (xdisplay, xdev, map, G_N_ELEMENTS (map)); - } - - if (meta_x11_error_trap_pop_with_return (display->x11_display)) - { - g_warning ("Could not set stylus button map for %s", - clutter_input_device_get_device_name (device)); - } -} - -static void -meta_input_settings_x11_set_mouse_middle_click_emulation (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ - guchar value = enabled ? 1 : 0; - - if (!is_mouse (settings, device)) - return; - - change_property (device, "libinput Middle Click Emulation Enabled", - XA_INTEGER, 8, &value, 1); -} - -static void -meta_input_settings_x11_set_touchpad_middle_click_emulation (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ - guchar value = enabled ? 1 : 0; - - if (!meta_input_settings_x11_is_touchpad_device (settings, device)) - return; - - change_property (device, "libinput Middle Click Emulation Enabled", - XA_INTEGER, 8, &value, 1); -} - -static void -meta_input_settings_x11_set_trackball_middle_click_emulation (MetaInputSettings *settings, - ClutterInputDevice *device, - gboolean enabled) -{ - guchar value = enabled ? 1 : 0; - - if (!meta_input_settings_x11_is_trackball_device (settings, device)) - return; - - change_property (device, "libinput Middle Click Emulation Enabled", - XA_INTEGER, 8, &value, 1); -} - -static void -meta_input_settings_x11_set_stylus_pressure (MetaInputSettings *settings, - ClutterInputDevice *device, - ClutterInputDeviceTool *tool, - const gint32 pressure[4]) -{ - guint32 values[4] = { pressure[0], pressure[1], pressure[2], pressure[3] }; - - change_property (device, "Wacom Pressurecurve", XA_INTEGER, 32, - &values, G_N_ELEMENTS (values)); -} - -static void -meta_input_settings_x11_class_init (MetaInputSettingsX11Class *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaInputSettingsClass *input_settings_class = META_INPUT_SETTINGS_CLASS (klass); - - object_class->dispose = meta_input_settings_x11_dispose; - - input_settings_class->set_send_events = meta_input_settings_x11_set_send_events; - input_settings_class->set_matrix = meta_input_settings_x11_set_matrix; - input_settings_class->set_speed = meta_input_settings_x11_set_speed; - input_settings_class->set_left_handed = meta_input_settings_x11_set_left_handed; - input_settings_class->set_tap_enabled = meta_input_settings_x11_set_tap_enabled; - input_settings_class->set_tap_button_map = meta_input_settings_x11_set_tap_button_map; - input_settings_class->set_tap_and_drag_enabled = meta_input_settings_x11_set_tap_and_drag_enabled; - input_settings_class->set_tap_and_drag_lock_enabled = - meta_input_settings_x11_set_tap_and_drag_lock_enabled; - input_settings_class->set_disable_while_typing = meta_input_settings_x11_set_disable_while_typing; - input_settings_class->set_invert_scroll = meta_input_settings_x11_set_invert_scroll; - input_settings_class->set_edge_scroll = meta_input_settings_x11_set_edge_scroll; - input_settings_class->set_two_finger_scroll = meta_input_settings_x11_set_two_finger_scroll; - input_settings_class->set_scroll_button = meta_input_settings_x11_set_scroll_button; - input_settings_class->set_click_method = meta_input_settings_x11_set_click_method; - input_settings_class->set_keyboard_repeat = meta_input_settings_x11_set_keyboard_repeat; - - input_settings_class->set_tablet_mapping = meta_input_settings_x11_set_tablet_mapping; - input_settings_class->set_tablet_aspect_ratio = meta_input_settings_x11_set_tablet_aspect_ratio; - input_settings_class->set_tablet_area = meta_input_settings_x11_set_tablet_area; - - input_settings_class->set_mouse_accel_profile = meta_input_settings_x11_set_mouse_accel_profile; - input_settings_class->set_trackball_accel_profile = meta_input_settings_x11_set_trackball_accel_profile; - - input_settings_class->set_stylus_pressure = meta_input_settings_x11_set_stylus_pressure; - input_settings_class->set_stylus_button_map = meta_input_settings_x11_set_stylus_button_map; - - input_settings_class->set_mouse_middle_click_emulation = meta_input_settings_x11_set_mouse_middle_click_emulation; - input_settings_class->set_touchpad_middle_click_emulation = meta_input_settings_x11_set_touchpad_middle_click_emulation; - input_settings_class->set_trackball_middle_click_emulation = meta_input_settings_x11_set_trackball_middle_click_emulation; - - input_settings_class->has_two_finger_scroll = meta_input_settings_x11_has_two_finger_scroll; - input_settings_class->is_trackball_device = meta_input_settings_x11_is_trackball_device; -} - -static void -meta_input_settings_x11_init (MetaInputSettingsX11 *settings) -{ -#ifdef HAVE_LIBGUDEV - MetaInputSettingsX11Private *priv = - meta_input_settings_x11_get_instance_private (settings); - const char *subsystems[] = { NULL }; - - priv->udev_client = g_udev_client_new (subsystems); -#endif -} diff --git a/src/backends/x11/meta-input-settings-x11.h b/src/backends/x11/meta-input-settings-x11.h deleted file mode 100644 index 2780bb224..000000000 --- a/src/backends/x11/meta-input-settings-x11.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright 2014 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 . - * - * Author: Carlos Garnacho - */ - -#ifndef META_INPUT_SETTINGS_X11_H -#define META_INPUT_SETTINGS_X11_H - -#include "backends/meta-input-settings-private.h" - -#define META_TYPE_INPUT_SETTINGS_X11 (meta_input_settings_x11_get_type ()) -#define META_INPUT_SETTINGS_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_INPUT_SETTINGS_X11, MetaInputSettingsX11)) -#define META_INPUT_SETTINGS_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_INPUT_SETTINGS_X11, MetaInputSettingsX11Class)) -#define META_IS_INPUT_SETTINGS_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_INPUT_SETTINGS_X11)) -#define META_IS_INPUT_SETTINGS_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_INPUT_SETTINGS_X11)) -#define META_INPUT_SETTINGS_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_INPUT_SETTINGS_X11, MetaInputSettingsX11Class)) - -typedef struct _MetaInputSettingsX11 MetaInputSettingsX11; -typedef struct _MetaInputSettingsX11Class MetaInputSettingsX11Class; - -struct _MetaInputSettingsX11 -{ - MetaInputSettings parent_instance; -}; - -struct _MetaInputSettingsX11Class -{ - MetaInputSettingsClass parent_class; -}; - -GType meta_input_settings_x11_get_type (void) G_GNUC_CONST; - -#endif /* META_INPUT_SETTINGS_X11_H */ diff --git a/src/backends/x11/meta-keymap-x11.c b/src/backends/x11/meta-keymap-x11.c deleted file mode 100644 index 994ad8594..000000000 --- a/src/backends/x11/meta-keymap-x11.c +++ /dev/null @@ -1,949 +0,0 @@ -/* - * Clutter. - * - * An OpenGL based 'interactive canvas' library. - * - * Copyright (C) 2010 Intel Corp. - * - * 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 . - * - * Author: Emmanuele Bassi - */ - -#include "config.h" - -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-input-settings-private.h" -#include "backends/x11/meta-clutter-backend-x11.h" -#include "backends/x11/meta-keymap-x11.h" -#include "clutter/clutter.h" -#include "clutter/clutter-keymap-private.h" -#include "clutter/clutter-mutter.h" - -typedef struct _DirectionCacheEntry DirectionCacheEntry; -typedef struct _ClutterKeymapKey ClutterKeymapKey; - -struct _ClutterKeymapKey -{ - uint32_t keycode; - uint32_t group; - uint32_t level; -}; - -struct _DirectionCacheEntry -{ - uint32_t serial; - Atom group_atom; - PangoDirection direction; -}; - -struct _MetaKeymapX11 -{ - ClutterKeymap parent_instance; - - ClutterBackend *backend; - - int min_keycode; - int max_keycode; - - ClutterModifierType modmap[8]; - - ClutterModifierType num_lock_mask; - ClutterModifierType scroll_lock_mask; - ClutterModifierType level3_shift_mask; - - PangoDirection current_direction; - - XkbDescPtr xkb_desc; - int xkb_event_base; - uint32_t xkb_map_serial; - Atom current_group_atom; - uint32_t current_cache_serial; - DirectionCacheEntry group_direction_cache[4]; - int current_group; - - GHashTable *reserved_keycodes; - GQueue *available_keycodes; - - uint32_t keymap_serial; - - uint32_t has_direction : 1; - - uint32_t use_xkb : 1; - uint32_t have_xkb_autorepeat : 1; -}; - -enum -{ - PROP_0, - - PROP_BACKEND, - - PROP_LAST -}; - -static GParamSpec *obj_props[PROP_LAST] = { NULL, }; - -G_DEFINE_TYPE (MetaKeymapX11, meta_keymap_x11, CLUTTER_TYPE_KEYMAP) - -/* code adapted from gdk/x11/gdkkeys-x11.c - update_modmap */ -static void -update_modmap (Display *display, - MetaKeymapX11 *keymap_x11) -{ - static struct { - const char *name; - Atom atom; - ClutterModifierType mask; - } vmods[] = { - { "Meta", 0, CLUTTER_META_MASK }, - { "Super", 0, CLUTTER_SUPER_MASK }, - { "Hyper", 0, CLUTTER_HYPER_MASK }, - { NULL, 0, 0 } - }; - - int i, j, k; - - if (vmods[0].atom == 0) - for (i = 0; vmods[i].name; i++) - vmods[i].atom = XInternAtom (display, vmods[i].name, FALSE); - - for (i = 0; i < 8; i++) - keymap_x11->modmap[i] = 1 << i; - - for (i = 0; i < XkbNumVirtualMods; i++) - { - for (j = 0; vmods[j].atom; j++) - { - if (keymap_x11->xkb_desc->names->vmods[i] == vmods[j].atom) - { - for (k = 0; k < 8; k++) - { - if (keymap_x11->xkb_desc->server->vmods[i] & (1 << k)) - keymap_x11->modmap[k] |= vmods[j].mask; - } - } - } - } -} - -static XkbDescPtr -get_xkb (MetaKeymapX11 *keymap_x11) -{ - Display *xdisplay = meta_clutter_x11_get_default_display (); - - if (keymap_x11->max_keycode == 0) - XDisplayKeycodes (xdisplay, - &keymap_x11->min_keycode, - &keymap_x11->max_keycode); - - if (keymap_x11->xkb_desc == NULL) - { - int flags = XkbKeySymsMask - | XkbKeyTypesMask - | XkbModifierMapMask - | XkbVirtualModsMask; - - keymap_x11->xkb_desc = XkbGetMap (xdisplay, flags, XkbUseCoreKbd); - if (G_UNLIKELY (keymap_x11->xkb_desc == NULL)) - { - g_error ("Failed to get the keymap from XKB"); - return NULL; - } - - flags = XkbGroupNamesMask | XkbVirtualModNamesMask; - XkbGetNames (xdisplay, flags, keymap_x11->xkb_desc); - - update_modmap (xdisplay, keymap_x11); - } - else if (keymap_x11->xkb_map_serial != keymap_x11->keymap_serial) - { - int flags = XkbKeySymsMask - | XkbKeyTypesMask - | XkbModifierMapMask - | XkbVirtualModsMask; - - XkbGetUpdatedMap (xdisplay, flags, keymap_x11->xkb_desc); - - flags = XkbGroupNamesMask | XkbVirtualModNamesMask; - XkbGetNames (xdisplay, flags, keymap_x11->xkb_desc); - - update_modmap (xdisplay, keymap_x11); - - keymap_x11->xkb_map_serial = keymap_x11->keymap_serial; - } - - if (keymap_x11->num_lock_mask == 0) - keymap_x11->num_lock_mask = XkbKeysymToModifiers (xdisplay, XK_Num_Lock); - - if (keymap_x11->scroll_lock_mask == 0) - keymap_x11->scroll_lock_mask = XkbKeysymToModifiers (xdisplay, - XK_Scroll_Lock); - if (keymap_x11->level3_shift_mask == 0) - keymap_x11->level3_shift_mask = XkbKeysymToModifiers (xdisplay, - XK_ISO_Level3_Shift); - - return keymap_x11->xkb_desc; -} - -static void -update_locked_mods (MetaKeymapX11 *keymap_x11, - int locked_mods) -{ - ClutterKeymap *keymap = CLUTTER_KEYMAP (keymap_x11); - gboolean caps_lock_state; - gboolean num_lock_state; - gboolean old_num_lock_state; - - caps_lock_state = !!(locked_mods & CLUTTER_LOCK_MASK); - num_lock_state = !!(locked_mods & keymap_x11->num_lock_mask); - - old_num_lock_state = clutter_keymap_get_num_lock_state (keymap); - clutter_keymap_set_lock_modifier_state (CLUTTER_KEYMAP (keymap_x11), - caps_lock_state, - num_lock_state); - - if (num_lock_state != old_num_lock_state) - { - MetaBackend *backend; - MetaInputSettings *input_settings; - - backend = meta_get_backend (); - input_settings = meta_backend_get_input_settings (backend); - - if (input_settings) - { - meta_input_settings_maybe_save_numlock_state (input_settings, - num_lock_state); - } - } -} - -/* the code to retrieve the keymap direction and cache it - * is taken from GDK: - * gdk/x11/gdkkeys-x11.c - */ -static PangoDirection -get_direction (XkbDescPtr xkb, - int group) -{ - int rtl_minus_ltr = 0; /* total number of RTL keysyms minus LTR ones */ - int code; - - for (code = xkb->min_key_code; - code <= xkb->max_key_code; - code += 1) - { - int level = 0; - KeySym sym = XkbKeySymEntry (xkb, code, level, group); - PangoDirection dir = - _clutter_pango_unichar_direction (clutter_keysym_to_unicode (sym)); - - switch (dir) - { - case PANGO_DIRECTION_RTL: - rtl_minus_ltr++; - break; - - case PANGO_DIRECTION_LTR: - rtl_minus_ltr--; - break; - - default: - break; - } - } - - if (rtl_minus_ltr > 0) - return PANGO_DIRECTION_RTL; - - return PANGO_DIRECTION_LTR; -} - -static PangoDirection -get_direction_from_cache (MetaKeymapX11 *keymap_x11, - XkbDescPtr xkb, - int group) -{ - Atom group_atom = xkb->names->groups[group]; - gboolean cache_hit = FALSE; - DirectionCacheEntry *cache = keymap_x11->group_direction_cache; - PangoDirection direction = PANGO_DIRECTION_NEUTRAL; - int i; - - if (keymap_x11->has_direction) - { - /* look up in the cache */ - for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++) - { - if (cache[i].group_atom == group_atom) - { - cache_hit = TRUE; - cache[i].serial = keymap_x11->current_cache_serial++; - direction = cache[i].direction; - group_atom = cache[i].group_atom; - break; - } - } - } - else - { - /* initialize the cache */ - for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++) - { - cache[i].group_atom = 0; - cache[i].direction = PANGO_DIRECTION_NEUTRAL; - cache[i].serial = keymap_x11->current_cache_serial; - } - - keymap_x11->current_cache_serial += 1; - } - - /* insert the new entry in the cache */ - if (!cache_hit) - { - int oldest = 0; - - direction = get_direction (xkb, group); - - /* replace the oldest entry */ - for (i = 0; i < G_N_ELEMENTS (keymap_x11->group_direction_cache); i++) - { - if (cache[i].serial < cache[oldest].serial) - oldest = i; - } - - cache[oldest].group_atom = group_atom; - cache[oldest].direction = direction; - cache[oldest].serial = keymap_x11->current_cache_serial++; - } - - return direction; -} - -static void -update_direction (MetaKeymapX11 *keymap_x11, - int group) -{ - XkbDescPtr xkb = get_xkb (keymap_x11); - Atom group_atom; - - group_atom = xkb->names->groups[group]; - - if (!keymap_x11->has_direction || keymap_x11->current_group_atom != group_atom) - { - keymap_x11->current_direction = get_direction_from_cache (keymap_x11, xkb, group); - keymap_x11->current_group_atom = group_atom; - keymap_x11->has_direction = TRUE; - } -} - -static void -meta_keymap_x11_constructed (GObject *object) -{ - MetaKeymapX11 *keymap_x11 = META_KEYMAP_X11 (object); - Display *xdisplay = meta_clutter_x11_get_default_display (); - int xkb_major = XkbMajorVersion; - int xkb_minor = XkbMinorVersion; - - g_assert (keymap_x11->backend != NULL); - - if (XkbLibraryVersion (&xkb_major, &xkb_minor)) - { - xkb_major = XkbMajorVersion; - xkb_minor = XkbMinorVersion; - - if (XkbQueryExtension (xdisplay, - NULL, - &keymap_x11->xkb_event_base, - NULL, - &xkb_major, &xkb_minor)) - { - Bool detectable_autorepeat_supported; - - keymap_x11->use_xkb = TRUE; - - XkbSelectEvents (xdisplay, - XkbUseCoreKbd, - XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask, - XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask); - - XkbSelectEventDetails (xdisplay, - XkbUseCoreKbd, XkbStateNotify, - XkbAllStateComponentsMask, - XkbGroupLockMask | XkbModifierLockMask); - - /* enable XKB autorepeat */ - XkbSetDetectableAutoRepeat (xdisplay, - True, - &detectable_autorepeat_supported); - - keymap_x11->have_xkb_autorepeat = detectable_autorepeat_supported; - } - } -} - -static void -meta_keymap_x11_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaKeymapX11 *keymap = META_KEYMAP_X11 (object); - - switch (prop_id) - { - case PROP_BACKEND: - keymap->backend = g_value_get_object (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_keymap_x11_refresh_reserved_keycodes (MetaKeymapX11 *keymap_x11) -{ - Display *xdisplay = meta_clutter_x11_get_default_display (); - GHashTableIter iter; - gpointer key, value; - - g_hash_table_iter_init (&iter, keymap_x11->reserved_keycodes); - while (g_hash_table_iter_next (&iter, &key, &value)) - { - uint32_t reserved_keycode = GPOINTER_TO_UINT (key); - uint32_t reserved_keysym = GPOINTER_TO_UINT (value); - uint32_t actual_keysym = XkbKeycodeToKeysym (xdisplay, reserved_keycode, 0, 0); - - /* If an available keycode is no longer mapped to the stored keysym, then - * the keycode should not be considered available anymore and should be - * removed both from the list of available and reserved keycodes. - */ - if (reserved_keysym != actual_keysym) - { - g_hash_table_iter_remove (&iter); - g_queue_remove (keymap_x11->available_keycodes, key); - } - } -} - -static gboolean -meta_keymap_x11_replace_keycode (MetaKeymapX11 *keymap_x11, - KeyCode keycode, - KeySym keysym) -{ - if (keymap_x11->use_xkb) - { - Display *xdisplay = meta_clutter_x11_get_default_display (); - XkbDescPtr xkb = get_xkb (keymap_x11); - XkbMapChangesRec changes; - - XFlush (xdisplay); - - xkb->device_spec = XkbUseCoreKbd; - memset (&changes, 0, sizeof(changes)); - - if (keysym != NoSymbol) - { - int types[XkbNumKbdGroups] = { XkbOneLevelIndex }; - XkbChangeTypesOfKey (xkb, keycode, 1, XkbGroup1Mask, types, &changes); - XkbKeySymEntry (xkb, keycode, 0, 0) = keysym; - } - else - { - /* Reset to NoSymbol */ - XkbChangeTypesOfKey (xkb, keycode, 0, XkbGroup1Mask, NULL, &changes); - } - - changes.changed = XkbKeySymsMask | XkbKeyTypesMask; - changes.first_key_sym = keycode; - changes.num_key_syms = 1; - changes.first_type = 0; - changes.num_types = xkb->map->num_types; - XkbChangeMap (xdisplay, xkb, &changes); - - XFlush (xdisplay); - - return TRUE; - } - - return FALSE; -} - -static void -meta_keymap_x11_finalize (GObject *object) -{ - MetaKeymapX11 *keymap; - GHashTableIter iter; - gpointer key, value; - - keymap = META_KEYMAP_X11 (object); - - meta_keymap_x11_refresh_reserved_keycodes (keymap); - g_hash_table_iter_init (&iter, keymap->reserved_keycodes); - while (g_hash_table_iter_next (&iter, &key, &value)) - { - uint32_t keycode = GPOINTER_TO_UINT (key); - meta_keymap_x11_replace_keycode (keymap, keycode, NoSymbol); - } - - g_hash_table_destroy (keymap->reserved_keycodes); - g_queue_free (keymap->available_keycodes); - - if (keymap->xkb_desc != NULL) - XkbFreeKeyboard (keymap->xkb_desc, XkbAllComponentsMask, True); - - G_OBJECT_CLASS (meta_keymap_x11_parent_class)->finalize (object); -} - -static PangoDirection -meta_keymap_x11_get_direction (ClutterKeymap *keymap) -{ - MetaKeymapX11 *keymap_x11; - - g_return_val_if_fail (META_IS_KEYMAP_X11 (keymap), PANGO_DIRECTION_NEUTRAL); - - keymap_x11 = META_KEYMAP_X11 (keymap); - - if (keymap_x11->use_xkb) - { - if (!keymap_x11->has_direction) - { - XkbStateRec state_rec; - - XkbGetState (meta_clutter_x11_get_default_display (), - XkbUseCoreKbd, &state_rec); - update_direction (keymap_x11, XkbStateGroup (&state_rec)); - } - - return keymap_x11->current_direction; - } - else - { - return PANGO_DIRECTION_NEUTRAL; - } -} - -static void -meta_keymap_x11_class_init (MetaKeymapX11Class *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - ClutterKeymapClass *keymap_class = CLUTTER_KEYMAP_CLASS (klass); - - obj_props[PROP_BACKEND] = - g_param_spec_object ("backend", - "Backend", - "The Clutter backend", - CLUTTER_TYPE_BACKEND, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY); - - gobject_class->constructed = meta_keymap_x11_constructed; - gobject_class->set_property = meta_keymap_x11_set_property; - gobject_class->finalize = meta_keymap_x11_finalize; - - keymap_class->get_direction = meta_keymap_x11_get_direction; - - g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); -} - -static void -meta_keymap_x11_init (MetaKeymapX11 *keymap) -{ - keymap->current_direction = PANGO_DIRECTION_NEUTRAL; - keymap->current_group = -1; - keymap->reserved_keycodes = g_hash_table_new (NULL, NULL); - keymap->available_keycodes = g_queue_new (); -} - -gboolean -meta_keymap_x11_handle_event (MetaKeymapX11 *keymap_x11, - XEvent *xevent) -{ - gboolean retval; - - if (!keymap_x11->use_xkb) - return FALSE; - - retval = FALSE; - - if (xevent->type == keymap_x11->xkb_event_base) - { - XkbEvent *xkb_event = (XkbEvent *) xevent; - - switch (xkb_event->any.xkb_type) - { - case XkbStateNotify: - g_debug ("Updating keyboard state"); - keymap_x11->current_group = XkbStateGroup (&xkb_event->state); - update_direction (keymap_x11, keymap_x11->current_group); - update_locked_mods (keymap_x11, xkb_event->state.locked_mods); - retval = TRUE; - break; - - case XkbNewKeyboardNotify: - case XkbMapNotify: - g_debug ("Updating keyboard mapping"); - XkbRefreshKeyboardMapping (&xkb_event->map); - keymap_x11->keymap_serial += 1; - retval = TRUE; - break; - - default: - break; - } - } - else if (xevent->type == MappingNotify) - { - XRefreshKeyboardMapping (&xevent->xmapping); - keymap_x11->keymap_serial += 1; - retval = TRUE; - } - - return retval; -} - -int -meta_keymap_x11_get_key_group (MetaKeymapX11 *keymap, - ClutterModifierType state) -{ - return XkbGroupForCoreState (state); -} - -G_GNUC_BEGIN_IGNORE_DEPRECATIONS - -/* XXX - yes, I know that XKeycodeToKeysym() has been deprecated; hopefully, - * this code will never get run on any decent system that is also able to - * run Clutter. I just don't want to copy the implementation inside GDK for - * a fallback path. - */ -static int -translate_keysym (MetaKeymapX11 *keymap, - uint32_t hardware_keycode) -{ - int retval; - - retval = XKeycodeToKeysym (meta_clutter_x11_get_default_display (), - hardware_keycode, 0); - return retval; -} - -G_GNUC_END_IGNORE_DEPRECATIONS - -int -meta_keymap_x11_translate_key_state (MetaKeymapX11 *keymap, - uint32_t hardware_keycode, - ClutterModifierType *modifier_state_p, - ClutterModifierType *mods_p) -{ - ClutterModifierType unconsumed_modifiers = 0; - ClutterModifierType modifier_state = *modifier_state_p; - int retval; - - g_return_val_if_fail (META_IS_KEYMAP_X11 (keymap), 0); - - if (keymap->use_xkb) - { - XkbDescRec *xkb = get_xkb (keymap); - KeySym tmp_keysym; - - if (XkbTranslateKeyCode (xkb, hardware_keycode, modifier_state, - &unconsumed_modifiers, - &tmp_keysym)) - { - retval = tmp_keysym; - } - else - retval = 0; - } - else - retval = translate_keysym (keymap, hardware_keycode); - - if (mods_p) - *mods_p = unconsumed_modifiers; - - *modifier_state_p = modifier_state & ~(keymap->num_lock_mask | - keymap->scroll_lock_mask | - LockMask); - - return retval; -} - -gboolean -meta_keymap_x11_get_is_modifier (MetaKeymapX11 *keymap, - int keycode) -{ - g_return_val_if_fail (META_IS_KEYMAP_X11 (keymap), FALSE); - - if (keycode < keymap->min_keycode || keycode > keymap->max_keycode) - return FALSE; - - if (keymap->use_xkb) - { - XkbDescRec *xkb = get_xkb (keymap); - - if (xkb->map->modmap && xkb->map->modmap[keycode] != 0) - return TRUE; - } - - return FALSE; -} - -static gboolean -meta_keymap_x11_get_entries_for_keyval (MetaKeymapX11 *keymap_x11, - uint32_t keyval, - ClutterKeymapKey **keys, - int *n_keys) -{ - if (keymap_x11->use_xkb) - { - XkbDescRec *xkb = get_xkb (keymap_x11); - GArray *retval; - int keycode; - - keycode = keymap_x11->min_keycode; - retval = g_array_new (FALSE, FALSE, sizeof (ClutterKeymapKey)); - - while (keycode <= keymap_x11->max_keycode) - { - int max_shift_levels = XkbKeyGroupsWidth (xkb, keycode); - int group = 0; - int level = 0; - int total_syms = XkbKeyNumSyms (xkb, keycode); - int i = 0; - KeySym *entry; - - /* entry is an array with all syms for group 0, all - * syms for group 1, etc. and for each group the - * shift level syms are in order - */ - entry = XkbKeySymsPtr (xkb, keycode); - - while (i < total_syms) - { - g_assert (i == (group * max_shift_levels + level)); - - if (entry[i] == keyval) - { - ClutterKeymapKey key; - - key.keycode = keycode; - key.group = group; - key.level = level; - - g_array_append_val (retval, key); - - g_assert (XkbKeySymEntry (xkb, keycode, level, group) == - keyval); - } - - ++level; - - if (level == max_shift_levels) - { - level = 0; - ++group; - } - - ++i; - } - - ++keycode; - } - - if (retval->len > 0) - { - *keys = (ClutterKeymapKey*) retval->data; - *n_keys = retval->len; - } - else - { - *keys = NULL; - *n_keys = 0; - } - - g_array_free (retval, retval->len > 0 ? FALSE : TRUE); - - return *n_keys > 0; - } - else - { - return FALSE; - } -} - -static uint32_t -meta_keymap_x11_get_available_keycode (MetaKeymapX11 *keymap_x11) -{ - if (keymap_x11->use_xkb) - { - meta_keymap_x11_refresh_reserved_keycodes (keymap_x11); - - if (g_hash_table_size (keymap_x11->reserved_keycodes) < 5) - { - Display *xdisplay = meta_clutter_x11_get_default_display (); - XkbDescPtr xkb = get_xkb (keymap_x11); - uint32_t i; - - for (i = xkb->max_key_code; i >= xkb->min_key_code; --i) - { - if (XkbKeycodeToKeysym (xdisplay, i, 0, 0) == NoSymbol) - return i; - } - } - - return GPOINTER_TO_UINT (g_queue_pop_head (keymap_x11->available_keycodes)); - } - - return 0; -} - -gboolean -meta_keymap_x11_reserve_keycode (MetaKeymapX11 *keymap_x11, - uint32_t keyval, - uint32_t *keycode_out) -{ - g_return_val_if_fail (META_IS_KEYMAP_X11 (keymap_x11), FALSE); - g_return_val_if_fail (keyval != 0, FALSE); - g_return_val_if_fail (keycode_out != NULL, FALSE); - - *keycode_out = meta_keymap_x11_get_available_keycode (keymap_x11); - - if (*keycode_out == NoSymbol) - { - g_warning ("Cannot reserve a keycode for keyval %d: no available keycode", keyval); - return FALSE; - } - - if (!meta_keymap_x11_replace_keycode (keymap_x11, *keycode_out, keyval)) - { - g_warning ("Failed to remap keycode %d to keyval %d", *keycode_out, keyval); - return FALSE; - } - - g_hash_table_insert (keymap_x11->reserved_keycodes, GUINT_TO_POINTER (*keycode_out), GUINT_TO_POINTER (keyval)); - g_queue_remove (keymap_x11->available_keycodes, GUINT_TO_POINTER (*keycode_out)); - - return TRUE; -} - -void -meta_keymap_x11_release_keycode_if_needed (MetaKeymapX11 *keymap_x11, - uint32_t keycode) -{ - g_return_if_fail (META_IS_KEYMAP_X11 (keymap_x11)); - - if (!g_hash_table_contains (keymap_x11->reserved_keycodes, GUINT_TO_POINTER (keycode)) || - g_queue_index (keymap_x11->available_keycodes, GUINT_TO_POINTER (keycode)) != -1) - return; - - g_queue_push_tail (keymap_x11->available_keycodes, GUINT_TO_POINTER (keycode)); -} - -void -meta_keymap_x11_latch_modifiers (MetaKeymapX11 *keymap_x11, - uint32_t level, - gboolean enable) -{ - uint32_t modifiers[] = { - 0, - ShiftMask, - keymap_x11->level3_shift_mask, - keymap_x11->level3_shift_mask | ShiftMask, - }; - uint32_t value = 0; - - if (!keymap_x11->use_xkb) - return; - - level = CLAMP (level, 0, G_N_ELEMENTS (modifiers) - 1); - - if (enable) - value = modifiers[level]; - else - value = 0; - - XkbLatchModifiers (meta_clutter_x11_get_default_display (), - XkbUseCoreKbd, modifiers[level], - value); -} - -static uint32_t -meta_keymap_x11_get_current_group (MetaKeymapX11 *keymap_x11) -{ - XkbStateRec state_rec; - - if (keymap_x11->current_group >= 0) - return keymap_x11->current_group; - - XkbGetState (meta_clutter_x11_get_default_display (), - XkbUseCoreKbd, &state_rec); - return XkbStateGroup (&state_rec); -} - -gboolean -meta_keymap_x11_keycode_for_keyval (MetaKeymapX11 *keymap_x11, - uint32_t keyval, - uint32_t *keycode_out, - uint32_t *level_out) -{ - ClutterKeymapKey *keys; - int i, n_keys, group; - gboolean found = FALSE; - - g_return_val_if_fail (keycode_out != NULL, FALSE); - g_return_val_if_fail (level_out != NULL, FALSE); - - group = meta_keymap_x11_get_current_group (keymap_x11); - - if (!meta_keymap_x11_get_entries_for_keyval (keymap_x11, keyval, &keys, &n_keys)) - return FALSE; - - for (i = 0; i < n_keys && !found; i++) - { - if (keys[i].group == group) - { - *keycode_out = keys[i].keycode; - *level_out = keys[i].level; - found = TRUE; - } - } - - if (!found) - { - GHashTableIter iter; - gpointer key, value; - - g_hash_table_iter_init (&iter, keymap_x11->reserved_keycodes); - while (!found && g_hash_table_iter_next (&iter, &key, &value)) - { - uint32_t reserved_keycode = GPOINTER_TO_UINT (key); - uint32_t reserved_keysym = GPOINTER_TO_UINT (value); - - if (keyval == reserved_keysym) - { - *keycode_out = reserved_keycode; - *level_out = 0; - found = TRUE; - } - } - } - - g_free (keys); - return found; -} diff --git a/src/backends/x11/meta-keymap-x11.h b/src/backends/x11/meta-keymap-x11.h deleted file mode 100644 index 67a5f8eb9..000000000 --- a/src/backends/x11/meta-keymap-x11.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2009 Intel Corp. - * - * 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 . - * - * Author: Emmanuele Bassi - */ - -#ifndef META_KEYMAP_X11_H -#define META_KEYMAP_X11_H - -#include -#include - -#include "clutter/clutter.h" - -G_BEGIN_DECLS - -#define META_TYPE_KEYMAP_X11 (meta_keymap_x11_get_type ()) -G_DECLARE_FINAL_TYPE (MetaKeymapX11, meta_keymap_x11, - META, KEYMAP_X11, ClutterKeymap) - -int meta_keymap_x11_get_key_group (MetaKeymapX11 *keymap, - ClutterModifierType state); -int meta_keymap_x11_translate_key_state (MetaKeymapX11 *keymap, - guint hardware_keycode, - ClutterModifierType *modifier_state_p, - ClutterModifierType *mods_p); -gboolean meta_keymap_x11_get_is_modifier (MetaKeymapX11 *keymap, - int keycode); - -gboolean meta_keymap_x11_keycode_for_keyval (MetaKeymapX11 *keymap_x11, - guint keyval, - guint *keycode_out, - guint *level_out); -void meta_keymap_x11_latch_modifiers (MetaKeymapX11 *keymap_x11, - uint32_t level, - gboolean enable); -gboolean meta_keymap_x11_reserve_keycode (MetaKeymapX11 *keymap_x11, - guint keyval, - guint *keycode_out); -void meta_keymap_x11_release_keycode_if_needed (MetaKeymapX11 *keymap_x11, - guint keycode); - -gboolean meta_keymap_x11_handle_event (MetaKeymapX11 *keymap_x11, - XEvent *xevent); - -G_END_DECLS - -#endif /* META_KEYMAP_X11_H */ diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c deleted file mode 100644 index 489a9b424..000000000 --- a/src/backends/x11/meta-monitor-manager-xrandr.c +++ /dev/null @@ -1,1151 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001, 2002 Havoc Pennington - * Copyright (C) 2002, 2003 Red Hat Inc. - * Some ICCCM manager selection code derived from fvwm2, - * Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * Copyright (C) 2013 Red Hat Inc. - * Copyright (C) 2020 NVIDIA CORPORATION - * - * 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 . - */ - -/** - * SECTION:meta-monitor-manager-xrandr - * @title: MetaMonitorManagerXrandr - * @short_description: A subclass of #MetaMonitorManager using XRadR - * - * #MetaMonitorManagerXrandr is a subclass of #MetaMonitorManager which - * implements its functionality using the RandR X protocol. - * - * See also #MetaMonitorManagerKms for a native implementation using Linux DRM - * and udev. - */ - -#include "config.h" - -#include "backends/x11/meta-monitor-manager-xrandr.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "backends/meta-crtc.h" -#include "backends/meta-logical-monitor.h" -#include "backends/meta-monitor-config-manager.h" -#include "backends/meta-output.h" -#include "backends/x11/meta-backend-x11.h" -#include "backends/x11/meta-crtc-xrandr.h" -#include "backends/x11/meta-gpu-xrandr.h" -#include "backends/x11/meta-output-xrandr.h" -#include "clutter/clutter.h" -#include "meta/main.h" -#include "meta/meta-x11-errors.h" - -/* Look for DPI_FALLBACK in: - * http://git.gnome.org/browse/gnome-settings-daemon/tree/plugins/xsettings/gsd-xsettings-manager.c - * for the reasoning */ -#define DPI_FALLBACK 96.0 - -struct _MetaMonitorManagerXrandr -{ - MetaMonitorManager parent_instance; - - Display *xdisplay; - int rr_event_base; - int rr_error_base; - gboolean has_randr15; - - xcb_timestamp_t last_xrandr_set_timestamp; - - GHashTable *tiled_monitor_atoms; - - float *supported_scales; - int n_supported_scales; -}; - -struct _MetaMonitorManagerXrandrClass -{ - MetaMonitorManagerClass parent_class; -}; - -G_DEFINE_TYPE (MetaMonitorManagerXrandr, meta_monitor_manager_xrandr, META_TYPE_MONITOR_MANAGER); - -typedef struct _MetaMonitorXrandrData -{ - Atom xrandr_name; -} MetaMonitorXrandrData; - -GQuark quark_meta_monitor_xrandr_data; - -Display * -meta_monitor_manager_xrandr_get_xdisplay (MetaMonitorManagerXrandr *manager_xrandr) -{ - return manager_xrandr->xdisplay; -} - -gboolean -meta_monitor_manager_xrandr_has_randr15 (MetaMonitorManagerXrandr *manager_xrandr) -{ - return manager_xrandr->has_randr15; -} - -static GBytes * -meta_monitor_manager_xrandr_read_edid (MetaMonitorManager *manager, - MetaOutput *output) -{ - return meta_output_xrandr_read_edid (output); -} - -static MetaPowerSave -x11_dpms_state_to_power_save (CARD16 dpms_state) -{ - switch (dpms_state) - { - case DPMSModeOn: - return META_POWER_SAVE_ON; - case DPMSModeStandby: - return META_POWER_SAVE_STANDBY; - case DPMSModeSuspend: - return META_POWER_SAVE_SUSPEND; - case DPMSModeOff: - return META_POWER_SAVE_OFF; - default: - return META_POWER_SAVE_UNSUPPORTED; - } -} - -static void -meta_monitor_manager_xrandr_read_current_state (MetaMonitorManager *manager) -{ - MetaMonitorManagerXrandr *manager_xrandr = - META_MONITOR_MANAGER_XRANDR (manager); - MetaMonitorManagerClass *parent_class = - META_MONITOR_MANAGER_CLASS (meta_monitor_manager_xrandr_parent_class); - Display *xdisplay = meta_monitor_manager_xrandr_get_xdisplay (manager_xrandr); - BOOL dpms_capable, dpms_enabled; - CARD16 dpms_state; - MetaPowerSave power_save_mode; - - dpms_capable = DPMSCapable (xdisplay); - - if (dpms_capable && - DPMSInfo (xdisplay, &dpms_state, &dpms_enabled) && - dpms_enabled) - power_save_mode = x11_dpms_state_to_power_save (dpms_state); - else - power_save_mode = META_POWER_SAVE_UNSUPPORTED; - - meta_monitor_manager_power_save_mode_changed (manager, power_save_mode); - - parent_class->read_current_state (manager); -} - -static void -meta_monitor_manager_xrandr_set_power_save_mode (MetaMonitorManager *manager, - MetaPowerSave mode) -{ - MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager); - CARD16 state; - - switch (mode) { - case META_POWER_SAVE_ON: - state = DPMSModeOn; - break; - case META_POWER_SAVE_STANDBY: - state = DPMSModeStandby; - break; - case META_POWER_SAVE_SUSPEND: - state = DPMSModeSuspend; - break; - case META_POWER_SAVE_OFF: - state = DPMSModeOff; - break; - default: - return; - } - - DPMSForceLevel (manager_xrandr->xdisplay, state); - DPMSSetTimeouts (manager_xrandr->xdisplay, 0, 0, 0); -} - -static xcb_randr_rotation_t -meta_monitor_transform_to_xrandr (MetaMonitorTransform transform) -{ - switch (transform) - { - case META_MONITOR_TRANSFORM_NORMAL: - return XCB_RANDR_ROTATION_ROTATE_0; - case META_MONITOR_TRANSFORM_90: - return XCB_RANDR_ROTATION_ROTATE_90; - case META_MONITOR_TRANSFORM_180: - return XCB_RANDR_ROTATION_ROTATE_180; - case META_MONITOR_TRANSFORM_270: - return XCB_RANDR_ROTATION_ROTATE_270; - case META_MONITOR_TRANSFORM_FLIPPED: - return XCB_RANDR_ROTATION_REFLECT_X | XCB_RANDR_ROTATION_ROTATE_0; - case META_MONITOR_TRANSFORM_FLIPPED_90: - return XCB_RANDR_ROTATION_REFLECT_X | XCB_RANDR_ROTATION_ROTATE_90; - case META_MONITOR_TRANSFORM_FLIPPED_180: - return XCB_RANDR_ROTATION_REFLECT_X | XCB_RANDR_ROTATION_ROTATE_180; - case META_MONITOR_TRANSFORM_FLIPPED_270: - return XCB_RANDR_ROTATION_REFLECT_X | XCB_RANDR_ROTATION_ROTATE_270; - } - - g_assert_not_reached (); - return 0; -} - -static gboolean -xrandr_set_crtc_config (MetaMonitorManagerXrandr *manager_xrandr, - MetaCrtc *crtc, - gboolean save_timestamp, - xcb_randr_crtc_t xrandr_crtc, - xcb_timestamp_t timestamp, - int x, - int y, - xcb_randr_mode_t mode, - xcb_randr_rotation_t rotation, - xcb_randr_output_t *outputs, - int n_outputs) -{ - xcb_timestamp_t new_timestamp; - - if (!meta_crtc_xrandr_set_config (META_CRTC_XRANDR (crtc), - xrandr_crtc, timestamp, - x, y, mode, rotation, - outputs, n_outputs, - &new_timestamp)) - return FALSE; - - if (save_timestamp) - manager_xrandr->last_xrandr_set_timestamp = new_timestamp; - - return TRUE; -} - -static gboolean -is_crtc_assignment_changed (MetaCrtc *crtc, - MetaCrtcAssignment **crtc_assignments, - unsigned int n_crtc_assignments) -{ - unsigned int i; - - for (i = 0; i < n_crtc_assignments; i++) - { - MetaCrtcAssignment *crtc_assignment = crtc_assignments[i]; - - if (crtc_assignment->crtc != crtc) - continue; - - return meta_crtc_xrandr_is_assignment_changed (META_CRTC_XRANDR (crtc), - crtc_assignment); - } - - return !!meta_crtc_xrandr_get_current_mode (META_CRTC_XRANDR (crtc)); -} - -static gboolean -is_output_assignment_changed (MetaOutput *output, - MetaCrtcAssignment **crtc_assignments, - unsigned int n_crtc_assignments, - MetaOutputAssignment **output_assignments, - unsigned int n_output_assignments) -{ - MetaCrtc *assigned_crtc; - gboolean output_is_found = FALSE; - unsigned int i; - - for (i = 0; i < n_output_assignments; i++) - { - MetaOutputAssignment *output_assignment = output_assignments[i]; - - if (output_assignment->output != output) - continue; - - if (meta_output_is_primary (output) != output_assignment->is_primary) - return TRUE; - - if (meta_output_is_presentation (output) != - output_assignment->is_presentation) - return TRUE; - - if (meta_output_is_underscanning (output) != - output_assignment->is_underscanning) - return TRUE; - - output_is_found = TRUE; - } - - assigned_crtc = meta_output_get_assigned_crtc (output); - - if (!output_is_found) - return assigned_crtc != NULL; - - for (i = 0; i < n_crtc_assignments; i++) - { - MetaCrtcAssignment *crtc_assignment = crtc_assignments[i]; - unsigned int j; - - for (j = 0; j < crtc_assignment->outputs->len; j++) - { - MetaOutput *crtc_assignment_output = - ((MetaOutput**) crtc_assignment->outputs->pdata)[j]; - - if (crtc_assignment_output == output && - crtc_assignment->crtc == assigned_crtc) - return FALSE; - } - } - - return TRUE; -} - -static MetaGpu * -meta_monitor_manager_xrandr_get_gpu (MetaMonitorManagerXrandr *manager_xrandr) -{ - MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr); - MetaBackend *backend = meta_monitor_manager_get_backend (manager); - - return META_GPU (meta_backend_get_gpus (backend)->data); -} - -static gboolean -is_assignments_changed (MetaMonitorManager *manager, - MetaCrtcAssignment **crtc_assignments, - unsigned int n_crtc_assignments, - MetaOutputAssignment **output_assignments, - unsigned int n_output_assignments) -{ - MetaMonitorManagerXrandr *manager_xrandr = - META_MONITOR_MANAGER_XRANDR (manager); - MetaGpu *gpu = meta_monitor_manager_xrandr_get_gpu (manager_xrandr); - GList *l; - - for (l = meta_gpu_get_crtcs (gpu); l; l = l->next) - { - MetaCrtc *crtc = l->data; - - if (is_crtc_assignment_changed (crtc, crtc_assignments, n_crtc_assignments)) - return TRUE; - } - - for (l = meta_gpu_get_outputs (gpu); l; l = l->next) - { - MetaOutput *output = l->data; - - if (is_output_assignment_changed (output, - crtc_assignments, - n_crtc_assignments, - output_assignments, - n_output_assignments)) - return TRUE; - } - - return FALSE; -} - -static void -apply_crtc_assignments (MetaMonitorManager *manager, - gboolean save_timestamp, - MetaCrtcAssignment **crtcs, - unsigned int n_crtcs, - MetaOutputAssignment **outputs, - unsigned int n_outputs) -{ - MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager); - MetaGpu *gpu = meta_monitor_manager_xrandr_get_gpu (manager_xrandr); - g_autoptr (GList) to_configure_outputs = NULL; - g_autoptr (GList) to_disable_crtcs = NULL; - unsigned i; - GList *l; - int width, height, width_mm, height_mm; - - to_configure_outputs = g_list_copy (meta_gpu_get_outputs (gpu)); - to_disable_crtcs = g_list_copy (meta_gpu_get_crtcs (gpu)); - - XGrabServer (manager_xrandr->xdisplay); - - /* First compute the new size of the screen (framebuffer) */ - width = 0; height = 0; - for (i = 0; i < n_crtcs; i++) - { - MetaCrtcAssignment *crtc_assignment = crtcs[i]; - MetaCrtc *crtc = crtc_assignment->crtc; - - if (crtc_assignment->mode == NULL) - continue; - - to_disable_crtcs = g_list_remove (to_disable_crtcs, crtc); - - width = MAX (width, (int) roundf (crtc_assignment->layout.origin.x + - crtc_assignment->layout.size.width)); - height = MAX (height, (int) roundf (crtc_assignment->layout.origin.y + - crtc_assignment->layout.size.height)); - } - - /* Second disable all newly disabled CRTCs, or CRTCs that in the previous - configuration would be outside the new framebuffer (otherwise X complains - loudly when resizing) - CRTC will be enabled again after resizing the FB - */ - for (i = 0; i < n_crtcs; i++) - { - MetaCrtcAssignment *crtc_assignment = crtcs[i]; - MetaCrtc *crtc = crtc_assignment->crtc; - const MetaCrtcConfig *crtc_config; - int x2, y2; - - crtc_config = meta_crtc_get_config (crtc); - if (!crtc_config) - continue; - - x2 = (int) roundf (crtc_config->layout.origin.x + - crtc_config->layout.size.width); - y2 = (int) roundf (crtc_config->layout.origin.y + - crtc_config->layout.size.height); - - if (!crtc_assignment->mode || x2 > width || y2 > height) - { - xrandr_set_crtc_config (manager_xrandr, - crtc, - save_timestamp, - (xcb_randr_crtc_t) meta_crtc_get_id (crtc), - XCB_CURRENT_TIME, - 0, 0, XCB_NONE, - XCB_RANDR_ROTATION_ROTATE_0, - NULL, 0); - - meta_crtc_unset_config (crtc); - } - } - - for (l = to_disable_crtcs; l; l = l->next) - { - MetaCrtc *crtc = l->data; - - if (!meta_crtc_get_config (crtc)) - continue; - - xrandr_set_crtc_config (manager_xrandr, - crtc, - save_timestamp, - (xcb_randr_crtc_t) meta_crtc_get_id (crtc), - XCB_CURRENT_TIME, - 0, 0, XCB_NONE, - XCB_RANDR_ROTATION_ROTATE_0, - NULL, 0); - - meta_crtc_unset_config (crtc); - } - - if (!n_crtcs) - goto out; - - g_assert (width > 0 && height > 0); - /* The 'physical size' of an X screen is meaningless if that screen - * can consist of many monitors. So just pick a size that make the - * dpi 96. - * - * Firefox and Evince apparently believe what X tells them. - */ - width_mm = (width / DPI_FALLBACK) * 25.4 + 0.5; - height_mm = (height / DPI_FALLBACK) * 25.4 + 0.5; - XRRSetScreenSize (manager_xrandr->xdisplay, DefaultRootWindow (manager_xrandr->xdisplay), - width, height, width_mm, height_mm); - - for (i = 0; i < n_crtcs; i++) - { - MetaCrtcAssignment *crtc_assignment = crtcs[i]; - MetaCrtc *crtc = crtc_assignment->crtc; - - if (crtc_assignment->mode != NULL) - { - MetaCrtcMode *crtc_mode; - g_autofree xcb_randr_output_t *output_ids = NULL; - unsigned int j, n_output_ids; - xcb_randr_crtc_t crtc_id; - int x, y; - xcb_randr_rotation_t rotation; - xcb_randr_mode_t mode; - - crtc_mode = crtc_assignment->mode; - - n_output_ids = crtc_assignment->outputs->len; - output_ids = g_new (xcb_randr_output_t, n_output_ids); - - for (j = 0; j < n_output_ids; j++) - { - MetaOutput *output; - MetaOutputAssignment *output_assignment; - - output = ((MetaOutput**)crtc_assignment->outputs->pdata)[j]; - - to_configure_outputs = g_list_remove (to_configure_outputs, - output); - - output_assignment = meta_find_output_assignment (outputs, - n_outputs, - output); - meta_output_assign_crtc (output, crtc, output_assignment); - - output_ids[j] = meta_output_get_id (output); - } - - crtc_id = (xcb_randr_crtc_t) meta_crtc_get_id (crtc); - x = (int) roundf (crtc_assignment->layout.origin.x); - y = (int) roundf (crtc_assignment->layout.origin.y); - rotation = - meta_monitor_transform_to_xrandr (crtc_assignment->transform); - mode = meta_crtc_mode_get_id (crtc_mode); - if (!xrandr_set_crtc_config (manager_xrandr, - crtc, - save_timestamp, - crtc_id, - XCB_CURRENT_TIME, - x, y, - mode, - rotation, - output_ids, n_output_ids)) - { - const MetaCrtcModeInfo *crtc_mode_info = - meta_crtc_mode_get_info (crtc_mode); - - meta_warning ("Configuring CRTC %d with mode %d (%d x %d @ %f) at position %d, %d and transform %u failed", - (unsigned) meta_crtc_get_id (crtc), - (unsigned) mode, - crtc_mode_info->width, crtc_mode_info->height, - (float) crtc_mode_info->refresh_rate, - (int) roundf (crtc_assignment->layout.origin.x), - (int) roundf (crtc_assignment->layout.origin.y), - crtc_assignment->transform); - continue; - } - - meta_crtc_set_config (crtc, - &crtc_assignment->layout, - crtc_mode, - crtc_assignment->transform); - } - } - - for (i = 0; i < n_outputs; i++) - { - MetaOutputAssignment *output_assignment = outputs[i]; - MetaOutput *output = output_assignment->output; - - meta_output_xrandr_apply_mode (META_OUTPUT_XRANDR (output)); - } - - g_list_foreach (to_configure_outputs, - (GFunc) meta_output_unassign_crtc, - NULL); - -out: - XUngrabServer (manager_xrandr->xdisplay); - XFlush (manager_xrandr->xdisplay); -} - -static void -meta_monitor_manager_xrandr_ensure_initial_config (MetaMonitorManager *manager) -{ - MetaMonitorConfigManager *config_manager = - meta_monitor_manager_get_config_manager (manager); - MetaMonitorsConfig *config; - - meta_monitor_manager_ensure_configured (manager); - - /* - * Normally we don't rebuild our data structures until we see the - * RRScreenNotify event, but at least at startup we want to have the right - * configuration immediately. - */ - meta_monitor_manager_read_current_state (manager); - - config = meta_monitor_config_manager_get_current (config_manager); - meta_monitor_manager_update_logical_state_derived (manager, config); -} - -static void -meta_monitor_manager_xrandr_rebuild_derived (MetaMonitorManager *manager, - MetaMonitorsConfig *config) -{ - MetaMonitorManagerXrandr *manager_xrandr = - META_MONITOR_MANAGER_XRANDR (manager); - - g_clear_pointer (&manager_xrandr->supported_scales, g_free); - meta_monitor_manager_rebuild_derived (manager, config); -} - -static gboolean -meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *manager, - MetaMonitorsConfig *config, - MetaMonitorsConfigMethod method, - GError **error) -{ - GPtrArray *crtc_assignments; - GPtrArray *output_assignments; - - if (!config) - { - if (!manager->in_init) - apply_crtc_assignments (manager, TRUE, NULL, 0, NULL, 0); - - meta_monitor_manager_xrandr_rebuild_derived (manager, NULL); - return TRUE; - } - - if (!meta_monitor_config_manager_assign (manager, config, - &crtc_assignments, - &output_assignments, - error)) - return FALSE; - - if (method != META_MONITORS_CONFIG_METHOD_VERIFY) - { - /* - * If the assignment has not changed, we won't get any notification about - * any new configuration from the X server; but we still need to update - * our own configuration, as something not applicable in Xrandr might - * have changed locally, such as the logical monitors scale. This means we - * must check that our new assignment actually changes anything, otherwise - * just update the logical state. - */ - if (is_assignments_changed (manager, - (MetaCrtcAssignment **) crtc_assignments->pdata, - crtc_assignments->len, - (MetaOutputAssignment **) output_assignments->pdata, - output_assignments->len)) - { - apply_crtc_assignments (manager, - TRUE, - (MetaCrtcAssignment **) crtc_assignments->pdata, - crtc_assignments->len, - (MetaOutputAssignment **) output_assignments->pdata, - output_assignments->len); - } - else - { - meta_monitor_manager_xrandr_rebuild_derived (manager, config); - } - } - - g_ptr_array_free (crtc_assignments, TRUE); - g_ptr_array_free (output_assignments, TRUE); - - return TRUE; -} - -static void -meta_monitor_manager_xrandr_change_backlight (MetaMonitorManager *manager, - MetaOutput *output, - gint value) -{ - meta_output_xrandr_change_backlight (META_OUTPUT_XRANDR (output), value); -} - -static void -meta_monitor_manager_xrandr_get_crtc_gamma (MetaMonitorManager *manager, - MetaCrtc *crtc, - gsize *size, - unsigned short **red, - unsigned short **green, - unsigned short **blue) -{ - MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager); - XRRCrtcGamma *gamma; - - gamma = XRRGetCrtcGamma (manager_xrandr->xdisplay, - (XID) meta_crtc_get_id (crtc)); - - *size = gamma->size; - *red = g_memdup2 (gamma->red, sizeof (unsigned short) * gamma->size); - *green = g_memdup2 (gamma->green, sizeof (unsigned short) * gamma->size); - *blue = g_memdup2 (gamma->blue, sizeof (unsigned short) * gamma->size); - - XRRFreeGamma (gamma); -} - -static void -meta_monitor_manager_xrandr_set_crtc_gamma (MetaMonitorManager *manager, - MetaCrtc *crtc, - gsize size, - unsigned short *red, - unsigned short *green, - unsigned short *blue) -{ - MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager); - XRRCrtcGamma *gamma; - - gamma = XRRAllocGamma (size); - memcpy (gamma->red, red, sizeof (unsigned short) * size); - memcpy (gamma->green, green, sizeof (unsigned short) * size); - memcpy (gamma->blue, blue, sizeof (unsigned short) * size); - - XRRSetCrtcGamma (manager_xrandr->xdisplay, - (XID) meta_crtc_get_id (crtc), - gamma); - - XRRFreeGamma (gamma); -} - -static MetaMonitorXrandrData * -meta_monitor_xrandr_data_from_monitor (MetaMonitor *monitor) -{ - MetaMonitorXrandrData *monitor_xrandr_data; - - monitor_xrandr_data = g_object_get_qdata (G_OBJECT (monitor), - quark_meta_monitor_xrandr_data); - if (monitor_xrandr_data) - return monitor_xrandr_data; - - monitor_xrandr_data = g_new0 (MetaMonitorXrandrData, 1); - g_object_set_qdata_full (G_OBJECT (monitor), - quark_meta_monitor_xrandr_data, - monitor_xrandr_data, - g_free); - - return monitor_xrandr_data; -} - -static void -meta_monitor_manager_xrandr_increase_monitor_count (MetaMonitorManagerXrandr *manager_xrandr, - Atom name_atom) -{ - int count; - - count = - GPOINTER_TO_INT (g_hash_table_lookup (manager_xrandr->tiled_monitor_atoms, - GSIZE_TO_POINTER (name_atom))); - - count++; - g_hash_table_insert (manager_xrandr->tiled_monitor_atoms, - GSIZE_TO_POINTER (name_atom), - GINT_TO_POINTER (count)); -} - -static int -meta_monitor_manager_xrandr_decrease_monitor_count (MetaMonitorManagerXrandr *manager_xrandr, - Atom name_atom) -{ - int count; - - count = - GPOINTER_TO_SIZE (g_hash_table_lookup (manager_xrandr->tiled_monitor_atoms, - GSIZE_TO_POINTER (name_atom))); - g_assert (count > 0); - - count--; - g_hash_table_insert (manager_xrandr->tiled_monitor_atoms, - GSIZE_TO_POINTER (name_atom), - GINT_TO_POINTER (count)); - - return count; -} - -static void -meta_monitor_manager_xrandr_tiled_monitor_added (MetaMonitorManager *manager, - MetaMonitor *monitor) -{ - MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager); - MetaMonitorTiled *monitor_tiled = META_MONITOR_TILED (monitor); - const char *product; - char *name; - uint32_t tile_group_id; - MetaMonitorXrandrData *monitor_xrandr_data; - Atom name_atom; - XRRMonitorInfo *xrandr_monitor_info; - GList *outputs; - GList *l; - int i; - - if (manager_xrandr->has_randr15 == FALSE) - return; - - product = meta_monitor_get_product (monitor); - tile_group_id = meta_monitor_tiled_get_tile_group_id (monitor_tiled); - - if (product) - name = g_strdup_printf ("%s-%d", product, tile_group_id); - else - name = g_strdup_printf ("Tiled-%d", tile_group_id); - - name_atom = XInternAtom (manager_xrandr->xdisplay, name, False); - g_free (name); - - monitor_xrandr_data = meta_monitor_xrandr_data_from_monitor (monitor); - monitor_xrandr_data->xrandr_name = name_atom; - - meta_monitor_manager_xrandr_increase_monitor_count (manager_xrandr, - name_atom); - - outputs = meta_monitor_get_outputs (monitor); - xrandr_monitor_info = XRRAllocateMonitor (manager_xrandr->xdisplay, - g_list_length (outputs)); - xrandr_monitor_info->name = name_atom; - xrandr_monitor_info->primary = meta_monitor_is_primary (monitor); - xrandr_monitor_info->automatic = True; - for (l = outputs, i = 0; l; l = l->next, i++) - { - MetaOutput *output = l->data; - - xrandr_monitor_info->outputs[i] = meta_output_get_id (output); - } - - XRRSetMonitor (manager_xrandr->xdisplay, - DefaultRootWindow (manager_xrandr->xdisplay), - xrandr_monitor_info); - XRRFreeMonitors (xrandr_monitor_info); -} - -static void -meta_monitor_manager_xrandr_tiled_monitor_removed (MetaMonitorManager *manager, - MetaMonitor *monitor) -{ - MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager); - MetaMonitorXrandrData *monitor_xrandr_data; - Atom monitor_name; - - int monitor_count; - - if (manager_xrandr->has_randr15 == FALSE) - return; - - monitor_xrandr_data = meta_monitor_xrandr_data_from_monitor (monitor); - monitor_name = monitor_xrandr_data->xrandr_name; - monitor_count = - meta_monitor_manager_xrandr_decrease_monitor_count (manager_xrandr, - monitor_name); - - if (monitor_count == 0) - XRRDeleteMonitor (manager_xrandr->xdisplay, - DefaultRootWindow (manager_xrandr->xdisplay), - monitor_name); -} - -static void -meta_monitor_manager_xrandr_init_monitors (MetaMonitorManagerXrandr *manager_xrandr) -{ - XRRMonitorInfo *m; - int n, i; - - if (manager_xrandr->has_randr15 == FALSE) - return; - - /* delete any tiled monitors setup, as mutter will want to recreate - things in its image */ - m = XRRGetMonitors (manager_xrandr->xdisplay, - DefaultRootWindow (manager_xrandr->xdisplay), - FALSE, &n); - if (n == -1) - return; - - for (i = 0; i < n; i++) - { - if (m[i].noutput > 1) - XRRDeleteMonitor (manager_xrandr->xdisplay, - DefaultRootWindow (manager_xrandr->xdisplay), - m[i].name); - } - XRRFreeMonitors (m); -} - -static gboolean -meta_monitor_manager_xrandr_is_transform_handled (MetaMonitorManager *manager, - MetaCrtc *crtc, - MetaMonitorTransform transform) -{ - g_warn_if_fail ((meta_crtc_get_all_transforms (crtc) & transform) == - transform); - - return TRUE; -} - -static float -meta_monitor_manager_xrandr_calculate_monitor_mode_scale (MetaMonitorManager *manager, - MetaMonitor *monitor, - MetaMonitorMode *monitor_mode) -{ - return meta_monitor_calculate_mode_scale (monitor, monitor_mode); -} - -static void -add_supported_scale (GArray *supported_scales, - float scale) -{ - unsigned int i; - - for (i = 0; i < supported_scales->len; i++) - { - float supported_scale = g_array_index (supported_scales, float, i); - - if (scale == supported_scale) - return; - } - - g_array_append_val (supported_scales, scale); -} - -static int -compare_scales (gconstpointer a, - gconstpointer b) -{ - float f = *(float *) a - *(float *) b; - - if (f < 0) - return -1; - if (f > 0) - return 1; - return 0; -} - -static void -ensure_supported_monitor_scales (MetaMonitorManager *manager) -{ - MetaMonitorManagerXrandr *manager_xrandr = - META_MONITOR_MANAGER_XRANDR (manager); - MetaMonitorScalesConstraint constraints; - GList *l; - GArray *supported_scales; - - if (manager_xrandr->supported_scales) - return; - - constraints = META_MONITOR_SCALES_CONSTRAINT_NO_FRAC; - supported_scales = g_array_new (FALSE, FALSE, sizeof (float)); - - for (l = manager->monitors; l; l = l->next) - { - MetaMonitor *monitor = l->data; - MetaMonitorMode *monitor_mode; - float *monitor_scales; - int n_monitor_scales; - int i; - - monitor_mode = meta_monitor_get_preferred_mode (monitor); - monitor_scales = - meta_monitor_calculate_supported_scales (monitor, - monitor_mode, - constraints, - &n_monitor_scales); - - for (i = 0; i < n_monitor_scales; i++) - add_supported_scale (supported_scales, monitor_scales[i]); - g_array_sort (supported_scales, compare_scales); - g_free (monitor_scales); - } - - manager_xrandr->supported_scales = (float *) supported_scales->data; - manager_xrandr->n_supported_scales = supported_scales->len; - g_array_free (supported_scales, FALSE); -} - -static float * -meta_monitor_manager_xrandr_calculate_supported_scales (MetaMonitorManager *manager, - MetaLogicalMonitorLayoutMode layout_mode, - MetaMonitor *monitor, - MetaMonitorMode *monitor_mode, - int *n_supported_scales) -{ - MetaMonitorManagerXrandr *manager_xrandr = - META_MONITOR_MANAGER_XRANDR (manager); - - ensure_supported_monitor_scales (manager); - - *n_supported_scales = manager_xrandr->n_supported_scales; - return g_memdup2 (manager_xrandr->supported_scales, - manager_xrandr->n_supported_scales * sizeof (float)); -} - -static MetaMonitorManagerCapability -meta_monitor_manager_xrandr_get_capabilities (MetaMonitorManager *manager) -{ - return META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED; -} - -static gboolean -meta_monitor_manager_xrandr_get_max_screen_size (MetaMonitorManager *manager, - int *max_width, - int *max_height) -{ - MetaMonitorManagerXrandr *manager_xrandr = - META_MONITOR_MANAGER_XRANDR (manager); - MetaGpu *gpu = meta_monitor_manager_xrandr_get_gpu (manager_xrandr); - - meta_gpu_xrandr_get_max_screen_size (META_GPU_XRANDR (gpu), - max_width, max_height); - - return TRUE; -} - -static MetaLogicalMonitorLayoutMode -meta_monitor_manager_xrandr_get_default_layout_mode (MetaMonitorManager *manager) -{ - return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL; -} - -static void -meta_monitor_manager_xrandr_set_output_ctm (MetaOutput *output, - const MetaOutputCtm *ctm) -{ - meta_output_xrandr_set_ctm (META_OUTPUT_XRANDR (output), ctm); -} - -static void -meta_monitor_manager_xrandr_constructed (GObject *object) -{ - MetaMonitorManagerXrandr *manager_xrandr = - META_MONITOR_MANAGER_XRANDR (object); - MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr); - MetaBackend *backend = meta_monitor_manager_get_backend (manager); - MetaBackendX11 *backend_x11 = META_BACKEND_X11 (backend); - - manager_xrandr->xdisplay = meta_backend_x11_get_xdisplay (backend_x11); - - if (!XRRQueryExtension (manager_xrandr->xdisplay, - &manager_xrandr->rr_event_base, - &manager_xrandr->rr_error_base)) - { - return; - } - else - { - int major_version, minor_version; - /* We only use ScreenChangeNotify, but GDK uses the others, - and we don't want to step on its toes */ - XRRSelectInput (manager_xrandr->xdisplay, - DefaultRootWindow (manager_xrandr->xdisplay), - RRScreenChangeNotifyMask - | RRCrtcChangeNotifyMask - | RROutputPropertyNotifyMask); - - manager_xrandr->has_randr15 = FALSE; - XRRQueryVersion (manager_xrandr->xdisplay, &major_version, - &minor_version); - if (major_version > 1 || - (major_version == 1 && - minor_version >= 5)) - { - manager_xrandr->has_randr15 = TRUE; - manager_xrandr->tiled_monitor_atoms = g_hash_table_new (NULL, NULL); - } - meta_monitor_manager_xrandr_init_monitors (manager_xrandr); - } - - G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->constructed (object); -} - -static void -meta_monitor_manager_xrandr_finalize (GObject *object) -{ - MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (object); - - g_hash_table_destroy (manager_xrandr->tiled_monitor_atoms); - g_free (manager_xrandr->supported_scales); - - G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->finalize (object); -} - -static void -meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr) -{ -} - -static void -meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass) -{ - MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass); - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_monitor_manager_xrandr_finalize; - object_class->constructed = meta_monitor_manager_xrandr_constructed; - - manager_class->read_edid = meta_monitor_manager_xrandr_read_edid; - manager_class->read_current_state = meta_monitor_manager_xrandr_read_current_state; - manager_class->ensure_initial_config = meta_monitor_manager_xrandr_ensure_initial_config; - manager_class->apply_monitors_config = meta_monitor_manager_xrandr_apply_monitors_config; - manager_class->set_power_save_mode = meta_monitor_manager_xrandr_set_power_save_mode; - manager_class->change_backlight = meta_monitor_manager_xrandr_change_backlight; - manager_class->get_crtc_gamma = meta_monitor_manager_xrandr_get_crtc_gamma; - manager_class->set_crtc_gamma = meta_monitor_manager_xrandr_set_crtc_gamma; - manager_class->tiled_monitor_added = meta_monitor_manager_xrandr_tiled_monitor_added; - manager_class->tiled_monitor_removed = meta_monitor_manager_xrandr_tiled_monitor_removed; - manager_class->is_transform_handled = meta_monitor_manager_xrandr_is_transform_handled; - manager_class->calculate_monitor_mode_scale = meta_monitor_manager_xrandr_calculate_monitor_mode_scale; - manager_class->calculate_supported_scales = meta_monitor_manager_xrandr_calculate_supported_scales; - manager_class->get_capabilities = meta_monitor_manager_xrandr_get_capabilities; - manager_class->get_max_screen_size = meta_monitor_manager_xrandr_get_max_screen_size; - manager_class->get_default_layout_mode = meta_monitor_manager_xrandr_get_default_layout_mode; - manager_class->set_output_ctm = meta_monitor_manager_xrandr_set_output_ctm; - - quark_meta_monitor_xrandr_data = - g_quark_from_static_string ("-meta-monitor-xrandr-data"); -} - -gboolean -meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xrandr, - XEvent *event) -{ - MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr); - MetaGpu *gpu = meta_monitor_manager_xrandr_get_gpu (manager_xrandr); - MetaGpuXrandr *gpu_xrandr; - XRRScreenResources *resources; - gboolean is_hotplug; - gboolean is_our_configuration; - - if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify) - return FALSE; - - XRRUpdateConfiguration (event); - - meta_monitor_manager_read_current_state (manager); - - gpu_xrandr = META_GPU_XRANDR (gpu); - resources = meta_gpu_xrandr_get_resources (gpu_xrandr); - - is_hotplug = resources->timestamp < resources->configTimestamp; - is_our_configuration = (resources->timestamp == - manager_xrandr->last_xrandr_set_timestamp); - if (is_hotplug) - { - meta_monitor_manager_reconfigure (manager); - } - else - { - MetaMonitorsConfig *config; - - if (is_our_configuration) - { - MetaMonitorConfigManager *config_manager = - meta_monitor_manager_get_config_manager (manager); - - config = meta_monitor_config_manager_get_current (config_manager); - } - else - { - config = NULL; - } - - meta_monitor_manager_xrandr_rebuild_derived (manager, config); - } - - return TRUE; -} diff --git a/src/backends/x11/meta-monitor-manager-xrandr.h b/src/backends/x11/meta-monitor-manager-xrandr.h deleted file mode 100644 index d55b3d2b8..000000000 --- a/src/backends/x11/meta-monitor-manager-xrandr.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * Copyright (C) 2013 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#ifndef META_MONITOR_MANAGER_XRANDR_H -#define META_MONITOR_MANAGER_XRANDR_H - -#include - -#include "backends/meta-monitor-manager-private.h" - -#define META_TYPE_MONITOR_MANAGER_XRANDR (meta_monitor_manager_xrandr_get_type ()) -G_DECLARE_FINAL_TYPE (MetaMonitorManagerXrandr, meta_monitor_manager_xrandr, - META, MONITOR_MANAGER_XRANDR, MetaMonitorManager) - -Display * meta_monitor_manager_xrandr_get_xdisplay (MetaMonitorManagerXrandr *manager_xrandr); - -gboolean meta_monitor_manager_xrandr_has_randr15 (MetaMonitorManagerXrandr *manager_xrandr); - -gboolean meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager, - XEvent *event); - -#endif /* META_MONITOR_MANAGER_XRANDR_H */ diff --git a/src/backends/x11/meta-output-xrandr.c b/src/backends/x11/meta-output-xrandr.c deleted file mode 100644 index 7265624f4..000000000 --- a/src/backends/x11/meta-output-xrandr.c +++ /dev/null @@ -1,987 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001, 2002 Havoc Pennington - * Copyright (C) 2001, 2002 Havoc Pennington - * Copyright (C) 2002, 2003 Red Hat Inc. - * Some ICCCM manager selection code derived from fvwm2, - * Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * Copyright (C) 2002, 2003 Red Hat Inc. - * Some ICCCM manager selection code derived from fvwm2, - * Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * Copyright (C) 2013-2017 Red Hat Inc. - * Copyright (C) 2020 NVIDIA CORPORATION - * - * 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 "backends/x11/meta-output-xrandr.h" - -#include -#include -#include -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-crtc.h" -#include "backends/x11/meta-monitor-manager-xrandr.h" -#include "meta/util.h" - -struct _MetaOutputXrandr -{ - MetaOutput parent; - - gboolean ctm_initialized; - MetaOutputCtm ctm; -}; - -G_DEFINE_TYPE (MetaOutputXrandr, meta_output_xrandr, META_TYPE_OUTPUT) - -static Display * -xdisplay_from_gpu (MetaGpu *gpu) -{ - MetaBackend *backend = meta_gpu_get_backend (gpu); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerXrandr *monitor_manager_xrandr = - META_MONITOR_MANAGER_XRANDR (monitor_manager); - - return meta_monitor_manager_xrandr_get_xdisplay (monitor_manager_xrandr); -} - -static Display * -xdisplay_from_output (MetaOutput *output) -{ - return xdisplay_from_gpu (meta_output_get_gpu (output)); -} - -static void -output_set_presentation_xrandr (MetaOutput *output, - gboolean presentation) -{ - Display *xdisplay = xdisplay_from_output (output); - Atom atom; - int value = presentation; - - atom = XInternAtom (xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False); - - xcb_randr_change_output_property (XGetXCBConnection (xdisplay), - (XID) meta_output_get_id (output), - atom, XCB_ATOM_CARDINAL, 32, - XCB_PROP_MODE_REPLACE, - 1, &value); -} - -static void -output_set_underscanning_xrandr (MetaOutput *output, - gboolean underscanning) -{ - Display *xdisplay = xdisplay_from_output (output); - Atom prop, valueatom; - const char *value; - - prop = XInternAtom (xdisplay, "underscan", False); - - value = underscanning ? "on" : "off"; - valueatom = XInternAtom (xdisplay, value, False); - - xcb_randr_change_output_property (XGetXCBConnection (xdisplay), - (XID) meta_output_get_id (output), - prop, XCB_ATOM_ATOM, 32, - XCB_PROP_MODE_REPLACE, - 1, &valueatom); - - /* Configure the border at the same time. Currently, we use a - * 5% of the width/height of the mode. In the future, we should - * make the border configurable. */ - if (underscanning) - { - MetaCrtc *crtc; - const MetaCrtcConfig *crtc_config; - const MetaCrtcModeInfo *crtc_mode_info; - uint32_t border_value; - - crtc = meta_output_get_assigned_crtc (output); - crtc_config = meta_crtc_get_config (crtc); - crtc_mode_info = meta_crtc_mode_get_info (crtc_config->mode); - - prop = XInternAtom (xdisplay, "underscan hborder", False); - border_value = crtc_mode_info->width * 0.05; - - xcb_randr_change_output_property (XGetXCBConnection (xdisplay), - (XID) meta_output_get_id (output), - prop, XCB_ATOM_INTEGER, 32, - XCB_PROP_MODE_REPLACE, - 1, &border_value); - - prop = XInternAtom (xdisplay, "underscan vborder", False); - border_value = crtc_mode_info->height * 0.05; - - xcb_randr_change_output_property (XGetXCBConnection (xdisplay), - (XID) meta_output_get_id (output), - prop, XCB_ATOM_INTEGER, 32, - XCB_PROP_MODE_REPLACE, - 1, &border_value); - } -} - -void -meta_output_xrandr_apply_mode (MetaOutputXrandr *output_xrandr) -{ - MetaOutput *output = META_OUTPUT (output_xrandr); - Display *xdisplay = xdisplay_from_output (output); - - if (meta_output_is_primary (output)) - { - XRRSetOutputPrimary (xdisplay, DefaultRootWindow (xdisplay), - (XID) meta_output_get_id (output)); - } - - output_set_presentation_xrandr (output, meta_output_is_presentation (output)); - - if (meta_output_get_info (output)->supports_underscanning) - { - output_set_underscanning_xrandr (output, - meta_output_is_underscanning (output)); - } -} - -static int -normalize_backlight (MetaOutput *output, - int hw_value) -{ - const MetaOutputInfo *output_info = meta_output_get_info (output); - - return round ((double) (hw_value - output_info->backlight_min) / - (output_info->backlight_max - output_info->backlight_min) * 100.0); -} - -void -meta_output_xrandr_change_backlight (MetaOutputXrandr *output_xrandr, - int value) -{ - MetaOutput *output = META_OUTPUT (output_xrandr); - const MetaOutputInfo *output_info = meta_output_get_info (output); - Display *xdisplay = xdisplay_from_output (output); - Atom atom; - int hw_value; - - hw_value = round ((double) value / 100.0 * output_info->backlight_max + - output_info->backlight_min); - - atom = XInternAtom (xdisplay, "Backlight", False); - - xcb_randr_change_output_property (XGetXCBConnection (xdisplay), - (XID) meta_output_get_id (output), - atom, XCB_ATOM_INTEGER, 32, - XCB_PROP_MODE_REPLACE, - 1, &hw_value); - - /* We're not selecting for property notifies, so update the value immediately */ - meta_output_set_backlight (output, normalize_backlight (output, hw_value)); -} - -static gboolean -ctm_is_equal (const MetaOutputCtm *ctm1, - const MetaOutputCtm *ctm2) -{ - int i; - - for (i = 0; i < 9; i++) - { - if (ctm1->matrix[i] != ctm2->matrix[i]) - return FALSE; - } - - return TRUE; -} - -void -meta_output_xrandr_set_ctm (MetaOutputXrandr *output_xrandr, - const MetaOutputCtm *ctm) -{ - if (!output_xrandr->ctm_initialized || - !ctm_is_equal (ctm, &output_xrandr->ctm)) - { - MetaOutput *output = META_OUTPUT (output_xrandr); - Display *xdisplay = xdisplay_from_output (output); - Atom ctm_atom = XInternAtom (xdisplay, "CTM", False); - - xcb_randr_change_output_property (XGetXCBConnection (xdisplay), - (XID) meta_output_get_id (output), - ctm_atom, XCB_ATOM_INTEGER, 32, - XCB_PROP_MODE_REPLACE, - 18, &ctm->matrix); - - output_xrandr->ctm = *ctm; - output_xrandr->ctm_initialized = TRUE; - } -} - -static gboolean -output_get_integer_property (Display *xdisplay, - RROutput output_id, - const char *propname, - gint *value) -{ - gboolean exists = FALSE; - Atom atom, actual_type; - int actual_format; - unsigned long nitems, bytes_after; - unsigned char *buffer; - - atom = XInternAtom (xdisplay, propname, False); - XRRGetOutputProperty (xdisplay, - (XID) output_id, - atom, - 0, G_MAXLONG, False, False, XA_INTEGER, - &actual_type, &actual_format, - &nitems, &bytes_after, &buffer); - - exists = (actual_type == XA_INTEGER && actual_format == 32 && nitems == 1); - - if (exists && value != NULL) - *value = ((int*)buffer)[0]; - - XFree (buffer); - return exists; -} - -static gboolean -output_get_property_exists (Display *xdisplay, - RROutput output_id, - const char *propname) -{ - gboolean exists = FALSE; - Atom atom, actual_type; - int actual_format; - unsigned long nitems, bytes_after; - unsigned char *buffer; - - atom = XInternAtom (xdisplay, propname, False); - XRRGetOutputProperty (xdisplay, - (XID) output_id, - atom, - 0, G_MAXLONG, False, False, AnyPropertyType, - &actual_type, &actual_format, - &nitems, &bytes_after, &buffer); - - exists = (actual_type != None); - - XFree (buffer); - return exists; -} - -static gboolean -output_get_boolean_property (MetaOutput *output, - const char *propname) -{ - Display *xdisplay = xdisplay_from_output (output); - Atom atom, actual_type; - int actual_format; - unsigned long nitems, bytes_after; - g_autofree unsigned char *buffer = NULL; - - atom = XInternAtom (xdisplay, propname, False); - XRRGetOutputProperty (xdisplay, - (XID) meta_output_get_id (output), - atom, - 0, G_MAXLONG, False, False, XA_CARDINAL, - &actual_type, &actual_format, - &nitems, &bytes_after, &buffer); - - if (actual_type != XA_CARDINAL || actual_format != 32 || nitems < 1) - return FALSE; - - return ((int*)buffer)[0]; -} - -static gboolean -output_get_presentation_xrandr (MetaOutput *output) -{ - return output_get_boolean_property (output, "_MUTTER_PRESENTATION_OUTPUT"); -} - -static gboolean -output_get_underscanning_xrandr (MetaOutput *output) -{ - Display *xdisplay = xdisplay_from_output (output); - Atom atom, actual_type; - int actual_format; - unsigned long nitems, bytes_after; - g_autofree unsigned char *buffer = NULL; - g_autofree char *str = NULL; - - atom = XInternAtom (xdisplay, "underscan", False); - XRRGetOutputProperty (xdisplay, - (XID) meta_output_get_id (output), - atom, - 0, G_MAXLONG, False, False, XA_ATOM, - &actual_type, &actual_format, - &nitems, &bytes_after, &buffer); - - if (actual_type != XA_ATOM || actual_format != 32 || nitems < 1) - return FALSE; - - str = XGetAtomName (xdisplay, *(Atom *)buffer); - return (strcmp (str, "on") == 0); -} - -static gboolean -output_get_supports_underscanning_xrandr (Display *xdisplay, - RROutput output_id) -{ - Atom atom, actual_type; - int actual_format, i; - unsigned long nitems, bytes_after; - g_autofree unsigned char *buffer = NULL; - XRRPropertyInfo *property_info; - Atom *values; - gboolean supports_underscanning = FALSE; - - atom = XInternAtom (xdisplay, "underscan", False); - XRRGetOutputProperty (xdisplay, - (XID) output_id, - atom, - 0, G_MAXLONG, False, False, XA_ATOM, - &actual_type, &actual_format, - &nitems, &bytes_after, &buffer); - - if (actual_type != XA_ATOM || actual_format != 32 || nitems < 1) - return FALSE; - - property_info = XRRQueryOutputProperty (xdisplay, - (XID) output_id, - atom); - values = (Atom *) property_info->values; - - for (i = 0; i < property_info->num_values; i++) - { - /* The output supports underscanning if "on" is a valid value - * for the underscan property. - */ - char *name = XGetAtomName (xdisplay, values[i]); - if (strcmp (name, "on") == 0) - supports_underscanning = TRUE; - - XFree (name); - } - - XFree (property_info); - - return supports_underscanning; -} - -static gboolean -output_get_supports_color_transform_xrandr (Display *xdisplay, - RROutput output_id) -{ - Atom atom, actual_type; - int actual_format; - unsigned long nitems, bytes_after; - g_autofree unsigned char *buffer = NULL; - - atom = XInternAtom (xdisplay, "CTM", False); - XRRGetOutputProperty (xdisplay, - (XID) output_id, - atom, - 0, G_MAXLONG, False, False, XA_INTEGER, - &actual_type, &actual_format, - &nitems, &bytes_after, &buffer); - - /* - * X's CTM property is 9 64-bit integers represented as an array of 18 32-bit - * integers. - */ - return (actual_type == XA_INTEGER && - actual_format == 32 && - nitems == 18); -} - -static int -output_get_backlight_xrandr (MetaOutput *output) -{ - Display *xdisplay = xdisplay_from_output (output); - int value = -1; - Atom atom, actual_type; - int actual_format; - unsigned long nitems, bytes_after; - g_autofree unsigned char *buffer = NULL; - - atom = XInternAtom (xdisplay, "Backlight", False); - XRRGetOutputProperty (xdisplay, - (XID) meta_output_get_id (output), - atom, - 0, G_MAXLONG, False, False, XA_INTEGER, - &actual_type, &actual_format, - &nitems, &bytes_after, &buffer); - - if (actual_type != XA_INTEGER || actual_format != 32 || nitems < 1) - return FALSE; - - value = ((int*)buffer)[0]; - if (value > 0) - return normalize_backlight (output, value); - else - return -1; -} - -static void -output_info_init_backlight_limits_xrandr (MetaOutputInfo *output_info, - Display *xdisplay, - xcb_randr_output_t output_id) -{ - Atom atom; - xcb_connection_t *xcb_conn; - xcb_randr_query_output_property_cookie_t cookie; - g_autofree xcb_randr_query_output_property_reply_t *reply = NULL; - - atom = XInternAtom (xdisplay, "Backlight", False); - - xcb_conn = XGetXCBConnection (xdisplay); - cookie = xcb_randr_query_output_property (xcb_conn, - output_id, - (xcb_atom_t) atom); - reply = xcb_randr_query_output_property_reply (xcb_conn, - cookie, - NULL); - - /* This can happen on systems without backlights. */ - if (reply == NULL) - return; - - if (!reply->range || reply->length != 2) - { - meta_verbose ("backlight %s was not range", output_info->name); - return; - } - - int32_t *values = xcb_randr_query_output_property_valid_values (reply); - output_info->backlight_min = values[0]; - output_info->backlight_max = values[1]; -} - -static guint8 * -get_edid_property (Display *xdisplay, - RROutput output, - Atom atom, - gsize *len) -{ - unsigned char *prop; - int actual_format; - unsigned long nitems, bytes_after; - Atom actual_type; - guint8 *result; - - XRRGetOutputProperty (xdisplay, output, atom, - 0, 100, False, False, - AnyPropertyType, - &actual_type, &actual_format, - &nitems, &bytes_after, &prop); - - if (actual_type == XA_INTEGER && actual_format == 8) - { - result = g_memdup2 (prop, nitems); - if (len) - *len = nitems; - } - else - { - result = NULL; - } - - XFree (prop); - - return result; -} - -static GBytes * -read_xrandr_edid (Display *xdisplay, - RROutput output_id) -{ - Atom edid_atom; - guint8 *result; - gsize len; - - edid_atom = XInternAtom (xdisplay, "EDID", FALSE); - result = get_edid_property (xdisplay, output_id, edid_atom, &len); - - if (!result) - { - edid_atom = XInternAtom (xdisplay, "EDID_DATA", FALSE); - result = get_edid_property (xdisplay, output_id, edid_atom, &len); - } - - if (result) - { - if (len > 0 && len % 128 == 0) - return g_bytes_new_take (result, len); - else - g_free (result); - } - - return NULL; -} - -GBytes * -meta_output_xrandr_read_edid (MetaOutput *output) -{ - Display *xdisplay = xdisplay_from_output (output); - RROutput output_id = (RROutput) meta_output_get_id (output); - - return read_xrandr_edid (xdisplay, output_id); -} - -static gboolean -output_get_hotplug_mode_update (Display *xdisplay, - RROutput output_id) -{ - return output_get_property_exists (xdisplay, output_id, "hotplug_mode_update"); -} - -static gint -output_get_suggested_x (Display *xdisplay, - RROutput output_id) -{ - gint val; - if (output_get_integer_property (xdisplay, output_id, "suggested X", &val)) - return val; - - return -1; -} - -static gint -output_get_suggested_y (Display *xdisplay, - RROutput output_id) -{ - gint val; - if (output_get_integer_property (xdisplay, output_id, "suggested Y", &val)) - return val; - - return -1; -} - -static MetaConnectorType -connector_type_from_atom (Display *xdisplay, - Atom atom) -{ - if (atom == XInternAtom (xdisplay, "HDMI", True)) - return META_CONNECTOR_TYPE_HDMIA; - if (atom == XInternAtom (xdisplay, "VGA", True)) - return META_CONNECTOR_TYPE_VGA; - /* Doesn't have a DRM equivalent, but means an internal panel. - * We could pick either LVDS or eDP here. */ - if (atom == XInternAtom (xdisplay, "Panel", True)) - return META_CONNECTOR_TYPE_LVDS; - if (atom == XInternAtom (xdisplay, "DVI", True) || - atom == XInternAtom (xdisplay, "DVI-I", True)) - return META_CONNECTOR_TYPE_DVII; - if (atom == XInternAtom (xdisplay, "DVI-A", True)) - return META_CONNECTOR_TYPE_DVIA; - if (atom == XInternAtom (xdisplay, "DVI-D", True)) - return META_CONNECTOR_TYPE_DVID; - if (atom == XInternAtom (xdisplay, "DisplayPort", True)) - return META_CONNECTOR_TYPE_DisplayPort; - - if (atom == XInternAtom (xdisplay, "TV", True)) - return META_CONNECTOR_TYPE_TV; - if (atom == XInternAtom (xdisplay, "TV-Composite", True)) - return META_CONNECTOR_TYPE_Composite; - if (atom == XInternAtom (xdisplay, "TV-SVideo", True)) - return META_CONNECTOR_TYPE_SVIDEO; - /* Another set of mismatches. */ - if (atom == XInternAtom (xdisplay, "TV-SCART", True)) - return META_CONNECTOR_TYPE_TV; - if (atom == XInternAtom (xdisplay, "TV-C4", True)) - return META_CONNECTOR_TYPE_TV; - - return META_CONNECTOR_TYPE_Unknown; -} - -static MetaConnectorType -output_get_connector_type_from_prop (Display *xdisplay, - RROutput output_id) -{ - Atom atom, actual_type, connector_type_atom; - int actual_format; - unsigned long nitems, bytes_after; - g_autofree unsigned char *buffer = NULL; - - atom = XInternAtom (xdisplay, "ConnectorType", False); - XRRGetOutputProperty (xdisplay, - (XID) output_id, - atom, - 0, G_MAXLONG, False, False, XA_ATOM, - &actual_type, &actual_format, - &nitems, &bytes_after, &buffer); - - if (actual_type != XA_ATOM || actual_format != 32 || nitems < 1) - return META_CONNECTOR_TYPE_Unknown; - - connector_type_atom = ((Atom *) buffer)[0]; - return connector_type_from_atom (xdisplay, connector_type_atom); -} - -static MetaConnectorType -output_info_get_connector_type_from_name (const MetaOutputInfo *output_info) -{ - const char *name = output_info->name; - - /* drmmode_display.c, which was copy/pasted across all the FOSS - * xf86-video-* drivers, seems to name its outputs based on the - * connector type, so look for that.... - * - * SNA has its own naming scheme, because what else did you expect - * from SNA, but it's not too different, so we can thankfully use - * that with minor changes. - * - * http://cgit.freedesktop.org/xorg/xserver/tree/hw/xfree86/drivers/modesetting/drmmode_display.c#n953 - * http://cgit.freedesktop.org/xorg/driver/xf86-video-intel/tree/src/sna/sna_display.c#n3486 - */ - - if (g_str_has_prefix (name, "DVI")) - return META_CONNECTOR_TYPE_DVII; - if (g_str_has_prefix (name, "LVDS")) - return META_CONNECTOR_TYPE_LVDS; - if (g_str_has_prefix (name, "HDMI")) - return META_CONNECTOR_TYPE_HDMIA; - if (g_str_has_prefix (name, "VGA")) - return META_CONNECTOR_TYPE_VGA; - /* SNA uses DP, not DisplayPort. Test for both. */ - if (g_str_has_prefix (name, "DP") || g_str_has_prefix (name, "DisplayPort")) - return META_CONNECTOR_TYPE_DisplayPort; - if (g_str_has_prefix (name, "eDP")) - return META_CONNECTOR_TYPE_eDP; - if (g_str_has_prefix (name, "Virtual")) - return META_CONNECTOR_TYPE_VIRTUAL; - if (g_str_has_prefix (name, "Composite")) - return META_CONNECTOR_TYPE_Composite; - if (g_str_has_prefix (name, "S-video")) - return META_CONNECTOR_TYPE_SVIDEO; - if (g_str_has_prefix (name, "TV")) - return META_CONNECTOR_TYPE_TV; - if (g_str_has_prefix (name, "CTV")) - return META_CONNECTOR_TYPE_Composite; - if (g_str_has_prefix (name, "DSI")) - return META_CONNECTOR_TYPE_DSI; - if (g_str_has_prefix (name, "DIN")) - return META_CONNECTOR_TYPE_9PinDIN; - - return META_CONNECTOR_TYPE_Unknown; -} - -static MetaConnectorType -output_info_get_connector_type (MetaOutputInfo *output_info, - Display *xdisplay, - RROutput output_id) -{ - MetaConnectorType ret; - - /* The "ConnectorType" property is considered mandatory since RandR 1.3, - * but none of the FOSS drivers support it, because we're a bunch of - * professional software developers. - * - * Try poking it first, without any expectations that it will work. - * If it's not there, we thankfully have other bonghits to try next. - */ - ret = output_get_connector_type_from_prop (xdisplay, output_id); - if (ret != META_CONNECTOR_TYPE_Unknown) - return ret; - - /* Fall back to heuristics based on the output name. */ - ret = output_info_get_connector_type_from_name (output_info); - if (ret != META_CONNECTOR_TYPE_Unknown) - return ret; - - return META_CONNECTOR_TYPE_Unknown; -} - -static gint -output_get_panel_orientation_transform (Display *xdisplay, - RROutput output_id) -{ - unsigned long nitems, bytes_after; - Atom atom, actual_type; - int actual_format; - g_autofree unsigned char *buffer = NULL; - g_autofree char *str = NULL; - - atom = XInternAtom (xdisplay, "panel orientation", False); - XRRGetOutputProperty (xdisplay, - (XID) output_id, - atom, - 0, G_MAXLONG, False, False, XA_ATOM, - &actual_type, &actual_format, - &nitems, &bytes_after, &buffer); - - if (actual_type != XA_ATOM || actual_format != 32 || nitems < 1) - return META_MONITOR_TRANSFORM_NORMAL; - - str = XGetAtomName (xdisplay, *(Atom *)buffer); - if (strcmp (str, "Upside Down") == 0) - return META_MONITOR_TRANSFORM_180; - - if (strcmp (str, "Left Side Up") == 0) - return META_MONITOR_TRANSFORM_90; - - if (strcmp (str, "Right Side Up") == 0) - return META_MONITOR_TRANSFORM_270; - - return META_MONITOR_TRANSFORM_NORMAL; -} - -static void -output_info_init_tile_info (MetaOutputInfo *output_info, - Display *xdisplay, - RROutput output_id) -{ - Atom tile_atom; - unsigned char *prop; - unsigned long nitems, bytes_after; - int actual_format; - Atom actual_type; - - tile_atom = XInternAtom (xdisplay, "TILE", FALSE); - XRRGetOutputProperty (xdisplay, - (XID) output_id, - tile_atom, 0, 100, False, - False, AnyPropertyType, - &actual_type, &actual_format, - &nitems, &bytes_after, &prop); - - if (actual_type == XA_INTEGER && actual_format == 32 && nitems == 8) - { - long *values = (long *)prop; - - output_info->tile_info.group_id = values[0]; - output_info->tile_info.flags = values[1]; - output_info->tile_info.max_h_tiles = values[2]; - output_info->tile_info.max_v_tiles = values[3]; - output_info->tile_info.loc_h_tile = values[4]; - output_info->tile_info.loc_v_tile = values[5]; - output_info->tile_info.tile_w = values[6]; - output_info->tile_info.tile_h = values[7]; - } - XFree (prop); -} - - -static void -output_info_init_modes (MetaOutputInfo *output_info, - MetaGpu *gpu, - XRROutputInfo *xrandr_output) -{ - unsigned int i; - unsigned int n_actual_modes; - - output_info->modes = g_new0 (MetaCrtcMode *, xrandr_output->nmode); - - n_actual_modes = 0; - for (i = 0; i < (unsigned int) xrandr_output->nmode; i++) - { - GList *l; - - for (l = meta_gpu_get_modes (gpu); l; l = l->next) - { - MetaCrtcMode *mode = l->data; - - if (xrandr_output->modes[i] == (XID) meta_crtc_mode_get_id (mode)) - { - output_info->modes[n_actual_modes] = mode; - n_actual_modes += 1; - break; - } - } - } - output_info->n_modes = n_actual_modes; - if (n_actual_modes > 0) - output_info->preferred_mode = output_info->modes[0]; -} - -static void -output_info_init_crtcs (MetaOutputInfo *output_info, - MetaGpu *gpu, - XRROutputInfo *xrandr_output) -{ - unsigned int i; - unsigned int n_actual_crtcs; - GList *l; - - output_info->possible_crtcs = g_new0 (MetaCrtc *, xrandr_output->ncrtc); - - n_actual_crtcs = 0; - for (i = 0; i < (unsigned int) xrandr_output->ncrtc; i++) - { - for (l = meta_gpu_get_crtcs (gpu); l; l = l->next) - { - MetaCrtc *crtc = l->data; - - if ((XID) meta_crtc_get_id (crtc) == xrandr_output->crtcs[i]) - { - output_info->possible_crtcs[n_actual_crtcs] = crtc; - n_actual_crtcs += 1; - break; - } - } - } - output_info->n_possible_crtcs = n_actual_crtcs; -} - -static MetaCrtc * -find_assigned_crtc (MetaGpu *gpu, - XRROutputInfo *xrandr_output) -{ - GList *l; - - for (l = meta_gpu_get_crtcs (gpu); l; l = l->next) - { - MetaCrtc *crtc = l->data; - - if ((XID) meta_crtc_get_id (crtc) == xrandr_output->crtc) - return crtc; - } - - return NULL; -} - -MetaOutputXrandr * -meta_output_xrandr_new (MetaGpuXrandr *gpu_xrandr, - XRROutputInfo *xrandr_output, - RROutput output_id, - RROutput primary_output) -{ - MetaGpu *gpu = META_GPU (gpu_xrandr); - MetaBackend *backend = meta_gpu_get_backend (gpu); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerXrandr *monitor_manager_xrandr = - META_MONITOR_MANAGER_XRANDR (monitor_manager); - Display *xdisplay = - meta_monitor_manager_xrandr_get_xdisplay (monitor_manager_xrandr); - g_autoptr (MetaOutputInfo) output_info = NULL; - MetaOutput *output; - GBytes *edid; - MetaCrtc *assigned_crtc; - unsigned int i; - - output_info = meta_output_info_new (); - - output_info->name = g_strdup (xrandr_output->name); - - edid = read_xrandr_edid (xdisplay, output_id); - meta_output_info_parse_edid (output_info, edid); - g_bytes_unref (edid); - - output_info->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN; - output_info->hotplug_mode_update = output_get_hotplug_mode_update (xdisplay, - output_id); - output_info->suggested_x = output_get_suggested_x (xdisplay, output_id); - output_info->suggested_y = output_get_suggested_y (xdisplay, output_id); - output_info->connector_type = output_info_get_connector_type (output_info, - xdisplay, - output_id); - output_info->panel_orientation_transform = - output_get_panel_orientation_transform (xdisplay, output_id); - - if (meta_monitor_transform_is_rotated ( - output_info->panel_orientation_transform)) - { - output_info->width_mm = xrandr_output->mm_height; - output_info->height_mm = xrandr_output->mm_width; - } - else - { - output_info->width_mm = xrandr_output->mm_width; - output_info->height_mm = xrandr_output->mm_height; - } - - if (meta_monitor_manager_xrandr_has_randr15 (monitor_manager_xrandr)) - output_info_init_tile_info (output_info, xdisplay, output_id); - output_info_init_modes (output_info, gpu, xrandr_output); - output_info_init_crtcs (output_info, gpu, xrandr_output); - - output_info->n_possible_clones = xrandr_output->nclone; - output_info->possible_clones = g_new0 (MetaOutput *, - output_info->n_possible_clones); - /* - * We can build the list of clones now, because we don't have the list of - * outputs yet, so temporarily set the pointers to the bare XIDs, and then - * we'll fix them in a second pass. - */ - for (i = 0; i < (unsigned int) xrandr_output->nclone; i++) - { - output_info->possible_clones[i] = GINT_TO_POINTER (xrandr_output->clones[i]); - } - - output_info->supports_underscanning = - output_get_supports_underscanning_xrandr (xdisplay, output_id); - output_info->supports_color_transform = - output_get_supports_color_transform_xrandr (xdisplay, output_id); - output_info_init_backlight_limits_xrandr (output_info, xdisplay, output_id); - - output = g_object_new (META_TYPE_OUTPUT_XRANDR, - "id", (uint64_t) output_id, - "gpu", gpu_xrandr, - "info", output_info, - NULL); - - assigned_crtc = find_assigned_crtc (gpu, xrandr_output); - if (assigned_crtc) - { - MetaOutputAssignment output_assignment; - - output_assignment = (MetaOutputAssignment) { - .is_primary = (XID) meta_output_get_id (output) == primary_output, - .is_presentation = output_get_presentation_xrandr (output), - .is_underscanning = output_get_underscanning_xrandr (output), - }; - meta_output_assign_crtc (output, assigned_crtc, &output_assignment); - } - else - { - meta_output_unassign_crtc (output); - } - - if (!(output_info->backlight_min == 0 && output_info->backlight_max == 0)) - meta_output_set_backlight (output, output_get_backlight_xrandr (output)); - - if (output_info->n_modes == 0 || output_info->n_possible_crtcs == 0) - { - g_object_unref (output); - return NULL; - } - else - { - return META_OUTPUT_XRANDR (output); - } -} - -static void -meta_output_xrandr_init (MetaOutputXrandr *output_xrandr) -{ -} - -static void -meta_output_xrandr_class_init (MetaOutputXrandrClass *klass) -{ -} diff --git a/src/backends/x11/meta-output-xrandr.h b/src/backends/x11/meta-output-xrandr.h deleted file mode 100644 index ec5104f30..000000000 --- a/src/backends/x11/meta-output-xrandr.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 Red Hat - * Copyright (C) 2020 NVIDIA CORPORATION - * - * 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_OUTPUT_XRANDR_H -#define META_OUTPUT_XRANDR_H - -#include - -#include "backends/meta-output.h" -#include "backends/x11/meta-gpu-xrandr.h" -#include "backends/x11/meta-monitor-manager-xrandr.h" - -#define META_TYPE_OUTPUT_XRANDR (meta_output_xrandr_get_type ()) -G_DECLARE_FINAL_TYPE (MetaOutputXrandr, meta_output_xrandr, - META, OUTPUT_XRANDR, - MetaOutput) - -void meta_output_xrandr_apply_mode (MetaOutputXrandr *output_xrandr); - -void meta_output_xrandr_change_backlight (MetaOutputXrandr *output_xrandr, - int value); - -void meta_output_xrandr_set_ctm (MetaOutputXrandr *output_xrandr, - const MetaOutputCtm *ctm); - -GBytes * meta_output_xrandr_read_edid (MetaOutput *output_xrandr); - -MetaOutputXrandr * meta_output_xrandr_new (MetaGpuXrandr *gpu_xrandr, - XRROutputInfo *xrandr_output, - RROutput output_id, - RROutput primary_output); - -#endif /* META_OUTPUT_XRANDR_H */ diff --git a/src/backends/x11/meta-renderer-x11.c b/src/backends/x11/meta-renderer-x11.c deleted file mode 100644 index e31faff53..000000000 --- a/src/backends/x11/meta-renderer-x11.c +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#include "config.h" - -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-logical-monitor.h" -#include "backends/meta-renderer-view.h" -#include "backends/meta-renderer.h" -#include "backends/x11/meta-clutter-backend-x11.h" -#include "backends/x11/meta-renderer-x11.h" -#include "cogl/cogl-xlib.h" -#include "cogl/cogl.h" -#include "core/boxes-private.h" -#include "meta/meta-backend.h" -#include "meta/util.h" - -#ifdef COGL_HAS_EGL_SUPPORT -#include "cogl/winsys/cogl-winsys-egl-x11-private.h" -#endif -#ifdef COGL_HAS_GLX_SUPPORT -#include "cogl/winsys/cogl-winsys-glx-private.h" -#endif - -G_DEFINE_TYPE (MetaRendererX11, meta_renderer_x11, META_TYPE_RENDERER) - -static const CoglWinsysVtable * -get_x11_cogl_winsys_vtable (CoglRenderer *renderer) -{ -#ifdef COGL_HAS_EGL_PLATFORM_XLIB_SUPPORT - if (meta_is_wayland_compositor ()) - return _cogl_winsys_egl_xlib_get_vtable (); -#endif - - switch (renderer->driver) - { - case COGL_DRIVER_GLES2: -#ifdef COGL_HAS_EGL_PLATFORM_XLIB_SUPPORT - return _cogl_winsys_egl_xlib_get_vtable (); -#else - break; -#endif - case COGL_DRIVER_GL: - case COGL_DRIVER_GL3: -#ifdef COGL_HAS_GLX_SUPPORT - return _cogl_winsys_glx_get_vtable (); -#else - break; -#endif - case COGL_DRIVER_ANY: - case COGL_DRIVER_NOP: - break; - } - g_assert_not_reached (); - return NULL; -} - -static CoglRenderer * -meta_renderer_x11_create_cogl_renderer (MetaRenderer *renderer) -{ - CoglRenderer *cogl_renderer; - Display *xdisplay = meta_clutter_x11_get_default_display (); - - cogl_renderer = cogl_renderer_new (); - cogl_renderer_set_custom_winsys (cogl_renderer, get_x11_cogl_winsys_vtable, - NULL); - cogl_xlib_renderer_set_foreign_display (cogl_renderer, xdisplay); - cogl_xlib_renderer_request_reset_on_video_memory_purge (cogl_renderer, TRUE); - - return cogl_renderer; -} - -static void -meta_renderer_x11_init (MetaRendererX11 *renderer_x11) -{ -} - -static void -meta_renderer_x11_class_init (MetaRendererX11Class *klass) -{ - MetaRendererClass *renderer_class = META_RENDERER_CLASS (klass); - - renderer_class->create_cogl_renderer = meta_renderer_x11_create_cogl_renderer; -} diff --git a/src/backends/x11/meta-renderer-x11.h b/src/backends/x11/meta-renderer-x11.h deleted file mode 100644 index 5ec0d4bc4..000000000 --- a/src/backends/x11/meta-renderer-x11.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#ifndef META_RENDERER_X11_H -#define META_RENDERER_X11_H - -#include - -#include "backends/meta-renderer.h" - -struct _MetaRendererX11Class -{ - MetaRendererClass parent_class; -}; - -#define META_TYPE_RENDERER_X11 (meta_renderer_x11_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaRendererX11, meta_renderer_x11, - META, RENDERER_X11, - MetaRenderer) - -#endif /* META_RENDERER_X11_H */ diff --git a/src/backends/x11/meta-seat-x11.c b/src/backends/x11/meta-seat-x11.c deleted file mode 100644 index 2f2637ac8..000000000 --- a/src/backends/x11/meta-seat-x11.c +++ /dev/null @@ -1,2422 +0,0 @@ -/* - * 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 . - * - * Author: Carlos Garnacho - */ -#include "config.h" - -#include -#include -#include - -#include "backends/meta-input-settings-private.h" -#include "backends/x11/meta-backend-x11.h" -#include "backends/x11/meta-clutter-backend-x11.h" -#include "backends/x11/meta-event-x11.h" -#include "backends/x11/meta-input-device-tool-x11.h" -#include "backends/x11/meta-input-device-x11.h" -#include "backends/x11/meta-keymap-x11.h" -#include "backends/x11/meta-stage-x11.h" -#include "backends/x11/meta-virtual-input-device-x11.h" -#include "backends/x11/meta-xkb-a11y-x11.h" -#include "clutter/clutter-mutter.h" -#include "core/bell.h" -#include "meta-seat-x11.h" - -enum -{ - PROP_0, - PROP_OPCODE, - PROP_POINTER_ID, - PROP_KEYBOARD_ID, - N_PROPS, - - /* This property is overridden */ - PROP_TOUCH_MODE, -}; - -typedef struct _MetaTouchInfo MetaTouchInfo; - -struct _MetaTouchInfo -{ - ClutterEventSequence *sequence; - double x; - double y; -}; - -struct _MetaSeatX11 -{ - ClutterSeat parent_instance; - ClutterInputDevice *core_pointer; - ClutterInputDevice *core_keyboard; - GList *devices; - GHashTable *devices_by_id; - GHashTable *tools_by_serial; - GHashTable *touch_coords; - MetaKeymapX11 *keymap; - - int pointer_id; - int keyboard_id; - int opcode; - guint has_touchscreens : 1; - guint touch_mode : 1; - guint has_pointer_focus : 1; -}; - -static GParamSpec *props[N_PROPS] = { 0 }; - -G_DEFINE_TYPE (MetaSeatX11, meta_seat_x11, CLUTTER_TYPE_SEAT) - -static const char *clutter_input_axis_atom_names[] = { - "Abs X", /* CLUTTER_INPUT_AXIS_X */ - "Abs Y", /* CLUTTER_INPUT_AXIS_Y */ - "Abs Pressure", /* CLUTTER_INPUT_AXIS_PRESSURE */ - "Abs Tilt X", /* CLUTTER_INPUT_AXIS_XTILT */ - "Abs Tilt Y", /* CLUTTER_INPUT_AXIS_YTILT */ - "Abs Wheel", /* CLUTTER_INPUT_AXIS_WHEEL */ - "Abs Distance", /* CLUTTER_INPUT_AXIS_DISTANCE */ -}; - -static const char *wacom_type_atoms[] = { - "STYLUS", - "CURSOR", - "ERASER", - "PAD", - "TOUCH" -}; -#define N_WACOM_TYPE_ATOMS G_N_ELEMENTS (wacom_type_atoms) - -enum -{ - WACOM_TYPE_STYLUS, - WACOM_TYPE_CURSOR, - WACOM_TYPE_ERASER, - WACOM_TYPE_PAD, - WACOM_TYPE_TOUCH, -}; - -enum -{ - PAD_AXIS_FIRST = 3, /* First axes are always x/y/pressure, ignored in pads */ - PAD_AXIS_STRIP1 = PAD_AXIS_FIRST, - PAD_AXIS_STRIP2, - PAD_AXIS_RING1, - PAD_AXIS_RING2, -}; - -#define N_AXIS_ATOMS G_N_ELEMENTS (clutter_input_axis_atom_names) - -static Atom clutter_input_axis_atoms[N_AXIS_ATOMS] = { 0, }; - -static void -translate_valuator_class (Display *xdisplay, - ClutterInputDevice *device, - XIValuatorClassInfo *class) -{ - static gboolean atoms_initialized = FALSE; - ClutterInputAxis i, axis = CLUTTER_INPUT_AXIS_IGNORE; - - if (G_UNLIKELY (!atoms_initialized)) - { - XInternAtoms (xdisplay, - (char **) clutter_input_axis_atom_names, N_AXIS_ATOMS, - False, - clutter_input_axis_atoms); - - atoms_initialized = TRUE; - } - - for (i = 0; - i < N_AXIS_ATOMS; - i += 1) - { - if (clutter_input_axis_atoms[i] == class->label) - { - axis = i + 1; - break; - } - } - - meta_input_device_x11_add_axis (device, axis, - class->min, - class->max, - class->resolution); - - g_debug ("Added axis '%s' (min:%.2f, max:%.2fd, res:%d) of device %d", - clutter_input_axis_atom_names[axis], - class->min, - class->max, - class->resolution, - meta_input_device_x11_get_device_id (device)); -} - -static void -translate_device_classes (Display *xdisplay, - ClutterInputDevice *device, - XIAnyClassInfo **classes, - int n_classes) -{ - int i; - - for (i = 0; i < n_classes; i++) - { - XIAnyClassInfo *class_info = classes[i]; - - switch (class_info->type) - { - case XIValuatorClass: - translate_valuator_class (xdisplay, device, - (XIValuatorClassInfo *) class_info); - break; - - case XIScrollClass: - { - XIScrollClassInfo *scroll_info = (XIScrollClassInfo *) class_info; - ClutterScrollDirection direction; - - if (scroll_info->scroll_type == XIScrollTypeVertical) - direction = CLUTTER_SCROLL_DOWN; - else - direction = CLUTTER_SCROLL_RIGHT; - - g_debug ("Scroll valuator %d: %s, increment: %f", - scroll_info->number, - scroll_info->scroll_type == XIScrollTypeVertical - ? "vertical" - : "horizontal", - scroll_info->increment); - - meta_input_device_x11_add_scroll_info (device, - scroll_info->number, - direction, - scroll_info->increment); - } - break; - - default: - break; - } - } -} - -static gboolean -is_touch_device (XIAnyClassInfo **classes, - int n_classes, - ClutterInputDeviceType *device_type, - uint32_t *n_touch_points) -{ - int i; - - for (i = 0; i < n_classes; i++) - { - XITouchClassInfo *class = (XITouchClassInfo *) classes[i]; - - if (class->type != XITouchClass) - continue; - - if (class->num_touches > 0) - { - if (class->mode == XIDirectTouch) - *device_type = CLUTTER_TOUCHSCREEN_DEVICE; - else if (class->mode == XIDependentTouch) - *device_type = CLUTTER_TOUCHPAD_DEVICE; - else - continue; - - *n_touch_points = class->num_touches; - - return TRUE; - } - } - - return FALSE; -} - -static gboolean -is_touchpad_device (XIDeviceInfo *info) -{ - gulong nitems, bytes_after; - uint32_t *data = NULL; - int rc, format; - Atom type; - Atom prop; - - prop = XInternAtom (meta_clutter_x11_get_default_display (), - "libinput Tapping Enabled", True); - if (prop == None) - return FALSE; - - meta_clutter_x11_trap_x_errors (); - rc = XIGetProperty (meta_clutter_x11_get_default_display (), - info->deviceid, - prop, - 0, 1, False, XA_INTEGER, &type, &format, &nitems, &bytes_after, - (guchar **) &data); - meta_clutter_x11_untrap_x_errors (); - - /* We don't care about the data */ - XFree (data); - - if (rc != Success || type != XA_INTEGER || format != 8 || nitems != 1) - return FALSE; - - return TRUE; -} - -static gboolean -get_device_ids (XIDeviceInfo *info, - char **vendor_id, - char **product_id) -{ - gulong nitems, bytes_after; - uint32_t *data = NULL; - int rc, format; - Atom type; - - meta_clutter_x11_trap_x_errors (); - rc = XIGetProperty (meta_clutter_x11_get_default_display (), - info->deviceid, - XInternAtom (meta_clutter_x11_get_default_display (), "Device Product ID", False), - 0, 2, False, XA_INTEGER, &type, &format, &nitems, &bytes_after, - (guchar **) &data); - meta_clutter_x11_untrap_x_errors (); - - if (rc != Success || type != XA_INTEGER || format != 32 || nitems != 2) - { - XFree (data); - return FALSE; - } - - if (vendor_id) - *vendor_id = g_strdup_printf ("%.4x", data[0]); - if (product_id) - *product_id = g_strdup_printf ("%.4x", data[1]); - - XFree (data); - - return TRUE; -} - -static char * -get_device_node_path (XIDeviceInfo *info) -{ - gulong nitems, bytes_after; - guchar *data; - int rc, format; - Atom prop, type; - char *node_path; - - prop = XInternAtom (meta_clutter_x11_get_default_display (), "Device Node", False); - if (prop == None) - return NULL; - - meta_clutter_x11_trap_x_errors (); - - rc = XIGetProperty (meta_clutter_x11_get_default_display (), - info->deviceid, prop, 0, 1024, False, - XA_STRING, &type, &format, &nitems, &bytes_after, - (guchar **) &data); - - if (meta_clutter_x11_untrap_x_errors ()) - return NULL; - - if (rc != Success || type != XA_STRING || format != 8) - { - XFree (data); - return FALSE; - } - - node_path = g_strdup ((char *) data); - XFree (data); - - return node_path; -} - -static void -get_pad_features (XIDeviceInfo *info, - uint32_t *n_rings, - uint32_t *n_strips) -{ - int i, rings = 0, strips = 0; - - for (i = PAD_AXIS_FIRST; i < info->num_classes; i++) - { - XIValuatorClassInfo *valuator = (XIValuatorClassInfo*) info->classes[i]; - int axis = valuator->number; - - if (valuator->type != XIValuatorClass) - continue; - if (valuator->max <= 1) - continue; - - /* Ring/strip axes are fixed in pad devices as handled by the - * wacom driver. Match those to detect pad features. - */ - if (axis == PAD_AXIS_STRIP1 || axis == PAD_AXIS_STRIP2) - strips++; - else if (axis == PAD_AXIS_RING1 || axis == PAD_AXIS_RING2) - rings++; - } - - *n_rings = rings; - *n_strips = strips; -} - -/* The Wacom driver exports the tool type as property. Use that over - guessing based on the device name */ -static gboolean -guess_source_from_wacom_type (XIDeviceInfo *info, - ClutterInputDeviceType *source_out) -{ - gulong nitems, bytes_after; - uint32_t *data = NULL; - int rc, format; - Atom type; - Atom prop; - Atom device_type; - Atom types[N_WACOM_TYPE_ATOMS]; - - prop = XInternAtom (meta_clutter_x11_get_default_display (), "Wacom Tool Type", True); - if (prop == None) - return FALSE; - - meta_clutter_x11_trap_x_errors (); - rc = XIGetProperty (meta_clutter_x11_get_default_display (), - info->deviceid, - prop, - 0, 1, False, XA_ATOM, &type, &format, &nitems, &bytes_after, - (guchar **) &data); - meta_clutter_x11_untrap_x_errors (); - - if (rc != Success || type != XA_ATOM || format != 32 || nitems != 1) - { - XFree (data); - return FALSE; - } - - device_type = *data; - XFree (data); - - if (device_type == 0) - return FALSE; - - rc = XInternAtoms (meta_clutter_x11_get_default_display (), - (char **)wacom_type_atoms, - N_WACOM_TYPE_ATOMS, - False, - types); - if (rc == 0) - return FALSE; - - if (device_type == types[WACOM_TYPE_STYLUS]) - { - *source_out = CLUTTER_PEN_DEVICE; - } - else if (device_type == types[WACOM_TYPE_CURSOR]) - { - *source_out = CLUTTER_CURSOR_DEVICE; - } - else if (device_type == types[WACOM_TYPE_ERASER]) - { - *source_out = CLUTTER_ERASER_DEVICE; - } - else if (device_type == types[WACOM_TYPE_PAD]) - { - *source_out = CLUTTER_PAD_DEVICE; - } - else if (device_type == types[WACOM_TYPE_TOUCH]) - { - uint32_t num_touches = 0; - - if (!is_touch_device (info->classes, info->num_classes, - source_out, &num_touches)) - *source_out = CLUTTER_TOUCHSCREEN_DEVICE; - } - else - { - return FALSE; - } - - return TRUE; -} - -static ClutterInputDevice * -create_device (MetaSeatX11 *seat_x11, - ClutterBackend *backend, - XIDeviceInfo *info) -{ - ClutterInputDeviceType source, touch_source; - ClutterInputDevice *retval; - ClutterInputMode mode; - uint32_t num_touches = 0, num_rings = 0, num_strips = 0; - char *vendor_id = NULL, *product_id = NULL, *node_path = NULL; - - if (info->use == XIMasterKeyboard || info->use == XISlaveKeyboard) - { - source = CLUTTER_KEYBOARD_DEVICE; - } - else if (is_touchpad_device (info)) - { - source = CLUTTER_TOUCHPAD_DEVICE; - } - else if (info->use == XISlavePointer && - is_touch_device (info->classes, info->num_classes, - &touch_source, - &num_touches)) - { - source = touch_source; - } - else if (!guess_source_from_wacom_type (info, &source)) - { - char *name; - - name = g_ascii_strdown (info->name, -1); - - if (strstr (name, "eraser") != NULL) - source = CLUTTER_ERASER_DEVICE; - else if (strstr (name, "cursor") != NULL) - source = CLUTTER_CURSOR_DEVICE; - else if (strstr (name, " pad") != NULL) - source = CLUTTER_PAD_DEVICE; - else if (strstr (name, "wacom") != NULL || strstr (name, "pen") != NULL) - source = CLUTTER_PEN_DEVICE; - else if (strstr (name, "touchpad") != NULL) - source = CLUTTER_TOUCHPAD_DEVICE; - else - source = CLUTTER_POINTER_DEVICE; - - g_free (name); - } - - switch (info->use) - { - case XIMasterKeyboard: - case XIMasterPointer: - mode = CLUTTER_INPUT_MODE_LOGICAL; - break; - - case XISlaveKeyboard: - case XISlavePointer: - mode = CLUTTER_INPUT_MODE_PHYSICAL; - break; - - case XIFloatingSlave: - default: - mode = CLUTTER_INPUT_MODE_FLOATING; - break; - } - - if (info->use != XIMasterKeyboard && - info->use != XIMasterPointer) - { - get_device_ids (info, &vendor_id, &product_id); - node_path = get_device_node_path (info); - } - - if (source == CLUTTER_PAD_DEVICE) - get_pad_features (info, &num_rings, &num_strips); - - retval = g_object_new (META_TYPE_INPUT_DEVICE_X11, - "name", info->name, - "id", info->deviceid, - "has-cursor", (info->use == XIMasterPointer), - "device-type", source, - "device-mode", mode, - "backend", backend, - "vendor-id", vendor_id, - "product-id", product_id, - "device-node", node_path, - "n-rings", num_rings, - "n-strips", num_strips, - "n-mode-groups", MAX (num_rings, num_strips), - "seat", seat_x11, - NULL); - - translate_device_classes (meta_clutter_x11_get_default_display (), retval, - info->classes, - info->num_classes); - - g_free (vendor_id); - g_free (product_id); - g_free (node_path); - - g_debug ("Created device '%s' (id: %d, has-cursor: %s)", - info->name, - info->deviceid, - info->use == XIMasterPointer ? "yes" : "no"); - - return retval; -} - -static void -pad_passive_button_grab (ClutterInputDevice *device) -{ - XIGrabModifiers xi_grab_mods = { XIAnyModifier, }; - XIEventMask xi_event_mask; - int device_id, rc; - - device_id = meta_input_device_x11_get_device_id (device); - - xi_event_mask.deviceid = device_id; - xi_event_mask.mask_len = XIMaskLen (XI_LASTEVENT); - xi_event_mask.mask = g_new0 (unsigned char, xi_event_mask.mask_len); - - XISetMask (xi_event_mask.mask, XI_Motion); - XISetMask (xi_event_mask.mask, XI_ButtonPress); - XISetMask (xi_event_mask.mask, XI_ButtonRelease); - - meta_clutter_x11_trap_x_errors (); - rc = XIGrabButton (meta_clutter_x11_get_default_display (), - device_id, XIAnyButton, - meta_clutter_x11_get_root_window (), None, - XIGrabModeSync, XIGrabModeSync, - True, &xi_event_mask, 1, &xi_grab_mods); - if (rc != 0) - { - g_warning ("Could not passively grab pad device: %s", - clutter_input_device_get_device_name (device)); - } - else - { - XIAllowEvents (meta_clutter_x11_get_default_display (), - device_id, XIAsyncDevice, - CLUTTER_CURRENT_TIME); - } - - meta_clutter_x11_untrap_x_errors (); - - g_free (xi_event_mask.mask); -} - -static void -update_touch_mode (MetaSeatX11 *seat_x11) -{ - gboolean touch_mode; - - touch_mode = seat_x11->has_touchscreens; - - if (seat_x11->touch_mode == touch_mode) - return; - - seat_x11->touch_mode = touch_mode; - g_object_notify (G_OBJECT (seat_x11), "touch-mode"); -} - -static ClutterInputDevice * -add_device (MetaSeatX11 *seat_x11, - ClutterBackend *backend, - XIDeviceInfo *info) -{ - ClutterInputDevice *device; - - device = create_device (seat_x11, backend, info); - - g_hash_table_replace (seat_x11->devices_by_id, - GINT_TO_POINTER (info->deviceid), - device); - - if (info->use == XIMasterPointer && - info->deviceid == seat_x11->pointer_id) - { - seat_x11->core_pointer = device; - } - else if (info->use == XIMasterKeyboard && - info->deviceid == seat_x11->keyboard_id) - { - seat_x11->core_keyboard = device; - } - else if ((info->use == XISlavePointer && - info->attachment == seat_x11->pointer_id) || - (info->use == XISlaveKeyboard && - info->attachment == seat_x11->keyboard_id)) - { - seat_x11->devices = g_list_prepend (seat_x11->devices, device); - } - else - { - g_warning ("Unhandled device: %s", - clutter_input_device_get_device_name (device)); - } - - if (clutter_input_device_get_device_type (device) == CLUTTER_PAD_DEVICE) - pad_passive_button_grab (device); - - return device; -} - -static gboolean -has_touchscreens (MetaSeatX11 *seat_x11) -{ - GList *l; - - for (l = seat_x11->devices; l; l = l->next) - { - if (clutter_input_device_get_device_type (l->data) == CLUTTER_TOUCHSCREEN_DEVICE) - return TRUE; - } - - return FALSE; -} - -static void -remove_device (MetaSeatX11 *seat_x11, - ClutterInputDevice *device) -{ - if (seat_x11->core_pointer == device) - { - seat_x11->core_pointer = NULL; - } - else if (seat_x11->core_keyboard == device) - { - seat_x11->core_keyboard = NULL; - } - else - { - seat_x11->devices = g_list_remove (seat_x11->devices, device); - } -} - -static gboolean -meta_seat_x11_handle_event_post (ClutterSeat *seat, - const ClutterEvent *event) -{ - MetaSeatX11 *seat_x11 = META_SEAT_X11 (seat); - ClutterInputDevice *device; - MetaInputSettings *input_settings; - gboolean is_touch; - - if (event->type != CLUTTER_DEVICE_ADDED && - event->type != CLUTTER_DEVICE_REMOVED) - return TRUE; - - device = clutter_event_get_device (event); - is_touch = - clutter_input_device_get_device_type (device) == CLUTTER_TOUCHSCREEN_DEVICE; - input_settings = meta_backend_get_input_settings (meta_get_backend ()); - - switch (event->type) - { - case CLUTTER_DEVICE_ADDED: - meta_input_settings_add_device (input_settings, device); - seat_x11->has_touchscreens |= is_touch; - break; - case CLUTTER_DEVICE_REMOVED: - if (is_touch) - seat_x11->has_touchscreens = has_touchscreens (seat_x11); - meta_input_settings_remove_device (input_settings, device); - break; - default: - break; - } - - if (is_touch) - update_touch_mode (seat_x11); - - return TRUE; -} - -static uint -device_get_tool_serial (ClutterInputDevice *device) -{ - gulong nitems, bytes_after; - uint32_t *data = NULL; - int serial_id = 0; - int rc, format; - Atom type; - Atom prop; - - prop = XInternAtom (meta_clutter_x11_get_default_display (), - "Wacom Serial IDs", True); - if (prop == None) - return 0; - - meta_clutter_x11_trap_x_errors (); - rc = XIGetProperty (meta_clutter_x11_get_default_display (), - meta_input_device_x11_get_device_id (device), - prop, 0, 4, FALSE, XA_INTEGER, &type, &format, &nitems, &bytes_after, - (guchar **) &data); - meta_clutter_x11_untrap_x_errors (); - - if (rc == Success && type == XA_INTEGER && format == 32 && nitems >= 4) - serial_id = data[3]; - - XFree (data); - - return serial_id; -} - -static gboolean -translate_hierarchy_event (ClutterBackend *backend, - MetaSeatX11 *seat_x11, - XIHierarchyEvent *ev, - ClutterEvent *event) -{ - int i; - gboolean retval = FALSE; - - for (i = 0; i < ev->num_info; i++) - { - if (ev->info[i].flags & XIDeviceEnabled && - !g_hash_table_lookup (seat_x11->devices_by_id, - GINT_TO_POINTER (ev->info[i].deviceid))) - { - XIDeviceInfo *info; - int n_devices; - - g_debug ("Hierarchy event: device enabled"); - - meta_clutter_x11_trap_x_errors (); - info = XIQueryDevice (meta_clutter_x11_get_default_display (), - ev->info[i].deviceid, - &n_devices); - meta_clutter_x11_untrap_x_errors (); - if (info != NULL) - { - ClutterInputDevice *device; - - device = add_device (seat_x11, backend, &info[0]); - - event->any.type = CLUTTER_DEVICE_ADDED; - event->any.time = ev->time; - clutter_event_set_device (event, device); - - retval = TRUE; - XIFreeDeviceInfo (info); - } - } - else if (ev->info[i].flags & XIDeviceDisabled) - { - g_autoptr (ClutterInputDevice) device = NULL; - g_debug ("Hierarchy event: device disabled"); - - g_hash_table_steal_extended (seat_x11->devices_by_id, - GINT_TO_POINTER (ev->info[i].deviceid), - NULL, - (gpointer) &device); - - if (device != NULL) - { - remove_device (seat_x11, device); - - event->any.type = CLUTTER_DEVICE_REMOVED; - event->any.time = ev->time; - clutter_event_set_device (event, device); - - retval = TRUE; - } - } - else if ((ev->info[i].flags & XISlaveAttached) || - (ev->info[i].flags & XISlaveDetached)) - { - g_debug ("Hierarchy event: physical device %s", - (ev->info[i].flags & XISlaveAttached) - ? "attached" - : "detached"); - } - } - - return retval; -} - -static void -translate_property_event (MetaSeatX11 *seat_x11, - XIEvent *event) -{ - XIPropertyEvent *xev = (XIPropertyEvent *) event; - Atom serial_ids_prop; - ClutterInputDevice *device; - - serial_ids_prop = XInternAtom (meta_clutter_x11_get_default_display (), - "Wacom Serial IDs", True); - if (serial_ids_prop == None) - return; - - device = g_hash_table_lookup (seat_x11->devices_by_id, - GINT_TO_POINTER (xev->deviceid)); - if (!device) - return; - - if (xev->property == serial_ids_prop) - { - ClutterInputDeviceTool *tool = NULL; - ClutterInputDeviceToolType type; - MetaInputSettings *input_settings; - int serial_id; - - serial_id = device_get_tool_serial (device); - - if (serial_id != 0) - { - tool = g_hash_table_lookup (seat_x11->tools_by_serial, - GUINT_TO_POINTER (serial_id)); - if (!tool) - { - type = clutter_input_device_get_device_type (device) == CLUTTER_ERASER_DEVICE ? - CLUTTER_INPUT_DEVICE_TOOL_ERASER : CLUTTER_INPUT_DEVICE_TOOL_PEN; - tool = meta_input_device_tool_x11_new (serial_id, type); - g_hash_table_insert (seat_x11->tools_by_serial, - GUINT_TO_POINTER (serial_id), - tool); - } - } - - meta_input_device_x11_update_tool (device, tool); - input_settings = meta_backend_get_input_settings (meta_get_backend ()); - meta_input_settings_notify_tool_change (input_settings, device, tool); - } -} - -static void -emulate_motion (MetaSeatX11 *seat_x11, - double x, - double y) -{ - ClutterInputDevice *pointer; - ClutterEvent *event; - ClutterStage *stage; - - pointer = clutter_seat_get_pointer (CLUTTER_SEAT (seat_x11)); - stage = CLUTTER_STAGE (meta_backend_get_stage (meta_get_backend ())); - - event = clutter_event_new (CLUTTER_MOTION); - clutter_event_set_flags (event, CLUTTER_EVENT_FLAG_SYNTHETIC); - clutter_event_set_coords (event, x, y); - clutter_event_set_device (event, pointer); - clutter_event_set_source_device (event, NULL); - clutter_event_set_stage (event, stage); - - clutter_event_put (event); - clutter_event_free (event); -} - -static void -translate_raw_event (MetaSeatX11 *seat_x11, - 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 (seat_x11->devices_by_id, - GINT_TO_POINTER (xev->deviceid)); - if (device == NULL) - return; - - switch (cookie->evtype) - { - case XI_RawMotion: - g_debug ("raw motion: device:%d '%s'", - meta_input_device_x11_get_device_id (device), - clutter_input_device_get_device_name (device)); - - /* 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 explicitly query the pointer here... - */ - if (meta_input_device_x11_get_pointer_location (device, &x, &y)) - { - if (_clutter_is_input_pointer_a11y_enabled (device)) - _clutter_input_pointer_a11y_on_motion_event (device, x, y); - if (!seat_x11->has_pointer_focus) - emulate_motion (seat_x11, x, y); - } - break; - case XI_RawButtonPress: - case XI_RawButtonRelease: - g_debug ("raw button %s: device:%d '%s' button %i", - cookie->evtype == XI_RawButtonPress - ? "press " - : "release", - meta_input_device_x11_get_device_id (device), - clutter_input_device_get_device_name (device), - xev->detail); - if (_clutter_is_input_pointer_a11y_enabled (device)) - { - _clutter_input_pointer_a11y_on_button_event (device, - xev->detail, - (cookie->evtype == XI_RawButtonPress)); - } - break; - } -} - -static gboolean -translate_pad_axis (ClutterInputDevice *device, - XIValuatorState *valuators, - ClutterEventType *evtype, - uint32_t *number, - double *value) -{ - double *values; - int i; - - values = valuators->values; - - for (i = PAD_AXIS_FIRST; i < valuators->mask_len * 8; i++) - { - double val; - uint32_t axis_number = 0; - - if (!XIMaskIsSet (valuators->mask, i)) - continue; - - val = *values++; - if (val <= 0) - continue; - - meta_input_device_x11_translate_axis (device, i, val, value); - - if (i == PAD_AXIS_RING1 || i == PAD_AXIS_RING2) - { - *evtype = CLUTTER_PAD_RING; - (*value) *= 360.0; - } - else if (i == PAD_AXIS_STRIP1 || i == PAD_AXIS_STRIP2) - { - *evtype = CLUTTER_PAD_STRIP; - } - else - continue; - - if (i == PAD_AXIS_STRIP2 || i == PAD_AXIS_RING2) - axis_number++; - - *number = axis_number; - return TRUE; - } - - return FALSE; -} - -static gboolean -translate_pad_event (ClutterEvent *event, - XIDeviceEvent *xev, - ClutterInputDevice *device) -{ - double value; - uint32_t number, mode = 0; - - if (!translate_pad_axis (device, &xev->valuators, - &event->any.type, - &number, &value)) - return FALSE; - - /* When touching a ring/strip a first XI_Motion event - * is generated. Use it to reset the pad state, so - * later events actually have a directionality. - */ - if (xev->evtype == XI_Motion) - value = -1; - -#ifdef HAVE_LIBWACOM - mode = meta_input_device_x11_get_pad_group_mode (device, number); -#endif - - if (event->any.type == CLUTTER_PAD_RING) - { - event->pad_ring.ring_number = number; - event->pad_ring.angle = value; - event->pad_ring.mode = mode; - } - else - { - event->pad_strip.strip_number = number; - event->pad_strip.value = value; - event->pad_strip.mode = mode; - } - - event->any.time = xev->time; - clutter_event_set_device (event, device); - clutter_event_set_source_device (event, device); - - g_debug ("%s: win:0x%x, device:%d '%s', time:%d " - "(value:%f)", - event->any.type == CLUTTER_PAD_RING - ? "pad ring " - : "pad strip", - (unsigned int) xev->event, - meta_input_device_x11_get_device_id (device), - clutter_input_device_get_device_name (device), - event->any.time, value); - - return TRUE; -} - -static ClutterStage * -get_event_stage (MetaSeatX11 *seat_x11, - XIEvent *xi_event) -{ - Window xwindow = None; - - switch (xi_event->evtype) - { - case XI_KeyPress: - case XI_KeyRelease: - case XI_ButtonPress: - case XI_ButtonRelease: - case XI_Motion: - case XI_TouchBegin: - case XI_TouchUpdate: - case XI_TouchEnd: - { - XIDeviceEvent *xev = (XIDeviceEvent *) xi_event; - - xwindow = xev->event; - } - break; - - case XI_Enter: - case XI_Leave: - case XI_FocusIn: - case XI_FocusOut: - { - XIEnterEvent *xev = (XIEnterEvent *) xi_event; - - xwindow = xev->event; - } - break; - - case XI_HierarchyChanged: - return CLUTTER_STAGE (meta_backend_get_stage (meta_get_backend ())); - - default: - break; - } - - if (xwindow == None) - return NULL; - - return meta_x11_get_stage_from_window (xwindow); -} - -/* - * print_key_sym: Translate a symbol to its printable form if any - * @symbol: the symbol to translate - * @buffer: the buffer where to put the translated string - * @len: size of the buffer - * - * Translates @symbol into a printable representation in @buffer, if possible. - * - * Return value: The number of bytes of the translated string, 0 if the - * symbol can't be printed - * - * Note: The code is derived from libX11's src/KeyBind.c - * Copyright 1985, 1987, 1998 The Open Group - * - * Note: This code works for Latin-1 symbols. clutter_keysym_to_unicode() - * does the work for the other keysyms. - */ -static int -print_keysym (uint32_t symbol, - char *buffer, - int len) -{ - unsigned long high_bytes; - unsigned char c; - - high_bytes = symbol >> 8; - if (!(len && - ((high_bytes == 0) || - ((high_bytes == 0xFF) && - (((symbol >= CLUTTER_KEY_BackSpace) && - (symbol <= CLUTTER_KEY_Clear)) || - (symbol == CLUTTER_KEY_Return) || - (symbol == CLUTTER_KEY_Escape) || - (symbol == CLUTTER_KEY_KP_Space) || - (symbol == CLUTTER_KEY_KP_Tab) || - (symbol == CLUTTER_KEY_KP_Enter) || - ((symbol >= CLUTTER_KEY_KP_Multiply) && - (symbol <= CLUTTER_KEY_KP_9)) || - (symbol == CLUTTER_KEY_KP_Equal) || - (symbol == CLUTTER_KEY_Delete)))))) - return 0; - - /* if X keysym, convert to ascii by grabbing low 7 bits */ - if (symbol == CLUTTER_KEY_KP_Space) - c = CLUTTER_KEY_space & 0x7F; /* patch encoding botch */ - else if (high_bytes == 0xFF) - c = symbol & 0x7F; - else - c = symbol & 0xFF; - - buffer[0] = c; - return 1; -} - -static double * -translate_axes (ClutterInputDevice *device, - double x, - double y, - XIValuatorState *valuators) -{ - uint32_t i; - double *retval; - double *values; - - retval = g_new0 (double, CLUTTER_INPUT_AXIS_LAST); - values = valuators->values; - - for (i = 0; i < valuators->mask_len * 8; i++) - { - ClutterInputAxis axis; - double val; - - if (!XIMaskIsSet (valuators->mask, i)) - continue; - if (!meta_input_device_x11_get_axis (device, i, &axis)) - continue; - - val = *values++; - - switch (axis) - { - case CLUTTER_INPUT_AXIS_X: - retval[axis] = x; - break; - - case CLUTTER_INPUT_AXIS_Y: - retval[axis] = y; - break; - - default: - meta_input_device_x11_translate_axis (device, i, val, &retval[axis]); - break; - } - } - - return retval; -} - -static double -scroll_valuators_changed (ClutterInputDevice *device, - XIValuatorState *valuators, - double *dx_p, - double *dy_p) -{ - gboolean retval = FALSE; - uint32_t n_axes, n_val, i; - double *values; - - n_axes = meta_input_device_x11_get_n_axes (device); - values = valuators->values; - - *dx_p = *dy_p = 0.0; - - n_val = 0; - - for (i = 0; i < MIN (valuators->mask_len * 8, n_axes); i++) - { - ClutterScrollDirection direction; - double delta; - - if (!XIMaskIsSet (valuators->mask, i)) - continue; - - if (meta_input_device_x11_get_scroll_delta (device, i, - values[n_val], - &direction, - &delta)) - { - retval = TRUE; - - if (direction == CLUTTER_SCROLL_UP || - direction == CLUTTER_SCROLL_DOWN) - *dy_p = delta; - else - *dx_p = delta; - } - - n_val += 1; - } - - return retval; -} - -static void -translate_coords (MetaStageX11 *stage_x11, - double event_x, - double event_y, - float *x_out, - float *y_out) -{ - MetaStageImpl *stage_impl = META_STAGE_IMPL (stage_x11); - ClutterActor *stage = CLUTTER_ACTOR (stage_impl->wrapper); - float stage_width; - float stage_height; - - clutter_actor_get_size (stage, &stage_width, &stage_height); - - *x_out = CLAMP (event_x, 0, stage_width); - *y_out = CLAMP (event_y, 0, stage_height); -} - -static void -on_keymap_state_change (MetaKeymapX11 *keymap_x11, - gpointer data) -{ - ClutterSeat *seat = data; - MetaInputSettings *input_settings; - MetaKbdA11ySettings kbd_a11y_settings; - - /* On keymaps state change, just reapply the current settings, it'll - * take care of enabling/disabling mousekeys based on NumLock state. - */ - input_settings = meta_backend_get_input_settings (meta_get_backend ()); - meta_input_settings_get_kbd_a11y_settings (input_settings, &kbd_a11y_settings); - meta_seat_x11_apply_kbd_a11y_settings (seat, &kbd_a11y_settings); -} - -static void -meta_seat_x11_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaSeatX11 *seat_x11 = META_SEAT_X11 (object); - - switch (prop_id) - { - case PROP_OPCODE: - seat_x11->opcode = g_value_get_int (value); - break; - case PROP_POINTER_ID: - seat_x11->pointer_id = g_value_get_int (value); - break; - case PROP_KEYBOARD_ID: - seat_x11->keyboard_id = g_value_get_int (value); - break; - case PROP_TOUCH_MODE: - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_seat_x11_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaSeatX11 *seat_x11 = META_SEAT_X11 (object); - - switch (prop_id) - { - case PROP_OPCODE: - g_value_set_int (value, seat_x11->opcode); - break; - case PROP_POINTER_ID: - g_value_set_int (value, seat_x11->pointer_id); - break; - case PROP_KEYBOARD_ID: - g_value_set_int (value, seat_x11->keyboard_id); - break; - case PROP_TOUCH_MODE: - g_value_set_boolean (value, seat_x11->touch_mode); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -void -meta_seat_x11_notify_devices (MetaSeatX11 *seat_x11, - ClutterStage *stage) -{ - GHashTableIter iter; - ClutterInputDevice *device; - - g_hash_table_iter_init (&iter, seat_x11->devices_by_id); - while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &device)) - { - ClutterEvent *event; - - event = clutter_event_new (CLUTTER_DEVICE_ADDED); - clutter_event_set_device (event, device); - clutter_event_set_stage (event, stage); - clutter_event_put (event); - clutter_event_free (event); - } -} - -static void -meta_seat_x11_constructed (GObject *object) -{ - MetaSeatX11 *seat_x11 = META_SEAT_X11 (object); - ClutterBackend *backend = clutter_get_default_backend (); - XIDeviceInfo *info; - XIEventMask event_mask; - unsigned char mask[XIMaskLen(XI_LASTEVENT)] = { 0, }; - int n_devices, i; - Display *xdisplay; - - xdisplay = meta_clutter_x11_get_default_display (); - - info = XIQueryDevice (xdisplay, XIAllDevices, &n_devices); - - for (i = 0; i < n_devices; i++) - { - XIDeviceInfo *xi_device = &info[i]; - - if (!xi_device->enabled) - continue; - - add_device (seat_x11, backend, xi_device); - } - - XIFreeDeviceInfo (info); - - XISetMask (mask, XI_HierarchyChanged); - XISetMask (mask, XI_DeviceChanged); - XISetMask (mask, XI_PropertyEvent); - - event_mask.deviceid = XIAllDevices; - event_mask.mask_len = sizeof (mask); - event_mask.mask = mask; - - XISelectEvents (xdisplay, meta_clutter_x11_get_root_window (), - &event_mask, 1); - - 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; - - XISelectEvents (xdisplay, meta_clutter_x11_get_root_window (), - &event_mask, 1); - - XSync (xdisplay, False); - - seat_x11->keymap = g_object_new (META_TYPE_KEYMAP_X11, - "backend", backend, - NULL); - g_signal_connect (seat_x11->keymap, - "state-changed", - G_CALLBACK (on_keymap_state_change), - seat_x11); - - meta_seat_x11_a11y_init (CLUTTER_SEAT (seat_x11)); - - if (G_OBJECT_CLASS (meta_seat_x11_parent_class)->constructed) - G_OBJECT_CLASS (meta_seat_x11_parent_class)->constructed (object); -} - -static void -meta_seat_x11_finalize (GObject *object) -{ - MetaSeatX11 *seat_x11 = META_SEAT_X11 (object); - - g_hash_table_unref (seat_x11->devices_by_id); - g_hash_table_unref (seat_x11->tools_by_serial); - g_hash_table_unref (seat_x11->touch_coords); - g_list_free (seat_x11->devices); - - G_OBJECT_CLASS (meta_seat_x11_parent_class)->finalize (object); -} - -static ClutterInputDevice * -meta_seat_x11_get_pointer (ClutterSeat *seat) -{ - MetaSeatX11 *seat_x11 = META_SEAT_X11 (seat); - - return seat_x11->core_pointer; -} - -static ClutterInputDevice * -meta_seat_x11_get_keyboard (ClutterSeat *seat) -{ - MetaSeatX11 *seat_x11 = META_SEAT_X11 (seat); - - return seat_x11->core_keyboard; -} - -static const GList * -meta_seat_x11_peek_devices (ClutterSeat *seat) -{ - MetaSeatX11 *seat_x11 = META_SEAT_X11 (seat); - - return (const GList *) seat_x11->devices; -} - -static void -meta_seat_x11_bell_notify (ClutterSeat *seat) -{ - MetaDisplay *display = meta_get_display (); - - meta_bell_notify (display, NULL); -} - -static ClutterKeymap * -meta_seat_x11_get_keymap (ClutterSeat *seat) -{ - return CLUTTER_KEYMAP (META_SEAT_X11 (seat)->keymap); -} - -static ClutterVirtualInputDevice * -meta_seat_x11_create_virtual_device (ClutterSeat *seat, - ClutterInputDeviceType device_type) -{ - return g_object_new (META_TYPE_VIRTUAL_INPUT_DEVICE_X11, - "seat", seat, - "device-type", device_type, - NULL); -} - -static ClutterVirtualDeviceType -meta_seat_x11_get_supported_virtual_device_types (ClutterSeat *seat) -{ - return (CLUTTER_VIRTUAL_DEVICE_TYPE_KEYBOARD | - CLUTTER_VIRTUAL_DEVICE_TYPE_POINTER); -} - -static void -meta_seat_x11_warp_pointer (ClutterSeat *seat, - int x, - int y) -{ - MetaSeatX11 *seat_x11 = META_SEAT_X11 (seat); - - meta_clutter_x11_trap_x_errors (); - XIWarpPointer (meta_clutter_x11_get_default_display (), - seat_x11->pointer_id, - None, - meta_clutter_x11_get_root_window (), - 0, 0, 0, 0, - x, y); - meta_clutter_x11_untrap_x_errors (); -} - -static uint32_t -translate_state (XIButtonState *button_state, - XIModifierState *modifier_state, - XIGroupState *group_state) -{ - uint32_t state = 0; - int i; - - if (modifier_state) - state |= modifier_state->effective; - - if (button_state) - { - for (i = 1; i < button_state->mask_len * 8; i++) - { - if (!XIMaskIsSet (button_state->mask, i)) - continue; - - switch (i) - { - case 1: - state |= CLUTTER_BUTTON1_MASK; - break; - case 2: - state |= CLUTTER_BUTTON2_MASK; - break; - case 3: - state |= CLUTTER_BUTTON3_MASK; - break; - case 8: - state |= CLUTTER_BUTTON4_MASK; - break; - case 9: - state |= CLUTTER_BUTTON5_MASK; - break; - default: - break; - } - } - } - - if (group_state) - state |= XkbBuildCoreState (0, group_state->effective); - - return state; -} - -static gboolean -meta_seat_x11_query_state (ClutterSeat *seat, - ClutterInputDevice *device, - ClutterEventSequence *sequence, - graphene_point_t *coords, - ClutterModifierType *modifiers) -{ - MetaBackendX11 *backend_x11 = META_BACKEND_X11 (meta_get_backend ()); - MetaSeatX11 *seat_x11 = META_SEAT_X11 (seat); - Window root_ret, child_ret; - double root_x, root_y, win_x, win_y; - XIButtonState button_state = { 0 }; - XIModifierState modifier_state; - XIGroupState group_state; - - meta_clutter_x11_trap_x_errors (); - XIQueryPointer (meta_clutter_x11_get_default_display (), - seat_x11->pointer_id, - meta_backend_x11_get_xwindow (backend_x11), - &root_ret, &child_ret, - &root_x, &root_y, &win_x, &win_y, - &button_state, &modifier_state, &group_state); - if (meta_clutter_x11_untrap_x_errors ()) - { - g_free (button_state.mask); - return FALSE; - } - - if (sequence) - { - MetaTouchInfo *touch_info; - - touch_info = g_hash_table_lookup (seat_x11->touch_coords, sequence); - if (!touch_info) - { - g_free (button_state.mask); - return FALSE; - } - - if (coords) - { - coords->x = touch_info->x; - coords->y = touch_info->y; - } - } - else - { - if (coords) - { - coords->x = win_x; - coords->y = win_y; - } - } - - if (modifiers) - *modifiers = translate_state (&button_state, &modifier_state, &group_state); - - g_free (button_state.mask); - return TRUE; -} - -static void -meta_seat_x11_update_touchpoint (MetaSeatX11 *seat, - ClutterEventSequence *sequence, - double x, - double y) -{ - MetaTouchInfo *touch_info; - - touch_info = g_hash_table_lookup (seat->touch_coords, sequence); - if (!touch_info) - { - touch_info = g_new0 (MetaTouchInfo, 1); - touch_info->sequence = sequence; - g_hash_table_insert (seat->touch_coords, sequence, touch_info); - } - - touch_info->x = x; - touch_info->y = y; -} - -static void -meta_seat_x11_remove_touchpoint (MetaSeatX11 *seat, - ClutterEventSequence *sequence) -{ - g_hash_table_remove (seat->touch_coords, sequence); -} - -static void -meta_touch_info_free (MetaTouchInfo *touch_info) -{ - g_free (touch_info); -} - -static void -meta_seat_x11_class_init (MetaSeatX11Class *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - ClutterSeatClass *seat_class = CLUTTER_SEAT_CLASS (klass); - - object_class->set_property = meta_seat_x11_set_property; - object_class->get_property = meta_seat_x11_get_property; - object_class->constructed = meta_seat_x11_constructed; - object_class->finalize = meta_seat_x11_finalize; - - seat_class->get_pointer = meta_seat_x11_get_pointer; - seat_class->get_keyboard = meta_seat_x11_get_keyboard; - seat_class->peek_devices = meta_seat_x11_peek_devices; - seat_class->bell_notify = meta_seat_x11_bell_notify; - seat_class->get_keymap = meta_seat_x11_get_keymap; - seat_class->create_virtual_device = meta_seat_x11_create_virtual_device; - seat_class->get_supported_virtual_device_types = meta_seat_x11_get_supported_virtual_device_types; - seat_class->warp_pointer = meta_seat_x11_warp_pointer; - seat_class->handle_event_post = meta_seat_x11_handle_event_post; - seat_class->query_state = meta_seat_x11_query_state; - - props[PROP_OPCODE] = - g_param_spec_int ("opcode", - "Opcode", - "Opcode", - 0, G_MAXINT, 0, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - props[PROP_POINTER_ID] = - g_param_spec_int ("pointer-id", - "Pointer ID", - "Pointer ID", - 2, G_MAXINT, 2, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - props[PROP_KEYBOARD_ID] = - g_param_spec_int ("keyboard-id", - "Keyboard ID", - "Keyboard ID", - 2, G_MAXINT, 2, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - - g_object_class_install_properties (object_class, N_PROPS, props); - - g_object_class_override_property (object_class, PROP_TOUCH_MODE, - "touch-mode"); -} - -static void -meta_seat_x11_init (MetaSeatX11 *seat) -{ - seat->devices_by_id = g_hash_table_new_full (NULL, NULL, - NULL, - (GDestroyNotify) g_object_unref); - seat->tools_by_serial = g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) g_object_unref); - seat->touch_coords = g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) meta_touch_info_free); -} - -MetaSeatX11 * -meta_seat_x11_new (int opcode, - int logical_pointer, - int logical_keyboard) -{ - return g_object_new (META_TYPE_SEAT_X11, - "opcode", opcode, - "pointer-id", logical_pointer, - "keyboard-id", logical_keyboard, - NULL); -} - -static ClutterInputDevice * -get_source_device_checked (MetaSeatX11 *seat, - XIDeviceEvent *xev) -{ - ClutterInputDevice *source_device; - - source_device = g_hash_table_lookup (seat->devices_by_id, - GINT_TO_POINTER (xev->sourceid)); - - if (!source_device) - g_warning ("Impossible to get the source device with id %d for event of " - "type %d", xev->sourceid, xev->evtype); - - return source_device; -} - -static uint32_t -evdev_button_code (uint32_t x_button) -{ - uint32_t button; - - switch (x_button) - { - case 1: - button = BTN_LEFT; - break; - - /* The evdev input right and middle button numbers are swapped - relative to how Clutter numbers them */ - case 2: - button = BTN_MIDDLE; - break; - - case 3: - button = BTN_RIGHT; - break; - - default: - button = x_button + (BTN_LEFT - 1) + 4; - break; - } - - return button; -} - -gboolean -meta_seat_x11_translate_event (MetaSeatX11 *seat, - XEvent *xevent, - ClutterEvent *event) -{ - gboolean retval = FALSE; - ClutterBackend *backend = clutter_get_default_backend (); - ClutterStage *stage = NULL; - MetaStageX11 *stage_x11 = NULL; - ClutterInputDevice *device, *source_device; - XGenericEventCookie *cookie; - XIEvent *xi_event; - - if (meta_keymap_x11_handle_event (seat->keymap, xevent)) - return FALSE; - - cookie = &xevent->xcookie; - - if (cookie->type != GenericEvent || - cookie->extension != seat->opcode) - return FALSE; - - xi_event = (XIEvent *) cookie->data; - - if (!xi_event) - return FALSE; - - if (cookie->evtype == XI_RawMotion || - cookie->evtype == XI_RawButtonPress || - cookie->evtype == XI_RawButtonRelease) - { - translate_raw_event (seat, xevent); - return FALSE; - } - - if (!(xi_event->evtype == XI_DeviceChanged || - xi_event->evtype == XI_PropertyEvent)) - { - stage = get_event_stage (seat, xi_event); - if (stage == NULL || CLUTTER_ACTOR_IN_DESTRUCTION (stage)) - return FALSE; - else - stage_x11 = META_STAGE_X11 (_clutter_stage_get_window (stage)); - } - - event->any.stage = stage; - - switch (xi_event->evtype) - { - case XI_HierarchyChanged: - { - XIHierarchyEvent *xev = (XIHierarchyEvent *) xi_event; - - retval = translate_hierarchy_event (backend, seat, xev, event); - } - break; - - case XI_DeviceChanged: - { - XIDeviceChangedEvent *xev = (XIDeviceChangedEvent *) xi_event; - - device = g_hash_table_lookup (seat->devices_by_id, - GINT_TO_POINTER (xev->deviceid)); - source_device = g_hash_table_lookup (seat->devices_by_id, - GINT_TO_POINTER (xev->sourceid)); - if (device) - { - meta_input_device_x11_reset_axes (device); - translate_device_classes (meta_clutter_x11_get_default_display (), - device, - xev->classes, - xev->num_classes); - } - - if (source_device) - meta_input_device_x11_reset_scroll_info (source_device); - } - retval = FALSE; - break; - case XI_KeyPress: - case XI_KeyRelease: - { - XIDeviceEvent *xev = (XIDeviceEvent *) xi_event; - MetaKeymapX11 *keymap_x11 = seat->keymap; - char buffer[7] = { 0, }; - gunichar n; - - source_device = get_source_device_checked (seat, xev); - if (!source_device) - return FALSE; - - event->key.type = event->type = (xev->evtype == XI_KeyPress) - ? CLUTTER_KEY_PRESS - : CLUTTER_KEY_RELEASE; - - if (xev->evtype == XI_KeyPress && xev->flags & XIKeyRepeat) - clutter_event_set_flags (event, CLUTTER_EVENT_FLAG_REPEATED); - - event->key.time = xev->time; - event->key.stage = stage; - meta_input_device_x11_translate_state (event, &xev->mods, &xev->buttons, &xev->group); - event->key.hardware_keycode = xev->detail; - - /* clutter-xkb-utils.c adds a fixed offset of 8 to go into XKB's - * range, so we do the reverse here. */ - event->key.evdev_code = event->key.hardware_keycode - 8; - - /* keyval is the key ignoring all modifiers ('1' vs. '!') */ - event->key.keyval = - meta_keymap_x11_translate_key_state (keymap_x11, - event->key.hardware_keycode, - &event->key.modifier_state, - NULL); - - clutter_event_set_source_device (event, source_device); - - device = g_hash_table_lookup (seat->devices_by_id, - GINT_TO_POINTER (xev->deviceid)); - clutter_event_set_device (event, device); - - /* XXX keep this in sync with the evdev device manager */ - n = print_keysym (event->key.keyval, buffer, sizeof (buffer)); - if (n == 0) - { - /* not printable */ - event->key.unicode_value = (gunichar) '\0'; - } - else - { - event->key.unicode_value = g_utf8_get_char_validated (buffer, n); - if (event->key.unicode_value == -1 || - event->key.unicode_value == -2) - event->key.unicode_value = (gunichar) '\0'; - } - - g_debug ("%s: win:0x%x device:%d source:%d, key: %12s (%d)", - event->any.type == CLUTTER_KEY_PRESS - ? "key press " - : "key release", - (unsigned int) stage_x11->xwin, - xev->deviceid, - xev->sourceid, - event->key.keyval ? buffer : "(none)", - event->key.keyval); - - if (xi_event->evtype == XI_KeyPress) - meta_stage_x11_set_user_time (stage_x11, event->key.time); - - retval = TRUE; - } - break; - - case XI_ButtonPress: - case XI_ButtonRelease: - { - XIDeviceEvent *xev = (XIDeviceEvent *) xi_event; - - source_device = get_source_device_checked (seat, xev); - if (!source_device) - return FALSE; - - device = g_hash_table_lookup (seat->devices_by_id, - GINT_TO_POINTER (xev->deviceid)); - - if (clutter_input_device_get_device_type (source_device) == CLUTTER_PAD_DEVICE) - { - /* We got these events because of the passive button grab */ - XIAllowEvents (meta_clutter_x11_get_default_display (), - xev->sourceid, - XIAsyncDevice, - xev->time); - - event->any.stage = stage; - - if (xev->detail >= 4 && xev->detail <= 7) - { - retval = FALSE; - - if (xi_event->evtype == XI_ButtonPress && - translate_pad_event (event, xev, source_device)) - retval = TRUE; - - break; - } - - event->any.type = - (xi_event->evtype == XI_ButtonPress) ? CLUTTER_PAD_BUTTON_PRESS - : CLUTTER_PAD_BUTTON_RELEASE; - event->any.time = xev->time; - - /* The 4-7 button range is taken as non-existent on pad devices, - * let the buttons above that take over this range. - */ - if (xev->detail > 7) - xev->detail -= 4; - - /* Pad buttons are 0-indexed */ - event->pad_button.button = xev->detail - 1; -#ifdef HAVE_LIBWACOM - meta_input_device_x11_update_pad_state (device, - event->pad_button.button, - (xi_event->evtype == XI_ButtonPress), - &event->pad_button.group, - &event->pad_button.mode); -#endif - clutter_event_set_device (event, device); - clutter_event_set_source_device (event, source_device); - - g_debug ("%s: win:0x%x, device:%d '%s', time:%d " - "(button:%d)", - event->any.type == CLUTTER_BUTTON_PRESS - ? "pad button press " - : "pad button release", - (unsigned int) stage_x11->xwin, - meta_input_device_x11_get_device_id (device), - clutter_input_device_get_device_name (device), - event->any.time, - event->pad_button.button); - retval = TRUE; - break; - } - - switch (xev->detail) - { - case 4: - case 5: - case 6: - case 7: - /* we only generate Scroll events on ButtonPress */ - if (xi_event->evtype == XI_ButtonRelease) - return FALSE; - - event->scroll.type = event->type = CLUTTER_SCROLL; - - if (xev->detail == 4) - event->scroll.direction = CLUTTER_SCROLL_UP; - else if (xev->detail == 5) - event->scroll.direction = CLUTTER_SCROLL_DOWN; - else if (xev->detail == 6) - event->scroll.direction = CLUTTER_SCROLL_LEFT; - else - event->scroll.direction = CLUTTER_SCROLL_RIGHT; - - event->scroll.stage = stage; - - event->scroll.time = xev->time; - translate_coords (stage_x11, xev->event_x, xev->event_y, &event->scroll.x, &event->scroll.y); - meta_input_device_x11_translate_state (event, - &xev->mods, - &xev->buttons, - &xev->group); - - clutter_event_set_source_device (event, source_device); - clutter_event_set_device (event, device); - - event->scroll.axes = translate_axes (event->scroll.device, - event->scroll.x, - event->scroll.y, - &xev->valuators); - g_debug ("scroll: win:0x%x, device:%d '%s', time:%d " - "(direction:%s, " - "x:%.2f, y:%.2f, " - "emulated:%s)", - (unsigned int) stage_x11->xwin, - meta_input_device_x11_get_device_id (device), - clutter_input_device_get_device_name (device), - event->any.time, - event->scroll.direction == CLUTTER_SCROLL_UP ? "up" : - event->scroll.direction == CLUTTER_SCROLL_DOWN ? "down" : - event->scroll.direction == CLUTTER_SCROLL_LEFT ? "left" : - event->scroll.direction == CLUTTER_SCROLL_RIGHT ? "right" : - "invalid", - event->scroll.x, - event->scroll.y, - (xev->flags & XIPointerEmulated) ? "yes" : "no"); - break; - - default: - event->button.type = event->type = - (xi_event->evtype == XI_ButtonPress) ? CLUTTER_BUTTON_PRESS - : CLUTTER_BUTTON_RELEASE; - - event->button.stage = stage; - - event->button.time = xev->time; - translate_coords (stage_x11, xev->event_x, xev->event_y, &event->button.x, &event->button.y); - event->button.button = xev->detail; - event->button.evdev_code = evdev_button_code (xev->detail); - meta_input_device_x11_translate_state (event, - &xev->mods, - &xev->buttons, - &xev->group); - - clutter_event_set_source_device (event, source_device); - clutter_event_set_device (event, device); - clutter_event_set_device_tool (event, - meta_input_device_x11_get_current_tool (source_device)); - - event->button.axes = translate_axes (event->button.device, - event->button.x, - event->button.y, - &xev->valuators); - g_debug ("%s: win:0x%x, device:%d '%s', time:%d " - "(button:%d, " - "x:%.2f, y:%.2f, " - "axes:%s, " - "emulated:%s)", - event->any.type == CLUTTER_BUTTON_PRESS - ? "button press " - : "button release", - (unsigned int) stage_x11->xwin, - meta_input_device_x11_get_device_id (device), - clutter_input_device_get_device_name (device), - event->any.time, - event->button.button, - event->button.x, - event->button.y, - event->button.axes != NULL ? "yes" : "no", - (xev->flags & XIPointerEmulated) ? "yes" : "no"); - break; - } - - if (xev->flags & XIPointerEmulated) - _clutter_event_set_pointer_emulated (event, TRUE); - - if (xi_event->evtype == XI_ButtonPress) - meta_stage_x11_set_user_time (stage_x11, event->button.time); - - retval = TRUE; - } - break; - - case XI_Motion: - { - XIDeviceEvent *xev = (XIDeviceEvent *) xi_event; - double delta_x, delta_y; - - source_device = get_source_device_checked (seat, xev); - if (!source_device) - return FALSE; - - device = g_hash_table_lookup (seat->devices_by_id, - GINT_TO_POINTER (xev->deviceid)); - - if (clutter_input_device_get_device_type (source_device) == CLUTTER_PAD_DEVICE) - { - event->any.stage = stage; - - if (translate_pad_event (event, xev, source_device)) - retval = TRUE; - break; - } - - if (scroll_valuators_changed (source_device, - &xev->valuators, - &delta_x, &delta_y)) - { - event->scroll.type = event->type = CLUTTER_SCROLL; - event->scroll.direction = CLUTTER_SCROLL_SMOOTH; - - event->scroll.stage = stage; - event->scroll.time = xev->time; - translate_coords (stage_x11, xev->event_x, xev->event_y, &event->scroll.x, &event->scroll.y); - meta_input_device_x11_translate_state (event, - &xev->mods, - &xev->buttons, - &xev->group); - - clutter_event_set_scroll_delta (event, delta_x, delta_y); - clutter_event_set_source_device (event, source_device); - clutter_event_set_device (event, device); - - g_debug ("smooth scroll: win:0x%x device:%d '%s' (x:%.2f, y:%.2f, delta:%f, %f)", - (unsigned int) stage_x11->xwin, - meta_input_device_x11_get_device_id (event->scroll.device), - clutter_input_device_get_device_name (event->scroll.device), - event->scroll.x, - event->scroll.y, - delta_x, delta_y); - - retval = TRUE; - break; - } - - event->motion.type = event->type = CLUTTER_MOTION; - - event->motion.stage = stage; - - event->motion.time = xev->time; - translate_coords (stage_x11, xev->event_x, xev->event_y, &event->motion.x, &event->motion.y); - meta_input_device_x11_translate_state (event, - &xev->mods, - &xev->buttons, - &xev->group); - - clutter_event_set_source_device (event, source_device); - clutter_event_set_device (event, device); - clutter_event_set_device_tool (event, - meta_input_device_x11_get_current_tool (source_device)); - - event->motion.axes = translate_axes (event->motion.device, - event->motion.x, - event->motion.y, - &xev->valuators); - - if (xev->flags & XIPointerEmulated) - _clutter_event_set_pointer_emulated (event, TRUE); - - g_debug ("motion: win:0x%x device:%d '%s' (x:%.2f, y:%.2f, axes:%s)", - (unsigned int) stage_x11->xwin, - meta_input_device_x11_get_device_id (event->motion.device), - clutter_input_device_get_device_name (event->motion.device), - event->motion.x, - event->motion.y, - event->motion.axes != NULL ? "yes" : "no"); - - retval = TRUE; - } - break; - - case XI_TouchBegin: - { - XIDeviceEvent *xev = (XIDeviceEvent *) xi_event; - device = g_hash_table_lookup (seat->devices_by_id, - GINT_TO_POINTER (xev->deviceid)); - } - /* Fall through */ - case XI_TouchEnd: - { - XIDeviceEvent *xev = (XIDeviceEvent *) xi_event; - - source_device = g_hash_table_lookup (seat->devices_by_id, - GINT_TO_POINTER (xev->sourceid)); - - if (xi_event->evtype == XI_TouchBegin) - event->touch.type = event->type = CLUTTER_TOUCH_BEGIN; - else - event->touch.type = event->type = CLUTTER_TOUCH_END; - - event->touch.stage = stage; - event->touch.time = xev->time; - translate_coords (stage_x11, xev->event_x, xev->event_y, &event->touch.x, &event->touch.y); - meta_input_device_x11_translate_state (event, - &xev->mods, - &xev->buttons, - &xev->group); - - clutter_event_set_source_device (event, source_device); - - device = g_hash_table_lookup (seat->devices_by_id, - GINT_TO_POINTER (xev->deviceid)); - clutter_event_set_device (event, device); - - event->touch.axes = translate_axes (event->touch.device, - event->motion.x, - event->motion.y, - &xev->valuators); - - if (xi_event->evtype == XI_TouchBegin) - { - event->touch.modifier_state |= CLUTTER_BUTTON1_MASK; - - meta_stage_x11_set_user_time (stage_x11, event->touch.time); - meta_seat_x11_update_touchpoint (seat, - GUINT_TO_POINTER (xev->detail), - xev->root_x, - xev->root_y); - } - else if (xi_event->evtype == XI_TouchEnd) - { - meta_seat_x11_remove_touchpoint (seat, - GUINT_TO_POINTER (xev->detail)); - } - - /* "NULL" sequences are special cased in clutter */ - event->touch.sequence = GINT_TO_POINTER (MAX (1, xev->detail + 1)); - - if (xev->flags & XITouchEmulatingPointer) - _clutter_event_set_pointer_emulated (event, TRUE); - - g_debug ("touch %s: win:0x%x device:%d '%s' (seq:%d, x:%.2f, y:%.2f, axes:%s)", - event->type == CLUTTER_TOUCH_BEGIN ? "begin" : "end", - (unsigned int) stage_x11->xwin, - meta_input_device_x11_get_device_id (event->touch.device), - clutter_input_device_get_device_name (event->touch.device), - GPOINTER_TO_UINT (event->touch.sequence), - event->touch.x, - event->touch.y, - event->touch.axes != NULL ? "yes" : "no"); - - retval = TRUE; - } - break; - - case XI_TouchUpdate: - { - XIDeviceEvent *xev = (XIDeviceEvent *) xi_event; - - source_device = g_hash_table_lookup (seat->devices_by_id, - GINT_TO_POINTER (xev->sourceid)); - - event->touch.type = event->type = CLUTTER_TOUCH_UPDATE; - event->touch.stage = stage; - event->touch.time = xev->time; - /* "NULL" sequences are special cased in clutter */ - event->touch.sequence = GINT_TO_POINTER (MAX (1, xev->detail + 1)); - translate_coords (stage_x11, xev->event_x, xev->event_y, &event->touch.x, &event->touch.y); - - clutter_event_set_source_device (event, source_device); - - device = g_hash_table_lookup (seat->devices_by_id, - GINT_TO_POINTER (xev->deviceid)); - clutter_event_set_device (event, device); - - event->touch.axes = translate_axes (event->touch.device, - event->motion.x, - event->motion.y, - &xev->valuators); - - meta_input_device_x11_translate_state (event, - &xev->mods, - &xev->buttons, - &xev->group); - event->touch.modifier_state |= CLUTTER_BUTTON1_MASK; - - if (xev->flags & XITouchEmulatingPointer) - _clutter_event_set_pointer_emulated (event, TRUE); - - meta_seat_x11_update_touchpoint (seat, - event->touch.sequence, - xev->root_x, - xev->root_y); - - g_debug ("touch update: win:0x%x device:%d '%s' (seq:%d, x:%.2f, y:%.2f, axes:%s)", - (unsigned int) stage_x11->xwin, - meta_input_device_x11_get_device_id (event->touch.device), - clutter_input_device_get_device_name (event->touch.device), - GPOINTER_TO_UINT (event->touch.sequence), - event->touch.x, - event->touch.y, - event->touch.axes != NULL ? "yes" : "no"); - - retval = TRUE; - } - break; - - case XI_Enter: - case XI_Leave: - { - XIEnterEvent *xev = (XIEnterEvent *) xi_event; - - device = g_hash_table_lookup (seat->devices_by_id, - GINT_TO_POINTER (xev->deviceid)); - - source_device = g_hash_table_lookup (seat->devices_by_id, - GINT_TO_POINTER (xev->sourceid)); - - if (xi_event->evtype == XI_Enter) - { - event->crossing.type = event->type = CLUTTER_ENTER; - - event->crossing.stage = stage; - event->crossing.source = CLUTTER_ACTOR (stage); - event->crossing.related = NULL; - - event->crossing.time = xev->time; - translate_coords (stage_x11, xev->event_x, xev->event_y, &event->crossing.x, &event->crossing.y); - - if (xev->deviceid == seat->pointer_id) - seat->has_pointer_focus = TRUE; - } - else - { - event->crossing.type = event->type = CLUTTER_LEAVE; - - event->crossing.stage = stage; - event->crossing.source = CLUTTER_ACTOR (stage); - event->crossing.related = NULL; - - event->crossing.time = xev->time; - translate_coords (stage_x11, xev->event_x, xev->event_y, &event->crossing.x, &event->crossing.y); - - if (xev->deviceid == seat->pointer_id) - seat->has_pointer_focus = FALSE; - } - - meta_input_device_x11_reset_scroll_info (source_device); - - clutter_event_set_device (event, device); - clutter_event_set_source_device (event, source_device); - - retval = TRUE; - } - break; - - case XI_FocusIn: - case XI_FocusOut: - retval = FALSE; - break; - case XI_PropertyEvent: - translate_property_event (seat, xi_event); - retval = FALSE; - break; - } - - return retval; -} - -ClutterInputDevice * -meta_seat_x11_lookup_device_id (MetaSeatX11 *seat_x11, - int device_id) -{ - return g_hash_table_lookup (seat_x11->devices_by_id, - GINT_TO_POINTER (device_id)); -} - -void -meta_seat_x11_select_stage_events (MetaSeatX11 *seat, - ClutterStage *stage) -{ - MetaStageX11 *stage_x11; - XIEventMask xi_event_mask; - unsigned char *mask; - int len; - - stage_x11 = META_STAGE_X11 (_clutter_stage_get_window (stage)); - - len = XIMaskLen (XI_LASTEVENT); - mask = g_new0 (unsigned char, len); - - XISetMask (mask, XI_Motion); - XISetMask (mask, XI_ButtonPress); - XISetMask (mask, XI_ButtonRelease); - XISetMask (mask, XI_KeyPress); - XISetMask (mask, XI_KeyRelease); - XISetMask (mask, XI_Enter); - XISetMask (mask, XI_Leave); - - XISetMask (mask, XI_TouchBegin); - XISetMask (mask, XI_TouchUpdate); - XISetMask (mask, XI_TouchEnd); - - xi_event_mask.deviceid = XIAllMasterDevices; - xi_event_mask.mask = mask; - xi_event_mask.mask_len = len; - - XISelectEvents (meta_clutter_x11_get_default_display (), - stage_x11->xwin, &xi_event_mask, 1); - - g_free (mask); -} diff --git a/src/backends/x11/meta-seat-x11.h b/src/backends/x11/meta-seat-x11.h deleted file mode 100644 index 326db4a45..000000000 --- a/src/backends/x11/meta-seat-x11.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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 . - * - * Author: Carlos Garnacho - */ -#ifndef META_SEAT_X11_H -#define META_SEAT_X11_H - -#include "clutter/clutter.h" - -G_BEGIN_DECLS - -#define META_TYPE_SEAT_X11 meta_seat_x11_get_type () -G_DECLARE_FINAL_TYPE (MetaSeatX11, meta_seat_x11, META, SEAT_X11, ClutterSeat) - -MetaSeatX11 * meta_seat_x11_new (int opcode, - int logical_pointer, - int logical_keyboard); -gboolean meta_seat_x11_translate_event (MetaSeatX11 *seat, - XEvent *xevent, - ClutterEvent *event); -ClutterInputDevice * meta_seat_x11_lookup_device_id (MetaSeatX11 *seat_x11, - int device_id); -void meta_seat_x11_select_stage_events (MetaSeatX11 *seat, - ClutterStage *stage); -void meta_seat_x11_notify_devices (MetaSeatX11 *seat_x11, - ClutterStage *stage); - -G_END_DECLS - -#endif /* META_SEAT_X11_H */ diff --git a/src/backends/x11/meta-stage-x11.c b/src/backends/x11/meta-stage-x11.c deleted file mode 100644 index 87e7ffec6..000000000 --- a/src/backends/x11/meta-stage-x11.c +++ /dev/null @@ -1,853 +0,0 @@ -/* - * Authored By Matthew Allum - * Copyright (C) 2006-2007 OpenedHand - * - * 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 . - * - */ - -#include "config.h" - -#include -#include - -#ifdef HAVE_UNISTD_H -#include -#endif - -#include "backends/meta-stage-private.h" -#include "backends/x11/cm/meta-backend-x11-cm.h" -#include "backends/x11/cm/meta-renderer-x11-cm.h" -#include "backends/x11/meta-backend-x11.h" -#include "backends/x11/meta-clutter-backend-x11.h" -#include "backends/x11/meta-seat-x11.h" -#include "backends/x11/meta-stage-x11.h" -#include "backends/x11/nested/meta-stage-x11-nested.h" -#include "clutter/clutter-mutter.h" -#include "cogl/cogl-mutter.h" -#include "cogl/cogl.h" -#include "core/display-private.h" -#include "meta/meta-context.h" -#include "meta/meta-x11-errors.h" - -#define STAGE_X11_IS_MAPPED(s) ((((MetaStageX11 *) (s))->wm_state & STAGE_X11_WITHDRAWN) == 0) - -static ClutterStageWindowInterface *clutter_stage_window_parent_iface = NULL; - -static void -clutter_stage_window_iface_init (ClutterStageWindowInterface *iface); - -static MetaStageImpl *meta_x11_get_stage_window_from_window (Window win); - -static GHashTable *clutter_stages_by_xid = NULL; - -G_DEFINE_TYPE_WITH_CODE (MetaStageX11, - meta_stage_x11, - META_TYPE_STAGE_IMPL, - G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW, - clutter_stage_window_iface_init)); - -#define _NET_WM_STATE_REMOVE 0 /* remove/unset property */ -#define _NET_WM_STATE_ADD 1 /* add/set property */ -#define _NET_WM_STATE_TOGGLE 2 /* toggle property */ - -#define META_STAGE_X11_EVENT_MASK \ - StructureNotifyMask | \ - FocusChangeMask | \ - ExposureMask | \ - PropertyChangeMask | \ - EnterWindowMask | \ - LeaveWindowMask | \ - KeyPressMask | \ - KeyReleaseMask | \ - ButtonPressMask | \ - ButtonReleaseMask | \ - PointerMotionMask - -static void -meta_stage_x11_fix_window_size (MetaStageX11 *stage_x11, - int new_width, - int new_height) -{ - MetaStageImpl *stage_impl = META_STAGE_IMPL (stage_x11); - - if (stage_x11->xwin != None) - { - Display *xdisplay = meta_clutter_x11_get_default_display (); - uint32_t min_width, min_height; - XSizeHints *size_hints; - - size_hints = XAllocSizeHints(); - - clutter_stage_get_minimum_size (stage_impl->wrapper, - &min_width, - &min_height); - - if (new_width <= 0) - new_width = min_width; - - if (new_height <= 0) - new_height = min_height; - - 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 (xdisplay, stage_x11->xwin, size_hints); - - XFree(size_hints); - } -} - -static void -meta_stage_x11_set_wm_protocols (MetaStageX11 *stage_x11) -{ - MetaStageImpl *stage_impl = META_STAGE_IMPL (stage_x11); - MetaClutterBackendX11 *backend_x11 = - META_CLUTTER_BACKEND_X11 (stage_impl->backend); - Display *xdisplay = meta_clutter_x11_get_default_display (); - Atom protocols[2]; - int n = 0; - - protocols[n++] = backend_x11->atom_WM_DELETE_WINDOW; - protocols[n++] = backend_x11->atom_NET_WM_PING; - - XSetWMProtocols (xdisplay, stage_x11->xwin, protocols, n); -} - -static void -meta_stage_x11_get_geometry (ClutterStageWindow *stage_window, - cairo_rectangle_int_t *geometry) -{ - MetaStageX11 *stage_x11 = META_STAGE_X11 (stage_window); - - geometry->x = geometry->y = 0; - geometry->width = stage_x11->xwin_width; - geometry->height = stage_x11->xwin_height; -} - -static void -meta_stage_x11_resize (ClutterStageWindow *stage_window, - int width, - int height) -{ - MetaStageX11 *stage_x11 = META_STAGE_X11 (stage_window); - - if (width == 0 || height == 0) - { - /* Should not happen, if this turns up we need to debug it and - * determine the cleanest way to fix. - */ - g_warning ("X11 stage not allowed to have 0 width or height"); - width = 1; - height = 1; - } - - if (stage_x11->xwin != None) - { - meta_stage_x11_fix_window_size (stage_x11, width, height); - - if (width != stage_x11->xwin_width || - height != stage_x11->xwin_height) - { - Display *xdisplay = meta_clutter_x11_get_default_display (); - - /* XXX: in this case we can rely on a subsequent - * ConfigureNotify that will result in the stage - * being reallocated so we don't actively do anything - * to affect the stage allocation here. */ - XResizeWindow (xdisplay, - stage_x11->xwin, - width, - height); - } - } - else - { - /* if the backing window hasn't been created yet, we just - * need to store the new window size - */ - stage_x11->xwin_width = width; - stage_x11->xwin_height = height; - } -} - -static inline void -set_wm_pid (MetaStageX11 *stage_x11) -{ - MetaStageImpl *stage_impl = META_STAGE_IMPL (stage_x11); - MetaClutterBackendX11 *backend_x11 = - META_CLUTTER_BACKEND_X11 (stage_impl->backend); - Display *xdisplay = meta_clutter_x11_get_default_display (); - long pid; - - if (stage_x11->xwin == None) - return; - - /* this will take care of WM_CLIENT_MACHINE and WM_LOCALE_NAME */ - XSetWMProperties (xdisplay, stage_x11->xwin, - NULL, - NULL, - NULL, 0, - NULL, NULL, NULL); - - pid = getpid (); - XChangeProperty (xdisplay, - stage_x11->xwin, - backend_x11->atom_NET_WM_PID, XA_CARDINAL, 32, - PropModeReplace, - (guchar *) &pid, 1); -} - -static inline void -set_wm_title (MetaStageX11 *stage_x11) -{ - MetaStageImpl *stage_impl = META_STAGE_IMPL (stage_x11); - MetaClutterBackendX11 *backend_x11 = - META_CLUTTER_BACKEND_X11 (stage_impl->backend); - Display *xdisplay = meta_clutter_x11_get_default_display (); - - if (stage_x11->xwin == None) - return; - - if (stage_x11->title == NULL) - { - XDeleteProperty (xdisplay, - stage_x11->xwin, - backend_x11->atom_NET_WM_NAME); - } - else - { - XChangeProperty (xdisplay, - stage_x11->xwin, - backend_x11->atom_NET_WM_NAME, - backend_x11->atom_UTF8_STRING, - 8, - PropModeReplace, - (unsigned char *) stage_x11->title, - (int) strlen (stage_x11->title)); - } -} - -static void -meta_stage_x11_unrealize (ClutterStageWindow *stage_window) -{ - MetaStageX11 *stage_x11 = META_STAGE_X11 (stage_window); - - if (clutter_stages_by_xid != NULL) - { - g_hash_table_remove (clutter_stages_by_xid, - GINT_TO_POINTER (stage_x11->xwin)); - } - - clutter_stage_window_parent_iface->unrealize (stage_window); - - g_clear_object (&stage_x11->onscreen); -} - -static CoglOnscreen * -create_onscreen (CoglContext *cogl_context, - int width, - int height) -{ - CoglDisplay *cogl_display = cogl_context_get_display (cogl_context); - CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_display); - - switch (cogl_renderer_get_winsys_id (cogl_renderer)) - { - case COGL_WINSYS_ID_GLX: -#ifdef COGL_HAS_GLX_SUPPORT - return COGL_ONSCREEN (cogl_onscreen_glx_new (cogl_context, - width, height)); -#else - g_assert_not_reached (); - break; -#endif - case COGL_WINSYS_ID_EGL_XLIB: -#ifdef COGL_HAS_EGL_SUPPORT - return COGL_ONSCREEN (cogl_onscreen_xlib_new (cogl_context, - width, height)); -#else - g_assert_not_reached (); - break; -#endif - default: - g_assert_not_reached (); - return NULL; - } -} - -static gboolean -meta_stage_x11_realize (ClutterStageWindow *stage_window) -{ - MetaStageX11 *stage_x11 = META_STAGE_X11 (stage_window); - MetaStageImpl *stage_impl = META_STAGE_IMPL (stage_window); - ClutterBackend *backend = CLUTTER_BACKEND (stage_impl->backend); - MetaSeatX11 *seat_x11 = META_SEAT_X11 (clutter_backend_get_default_seat (backend)); - Display *xdisplay = meta_clutter_x11_get_default_display (); - float width, height; - GError *error = NULL; - - clutter_actor_get_size (CLUTTER_ACTOR (stage_impl->wrapper), &width, &height); - - stage_x11->onscreen = create_onscreen (backend->cogl_context, width, height); - - if (META_IS_BACKEND_X11_CM (stage_x11->backend)) - { - MetaRenderer *renderer = meta_backend_get_renderer (stage_x11->backend); - MetaRendererX11Cm *renderer_x11_cm = META_RENDERER_X11_CM (renderer); - - meta_renderer_x11_cm_init_screen_view (renderer_x11_cm, - stage_x11->onscreen, - stage_x11->xwin_width, - stage_x11->xwin_height); - } - - /* We just created a window of the size of the actor. No need to fix - the size of the stage, just update it. */ - stage_x11->xwin_width = width; - stage_x11->xwin_height = height; - - if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (stage_x11->onscreen), &error)) - { - g_warning ("Failed to allocate stage: %s", error->message); - g_error_free (error); - g_object_unref (stage_x11->onscreen); - abort(); - } - - if (!(clutter_stage_window_parent_iface->realize (stage_window))) - return FALSE; - - stage_x11->xwin = - cogl_x11_onscreen_get_x11_window (COGL_X11_ONSCREEN (stage_x11->onscreen)); - - if (clutter_stages_by_xid == NULL) - clutter_stages_by_xid = g_hash_table_new (NULL, NULL); - - g_hash_table_insert (clutter_stages_by_xid, - GINT_TO_POINTER (stage_x11->xwin), - stage_x11); - - set_wm_pid (stage_x11); - set_wm_title (stage_x11); - - /* we unconditionally select input events even with event retrieval - * disabled because we need to guarantee that the Clutter internal - * state is maintained when calling meta_clutter_x11_handle_event() without - * requiring applications or embedding toolkits to select events - * themselves. if we did that, we'd have to document the events to be - * selected, and also update applications and embedding toolkits each - * time we added a new mask, or a new class of events. - * - * see: http://bugzilla.clutter-project.org/show_bug.cgi?id=998 - * for the rationale of why we did conditional selection. it is now - * clear that a compositor should clear out the input region, since - * it cannot assume a perfectly clean slate coming from us. - * - * see: http://bugzilla.clutter-project.org/show_bug.cgi?id=2228 - * for an example of things that break if we do conditional event - * selection. - */ - XSelectInput (xdisplay, stage_x11->xwin, META_STAGE_X11_EVENT_MASK); - - meta_seat_x11_select_stage_events (seat_x11, stage_impl->wrapper); - - meta_stage_x11_fix_window_size (stage_x11, - stage_x11->xwin_width, - stage_x11->xwin_height); - meta_stage_x11_set_wm_protocols (stage_x11); - - return TRUE; -} - -static void -meta_stage_x11_set_title (ClutterStageWindow *stage_window, - const char *title) -{ - MetaStageX11 *stage_x11 = META_STAGE_X11 (stage_window); - - g_free (stage_x11->title); - stage_x11->title = g_strdup (title); - set_wm_title (stage_x11); -} - -static inline void -update_wm_hints (MetaStageX11 *stage_x11) -{ - Display *xdisplay = meta_clutter_x11_get_default_display (); - XWMHints wm_hints; - - if (stage_x11->wm_state & STAGE_X11_WITHDRAWN) - return; - - wm_hints.flags = StateHint | InputHint; - wm_hints.initial_state = NormalState; - wm_hints.input = True; - - XSetWMHints (xdisplay, stage_x11->xwin, &wm_hints); -} - -static void -set_stage_x11_state (MetaStageX11 *stage_x11, - MetaStageX11State unset_flags, - MetaStageX11State set_flags) -{ - MetaStageX11State new_stage_state, old_stage_state; - - old_stage_state = stage_x11->wm_state; - - new_stage_state = old_stage_state; - new_stage_state |= set_flags; - new_stage_state &= ~unset_flags; - - if (new_stage_state == old_stage_state) - return; - - stage_x11->wm_state = new_stage_state; -} - -static void -meta_stage_x11_show (ClutterStageWindow *stage_window, - gboolean do_raise) -{ - MetaStageX11 *stage_x11 = META_STAGE_X11 (stage_window); - MetaStageImpl *stage_impl = META_STAGE_IMPL (stage_x11); - - if (stage_x11->xwin != None) - { - Display *xdisplay = meta_clutter_x11_get_default_display (); - - if (do_raise) - { - XRaiseWindow (xdisplay, stage_x11->xwin); - } - - if (!STAGE_X11_IS_MAPPED (stage_x11)) - { - set_stage_x11_state (stage_x11, STAGE_X11_WITHDRAWN, 0); - - update_wm_hints (stage_x11); - } - - g_assert (STAGE_X11_IS_MAPPED (stage_x11)); - - clutter_actor_map (CLUTTER_ACTOR (stage_impl->wrapper)); - - XMapWindow (xdisplay, stage_x11->xwin); - } -} - -static void -meta_stage_x11_hide (ClutterStageWindow *stage_window) -{ - MetaStageX11 *stage_x11 = META_STAGE_X11 (stage_window); - MetaStageImpl *stage_impl = META_STAGE_IMPL (stage_x11); - - if (stage_x11->xwin != None) - { - Display *xdisplay = meta_clutter_x11_get_default_display (); - - if (STAGE_X11_IS_MAPPED (stage_x11)) - set_stage_x11_state (stage_x11, 0, STAGE_X11_WITHDRAWN); - - g_assert (!STAGE_X11_IS_MAPPED (stage_x11)); - - clutter_actor_unmap (CLUTTER_ACTOR (stage_impl->wrapper)); - - XWithdrawWindow (xdisplay, stage_x11->xwin, 0); - } -} - -static gboolean -meta_stage_x11_can_clip_redraws (ClutterStageWindow *stage_window) -{ - MetaStageX11 *stage_x11 = META_STAGE_X11 (stage_window); - - /* while resizing a window, clipped redraws are disabled in order to - * avoid artefacts. - */ - return stage_x11->clipped_redraws_cool_off == 0; -} - -static GList * -meta_stage_x11_get_views (ClutterStageWindow *stage_window) -{ - MetaStageX11 *stage_x11 = META_STAGE_X11 (stage_window); - MetaRenderer *renderer = meta_backend_get_renderer (stage_x11->backend); - - return meta_renderer_get_views (renderer); -} - -static void -meta_stage_x11_redraw_view (ClutterStageWindow *stage_window, - ClutterStageView *view, - ClutterFrame *frame) -{ - clutter_stage_window_parent_iface->redraw_view (stage_window, view, frame); - clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED); -} - -static void -meta_stage_x11_finalize (GObject *object) -{ - MetaStageX11 *stage_x11 = META_STAGE_X11 (object); - - g_free (stage_x11->title); - - G_OBJECT_CLASS (meta_stage_x11_parent_class)->finalize (object); -} - -static void -meta_stage_x11_class_init (MetaStageX11Class *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - gobject_class->finalize = meta_stage_x11_finalize; -} - -static void -meta_stage_x11_init (MetaStageX11 *stage) -{ - stage->xwin = None; - stage->xwin_width = 640; - stage->xwin_height = 480; - - stage->wm_state = STAGE_X11_WITHDRAWN; - - stage->title = NULL; - - stage->backend = meta_get_backend (); - g_assert (stage->backend); -} - -static void -clutter_stage_window_iface_init (ClutterStageWindowInterface *iface) -{ - clutter_stage_window_parent_iface = g_type_interface_peek_parent (iface); - - iface->set_title = meta_stage_x11_set_title; - iface->show = meta_stage_x11_show; - iface->hide = meta_stage_x11_hide; - iface->resize = meta_stage_x11_resize; - iface->get_geometry = meta_stage_x11_get_geometry; - iface->realize = meta_stage_x11_realize; - iface->unrealize = meta_stage_x11_unrealize; - iface->can_clip_redraws = meta_stage_x11_can_clip_redraws; - iface->get_views = meta_stage_x11_get_views; - iface->redraw_view = meta_stage_x11_redraw_view; -} - -static inline void -set_user_time (MetaClutterBackendX11 *backend_x11, - MetaStageX11 *stage_x11, - long timestamp) -{ - if (timestamp != CLUTTER_CURRENT_TIME) - { - Display *xdisplay = meta_clutter_x11_get_default_display (); - - XChangeProperty (xdisplay, - stage_x11->xwin, - backend_x11->atom_NET_WM_USER_TIME, - XA_CARDINAL, 32, - PropModeReplace, - (unsigned char *) ×tamp, 1); - } -} - -static gboolean -handle_wm_protocols_event (MetaClutterBackendX11 *backend_x11, - MetaStageX11 *stage_x11, - XEvent *xevent) -{ - Atom atom = (Atom) xevent->xclient.data.l[0]; - - if (atom == backend_x11->atom_WM_DELETE_WINDOW && - xevent->xany.window == stage_x11->xwin) - { - set_user_time (backend_x11, stage_x11, xevent->xclient.data.l[1]); - - return TRUE; - } - else if (atom == backend_x11->atom_NET_WM_PING && - xevent->xany.window == stage_x11->xwin) - { - XClientMessageEvent xclient = xevent->xclient; - Display *xdisplay = meta_clutter_x11_get_default_display (); - - xclient.window = backend_x11->xwin_root; - XSendEvent (xdisplay, xclient.window, - False, - SubstructureRedirectMask | SubstructureNotifyMask, - (XEvent *) &xclient); - return FALSE; - } - - /* do not send any of the WM_PROTOCOLS events to the queue */ - return FALSE; -} - -static gboolean -clipped_redraws_cool_off_cb (void *data) -{ - MetaStageX11 *stage_x11 = data; - - stage_x11->clipped_redraws_cool_off = 0; - - return G_SOURCE_REMOVE; -} - -gboolean -meta_stage_x11_translate_event (MetaStageX11 *stage_x11, - XEvent *xevent, - ClutterEvent *event) -{ - MetaStageImpl *stage_impl; - gboolean res = FALSE; - MetaClutterBackendX11 *clutter_backend_x11; - ClutterStage *stage; - MetaBackend *backend; - - stage_impl = meta_x11_get_stage_window_from_window (xevent->xany.window); - if (stage_impl == NULL) - return FALSE; - - stage = stage_impl->wrapper; - backend = stage_x11->backend; - clutter_backend_x11 = META_CLUTTER_BACKEND_X11 (stage_impl->backend); - - switch (xevent->type) - { - case ConfigureNotify: - { - gboolean size_changed = FALSE; - int stage_width; - int stage_height; - - g_debug ("ConfigureNotify[%x] (%d, %d)", - (unsigned int) stage_x11->xwin, - xevent->xconfigure.width, - 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; - stage_x11->xwin_height = xevent->xconfigure.height; - } - - stage_width = xevent->xconfigure.width; - stage_height = xevent->xconfigure.height; - - if (META_IS_BACKEND_X11_CM (stage_x11->backend)) - { - clutter_actor_set_size (CLUTTER_ACTOR (stage), - stage_width, - stage_height); - } - - if (size_changed) - { - /* XXX: This is a workaround for a race condition when - * resizing windows while there are in-flight - * glXCopySubBuffer blits happening. - * - * The problem stems from the fact that rectangles for the - * blits are described relative to the bottom left of the - * window and because we can't guarantee control over the X - * window gravity used when resizing so the gravity is - * typically NorthWest not SouthWest. - * - * This means if you grow a window vertically the server - * will make sure to place the old contents of the window - * at the top-left/north-west of your new larger window, but - * that may happen asynchronous to GLX preparing to do a - * blit specified relative to the bottom-left/south-west of - * the window (based on the old smaller window geometry). - * - * When the GLX issued blit finally happens relative to the - * new bottom of your window, the destination will have - * shifted relative to the top-left where all the pixels you - * care about are so it will result in a nasty artefact - * making resizing look very ugly! - * - * We can't currently fix this completely, in-part because - * the window manager tends to trample any gravity we might - * set. This workaround instead simply disables blits for a - * while if we are notified of any resizes happening so if - * the user is resizing a window via the window manager then - * they may see an artefact for one frame but then we will - * fallback to redrawing the full stage until the cooling - * off period is over. - */ - g_clear_handle_id (&stage_x11->clipped_redraws_cool_off, - g_source_remove); - - stage_x11->clipped_redraws_cool_off = - clutter_threads_add_timeout (1000, - clipped_redraws_cool_off_cb, - stage_x11); - - /* Queue a relayout - we want glViewport to be called - * with the correct values, and this is done in ClutterStage - * via cogl_onscreen_clutter_backend_set_size (). - * - * We queue a relayout, because if this ConfigureNotify is - * in response to a size we set in the application, the - * set_size() call above is essentially a null-op. - * - * Make sure we do this only when the size has changed, - * otherwise we end up relayouting on window moves. - */ - clutter_actor_queue_relayout (CLUTTER_ACTOR (stage)); - - /* the resize process is complete, so we can ask the stage - * to set up the GL viewport with the new size - */ - clutter_stage_ensure_viewport (stage); - - /* If this was a result of the Xrandr change when running as a - * X11 compositing manager, we need to reset the legacy - * stage view, now that it has a new size. - */ - if (META_IS_BACKEND_X11_CM (stage_x11->backend)) - { - MetaRenderer *renderer = meta_backend_get_renderer (backend); - MetaRendererX11Cm *renderer_x11_cm = - META_RENDERER_X11_CM (renderer); - - meta_renderer_x11_cm_resize (renderer_x11_cm, - stage_width, - stage_height); - } - } - } - break; - - case FocusIn: - meta_stage_set_active ((MetaStage *) stage_impl->wrapper, TRUE); - break; - - case FocusOut: - meta_stage_set_active ((MetaStage *) stage_impl->wrapper, FALSE); - break; - - case Expose: - { - XExposeEvent *expose = (XExposeEvent *) xevent; - cairo_rectangle_int_t clip; - - g_debug ("expose for stage: win:0x%x - " - "redrawing area (x: %d, y: %d, width: %d, height: %d)", - (unsigned int) xevent->xany.window, - expose->x, - expose->y, - expose->width, - expose->height); - - clip.x = expose->x; - clip.y = expose->y; - clip.width = expose->width; - clip.height = expose->height; - clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip); - } - break; - - case DestroyNotify: - g_debug ("Destroy notification received for stage, win:0x%x", - (unsigned int) xevent->xany.window); - - g_return_val_if_fail (META_IS_STAGE_X11_NESTED (stage_x11), - FALSE); - meta_context_terminate (meta_backend_get_context (backend)); - res = FALSE; - break; - - case ClientMessage: - g_debug ("Client message for stage, win:0x%x", - (unsigned int) xevent->xany.window); - - if (xevent->xclient.message_type == clutter_backend_x11->atom_WM_PROTOCOLS) - { - if (handle_wm_protocols_event (clutter_backend_x11, - stage_x11, - xevent)) - { - g_return_val_if_fail (META_IS_STAGE_X11_NESTED (stage_x11), - FALSE); - meta_context_terminate (meta_backend_get_context (backend)); - res = FALSE; - } - } - - break; - - default: - res = FALSE; - break; - } - - return res; -} - -Window -meta_x11_get_stage_window (ClutterStage *stage) -{ - ClutterStageWindow *impl; - - g_return_val_if_fail (CLUTTER_IS_STAGE (stage), None); - - impl = _clutter_stage_get_window (stage); - g_assert (META_IS_STAGE_X11 (impl)); - - return META_STAGE_X11 (impl)->xwin; -} - -static MetaStageImpl * -meta_x11_get_stage_window_from_window (Window win) -{ - if (clutter_stages_by_xid == NULL) - return NULL; - - return g_hash_table_lookup (clutter_stages_by_xid, - GINT_TO_POINTER (win)); -} - -ClutterStage * -meta_x11_get_stage_from_window (Window win) -{ - MetaStageImpl *stage_impl; - - stage_impl = meta_x11_get_stage_window_from_window (win); - - if (stage_impl != NULL) - return stage_impl->wrapper; - - return NULL; -} - -void -meta_stage_x11_set_user_time (MetaStageX11 *stage_x11, - uint32_t user_time) -{ - MetaStageImpl *stage_impl = META_STAGE_IMPL (stage_x11); - MetaClutterBackendX11 *backend_x11 = - META_CLUTTER_BACKEND_X11 (stage_impl->backend); - - set_user_time (backend_x11, stage_x11, user_time); -} diff --git a/src/backends/x11/meta-stage-x11.h b/src/backends/x11/meta-stage-x11.h deleted file mode 100644 index 041767167..000000000 --- a/src/backends/x11/meta-stage-x11.h +++ /dev/null @@ -1,96 +0,0 @@ -/* Clutter. - * An OpenGL based 'interactive canvas' library. - * Authored By Matthew Allum - * Copyright (C) 2006-2007 OpenedHand - * - * 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 . - * - * - */ - -#ifndef META_STAGE_X11_H -#define META_STAGE_X11_H - -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/x11/meta-clutter-backend-x11.h" -#include "clutter/clutter-mutter.h" - -G_BEGIN_DECLS - -#define META_TYPE_STAGE_X11 (meta_stage_x11_get_type ()) -#define META_STAGE_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_STAGE_X11, MetaStageX11)) -#define META_IS_STAGE_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_STAGE_X11)) -#define META_STAGE_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_STAGE_X11, MetaStageX11Class)) -#define META_IS_STAGE_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_STAGE_X11)) -#define META_STAGE_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_STAGE_X11, MetaStageX11Class)) - -typedef struct _MetaStageX11 MetaStageX11; -typedef struct _MetaStageX11Class MetaStageX11Class; - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaStageX11, g_object_unref) - -typedef enum -{ - STAGE_X11_WITHDRAWN = 1 << 1 -} MetaStageX11State; - -struct _MetaStageX11 -{ - MetaStageImpl parent_instance; - - MetaBackend *backend; - - CoglOnscreen *onscreen; - Window xwin; - gint xwin_width; - gint xwin_height; /* FIXME target_width / height */ - - CoglFrameClosure *frame_closure; - - gchar *title; - - guint clipped_redraws_cool_off; - - MetaStageX11State wm_state; - - guint viewport_initialized : 1; -}; - -struct _MetaStageX11Class -{ - MetaStageImplClass parent_class; -}; - -CLUTTER_EXPORT -GType meta_stage_x11_get_type (void) G_GNUC_CONST; - -/* Private to subclasses */ -void meta_stage_x11_set_user_time (MetaStageX11 *stage_x11, - guint32 user_time); - -gboolean meta_stage_x11_translate_event (MetaStageX11 *stage_x11, - XEvent *xevent, - ClutterEvent *event); - -ClutterStage *meta_x11_get_stage_from_window (Window win); - -Window meta_x11_get_stage_window (ClutterStage *stage); - - -G_END_DECLS - -#endif /* META_STAGE_H */ diff --git a/src/backends/x11/meta-virtual-input-device-x11.c b/src/backends/x11/meta-virtual-input-device-x11.c deleted file mode 100644 index 54bb43ad1..000000000 --- a/src/backends/x11/meta-virtual-input-device-x11.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright (C) 2016 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 . - * - * Author: Jonas Ådahl - */ - -#include "config.h" - -#include - -#include - -#include "backends/x11/meta-clutter-backend-x11.h" -#include "clutter/clutter.h" -#include "meta-keymap-x11.h" -#include "meta-virtual-input-device-x11.h" - -#define DISCRETE_SCROLL_STEP 10.0 - -struct _MetaVirtualInputDeviceX11 -{ - ClutterVirtualInputDevice parent; - - double accum_scroll_dx; - double accum_scroll_dy; -}; - -G_DEFINE_TYPE (MetaVirtualInputDeviceX11, - meta_virtual_input_device_x11, - CLUTTER_TYPE_VIRTUAL_INPUT_DEVICE) - -static void -meta_virtual_input_device_x11_notify_relative_motion (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - double dx, - double dy) -{ - XTestFakeRelativeMotionEvent (meta_clutter_x11_get_default_display (), - (int) dx, - (int) dy, - 0); -} - -static void -meta_virtual_input_device_x11_notify_absolute_motion (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - double x, - double y) -{ - XTestFakeMotionEvent (meta_clutter_x11_get_default_display (), - meta_clutter_x11_get_default_screen (), - (int) x, - (int) y, - 0); -} - -static void -meta_virtual_input_device_x11_notify_button (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - uint32_t button, - ClutterButtonState button_state) -{ - XTestFakeButtonEvent (meta_clutter_x11_get_default_display (), - button, button_state == CLUTTER_BUTTON_STATE_PRESSED, 0); -} - -static void -meta_virtual_input_device_x11_notify_discrete_scroll (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - ClutterScrollDirection direction, - ClutterScrollSource scroll_source) -{ - Display *xdisplay = meta_clutter_x11_get_default_display (); - int button; - - switch (direction) - { - case CLUTTER_SCROLL_UP: - button = 4; - break; - case CLUTTER_SCROLL_DOWN: - button = 5; - break; - case CLUTTER_SCROLL_LEFT: - button = 6; - break; - case CLUTTER_SCROLL_RIGHT: - button = 7; - break; - default: - g_warn_if_reached (); - return; - } - - XTestFakeButtonEvent (xdisplay, button, True, 0); - XTestFakeButtonEvent (xdisplay, button, False, 0); -} - -static void -meta_virtual_input_device_x11_notify_scroll_continuous (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - double dx, - double dy, - ClutterScrollSource scroll_source, - ClutterScrollFinishFlags finish_flags) -{ - MetaVirtualInputDeviceX11 *virtual_device_x11; - ClutterScrollDirection direction; - int i, n_xscrolls, n_yscrolls; - - virtual_device_x11 = META_VIRTUAL_INPUT_DEVICE_X11 (virtual_device); - - virtual_device_x11->accum_scroll_dx += dx; - virtual_device_x11->accum_scroll_dy += dy; - n_xscrolls = floor ((fabs (virtual_device_x11->accum_scroll_dx) + DBL_EPSILON) / - DISCRETE_SCROLL_STEP); - n_yscrolls = floor ((fabs (virtual_device_x11->accum_scroll_dy) + DBL_EPSILON) / - DISCRETE_SCROLL_STEP); - - direction = virtual_device_x11->accum_scroll_dx > 0 ? CLUTTER_SCROLL_RIGHT - : CLUTTER_SCROLL_LEFT; - for (i = 0; i < n_xscrolls; ++i) - { - meta_virtual_input_device_x11_notify_discrete_scroll ( - virtual_device, time_us, direction, CLUTTER_SCROLL_SOURCE_WHEEL); - } - - direction = virtual_device_x11->accum_scroll_dy > 0 ? CLUTTER_SCROLL_DOWN - : CLUTTER_SCROLL_UP; - for (i = 0; i < n_yscrolls; ++i) - { - meta_virtual_input_device_x11_notify_discrete_scroll ( - virtual_device, time_us, direction, CLUTTER_SCROLL_SOURCE_WHEEL); - } - - virtual_device_x11->accum_scroll_dx = - fmod (virtual_device_x11->accum_scroll_dx, DISCRETE_SCROLL_STEP); - virtual_device_x11->accum_scroll_dy = - fmod (virtual_device_x11->accum_scroll_dy, DISCRETE_SCROLL_STEP); -} - -static void -meta_virtual_input_device_x11_notify_key (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - uint32_t key, - ClutterKeyState key_state) -{ - XTestFakeKeyEvent (meta_clutter_x11_get_default_display (), - key + 8, key_state == CLUTTER_KEY_STATE_PRESSED, 0); -} - -static void -meta_virtual_input_device_x11_notify_keyval (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - uint32_t keyval, - ClutterKeyState key_state) -{ - ClutterBackend *backend = clutter_get_default_backend (); - ClutterSeat *seat = clutter_backend_get_default_seat (backend); - MetaKeymapX11 *keymap = META_KEYMAP_X11 (clutter_seat_get_keymap (seat)); - uint32_t keycode, level; - - if (!meta_keymap_x11_keycode_for_keyval (keymap, keyval, &keycode, &level)) - { - level = 0; - - if (!meta_keymap_x11_reserve_keycode (keymap, keyval, &keycode)) - { - g_warning ("No keycode found for keyval %x in current group", keyval); - return; - } - } - - if (!meta_keymap_x11_get_is_modifier (keymap, keycode) && - key_state == CLUTTER_KEY_STATE_PRESSED) - meta_keymap_x11_latch_modifiers (keymap, level, TRUE); - - XTestFakeKeyEvent (meta_clutter_x11_get_default_display (), - (KeyCode) keycode, - key_state == CLUTTER_KEY_STATE_PRESSED, 0); - - - if (key_state == CLUTTER_KEY_STATE_RELEASED) - { - if (!meta_keymap_x11_get_is_modifier (keymap, keycode)) - meta_keymap_x11_latch_modifiers (keymap, level, FALSE); - meta_keymap_x11_release_keycode_if_needed (keymap, keycode); - } -} - -static void -meta_virtual_input_device_x11_notify_touch_down (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - int device_slot, - double x, - double y) -{ - g_warning ("Virtual touch motion not implemented under X11"); -} - -static void -meta_virtual_input_device_x11_notify_touch_motion (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - int device_slot, - double x, - double y) -{ - g_warning ("Virtual touch motion not implemented under X11"); -} - -static void -meta_virtual_input_device_x11_notify_touch_up (ClutterVirtualInputDevice *virtual_device, - uint64_t time_us, - int device_slot) -{ - g_warning ("Virtual touch motion not implemented under X11"); -} - -static void -meta_virtual_input_device_x11_init (MetaVirtualInputDeviceX11 *virtual_device_x11) -{ -} - -static void -meta_virtual_input_device_x11_class_init (MetaVirtualInputDeviceX11Class *klass) -{ - ClutterVirtualInputDeviceClass *virtual_input_device_class = - CLUTTER_VIRTUAL_INPUT_DEVICE_CLASS (klass); - - virtual_input_device_class->notify_relative_motion = meta_virtual_input_device_x11_notify_relative_motion; - virtual_input_device_class->notify_absolute_motion = meta_virtual_input_device_x11_notify_absolute_motion; - virtual_input_device_class->notify_button = meta_virtual_input_device_x11_notify_button; - virtual_input_device_class->notify_discrete_scroll = meta_virtual_input_device_x11_notify_discrete_scroll; - virtual_input_device_class->notify_scroll_continuous = meta_virtual_input_device_x11_notify_scroll_continuous; - virtual_input_device_class->notify_key = meta_virtual_input_device_x11_notify_key; - virtual_input_device_class->notify_keyval = meta_virtual_input_device_x11_notify_keyval; - virtual_input_device_class->notify_touch_down = meta_virtual_input_device_x11_notify_touch_down; - virtual_input_device_class->notify_touch_motion = meta_virtual_input_device_x11_notify_touch_motion; - virtual_input_device_class->notify_touch_up = meta_virtual_input_device_x11_notify_touch_up; -} diff --git a/src/backends/x11/meta-virtual-input-device-x11.h b/src/backends/x11/meta-virtual-input-device-x11.h deleted file mode 100644 index 88c41ae8d..000000000 --- a/src/backends/x11/meta-virtual-input-device-x11.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2016 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 . - * - * Author: Jonas Ådahl - */ - -#ifndef META_VIRTUAL_INPUT_DEVICE_X11_H -#define META_VIRTUAL_INPUT_DEVICE_X11_H - -#include "clutter/clutter.h" - -#define META_TYPE_VIRTUAL_INPUT_DEVICE_X11 (meta_virtual_input_device_x11_get_type ()) -G_DECLARE_FINAL_TYPE (MetaVirtualInputDeviceX11, - meta_virtual_input_device_x11, - META, VIRTUAL_INPUT_DEVICE_X11, - ClutterVirtualInputDevice) - -#endif /* META_VIRTUAL_INPUT_DEVICE_X11_H */ diff --git a/src/backends/x11/meta-xkb-a11y-x11.c b/src/backends/x11/meta-xkb-a11y-x11.c deleted file mode 100644 index c73b9dc4f..000000000 --- a/src/backends/x11/meta-xkb-a11y-x11.c +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Copyright © 2001 Ximian, Inc. - * Copyright (C) 2007 William Jon McCann - * Copyright (C) 2017 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. - * - */ - -#include "config.h" - -#include -#include - -#include "backends/x11/meta-clutter-backend-x11.h" -#include "backends/x11/meta-xkb-a11y-x11.h" -#include "core/display-private.h" -#include "meta/meta-x11-errors.h" - -#define DEFAULT_XKB_SET_CONTROLS_MASK XkbSlowKeysMask | \ - XkbBounceKeysMask | \ - XkbStickyKeysMask | \ - XkbMouseKeysMask | \ - XkbMouseKeysAccelMask | \ - XkbAccessXKeysMask | \ - XkbAccessXTimeoutMask | \ - XkbAccessXFeedbackMask | \ - XkbControlsEnabledMask - -static int _xkb_event_base; - -static XkbDescRec * -get_xkb_desc_rec (Display *xdisplay) -{ - XkbDescRec *desc; - Status status = Success; - - meta_clutter_x11_trap_x_errors (); - desc = XkbGetMap (xdisplay, XkbAllMapComponentsMask, XkbUseCoreKbd); - if (desc != NULL) - { - desc->ctrls = NULL; - status = XkbGetControls (xdisplay, XkbAllControlsMask, desc); - } - meta_clutter_x11_untrap_x_errors (); - - g_return_val_if_fail (desc != NULL, NULL); - g_return_val_if_fail (desc->ctrls != NULL, NULL); - g_return_val_if_fail (status == Success, NULL); - - return desc; -} - -static void -set_xkb_desc_rec (Display *xdisplay, - XkbDescRec *desc) -{ - meta_clutter_x11_trap_x_errors (); - XkbSetControls (xdisplay, DEFAULT_XKB_SET_CONTROLS_MASK, desc); - XSync (xdisplay, FALSE); - meta_clutter_x11_untrap_x_errors (); -} - -static void -check_settings_changed (ClutterSeat *seat) -{ - Display *xdisplay = meta_clutter_x11_get_default_display (); - MetaKbdA11ySettings kbd_a11y_settings; - MetaKeyboardA11yFlags what_changed = 0; - MetaInputSettings *input_settings; - XkbDescRec *desc; - - desc = get_xkb_desc_rec (xdisplay); - if (!desc) - return; - - input_settings = meta_backend_get_input_settings (meta_get_backend ()); - meta_input_settings_get_kbd_a11y_settings (input_settings, - &kbd_a11y_settings); - - if (desc->ctrls->enabled_ctrls & XkbSlowKeysMask && - !(kbd_a11y_settings.controls & META_A11Y_SLOW_KEYS_ENABLED)) - { - what_changed |= META_A11Y_SLOW_KEYS_ENABLED; - kbd_a11y_settings.controls |= META_A11Y_SLOW_KEYS_ENABLED; - } - else if (!(desc->ctrls->enabled_ctrls & XkbSlowKeysMask) && - kbd_a11y_settings.controls & META_A11Y_SLOW_KEYS_ENABLED) - { - what_changed |= META_A11Y_SLOW_KEYS_ENABLED; - kbd_a11y_settings.controls &= ~META_A11Y_SLOW_KEYS_ENABLED; - } - - if (desc->ctrls->enabled_ctrls & XkbStickyKeysMask && - !(kbd_a11y_settings.controls & META_A11Y_STICKY_KEYS_ENABLED)) - { - what_changed |= META_A11Y_STICKY_KEYS_ENABLED; - kbd_a11y_settings.controls |= META_A11Y_STICKY_KEYS_ENABLED; - } - else if (!(desc->ctrls->enabled_ctrls & XkbStickyKeysMask) && - kbd_a11y_settings.controls & META_A11Y_STICKY_KEYS_ENABLED) - { - what_changed |= META_A11Y_STICKY_KEYS_ENABLED; - kbd_a11y_settings.controls &= ~META_A11Y_STICKY_KEYS_ENABLED; - } - - if (what_changed) - { - meta_input_settings_notify_kbd_a11y_change (input_settings, - kbd_a11y_settings.controls, - what_changed); - g_signal_emit_by_name (seat, - "kbd-a11y-flags-changed", - kbd_a11y_settings.controls, - what_changed); - } - - XkbFreeKeyboard (desc, XkbAllComponentsMask, TRUE); -} - -static MetaX11FilterReturn -xkb_a11y_event_filter (XEvent *xevent, - ClutterEvent *clutter_event, - gpointer data) -{ - ClutterSeat *seat = CLUTTER_SEAT (data); - XkbEvent *xkbev = (XkbEvent *) xevent; - - /* 'event_type' is set to zero on notifying us of updates in - * response to client requests (including our own) and non-zero - * to notify us of key/mouse events causing changes (like - * pressing shift 5 times to enable sticky keys). - * - * We only want to update out settings when it's in response to an - * explicit user input event, so require a non-zero event_type. - */ - if (xevent->xany.type == (_xkb_event_base + XkbEventCode) && - xkbev->any.xkb_type == XkbControlsNotify && xkbev->ctrls.event_type != 0) - check_settings_changed (seat); - - return META_X11_FILTER_CONTINUE; -} - -static gboolean -is_xkb_available (Display *xdisplay) -{ - int opcode, error_base, event_base, major, minor; - - if (_xkb_event_base) - return TRUE; - - if (!XkbQueryExtension (xdisplay, - &opcode, - &event_base, - &error_base, - &major, - &minor)) - return FALSE; - - if (!XkbUseExtension (xdisplay, &major, &minor)) - return FALSE; - - _xkb_event_base = event_base; - - return TRUE; -} - -static unsigned long -set_value_mask (gboolean flag, - unsigned long value, - unsigned long mask) -{ - if (flag) - return value | mask; - - return value & ~mask; -} - -static gboolean -set_xkb_ctrl (XkbDescRec *desc, - MetaKeyboardA11yFlags settings, - MetaKeyboardA11yFlags flag, - unsigned long mask) -{ - gboolean result = (settings & flag) == flag; - desc->ctrls->enabled_ctrls = set_value_mask (result, desc->ctrls->enabled_ctrls, mask); - - return result; -} - -void -meta_seat_x11_apply_kbd_a11y_settings (ClutterSeat *seat, - MetaKbdA11ySettings *kbd_a11y_settings) -{ - Display *xdisplay = meta_clutter_x11_get_default_display (); - XkbDescRec *desc; - gboolean enable_accessX; - - desc = get_xkb_desc_rec (xdisplay); - if (!desc) - return; - - /* general */ - enable_accessX = kbd_a11y_settings->controls & META_A11Y_KEYBOARD_ENABLED; - - desc->ctrls->enabled_ctrls = set_value_mask (enable_accessX, - desc->ctrls->enabled_ctrls, - XkbAccessXKeysMask); - - if (set_xkb_ctrl (desc, kbd_a11y_settings->controls, META_A11Y_TIMEOUT_ENABLED, - XkbAccessXTimeoutMask)) - { - desc->ctrls->ax_timeout = kbd_a11y_settings->timeout_delay; - /* disable only the master flag via the server we will disable - * the rest on the rebound without affecting settings state - * don't change the option flags at all. - */ - desc->ctrls->axt_ctrls_mask = XkbAccessXKeysMask | XkbAccessXFeedbackMask; - desc->ctrls->axt_ctrls_values = 0; - desc->ctrls->axt_opts_mask = 0; - } - - desc->ctrls->ax_options = - set_value_mask (kbd_a11y_settings->controls & META_A11Y_FEATURE_STATE_CHANGE_BEEP, - desc->ctrls->ax_options, - XkbAccessXFeedbackMask | XkbAX_FeatureFBMask | XkbAX_SlowWarnFBMask); - - /* bounce keys */ - if (set_xkb_ctrl (desc, kbd_a11y_settings->controls, - META_A11Y_BOUNCE_KEYS_ENABLED, XkbBounceKeysMask)) - { - desc->ctrls->debounce_delay = kbd_a11y_settings->debounce_delay; - desc->ctrls->ax_options = - set_value_mask (kbd_a11y_settings->controls & META_A11Y_BOUNCE_KEYS_BEEP_REJECT, - desc->ctrls->ax_options, - XkbAccessXFeedbackMask | XkbAX_BKRejectFBMask); - } - - /* mouse keys */ - if (clutter_keymap_get_num_lock_state (clutter_seat_get_keymap (seat))) - { - /* Disable mousekeys when NumLock is ON */ - desc->ctrls->enabled_ctrls &= ~(XkbMouseKeysMask | XkbMouseKeysAccelMask); - } - else if (set_xkb_ctrl (desc, kbd_a11y_settings->controls, - META_A11Y_MOUSE_KEYS_ENABLED, XkbMouseKeysMask | XkbMouseKeysAccelMask)) - { - int mk_max_speed; - int mk_accel_time; - - desc->ctrls->mk_interval = 100; /* msec between mousekey events */ - desc->ctrls->mk_curve = 50; - - /* We store pixels / sec, XKB wants pixels / event */ - mk_max_speed = kbd_a11y_settings->mousekeys_max_speed; - desc->ctrls->mk_max_speed = mk_max_speed / (1000 / desc->ctrls->mk_interval); - if (desc->ctrls->mk_max_speed <= 0) - desc->ctrls->mk_max_speed = 1; - - mk_accel_time = kbd_a11y_settings->mousekeys_accel_time; - desc->ctrls->mk_time_to_max = mk_accel_time / desc->ctrls->mk_interval; - - if (desc->ctrls->mk_time_to_max <= 0) - desc->ctrls->mk_time_to_max = 1; - - desc->ctrls->mk_delay = kbd_a11y_settings->mousekeys_init_delay; - } - - /* slow keys */ - if (set_xkb_ctrl (desc, kbd_a11y_settings->controls, - META_A11Y_SLOW_KEYS_ENABLED, XkbSlowKeysMask)) - { - desc->ctrls->ax_options = - set_value_mask (kbd_a11y_settings->controls & META_A11Y_SLOW_KEYS_BEEP_PRESS, - desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_SKPressFBMask); - desc->ctrls->ax_options = - set_value_mask (kbd_a11y_settings->controls & META_A11Y_SLOW_KEYS_BEEP_ACCEPT, - desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_SKAcceptFBMask); - desc->ctrls->ax_options = - set_value_mask (kbd_a11y_settings->controls & META_A11Y_SLOW_KEYS_BEEP_REJECT, - desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_SKRejectFBMask); - desc->ctrls->slow_keys_delay = kbd_a11y_settings->slowkeys_delay; - /* anything larger than 500 seems to loose all keyboard input */ - if (desc->ctrls->slow_keys_delay > 500) - desc->ctrls->slow_keys_delay = 500; - } - - /* sticky keys */ - if (set_xkb_ctrl (desc, kbd_a11y_settings->controls, - META_A11Y_STICKY_KEYS_ENABLED, XkbStickyKeysMask)) - { - desc->ctrls->ax_options |= XkbAX_LatchToLockMask; - desc->ctrls->ax_options = - set_value_mask (kbd_a11y_settings->controls & META_A11Y_STICKY_KEYS_TWO_KEY_OFF, - desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_TwoKeysMask); - desc->ctrls->ax_options = - set_value_mask (kbd_a11y_settings->controls & META_A11Y_STICKY_KEYS_BEEP, - desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_StickyKeysFBMask); - } - - /* toggle keys */ - desc->ctrls->ax_options = - set_value_mask (kbd_a11y_settings->controls & META_A11Y_TOGGLE_KEYS_ENABLED, - desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_IndicatorFBMask); - - set_xkb_desc_rec (xdisplay, desc); - XkbFreeKeyboard (desc, XkbAllComponentsMask, TRUE); -} - -gboolean -meta_seat_x11_a11y_init (ClutterSeat *seat) -{ - Display *xdisplay = meta_clutter_x11_get_default_display (); - guint event_mask; - - if (!is_xkb_available (xdisplay)) - return FALSE; - - event_mask = XkbControlsNotifyMask | XkbAccessXNotifyMask; - - XkbSelectEvents (xdisplay, XkbUseCoreKbd, event_mask, event_mask); - - meta_clutter_x11_add_filter (xkb_a11y_event_filter, seat); - - return TRUE; -} diff --git a/src/backends/x11/meta-xkb-a11y-x11.h b/src/backends/x11/meta-xkb-a11y-x11.h deleted file mode 100644 index 58a4e1766..000000000 --- a/src/backends/x11/meta-xkb-a11y-x11.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * - * Copyright © 2001 Ximian, Inc. - * Copyright (C) 2007 William Jon McCann - * Copyright (C) 2017 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_XKB_A11Y_X11_H -#define META_XKB_A11Y_X11_H - -#include - -#include "backends/meta-input-settings-private.h" -#include "clutter/clutter.h" - -void -meta_seat_x11_apply_kbd_a11y_settings (ClutterSeat *seat, - MetaKbdA11ySettings *kbd_a11y_settings); - -gboolean -meta_seat_x11_a11y_init (ClutterSeat *seat); - -#endif /* META_XKB_A11Y_X11_H */ diff --git a/src/backends/x11/nested/meta-backend-x11-nested.c b/src/backends/x11/nested/meta-backend-x11-nested.c deleted file mode 100644 index 041b42860..000000000 --- a/src/backends/x11/nested/meta-backend-x11-nested.c +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Copyright (C) 2017 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. - */ - -#include "config.h" - -#include "backends/x11/nested/meta-backend-x11-nested.h" - -#include "backends/meta-input-settings-dummy.h" -#include "backends/meta-monitor-manager-dummy.h" -#include "backends/x11/nested/meta-backend-x11-nested.h" -#include "backends/x11/nested/meta-cursor-renderer-x11-nested.h" -#include "backends/x11/nested/meta-renderer-x11-nested.h" - -#include "wayland/meta-wayland.h" - -typedef struct _MetaBackendX11NestedPrivate -{ - MetaGpu *gpu; - MetaCursorRenderer *cursor_renderer; - MetaInputSettings *input_settings; -} MetaBackendX11NestedPrivate; - -static GInitableIface *initable_parent_iface; - -static void -initable_iface_init (GInitableIface *initable_iface); - -G_DEFINE_TYPE_WITH_CODE (MetaBackendX11Nested, meta_backend_x11_nested, - META_TYPE_BACKEND_X11, - G_ADD_PRIVATE (MetaBackendX11Nested) - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - initable_iface_init)); - -static MetaRenderer * -meta_backend_x11_nested_create_renderer (MetaBackend *backend, - GError **error) -{ - return g_object_new (META_TYPE_RENDERER_X11_NESTED, - "backend", backend, - NULL); -} - -static MetaMonitorManager * -meta_backend_x11_nested_create_monitor_manager (MetaBackend *backend, - GError **error) -{ - return g_object_new (META_TYPE_MONITOR_MANAGER_DUMMY, - "backend", backend, - NULL); -} - -static MetaCursorRenderer * -meta_backend_x11_nested_get_cursor_renderer (MetaBackend *backend, - ClutterInputDevice *device) -{ - MetaBackendX11Nested *backend_x11_nested = META_BACKEND_X11_NESTED (backend); - MetaBackendX11NestedPrivate *priv = - meta_backend_x11_nested_get_instance_private (backend_x11_nested); - - if (!priv->cursor_renderer) - { - priv->cursor_renderer = - g_object_new (META_TYPE_CURSOR_RENDERER_X11_NESTED, - "backend", backend, - "device", device, - NULL); - } - - return priv->cursor_renderer; -} - -static MetaInputSettings * -meta_backend_x11_nested_get_input_settings (MetaBackend *backend) -{ - MetaBackendX11Nested *backend_x11_nested = META_BACKEND_X11_NESTED (backend); - MetaBackendX11NestedPrivate *priv = - meta_backend_x11_nested_get_instance_private (backend_x11_nested); - - if (!priv->input_settings) - { - priv->input_settings = - g_object_new (META_TYPE_INPUT_SETTINGS_DUMMY, NULL); - } - - return priv->input_settings; -} - -static void -meta_backend_x11_nested_update_screen_size (MetaBackend *backend, - int width, - int height) -{ - ClutterActor *stage = meta_backend_get_stage (backend); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - - if (meta_is_stage_views_enabled ()) - { - meta_renderer_rebuild_views (renderer); - clutter_stage_clear_stage_views (CLUTTER_STAGE (stage)); - } - clutter_actor_set_size (stage, width, height); -} - -static void -meta_backend_x11_nested_select_stage_events (MetaBackend *backend) -{ - MetaBackendX11 *x11 = META_BACKEND_X11 (backend); - Display *xdisplay = meta_backend_x11_get_xdisplay (x11); - Window xwin = meta_backend_x11_get_xwindow (x11); - unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 }; - XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits }; - - XISetMask (mask.mask, XI_KeyPress); - XISetMask (mask.mask, XI_KeyRelease); - XISetMask (mask.mask, XI_ButtonPress); - XISetMask (mask.mask, XI_ButtonRelease); - XISetMask (mask.mask, XI_Enter); - XISetMask (mask.mask, XI_Leave); - XISetMask (mask.mask, XI_FocusIn); - XISetMask (mask.mask, XI_FocusOut); - XISetMask (mask.mask, XI_Motion); - - /* - * When we're an X11 compositor, we can't take these events or else replaying - * events from our passive root window grab will cause them to come back to - * us. - * - * When we're a nested application, we want to behave like any other - * application, so select these events like normal apps do. - */ - XISetMask (mask.mask, XI_TouchBegin); XISetMask (mask.mask, XI_TouchEnd); - XISetMask (mask.mask, XI_TouchUpdate); - - XISelectEvents (xdisplay, xwin, &mask, 1); - - /* - * We have no way of tracking key changes when the stage doesn't have focus, - * so we select for KeymapStateMask so that we get a complete dump of the - * keyboard state in a KeymapNotify event that immediately follows each - * FocusIn (and EnterNotify, but we ignore that.) - */ - XWindowAttributes xwa; - - XGetWindowAttributes(xdisplay, xwin, &xwa); - XSelectInput(xdisplay, xwin, - xwa.your_event_mask | FocusChangeMask | KeymapStateMask); -} - -static void -meta_backend_x11_nested_lock_layout_group (MetaBackend *backend, - guint idx) -{ -} - -static void -meta_backend_x11_nested_set_keymap (MetaBackend *backend, - const char *layouts, - const char *variants, - const char *options) -{ -} - -static gboolean -meta_backend_x11_nested_is_lid_closed (MetaBackend *backend) -{ - return FALSE; -} - -static gboolean -meta_backend_x11_nested_handle_host_xevent (MetaBackendX11 *x11, - XEvent *event) -{ -#ifdef HAVE_WAYLAND - if (event->type == FocusIn) - { - Window xwin = meta_backend_x11_get_xwindow (x11); - XEvent xev; - - if (event->xfocus.window == xwin) - { - MetaWaylandCompositor *compositor = - meta_wayland_compositor_get_default (); - Display *xdisplay = meta_backend_x11_get_xdisplay (x11); - - /* - * Since we've selected for KeymapStateMask, every FocusIn is - * followed immediately by a KeymapNotify event. - */ - XMaskEvent (xdisplay, KeymapStateMask, &xev); - meta_wayland_compositor_update_key_state (compositor, - xev.xkeymap.key_vector, - 32, 8); - } - } -#endif - - return FALSE; -} - -static void -meta_backend_x11_nested_translate_device_event (MetaBackendX11 *x11, - XIDeviceEvent *device_event) -{ - /* This codepath should only ever trigger as an X11 compositor, - * and never under nested, as under nested all backend events - * should be reported with respect to the stage window. - */ - g_assert (device_event->event == meta_backend_x11_get_xwindow (x11)); -} - -static void -meta_backend_x11_nested_real_init_gpus (MetaBackendX11Nested *backend_x11_nested) -{ - MetaBackendX11NestedPrivate *priv = - meta_backend_x11_nested_get_instance_private (backend_x11_nested); - - priv->gpu = g_object_new (META_TYPE_GPU_DUMMY, - "backend", backend_x11_nested, - NULL); - meta_backend_add_gpu (META_BACKEND (backend_x11_nested), priv->gpu); -} - -static void -meta_backend_x11_nested_post_init (MetaBackend *backend) -{ - MetaBackendClass *backend_class = - META_BACKEND_CLASS (meta_backend_x11_nested_parent_class); - - backend_class->post_init (backend); -} - -static gboolean -meta_backend_x11_nested_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - return initable_parent_iface->init (initable, cancellable, error); -} - -static void -initable_iface_init (GInitableIface *initable_iface) -{ - initable_parent_iface = g_type_interface_peek_parent (initable_iface); - - initable_iface->init = meta_backend_x11_nested_initable_init; -} - -static void -meta_backend_x11_nested_constructed (GObject *object) -{ - MetaBackendX11Nested *backend_x11_nested = META_BACKEND_X11_NESTED (object); - MetaBackendX11NestedClass *backend_x11_nested_class = - META_BACKEND_X11_NESTED_GET_CLASS (backend_x11_nested); - GObjectClass *parent_class = - G_OBJECT_CLASS (meta_backend_x11_nested_parent_class); - - parent_class->constructed (object); - - backend_x11_nested_class->init_gpus (backend_x11_nested); -} - -static void -meta_backend_x11_nested_dispose (GObject *object) -{ - MetaBackendX11Nested *backend_x11_nested = META_BACKEND_X11_NESTED (object); - MetaBackendX11NestedPrivate *priv = - meta_backend_x11_nested_get_instance_private (backend_x11_nested); - - g_clear_object (&priv->input_settings); - - G_OBJECT_CLASS (meta_backend_x11_nested_parent_class)->dispose (object); -} - -static void -meta_backend_x11_nested_init (MetaBackendX11Nested *backend_x11_nested) -{ -} - -static void -meta_backend_x11_nested_class_init (MetaBackendX11NestedClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaBackendClass *backend_class = META_BACKEND_CLASS (klass); - MetaBackendX11Class *backend_x11_class = META_BACKEND_X11_CLASS (klass); - - object_class->constructed = meta_backend_x11_nested_constructed; - object_class->dispose = meta_backend_x11_nested_dispose; - - backend_class->post_init = meta_backend_x11_nested_post_init; - backend_class->create_renderer = meta_backend_x11_nested_create_renderer; - backend_class->create_monitor_manager = meta_backend_x11_nested_create_monitor_manager; - backend_class->get_cursor_renderer = meta_backend_x11_nested_get_cursor_renderer; - backend_class->get_input_settings = meta_backend_x11_nested_get_input_settings; - backend_class->update_screen_size = meta_backend_x11_nested_update_screen_size; - backend_class->select_stage_events = meta_backend_x11_nested_select_stage_events; - backend_class->lock_layout_group = meta_backend_x11_nested_lock_layout_group; - backend_class->set_keymap = meta_backend_x11_nested_set_keymap; - backend_class->is_lid_closed = meta_backend_x11_nested_is_lid_closed; - - backend_x11_class->handle_host_xevent = meta_backend_x11_nested_handle_host_xevent; - backend_x11_class->translate_device_event = meta_backend_x11_nested_translate_device_event; - - klass->init_gpus = meta_backend_x11_nested_real_init_gpus; -} diff --git a/src/backends/x11/nested/meta-backend-x11-nested.h b/src/backends/x11/nested/meta-backend-x11-nested.h deleted file mode 100644 index 4f19ff54a..000000000 --- a/src/backends/x11/nested/meta-backend-x11-nested.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2017 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_X11_NESTED_H -#define META_BACKEND_X11_NESTED_H - -#include - -#include "backends/x11/meta-backend-x11.h" -#include "core/util-private.h" - -#define META_TYPE_BACKEND_X11_NESTED (meta_backend_x11_nested_get_type ()) -META_EXPORT_TEST -G_DECLARE_DERIVABLE_TYPE (MetaBackendX11Nested, meta_backend_x11_nested, - META, BACKEND_X11_NESTED, MetaBackendX11) - -struct _MetaBackendX11NestedClass -{ - MetaBackendX11Class parent_class; - - void (* init_gpus) (MetaBackendX11Nested *backend_x11_nested); -}; - -#endif /* META_BACKEND_X11_NESTED_H */ diff --git a/src/backends/x11/nested/meta-cursor-renderer-x11-nested.c b/src/backends/x11/nested/meta-cursor-renderer-x11-nested.c deleted file mode 100644 index 0daae683c..000000000 --- a/src/backends/x11/nested/meta-cursor-renderer-x11-nested.c +++ /dev/null @@ -1,91 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#include "config.h" - -#include "backends/x11/nested/meta-cursor-renderer-x11-nested.h" - -#include - -#include "backends/x11/meta-backend-x11.h" - -struct _MetaCursorRendererX11Nested -{ - MetaCursorRenderer parent; -}; - -G_DEFINE_TYPE (MetaCursorRendererX11Nested, meta_cursor_renderer_x11_nested, - META_TYPE_CURSOR_RENDERER); - -static gboolean -meta_cursor_renderer_x11_nested_update_cursor (MetaCursorRenderer *renderer, - MetaCursorSprite *cursor_sprite) -{ - if (cursor_sprite) - meta_cursor_sprite_realize_texture (cursor_sprite); - return FALSE; -} - -static Cursor -create_empty_cursor (Display *xdisplay) -{ - XcursorImage *image; - XcursorPixel *pixels; - Cursor xcursor; - - image = XcursorImageCreate (1, 1); - if (image == NULL) - return None; - - image->xhot = 0; - image->yhot = 0; - - pixels = image->pixels; - pixels[0] = 0; - - xcursor = XcursorImageLoadCursor (xdisplay, image); - XcursorImageDestroy (image); - - return xcursor; -} - -static void -meta_cursor_renderer_x11_nested_init (MetaCursorRendererX11Nested *x11_nested) -{ - MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ()); - Window xwindow = meta_backend_x11_get_xwindow (backend); - Display *xdisplay = meta_backend_x11_get_xdisplay (backend); - - Cursor empty_xcursor = create_empty_cursor (xdisplay); - XDefineCursor (xdisplay, xwindow, empty_xcursor); - XFreeCursor (xdisplay, empty_xcursor); -} - -static void -meta_cursor_renderer_x11_nested_class_init (MetaCursorRendererX11NestedClass *klass) -{ - MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_CLASS (klass); - - renderer_class->update_cursor = meta_cursor_renderer_x11_nested_update_cursor; -} diff --git a/src/backends/x11/nested/meta-cursor-renderer-x11-nested.h b/src/backends/x11/nested/meta-cursor-renderer-x11-nested.h deleted file mode 100644 index 32f816629..000000000 --- a/src/backends/x11/nested/meta-cursor-renderer-x11-nested.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#ifndef META_CURSOR_RENDERER_X11_NESTED_NESTED_H -#define META_CURSOR_RENDERER_X11_NESTED_NESTED_H - -#include - -#include "backends/meta-cursor-renderer.h" - -#define META_TYPE_CURSOR_RENDERER_X11_NESTED (meta_cursor_renderer_x11_nested_get_type ()) -G_DECLARE_FINAL_TYPE (MetaCursorRendererX11Nested, - meta_cursor_renderer_x11_nested, - META, CURSOR_RENDERER_X11_NESTED, - MetaCursorRenderer); - -#endif /* META_CURSOR_RENDERER_X11_NESTED_NESTED_H */ diff --git a/src/backends/x11/nested/meta-renderer-x11-nested.c b/src/backends/x11/nested/meta-renderer-x11-nested.c deleted file mode 100644 index 7c1a4facf..000000000 --- a/src/backends/x11/nested/meta-renderer-x11-nested.c +++ /dev/null @@ -1,248 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 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. - * - */ - -#include "config.h" - -#include "backends/x11/nested/meta-renderer-x11-nested.h" - -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-logical-monitor.h" -#include "backends/meta-output.h" -#include "backends/meta-renderer.h" -#include "backends/meta-renderer-view.h" -#include "backends/x11/meta-clutter-backend-x11.h" -#include "core/boxes-private.h" -#include "meta/meta-backend.h" -#include "meta/util.h" - -struct _MetaRendererX11Nested -{ - MetaRendererX11 parent; -}; - -G_DEFINE_TYPE (MetaRendererX11Nested, meta_renderer_x11_nested, - META_TYPE_RENDERER_X11) - -static MetaMonitorTransform -calculate_view_transform (MetaMonitorManager *monitor_manager, - MetaLogicalMonitor *logical_monitor) -{ - MetaMonitor *main_monitor; - MetaOutput *main_output; - MetaCrtc *crtc; - MetaMonitorTransform crtc_transform; - - main_monitor = meta_logical_monitor_get_monitors (logical_monitor)->data; - main_output = meta_monitor_get_main_output (main_monitor); - crtc = meta_output_get_assigned_crtc (main_output); - crtc_transform = - meta_monitor_logical_to_crtc_transform (main_monitor, - logical_monitor->transform); - /* - * Pick any monitor and output and check; all CRTCs of a logical monitor will - * always have the same transform assigned to them. - */ - - if (meta_monitor_manager_is_transform_handled (monitor_manager, - crtc, - crtc_transform)) - return META_MONITOR_TRANSFORM_NORMAL; - else - return crtc_transform; -} - -static MetaRendererView * -get_legacy_view (MetaRenderer *renderer) -{ - GList *views; - - views = meta_renderer_get_views (renderer); - if (views) - return META_RENDERER_VIEW (views->data); - else - return NULL; -} - -static CoglOffscreen * -create_offscreen (CoglContext *cogl_context, - int width, - int height) -{ - CoglTexture2D *texture_2d; - CoglOffscreen *offscreen; - GError *error = NULL; - - texture_2d = cogl_texture_2d_new_with_size (cogl_context, width, height); - offscreen = cogl_offscreen_new_with_texture (COGL_TEXTURE (texture_2d)); - - if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (offscreen), &error)) - meta_fatal ("Couldn't allocate framebuffer: %s", error->message); - - return offscreen; -} - -static void -meta_renderer_x11_nested_resize_legacy_view (MetaRendererX11Nested *renderer_x11_nested, - int width, - int height) -{ - MetaRenderer *renderer = META_RENDERER (renderer_x11_nested); - MetaBackend *backend = meta_get_backend (); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); - MetaRendererView *legacy_view; - cairo_rectangle_int_t view_layout; - CoglOffscreen *fake_onscreen; - - legacy_view = get_legacy_view (renderer); - - clutter_stage_view_get_layout (CLUTTER_STAGE_VIEW (legacy_view), - &view_layout); - if (view_layout.width == width && - view_layout.height == height) - return; - - view_layout = (cairo_rectangle_int_t) { - .width = width, - .height = height - }; - - fake_onscreen = create_offscreen (cogl_context, width, height); - - g_object_set (G_OBJECT (legacy_view), - "layout", &view_layout, - "framebuffer", COGL_FRAMEBUFFER (fake_onscreen), - NULL); -} - -void -meta_renderer_x11_nested_ensure_legacy_view (MetaRendererX11Nested *renderer_x11_nested, - int width, - int height) -{ - MetaRenderer *renderer = META_RENDERER (renderer_x11_nested); - MetaBackend *backend = meta_get_backend (); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); - cairo_rectangle_int_t view_layout; - CoglOffscreen *fake_onscreen; - MetaRendererView *legacy_view; - - if (get_legacy_view (renderer)) - { - meta_renderer_x11_nested_resize_legacy_view (renderer_x11_nested, - width, height); - return; - } - - fake_onscreen = create_offscreen (cogl_context, width, height); - - view_layout = (cairo_rectangle_int_t) { - .width = width, - .height = height - }; - legacy_view = g_object_new (META_TYPE_RENDERER_VIEW, - "name", "legacy nested", - "stage", meta_backend_get_stage (backend), - "layout", &view_layout, - "framebuffer", COGL_FRAMEBUFFER (fake_onscreen), - NULL); - - g_assert (!meta_renderer_get_views (renderer)); - meta_renderer_add_view (renderer, legacy_view); -} - -static MetaRendererView * -meta_renderer_x11_nested_create_view (MetaRenderer *renderer, - MetaLogicalMonitor *logical_monitor, - MetaOutput *output, - MetaCrtc *crtc) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); - MetaMonitorTransform view_transform; - float view_scale; - const MetaCrtcConfig *crtc_config; - int width, height; - CoglOffscreen *fake_onscreen; - CoglOffscreen *offscreen; - MetaRectangle view_layout; - const MetaCrtcModeInfo *mode_info; - MetaRendererView *view; - - view_transform = calculate_view_transform (monitor_manager, logical_monitor); - - if (meta_is_stage_views_scaled ()) - view_scale = logical_monitor->scale; - else - view_scale = 1.0; - - crtc_config = meta_crtc_get_config (crtc); - width = roundf (crtc_config->layout.size.width * view_scale); - height = roundf (crtc_config->layout.size.height * view_scale); - - fake_onscreen = create_offscreen (cogl_context, width, height); - - if (view_transform != META_MONITOR_TRANSFORM_NORMAL) - offscreen = create_offscreen (cogl_context, width, height); - else - offscreen = NULL; - - meta_rectangle_from_graphene_rect (&crtc_config->layout, - META_ROUNDING_STRATEGY_ROUND, - &view_layout); - - mode_info = meta_crtc_mode_get_info (crtc_config->mode); - - view = g_object_new (META_TYPE_RENDERER_VIEW, - "name", meta_output_get_name (output), - "stage", meta_backend_get_stage (backend), - "layout", &view_layout, - "crtc", crtc, - "refresh-rate", mode_info->refresh_rate, - "framebuffer", COGL_FRAMEBUFFER (fake_onscreen), - "offscreen", COGL_FRAMEBUFFER (offscreen), - "transform", view_transform, - "scale", view_scale, - NULL); - g_object_set_data (G_OBJECT (view), "crtc", crtc); - - return view; -} - -static void -meta_renderer_x11_nested_init (MetaRendererX11Nested *renderer_x11_nested) -{ -} - -static void -meta_renderer_x11_nested_class_init (MetaRendererX11NestedClass *klass) -{ - MetaRendererClass *renderer_class = META_RENDERER_CLASS (klass); - - renderer_class->create_view = meta_renderer_x11_nested_create_view; -} diff --git a/src/backends/x11/nested/meta-renderer-x11-nested.h b/src/backends/x11/nested/meta-renderer-x11-nested.h deleted file mode 100644 index 9fc88e85b..000000000 --- a/src/backends/x11/nested/meta-renderer-x11-nested.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 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_RENDERER_X11_NESTED_H -#define META_RENDERER_X11_NESTED_H - -#include "backends/x11/meta-renderer-x11.h" - -#define META_TYPE_RENDERER_X11_NESTED (meta_renderer_x11_nested_get_type ()) -G_DECLARE_FINAL_TYPE (MetaRendererX11Nested, meta_renderer_x11_nested, - META, RENDERER_X11_NESTED, - MetaRendererX11) - -void meta_renderer_x11_nested_ensure_legacy_view (MetaRendererX11Nested *renderer_x11_nested, - int width, - int height); - -#endif /* META_RENDERER_X11_NESTED_H */ diff --git a/src/backends/x11/nested/meta-stage-x11-nested.c b/src/backends/x11/nested/meta-stage-x11-nested.c deleted file mode 100644 index dbf3b7bbf..000000000 --- a/src/backends/x11/nested/meta-stage-x11-nested.c +++ /dev/null @@ -1,236 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#include "config.h" - -#include "backends/x11/nested/meta-stage-x11-nested.h" - -#include "backends/meta-backend-private.h" -#include "backends/meta-crtc.h" -#include "backends/meta-logical-monitor.h" -#include "backends/meta-monitor.h" -#include "backends/meta-output.h" -#include "backends/meta-renderer.h" -#include "backends/x11/nested/meta-renderer-x11-nested.h" -#include "clutter/clutter-mutter.h" - -static ClutterStageWindowInterface *clutter_stage_window_parent_iface = NULL; - -struct _MetaStageX11Nested -{ - MetaStageX11 parent; - - CoglPipeline *pipeline; -}; - -static void -clutter_stage_window_iface_init (ClutterStageWindowInterface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaStageX11Nested, meta_stage_x11_nested, - META_TYPE_STAGE_X11, - G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW, - clutter_stage_window_iface_init)) - -typedef struct _MetaStageX11View -{ - CoglTexture *texture; - MetaStageView *view; -} MetaStageX11NestedView; - -static void -meta_stage_x11_nested_resize (ClutterStageWindow *stage_window, - gint width, - gint height) -{ - if (!meta_is_stage_views_enabled ()) - { - MetaBackend *backend = meta_get_backend (); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - MetaRendererX11Nested *renderer_x11_nested = - META_RENDERER_X11_NESTED (renderer); - - meta_renderer_x11_nested_ensure_legacy_view (renderer_x11_nested, - width, height); - } - - clutter_stage_window_parent_iface->resize (stage_window, width, height); -} - -static gboolean -meta_stage_x11_nested_can_clip_redraws (ClutterStageWindow *stage_window) -{ - return FALSE; -} - -static GList * -meta_stage_x11_nested_get_views (ClutterStageWindow *stage_window) -{ - MetaBackend *backend = meta_get_backend (); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - - return meta_renderer_get_views (renderer); -} - -typedef struct -{ - MetaStageX11Nested *stage_nested; - CoglTexture *texture; - ClutterStageView *view; - MetaLogicalMonitor *logical_monitor; -} DrawCrtcData; - -static gboolean -draw_view (MetaStageX11Nested *stage_nested, - MetaRendererView *renderer_view, - CoglTexture *texture) -{ - MetaStageX11 *stage_x11 = META_STAGE_X11 (stage_nested); - CoglFramebuffer *onscreen = COGL_FRAMEBUFFER (stage_x11->onscreen); - ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (renderer_view); - MetaCrtc *crtc; - const MetaCrtcConfig *crtc_config; - graphene_matrix_t projection_matrix; - graphene_matrix_t transform; - float texture_width, texture_height; - float sample_x, sample_y, sample_width, sample_height; - float s_1, t_1, s_2, t_2; - - texture_width = cogl_texture_get_width (texture); - texture_height = cogl_texture_get_height (texture); - - crtc = g_object_get_data (G_OBJECT (renderer_view), "crtc"); - crtc_config = meta_crtc_get_config (crtc); - - sample_x = 0; - sample_y = 0; - sample_width = texture_width; - sample_height = texture_height; - - clutter_stage_view_get_offscreen_transformation_matrix (stage_view, - &transform); - - cogl_framebuffer_push_matrix (onscreen); - graphene_matrix_init_scale (&projection_matrix, 2, -2, 0); - graphene_matrix_translate (&projection_matrix, - &GRAPHENE_POINT3D_INIT (-1, 1, 0)); - graphene_matrix_multiply (&transform, &projection_matrix, &projection_matrix); - cogl_framebuffer_set_projection_matrix (onscreen, &projection_matrix); - - s_1 = sample_x / texture_width; - t_1 = sample_y / texture_height; - s_2 = (sample_x + sample_width) / texture_width; - t_2 = (sample_y + sample_height) / texture_height; - - cogl_framebuffer_set_viewport (onscreen, - crtc_config->layout.origin.x, - crtc_config->layout.origin.y, - crtc_config->layout.size.width, - crtc_config->layout.size.height); - - cogl_framebuffer_draw_textured_rectangle (onscreen, - stage_nested->pipeline, - 0, 0, 1, 1, - s_1, t_1, s_2, t_2); - - cogl_framebuffer_pop_matrix (onscreen); - return TRUE; -} - -static void -meta_stage_x11_nested_finish_frame (ClutterStageWindow *stage_window, - ClutterStageView *stage_view, - ClutterFrame *frame) -{ - MetaStageX11Nested *stage_nested = META_STAGE_X11_NESTED (stage_window); - MetaStageX11 *stage_x11 = META_STAGE_X11 (stage_window); - MetaBackend *backend = meta_get_backend (); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - CoglFramebuffer *onscreen = COGL_FRAMEBUFFER (stage_x11->onscreen); - CoglContext *context = cogl_framebuffer_get_context (onscreen); - GList *l; - CoglFrameInfo *frame_info; - - if (!stage_nested->pipeline) - stage_nested->pipeline = cogl_pipeline_new (clutter_backend->cogl_context); - - cogl_framebuffer_clear4f (onscreen, - COGL_BUFFER_BIT_COLOR, - 0.0f, 0.0f, 0.0f, 1.0f); - - for (l = meta_renderer_get_views (renderer); l; l = l->next) - { - ClutterStageView *view = l->data; - MetaRendererView *renderer_view = META_RENDERER_VIEW (view); - CoglFramebuffer *framebuffer; - CoglTexture *texture; - - framebuffer = clutter_stage_view_get_onscreen (view); - texture = cogl_offscreen_get_texture (COGL_OFFSCREEN (framebuffer)); - - cogl_pipeline_set_layer_texture (stage_nested->pipeline, 0, texture); - cogl_pipeline_set_layer_wrap_mode (stage_nested->pipeline, 0, - COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); - - draw_view (stage_nested, renderer_view, texture); - } - - frame_info = cogl_frame_info_new (context, 0); - cogl_onscreen_swap_buffers (stage_x11->onscreen, frame_info, frame); - - if (!clutter_frame_has_result (frame)) - clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_IDLE); -} - -static void -meta_stage_x11_nested_unrealize (ClutterStageWindow *stage_window) -{ - MetaStageX11Nested *stage_nested = META_STAGE_X11_NESTED (stage_window); - - g_clear_pointer (&stage_nested->pipeline, cogl_object_unref); - - clutter_stage_window_parent_iface->unrealize (stage_window); -} - -static void -meta_stage_x11_nested_init (MetaStageX11Nested *stage_x11_nested) -{ -} - -static void -meta_stage_x11_nested_class_init (MetaStageX11NestedClass *klass) -{ -} - -static void -clutter_stage_window_iface_init (ClutterStageWindowInterface *iface) -{ - clutter_stage_window_parent_iface = g_type_interface_peek_parent (iface); - - iface->resize = meta_stage_x11_nested_resize; - iface->can_clip_redraws = meta_stage_x11_nested_can_clip_redraws; - iface->unrealize = meta_stage_x11_nested_unrealize; - iface->get_views = meta_stage_x11_nested_get_views; - iface->finish_frame = meta_stage_x11_nested_finish_frame; -} diff --git a/src/backends/x11/nested/meta-stage-x11-nested.h b/src/backends/x11/nested/meta-stage-x11-nested.h deleted file mode 100644 index 76678465b..000000000 --- a/src/backends/x11/nested/meta-stage-x11-nested.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#ifndef META_STAGE_X11_NESTED_H -#define META_STAGE_X11_NESTED_H - -#include "clutter/clutter-mutter.h" -#include "backends/x11/meta-stage-x11.h" - -#define META_TYPE_STAGE_X11_NESTED (meta_stage_x11_nested_get_type ()) -G_DECLARE_FINAL_TYPE (MetaStageX11Nested, meta_stage_x11_nested, - META, STAGE_X11_NESTED, MetaStageX11) - -#endif /* META_STAGE_X11_NESTED_H */ diff --git a/src/compositor/README b/src/compositor/README deleted file mode 100644 index 93edf8dc9..000000000 --- a/src/compositor/README +++ /dev/null @@ -1,70 +0,0 @@ -Intro -===== - -In general, the compositor splits the window from the contents of -the window from the shape of the window. In other words, a window -has contents, and the contents of the window have a shape. This is -represented by the actor hierarchy: - - +--------------------------------------+ - | MetaWindowActor | - | +----------------------------------+ | - | | MetaSurfaceActor | | - | | +------------------------------+ | | - | | | MetaShapedTexture | | | - | | | | | | - | | | | | | - | | | | | | - | | | | | | - | | +------------------------------+ | | - | +----------------------------------+ | - +--------------------------------------+ - -Surfaces may also contain subsurfaces. The MetaWindowActor and -MetaSurfaceActor subclasses that will be created depend on the client -type, and the display server type. - -## Subsurfaces - -Additionally, there is also the case of subsurfaces: surfaces that -are child of other surfaces. That is also represented in the actor -hierarchy by having one or many MetaSurfaceActors (the subsurfaces) -added as children of a parent MetaSurfaceActor. There are no limits -to how many subsurfaces a surface may have. With subsurfaces, the -actor hierarchy looks like this: - - MetaWindowActor - ↳ MetaSurfaceActor (surface) - ↳ MetaShapedTexture - ↳ MetaSurfaceActor (subsurface) - ↳ MetaShapedTexture - ↳ MetaSurfaceActor (sub-subsurface) - ↳ MetaShapedTexture - ↳ MetaSurfaceActor (subsurface) - ↳ MetaShapedTexture - -In this example, the main surface has 2 subsurfaces. One of these -subsurfaces contains a subsurface as well. - -All MetaWindowActors contain at least one MetaSurfaceActor, and all -MetaSurfaceActors contain a MetaShapedTexture. - -## Client and compositor - -MetaWindowActor and its subclasses represent the client window's -type. A X11 client will have a MetaWindowActorX11 representing it, -and a Wayland client will have a MetaWindowActorWayland. - -On the compositor side, the surface where the contents of the window -are drawn into are represented by MetaSurfaceActor subclasses. On a -Wayland session, windows are backed by a MetaSurfaceActorWayland -surface, whereas on X11 sessions, by MetaSurfaceActorX11. - -XWayland windows are X11 client windows (MetaWindowActorX11) backed -by Wayland surfaces (MetaWindowActorWayland). - - -Env Vars -======== - -MUTTER_DISABLE_MIPMAPS - set to disable use of mipmaped windows. \ No newline at end of file diff --git a/src/compositor/clutter-utils.c b/src/compositor/clutter-utils.c deleted file mode 100644 index 86d788562..000000000 --- a/src/compositor/clutter-utils.c +++ /dev/null @@ -1,188 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * Utilities for use with Cogl - * - * Copyright 2010 Red Hat, Inc. - * Copyright 2010 Intel Corporation - * - * 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 . - */ - -#include "config.h" - -#include "compositor/clutter-utils.h" - -#include - -/* This file uses pixel-aligned region computation to determine what - * can be clipped out. This only really works if everything is aligned - * to the pixel grid - not scaled or rotated and at integer offsets. - * - * (This could be relaxed - if we turned off filtering for unscaled - * windows then windows would be, by definition aligned to the pixel - * grid. And for rectangular windows without a shape, the outline that - * we draw for an unrotated window is always a rectangle because we - * don't use antialasing for the window boundary - with or without - * filtering, with or without a scale. But figuring out exactly - * what pixels will be drawn by the graphics system in these cases - * gets tricky, so we just go for the easiest part - no scale, - * and at integer offsets.) - * - * The way we check for pixel-aligned is by looking at the - * transformation into screen space of the allocation box of an actor - * and and checking if the corners are "close enough" to integral - * pixel values. - */ - -/* The definition of "close enough" to integral pixel values is - * equality when we convert to 24.8 fixed-point. - */ -static inline int -round_to_fixed (float x) -{ - return roundf (x * 256); -} - -/* Help macros to scale from OpenGL <-1,1> coordinates system to - * window coordinates ranging [0,window-size]. Borrowed from clutter-utils.c - */ -#define MTX_GL_SCALE_X(x,w,v1,v2) ((((((x) / (w)) + 1.0f) / 2.0f) * (v1)) + (v2)) -#define MTX_GL_SCALE_Y(y,w,v1,v2) ((v1) - (((((y) / (w)) + 1.0f) / 2.0f) * (v1)) + (v2)) - -/* This helper function checks if (according to our fixed point precision) - * the vertices @verts form a box of width @widthf and height @heightf - * located at integral coordinates. These coordinates are returned - * in @x_origin and @y_origin. - */ -gboolean -meta_actor_vertices_are_untransformed (graphene_point3d_t *verts, - float widthf, - float heightf, - int *x_origin, - int *y_origin) -{ - int width, height; - int v0x, v0y, v1x, v1y, v2x, v2y, v3x, v3y; - int x, y; - - width = round_to_fixed (widthf); - height = round_to_fixed (heightf); - - v0x = round_to_fixed (verts[0].x); v0y = round_to_fixed (verts[0].y); - v1x = round_to_fixed (verts[1].x); v1y = round_to_fixed (verts[1].y); - v2x = round_to_fixed (verts[2].x); v2y = round_to_fixed (verts[2].y); - v3x = round_to_fixed (verts[3].x); v3y = round_to_fixed (verts[3].y); - - /* Using shifting for converting fixed => int, gets things right for - * negative values. / 256. wouldn't do the same - */ - x = v0x >> 8; - y = v0y >> 8; - - /* At integral coordinates? */ - if (x * 256 != v0x || y * 256 != v0y) - return FALSE; - - /* Not scaled? */ - if (v1x - v0x != width || v2y - v0y != height) - return FALSE; - - /* Not rotated/skewed? */ - if (v0x != v2x || v0y != v1y || - v3x != v1x || v3y != v2y) - return FALSE; - - if (x_origin) - *x_origin = x; - if (y_origin) - *y_origin = y; - - return TRUE; -} - -/** - * meta_actor_painting_untransformed: - * @paint_width: the width of the painted area - * @paint_height: the height of the painted area - * @sample_width: the width of the sampled area of the texture - * @sample_height: the height of the sampled area of the texture - * @x_origin: if the transform is only an integer translation - * then the X coordinate of the location of the origin under the transformation - * from drawing space to screen pixel space is returned here. - * @y_origin: if the transform is only an integer translation - * then the X coordinate of the location of the origin under the transformation - * from drawing space to screen pixel space is returned here. - * - * Determines if the current painting transform is an integer translation. - * This can differ from the result of meta_actor_is_untransformed() when - * painting an actor if we're inside a inside a clone paint. @paint_width - * and @paint_height are used to determine the vertices of the rectangle - * we check to see if the painted area is "close enough" to the integer - * transform. - */ -gboolean -meta_actor_painting_untransformed (CoglFramebuffer *fb, - int paint_width, - int paint_height, - int sample_width, - int sample_height, - int *x_origin, - int *y_origin) -{ - graphene_matrix_t modelview, projection, modelview_projection; - graphene_point3d_t vertices[4]; - float viewport[4]; - int i; - - cogl_framebuffer_get_modelview_matrix (fb, &modelview); - cogl_framebuffer_get_projection_matrix (fb, &projection); - - graphene_matrix_multiply (&modelview, - &projection, - &modelview_projection); - - vertices[0].x = 0; - vertices[0].y = 0; - vertices[0].z = 0; - vertices[1].x = paint_width; - vertices[1].y = 0; - vertices[1].z = 0; - vertices[2].x = 0; - vertices[2].y = paint_height; - vertices[2].z = 0; - vertices[3].x = paint_width; - vertices[3].y = paint_height; - vertices[3].z = 0; - - cogl_framebuffer_get_viewport4fv (fb, viewport); - - for (i = 0; i < 4; i++) - { - float w = 1; - cogl_graphene_matrix_project_point (&modelview_projection, - &vertices[i].x, - &vertices[i].y, - &vertices[i].z, - &w); - vertices[i].x = MTX_GL_SCALE_X (vertices[i].x, w, - viewport[2], viewport[0]); - vertices[i].y = MTX_GL_SCALE_Y (vertices[i].y, w, - viewport[3], viewport[1]); - } - - return meta_actor_vertices_are_untransformed (vertices, - sample_width, sample_height, - x_origin, y_origin); -} - diff --git a/src/compositor/clutter-utils.h b/src/compositor/clutter-utils.h deleted file mode 100644 index 8ed0e2a4d..000000000 --- a/src/compositor/clutter-utils.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * Utilities for use with Clutter - * - * Copyright 2010 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 . - */ - -#ifndef __META_CLUTTER_UTILS_H__ -#define __META_CLUTTER_UTILS_H__ - -#include "clutter/clutter.h" - -gboolean meta_actor_vertices_are_untransformed (graphene_point3d_t *verts, - float widthf, - float heightf, - int *x_origin, - int *y_origin); - -gboolean meta_actor_painting_untransformed (CoglFramebuffer *fb, - int paint_width, - int paint_height, - int sample_widthf, - int sample_heightf, - int *x_origin, - int *y_origin); - -#endif /* __META_CLUTTER_UTILS_H__ */ diff --git a/src/compositor/cogl-utils.c b/src/compositor/cogl-utils.c deleted file mode 100644 index 0a39755a5..000000000 --- a/src/compositor/cogl-utils.c +++ /dev/null @@ -1,114 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * Utilities for use with Cogl - * - * Copyright 2010 Red Hat, Inc. - * Copyright 2010 Intel Corporation - * - * 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 . - */ - -#include "config.h" - -#include "clutter/clutter.h" -#include "compositor/cogl-utils.h" - -/* Based on gnome-shell/src/st/st-private.c:_st_create_texture_material.c */ - -/** - * meta_create_texture_pipeline: - * @src_texture: (nullable): texture to use initially for the layer - * - * Creates a pipeline with a single layer. Using a common template - * makes it easier for Cogl to share a shader for different uses in - * Mutter. - * - * Return value: (transfer full): a newly created #CoglPipeline - */ -CoglPipeline * -meta_create_texture_pipeline (CoglTexture *src_texture) -{ - static CoglPipeline *texture_pipeline_template = NULL; - CoglPipeline *pipeline; - - /* The only state used in the pipeline that would affect the shader - generation is the texture type on the layer. Therefore we create - a template pipeline which sets this state and all texture - pipelines are created as a copy of this. That way Cogl can find - the shader state for the pipeline more quickly by looking at the - pipeline ancestry instead of resorting to the shader cache. */ - if (G_UNLIKELY (texture_pipeline_template == NULL)) - { - CoglContext *ctx = - clutter_backend_get_cogl_context (clutter_get_default_backend ()); - - texture_pipeline_template = cogl_pipeline_new (ctx); - cogl_pipeline_set_layer_null_texture (texture_pipeline_template, 0); - } - - pipeline = cogl_pipeline_copy (texture_pipeline_template); - - if (src_texture != NULL) - cogl_pipeline_set_layer_texture (pipeline, 0, src_texture); - - return pipeline; -} - -/** - * meta_create_texture: - * @width: width of the texture to create - * @height: height of the texture to create - * @components; components to store in the texture (color or alpha) - * @flags: flags that affect the allocation behavior - * - * Creates a texture of the given size with the specified components - * for use as a frame buffer object. - * - * If %META_TEXTURE_ALLOW_SLICING is present in @flags, and the texture - * is larger than the texture size limits of the system, then the texture - * will be created as a sliced texture. This also will cause problems - * with using the texture with GLSL, and is more likely to be an issue - * since all GL implementations have texture size limits, and they can - * be as small as 2048x2048 on reasonably current systems. - */ -CoglTexture * -meta_create_texture (int width, - int height, - CoglTextureComponents components, - MetaTextureFlags flags) -{ - ClutterBackend *backend = clutter_get_default_backend (); - CoglContext *ctx = clutter_backend_get_cogl_context (backend); - CoglTexture *texture; - - texture = COGL_TEXTURE (cogl_texture_2d_new_with_size (ctx, width, height)); - cogl_texture_set_components (texture, components); - - if ((flags & META_TEXTURE_ALLOW_SLICING) != 0) - { - /* To find out if we need to slice the texture, we have to go ahead and force storage - * to be allocated - */ - GError *catch_error = NULL; - if (!cogl_texture_allocate (texture, &catch_error)) - { - g_error_free (catch_error); - cogl_object_unref (texture); - texture = COGL_TEXTURE (cogl_texture_2d_sliced_new_with_size (ctx, width, height, COGL_TEXTURE_MAX_WASTE)); - cogl_texture_set_components (texture, components); - } - } - - return texture; -} diff --git a/src/compositor/cogl-utils.h b/src/compositor/cogl-utils.h deleted file mode 100644 index ae7e85176..000000000 --- a/src/compositor/cogl-utils.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * Utilities for use with Cogl - * - * Copyright 2010 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 . - */ - -#ifndef __META_COGL_UTILS_H__ -#define __META_COGL_UTILS_H__ - -#include "cogl/cogl.h" - -CoglPipeline * meta_create_texture_pipeline (CoglTexture *texture); - -typedef enum -{ - META_TEXTURE_FLAGS_NONE = 0, - META_TEXTURE_ALLOW_SLICING = 1 << 1 -} MetaTextureFlags; - -CoglTexture *meta_create_texture (int width, - int height, - CoglTextureComponents components, - MetaTextureFlags flags); - -#endif /* __META_COGL_UTILS_H__ */ diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h deleted file mode 100644 index 580618e48..000000000 --- a/src/compositor/compositor-private.h +++ /dev/null @@ -1,101 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -#ifndef META_COMPOSITOR_PRIVATE_H -#define META_COMPOSITOR_PRIVATE_H - -#include - -#include "clutter/clutter-mutter.h" -#include "clutter/clutter.h" -#include "compositor/meta-plugin-manager.h" -#include "compositor/meta-window-actor-private.h" -#include "meta/compositor.h" -#include "meta/display.h" - -/* Wait 2ms after vblank before starting to draw next frame */ -#define META_SYNC_DELAY 2 - -typedef struct _MetaLaters MetaLaters; - -struct _MetaCompositorClass -{ - GObjectClass parent_class; - - gboolean (* manage) (MetaCompositor *compositor, - GError **error); - void (* unmanage) (MetaCompositor *compositor); - void (* before_paint) (MetaCompositor *compositor, - ClutterStageView *stage_view); - void (* after_paint) (MetaCompositor *compositor, - ClutterStageView *stage_view); - void (* remove_window) (MetaCompositor *compositor, - MetaWindow *window); - int64_t (* monotonic_to_high_res_xserver_time) (MetaCompositor *compositor, - int64_t time_us); - void (* grab_begin) (MetaCompositor *compositor); - void (* grab_end) (MetaCompositor *compositor); -}; - -gboolean meta_compositor_do_manage (MetaCompositor *compositor, - GError **error); - -void meta_compositor_remove_window_actor (MetaCompositor *compositor, - MetaWindowActor *window_actor); - -void meta_switch_workspace_completed (MetaCompositor *compositor); - -gboolean meta_begin_modal_for_plugin (MetaCompositor *compositor, - MetaPlugin *plugin, - MetaModalOptions options, - guint32 timestamp); -void meta_end_modal_for_plugin (MetaCompositor *compositor, - MetaPlugin *plugin, - guint32 timestamp); - -MetaPluginManager * meta_compositor_get_plugin_manager (MetaCompositor *compositor); - -int64_t meta_compositor_monotonic_to_high_res_xserver_time (MetaCompositor *compositor, - int64_t monotonic_time_us); - -void meta_compositor_flash_window (MetaCompositor *compositor, - MetaWindow *window); - -MetaCloseDialog * meta_compositor_create_close_dialog (MetaCompositor *compositor, - MetaWindow *window); - -MetaInhibitShortcutsDialog * meta_compositor_create_inhibit_shortcuts_dialog (MetaCompositor *compositor, - MetaWindow *window); - -void meta_compositor_locate_pointer (MetaCompositor *compositor); - -void meta_compositor_redirect_x11_windows (MetaCompositor *compositor); - -gboolean meta_compositor_is_unredirect_inhibited (MetaCompositor *compositor); - -MetaDisplay * meta_compositor_get_display (MetaCompositor *compositor); - -MetaWindowActor * meta_compositor_get_top_window_actor (MetaCompositor *compositor); - -ClutterStage * meta_compositor_get_stage (MetaCompositor *compositor); - -gboolean meta_compositor_is_switching_workspace (MetaCompositor *compositor); - -MetaLaters * meta_compositor_get_laters (MetaCompositor *compositor); - -/* - * This function takes a 64 bit time stamp from the monotonic clock, and clamps - * it to the scope of the X server clock, without losing the granularity. - */ -static inline int64_t -meta_translate_to_high_res_xserver_time (int64_t time_us) -{ - int64_t us; - int64_t ms; - - us = time_us % 1000; - ms = time_us / 1000; - - return ms2us (ms & 0xffffffff) + us; -} - -#endif /* META_COMPOSITOR_PRIVATE_H */ diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c deleted file mode 100644 index 9cdd39c15..000000000 --- a/src/compositor/compositor.c +++ /dev/null @@ -1,1581 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/** - * SECTION:compositor - * @Title: MetaCompositor - * @Short_Description: Compositor API - * - * At a high-level, a window is not-visible or visible. When a - * window is added (with meta_compositor_add_window()) it is not visible. - * meta_compositor_show_window() indicates a transition from not-visible to - * visible. Some of the reasons for this: - * - * - Window newly created - * - Window is unminimized - * - Window is moved to the current desktop - * - Window was made sticky - * - * meta_compositor_hide_window() indicates that the window has transitioned from - * visible to not-visible. Some reasons include: - * - * - Window was destroyed - * - Window is minimized - * - Window is moved to a different desktop - * - Window no longer sticky. - * - * Note that combinations are possible - a window might have first - * been minimized and then moved to a different desktop. The 'effect' parameter - * to meta_compositor_show_window() and meta_compositor_hide_window() is a hint - * as to the appropriate effect to show the user and should not - * be considered to be indicative of a state change. - * - * When the active workspace is changed, meta_compositor_switch_workspace() is - * called first, then meta_compositor_show_window() and - * meta_compositor_hide_window() are called individually for each window - * affected, with an effect of META_COMP_EFFECT_NONE. - * If hiding windows will affect the switch workspace animation, the - * compositor needs to delay hiding the windows until the switch - * workspace animation completes. - * - * # Containers # - * - * There's two containers in the stage that are used to place window actors, here - * are listed in the order in which they are painted: - * - * - window group, accessible with meta_get_window_group_for_display() - * - top window group, accessible with meta_get_top_window_group_for_display() - * - * Mutter will place actors representing windows in the window group, except for - * override-redirect windows (ie. popups and menus) which will be placed in the - * top window group. - */ - -#include "config.h" - -#include "compositor/compositor-private.h" - -#include - -#include "backends/x11/meta-backend-x11.h" -#include "backends/x11/meta-event-x11.h" -#include "backends/x11/meta-stage-x11.h" -#include "clutter/clutter-mutter.h" -#include "cogl/cogl.h" -#include "compositor/meta-later-private.h" -#include "compositor/meta-window-actor-x11.h" -#include "compositor/meta-window-actor-private.h" -#include "compositor/meta-window-group-private.h" -#include "core/frame.h" -#include "core/util-private.h" -#include "core/window-private.h" -#include "meta/compositor-mutter.h" -#include "meta/main.h" -#include "meta/meta-backend.h" -#include "meta/meta-background-actor.h" -#include "meta/meta-background-group.h" -#include "meta/meta-context.h" -#include "meta/meta-shadow-factory.h" -#include "meta/meta-x11-errors.h" -#include "meta/prefs.h" -#include "meta/window.h" -#include "x11/meta-x11-display-private.h" - -#ifdef HAVE_WAYLAND -#include "compositor/meta-window-actor-wayland.h" -#include "wayland/meta-wayland-private.h" -#endif - -enum -{ - PROP_0, - - PROP_DISPLAY, - PROP_BACKEND, - - N_PROPS -}; - -static GParamSpec *obj_props[N_PROPS] = { NULL, }; - -typedef struct _MetaCompositorPrivate -{ - GObject parent; - - MetaDisplay *display; - MetaBackend *backend; - - gulong stage_presented_id; - gulong before_paint_handler_id; - gulong after_paint_handler_id; - - int64_t server_time_query_time; - int64_t server_time_offset; - - gboolean server_time_is_monotonic_time; - - ClutterActor *window_group; - ClutterActor *top_window_group; - ClutterActor *feedback_group; - - GList *windows; - - CoglContext *context; - - MetaWindowActor *top_window_actor; - gulong top_window_actor_destroy_id; - - int disable_unredirect_count; - - int switch_workspace_in_progress; - - MetaPluginManager *plugin_mgr; - - MetaLaters *laters; -} MetaCompositorPrivate; - -G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaCompositor, meta_compositor, - G_TYPE_OBJECT) - -static void -on_presented (ClutterStage *stage, - ClutterStageView *stage_view, - ClutterFrameInfo *frame_info, - MetaCompositor *compositor); - -static void -on_top_window_actor_destroyed (MetaWindowActor *window_actor, - MetaCompositor *compositor); - -static gboolean -is_modal (MetaDisplay *display) -{ - return display->event_route == META_EVENT_ROUTE_COMPOSITOR_GRAB; -} - -static void sync_actor_stacking (MetaCompositor *compositor); - -static void -meta_finish_workspace_switch (MetaCompositor *compositor) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - GList *l; - - /* Finish hiding and showing actors for the new workspace */ - for (l = priv->windows; l; l = l->next) - meta_window_actor_sync_visibility (l->data); - - /* Fix up stacking order. */ - sync_actor_stacking (compositor); -} - -void -meta_switch_workspace_completed (MetaCompositor *compositor) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - - /* FIXME -- must redo stacking order */ - priv->switch_workspace_in_progress--; - if (priv->switch_workspace_in_progress < 0) - { - g_warning ("Error in workspace_switch accounting!"); - priv->switch_workspace_in_progress = 0; - } - - if (!priv->switch_workspace_in_progress) - meta_finish_workspace_switch (compositor); -} - -void -meta_compositor_destroy (MetaCompositor *compositor) -{ - g_object_run_dispose (G_OBJECT (compositor)); - g_object_unref (compositor); -} - -/* compat helper */ -static MetaCompositor * -get_compositor_for_display (MetaDisplay *display) -{ - return display->compositor; -} - -/** - * meta_get_stage_for_display: - * @display: a #MetaDisplay - * - * Returns: (transfer none): The #ClutterStage for the display - */ -ClutterActor * -meta_get_stage_for_display (MetaDisplay *display) -{ - MetaCompositor *compositor; - MetaCompositorPrivate *priv; - - g_return_val_if_fail (display, NULL); - - compositor = get_compositor_for_display (display); - g_return_val_if_fail (compositor, NULL); - priv = meta_compositor_get_instance_private (compositor); - - return meta_backend_get_stage (priv->backend); -} - -/** - * meta_get_window_group_for_display: - * @display: a #MetaDisplay - * - * Returns: (transfer none): The window group corresponding to @display - */ -ClutterActor * -meta_get_window_group_for_display (MetaDisplay *display) -{ - MetaCompositor *compositor; - MetaCompositorPrivate *priv; - - g_return_val_if_fail (display, NULL); - - compositor = get_compositor_for_display (display); - g_return_val_if_fail (compositor, NULL); - priv = meta_compositor_get_instance_private (compositor); - - return priv->window_group; -} - -/** - * meta_get_top_window_group_for_display: - * @display: a #MetaDisplay - * - * Returns: (transfer none): The top window group corresponding to @display - */ -ClutterActor * -meta_get_top_window_group_for_display (MetaDisplay *display) -{ - MetaCompositor *compositor; - MetaCompositorPrivate *priv; - - g_return_val_if_fail (display, NULL); - - compositor = get_compositor_for_display (display); - g_return_val_if_fail (compositor, NULL); - priv = meta_compositor_get_instance_private (compositor); - - return priv->top_window_group; -} - -/** - * meta_get_feedback_group_for_display: - * @display: a #MetaDisplay - * - * Returns: (transfer none): The feedback group corresponding to @display - */ -ClutterActor * -meta_get_feedback_group_for_display (MetaDisplay *display) -{ - MetaCompositor *compositor; - MetaCompositorPrivate *priv; - - g_return_val_if_fail (display, NULL); - - compositor = get_compositor_for_display (display); - g_return_val_if_fail (compositor, NULL); - priv = meta_compositor_get_instance_private (compositor); - - return priv->feedback_group; -} - -/** - * meta_get_window_actors: - * @display: a #MetaDisplay - * - * Returns: (transfer none) (element-type Clutter.Actor): The set of #MetaWindowActor on @display - */ -GList * -meta_get_window_actors (MetaDisplay *display) -{ - MetaCompositor *compositor; - MetaCompositorPrivate *priv; - - g_return_val_if_fail (display, NULL); - - compositor = get_compositor_for_display (display); - g_return_val_if_fail (compositor, NULL); - priv = meta_compositor_get_instance_private (compositor); - - return priv->windows; -} - -void -meta_focus_stage_window (MetaDisplay *display, - guint32 timestamp) -{ - ClutterStage *stage; - Window window; - - stage = CLUTTER_STAGE (meta_get_stage_for_display (display)); - if (!stage) - return; - - window = meta_x11_get_stage_window (stage); - - if (window == None) - return; - - meta_x11_display_set_input_focus_xwindow (display->x11_display, - window, - timestamp); -} - -gboolean -meta_stage_is_focused (MetaDisplay *display) -{ - ClutterStage *stage; - Window window; - - if (meta_is_wayland_compositor ()) - return TRUE; - - stage = CLUTTER_STAGE (meta_get_stage_for_display (display)); - if (!stage) - return FALSE; - - window = meta_x11_get_stage_window (stage); - - if (window == None) - return FALSE; - - return (display->x11_display->focus_xwindow == window); -} - -static gboolean -grab_devices (MetaModalOptions options, - guint32 timestamp) -{ - MetaBackend *backend = META_BACKEND (meta_get_backend ()); - gboolean pointer_grabbed = FALSE; - gboolean keyboard_grabbed = FALSE; - - if ((options & META_MODAL_POINTER_ALREADY_GRABBED) == 0) - { - if (!meta_backend_grab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp)) - goto fail; - - pointer_grabbed = TRUE; - } - - if ((options & META_MODAL_KEYBOARD_ALREADY_GRABBED) == 0) - { - if (!meta_backend_grab_device (backend, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp)) - goto fail; - - keyboard_grabbed = TRUE; - } - - return TRUE; - - fail: - if (pointer_grabbed) - meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp); - if (keyboard_grabbed) - meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp); - - return FALSE; -} - -static void -meta_compositor_grab_begin (MetaCompositor *compositor) -{ - META_COMPOSITOR_GET_CLASS (compositor)->grab_begin (compositor); -} - -static void -meta_compositor_grab_end (MetaCompositor *compositor) -{ - META_COMPOSITOR_GET_CLASS (compositor)->grab_end (compositor); -} - -gboolean -meta_begin_modal_for_plugin (MetaCompositor *compositor, - MetaPlugin *plugin, - MetaModalOptions options, - guint32 timestamp) -{ - /* To some extent this duplicates code in meta_display_begin_grab_op(), but there - * are significant differences in how we handle grabs that make it difficult to - * merge the two. - */ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - MetaDisplay *display = priv->display; - -#ifdef HAVE_WAYLAND - if (display->grab_op == META_GRAB_OP_WAYLAND_POPUP) - { - MetaWaylandSeat *seat = meta_wayland_compositor_get_default ()->seat; - meta_wayland_pointer_end_popup_grab (seat->pointer); - } -#endif - - if (is_modal (display) || display->grab_op != META_GRAB_OP_NONE) - return FALSE; - - if (display->x11_display) - { - /* XXX: why is this needed? */ - XIUngrabDevice (display->x11_display->xdisplay, - META_VIRTUAL_CORE_POINTER_ID, - timestamp); - XSync (display->x11_display->xdisplay, False); - } - - if (!grab_devices (options, timestamp)) - return FALSE; - - display->grab_op = META_GRAB_OP_COMPOSITOR; - display->event_route = META_EVENT_ROUTE_COMPOSITOR_GRAB; - display->grab_window = NULL; - display->grab_have_pointer = TRUE; - display->grab_have_keyboard = TRUE; - - g_signal_emit_by_name (display, "grab-op-begin", - display->grab_window, display->grab_op); - - meta_compositor_grab_begin (compositor); - - return TRUE; -} - -void -meta_end_modal_for_plugin (MetaCompositor *compositor, - MetaPlugin *plugin, - guint32 timestamp) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - MetaDisplay *display = priv->display; - MetaBackend *backend = meta_get_backend (); - MetaWindow *grab_window = display->grab_window; - MetaGrabOp grab_op = display->grab_op; - - g_return_if_fail (is_modal (display)); - - display->grab_op = META_GRAB_OP_NONE; - display->event_route = META_EVENT_ROUTE_NORMAL; - display->grab_window = NULL; - display->grab_have_pointer = FALSE; - display->grab_have_keyboard = FALSE; - - meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp); - meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp); - - meta_compositor_grab_end (compositor); - - g_signal_emit_by_name (display, "grab-op-end", - grab_window, grab_op); -} - -static void -redirect_windows (MetaX11Display *x11_display) -{ - MetaBackend *backend = meta_get_backend (); - MetaContext *context = meta_backend_get_context (backend); - Display *xdisplay = meta_x11_display_get_xdisplay (x11_display); - Window xroot = meta_x11_display_get_xroot (x11_display); - int screen_number = meta_x11_display_get_screen_number (x11_display); - guint n_retries; - guint max_retries; - - if (meta_context_is_replacing (context)) - max_retries = 5; - else - max_retries = 1; - - n_retries = 0; - - /* Some compositors (like old versions of Mutter) might not properly unredirect - * subwindows before destroying the WM selection window; so we wait a while - * for such a compositor to exit before giving up. - */ - while (TRUE) - { - meta_x11_error_trap_push (x11_display); - XCompositeRedirectSubwindows (xdisplay, xroot, CompositeRedirectManual); - XSync (xdisplay, FALSE); - - if (!meta_x11_error_trap_pop_with_return (x11_display)) - break; - - if (n_retries == max_retries) - { - /* This probably means that a non-WM compositor like xcompmgr is running; - * we have no way to get it to exit */ - meta_fatal (_("Another compositing manager is already running on screen %i on display “%s”."), - screen_number, x11_display->name); - } - - n_retries++; - g_usleep (G_USEC_PER_SEC); - } -} - -void -meta_compositor_redirect_x11_windows (MetaCompositor *compositor) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - MetaDisplay *display = priv->display; - - if (display->x11_display) - redirect_windows (display->x11_display); -} - -gboolean -meta_compositor_do_manage (MetaCompositor *compositor, - GError **error) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - MetaDisplay *display = priv->display; - MetaBackend *backend = priv->backend; - ClutterActor *stage = meta_backend_get_stage (backend); - - priv->stage_presented_id = - g_signal_connect (stage, "presented", - G_CALLBACK (on_presented), - compositor); - - priv->window_group = meta_window_group_new (display); - priv->top_window_group = meta_window_group_new (display); - priv->feedback_group = meta_window_group_new (display); - - clutter_actor_add_child (stage, priv->window_group); - clutter_actor_add_child (stage, priv->top_window_group); - clutter_actor_add_child (stage, priv->feedback_group); - - if (!META_COMPOSITOR_GET_CLASS (compositor)->manage (compositor, error)) - return FALSE; - - priv->plugin_mgr = meta_plugin_manager_new (compositor); - - return TRUE; -} - -void -meta_compositor_manage (MetaCompositor *compositor) -{ - GError *error = NULL; - - if (!meta_compositor_do_manage (compositor, &error)) - g_error ("Compositor failed to manage display: %s", error->message); -} - -void -meta_compositor_unmanage (MetaCompositor *compositor) -{ - META_COMPOSITOR_GET_CLASS (compositor)->unmanage (compositor); -} - -void -meta_compositor_add_window (MetaCompositor *compositor, - MetaWindow *window) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - MetaWindowActor *window_actor; - ClutterActor *window_group; - GType window_actor_type = G_TYPE_INVALID; - - switch (window->client_type) - { - case META_WINDOW_CLIENT_TYPE_X11: - window_actor_type = META_TYPE_WINDOW_ACTOR_X11; - break; - -#ifdef HAVE_WAYLAND - case META_WINDOW_CLIENT_TYPE_WAYLAND: - window_actor_type = META_TYPE_WINDOW_ACTOR_WAYLAND; - break; -#endif - - default: - g_return_if_reached (); - } - - window_actor = g_object_new (window_actor_type, - "meta-window", window, - "show-on-set-parent", FALSE, - NULL); - - if (window->layer == META_LAYER_OVERRIDE_REDIRECT) - window_group = priv->top_window_group; - else - window_group = priv->window_group; - - clutter_actor_add_child (window_group, CLUTTER_ACTOR (window_actor)); - - /* Initial position in the stack is arbitrary; stacking will be synced - * before we first paint. - */ - priv->windows = g_list_append (priv->windows, window_actor); - sync_actor_stacking (compositor); -} - -static void -meta_compositor_real_remove_window (MetaCompositor *compositor, - MetaWindow *window) -{ - MetaWindowActor *window_actor = meta_window_actor_from_window (window); - - meta_window_actor_queue_destroy (window_actor); -} - -void -meta_compositor_remove_window (MetaCompositor *compositor, - MetaWindow *window) -{ - META_COMPOSITOR_GET_CLASS (compositor)->remove_window (compositor, window); -} - -void -meta_compositor_remove_window_actor (MetaCompositor *compositor, - MetaWindowActor *window_actor) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - - priv->windows = g_list_remove (priv->windows, window_actor); -} - -void -meta_compositor_sync_updates_frozen (MetaCompositor *compositor, - MetaWindow *window) -{ - MetaWindowActor *window_actor = meta_window_actor_from_window (window); - - meta_window_actor_sync_updates_frozen (window_actor); -} - -void -meta_compositor_queue_frame_drawn (MetaCompositor *compositor, - MetaWindow *window, - gboolean no_delay_frame) -{ - MetaWindowActor *window_actor = meta_window_actor_from_window (window); - - meta_window_actor_queue_frame_drawn (window_actor, no_delay_frame); -} - -void -meta_compositor_window_shape_changed (MetaCompositor *compositor, - MetaWindow *window) -{ - MetaWindowActor *window_actor; - - window_actor = meta_window_actor_from_window (window); - if (!window_actor) - return; - - meta_window_actor_x11_update_shape (META_WINDOW_ACTOR_X11 (window_actor)); -} - -void -meta_compositor_window_opacity_changed (MetaCompositor *compositor, - MetaWindow *window) -{ - MetaWindowActor *window_actor; - - window_actor = meta_window_actor_from_window (window); - if (!window_actor) - return; - - meta_window_actor_update_opacity (window_actor); -} - -gboolean -meta_compositor_filter_keybinding (MetaCompositor *compositor, - MetaKeyBinding *binding) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - - return meta_plugin_manager_filter_keybinding (priv->plugin_mgr, binding); -} - -void -meta_compositor_show_window (MetaCompositor *compositor, - MetaWindow *window, - MetaCompEffect effect) -{ - MetaWindowActor *window_actor = meta_window_actor_from_window (window); - - meta_window_actor_show (window_actor, effect); -} - -void -meta_compositor_hide_window (MetaCompositor *compositor, - MetaWindow *window, - MetaCompEffect effect) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - MetaWindowActor *window_actor = meta_window_actor_from_window (window); - - meta_window_actor_hide (window_actor, effect); - meta_stack_tracker_queue_sync_stack (priv->display->stack_tracker); -} - -void -meta_compositor_size_change_window (MetaCompositor *compositor, - MetaWindow *window, - MetaSizeChange which_change, - MetaRectangle *old_frame_rect, - MetaRectangle *old_buffer_rect) -{ - MetaWindowActor *window_actor = meta_window_actor_from_window (window); - - meta_window_actor_size_change (window_actor, which_change, old_frame_rect, old_buffer_rect); -} - -void -meta_compositor_switch_workspace (MetaCompositor *compositor, - MetaWorkspace *from, - MetaWorkspace *to, - MetaMotionDirection direction) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - gint to_indx, from_indx; - - to_indx = meta_workspace_index (to); - from_indx = meta_workspace_index (from); - - priv->switch_workspace_in_progress++; - - if (!meta_plugin_manager_switch_workspace (priv->plugin_mgr, - from_indx, - to_indx, - direction)) - { - priv->switch_workspace_in_progress--; - - /* We have to explicitly call this to fix up stacking order of the - * actors; this is because the abs stacking position of actors does not - * necessarily change during the window hiding/unhiding, only their - * relative position toward the destkop window. - */ - meta_finish_workspace_switch (compositor); - } -} - -static void -sync_actor_stacking (MetaCompositor *compositor) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - GList *children; - GList *expected_window_node; - GList *tmp; - GList *old; - GList *backgrounds; - gboolean has_windows; - gboolean reordered; - - /* NB: The first entries in the lists are stacked the lowest */ - - /* Restacking will trigger full screen redraws, so it's worth a - * little effort to make sure we actually need to restack before - * we go ahead and do it */ - - children = clutter_actor_get_children (priv->window_group); - has_windows = FALSE; - reordered = FALSE; - - /* We allow for actors in the window group other than the actors we - * know about, but it's up to a plugin to try and keep them stacked correctly - * (we really need extra API to make that reliable.) - */ - - /* First we collect a list of all backgrounds, and check if they're at the - * bottom. Then we check if the window actors are in the correct sequence */ - backgrounds = NULL; - expected_window_node = priv->windows; - for (old = children; old != NULL; old = old->next) - { - ClutterActor *actor = old->data; - - if (META_IS_BACKGROUND_GROUP (actor) || - META_IS_BACKGROUND_ACTOR (actor)) - { - backgrounds = g_list_prepend (backgrounds, actor); - - if (has_windows) - reordered = TRUE; - } - else if (META_IS_WINDOW_ACTOR (actor) && !reordered) - { - has_windows = TRUE; - - if (expected_window_node != NULL && actor == expected_window_node->data) - expected_window_node = expected_window_node->next; - else - reordered = TRUE; - } - } - - g_list_free (children); - - if (!reordered) - { - g_list_free (backgrounds); - return; - } - - /* reorder the actors by lowering them in turn to the bottom of the stack. - * windows first, then background. - * - * We reorder the actors even if they're not parented to the window group, - * to allow stacking to work with intermediate actors (eg during effects) - */ - for (tmp = g_list_last (priv->windows); tmp != NULL; tmp = tmp->prev) - { - ClutterActor *actor = tmp->data, *parent; - - parent = clutter_actor_get_parent (actor); - clutter_actor_set_child_below_sibling (parent, actor, NULL); - } - - /* we prepended the backgrounds above so the last actor in the list - * should get lowered to the bottom last. - */ - for (tmp = backgrounds; tmp != NULL; tmp = tmp->next) - { - ClutterActor *actor = tmp->data, *parent; - - parent = clutter_actor_get_parent (actor); - clutter_actor_set_child_below_sibling (parent, actor, NULL); - } - g_list_free (backgrounds); -} - -/* - * Find the top most window that is visible on the screen. The intention of - * this is to avoid offscreen windows that isn't actually part of the visible - * desktop (such as the UI frames override redirect window). - */ -static MetaWindowActor * -get_top_visible_window_actor (MetaCompositor *compositor) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - GList *l; - - for (l = g_list_last (priv->windows); l; l = l->prev) - { - MetaWindowActor *window_actor = l->data; - MetaWindow *window = meta_window_actor_get_meta_window (window_actor); - MetaRectangle buffer_rect; - MetaRectangle display_rect = { 0 }; - - if (!window->visible_to_compositor) - continue; - - meta_window_get_buffer_rect (window, &buffer_rect); - meta_display_get_size (priv->display, - &display_rect.width, &display_rect.height); - - if (meta_rectangle_overlap (&display_rect, &buffer_rect)) - return window_actor; - } - - return NULL; -} - -static void -on_top_window_actor_destroyed (MetaWindowActor *window_actor, - MetaCompositor *compositor) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - - priv->top_window_actor = NULL; - priv->top_window_actor_destroy_id = 0; - priv->windows = g_list_remove (priv->windows, window_actor); - - meta_stack_tracker_queue_sync_stack (priv->display->stack_tracker); -} - -void -meta_compositor_sync_stack (MetaCompositor *compositor, - GList *stack) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - MetaWindowActor *top_window_actor; - GList *old_stack; - - /* This is painful because hidden windows that we are in the process - * of animating out of existence. They'll be at the bottom of the - * stack of X windows, but we want to leave them in their old position - * until the animation effect finishes. - */ - - /* Sources: first window is the highest */ - stack = g_list_copy (stack); /* The new stack of MetaWindow */ - old_stack = g_list_reverse (priv->windows); /* The old stack of MetaWindowActor */ - priv->windows = NULL; - - while (TRUE) - { - MetaWindowActor *old_actor = NULL, *stack_actor = NULL, *actor; - MetaWindow *old_window = NULL, *stack_window = NULL, *window; - - /* Find the remaining top actor in our existing stack (ignoring - * windows that have been hidden and are no longer animating) */ - while (old_stack) - { - old_actor = old_stack->data; - old_window = meta_window_actor_get_meta_window (old_actor); - - if ((old_window->hidden || old_window->unmanaging) && - !meta_window_actor_effect_in_progress (old_actor)) - { - old_stack = g_list_delete_link (old_stack, old_stack); - old_actor = NULL; - } - else - break; - } - - /* And the remaining top actor in the new stack */ - while (stack) - { - stack_window = stack->data; - stack_actor = meta_window_actor_from_window (stack_window); - if (!stack_actor) - { - meta_verbose ("Failed to find corresponding MetaWindowActor " - "for window %s", meta_window_get_description (stack_window)); - stack = g_list_delete_link (stack, stack); - } - else - break; - } - - if (!old_actor && !stack_actor) /* Nothing more to stack */ - break; - - /* We usually prefer the window in the new stack, but if if we - * found a hidden window in the process of being animated out - * of existence in the old stack we use that instead. We've - * filtered out non-animating hidden windows above. - */ - if (old_actor && - (!stack_actor || old_window->hidden || old_window->unmanaging)) - { - actor = old_actor; - window = old_window; - } - else - { - actor = stack_actor; - window = stack_window; - } - - /* OK, we know what actor we want next. Add it to our window - * list, and remove it from both source lists. (It will - * be at the front of at least one, hopefully it will be - * near the front of the other.) - */ - priv->windows = g_list_prepend (priv->windows, actor); - - stack = g_list_remove (stack, window); - old_stack = g_list_remove (old_stack, actor); - } - - sync_actor_stacking (compositor); - - top_window_actor = get_top_visible_window_actor (compositor); - - if (priv->top_window_actor == top_window_actor) - return; - - g_clear_signal_handler (&priv->top_window_actor_destroy_id, - priv->top_window_actor); - - priv->top_window_actor = top_window_actor; - - if (priv->top_window_actor) - priv->top_window_actor_destroy_id = - g_signal_connect (priv->top_window_actor, "destroy", - G_CALLBACK (on_top_window_actor_destroyed), - compositor); -} - -void -meta_compositor_sync_window_geometry (MetaCompositor *compositor, - MetaWindow *window, - gboolean did_placement) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - MetaWindowActor *window_actor = meta_window_actor_from_window (window); - MetaWindowActorChanges changes; - - changes = meta_window_actor_sync_actor_geometry (window_actor, did_placement); - - if (changes & META_WINDOW_ACTOR_CHANGE_SIZE) - meta_plugin_manager_event_size_changed (priv->plugin_mgr, window_actor); -} - -static void -on_presented (ClutterStage *stage, - ClutterStageView *stage_view, - ClutterFrameInfo *frame_info, - MetaCompositor *compositor) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - int64_t presentation_time = frame_info->presentation_time; - GList *l; - - for (l = priv->windows; l; l = l->next) - { - ClutterActor *actor = l->data; - GList *actor_stage_views; - - actor_stage_views = clutter_actor_peek_stage_views (actor); - if (g_list_find (actor_stage_views, stage_view)) - { - meta_window_actor_frame_complete (META_WINDOW_ACTOR (actor), - frame_info, - presentation_time); - } - } -} - -static void -meta_compositor_real_before_paint (MetaCompositor *compositor, - ClutterStageView *stage_view) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - GList *l; - - for (l = priv->windows; l; l = l->next) - meta_window_actor_before_paint (l->data, stage_view); -} - -static void -meta_compositor_before_paint (MetaCompositor *compositor, - ClutterStageView *stage_view) -{ - COGL_TRACE_BEGIN_SCOPED (MetaCompositorPrePaint, - "Compositor (before-paint)"); - META_COMPOSITOR_GET_CLASS (compositor)->before_paint (compositor, stage_view); -} - -static void -meta_compositor_real_after_paint (MetaCompositor *compositor, - ClutterStageView *stage_view) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - ClutterActor *stage_actor = meta_backend_get_stage (priv->backend); - CoglGraphicsResetStatus status; - GList *l; - - status = cogl_get_graphics_reset_status (priv->context); - switch (status) - { - case COGL_GRAPHICS_RESET_STATUS_NO_ERROR: - break; - - case COGL_GRAPHICS_RESET_STATUS_PURGED_CONTEXT_RESET: - g_signal_emit_by_name (priv->display, "gl-video-memory-purged"); - g_signal_emit_by_name (stage_actor, "gl-video-memory-purged"); - clutter_actor_queue_redraw (stage_actor); - break; - - default: - /* The ARB_robustness spec says that, on error, the application - should destroy the old context and create a new one. Since we - don't have the necessary plumbing to do this we'll simply - restart the process. Obviously we can't do this when we are - a wayland compositor but in that case we shouldn't get here - since we don't enable robustness in that case. */ - g_assert (!meta_is_wayland_compositor ()); - meta_restart (NULL); - break; - } - - for (l = priv->windows; l; l = l->next) - { - ClutterActor *actor = l->data; - GList *actor_stage_views; - - actor_stage_views = clutter_actor_peek_stage_views (actor); - if (g_list_find (actor_stage_views, stage_view)) - meta_window_actor_after_paint (META_WINDOW_ACTOR (actor), stage_view); - } -} - -static void -meta_compositor_after_paint (MetaCompositor *compositor, - ClutterStageView *stage_view) -{ - COGL_TRACE_BEGIN_SCOPED (MetaCompositorPostPaint, - "Compositor (after-paint)"); - META_COMPOSITOR_GET_CLASS (compositor)->after_paint (compositor, stage_view); -} - -static void -on_before_paint (ClutterStage *stage, - ClutterStageView *stage_view, - MetaCompositor *compositor) -{ - meta_compositor_before_paint (compositor, stage_view); -} - -static void -on_after_paint (ClutterStage *stage, - ClutterStageView *stage_view, - MetaCompositor *compositor) -{ - meta_compositor_after_paint (compositor, stage_view); -} - -static void -meta_compositor_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaCompositor *compositor = META_COMPOSITOR (object); - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - - switch (prop_id) - { - case PROP_DISPLAY: - priv->display = g_value_get_object (value); - break; - case PROP_BACKEND: - priv->backend = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_compositor_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaCompositor *compositor = META_COMPOSITOR (object); - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - - switch (prop_id) - { - case PROP_DISPLAY: - g_value_set_object (value, priv->display); - break; - case PROP_BACKEND: - g_value_set_object (value, priv->backend); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_compositor_init (MetaCompositor *compositor) -{ -} - -static void -meta_compositor_constructed (GObject *object) -{ - MetaCompositor *compositor = META_COMPOSITOR (object); - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - ClutterBackend *clutter_backend = - meta_backend_get_clutter_backend (priv->backend); - ClutterActor *stage = meta_backend_get_stage (priv->backend); - - priv->context = clutter_backend->cogl_context; - - priv->before_paint_handler_id = - g_signal_connect (stage, - "before-paint", - G_CALLBACK (on_before_paint), - compositor); - priv->after_paint_handler_id = - g_signal_connect_after (stage, - "after-paint", - G_CALLBACK (on_after_paint), - compositor); - - priv->laters = meta_laters_new (compositor); - - G_OBJECT_CLASS (meta_compositor_parent_class)->constructed (object); -} - -static void -meta_compositor_dispose (GObject *object) -{ - MetaCompositor *compositor = META_COMPOSITOR (object); - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - ClutterActor *stage = meta_backend_get_stage (priv->backend); - - g_clear_pointer (&priv->laters, meta_laters_free); - - g_clear_signal_handler (&priv->stage_presented_id, stage); - g_clear_signal_handler (&priv->before_paint_handler_id, stage); - g_clear_signal_handler (&priv->after_paint_handler_id, stage); - - g_clear_signal_handler (&priv->top_window_actor_destroy_id, - priv->top_window_actor); - - g_clear_pointer (&priv->window_group, clutter_actor_destroy); - g_clear_pointer (&priv->top_window_group, clutter_actor_destroy); - g_clear_pointer (&priv->feedback_group, clutter_actor_destroy); - g_clear_pointer (&priv->windows, g_list_free); - - G_OBJECT_CLASS (meta_compositor_parent_class)->dispose (object); -} - -static void -meta_compositor_class_init (MetaCompositorClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->set_property = meta_compositor_set_property; - object_class->get_property = meta_compositor_get_property; - object_class->constructed = meta_compositor_constructed; - object_class->dispose = meta_compositor_dispose; - - klass->remove_window = meta_compositor_real_remove_window; - klass->before_paint = meta_compositor_real_before_paint; - klass->after_paint = meta_compositor_real_after_paint; - - obj_props[PROP_DISPLAY] = - g_param_spec_object ("display", - "display", - "MetaDisplay", - META_TYPE_DISPLAY, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - 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); - g_object_class_install_properties (object_class, N_PROPS, obj_props); -} - -/** - * meta_disable_unredirect_for_display: - * @display: a #MetaDisplay - * - * Disables unredirection, can be useful in situations where having - * unredirected windows is undesirable like when recording a video. - * - */ -void -meta_disable_unredirect_for_display (MetaDisplay *display) -{ - MetaCompositor *compositor; - MetaCompositorPrivate *priv; - - if (display->closing) - return; - - compositor = get_compositor_for_display (display); - priv = meta_compositor_get_instance_private (compositor); - - priv->disable_unredirect_count++; -} - -/** - * meta_enable_unredirect_for_display: - * @display: a #MetaDisplay - * - * Enables unredirection which reduces the overhead for apps like games. - * - */ -void -meta_enable_unredirect_for_display (MetaDisplay *display) -{ - MetaCompositor *compositor; - MetaCompositorPrivate *priv; - - if (display->closing) - return; - - compositor = get_compositor_for_display (display); - priv = meta_compositor_get_instance_private (compositor); - - if (priv->disable_unredirect_count == 0) - g_warning ("Called enable_unredirect_for_display while unredirection is enabled."); - if (priv->disable_unredirect_count > 0) - priv->disable_unredirect_count--; -} - -gboolean -meta_compositor_is_unredirect_inhibited (MetaCompositor *compositor) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - - return priv->disable_unredirect_count > 0; -} - -#define FLASH_TIME_MS 50 - -static void -flash_out_completed (ClutterTimeline *timeline, - gboolean is_finished, - gpointer user_data) -{ - ClutterActor *flash = CLUTTER_ACTOR (user_data); - clutter_actor_destroy (flash); -} - -void -meta_compositor_flash_display (MetaCompositor *compositor, - MetaDisplay *display) -{ - ClutterActor *stage; - ClutterActor *flash; - ClutterTransition *transition; - gfloat width, height; - - stage = meta_get_stage_for_display (display); - clutter_actor_get_size (stage, &width, &height); - - flash = clutter_actor_new (); - clutter_actor_set_background_color (flash, CLUTTER_COLOR_Black); - clutter_actor_set_size (flash, width, height); - clutter_actor_set_opacity (flash, 0); - clutter_actor_add_child (stage, flash); - - clutter_actor_save_easing_state (flash); - clutter_actor_set_easing_mode (flash, CLUTTER_EASE_IN_QUAD); - clutter_actor_set_easing_duration (flash, FLASH_TIME_MS); - clutter_actor_set_opacity (flash, 192); - - transition = clutter_actor_get_transition (flash, "opacity"); - clutter_timeline_set_auto_reverse (CLUTTER_TIMELINE (transition), TRUE); - clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (transition), 2); - - g_signal_connect (transition, "stopped", - G_CALLBACK (flash_out_completed), flash); - - clutter_actor_restore_easing_state (flash); -} - -static void -window_flash_out_completed (ClutterTimeline *timeline, - gboolean is_finished, - gpointer user_data) -{ - ClutterActor *flash = CLUTTER_ACTOR (user_data); - clutter_actor_destroy (flash); -} - -void -meta_compositor_flash_window (MetaCompositor *compositor, - MetaWindow *window) -{ - ClutterActor *window_actor = - CLUTTER_ACTOR (meta_window_actor_from_window (window)); - ClutterActor *flash; - ClutterTransition *transition; - - flash = clutter_actor_new (); - clutter_actor_set_background_color (flash, CLUTTER_COLOR_Black); - clutter_actor_set_size (flash, window->rect.width, window->rect.height); - clutter_actor_set_position (flash, - window->custom_frame_extents.left, - window->custom_frame_extents.top); - clutter_actor_set_opacity (flash, 0); - clutter_actor_add_child (window_actor, flash); - - clutter_actor_save_easing_state (flash); - clutter_actor_set_easing_mode (flash, CLUTTER_EASE_IN_QUAD); - clutter_actor_set_easing_duration (flash, FLASH_TIME_MS); - clutter_actor_set_opacity (flash, 192); - - transition = clutter_actor_get_transition (flash, "opacity"); - clutter_timeline_set_auto_reverse (CLUTTER_TIMELINE (transition), TRUE); - clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (transition), 2); - - g_signal_connect (transition, "stopped", - G_CALLBACK (window_flash_out_completed), flash); - - clutter_actor_restore_easing_state (flash); -} - -/** - * meta_compositor_monotonic_to_high_res_xserver_time: - * @display: a #MetaDisplay - * @monotonic_time: time in the units of g_get_monotonic_time() - * - * _NET_WM_FRAME_DRAWN and _NET_WM_FRAME_TIMINGS messages represent time - * as a "high resolution server time" - this is the server time interpolated - * to microsecond resolution. The advantage of this time representation - * is that if X server is running on the same computer as a client, and - * the Xserver uses 'clock_gettime(CLOCK_MONOTONIC, ...)' for the server - * time, the client can detect this, and all such clients will share a - * a time representation with high accuracy. If there is not a common - * time source, then the time synchronization will be less accurate. - */ -int64_t -meta_compositor_monotonic_to_high_res_xserver_time (MetaCompositor *compositor, - int64_t monotonic_time_us) -{ - MetaCompositorClass *klass = META_COMPOSITOR_GET_CLASS (compositor); - - return klass->monotonic_to_high_res_xserver_time (compositor, monotonic_time_us); -} - -void -meta_compositor_show_tile_preview (MetaCompositor *compositor, - MetaWindow *window, - MetaRectangle *tile_rect, - int tile_monitor_number) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - - meta_plugin_manager_show_tile_preview (priv->plugin_mgr, - window, tile_rect, tile_monitor_number); -} - -void -meta_compositor_hide_tile_preview (MetaCompositor *compositor) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - - meta_plugin_manager_hide_tile_preview (priv->plugin_mgr); -} - -void -meta_compositor_show_window_menu (MetaCompositor *compositor, - MetaWindow *window, - MetaWindowMenuType menu, - int x, - int y) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - - meta_plugin_manager_show_window_menu (priv->plugin_mgr, window, menu, x, y); -} - -void -meta_compositor_show_window_menu_for_rect (MetaCompositor *compositor, - MetaWindow *window, - MetaWindowMenuType menu, - MetaRectangle *rect) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - - meta_plugin_manager_show_window_menu_for_rect (priv->plugin_mgr, window, menu, rect); -} - -MetaCloseDialog * -meta_compositor_create_close_dialog (MetaCompositor *compositor, - MetaWindow *window) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - - return meta_plugin_manager_create_close_dialog (priv->plugin_mgr, - window); -} - -MetaInhibitShortcutsDialog * -meta_compositor_create_inhibit_shortcuts_dialog (MetaCompositor *compositor, - MetaWindow *window) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - - return meta_plugin_manager_create_inhibit_shortcuts_dialog (priv->plugin_mgr, - window); -} - -void -meta_compositor_locate_pointer (MetaCompositor *compositor) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - - meta_plugin_manager_locate_pointer (priv->plugin_mgr); -} - -MetaPluginManager * -meta_compositor_get_plugin_manager (MetaCompositor *compositor) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - - return priv->plugin_mgr; -} - -MetaDisplay * -meta_compositor_get_display (MetaCompositor *compositor) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - - return priv->display; -} - -ClutterStage * -meta_compositor_get_stage (MetaCompositor *compositor) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - - return CLUTTER_STAGE (meta_backend_get_stage (priv->backend)); -} - -MetaWindowActor * -meta_compositor_get_top_window_actor (MetaCompositor *compositor) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - - return priv->top_window_actor; -} - -gboolean -meta_compositor_is_switching_workspace (MetaCompositor *compositor) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - - return priv->switch_workspace_in_progress > 0; -} - -MetaLaters * -meta_compositor_get_laters (MetaCompositor *compositor) -{ - MetaCompositorPrivate *priv = - meta_compositor_get_instance_private (compositor); - - return priv->laters; -} diff --git a/src/compositor/meta-background-actor-private.h b/src/compositor/meta-background-actor-private.h deleted file mode 100644 index bdf8c4744..000000000 --- a/src/compositor/meta-background-actor-private.h +++ /dev/null @@ -1,10 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -#ifndef META_BACKGROUND_ACTOR_PRIVATE_H -#define META_BACKGROUND_ACTOR_PRIVATE_H - -#include "meta/meta-background-actor.h" - -cairo_region_t *meta_background_actor_get_clip_region (MetaBackgroundActor *self); - -#endif /* META_BACKGROUND_ACTOR_PRIVATE_H */ diff --git a/src/compositor/meta-background-actor.c b/src/compositor/meta-background-actor.c deleted file mode 100644 index 105f94259..000000000 --- a/src/compositor/meta-background-actor.c +++ /dev/null @@ -1,218 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * Copyright 2009 Sander Dijkhuis - * Copyright 2014 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 . - * - * Portions adapted from gnome-shell/src/shell-global.c - */ - -#include "config.h" - -#include "compositor/meta-background-actor-private.h" -#include "compositor/meta-background-content-private.h" - -#include "compositor/meta-cullable.h" - -enum -{ - PROP_META_DISPLAY = 1, - PROP_MONITOR, -}; - -struct _MetaBackgroundActor -{ - ClutterActor parent; - - MetaDisplay *display; - int monitor; - - MetaBackgroundContent *content; -}; - -static void cullable_iface_init (MetaCullableInterface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaBackgroundActor, meta_background_actor, CLUTTER_TYPE_ACTOR, - G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init)); - -static void -maybe_create_content (MetaBackgroundActor *self) -{ - g_autoptr (ClutterContent) content = NULL; - - if (self->content || !self->display || self->monitor == -1) - return; - - content = meta_background_content_new (self->display, self->monitor); - self->content = META_BACKGROUND_CONTENT (content); - clutter_actor_set_content (CLUTTER_ACTOR (self), content); -} - -static void -meta_background_actor_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaBackgroundActor *self = META_BACKGROUND_ACTOR (object); - - switch (prop_id) - { - case PROP_META_DISPLAY: - self->display = g_value_get_object (value); - maybe_create_content (self); - break; - case PROP_MONITOR: - self->monitor = g_value_get_int (value); - maybe_create_content (self); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_background_actor_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaBackgroundActor *self = META_BACKGROUND_ACTOR (object); - - switch (prop_id) - { - case PROP_META_DISPLAY: - g_value_set_object (value, self->display); - break; - case PROP_MONITOR: - g_value_set_int (value, self->monitor); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_background_actor_class_init (MetaBackgroundActorClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GParamSpec *param_spec; - - object_class->set_property = meta_background_actor_set_property; - object_class->get_property = meta_background_actor_get_property; - - param_spec = g_param_spec_object ("meta-display", - "MetaDisplay", - "MetaDisplay", - META_TYPE_DISPLAY, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - - g_object_class_install_property (object_class, - PROP_META_DISPLAY, - param_spec); - - param_spec = g_param_spec_int ("monitor", - "monitor", - "monitor", - 0, G_MAXINT, 0, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - - g_object_class_install_property (object_class, - PROP_MONITOR, - param_spec); -} - -static void -meta_background_actor_init (MetaBackgroundActor *self) -{ - self->monitor = -1; - - clutter_actor_set_request_mode (CLUTTER_ACTOR (self), - CLUTTER_REQUEST_CONTENT_SIZE); -} - -/** - * meta_background_actor_new: - * @monitor: Index of the monitor for which to draw the background - * - * Creates a new actor to draw the background for the given monitor. - * - * Return value: the newly created background actor - */ -ClutterActor * -meta_background_actor_new (MetaDisplay *display, - int monitor) -{ - MetaBackgroundActor *self; - - self = g_object_new (META_TYPE_BACKGROUND_ACTOR, - "meta-display", display, - "monitor", monitor, - NULL); - - return CLUTTER_ACTOR (self); -} - -static void -meta_background_actor_cull_out (MetaCullable *cullable, - cairo_region_t *unobscured_region, - cairo_region_t *clip_region) -{ - MetaBackgroundActor *self = META_BACKGROUND_ACTOR (cullable); - - if (!self->content) - return; - - meta_background_content_cull_out (self->content, - unobscured_region, - clip_region); -} - -static void -meta_background_actor_reset_culling (MetaCullable *cullable) -{ - MetaBackgroundActor *self = META_BACKGROUND_ACTOR (cullable); - - if (!self->content) - return; - - meta_background_content_reset_culling (self->content); -} - -static void -cullable_iface_init (MetaCullableInterface *iface) -{ - iface->cull_out = meta_background_actor_cull_out; - iface->reset_culling = meta_background_actor_reset_culling; -} - -/** - * meta_background_actor_get_clip_region: - * @self: a #MetaBackgroundActor - * - * Return value (transfer none): a #cairo_region_t that represents the part of - * the background not obscured by other #MetaBackgroundActor or - * #MetaWindowActor objects. - */ -cairo_region_t * -meta_background_actor_get_clip_region (MetaBackgroundActor *self) -{ - if (!self->content) - return NULL; - - return meta_background_content_get_clip_region (self->content); -} diff --git a/src/compositor/meta-background-content-private.h b/src/compositor/meta-background-content-private.h deleted file mode 100644 index 284cddb3a..000000000 --- a/src/compositor/meta-background-content-private.h +++ /dev/null @@ -1,16 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -#ifndef META_BACKGROUND_CONTENT_PRIVATE_H -#define META_BACKGROUND_CONTENT_PRIVATE_H - -#include "meta/meta-background-content.h" - -cairo_region_t *meta_background_content_get_clip_region (MetaBackgroundContent *self); - -void meta_background_content_cull_out (MetaBackgroundContent *self, - cairo_region_t *unobscured_region, - cairo_region_t *clip_region); - -void meta_background_content_reset_culling (MetaBackgroundContent *self); - -#endif /* META_BACKGROUND_CONTENT_PRIVATE_H */ diff --git a/src/compositor/meta-background-content.c b/src/compositor/meta-background-content.c deleted file mode 100644 index 86f777752..000000000 --- a/src/compositor/meta-background-content.c +++ /dev/null @@ -1,1312 +0,0 @@ -/* - * Copyright 2009 Sander Dijkhuis - * Copyright 2014 Red Hat, Inc. - * Copyright 2020 Endless Foundation. - * - * 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 . - * - * Portions adapted from gnome-shell/src/shell-global.c - */ - - -/** - * SECTION:meta-background-content - * @title: MetaBackgroundContent - * @short_description: ClutterContent for painting the root window background - * - */ - -/* - * The overall model drawing model of this content is that we have one - * texture, or two interpolated textures, possibly with alpha or - * margins that let the underlying background show through, blended - * over a solid color or a gradient. The result of that combination - * can then be affected by a "vignette" that darkens the background - * away from a central point (or as a no-GLSL fallback, simply darkens - * the background) and by overall opacity. - * - * As of GNOME 3.14, GNOME is only using a fraction of this when the - * user sets the background through the control center - what can be - * set is: - * - * A single image without a border - * An animation of images without a border that blend together, - * with the blend changing every 4-5 minutes - * A solid color with a repeated noise texture blended over it - * - * This all is pretty easy to do in a fragment shader, except when: - * - * A) We don't have GLSL - in this case, the operation of - * interpolating the two textures and blending the result over the - * background can't be expressed with Cogl's fixed-function layer - * combining (which is confined to what GL's texture environment - * combining can do) So we can only handle the above directly if - * there are no margins or alpha. - * - * B) The image textures are sliced. Texture size limits on older - * hardware (pre-965 intel hardware, r300, etc.) is often 2048, - * and it would be common to use a texture larger than this for a - * background and expect it to be scaled down. Cogl can compensate - * for this by breaking the texture up into multiple textures, but - * can't multitexture with sliced textures. So we can only handle - * the above if there's a single texture. - * - * However, even when we *can* represent everything in a single pass, - * it's not necessarily efficient. If we want to draw a 1024x768 - * background, it's pretty inefficient to bilinearly texture from - * two 2560x1440 images and mix that. So the drawing model we take - * here is that MetaBackground generates a single texture (which - * might be a 1x1 texture for a solid color, or a 1x2 texture for a - * gradient, or a repeated texture for wallpaper, or a pre-rendered - * texture the size of the screen), and we draw with that, possibly - * adding the vignette and opacity. - */ - -#include "config.h" - -#include "compositor/meta-background-content-private.h" - -#include "backends/meta-backend-private.h" -#include "clutter/clutter.h" -#include "compositor/clutter-utils.h" -#include "compositor/cogl-utils.h" -#include "compositor/meta-background-private.h" -#include "compositor/meta-cullable.h" -#include "meta/display.h" - -typedef enum -{ - CHANGED_BACKGROUND = 1 << 0, - CHANGED_EFFECTS = 1 << 2, - CHANGED_VIGNETTE_PARAMETERS = 1 << 3, - CHANGED_GRADIENT_PARAMETERS = 1 << 4, - CHANGED_ROUNDED_CLIP_PARAMETERS = 1 << 5, - CHANGED_ALL = 0xFFFF -} ChangedFlags; - -#define GRADIENT_VERTEX_SHADER_DECLARATIONS \ -"uniform vec2 scale;\n" \ -"varying vec2 position;\n" \ - -#define GRADIENT_VERTEX_SHADER_CODE \ -"position = cogl_tex_coord0_in.xy * scale;\n" \ - -#define GRADIENT_FRAGMENT_SHADER_DECLARATIONS \ -"uniform float gradient_height_perc;\n" \ -"uniform float gradient_max_darkness;\n" \ -"varying vec2 position;\n" \ - -#define GRADIENT_FRAGMENT_SHADER_CODE \ -"float min_brightness = 1.0 - gradient_max_darkness;\n" \ -"float gradient_y_pos = min(position.y, gradient_height_perc) / gradient_height_perc;\n" \ -"float pixel_brightness = (1.0 - min_brightness) * gradient_y_pos + min_brightness;\n" \ -"cogl_color_out.rgb = cogl_color_out.rgb * pixel_brightness;\n" \ - -#define VIGNETTE_VERTEX_SHADER_DECLARATIONS \ -"uniform vec2 scale;\n" \ -"uniform vec2 offset;\n" \ -"varying vec2 position;\n" \ - -#define VIGNETTE_VERTEX_SHADER_CODE \ -"position = cogl_tex_coord0_in.xy * scale + offset;\n" \ - -#define VIGNETTE_SQRT_2 "1.4142" - -#define VIGNETTE_FRAGMENT_SHADER_DECLARATIONS \ -"uniform float vignette_sharpness;\n" \ -"varying vec2 position;\n" \ -"float rand(vec2 p) { return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453123); }\n" \ - -#define VIGNETTE_FRAGMENT_SHADER_CODE \ -"float t = " VIGNETTE_SQRT_2 " * length(position);\n" \ -"t = min(t, 1.0);\n" \ -"float pixel_brightness = 1.0 - t * vignette_sharpness;\n" \ -"cogl_color_out.rgb = cogl_color_out.rgb * pixel_brightness;\n" \ -"cogl_color_out.rgb += (rand(position) - 0.5) / 255.0;\n" \ - -/* The ellipsis_dist(), ellipsis_coverage() and rounded_rect_coverage() are - * copied from GSK, see gsk_ellipsis_dist(), gsk_ellipsis_coverage(), and - * gsk_rounded_rect_coverage() here: - * https://gitlab.gnome.org/GNOME/gtk/-/blob/4.3.1/gsk/gl/resources/preamble.fs.glsl - */ -#define ROUNDED_CLIP_FRAGMENT_SHADER_DECLARATIONS \ -"uniform vec4 bounds; // x, y: top left; w, v: bottom right \n"\ -"uniform vec4 corner_centers_1; // x, y: top left; w, v: top right \n"\ -"uniform vec4 corner_centers_2; // x, y: bottom right; w, v: bottom left \n"\ -"uniform vec2 pixel_step; \n"\ -" \n"\ -"float \n"\ -"ellipsis_dist (vec2 p, vec2 radius) \n"\ -"{ \n"\ -" if (radius == vec2(0, 0)) \n"\ -" return 0.0; \n"\ -" \n"\ -" vec2 p0 = p / radius; \n"\ -" vec2 p1 = (2.0 * p0) / radius; \n"\ -" \n"\ -" return (dot(p0, p0) - 1.0) / length (p1); \n"\ -"} \n"\ -" \n"\ -"float \n"\ -"ellipsis_coverage (vec2 point, vec2 center, vec2 radius) \n"\ -"{ \n"\ -" float d = ellipsis_dist ((point - center), radius); \n"\ -" return clamp (0.5 - d, 0.0, 1.0); \n"\ -"} \n"\ -" \n"\ -"float \n"\ -"rounded_rect_coverage (vec4 bounds, \n"\ -" vec4 corner_centers_1, \n"\ -" vec4 corner_centers_2, \n"\ -" vec2 p) \n"\ -"{ \n"\ -" if (p.x < bounds.x || p.y < bounds.y || \n"\ -" p.x >= bounds.z || p.y >= bounds.w) \n"\ -" return 0.0; \n"\ -" \n"\ -" vec2 ref_tl = corner_centers_1.xy; \n"\ -" vec2 ref_tr = corner_centers_1.zw; \n"\ -" vec2 ref_br = corner_centers_2.xy; \n"\ -" vec2 ref_bl = corner_centers_2.zw; \n"\ -" \n"\ -" if (p.x >= ref_tl.x && p.x >= ref_bl.x && \n"\ -" p.x <= ref_tr.x && p.x <= ref_br.x) \n"\ -" return 1.0; \n"\ -" \n"\ -" if (p.y >= ref_tl.y && p.y >= ref_tr.y && \n"\ -" p.y <= ref_bl.y && p.y <= ref_br.y) \n"\ -" return 1.0; \n"\ -" \n"\ -" vec2 rad_tl = corner_centers_1.xy - bounds.xy; \n"\ -" vec2 rad_tr = corner_centers_1.zw - bounds.zy; \n"\ -" vec2 rad_br = corner_centers_2.xy - bounds.zw; \n"\ -" vec2 rad_bl = corner_centers_2.zw - bounds.xw; \n"\ -" \n"\ -" float d_tl = ellipsis_coverage(p, ref_tl, rad_tl); \n"\ -" float d_tr = ellipsis_coverage(p, ref_tr, rad_tr); \n"\ -" float d_br = ellipsis_coverage(p, ref_br, rad_br); \n"\ -" float d_bl = ellipsis_coverage(p, ref_bl, rad_bl); \n"\ -" \n"\ -" vec4 corner_coverages = 1.0 - vec4(d_tl, d_tr, d_br, d_bl); \n"\ -" \n"\ -" bvec4 is_out = bvec4(p.x < ref_tl.x && p.y < ref_tl.y, \n"\ -" p.x > ref_tr.x && p.y < ref_tr.y, \n"\ -" p.x > ref_br.x && p.y > ref_br.y, \n"\ -" p.x < ref_bl.x && p.y > ref_bl.y); \n"\ -" \n"\ -" return 1.0 - dot(vec4(is_out), corner_coverages); \n"\ -"} \n" - -#define ROUNDED_CLIP_FRAGMENT_SHADER_CODE \ -"vec2 texture_coord; \n"\ -" \n"\ -"texture_coord = cogl_tex_coord0_in.xy / pixel_step; \n"\ -" \n"\ -"cogl_color_out *= rounded_rect_coverage (bounds, \n"\ -" corner_centers_1, \n"\ -" corner_centers_2, \n"\ -" texture_coord); \n" - -typedef struct _MetaBackgroundLayer MetaBackgroundLayer; - -typedef enum -{ - PIPELINE_VIGNETTE = (1 << 0), - PIPELINE_BLEND = (1 << 1), - PIPELINE_GRADIENT = (1 << 2), - PIPELINE_ROUNDED_CLIP = (1 << 3), - - PIPELINE_ALL = (PIPELINE_VIGNETTE | - PIPELINE_BLEND | - PIPELINE_GRADIENT | - PIPELINE_ROUNDED_CLIP) -} PipelineFlags; - -struct _MetaBackgroundContent -{ - GObject parent; - - MetaDisplay *display; - int monitor; - - MetaBackground *background; - - gboolean gradient; - double gradient_max_darkness; - int gradient_height; - - gboolean vignette; - double vignette_brightness; - double vignette_sharpness; - - gboolean has_rounded_clip; - float rounded_clip_radius; - gboolean rounded_clip_bounds_set; - graphene_rect_t rounded_clip_bounds; - - ChangedFlags changed; - CoglPipeline *pipeline; - PipelineFlags pipeline_flags; - cairo_rectangle_int_t texture_area; - int texture_width, texture_height; - - cairo_region_t *clip_region; - cairo_region_t *unobscured_region; -}; - -static void clutter_content_iface_init (ClutterContentInterface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaBackgroundContent, - meta_background_content, - G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTENT, - clutter_content_iface_init)); - -enum -{ - PROP_0, - PROP_META_DISPLAY, - PROP_MONITOR, - PROP_BACKGROUND, - PROP_GRADIENT, - PROP_GRADIENT_HEIGHT, - PROP_GRADIENT_MAX_DARKNESS, - PROP_VIGNETTE, - PROP_VIGNETTE_SHARPNESS, - PROP_VIGNETTE_BRIGHTNESS, - PROP_ROUNDED_CLIP_RADIUS, - N_PROPS, -}; - -static GParamSpec *properties[N_PROPS] = { NULL, }; - -static void -set_clip_region (MetaBackgroundContent *self, - cairo_region_t *clip_region) -{ - g_clear_pointer (&self->clip_region, cairo_region_destroy); - if (clip_region) - { - if (cairo_region_is_empty (clip_region)) - self->clip_region = cairo_region_reference (clip_region); - else - self->clip_region = cairo_region_copy (clip_region); - } -} - -static void -set_unobscured_region (MetaBackgroundContent *self, - cairo_region_t *unobscured_region) -{ - g_clear_pointer (&self->unobscured_region, cairo_region_destroy); - if (unobscured_region) - { - if (cairo_region_is_empty (unobscured_region)) - self->unobscured_region = cairo_region_reference (unobscured_region); - else - self->unobscured_region = cairo_region_copy (unobscured_region); - } -} - -static void -invalidate_pipeline (MetaBackgroundContent *self, - ChangedFlags changed) -{ - self->changed |= changed; -} - -static void -on_background_changed (MetaBackground *background, - MetaBackgroundContent *self) -{ - invalidate_pipeline (self, CHANGED_BACKGROUND); - clutter_content_invalidate (CLUTTER_CONTENT (self)); -} - -static CoglPipeline * -make_pipeline (PipelineFlags pipeline_flags) -{ - static CoglPipeline *templates[PIPELINE_ALL + 1]; - CoglPipeline **templatep; - - g_assert (pipeline_flags < G_N_ELEMENTS (templates)); - - templatep = &templates[pipeline_flags]; - if (*templatep == NULL) - { - /* Cogl automatically caches pipelines with no eviction policy, - * so we need to prevent identical pipelines from getting cached - * separately, by reusing the same shader snippets. - */ - *templatep = COGL_PIPELINE (meta_create_texture_pipeline (NULL)); - - if ((pipeline_flags & PIPELINE_VIGNETTE) != 0) - { - static CoglSnippet *vignette_vertex_snippet; - static CoglSnippet *vignette_fragment_snippet; - - if (!vignette_vertex_snippet) - vignette_vertex_snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX, - VIGNETTE_VERTEX_SHADER_DECLARATIONS, - VIGNETTE_VERTEX_SHADER_CODE); - - cogl_pipeline_add_snippet (*templatep, vignette_vertex_snippet); - - if (!vignette_fragment_snippet) - vignette_fragment_snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, - VIGNETTE_FRAGMENT_SHADER_DECLARATIONS, - VIGNETTE_FRAGMENT_SHADER_CODE); - - cogl_pipeline_add_snippet (*templatep, vignette_fragment_snippet); - } - - if ((pipeline_flags & PIPELINE_GRADIENT) != 0) - { - static CoglSnippet *gradient_vertex_snippet; - static CoglSnippet *gradient_fragment_snippet; - - if (!gradient_vertex_snippet) - gradient_vertex_snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX, - GRADIENT_VERTEX_SHADER_DECLARATIONS, - GRADIENT_VERTEX_SHADER_CODE); - - cogl_pipeline_add_snippet (*templatep, gradient_vertex_snippet); - - if (!gradient_fragment_snippet) - gradient_fragment_snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, - GRADIENT_FRAGMENT_SHADER_DECLARATIONS, - GRADIENT_FRAGMENT_SHADER_CODE); - - cogl_pipeline_add_snippet (*templatep, gradient_fragment_snippet); - } - - if ((pipeline_flags & PIPELINE_ROUNDED_CLIP) != 0) - { - static CoglSnippet *rounded_clip_fragment_snippet; - - if (!rounded_clip_fragment_snippet) - { - rounded_clip_fragment_snippet = - cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, - ROUNDED_CLIP_FRAGMENT_SHADER_DECLARATIONS, - ROUNDED_CLIP_FRAGMENT_SHADER_CODE); - } - - cogl_pipeline_add_snippet (*templatep, rounded_clip_fragment_snippet); - } - - - if ((pipeline_flags & PIPELINE_BLEND) == 0) - cogl_pipeline_set_blend (*templatep, "RGBA = ADD (SRC_COLOR, 0)", NULL); - } - - return cogl_pipeline_copy (*templatep); -} - -static void -setup_pipeline (MetaBackgroundContent *self, - ClutterActor *actor, - ClutterPaintContext *paint_context, - cairo_rectangle_int_t *actor_pixel_rect) -{ - PipelineFlags pipeline_flags = 0; - guint8 opacity; - float color_component; - CoglFramebuffer *fb; - CoglPipelineFilter min_filter, mag_filter; - - opacity = clutter_actor_get_paint_opacity (actor); - if (opacity < 255) - pipeline_flags |= PIPELINE_BLEND; - if (self->vignette && clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) - pipeline_flags |= PIPELINE_VIGNETTE; - if (self->gradient && clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) - pipeline_flags |= PIPELINE_GRADIENT; - if (self->has_rounded_clip && clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) - pipeline_flags |= PIPELINE_ROUNDED_CLIP | PIPELINE_BLEND; - - if (pipeline_flags != self->pipeline_flags) - g_clear_pointer (&self->pipeline, cogl_object_unref); - - if (self->pipeline == NULL) - { - self->pipeline_flags = pipeline_flags; - self->pipeline = make_pipeline (pipeline_flags); - self->changed = CHANGED_ALL; - } - - if (self->changed & CHANGED_BACKGROUND) - { - CoglPipelineWrapMode wrap_mode; - CoglTexture *texture = meta_background_get_texture (self->background, - self->monitor, - &self->texture_area, - &wrap_mode); - - if (texture) - { - self->texture_width = cogl_texture_get_width (texture); - self->texture_height = cogl_texture_get_height (texture); - } - else - { - self->texture_width = 0; - self->texture_height = 0; - } - - cogl_pipeline_set_layer_texture (self->pipeline, 0, texture); - cogl_pipeline_set_layer_wrap_mode (self->pipeline, 0, wrap_mode); - - self->changed &= ~CHANGED_BACKGROUND; - } - - if (self->changed & CHANGED_VIGNETTE_PARAMETERS) - { - cogl_pipeline_set_uniform_1f (self->pipeline, - cogl_pipeline_get_uniform_location (self->pipeline, - "vignette_sharpness"), - self->vignette_sharpness); - - self->changed &= ~CHANGED_VIGNETTE_PARAMETERS; - } - - if (self->changed & CHANGED_GRADIENT_PARAMETERS) - { - MetaRectangle monitor_geometry; - float gradient_height_perc; - - meta_display_get_monitor_geometry (self->display, - self->monitor, &monitor_geometry); - gradient_height_perc = MAX (0.0001, self->gradient_height / (float)monitor_geometry.height); - cogl_pipeline_set_uniform_1f (self->pipeline, - cogl_pipeline_get_uniform_location (self->pipeline, - "gradient_height_perc"), - gradient_height_perc); - cogl_pipeline_set_uniform_1f (self->pipeline, - cogl_pipeline_get_uniform_location (self->pipeline, - "gradient_max_darkness"), - self->gradient_max_darkness); - - self->changed &= ~CHANGED_GRADIENT_PARAMETERS; - } - - if (self->changed & CHANGED_ROUNDED_CLIP_PARAMETERS) - { - float monitor_scale; - float bounds_x1, bounds_x2, bounds_y1, bounds_y2; - float clip_radius; - - monitor_scale = meta_is_stage_views_scaled () - ? meta_display_get_monitor_scale (self->display, self->monitor) - : 1.0; - - if (self->rounded_clip_bounds_set) - { - bounds_x1 = self->rounded_clip_bounds.origin.x; - bounds_x2 = self->rounded_clip_bounds.origin.x + self->rounded_clip_bounds.size.width; - bounds_y1 = self->rounded_clip_bounds.origin.y; - bounds_y2 = self->rounded_clip_bounds.origin.y + self->rounded_clip_bounds.size.height; - - bounds_x1 *= monitor_scale; - bounds_x2 *= monitor_scale; - bounds_y1 *= monitor_scale; - bounds_y2 *= monitor_scale; - } - else - { - bounds_x1 = 0.0; - bounds_x2 = self->texture_width; - bounds_y1 = 0.0; - bounds_y2 = self->texture_height; - } - - clip_radius = self->rounded_clip_radius * monitor_scale; - - float bounds[] = { - bounds_x1, - bounds_y1, - bounds_x2, - bounds_y2, - }; - - float corner_centers_1[] = { - bounds_x1 + clip_radius, - bounds_y1 + clip_radius, - bounds_x2 - clip_radius, - bounds_y1 + clip_radius, - }; - - float corner_centers_2[] = { - bounds_x2 - clip_radius, - bounds_y2 - clip_radius, - bounds_x1 + clip_radius, - bounds_y2 - clip_radius, - }; - - int bounds_uniform_location; - int corner_centers_1_uniform_location; - int corner_centers_2_uniform_location; - - bounds_uniform_location = - cogl_pipeline_get_uniform_location (self->pipeline, "bounds"); - corner_centers_1_uniform_location = - cogl_pipeline_get_uniform_location (self->pipeline, "corner_centers_1"); - corner_centers_2_uniform_location = - cogl_pipeline_get_uniform_location (self->pipeline, "corner_centers_2"); - - cogl_pipeline_set_uniform_float (self->pipeline, - bounds_uniform_location, - 4, 1, - bounds); - - cogl_pipeline_set_uniform_float (self->pipeline, - corner_centers_1_uniform_location, - 4, 1, - corner_centers_1); - - cogl_pipeline_set_uniform_float (self->pipeline, - corner_centers_2_uniform_location, - 4, 1, - corner_centers_2); - - self->changed &= ~CHANGED_ROUNDED_CLIP_PARAMETERS; - } - - if (self->vignette) - { - color_component = self->vignette_brightness * opacity / 255.; - - if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) - { - /* Darken everything to match the average brightness that would - * be there if we were drawing the vignette, which is - * (1 - (pi/12.) * vignette_sharpness) [exercise for the reader :] - */ - color_component *= (1 - 0.74 * self->vignette_sharpness); - } - } - else - { - color_component = opacity / 255.; - } - - cogl_pipeline_set_color4f (self->pipeline, - color_component, - color_component, - color_component, - opacity / 255.); - - fb = clutter_paint_context_get_framebuffer (paint_context); - if (meta_actor_painting_untransformed (fb, - actor_pixel_rect->width, - actor_pixel_rect->height, - self->texture_width, - self->texture_height, - NULL, NULL)) - { - min_filter = COGL_PIPELINE_FILTER_NEAREST; - mag_filter = COGL_PIPELINE_FILTER_NEAREST; - } - else - { - min_filter = COGL_PIPELINE_FILTER_LINEAR_MIPMAP_NEAREST; - mag_filter = COGL_PIPELINE_FILTER_LINEAR; - } - - cogl_pipeline_set_layer_filters (self->pipeline, 0, min_filter, mag_filter); -} - -static void -set_glsl_parameters (MetaBackgroundContent *self, - cairo_rectangle_int_t *actor_pixel_rect) -{ - float monitor_scale; - float scale[2]; - float offset[2]; - int pixel_step_uniform_location; - - monitor_scale = meta_is_stage_views_scaled () - ? meta_display_get_monitor_scale (self->display, self->monitor) - : 1.0; - - float pixel_step[] = { - 1.f / (self->texture_area.width * monitor_scale), - 1.f / (self->texture_area.height * monitor_scale), - }; - - pixel_step_uniform_location = - cogl_pipeline_get_uniform_location (self->pipeline, - "pixel_step"); - - /* Compute a scale and offset for transforming texture coordinates to the - * coordinate system from [-0.5 to 0.5] across the area of the actor - */ - scale[0] = self->texture_area.width / (float)actor_pixel_rect->width; - scale[1] = self->texture_area.height / (float)actor_pixel_rect->height; - offset[0] = self->texture_area.x / (float)actor_pixel_rect->width - 0.5; - offset[1] = self->texture_area.y / (float)actor_pixel_rect->height - 0.5; - - cogl_pipeline_set_uniform_float (self->pipeline, - cogl_pipeline_get_uniform_location (self->pipeline, - "scale"), - 2, 1, scale); - - cogl_pipeline_set_uniform_float (self->pipeline, - cogl_pipeline_get_uniform_location (self->pipeline, - "offset"), - 2, 1, offset); - - cogl_pipeline_set_uniform_float (self->pipeline, - pixel_step_uniform_location, - 2, 1, - pixel_step); -} - -static void -paint_clipped_rectangle (MetaBackgroundContent *self, - ClutterPaintNode *node, - ClutterActorBox *actor_box, - cairo_rectangle_int_t *rect) -{ - g_autoptr (ClutterPaintNode) pipeline_node = NULL; - float h_scale, v_scale; - float x1, y1, x2, y2; - float tx1, ty1, tx2, ty2; - - h_scale = self->texture_area.width / clutter_actor_box_get_width (actor_box); - v_scale = self->texture_area.height / clutter_actor_box_get_height (actor_box); - - x1 = rect->x; - y1 = rect->y; - x2 = rect->x + rect->width; - y2 = rect->y + rect->height; - - tx1 = (x1 * h_scale - self->texture_area.x) / (float)self->texture_area.width; - ty1 = (y1 * v_scale - self->texture_area.y) / (float)self->texture_area.height; - tx2 = (x2 * h_scale - self->texture_area.x) / (float)self->texture_area.width; - ty2 = (y2 * v_scale - self->texture_area.y) / (float)self->texture_area.height; - - pipeline_node = clutter_pipeline_node_new (self->pipeline); - clutter_paint_node_set_name (pipeline_node, "MetaBackgroundContent (Slice)"); - clutter_paint_node_add_texture_rectangle (pipeline_node, - &(ClutterActorBox) { - .x1 = x1, - .y1 = y1, - .x2 = x2, - .y2 = y2, - }, - tx1, ty1, - tx2, ty2); - - clutter_paint_node_add_child (node, pipeline_node); -} - -static void -meta_background_content_paint_content (ClutterContent *content, - ClutterActor *actor, - ClutterPaintNode *node, - ClutterPaintContext *paint_context) -{ - MetaBackgroundContent *self = META_BACKGROUND_CONTENT (content); - ClutterActorBox actor_box; - cairo_rectangle_int_t rect_within_actor; - cairo_rectangle_int_t rect_within_stage; - cairo_region_t *region; - int i, n_rects; - float transformed_x, transformed_y, transformed_width, transformed_height; - gboolean untransformed; - - if ((self->clip_region && cairo_region_is_empty (self->clip_region))) - return; - - clutter_actor_get_content_box (actor, &actor_box); - rect_within_actor.x = actor_box.x1; - rect_within_actor.y = actor_box.y1; - rect_within_actor.width = actor_box.x2 - actor_box.x1; - rect_within_actor.height = actor_box.y2 - actor_box.y1; - - if (clutter_actor_is_in_clone_paint (actor)) - { - untransformed = FALSE; - } - else - { - clutter_actor_get_transformed_position (actor, - &transformed_x, - &transformed_y); - rect_within_stage.x = floorf (transformed_x); - rect_within_stage.y = floorf (transformed_y); - - clutter_actor_get_transformed_size (actor, - &transformed_width, - &transformed_height); - rect_within_stage.width = ceilf (transformed_width); - rect_within_stage.height = ceilf (transformed_height); - - untransformed = - rect_within_actor.x == rect_within_stage.x && - rect_within_actor.y == rect_within_stage.y && - rect_within_actor.width == rect_within_stage.width && - rect_within_actor.height == rect_within_stage.height; - } - - if (untransformed) /* actor and stage space are the same */ - { - if (self->clip_region) - { - region = cairo_region_copy (self->clip_region); - cairo_region_intersect_rectangle (region, &rect_within_stage); - } - else - { - const cairo_region_t *redraw_clip; - - redraw_clip = clutter_paint_context_get_redraw_clip (paint_context); - if (redraw_clip) - { - region = cairo_region_copy (redraw_clip); - cairo_region_intersect_rectangle (region, &rect_within_stage); - } - else - { - region = cairo_region_create_rectangle (&rect_within_stage); - } - } - } - else /* actor and stage space are different but we need actor space */ - { - if (self->clip_region) - { - region = cairo_region_copy (self->clip_region); - cairo_region_intersect_rectangle (region, &rect_within_actor); - } - else - { - region = cairo_region_create_rectangle (&rect_within_actor); - } - } - - if (self->unobscured_region) - cairo_region_intersect (region, self->unobscured_region); - - /* region is now in actor space */ - if (cairo_region_is_empty (region)) - { - cairo_region_destroy (region); - return; - } - - setup_pipeline (self, actor, paint_context, &rect_within_actor); - set_glsl_parameters (self, &rect_within_actor); - - /* Limit to how many separate rectangles we'll draw; beyond this just - * fall back and draw the whole thing */ -#define MAX_RECTS 64 - - n_rects = cairo_region_num_rectangles (region); - if (n_rects <= MAX_RECTS) - { - for (i = 0; i < n_rects; i++) - { - cairo_rectangle_int_t rect; - cairo_region_get_rectangle (region, i, &rect); - paint_clipped_rectangle (self, node, &actor_box, &rect); - } - } - else - { - cairo_rectangle_int_t rect; - cairo_region_get_extents (region, &rect); - paint_clipped_rectangle (self, node, &actor_box, &rect); - } - - cairo_region_destroy (region); -} - -static gboolean -meta_background_content_get_preferred_size (ClutterContent *content, - float *width, - float *height) - -{ - MetaBackgroundContent *background_content = META_BACKGROUND_CONTENT (content); - MetaRectangle monitor_geometry; - - meta_display_get_monitor_geometry (background_content->display, - background_content->monitor, - &monitor_geometry); - - if (width) - *width = monitor_geometry.width; - - if (height) - *height = monitor_geometry.height; - - return TRUE; -} - -static void -clutter_content_iface_init (ClutterContentInterface *iface) -{ - iface->paint_content = meta_background_content_paint_content; - iface->get_preferred_size = meta_background_content_get_preferred_size; -} - -static void -set_monitor (MetaBackgroundContent *self, - int monitor) -{ - MetaRectangle old_monitor_geometry; - MetaRectangle new_monitor_geometry; - MetaDisplay *display = self->display; - - if(self->monitor == monitor) - return; - - meta_display_get_monitor_geometry (display, self->monitor, &old_monitor_geometry); - meta_display_get_monitor_geometry (display, monitor, &new_monitor_geometry); - if(old_monitor_geometry.height != new_monitor_geometry.height) - invalidate_pipeline (self, CHANGED_GRADIENT_PARAMETERS); - - self->monitor = monitor; -} - -static void -meta_background_content_dispose (GObject *object) -{ - MetaBackgroundContent *self = META_BACKGROUND_CONTENT (object); - - set_clip_region (self, NULL); - set_unobscured_region (self, NULL); - meta_background_content_set_background (self, NULL); - - g_clear_pointer (&self->pipeline, cogl_object_unref); - - G_OBJECT_CLASS (meta_background_content_parent_class)->dispose (object); -} - -static void -meta_background_content_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaBackgroundContent *self = META_BACKGROUND_CONTENT (object); - - switch (prop_id) - { - case PROP_META_DISPLAY: - self->display = g_value_get_object (value); - break; - case PROP_MONITOR: - set_monitor (self, g_value_get_int (value)); - break; - case PROP_BACKGROUND: - meta_background_content_set_background (self, g_value_get_object (value)); - break; - case PROP_GRADIENT: - meta_background_content_set_gradient (self, - g_value_get_boolean (value), - self->gradient_height, - self->gradient_max_darkness); - break; - case PROP_GRADIENT_HEIGHT: - meta_background_content_set_gradient (self, - self->gradient, - g_value_get_int (value), - self->gradient_max_darkness); - break; - case PROP_GRADIENT_MAX_DARKNESS: - meta_background_content_set_gradient (self, - self->gradient, - self->gradient_height, - g_value_get_double (value)); - break; - case PROP_VIGNETTE: - meta_background_content_set_vignette (self, - g_value_get_boolean (value), - self->vignette_brightness, - self->vignette_sharpness); - break; - case PROP_VIGNETTE_SHARPNESS: - meta_background_content_set_vignette (self, - self->vignette, - self->vignette_brightness, - g_value_get_double (value)); - break; - case PROP_VIGNETTE_BRIGHTNESS: - meta_background_content_set_vignette (self, - self->vignette, - g_value_get_double (value), - self->vignette_sharpness); - break; - case PROP_ROUNDED_CLIP_RADIUS: - meta_background_content_set_rounded_clip_radius (self, - g_value_get_float (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_background_content_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaBackgroundContent *self = META_BACKGROUND_CONTENT (object); - - switch (prop_id) - { - case PROP_META_DISPLAY: - g_value_set_object (value, self->display); - break; - case PROP_MONITOR: - g_value_set_int (value, self->monitor); - break; - case PROP_BACKGROUND: - g_value_set_object (value, self->background); - break; - case PROP_GRADIENT: - g_value_set_boolean (value, self->gradient); - break; - case PROP_GRADIENT_HEIGHT: - g_value_set_int (value, self->gradient_height); - break; - case PROP_GRADIENT_MAX_DARKNESS: - g_value_set_double (value, self->gradient_max_darkness); - break; - case PROP_VIGNETTE: - g_value_set_boolean (value, self->vignette); - break; - case PROP_VIGNETTE_BRIGHTNESS: - g_value_set_double (value, self->vignette_brightness); - break; - case PROP_VIGNETTE_SHARPNESS: - g_value_set_double (value, self->vignette_sharpness); - break; - case PROP_ROUNDED_CLIP_RADIUS: - g_value_set_float (value, self->rounded_clip_radius); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_background_content_class_init (MetaBackgroundContentClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = meta_background_content_dispose; - object_class->set_property = meta_background_content_set_property; - object_class->get_property = meta_background_content_get_property; - - properties[PROP_META_DISPLAY] = - g_param_spec_object ("meta-display", - "MetaDisplay", - "MetaDisplay", - META_TYPE_DISPLAY, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - - properties[PROP_MONITOR] = - g_param_spec_int ("monitor", - "monitor", - "monitor", - 0, G_MAXINT, 0, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - - properties[PROP_BACKGROUND] = - g_param_spec_object ("background", - "Background", - "MetaBackground object holding background parameters", - META_TYPE_BACKGROUND, - G_PARAM_READWRITE); - - properties[PROP_GRADIENT] = - g_param_spec_boolean ("gradient", - "Gradient", - "Whether gradient effect is enabled", - FALSE, - G_PARAM_READWRITE); - - properties[PROP_GRADIENT_HEIGHT] = - g_param_spec_int ("gradient-height", - "Gradient Height", - "Height of gradient effect", - 0, G_MAXINT, 0, - G_PARAM_READWRITE); - - properties[PROP_GRADIENT_MAX_DARKNESS] = - g_param_spec_double ("gradient-max-darkness", - "Gradient Max Darkness", - "How dark is the gradient initially", - 0.0, 1.0, 0.0, - G_PARAM_READWRITE); - - properties[PROP_VIGNETTE] = - g_param_spec_boolean ("vignette", - "Vignette", - "Whether vignette effect is enabled", - FALSE, - G_PARAM_READWRITE); - - properties[PROP_VIGNETTE_BRIGHTNESS] = - g_param_spec_double ("brightness", - "Vignette Brightness", - "Brightness of vignette effect", - 0.0, 1.0, 1.0, - G_PARAM_READWRITE); - - properties[PROP_VIGNETTE_SHARPNESS] = - g_param_spec_double ("vignette-sharpness", - "Vignette Sharpness", - "Sharpness of vignette effect", - 0.0, G_MAXDOUBLE, 0.0, - G_PARAM_READWRITE); - - properties[PROP_ROUNDED_CLIP_RADIUS] = - g_param_spec_float ("rounded-clip-radius", - "Rounded clip radius", - "Rounded clip radius", - 0.0, G_MAXFLOAT, 0.0, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS | - G_PARAM_EXPLICIT_NOTIFY); - - g_object_class_install_properties (object_class, N_PROPS, properties); -} - -static void -meta_background_content_init (MetaBackgroundContent *self) -{ - self->gradient = FALSE; - self->gradient_height = 0; - self->gradient_max_darkness = 0.0; - - self->vignette = FALSE; - self->vignette_brightness = 1.0; - self->vignette_sharpness = 0.0; - - self->has_rounded_clip = FALSE; - self->rounded_clip_radius = 0.0; -} - -/** - * meta_background_content_new: - * @monitor: Index of the monitor for which to draw the background - * - * Creates a new actor to draw the background for the given monitor. - * - * Return value: (transfer full): the newly created background actor - */ -ClutterContent * -meta_background_content_new (MetaDisplay *display, - int monitor) -{ - return g_object_new (META_TYPE_BACKGROUND_CONTENT, - "meta-display", display, - "monitor", monitor, - NULL); -} - -void -meta_background_content_set_background (MetaBackgroundContent *self, - MetaBackground *background) -{ - g_return_if_fail (META_IS_BACKGROUND_CONTENT (self)); - g_return_if_fail (background == NULL || META_IS_BACKGROUND (background)); - - if (background == self->background) - return; - - if (self->background) - { - g_signal_handlers_disconnect_by_func (self->background, - (gpointer)on_background_changed, - self); - g_clear_object (&self->background); - } - - if (background) - { - self->background = g_object_ref (background); - g_signal_connect (self->background, "changed", - G_CALLBACK (on_background_changed), self); - } - - invalidate_pipeline (self, CHANGED_BACKGROUND); - clutter_content_invalidate (CLUTTER_CONTENT (self)); -} - -void -meta_background_content_set_gradient (MetaBackgroundContent *self, - gboolean enabled, - int height, - double max_darkness) -{ - gboolean changed = FALSE; - - g_return_if_fail (META_IS_BACKGROUND_CONTENT (self)); - g_return_if_fail (height >= 0); - g_return_if_fail (max_darkness >= 0. && max_darkness <= 1.); - - enabled = enabled != FALSE && height != 0; - - if (enabled != self->gradient) - { - self->gradient = enabled; - invalidate_pipeline (self, CHANGED_EFFECTS); - changed = TRUE; - } - - if (height != self->gradient_height || max_darkness != self->gradient_max_darkness) - { - self->gradient_height = height; - self->gradient_max_darkness = max_darkness; - invalidate_pipeline (self, CHANGED_GRADIENT_PARAMETERS); - changed = TRUE; - } - - if (changed) - clutter_content_invalidate (CLUTTER_CONTENT (self)); -} - -void -meta_background_content_set_vignette (MetaBackgroundContent *self, - gboolean enabled, - double brightness, - double sharpness) -{ - gboolean changed = FALSE; - - g_return_if_fail (META_IS_BACKGROUND_CONTENT (self)); - g_return_if_fail (brightness >= 0. && brightness <= 1.); - g_return_if_fail (sharpness >= 0.); - - enabled = enabled != FALSE; - - if (enabled != self->vignette) - { - self->vignette = enabled; - invalidate_pipeline (self, CHANGED_EFFECTS); - changed = TRUE; - } - - if (brightness != self->vignette_brightness || sharpness != self->vignette_sharpness) - { - self->vignette_brightness = brightness; - self->vignette_sharpness = sharpness; - invalidate_pipeline (self, CHANGED_VIGNETTE_PARAMETERS); - changed = TRUE; - } - - if (changed) - clutter_content_invalidate (CLUTTER_CONTENT (self)); -} - -void -meta_background_content_set_rounded_clip_radius (MetaBackgroundContent *self, - float radius) -{ - gboolean enabled; - gboolean changed = FALSE; - - g_return_if_fail (META_IS_BACKGROUND_CONTENT (self)); - g_return_if_fail (radius >= 0.0); - - enabled = radius > 0.0; - - if (enabled != self->has_rounded_clip) - { - self->has_rounded_clip = enabled; - invalidate_pipeline (self, CHANGED_EFFECTS); - changed = TRUE; - } - - if (!G_APPROX_VALUE (radius, self->rounded_clip_radius, FLT_EPSILON)) - { - self->rounded_clip_radius = radius; - invalidate_pipeline (self, CHANGED_ROUNDED_CLIP_PARAMETERS); - changed = TRUE; - } - - if (changed) - { - clutter_content_invalidate (CLUTTER_CONTENT (self)); - g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ROUNDED_CLIP_RADIUS]); - } -} - -/** - * meta_background_content_set_rounded_clip_bounds: - * @self: The #MetaBackgroundContent - * @bounds: (allow-none): The new bounding clip rectangle, or %NULL - * - * Sets the bounding clip rectangle of the #MetaBackgroundContent that's used - * when a rounded clip set via meta_background_content_set_rounded_clip_radius() - * is in effect, set it to %NULL to use no bounding clip, rounding the edges - * of the full texture. - */ -void -meta_background_content_set_rounded_clip_bounds (MetaBackgroundContent *self, - const graphene_rect_t *bounds) -{ - g_return_if_fail (META_IS_BACKGROUND_CONTENT (self)); - - if (bounds == NULL) - { - if (!self->rounded_clip_bounds_set) - return; - - self->rounded_clip_bounds_set = FALSE; - } - else - { - if (self->rounded_clip_bounds_set && - graphene_rect_equal (&self->rounded_clip_bounds, bounds)) - return; - - self->rounded_clip_bounds_set = TRUE; - graphene_rect_init_from_rect (&self->rounded_clip_bounds, bounds); - } - - invalidate_pipeline (self, CHANGED_ROUNDED_CLIP_PARAMETERS); - clutter_content_invalidate (CLUTTER_CONTENT (self)); -} - -cairo_region_t * -meta_background_content_get_clip_region (MetaBackgroundContent *self) -{ - return self->clip_region; -} - -void -meta_background_content_cull_out (MetaBackgroundContent *self, - cairo_region_t *unobscured_region, - cairo_region_t *clip_region) -{ - set_unobscured_region (self, unobscured_region); - set_clip_region (self, clip_region); -} - -void -meta_background_content_reset_culling (MetaBackgroundContent *self) -{ - set_unobscured_region (self, NULL); - set_clip_region (self, NULL); -} diff --git a/src/compositor/meta-background-group.c b/src/compositor/meta-background-group.c deleted file mode 100644 index e30b8af4c..000000000 --- a/src/compositor/meta-background-group.c +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/** - * SECTION:meta-background-group - * @title: MetaBackgroundGroup - * @short_description: Container for background actors - * - * This class is a subclass of ClutterActor with special handling for - * MetaBackgroundActor/MetaBackgroundGroup when painting children. - * It makes sure to only draw the parts of the backgrounds not - * occluded by opaque windows. - * - * See #MetaWindowGroup for more information behind the motivation, - * and details on implementation. - */ - -#include "config.h" - -#include "compositor/meta-cullable.h" -#include "meta/meta-background-group.h" - -static void cullable_iface_init (MetaCullableInterface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaBackgroundGroup, meta_background_group, CLUTTER_TYPE_ACTOR, - G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init)); - -static void -meta_background_group_class_init (MetaBackgroundGroupClass *klass) -{ -} - -static void -meta_background_group_cull_out (MetaCullable *cullable, - cairo_region_t *unobscured_region, - cairo_region_t *clip_region) -{ - meta_cullable_cull_out_children (cullable, unobscured_region, clip_region); -} - -static void -meta_background_group_reset_culling (MetaCullable *cullable) -{ - meta_cullable_reset_culling_children (cullable); -} - -static void -cullable_iface_init (MetaCullableInterface *iface) -{ - iface->cull_out = meta_background_group_cull_out; - iface->reset_culling = meta_background_group_reset_culling; -} - -static void -meta_background_group_init (MetaBackgroundGroup *self) -{ -} - -ClutterActor * -meta_background_group_new (void) -{ - MetaBackgroundGroup *background_group; - - background_group = g_object_new (META_TYPE_BACKGROUND_GROUP, NULL); - - return CLUTTER_ACTOR (background_group); -} diff --git a/src/compositor/meta-background-image.c b/src/compositor/meta-background-image.c deleted file mode 100644 index ed9425bb3..000000000 --- a/src/compositor/meta-background-image.c +++ /dev/null @@ -1,370 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * Copyright 2014 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 . - */ - -/** - * SECTION:meta-background-image - * @title: MetaBackgroundImage - * @short_description: objects holding images loaded from files, used for backgrounds - */ - -#include "config.h" - -#include "meta/meta-background-image.h" - -#include -#include - -#include "clutter/clutter.h" -#include "compositor/cogl-utils.h" - -enum -{ - LOADED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -/** - * MetaBackgroundImageCache: - * - * #MetaBackgroundImageCache caches loading of textures for backgrounds; there's actually - * nothing background specific about it, other than it is tuned to work well for - * large images as typically are used for backgrounds. - */ -struct _MetaBackgroundImageCache -{ - GObject parent_instance; - - GHashTable *images; -}; - -/** - * MetaBackgroundImage: - * - * #MetaBackgroundImage is an object that represents a loaded or loading background image. - */ -struct _MetaBackgroundImage -{ - GObject parent_instance; - GFile *file; - MetaBackgroundImageCache *cache; - gboolean in_cache; - gboolean loaded; - CoglTexture *texture; -}; - -G_DEFINE_TYPE (MetaBackgroundImageCache, meta_background_image_cache, G_TYPE_OBJECT); - -static void -meta_background_image_cache_init (MetaBackgroundImageCache *cache) -{ - cache->images = g_hash_table_new (g_file_hash, (GEqualFunc) g_file_equal); -} - -static void -meta_background_image_cache_finalize (GObject *object) -{ - MetaBackgroundImageCache *cache = META_BACKGROUND_IMAGE_CACHE (object); - GHashTableIter iter; - gpointer key, value; - - g_hash_table_iter_init (&iter, cache->images); - while (g_hash_table_iter_next (&iter, &key, &value)) - { - MetaBackgroundImage *image = value; - image->in_cache = FALSE; - } - - g_hash_table_destroy (cache->images); - - G_OBJECT_CLASS (meta_background_image_cache_parent_class)->finalize (object); -} - -static void -meta_background_image_cache_class_init (MetaBackgroundImageCacheClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_background_image_cache_finalize; -} - -/** - * meta_background_image_cache_get_default: - * - * Return value: (transfer none): the global singleton background cache - */ -MetaBackgroundImageCache * -meta_background_image_cache_get_default (void) -{ - static MetaBackgroundImageCache *cache; - - if (cache == NULL) - cache = g_object_new (META_TYPE_BACKGROUND_IMAGE_CACHE, NULL); - - return cache; -} - -static void -load_file (GTask *task, - MetaBackgroundImage *image, - gpointer task_data, - GCancellable *cancellable) -{ - GError *error = NULL; - GdkPixbuf *pixbuf; - GFileInputStream *stream; - - stream = g_file_read (image->file, NULL, &error); - if (stream == NULL) - { - g_task_return_error (task, error); - return; - } - - pixbuf = gdk_pixbuf_new_from_stream (G_INPUT_STREAM (stream), NULL, &error); - g_object_unref (stream); - - if (pixbuf == NULL) - { - g_task_return_error (task, error); - return; - } - - g_task_return_pointer (task, pixbuf, (GDestroyNotify) g_object_unref); -} - -static void -file_loaded (GObject *source_object, - GAsyncResult *result, - gpointer user_data) -{ - MetaBackgroundImage *image = META_BACKGROUND_IMAGE (source_object); - GError *error = NULL; - GError *catch_error = NULL; - GTask *task; - CoglTexture *texture; - GdkPixbuf *pixbuf, *rotated; - int width, height, row_stride; - guchar *pixels; - gboolean has_alpha; - - task = G_TASK (result); - pixbuf = g_task_propagate_pointer (task, &error); - - if (pixbuf == NULL) - { - char *uri = g_file_get_uri (image->file); - g_warning ("Failed to load background '%s': %s", - uri, error->message); - g_clear_error (&error); - g_free (uri); - goto out; - } - - rotated = gdk_pixbuf_apply_embedded_orientation (pixbuf); - if (rotated != NULL) - { - g_object_unref (pixbuf); - pixbuf = rotated; - } - - width = gdk_pixbuf_get_width (pixbuf); - height = gdk_pixbuf_get_height (pixbuf); - row_stride = gdk_pixbuf_get_rowstride (pixbuf); - pixels = gdk_pixbuf_get_pixels (pixbuf); - has_alpha = gdk_pixbuf_get_has_alpha (pixbuf); - - texture = meta_create_texture (width, height, - has_alpha ? COGL_TEXTURE_COMPONENTS_RGBA : COGL_TEXTURE_COMPONENTS_RGB, - META_TEXTURE_ALLOW_SLICING); - - if (!cogl_texture_set_data (texture, - has_alpha ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888, - row_stride, - pixels, 0, - &catch_error)) - { - g_warning ("Failed to create texture for background"); - g_error_free (catch_error); - cogl_object_unref (texture); - } - - image->texture = texture; - -out: - if (pixbuf != NULL) - g_object_unref (pixbuf); - - image->loaded = TRUE; - g_signal_emit (image, signals[LOADED], 0); -} - -/** - * meta_background_image_cache_load: - * @cache: a #MetaBackgroundImageCache - * @file: #GFile to load - * - * Loads an image to use as a background, or returns a reference to an - * image that is already in the process of loading or loaded. In either - * case, what is returned is a #MetaBackgroundImage which can be dereferenced - * to get a #CoglTexture. If meta_background_image_is_loaded() returns %TRUE, - * the background is loaded, otherwise the MetaBackgroundImage::loaded - * signal will be emitted exactly once. The 'loaded' state means that the - * loading process finished, whether it succeeded or failed. - * - * Return value: (transfer full): a #MetaBackgroundImage to dereference to get the loaded texture - */ -MetaBackgroundImage * -meta_background_image_cache_load (MetaBackgroundImageCache *cache, - GFile *file) -{ - MetaBackgroundImage *image; - GTask *task; - - g_return_val_if_fail (META_IS_BACKGROUND_IMAGE_CACHE (cache), NULL); - g_return_val_if_fail (file != NULL, NULL); - - image = g_hash_table_lookup (cache->images, file); - if (image != NULL) - return g_object_ref (image); - - image = g_object_new (META_TYPE_BACKGROUND_IMAGE, NULL); - image->cache = cache; - image->in_cache = TRUE; - image->file = g_object_ref (file); - g_hash_table_insert (cache->images, image->file, image); - - task = g_task_new (image, NULL, file_loaded, NULL); - - g_task_run_in_thread (task, (GTaskThreadFunc) load_file); - g_object_unref (task); - - return image; -} - -/** - * meta_background_image_cache_purge: - * @cache: a #MetaBackgroundImageCache - * @file: file to remove from the cache - * - * Remove an entry from the cache; this would be used if monitoring - * showed that the file changed. - */ -void -meta_background_image_cache_purge (MetaBackgroundImageCache *cache, - GFile *file) -{ - MetaBackgroundImage *image; - - g_return_if_fail (META_IS_BACKGROUND_IMAGE_CACHE (cache)); - g_return_if_fail (file != NULL); - - image = g_hash_table_lookup (cache->images, file); - if (image == NULL) - return; - - g_hash_table_remove (cache->images, image->file); - image->in_cache = FALSE; -} - -G_DEFINE_TYPE (MetaBackgroundImage, meta_background_image, G_TYPE_OBJECT); - -static void -meta_background_image_init (MetaBackgroundImage *image) -{ -} - -static void -meta_background_image_finalize (GObject *object) -{ - MetaBackgroundImage *image = META_BACKGROUND_IMAGE (object); - - if (image->in_cache) - g_hash_table_remove (image->cache->images, image->file); - - if (image->texture) - cogl_object_unref (image->texture); - if (image->file) - g_object_unref (image->file); - - G_OBJECT_CLASS (meta_background_image_parent_class)->finalize (object); -} - -static void -meta_background_image_class_init (MetaBackgroundImageClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_background_image_finalize; - - signals[LOADED] = - g_signal_new ("loaded", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); -} - -/** - * meta_background_image_is_loaded: - * @image: a #MetaBackgroundImage - * - * Return value: %TRUE if loading has already completed, %FALSE otherwise - */ -gboolean -meta_background_image_is_loaded (MetaBackgroundImage *image) -{ - g_return_val_if_fail (META_IS_BACKGROUND_IMAGE (image), FALSE); - - return image->loaded; -} - -/** - * meta_background_image_get_success: - * @image: a #MetaBackgroundImage - * - * This function is a convenience function for checking for success, - * without having to call meta_background_image_get_texture() and - * handle the return of a Cogl type. - * - * Return value: %TRUE if loading completed successfully, otherwise %FALSE - */ -gboolean -meta_background_image_get_success (MetaBackgroundImage *image) -{ - g_return_val_if_fail (META_IS_BACKGROUND_IMAGE (image), FALSE); - - return image->texture != NULL; -} - -/** - * meta_background_image_get_texture: - * @image: a #MetaBackgroundImage - * - * Return value: (transfer none): a #CoglTexture if loading succeeded; if - * loading failed or has not yet finished, %NULL. - */ -CoglTexture * -meta_background_image_get_texture (MetaBackgroundImage *image) -{ - g_return_val_if_fail (META_IS_BACKGROUND_IMAGE (image), NULL); - - return image->texture; -} diff --git a/src/compositor/meta-background-private.h b/src/compositor/meta-background-private.h deleted file mode 100644 index 871487da4..000000000 --- a/src/compositor/meta-background-private.h +++ /dev/null @@ -1,14 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -#ifndef META_BACKGROUND_PRIVATE_H -#define META_BACKGROUND_PRIVATE_H - -#include "cogl/cogl.h" -#include "meta/meta-background.h" - -CoglTexture *meta_background_get_texture (MetaBackground *self, - int monitor_index, - cairo_rectangle_int_t *texture_area, - CoglPipelineWrapMode *wrap_mode); - -#endif /* META_BACKGROUND_PRIVATE_H */ diff --git a/src/compositor/meta-background.c b/src/compositor/meta-background.c deleted file mode 100644 index c0d8d335d..000000000 --- a/src/compositor/meta-background.c +++ /dev/null @@ -1,1018 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright 2013 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#include "config.h" - -#include "compositor/meta-background-private.h" - -#include - -#include "backends/meta-backend-private.h" -#include "compositor/cogl-utils.h" -#include "meta/display.h" -#include "meta/meta-background-image.h" -#include "meta/meta-background.h" -#include "meta/meta-monitor-manager.h" -#include "meta/util.h" - -enum -{ - CHANGED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -typedef struct _MetaBackgroundMonitor MetaBackgroundMonitor; - -struct _MetaBackgroundMonitor -{ - gboolean dirty; - CoglTexture *texture; - CoglFramebuffer *fbo; -}; - -struct _MetaBackground -{ - GObject parent; - - MetaDisplay *display; - MetaBackgroundMonitor *monitors; - int n_monitors; - - GDesktopBackgroundStyle style; - GDesktopBackgroundShading shading_direction; - ClutterColor color; - ClutterColor second_color; - - GFile *file1; - MetaBackgroundImage *background_image1; - GFile *file2; - MetaBackgroundImage *background_image2; - - CoglTexture *color_texture; - CoglTexture *wallpaper_texture; - - float blend_factor; - - guint wallpaper_allocation_failed : 1; -}; - -enum -{ - PROP_META_DISPLAY = 1, - PROP_MONITOR, -}; - -G_DEFINE_TYPE (MetaBackground, meta_background, G_TYPE_OBJECT) - -static gboolean texture_has_alpha (CoglTexture *texture); - -static GSList *all_backgrounds = NULL; - -static void -free_fbos (MetaBackground *self) -{ - int i; - - for (i = 0; i < self->n_monitors; i++) - { - MetaBackgroundMonitor *monitor = &self->monitors[i]; - - g_clear_object (&monitor->fbo); - cogl_clear_object (&monitor->texture); - } -} - -static void -free_color_texture (MetaBackground *self) -{ - cogl_clear_object (&self->color_texture); -} - -static void -free_wallpaper_texture (MetaBackground *self) -{ - cogl_clear_object (&self->wallpaper_texture); - - self->wallpaper_allocation_failed = FALSE; -} - -static void -invalidate_monitor_backgrounds (MetaBackground *self) -{ - free_fbos (self); - g_clear_pointer (&self->monitors, g_free); - self->n_monitors = 0; - - if (self->display) - { - int i; - - self->n_monitors = meta_display_get_n_monitors (self->display); - self->monitors = g_new0 (MetaBackgroundMonitor, self->n_monitors); - - for (i = 0; i < self->n_monitors; i++) - self->monitors[i].dirty = TRUE; - } -} - -static void -on_monitors_changed (MetaBackground *self) -{ - invalidate_monitor_backgrounds (self); -} - -static void -set_display (MetaBackground *self, - MetaDisplay *display) -{ - g_set_object (&self->display, display); - - invalidate_monitor_backgrounds (self); -} - -static void -meta_background_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (prop_id) - { - case PROP_META_DISPLAY: - set_display (META_BACKGROUND (object), g_value_get_object (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_background_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaBackground *self = META_BACKGROUND (object); - - switch (prop_id) - { - case PROP_META_DISPLAY: - g_value_set_object (value, self->display); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gboolean -need_prerender (MetaBackground *self) -{ - CoglTexture *texture1 = self->background_image1 ? meta_background_image_get_texture (self->background_image1) : NULL; - CoglTexture *texture2 = self->background_image2 ? meta_background_image_get_texture (self->background_image2) : NULL; - - if (texture1 == NULL && texture2 == NULL) - return FALSE; - - if (texture2 == NULL && self->style == G_DESKTOP_BACKGROUND_STYLE_WALLPAPER) - return FALSE; - - return TRUE; -} - -static void -mark_changed (MetaBackground *self) -{ - int i; - - if (!need_prerender (self)) - free_fbos (self); - - for (i = 0; i < self->n_monitors; i++) - self->monitors[i].dirty = TRUE; - - g_signal_emit (self, signals[CHANGED], 0); -} - -static void -on_background_loaded (MetaBackgroundImage *image, - MetaBackground *self) -{ - mark_changed (self); -} - -static gboolean -file_equal0 (GFile *file1, - GFile *file2) -{ - if (file1 == file2) - return TRUE; - - if ((file1 == NULL) || (file2 == NULL)) - return FALSE; - - return g_file_equal (file1, file2); -} - -static void -set_file (MetaBackground *self, - GFile **filep, - MetaBackgroundImage **imagep, - GFile *file, - gboolean force_reload) -{ - if (force_reload || !file_equal0 (*filep, file)) - { - if (*imagep) - { - g_signal_handlers_disconnect_by_func (*imagep, - (gpointer)on_background_loaded, - self); - g_clear_object (imagep); - } - - g_set_object (filep, file); - - if (file) - { - MetaBackgroundImageCache *cache = meta_background_image_cache_get_default (); - - *imagep = meta_background_image_cache_load (cache, file); - g_signal_connect (*imagep, "loaded", - G_CALLBACK (on_background_loaded), self); - } - } -} - -static void -on_gl_video_memory_purged (MetaBackground *self) -{ - MetaBackgroundImageCache *cache = meta_background_image_cache_get_default (); - - /* The GPU memory that just got invalidated is the texture inside - * self->background_image1,2 and/or its mipmaps. However, to save memory the - * original pixbuf isn't kept in RAM so we can't do a simple re-upload. The - * only copy of the image was the one in texture memory that got invalidated. - * So we need to do a full reload from disk. - */ - if (self->file1) - { - meta_background_image_cache_purge (cache, self->file1); - set_file (self, &self->file1, &self->background_image1, self->file1, TRUE); - } - - if (self->file2) - { - meta_background_image_cache_purge (cache, self->file2); - set_file (self, &self->file2, &self->background_image2, self->file2, TRUE); - } - - mark_changed (self); -} - -static void -meta_background_dispose (GObject *object) -{ - MetaBackground *self = META_BACKGROUND (object); - - free_color_texture (self); - free_wallpaper_texture (self); - - set_file (self, &self->file1, &self->background_image1, NULL, FALSE); - set_file (self, &self->file2, &self->background_image2, NULL, FALSE); - - set_display (self, NULL); - - G_OBJECT_CLASS (meta_background_parent_class)->dispose (object); -} - -static void -meta_background_finalize (GObject *object) -{ - all_backgrounds = g_slist_remove (all_backgrounds, object); - - G_OBJECT_CLASS (meta_background_parent_class)->finalize (object); -} - -static void -meta_background_constructed (GObject *object) -{ - MetaBackground *self = META_BACKGROUND (object); - MetaMonitorManager *monitor_manager = meta_monitor_manager_get (); - - G_OBJECT_CLASS (meta_background_parent_class)->constructed (object); - - g_signal_connect_object (self->display, "gl-video-memory-purged", - G_CALLBACK (on_gl_video_memory_purged), object, G_CONNECT_SWAPPED); - - g_signal_connect_object (monitor_manager, "monitors-changed", - G_CALLBACK (on_monitors_changed), self, - G_CONNECT_SWAPPED); -} - -static void -meta_background_class_init (MetaBackgroundClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GParamSpec *param_spec; - - object_class->dispose = meta_background_dispose; - object_class->finalize = meta_background_finalize; - object_class->constructed = meta_background_constructed; - object_class->set_property = meta_background_set_property; - object_class->get_property = meta_background_get_property; - - signals[CHANGED] = - g_signal_new ("changed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - param_spec = g_param_spec_object ("meta-display", - "MetaDisplay", - "MetaDisplay", - META_TYPE_DISPLAY, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - - g_object_class_install_property (object_class, - PROP_META_DISPLAY, - param_spec); - -} - -static void -meta_background_init (MetaBackground *self) -{ - all_backgrounds = g_slist_prepend (all_backgrounds, self); -} - -static void -set_texture_area_from_monitor_area (cairo_rectangle_int_t *monitor_area, - cairo_rectangle_int_t *texture_area) -{ - texture_area->x = 0; - texture_area->y = 0; - texture_area->width = monitor_area->width; - texture_area->height = monitor_area->height; -} - -static void -get_texture_area (MetaBackground *self, - cairo_rectangle_int_t *monitor_rect, - float monitor_scale, - CoglTexture *texture, - cairo_rectangle_int_t *texture_area) -{ - cairo_rectangle_int_t image_area; - int screen_width, screen_height; - float texture_width, texture_height; - float monitor_x_scale, monitor_y_scale; - - texture_width = cogl_texture_get_width (texture); - texture_height = cogl_texture_get_height (texture); - - switch (self->style) - { - case G_DESKTOP_BACKGROUND_STYLE_STRETCHED: - default: - /* paint region is whole actor, and the texture - * is scaled disproportionately to fit the actor - */ - set_texture_area_from_monitor_area (monitor_rect, texture_area); - break; - case G_DESKTOP_BACKGROUND_STYLE_WALLPAPER: - meta_display_get_size (self->display, &screen_width, &screen_height); - - /* Start off by centering a tile in the middle of the - * total screen area taking care of the monitor scaling. - */ - image_area.x = (screen_width - texture_width) / 2.0; - image_area.y = (screen_height - texture_height) / 2.0; - image_area.width = texture_width; - image_area.height = texture_height; - - /* Translate into the coordinate system of the particular monitor */ - image_area.x -= monitor_rect->x; - image_area.y -= monitor_rect->y; - - *texture_area = image_area; - break; - case G_DESKTOP_BACKGROUND_STYLE_CENTERED: - /* paint region is the original image size centered in the actor, - * and the texture is scaled to the original image size */ - image_area.width = texture_width; - image_area.height = texture_height; - image_area.x = monitor_rect->width / 2 - image_area.width / 2; - image_area.y = monitor_rect->height / 2 - image_area.height / 2; - - *texture_area = image_area; - break; - case G_DESKTOP_BACKGROUND_STYLE_SCALED: - case G_DESKTOP_BACKGROUND_STYLE_ZOOM: - /* paint region is the actor size in one dimension, and centered and - * scaled by proportional amount in the other dimension. - * - * SCALED forces the centered dimension to fit on screen. - * ZOOM forces the centered dimension to grow off screen - */ - monitor_x_scale = monitor_rect->width / texture_width; - monitor_y_scale = monitor_rect->height / texture_height; - - if ((self->style == G_DESKTOP_BACKGROUND_STYLE_SCALED && - (monitor_x_scale < monitor_y_scale)) || - (self->style == G_DESKTOP_BACKGROUND_STYLE_ZOOM && - (monitor_x_scale > monitor_y_scale))) - { - /* Fill image to exactly fit actor horizontally */ - image_area.width = monitor_rect->width; - image_area.height = texture_height * monitor_x_scale; - - /* Position image centered vertically in actor */ - image_area.x = 0; - image_area.y = monitor_rect->height / 2 - image_area.height / 2; - } - else - { - /* Scale image to exactly fit actor vertically */ - image_area.width = texture_width * monitor_y_scale; - image_area.height = monitor_rect->height; - - /* Position image centered horizontally in actor */ - image_area.x = monitor_rect->width / 2 - image_area.width / 2; - image_area.y = 0; - } - - *texture_area = image_area; - break; - - case G_DESKTOP_BACKGROUND_STYLE_SPANNED: - { - /* paint region is the union of all monitors, with the origin - * of the region set to align with monitor associated with the background. - */ - meta_display_get_size (self->display, &screen_width, &screen_height); - - /* unclipped texture area is whole screen, scaled depending on monitor */ - image_area.width = screen_width * monitor_scale; - image_area.height = screen_height * monitor_scale; - - /* But make (0,0) line up with the appropriate monitor */ - image_area.x = -monitor_rect->x; - image_area.y = -monitor_rect->y; - - *texture_area = image_area; - break; - } - } -} - -static gboolean -draw_texture (MetaBackground *self, - CoglFramebuffer *framebuffer, - CoglPipeline *pipeline, - CoglTexture *texture, - cairo_rectangle_int_t *monitor_area, - float monitor_scale) -{ - cairo_rectangle_int_t texture_area; - gboolean bare_region_visible; - - get_texture_area (self, monitor_area, monitor_scale, texture, &texture_area); - - switch (self->style) - { - case G_DESKTOP_BACKGROUND_STYLE_STRETCHED: - case G_DESKTOP_BACKGROUND_STYLE_WALLPAPER: - case G_DESKTOP_BACKGROUND_STYLE_ZOOM: - case G_DESKTOP_BACKGROUND_STYLE_SPANNED: - /* Draw the entire monitor */ - cogl_framebuffer_draw_textured_rectangle (framebuffer, - pipeline, - 0, - 0, - monitor_area->width, - monitor_area->height, - - texture_area.x / (float)texture_area.width, - - texture_area.y / (float)texture_area.height, - (monitor_area->width - texture_area.x) / (float)texture_area.width, - (monitor_area->height - texture_area.y) / (float)texture_area.height); - - bare_region_visible = texture_has_alpha (texture); - - /* Draw just the texture */ - break; - case G_DESKTOP_BACKGROUND_STYLE_CENTERED: - case G_DESKTOP_BACKGROUND_STYLE_SCALED: - cogl_framebuffer_draw_textured_rectangle (framebuffer, - pipeline, - texture_area.x, texture_area.y, - texture_area.x + texture_area.width, - texture_area.y + texture_area.height, - 0, 0, 1.0, 1.0); - bare_region_visible = texture_has_alpha (texture) || memcmp (&texture_area, monitor_area, sizeof (cairo_rectangle_int_t)) != 0; - break; - case G_DESKTOP_BACKGROUND_STYLE_NONE: - bare_region_visible = TRUE; - break; - default: - g_return_val_if_reached(FALSE); - } - - return bare_region_visible; -} - -static void -ensure_color_texture (MetaBackground *self) -{ - if (self->color_texture == NULL) - { - ClutterBackend *backend = clutter_get_default_backend (); - CoglContext *ctx = clutter_backend_get_cogl_context (backend); - GError *error = NULL; - uint8_t pixels[6]; - int width, height; - - if (self->shading_direction == G_DESKTOP_BACKGROUND_SHADING_SOLID) - { - width = 1; - height = 1; - - pixels[0] = self->color.red; - pixels[1] = self->color.green; - pixels[2] = self->color.blue; - } - else - { - switch (self->shading_direction) - { - case G_DESKTOP_BACKGROUND_SHADING_VERTICAL: - width = 1; - height = 2; - break; - case G_DESKTOP_BACKGROUND_SHADING_HORIZONTAL: - width = 2; - height = 1; - break; - default: - g_return_if_reached (); - } - - pixels[0] = self->color.red; - pixels[1] = self->color.green; - pixels[2] = self->color.blue; - pixels[3] = self->second_color.red; - pixels[4] = self->second_color.green; - pixels[5] = self->second_color.blue; - } - - self->color_texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx, width, height, - COGL_PIXEL_FORMAT_RGB_888, - width * 3, - pixels, - &error)); - - if (error != NULL) - { - meta_warning ("Failed to allocate color texture: %s", error->message); - g_error_free (error); - } - } -} - -typedef enum -{ - PIPELINE_REPLACE, - PIPELINE_ADD, - PIPELINE_OVER_REVERSE, -} PipelineType; - -static CoglPipeline * -create_pipeline (PipelineType type) -{ - const char * const blend_strings[3] = { - [PIPELINE_REPLACE] = "RGBA = ADD (SRC_COLOR, 0)", - [PIPELINE_ADD] = "RGBA = ADD (SRC_COLOR, DST_COLOR)", - [PIPELINE_OVER_REVERSE] = "RGBA = ADD (SRC_COLOR * (1 - DST_COLOR[A]), DST_COLOR)", - }; - static CoglPipeline *templates[3]; - - if (templates[type] == NULL) - { - templates[type] = meta_create_texture_pipeline (NULL); - cogl_pipeline_set_blend (templates[type], blend_strings[type], NULL); - } - - cogl_pipeline_set_layer_filters (templates[type], - 0, - COGL_PIPELINE_FILTER_LINEAR_MIPMAP_LINEAR, - COGL_PIPELINE_FILTER_LINEAR); - - return cogl_pipeline_copy (templates[type]); -} - -static gboolean -texture_has_alpha (CoglTexture *texture) -{ - if (!texture) - return FALSE; - - switch (cogl_texture_get_components (texture)) - { - case COGL_TEXTURE_COMPONENTS_A: - case COGL_TEXTURE_COMPONENTS_RGBA: - return TRUE; - case COGL_TEXTURE_COMPONENTS_RG: - case COGL_TEXTURE_COMPONENTS_RGB: - case COGL_TEXTURE_COMPONENTS_DEPTH: - return FALSE; - default: - g_assert_not_reached (); - return FALSE; - } -} - -static gboolean -ensure_wallpaper_texture (MetaBackground *self, - CoglTexture *texture) -{ - if (self->wallpaper_texture == NULL && !self->wallpaper_allocation_failed) - { - int width = cogl_texture_get_width (texture); - int height = cogl_texture_get_height (texture); - CoglOffscreen *offscreen; - CoglFramebuffer *fbo; - GError *catch_error = NULL; - CoglPipeline *pipeline; - - self->wallpaper_texture = meta_create_texture (width, height, - COGL_TEXTURE_COMPONENTS_RGBA, - META_TEXTURE_FLAGS_NONE); - offscreen = cogl_offscreen_new_with_texture (self->wallpaper_texture); - fbo = COGL_FRAMEBUFFER (offscreen); - - if (!cogl_framebuffer_allocate (fbo, &catch_error)) - { - /* This probably means that the size of the wallpapered texture is larger - * than the maximum texture size; we treat it as permanent until the - * background is changed again. - */ - g_error_free (catch_error); - - cogl_clear_object (&self->wallpaper_texture); - g_object_unref (fbo); - - self->wallpaper_allocation_failed = TRUE; - return FALSE; - } - - cogl_framebuffer_orthographic (fbo, 0, 0, - width, height, -1., 1.); - - pipeline = create_pipeline (PIPELINE_REPLACE); - cogl_pipeline_set_layer_texture (pipeline, 0, texture); - cogl_framebuffer_draw_textured_rectangle (fbo, pipeline, 0, 0, width, height, - 0., 0., 1., 1.); - cogl_object_unref (pipeline); - - if (texture_has_alpha (texture)) - { - ensure_color_texture (self); - - pipeline = create_pipeline (PIPELINE_OVER_REVERSE); - cogl_pipeline_set_layer_texture (pipeline, 0, self->color_texture); - cogl_framebuffer_draw_rectangle (fbo, pipeline, 0, 0, width, height); - cogl_object_unref (pipeline); - } - - g_object_unref (fbo); - } - - return self->wallpaper_texture != NULL; -} - -static CoglPipelineWrapMode -get_wrap_mode (GDesktopBackgroundStyle style) -{ - switch (style) - { - case G_DESKTOP_BACKGROUND_STYLE_WALLPAPER: - return COGL_PIPELINE_WRAP_MODE_REPEAT; - case G_DESKTOP_BACKGROUND_STYLE_NONE: - case G_DESKTOP_BACKGROUND_STYLE_STRETCHED: - case G_DESKTOP_BACKGROUND_STYLE_CENTERED: - case G_DESKTOP_BACKGROUND_STYLE_SCALED: - case G_DESKTOP_BACKGROUND_STYLE_ZOOM: - case G_DESKTOP_BACKGROUND_STYLE_SPANNED: - default: - return COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE; - } -} - -static int -get_best_mipmap_level (CoglTexture *texture, - int visible_width, - int visible_height) -{ - int mipmap_width = cogl_texture_get_width (texture); - int mipmap_height = cogl_texture_get_height (texture); - int halves = 0; - - while (mipmap_width >= visible_width && mipmap_height >= visible_height) - { - halves++; - mipmap_width /= 2; - mipmap_height /= 2; - } - - return MAX (0, halves - 1); -} - -CoglTexture * -meta_background_get_texture (MetaBackground *self, - int monitor_index, - cairo_rectangle_int_t *texture_area, - CoglPipelineWrapMode *wrap_mode) -{ - MetaBackgroundMonitor *monitor; - MetaRectangle geometry; - cairo_rectangle_int_t monitor_area; - CoglTexture *texture1, *texture2; - float monitor_scale; - - g_return_val_if_fail (META_IS_BACKGROUND (self), NULL); - g_return_val_if_fail (monitor_index >= 0 && monitor_index < self->n_monitors, NULL); - - monitor = &self->monitors[monitor_index]; - - meta_display_get_monitor_geometry (self->display, monitor_index, &geometry); - monitor_scale = meta_display_get_monitor_scale (self->display, monitor_index); - monitor_area.x = geometry.x; - monitor_area.y = geometry.y; - monitor_area.width = geometry.width; - monitor_area.height = geometry.height; - - texture1 = self->background_image1 ? meta_background_image_get_texture (self->background_image1) : NULL; - texture2 = self->background_image2 ? meta_background_image_get_texture (self->background_image2) : NULL; - - if (texture1 == NULL && texture2 == NULL) - { - ensure_color_texture (self); - if (texture_area) - set_texture_area_from_monitor_area (&monitor_area, texture_area); - if (wrap_mode) - *wrap_mode = COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE; - return self->color_texture; - } - - if (texture2 == NULL && self->style == G_DESKTOP_BACKGROUND_STYLE_WALLPAPER && - self->shading_direction == G_DESKTOP_BACKGROUND_SHADING_SOLID && - ensure_wallpaper_texture (self, texture1)) - { - if (texture_area) - get_texture_area (self, &monitor_area, monitor_scale, - self->wallpaper_texture, texture_area); - if (wrap_mode) - *wrap_mode = COGL_PIPELINE_WRAP_MODE_REPEAT; - return self->wallpaper_texture; - } - - if (monitor->dirty) - { - GError *catch_error = NULL; - gboolean bare_region_visible = FALSE; - int texture_width, texture_height; - - if (meta_is_stage_views_scaled ()) - { - texture_width = monitor_area.width * monitor_scale; - texture_height = monitor_area.height * monitor_scale; - } - else - { - texture_width = monitor_area.width; - texture_height = monitor_area.height; - } - - if (monitor->texture == NULL) - { - CoglOffscreen *offscreen; - - monitor->texture = meta_create_texture (texture_width, - texture_height, - COGL_TEXTURE_COMPONENTS_RGB, - META_TEXTURE_FLAGS_NONE); - offscreen = cogl_offscreen_new_with_texture (monitor->texture); - monitor->fbo = COGL_FRAMEBUFFER (offscreen); - } - - if (self->style != G_DESKTOP_BACKGROUND_STYLE_WALLPAPER) - { - monitor_area.x *= monitor_scale; - monitor_area.y *= monitor_scale; - monitor_area.width *= monitor_scale; - monitor_area.height *= monitor_scale; - } - - if (!cogl_framebuffer_allocate (monitor->fbo, &catch_error)) - { - /* Texture or framebuffer allocation failed; it's unclear why this happened; - * we'll try again the next time this is called. (MetaBackgroundActor - * caches the result, so user might be left without a background.) - */ - cogl_clear_object (&monitor->texture); - g_clear_object (&monitor->fbo); - - g_error_free (catch_error); - return NULL; - } - - cogl_framebuffer_orthographic (monitor->fbo, 0, 0, - monitor_area.width, monitor_area.height, -1., 1.); - - if (texture2 != NULL && self->blend_factor != 0.0) - { - CoglPipeline *pipeline = create_pipeline (PIPELINE_REPLACE); - int mipmap_level; - - mipmap_level = get_best_mipmap_level (texture2, - texture_width, - texture_height); - - cogl_pipeline_set_color4f (pipeline, - self->blend_factor, self->blend_factor, self->blend_factor, self->blend_factor); - cogl_pipeline_set_layer_texture (pipeline, 0, texture2); - cogl_pipeline_set_layer_wrap_mode (pipeline, 0, get_wrap_mode (self->style)); - cogl_pipeline_set_layer_max_mipmap_level (pipeline, 0, mipmap_level); - - bare_region_visible = draw_texture (self, - monitor->fbo, pipeline, - texture2, &monitor_area, - monitor_scale); - - cogl_object_unref (pipeline); - } - else - { - cogl_framebuffer_clear4f (monitor->fbo, - COGL_BUFFER_BIT_COLOR, - 0.0, 0.0, 0.0, 0.0); - } - - if (texture1 != NULL && self->blend_factor != 1.0) - { - CoglPipeline *pipeline = create_pipeline (PIPELINE_ADD); - int mipmap_level; - - mipmap_level = get_best_mipmap_level (texture1, - texture_width, - texture_height); - - cogl_pipeline_set_color4f (pipeline, - (1 - self->blend_factor), - (1 - self->blend_factor), - (1 - self->blend_factor), - (1 - self->blend_factor)); - cogl_pipeline_set_layer_texture (pipeline, 0, texture1); - cogl_pipeline_set_layer_wrap_mode (pipeline, 0, get_wrap_mode (self->style)); - cogl_pipeline_set_layer_max_mipmap_level (pipeline, 0, mipmap_level); - - bare_region_visible = bare_region_visible || draw_texture (self, - monitor->fbo, pipeline, - texture1, &monitor_area, - monitor_scale); - - cogl_object_unref (pipeline); - } - - if (bare_region_visible) - { - CoglPipeline *pipeline = create_pipeline (PIPELINE_OVER_REVERSE); - - ensure_color_texture (self); - cogl_pipeline_set_layer_texture (pipeline, 0, self->color_texture); - cogl_framebuffer_draw_rectangle (monitor->fbo, - pipeline, - 0, 0, - monitor_area.width, monitor_area.height); - cogl_object_unref (pipeline); - } - - monitor->dirty = FALSE; - } - - if (texture_area) - set_texture_area_from_monitor_area (&geometry, texture_area); - - if (wrap_mode) - *wrap_mode = COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE; - return monitor->texture; -} - -MetaBackground * -meta_background_new (MetaDisplay *display) -{ - return g_object_new (META_TYPE_BACKGROUND, - "meta-display", display, - NULL); -} - -void -meta_background_set_color (MetaBackground *self, - ClutterColor *color) -{ - ClutterColor dummy = { 0 }; - - g_return_if_fail (META_IS_BACKGROUND (self)); - g_return_if_fail (color != NULL); - - meta_background_set_gradient (self, - G_DESKTOP_BACKGROUND_SHADING_SOLID, - color, &dummy); -} - -void -meta_background_set_gradient (MetaBackground *self, - GDesktopBackgroundShading shading_direction, - ClutterColor *color, - ClutterColor *second_color) -{ - g_return_if_fail (META_IS_BACKGROUND (self)); - g_return_if_fail (color != NULL); - g_return_if_fail (second_color != NULL); - - self->shading_direction = shading_direction; - self->color = *color; - self->second_color = *second_color; - - free_color_texture (self); - free_wallpaper_texture (self); - mark_changed (self); -} - -/** - * meta_background_set_file: - * @self: a #MetaBackground - * @file: (nullable): a #GFile representing the background file - * @style: the background style to apply - * - * Set the background to @file - */ -void -meta_background_set_file (MetaBackground *self, - GFile *file, - GDesktopBackgroundStyle style) -{ - g_return_if_fail (META_IS_BACKGROUND (self)); - - meta_background_set_blend (self, file, NULL, 0.0, style); -} - -void -meta_background_set_blend (MetaBackground *self, - GFile *file1, - GFile *file2, - double blend_factor, - GDesktopBackgroundStyle style) -{ - g_return_if_fail (META_IS_BACKGROUND (self)); - g_return_if_fail (blend_factor >= 0.0 && blend_factor <= 1.0); - - set_file (self, &self->file1, &self->background_image1, file1, FALSE); - set_file (self, &self->file2, &self->background_image2, file2, FALSE); - - self->blend_factor = blend_factor; - self->style = style; - - free_wallpaper_texture (self); - mark_changed (self); -} - -void -meta_background_refresh_all (void) -{ - GSList *l; - - for (l = all_backgrounds; l; l = l->next) - mark_changed (l->data); -} diff --git a/src/compositor/meta-compositor-native.c b/src/compositor/meta-compositor-native.c deleted file mode 100644 index 00f66b70d..000000000 --- a/src/compositor/meta-compositor-native.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2019 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "compositor/meta-compositor-native.h" - -#include "backends/meta-logical-monitor.h" -#include "compositor/meta-surface-actor-wayland.h" - -struct _MetaCompositorNative -{ - MetaCompositorServer parent; -}; - -G_DEFINE_TYPE (MetaCompositorNative, meta_compositor_native, - META_TYPE_COMPOSITOR_SERVER) - -static MetaRendererView * -get_window_view (MetaRenderer *renderer, - MetaWindow *window) -{ - GList *l; - MetaRendererView *view_found = NULL; - - for (l = meta_renderer_get_views (renderer); l; l = l->next) - { - ClutterStageView *stage_view = l->data; - MetaRectangle view_layout; - - clutter_stage_view_get_layout (stage_view, &view_layout); - - if (meta_rectangle_equal (&window->buffer_rect, - &view_layout)) - { - if (view_found) - return NULL; - view_found = META_RENDERER_VIEW (stage_view); - } - } - - return view_found; -} - -static void -maybe_assign_primary_plane (MetaCompositor *compositor) -{ - MetaBackend *backend = meta_get_backend (); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - MetaWindowActor *window_actor; - MetaWindow *window; - MetaRendererView *view; - CoglFramebuffer *framebuffer; - CoglOnscreen *onscreen; - MetaSurfaceActor *surface_actor; - MetaSurfaceActorWayland *surface_actor_wayland; - g_autoptr (CoglScanout) scanout = NULL; - - if (meta_compositor_is_unredirect_inhibited (compositor)) - return; - - window_actor = meta_compositor_get_top_window_actor (compositor); - if (!window_actor) - return; - - if (meta_window_actor_effect_in_progress (window_actor)) - return; - - if (clutter_actor_has_transitions (CLUTTER_ACTOR (window_actor))) - return; - - if (clutter_actor_get_n_children (CLUTTER_ACTOR (window_actor)) != 1) - return; - - window = meta_window_actor_get_meta_window (window_actor); - if (!window) - return; - - view = get_window_view (renderer, window); - if (!view) - return; - - framebuffer = clutter_stage_view_get_framebuffer (CLUTTER_STAGE_VIEW (view)); - if (!COGL_IS_ONSCREEN (framebuffer)) - return; - - surface_actor = meta_window_actor_get_surface (window_actor); - if (!META_IS_SURFACE_ACTOR_WAYLAND (surface_actor)) - return; - - surface_actor_wayland = META_SURFACE_ACTOR_WAYLAND (surface_actor); - onscreen = COGL_ONSCREEN (framebuffer); - scanout = meta_surface_actor_wayland_try_acquire_scanout (surface_actor_wayland, - onscreen); - if (!scanout) - return; - - clutter_stage_view_assign_next_scanout (CLUTTER_STAGE_VIEW (view), scanout); -} - -static void -meta_compositor_native_before_paint (MetaCompositor *compositor, - ClutterStageView *stage_view) -{ - MetaCompositorClass *parent_class; - - maybe_assign_primary_plane (compositor); - - parent_class = META_COMPOSITOR_CLASS (meta_compositor_native_parent_class); - parent_class->before_paint (compositor, stage_view); -} - -MetaCompositorNative * -meta_compositor_native_new (MetaDisplay *display, - MetaBackend *backend) -{ - return g_object_new (META_TYPE_COMPOSITOR_NATIVE, - "display", display, - "backend", backend, - NULL); -} - -static void -meta_compositor_native_init (MetaCompositorNative *compositor_native) -{ -} - -static void -meta_compositor_native_class_init (MetaCompositorNativeClass *klass) -{ - MetaCompositorClass *compositor_class = META_COMPOSITOR_CLASS (klass); - - compositor_class->before_paint = meta_compositor_native_before_paint; -} diff --git a/src/compositor/meta-compositor-native.h b/src/compositor/meta-compositor-native.h deleted file mode 100644 index 2b1c65208..000000000 --- a/src/compositor/meta-compositor-native.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2019 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_COMPOSITOR_NATIVE_H -#define META_COMPOSITOR_NATIVE_H - -#include "compositor/meta-compositor-server.h" - -#define META_TYPE_COMPOSITOR_NATIVE (meta_compositor_native_get_type ()) -G_DECLARE_FINAL_TYPE (MetaCompositorNative, meta_compositor_native, - META, COMPOSITOR_NATIVE, MetaCompositor) - -MetaCompositorNative * meta_compositor_native_new (MetaDisplay *display, - MetaBackend *backend); - -#endif /* META_COMPOSITOR_NATIVE_H */ diff --git a/src/compositor/meta-compositor-server.c b/src/compositor/meta-compositor-server.c deleted file mode 100644 index 179dc83ef..000000000 --- a/src/compositor/meta-compositor-server.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2019 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "backends/meta-dnd-private.h" -#include "compositor/meta-compositor-server.h" -#include "core/display-private.h" - -G_DEFINE_TYPE (MetaCompositorServer, meta_compositor_server, META_TYPE_COMPOSITOR) - -static gboolean -meta_compositor_server_manage (MetaCompositor *compositor, - GError **error) -{ - return TRUE; -} - -static void -meta_compositor_server_unmanage (MetaCompositor *compositor) -{ -} - -static int64_t -meta_compositor_server_monotonic_to_high_res_xserver_time (MetaCompositor *compositor, - int64_t monotonic_time_us) -{ - return meta_translate_to_high_res_xserver_time (monotonic_time_us); -} - -static void -meta_compositor_server_grab_begin (MetaCompositor *compositor) -{ - MetaDisplay *display; - - display = meta_compositor_get_display (compositor); - meta_display_sync_wayland_input_focus (display); - meta_display_cancel_touch (display); - -#ifdef HAVE_WAYLAND - meta_dnd_wayland_handle_begin_modal (compositor); -#endif -} - -static void -meta_compositor_server_grab_end (MetaCompositor *compositor) -{ - MetaDisplay *display; - - display = meta_compositor_get_display (compositor); -#ifdef HAVE_WAYLAND - meta_dnd_wayland_handle_end_modal (compositor); -#endif - meta_display_sync_wayland_input_focus (display); -} - -MetaCompositorServer * -meta_compositor_server_new (MetaDisplay *display, - MetaBackend *backend) -{ - return g_object_new (META_TYPE_COMPOSITOR_SERVER, - "display", display, - "backend", backend, - NULL); -} - -static void -meta_compositor_server_init (MetaCompositorServer *compositor_server) -{ -} - -static void -meta_compositor_server_class_init (MetaCompositorServerClass *klass) -{ - MetaCompositorClass *compositor_class = META_COMPOSITOR_CLASS (klass); - - compositor_class->manage = meta_compositor_server_manage; - compositor_class->unmanage = meta_compositor_server_unmanage; - compositor_class->monotonic_to_high_res_xserver_time = - meta_compositor_server_monotonic_to_high_res_xserver_time; - compositor_class->grab_begin = meta_compositor_server_grab_begin; - compositor_class->grab_end = meta_compositor_server_grab_end; -} diff --git a/src/compositor/meta-compositor-server.h b/src/compositor/meta-compositor-server.h deleted file mode 100644 index 2bf8d5ec3..000000000 --- a/src/compositor/meta-compositor-server.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2019 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_COMPOSITOR_SERVER_H -#define META_COMPOSITOR_SERVER_H - -#include "compositor/compositor-private.h" - -#define META_TYPE_COMPOSITOR_SERVER (meta_compositor_server_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaCompositorServer, meta_compositor_server, - META, COMPOSITOR_SERVER, MetaCompositor) - -struct _MetaCompositorServerClass -{ - MetaCompositorClass parent_class; -}; - -MetaCompositorServer * meta_compositor_server_new (MetaDisplay *display, - MetaBackend *backend); - -#endif /* META_COMPOSITOR_SERVER_H */ diff --git a/src/compositor/meta-compositor-x11.c b/src/compositor/meta-compositor-x11.c deleted file mode 100644 index a16604640..000000000 --- a/src/compositor/meta-compositor-x11.c +++ /dev/null @@ -1,530 +0,0 @@ -/* - * Copyright (C) 2019 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "compositor/meta-compositor-x11.h" - -#include -#include - -#include "backends/x11/meta-backend-x11.h" -#include "backends/x11/meta-clutter-backend-x11.h" -#include "backends/x11/meta-event-x11.h" -#include "compositor/meta-sync-ring.h" -#include "compositor/meta-window-actor-x11.h" -#include "core/display-private.h" -#include "x11/meta-x11-display-private.h" - -struct _MetaCompositorX11 -{ - MetaCompositor parent; - - Window output; - - gulong before_update_handler_id; - gulong after_update_handler_id; - - gboolean frame_has_updated_xsurfaces; - gboolean have_x11_sync_object; - - MetaWindow *unredirected_window; - - gboolean xserver_uses_monotonic_clock; - int64_t xserver_time_query_time_us; - int64_t xserver_time_offset_us; -}; - -G_DEFINE_TYPE (MetaCompositorX11, meta_compositor_x11, META_TYPE_COMPOSITOR) - -static void -process_damage (MetaCompositorX11 *compositor_x11, - XDamageNotifyEvent *damage_xevent, - MetaWindow *window) -{ - MetaWindowActor *window_actor = meta_window_actor_from_window (window); - MetaWindowActorX11 *window_actor_x11 = META_WINDOW_ACTOR_X11 (window_actor); - - meta_window_actor_x11_process_damage (window_actor_x11, damage_xevent); - - compositor_x11->frame_has_updated_xsurfaces = TRUE; -} - -void -meta_compositor_x11_process_xevent (MetaCompositorX11 *compositor_x11, - XEvent *xevent, - MetaWindow *window) -{ - MetaCompositor *compositor = META_COMPOSITOR (compositor_x11); - MetaDisplay *display = meta_compositor_get_display (compositor); - MetaX11Display *x11_display = display->x11_display; - int damage_event_base; - - damage_event_base = meta_x11_display_get_damage_event_base (x11_display); - if (xevent->type == damage_event_base + XDamageNotify) - { - /* - * Core code doesn't handle damage events, so we need to extract the - * MetaWindow ourselves. - */ - if (!window) - { - Window xwindow; - - xwindow = ((XDamageNotifyEvent *) xevent)->drawable; - window = meta_x11_display_lookup_x_window (x11_display, xwindow); - } - - if (window) - process_damage (compositor_x11, (XDamageNotifyEvent *) xevent, window); - } - - if (compositor_x11->have_x11_sync_object) - meta_sync_ring_handle_event (xevent); - - /* - * Clutter needs to know about MapNotify events otherwise it will think the - * stage is invisible - */ - if (xevent->type == MapNotify) - meta_x11_handle_event (xevent); -} - -static void -determine_server_clock_source (MetaCompositorX11 *compositor_x11) -{ - MetaCompositor *compositor = META_COMPOSITOR (compositor_x11); - MetaDisplay *display = meta_compositor_get_display (compositor); - MetaX11Display *x11_display = display->x11_display; - uint32_t server_time_ms; - int64_t server_time_us; - int64_t translated_monotonic_now_us; - - server_time_ms = meta_x11_display_get_current_time_roundtrip (x11_display); - server_time_us = ms2us (server_time_ms); - translated_monotonic_now_us = - meta_translate_to_high_res_xserver_time (g_get_monotonic_time ()); - - /* If the server time offset is within a second of the monotonic time, we - * assume that they are identical. This seems like a big margin, but we want - * to be as robust as possible even if the system is under load and our - * processing of the server response is delayed. - */ - if (ABS (server_time_us - translated_monotonic_now_us) < s2us (1)) - compositor_x11->xserver_uses_monotonic_clock = TRUE; - else - compositor_x11->xserver_uses_monotonic_clock = FALSE; -} - -static gboolean -meta_compositor_x11_manage (MetaCompositor *compositor, - GError **error) -{ - MetaCompositorX11 *compositor_x11 = META_COMPOSITOR_X11 (compositor); - MetaDisplay *display = meta_compositor_get_display (compositor); - MetaX11Display *x11_display = display->x11_display; - Display *xdisplay = meta_x11_display_get_xdisplay (x11_display); - int composite_version; - MetaBackend *backend = meta_get_backend (); - Window xwindow; - - if (!META_X11_DISPLAY_HAS_COMPOSITE (x11_display) || - !META_X11_DISPLAY_HAS_DAMAGE (x11_display)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Missing required extension %s", - !META_X11_DISPLAY_HAS_COMPOSITE (x11_display) ? - "composite" : "damage"); - return FALSE; - } - - composite_version = ((x11_display->composite_major_version * 10) + - x11_display->composite_minor_version); - if (composite_version < 3) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "COMPOSITE extension 3.0 required (found %d.%d)", - x11_display->composite_major_version, - x11_display->composite_minor_version); - return FALSE; - } - - determine_server_clock_source (compositor_x11); - - meta_x11_display_set_cm_selection (display->x11_display); - - compositor_x11->output = display->x11_display->composite_overlay_window; - - xwindow = meta_backend_x11_get_xwindow (META_BACKEND_X11 (backend)); - - XReparentWindow (xdisplay, xwindow, compositor_x11->output, 0, 0); - - meta_x11_display_clear_stage_input_region (display->x11_display); - - /* - * Make sure there isn't any left-over output shape on the overlay window by - * setting the whole screen to be an output region. - * - * Note: there doesn't seem to be any real chance of that because the X - * server will destroy the overlay window when the last client using it - * exits. - */ - XFixesSetWindowShapeRegion (xdisplay, compositor_x11->output, - ShapeBounding, 0, 0, None); - - /* - * Map overlay window before redirecting windows offscreen so we catch their - * contents until we show the stage. - */ - XMapWindow (xdisplay, compositor_x11->output); - - compositor_x11->have_x11_sync_object = meta_sync_ring_init (xdisplay); - - meta_compositor_redirect_x11_windows (META_COMPOSITOR (compositor)); - - return TRUE; -} - -static void -meta_compositor_x11_unmanage (MetaCompositor *compositor) -{ - MetaDisplay *display = meta_compositor_get_display (compositor); - MetaX11Display *x11_display = display->x11_display; - Display *xdisplay = x11_display->xdisplay; - Window xroot = x11_display->xroot; - - /* - * This is the most important part of cleanup - we have to do this before - * giving up the window manager selection or the next window manager won't be - * able to redirect subwindows - */ - XCompositeUnredirectSubwindows (xdisplay, xroot, CompositeRedirectManual); -} - -/* - * Sets an bounding shape on the COW so that the given window - * is exposed. If window is %NULL it clears the shape again. - * - * Used so we can unredirect windows, by shaping away the part - * of the COW, letting the raw window be seen through below. - */ -static void -shape_cow_for_window (MetaCompositorX11 *compositor_x11, - MetaWindow *window) -{ - MetaCompositor *compositor = META_COMPOSITOR (compositor_x11); - MetaDisplay *display = meta_compositor_get_display (compositor); - Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display); - - if (!window) - { - XFixesSetWindowShapeRegion (xdisplay, compositor_x11->output, - ShapeBounding, 0, 0, None); - } - else - { - XserverRegion output_region; - XRectangle screen_rect, window_bounds; - int width, height; - MetaRectangle rect; - - meta_window_get_frame_rect (window, &rect); - - window_bounds.x = rect.x; - window_bounds.y = rect.y; - window_bounds.width = rect.width; - window_bounds.height = rect.height; - - meta_display_get_size (display, &width, &height); - screen_rect.x = 0; - screen_rect.y = 0; - screen_rect.width = width; - screen_rect.height = height; - - output_region = XFixesCreateRegion (xdisplay, &window_bounds, 1); - - XFixesInvertRegion (xdisplay, output_region, &screen_rect, output_region); - XFixesSetWindowShapeRegion (xdisplay, compositor_x11->output, - ShapeBounding, 0, 0, output_region); - XFixesDestroyRegion (xdisplay, output_region); - } -} - -static void -set_unredirected_window (MetaCompositorX11 *compositor_x11, - MetaWindow *window) -{ - MetaWindow *prev_unredirected_window = compositor_x11->unredirected_window; - - if (prev_unredirected_window == window) - return; - - if (prev_unredirected_window) - { - MetaWindowActor *window_actor; - MetaWindowActorX11 *window_actor_x11; - - window_actor = meta_window_actor_from_window (prev_unredirected_window); - window_actor_x11 = META_WINDOW_ACTOR_X11 (window_actor); - meta_window_actor_x11_set_unredirected (window_actor_x11, FALSE); - } - - shape_cow_for_window (compositor_x11, window); - compositor_x11->unredirected_window = window; - - if (window) - { - MetaWindowActor *window_actor; - MetaWindowActorX11 *window_actor_x11; - - window_actor = meta_window_actor_from_window (window); - window_actor_x11 = META_WINDOW_ACTOR_X11 (window_actor); - meta_window_actor_x11_set_unredirected (window_actor_x11, TRUE); - } -} - -static void -maybe_unredirect_top_window (MetaCompositorX11 *compositor_x11) -{ - MetaCompositor *compositor = META_COMPOSITOR (compositor_x11); - MetaWindow *window_to_unredirect = NULL; - MetaWindowActor *window_actor; - MetaWindowActorX11 *window_actor_x11; - - if (meta_compositor_is_unredirect_inhibited (compositor)) - goto out; - - window_actor = meta_compositor_get_top_window_actor (compositor); - if (!window_actor) - goto out; - - window_actor_x11 = META_WINDOW_ACTOR_X11 (window_actor); - if (!meta_window_actor_x11_should_unredirect (window_actor_x11)) - goto out; - - window_to_unredirect = meta_window_actor_get_meta_window (window_actor); - -out: - set_unredirected_window (compositor_x11, window_to_unredirect); -} - -static void -on_before_update (ClutterStage *stage, - ClutterStageView *stage_view, - MetaCompositor *compositor) -{ - MetaCompositorX11 *compositor_x11 = META_COMPOSITOR_X11 (compositor); - - if (compositor_x11->frame_has_updated_xsurfaces) - { - MetaDisplay *display = meta_compositor_get_display (compositor); - - /* - * We need to make sure that any X drawing that happens before the - * XDamageSubtract() for each window above is visible to subsequent GL - * rendering; the standardized way to do this is GL_EXT_X11_sync_object. - * Since this isn't implemented yet in mesa, we also have a path that - * relies on the implementation of the open source drivers. - * - * Anything else, we just hope for the best. - * - * Xorg and open source driver specifics: - * - * The X server makes sure to flush drawing to the kernel before sending - * out damage events, but since we use DamageReportBoundingBox there may - * be drawing between the last damage event and the XDamageSubtract() - * that needs to be flushed as well. - * - * Xorg always makes sure that drawing is flushed to the kernel before - * writing events or responses to the client, so any round trip request - * at this point is sufficient to flush the GLX buffers. - */ - if (compositor_x11->have_x11_sync_object) - compositor_x11->have_x11_sync_object = meta_sync_ring_insert_wait (); - else - XSync (display->x11_display->xdisplay, False); - } -} - -static void -on_after_update (ClutterStage *stage, - ClutterStageView *stage_view, - MetaCompositor *compositor) -{ - MetaCompositorX11 *compositor_x11 = META_COMPOSITOR_X11 (compositor); - - if (compositor_x11->frame_has_updated_xsurfaces) - { - if (compositor_x11->have_x11_sync_object) - compositor_x11->have_x11_sync_object = meta_sync_ring_after_frame (); - - compositor_x11->frame_has_updated_xsurfaces = FALSE; - } -} - -static void -meta_compositor_x11_before_paint (MetaCompositor *compositor, - ClutterStageView *stage_view) -{ - MetaCompositorX11 *compositor_x11 = META_COMPOSITOR_X11 (compositor); - MetaCompositorClass *parent_class; - - maybe_unredirect_top_window (compositor_x11); - - parent_class = META_COMPOSITOR_CLASS (meta_compositor_x11_parent_class); - parent_class->before_paint (compositor, stage_view); -} - -static void -meta_compositor_x11_remove_window (MetaCompositor *compositor, - MetaWindow *window) -{ - MetaCompositorX11 *compositor_x11 = META_COMPOSITOR_X11 (compositor); - MetaCompositorClass *parent_class; - - if (compositor_x11->unredirected_window == window) - set_unredirected_window (compositor_x11, NULL); - - parent_class = META_COMPOSITOR_CLASS (meta_compositor_x11_parent_class); - parent_class->remove_window (compositor, window); -} - -static int64_t -meta_compositor_x11_monotonic_to_high_res_xserver_time (MetaCompositor *compositor, - int64_t monotonic_time_us) -{ - MetaCompositorX11 *compositor_x11 = META_COMPOSITOR_X11 (compositor); - int64_t now_us; - - if (compositor_x11->xserver_uses_monotonic_clock) - return meta_translate_to_high_res_xserver_time (monotonic_time_us); - - now_us = g_get_monotonic_time (); - - if (compositor_x11->xserver_time_query_time_us == 0 || - now_us > (compositor_x11->xserver_time_query_time_us + s2us (10))) - { - MetaDisplay *display = meta_compositor_get_display (compositor); - MetaX11Display *x11_display = display->x11_display; - uint32_t xserver_time_ms; - int64_t xserver_time_us; - - compositor_x11->xserver_time_query_time_us = now_us; - - xserver_time_ms = - meta_x11_display_get_current_time_roundtrip (x11_display); - xserver_time_us = ms2us (xserver_time_ms); - compositor_x11->xserver_time_offset_us = xserver_time_us - now_us; - } - - return monotonic_time_us + compositor_x11->xserver_time_offset_us; -} - -static void -meta_compositor_x11_grab_begin (MetaCompositor *compositor) -{ - MetaBackendX11 *backend_x11 = META_BACKEND_X11 (meta_get_backend ()); - - meta_backend_x11_sync_pointer (backend_x11); -} - -static void -meta_compositor_x11_grab_end (MetaCompositor *compositor) -{ - MetaBackendX11 *backend_x11 = META_BACKEND_X11 (meta_get_backend ()); - - meta_backend_x11_sync_pointer (backend_x11); -} - -Window -meta_compositor_x11_get_output_xwindow (MetaCompositorX11 *compositor_x11) -{ - return compositor_x11->output; -} - -MetaCompositorX11 * -meta_compositor_x11_new (MetaDisplay *display, - MetaBackend *backend) -{ - return g_object_new (META_TYPE_COMPOSITOR_X11, - "display", display, - "backend", backend, - NULL); -} - -static void -meta_compositor_x11_constructed (GObject *object) -{ - MetaCompositorX11 *compositor_x11 = META_COMPOSITOR_X11 (object); - MetaCompositor *compositor = META_COMPOSITOR (compositor_x11); - ClutterStage *stage = meta_compositor_get_stage (compositor); - - compositor_x11->before_update_handler_id = - g_signal_connect (stage, "before-update", - G_CALLBACK (on_before_update), compositor); - compositor_x11->after_update_handler_id = - g_signal_connect (stage, "after-update", - G_CALLBACK (on_after_update), compositor); - - G_OBJECT_CLASS (meta_compositor_x11_parent_class)->constructed (object); -} - -static void -meta_compositor_x11_dispose (GObject *object) -{ - MetaCompositorX11 *compositor_x11 = META_COMPOSITOR_X11 (object); - MetaCompositor *compositor = META_COMPOSITOR (compositor_x11); - ClutterStage *stage = meta_compositor_get_stage (compositor); - - if (compositor_x11->have_x11_sync_object) - { - meta_sync_ring_destroy (); - compositor_x11->have_x11_sync_object = FALSE; - } - - g_clear_signal_handler (&compositor_x11->before_update_handler_id, stage); - g_clear_signal_handler (&compositor_x11->after_update_handler_id, stage); - - G_OBJECT_CLASS (meta_compositor_x11_parent_class)->dispose (object); -} - -static void -meta_compositor_x11_init (MetaCompositorX11 *compositor_x11) -{ -} - -static void -meta_compositor_x11_class_init (MetaCompositorX11Class *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaCompositorClass *compositor_class = META_COMPOSITOR_CLASS (klass); - - object_class->constructed = meta_compositor_x11_constructed; - object_class->dispose = meta_compositor_x11_dispose; - - compositor_class->manage = meta_compositor_x11_manage; - compositor_class->unmanage = meta_compositor_x11_unmanage; - compositor_class->before_paint = meta_compositor_x11_before_paint; - compositor_class->remove_window = meta_compositor_x11_remove_window; - compositor_class->monotonic_to_high_res_xserver_time = - meta_compositor_x11_monotonic_to_high_res_xserver_time; - compositor_class->grab_begin = meta_compositor_x11_grab_begin; - compositor_class->grab_end = meta_compositor_x11_grab_end; -} diff --git a/src/compositor/meta-compositor-x11.h b/src/compositor/meta-compositor-x11.h deleted file mode 100644 index 42554feb3..000000000 --- a/src/compositor/meta-compositor-x11.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2019 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_COMPOSITOR_X11_H -#define META_COMPOSITOR_X11_H - -#include "compositor/compositor-private.h" - -#define META_TYPE_COMPOSITOR_X11 (meta_compositor_x11_get_type ()) -G_DECLARE_FINAL_TYPE (MetaCompositorX11, meta_compositor_x11, - META, COMPOSITOR_X11, MetaCompositor) - -MetaCompositorX11 * meta_compositor_x11_new (MetaDisplay *display, - MetaBackend *backend); - -void meta_compositor_x11_process_xevent (MetaCompositorX11 *compositor_x11, - XEvent *xevent, - MetaWindow *window); - -Window meta_compositor_x11_get_output_xwindow (MetaCompositorX11 *compositor_x11); - -#endif /* META_COMPOSITOR_X11_H */ diff --git a/src/compositor/meta-cullable.c b/src/compositor/meta-cullable.c deleted file mode 100644 index 6f38c5e47..000000000 --- a/src/compositor/meta-cullable.c +++ /dev/null @@ -1,245 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * Copyright (C) 2013 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, see . - * - * Written by: - * Owen Taylor - * Ray Strode - * Jasper St. Pierre - */ - -#include "config.h" - -#include "compositor/clutter-utils.h" -#include "compositor/meta-cullable.h" - -G_DEFINE_INTERFACE (MetaCullable, meta_cullable, CLUTTER_TYPE_ACTOR); - -static gboolean -has_active_effects (ClutterActor *actor) -{ - g_autoptr (GList) effects = NULL; - GList *l; - - effects = clutter_actor_get_effects (actor); - for (l = effects; l != NULL; l = l->next) - { - if (clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (l->data))) - return TRUE; - } - - return FALSE; -} - -/** - * SECTION:meta-cullable - * @title: MetaCullable - * @short_description: CPU culling operations for efficient drawing - * - * When we are painting a stack of 5-10 large actors, the standard - * bottom-to-top method of drawing every actor results in a tremendous - * amount of overdraw. If these actors are painting textures like - * windows, it can easily max out the available memory bandwidth on a - * low-end graphics chipset. It's even worse if window textures are - * being accessed over the AGP bus. - * - * #MetaCullable is our solution. The basic technique applied here is to - * do a pre-pass before painting where we walk each actor from top to bottom - * and ask each actor to "cull itself out". We pass in a region it can copy - * to clip its drawing to, and the actor can subtract its fully opaque pixels - * so that actors underneath know not to draw there as well. - */ - -/** - * meta_cullable_cull_out_children: - * @cullable: The #MetaCullable - * @unobscured_region: The unobscured region, as passed into cull_out() - * @clip_region: The clip region, as passed into cull_out() - * - * This is a helper method for actors that want to recurse over their - * child actors, and cull them out. - * - * See #MetaCullable and meta_cullable_cull_out() for more details. - */ -void -meta_cullable_cull_out_children (MetaCullable *cullable, - cairo_region_t *unobscured_region, - cairo_region_t *clip_region) -{ - ClutterActor *actor = CLUTTER_ACTOR (cullable); - ClutterActor *child; - ClutterActorIter iter; - - clutter_actor_iter_init (&iter, actor); - while (clutter_actor_iter_prev (&iter, &child)) - { - float x, y; - gboolean needs_culling; - - if (!META_IS_CULLABLE (child)) - continue; - - needs_culling = (unobscured_region != NULL && clip_region != NULL); - - if (needs_culling && !CLUTTER_ACTOR_IS_VISIBLE (child)) - needs_culling = FALSE; - - /* If an actor has effects applied, then that can change the area - * it paints and the opacity, so we no longer can figure out what - * portion of the actor is obscured and what portion of the screen - * it obscures, so we skip the actor. - * - * This has a secondary beneficial effect: if a ClutterOffscreenEffect - * is applied to an actor, then our clipped redraws interfere with the - * caching of the FBO - even if we only need to draw a small portion - * of the window right now, ClutterOffscreenEffect may use other portions - * of the FBO later. So, skipping actors with effects applied also - * prevents these bugs. - * - * Theoretically, we should check clutter_actor_get_offscreen_redirect() - * as well for the same reason, but omitted for simplicity in the - * hopes that no-one will do that. - */ - if (needs_culling && has_active_effects (child)) - needs_culling = FALSE; - - if (needs_culling && !meta_cullable_is_untransformed (META_CULLABLE (child))) - needs_culling = FALSE; - - if (needs_culling) - { - clutter_actor_get_position (child, &x, &y); - - /* Temporarily move to the coordinate system of the actor */ - cairo_region_translate (unobscured_region, - x, - y); - cairo_region_translate (clip_region, - x, - y); - - meta_cullable_cull_out (META_CULLABLE (child), unobscured_region, clip_region); - - cairo_region_translate (unobscured_region, x, y); - cairo_region_translate (clip_region, x, y); - } - else - { - meta_cullable_cull_out (META_CULLABLE (child), NULL, NULL); - } - } -} - -/** - * meta_cullable_reset_culling_children: - * @cullable: The #MetaCullable - * - * This is a helper method for actors that want to recurse over their - * child actors, and cull them out. - * - * See #MetaCullable and meta_cullable_reset_culling() for more details. - */ -void -meta_cullable_reset_culling_children (MetaCullable *cullable) -{ - ClutterActor *actor = CLUTTER_ACTOR (cullable); - ClutterActor *child; - ClutterActorIter iter; - - clutter_actor_iter_init (&iter, actor); - while (clutter_actor_iter_next (&iter, &child)) - { - if (!META_IS_CULLABLE (child)) - continue; - - meta_cullable_reset_culling (META_CULLABLE (child)); - } -} - -static gboolean -meta_cullable_default_is_untransformed (MetaCullable *cullable) -{ - float width, height; - graphene_point3d_t verts[4]; - - clutter_actor_get_size (CLUTTER_ACTOR (cullable), &width, &height); - clutter_actor_get_abs_allocation_vertices (CLUTTER_ACTOR (cullable), verts); - - return meta_actor_vertices_are_untransformed (verts, width, height, - NULL, NULL); -} - -static void -meta_cullable_default_init (MetaCullableInterface *iface) -{ - iface->is_untransformed = meta_cullable_default_is_untransformed; -} - -/** - * meta_cullable_cull_out: - * @cullable: The #MetaCullable - * @unobscured_region: The unobscured region, in @cullable's space. - * @clip_region: The clip region, in @cullable's space. - * - * When #MetaWindowGroup is painted, we walk over its direct cullable - * children from top to bottom and ask themselves to "cull out". Cullables - * can use @unobscured_region and @clip_region to clip their drawing. Actors - * interested in eliminating overdraw should copy the @clip_region and only - * paint those parts, as everything else has been obscured by actors above it. - * - * Actors that may have fully opaque parts should also subtract out a region - * that is fully opaque from @unobscured_region and @clip_region. - * - * @unobscured_region and @clip_region are extremely similar. The difference - * is that @clip_region starts off with the stage's clip, if Clutter detects - * that we're doing a clipped redraw. @unobscured_region, however, starts off - * with the full stage size, so actors that may want to record what parts of - * their window are unobscured for e.g. scheduling repaints can do so. - * - * Actors that have children can also use the meta_cullable_cull_out_children() - * helper method to do a simple cull across all their children. - */ -void -meta_cullable_cull_out (MetaCullable *cullable, - cairo_region_t *unobscured_region, - cairo_region_t *clip_region) -{ - META_CULLABLE_GET_IFACE (cullable)->cull_out (cullable, unobscured_region, clip_region); -} - -/** - * meta_cullable_is_untransformed: - * @cullable: The #MetaCullable - * - * Check if a cullable is "untransformed" - which actually means transformed by - * at most a integer-translation. - */ -gboolean -meta_cullable_is_untransformed (MetaCullable *cullable) -{ - return META_CULLABLE_GET_IFACE (cullable)->is_untransformed (cullable); -} - -/** - * meta_cullable_reset_culling: - * @cullable: The #MetaCullable - * - * Actors that copied data in their cull_out() implementation can now - * reset their data, as the paint is now over. Additional paints may be - * done by #ClutterClone or similar, and they should not be affected by - * the culling operation. - */ -void -meta_cullable_reset_culling (MetaCullable *cullable) -{ - META_CULLABLE_GET_IFACE (cullable)->reset_culling (cullable); -} diff --git a/src/compositor/meta-cullable.h b/src/compositor/meta-cullable.h deleted file mode 100644 index 471681da3..000000000 --- a/src/compositor/meta-cullable.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2013 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, see . - * - * Written by: - * Owen Taylor - * Ray Strode - * Jasper St. Pierre - */ - -#ifndef __META_CULLABLE_H__ -#define __META_CULLABLE_H__ - -#include "clutter/clutter.h" - -G_BEGIN_DECLS - -#define META_TYPE_CULLABLE (meta_cullable_get_type ()) -G_DECLARE_INTERFACE (MetaCullable, meta_cullable, META, CULLABLE, ClutterActor) - -struct _MetaCullableInterface -{ - GTypeInterface g_iface; - - void (* cull_out) (MetaCullable *cullable, - cairo_region_t *unobscured_region, - cairo_region_t *clip_region); - gboolean (* is_untransformed) (MetaCullable *cullable); - void (* reset_culling) (MetaCullable *cullable); -}; - -void meta_cullable_cull_out (MetaCullable *cullable, - cairo_region_t *unobscured_region, - cairo_region_t *clip_region); -gboolean meta_cullable_is_untransformed (MetaCullable *cullable); -void meta_cullable_reset_culling (MetaCullable *cullable); - -/* Utility methods for implementations */ -void meta_cullable_cull_out_children (MetaCullable *cullable, - cairo_region_t *unobscured_region, - cairo_region_t *clip_region); -void meta_cullable_reset_culling_children (MetaCullable *cullable); - -G_END_DECLS - -#endif /* __META_CULLABLE_H__ */ - diff --git a/src/compositor/meta-dnd-actor-private.h b/src/compositor/meta-dnd-actor-private.h deleted file mode 100644 index 20be369eb..000000000 --- a/src/compositor/meta-dnd-actor-private.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * meta-dnd-actor-private.h: Actor for painting the DnD surface - * - * Copyright 2014 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 . - * - * Author: Carlos Garnacho - */ - -#ifndef META_DND_ACTOR_PRIVATE_H -#define META_DND_ACTOR_PRIVATE_H - -#include "compositor/meta-feedback-actor-private.h" - -/** - * MetaDnDActor: - * - * This class handles the rendering of the DnD surface - */ - -#define META_TYPE_DND_ACTOR (meta_dnd_actor_get_type ()) -G_DECLARE_FINAL_TYPE (MetaDnDActor, - meta_dnd_actor, - META, DND_ACTOR, - MetaFeedbackActor) - - -ClutterActor *meta_dnd_actor_new (ClutterActor *drag_origin, - int start_x, - int start_y); - -void meta_dnd_actor_drag_finish (MetaDnDActor *self, - gboolean success); - -#endif /* META_DND_ACTOR_PRIVATE_H */ diff --git a/src/compositor/meta-dnd-actor.c b/src/compositor/meta-dnd-actor.c deleted file mode 100644 index 80bffdeb7..000000000 --- a/src/compositor/meta-dnd-actor.c +++ /dev/null @@ -1,242 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * Copyright 2014 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 . - * - * Author: Carlos Garnacho - */ - -/** - * SECTION:meta-dnd-actor - * @title: MetaDnDActor - * @short_description: Actor for painting the drag and drop surface - * - */ - -#include "config.h" - -#include "compositor/meta-dnd-actor-private.h" -#include "compositor/meta-window-actor-private.h" - -#include "clutter/clutter.h" - -#define DRAG_FAILED_DURATION 500 - -enum -{ - PROP_DRAG_ORIGIN = 1, - PROP_DRAG_START_X, - PROP_DRAG_START_Y -}; - -struct _MetaDnDActor -{ - MetaFeedbackActor parent; - - ClutterActor *drag_origin; - int drag_start_x; - int drag_start_y; -}; - -G_DEFINE_TYPE (MetaDnDActor, meta_dnd_actor, META_TYPE_FEEDBACK_ACTOR) - -static void -meta_dnd_actor_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaDnDActor *self = META_DND_ACTOR (object); - - switch (prop_id) - { - case PROP_DRAG_ORIGIN: - self->drag_origin = g_value_get_object (value); - break; - case PROP_DRAG_START_X: - self->drag_start_x = g_value_get_int (value); - break; - case PROP_DRAG_START_Y: - self->drag_start_y = g_value_get_int (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_dnd_actor_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaDnDActor *self = META_DND_ACTOR (object); - - switch (prop_id) - { - case PROP_DRAG_ORIGIN: - g_value_set_object (value, self->drag_origin); - break; - case PROP_DRAG_START_X: - g_value_set_int (value, self->drag_start_x); - break; - case PROP_DRAG_START_Y: - g_value_set_int (value, self->drag_start_y); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_dnd_actor_class_init (MetaDnDActorClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GParamSpec *pspec; - - object_class->set_property = meta_dnd_actor_set_property; - object_class->get_property = meta_dnd_actor_get_property; - - pspec = g_param_spec_object ("drag-origin", - "Drag origin", - "The origin of the DnD operation", - CLUTTER_TYPE_ACTOR, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - - g_object_class_install_property (object_class, - PROP_DRAG_ORIGIN, - pspec); - - pspec = g_param_spec_int ("drag-start-x", - "Drag start X", - "The X axis of the drag start point", - 0, G_MAXINT, 0, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - - g_object_class_install_property (object_class, - PROP_DRAG_START_X, - pspec); - - pspec = g_param_spec_int ("drag-start-y", - "Drag start Y", - "The Y axis of the drag start point", - 0, G_MAXINT, 0, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - - g_object_class_install_property (object_class, - PROP_DRAG_START_Y, - pspec); -} - -static void -meta_dnd_actor_init (MetaDnDActor *self) -{ -} - -/** - * meta_dnd_actor_new: - * - * Creates a new actor to draw the current drag and drop surface. - * - * Return value: the newly created background actor - */ -ClutterActor * -meta_dnd_actor_new (ClutterActor *drag_origin, - int drag_start_x, - int drag_start_y) -{ - MetaDnDActor *self; - - self = g_object_new (META_TYPE_DND_ACTOR, - "drag-origin", drag_origin, - "drag-start-x", drag_start_x, - "drag-start-y", drag_start_y, - NULL); - - return CLUTTER_ACTOR (self); -} - -static void -drag_failed_complete (ClutterTimeline *timeline, - gboolean is_finished, - gpointer user_data) -{ - ClutterActor *self = user_data; - - clutter_actor_remove_all_children (self); - clutter_actor_destroy (self); -} - -void -meta_dnd_actor_drag_finish (MetaDnDActor *self, - gboolean success) -{ - ClutterActor *actor; - - g_return_if_fail (META_IS_DND_ACTOR (self)); - - actor = CLUTTER_ACTOR (self); - - if (success) - { - clutter_actor_remove_all_children (CLUTTER_ACTOR (self)); - clutter_actor_destroy (CLUTTER_ACTOR (self)); - } - else - { - ClutterTransition *transition; - - clutter_actor_save_easing_state (actor); - clutter_actor_set_easing_mode (actor, CLUTTER_EASE_OUT_CUBIC); - clutter_actor_set_easing_duration (actor, DRAG_FAILED_DURATION); - clutter_actor_set_opacity (actor, 0); - - if (CLUTTER_ACTOR_IS_VISIBLE (self->drag_origin)) - { - MetaWindowActor *origin_actor; - float anchor_x, anchor_y; - graphene_point_t dest; - int origin_geometry_scale; - int feedback_geometry_scale; - - clutter_actor_get_transformed_position (self->drag_origin, - &dest.x, &dest.y); - - origin_actor = meta_window_actor_from_actor (self->drag_origin); - g_return_if_fail (origin_actor); - origin_geometry_scale = - meta_window_actor_get_geometry_scale (origin_actor); - - meta_feedback_actor_get_anchor (META_FEEDBACK_ACTOR (self), - &anchor_x, &anchor_y); - feedback_geometry_scale = - meta_feedback_actor_get_geometry_scale (META_FEEDBACK_ACTOR (self)); - - dest.x += ((self->drag_start_x * origin_geometry_scale) - - (anchor_x * feedback_geometry_scale)); - dest.y += ((self->drag_start_y * origin_geometry_scale) - - (anchor_y * feedback_geometry_scale)); - clutter_actor_set_position (actor, dest.x, dest.y); - } - - transition = clutter_actor_get_transition (actor, "opacity"); - g_signal_connect (transition, "stopped", - G_CALLBACK (drag_failed_complete), self); - - clutter_actor_restore_easing_state (actor); - } -} diff --git a/src/compositor/meta-dnd.c b/src/compositor/meta-dnd.c deleted file mode 100644 index 8461690a2..000000000 --- a/src/compositor/meta-dnd.c +++ /dev/null @@ -1,336 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * Copyright (C) 2016 Hyungwon Hwang - * - * 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 . - * - */ - -#include "config.h" - -#include - -#include "meta/meta-backend.h" -#include "compositor/compositor-private.h" -#include "core/display-private.h" -#include "backends/meta-dnd-private.h" -#include "backends/x11/meta-backend-x11.h" -#include "backends/x11/meta-clutter-backend-x11.h" -#include "backends/x11/meta-stage-x11.h" -#include "meta/meta-dnd.h" -#include "x11/meta-x11-display-private.h" - -struct _MetaDndClass -{ - GObjectClass parent_class; -}; - -#ifdef HAVE_WAYLAND -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-data-device.h" -#endif - -typedef struct _MetaDndPrivate MetaDndPrivate; - -struct _MetaDndPrivate -{ -#ifdef HAVE_WAYLAND - gulong handler_id[3]; - - MetaCompositor *compositor; - MetaWaylandCompositor *wl_compositor; -#else - /* to avoid warnings (g_type_class_add_private: assertion `private_size > 0' failed) */ - gchar dummy; -#endif -}; - -struct _MetaDnd -{ - GObject parent; - - MetaDndPrivate *priv; -}; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaDnd, meta_dnd, G_TYPE_OBJECT); - -enum -{ - ENTER, - POSITION_CHANGE, - LEAVE, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -static void -meta_dnd_class_init (MetaDndClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - signals[ENTER] = - g_signal_new ("dnd-enter", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - signals[POSITION_CHANGE] = - g_signal_new ("dnd-position-change", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT); - - signals[LEAVE] = - g_signal_new ("dnd-leave", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); -} - -static void -meta_dnd_init (MetaDnd *dnd) -{ -} - -void -meta_dnd_init_xdnd (MetaX11Display *x11_display) -{ - MetaBackend *backend = meta_get_backend (); - Display *xdisplay = x11_display->xdisplay; - Window xwindow, overlay_xwindow; - long xdnd_version = 5; - - overlay_xwindow = x11_display->composite_overlay_window; - xwindow = meta_backend_x11_get_xwindow (META_BACKEND_X11 (backend)); - - XChangeProperty (xdisplay, xwindow, - XInternAtom (xdisplay, "XdndAware", TRUE), XA_ATOM, - 32, PropModeReplace, - (const unsigned char *) &xdnd_version, 1); - - XChangeProperty (xdisplay, overlay_xwindow, - XInternAtom (xdisplay, "XdndProxy", TRUE), XA_WINDOW, - 32, PropModeReplace, (const unsigned char *) &xwindow, 1); - - /* - * XdndProxy is additionally set on the proxy window as verification that the - * XdndProxy property on the target window isn't a left-over - */ - XChangeProperty (xdisplay, xwindow, - XInternAtom (xdisplay, "XdndProxy", TRUE), XA_WINDOW, - 32, PropModeReplace, (const unsigned char *) &xwindow, 1); -} - -static void -meta_dnd_notify_dnd_enter (MetaDnd *dnd) -{ - g_signal_emit (dnd, signals[ENTER], 0); -} - -static void -meta_dnd_notify_dnd_position_change (MetaDnd *dnd, - int x, - int y) -{ - g_signal_emit (dnd, signals[POSITION_CHANGE], 0, x, y); -} - -static void -meta_dnd_notify_dnd_leave (MetaDnd *dnd) -{ - g_signal_emit (dnd, signals[LEAVE], 0); -} - -/* - * Process Xdnd events - * - * We pass the position and leave events to the plugin via a signal - * where the actual drag & drop handling happens. - * - * http://www.freedesktop.org/wiki/Specifications/XDND - */ -gboolean -meta_dnd_handle_xdnd_event (MetaBackend *backend, - MetaCompositorX11 *compositor_x11, - Display *xdisplay, - XEvent *xev) -{ - MetaDnd *dnd = meta_backend_get_dnd (backend); - MetaCompositor *compositor = META_COMPOSITOR (compositor_x11); - Window output_window; - ClutterStage *stage; - - if (xev->xany.type != ClientMessage) - return FALSE; - - output_window = meta_compositor_x11_get_output_xwindow (compositor_x11); - stage = meta_compositor_get_stage (compositor); - if (xev->xany.window != output_window && - xev->xany.window != meta_x11_get_stage_window (stage)) - return FALSE; - - if (xev->xclient.message_type == XInternAtom (xdisplay, "XdndPosition", TRUE)) - { - XEvent xevent; - Window src = xev->xclient.data.l[0]; - - memset (&xevent, 0, sizeof(xevent)); - xevent.xany.type = ClientMessage; - xevent.xany.display = xdisplay; - xevent.xclient.window = src; - xevent.xclient.message_type = XInternAtom (xdisplay, "XdndStatus", TRUE); - xevent.xclient.format = 32; - xevent.xclient.data.l[0] = output_window; - /* flags: bit 0: will we accept the drop? bit 1: do we want more position messages */ - xevent.xclient.data.l[1] = 2; - xevent.xclient.data.l[4] = None; - - XSendEvent (xdisplay, src, False, 0, &xevent); - - meta_dnd_notify_dnd_position_change (dnd, - (int)(xev->xclient.data.l[2] >> 16), - (int)(xev->xclient.data.l[2] & 0xFFFF)); - - return TRUE; - } - else if (xev->xclient.message_type == XInternAtom (xdisplay, "XdndLeave", TRUE)) - { - meta_dnd_notify_dnd_leave (dnd); - - return TRUE; - } - else if (xev->xclient.message_type == XInternAtom (xdisplay, "XdndEnter", TRUE)) - { - meta_dnd_notify_dnd_enter (dnd); - - return TRUE; - } - - return FALSE; -} - -#ifdef HAVE_WAYLAND -static void -meta_dnd_wayland_on_motion_event (ClutterActor *actor, - ClutterEvent *event, - MetaDnd *dnd) -{ - MetaDndPrivate *priv = meta_dnd_get_instance_private (dnd); - MetaWaylandDragGrab *current_grab; - gfloat event_x, event_y; - - g_return_if_fail (event != NULL); - - clutter_event_get_coords (event, &event_x, &event_y); - meta_dnd_notify_dnd_position_change (dnd, (int)event_x, (int)event_y); - - current_grab = meta_wayland_data_device_get_current_grab (&priv->wl_compositor->seat->data_device); - if (current_grab) - meta_wayland_drag_grab_update_feedback_actor (current_grab, event); -} - -static void -meta_dnd_wayland_end_notify (ClutterActor *actor, - ClutterEvent *event, - MetaDnd *dnd) -{ - MetaDndPrivate *priv = meta_dnd_get_instance_private (dnd); - - meta_wayland_data_device_end_drag (&priv->wl_compositor->seat->data_device); - meta_dnd_wayland_handle_end_modal (priv->compositor); -} - -static void -meta_dnd_wayland_on_button_released (ClutterActor *actor, - ClutterEvent *event, - MetaDnd *dnd) -{ - meta_dnd_wayland_end_notify (actor, event, dnd); -} - -static void -meta_dnd_wayland_on_key_pressed (ClutterActor *actor, - ClutterEvent *event, - MetaDnd *dnd) -{ - guint key = clutter_event_get_key_symbol (event); - - if (key != CLUTTER_KEY_Escape) - return; - - meta_dnd_wayland_end_notify (actor, event, dnd); -} - -void -meta_dnd_wayland_handle_begin_modal (MetaCompositor *compositor) -{ - MetaWaylandCompositor *wl_compositor = meta_wayland_compositor_get_default (); - MetaDnd *dnd = meta_backend_get_dnd (meta_get_backend ()); - MetaDndPrivate *priv = meta_dnd_get_instance_private (dnd); - - if (priv->handler_id[0] == 0 && - meta_wayland_data_device_get_current_grab (&wl_compositor->seat->data_device) != NULL) - { - ClutterStage *stage = meta_compositor_get_stage (compositor); - - priv->compositor = compositor; - priv->wl_compositor = wl_compositor; - - priv->handler_id[0] = g_signal_connect (stage, - "motion-event", - G_CALLBACK (meta_dnd_wayland_on_motion_event), - dnd); - - priv->handler_id[1] = g_signal_connect (stage, - "button-release-event", - G_CALLBACK (meta_dnd_wayland_on_button_released), - dnd); - - priv->handler_id[2] = g_signal_connect (stage, - "key-press-event", - G_CALLBACK (meta_dnd_wayland_on_key_pressed), - dnd); - - meta_dnd_notify_dnd_enter (dnd); - } -} - -void -meta_dnd_wayland_handle_end_modal (MetaCompositor *compositor) -{ - MetaDnd *dnd = meta_backend_get_dnd (meta_get_backend ()); - MetaDndPrivate *priv = meta_dnd_get_instance_private (dnd); - ClutterStage *stage = meta_compositor_get_stage (compositor); - unsigned int i; - - if (!priv->compositor) - return; - - for (i = 0; i < G_N_ELEMENTS (priv->handler_id); i++) - g_clear_signal_handler (&priv->handler_id[i], stage); - - priv->compositor = NULL; - priv->wl_compositor = NULL; - - meta_dnd_notify_dnd_leave (dnd); -} -#endif diff --git a/src/compositor/meta-feedback-actor-private.h b/src/compositor/meta-feedback-actor-private.h deleted file mode 100644 index 86cacb360..000000000 --- a/src/compositor/meta-feedback-actor-private.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * meta-feedback-actor-private.h: Actor for painting user interaction feedback - * - * Copyright 2014 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 . - * - * Author: Carlos Garnacho - */ - -#ifndef META_FEEDBACK_ACTOR_PRIVATE_H -#define META_FEEDBACK_ACTOR_PRIVATE_H - -#include "clutter/clutter.h" - -/** - * MetaFeedbackActor: - * - * This class handles the rendering of user interaction feedback - */ - -#define META_TYPE_FEEDBACK_ACTOR (meta_feedback_actor_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaFeedbackActor, - meta_feedback_actor, - META, FEEDBACK_ACTOR, - ClutterActor) - - -struct _MetaFeedbackActorClass -{ - /*< private >*/ - ClutterActorClass parent_class; -}; - - -ClutterActor *meta_feedback_actor_new (float anchor_x, - float anchor_y); - -void meta_feedback_actor_set_anchor (MetaFeedbackActor *actor, - float anchor_x, - float anchor_y); -void meta_feedback_actor_get_anchor (MetaFeedbackActor *actor, - float *anchor_x, - float *anchor_y); - -void meta_feedback_actor_set_position (MetaFeedbackActor *self, - float x, - float y); - -void meta_feedback_actor_update (MetaFeedbackActor *self, - const ClutterEvent *event); - -void meta_feedback_actor_set_geometry_scale (MetaFeedbackActor *self, - int geometry_scale); - -int meta_feedback_actor_get_geometry_scale (MetaFeedbackActor *self); - -#endif /* META_FEEDBACK_ACTOR_PRIVATE_H */ diff --git a/src/compositor/meta-feedback-actor.c b/src/compositor/meta-feedback-actor.c deleted file mode 100644 index 4b4bed78a..000000000 --- a/src/compositor/meta-feedback-actor.c +++ /dev/null @@ -1,285 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * Copyright 2014 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 . - * - * Author: Carlos Garnacho - */ - -/** - * SECTION:meta-feedback-actor - * @title: MetaFeedbackActor - * @short_description: Actor for painting user interaction feedback - */ - -#include "config.h" - -#include "compositor/compositor-private.h" -#include "compositor/meta-feedback-actor-private.h" -#include "core/display-private.h" - -enum -{ - PROP_ANCHOR_X = 1, - PROP_ANCHOR_Y -}; - -typedef struct _MetaFeedbackActorPrivate MetaFeedbackActorPrivate; - -struct _MetaFeedbackActorPrivate -{ - float anchor_x; - float anchor_y; - float pos_x; - float pos_y; - - int geometry_scale; -}; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaFeedbackActor, meta_feedback_actor, CLUTTER_TYPE_ACTOR) - -static void -meta_feedback_actor_constructed (GObject *object) -{ - MetaDisplay *display; - ClutterActor *feedback_group; - - display = meta_get_display (); - feedback_group = meta_get_feedback_group_for_display (display); - clutter_actor_add_child (feedback_group, CLUTTER_ACTOR (object)); -} - -static void -meta_feedback_actor_update_position (MetaFeedbackActor *self) -{ - MetaFeedbackActorPrivate *priv = meta_feedback_actor_get_instance_private (self); - - clutter_actor_set_position (CLUTTER_ACTOR (self), - priv->pos_x - - (priv->anchor_x * priv->geometry_scale), - priv->pos_y - - (priv->anchor_y * priv->geometry_scale)); -} - -static void -meta_feedback_actor_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaFeedbackActor *self = META_FEEDBACK_ACTOR (object); - MetaFeedbackActorPrivate *priv = meta_feedback_actor_get_instance_private (self); - - switch (prop_id) - { - case PROP_ANCHOR_X: - priv->anchor_x = g_value_get_int (value); - meta_feedback_actor_update_position (self); - break; - case PROP_ANCHOR_Y: - priv->anchor_y = g_value_get_int (value); - meta_feedback_actor_update_position (self); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_feedback_actor_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaFeedbackActor *self = META_FEEDBACK_ACTOR (object); - MetaFeedbackActorPrivate *priv = meta_feedback_actor_get_instance_private (self); - - switch (prop_id) - { - case PROP_ANCHOR_X: - g_value_set_float (value, priv->anchor_x); - break; - case PROP_ANCHOR_Y: - g_value_set_float (value, priv->anchor_y); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_feedback_actor_class_init (MetaFeedbackActorClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GParamSpec *pspec; - - object_class->constructed = meta_feedback_actor_constructed; - object_class->set_property = meta_feedback_actor_set_property; - object_class->get_property = meta_feedback_actor_get_property; - - pspec = g_param_spec_float ("anchor-x", - "Anchor X", - "The X axis of the anchor point", - 0, G_MAXFLOAT, 0, - G_PARAM_READWRITE); - - g_object_class_install_property (object_class, - PROP_ANCHOR_X, - pspec); - - pspec = g_param_spec_float ("anchor-y", - "Anchor Y", - "The Y axis of the anchor point", - 0, G_MAXFLOAT, 0, - G_PARAM_READWRITE); - - g_object_class_install_property (object_class, - PROP_ANCHOR_Y, - pspec); -} - -static void -meta_feedback_actor_init (MetaFeedbackActor *self) -{ - clutter_actor_set_reactive (CLUTTER_ACTOR (self), FALSE); -} - -/** - * meta_feedback_actor_new: - * - * Creates a new actor to draw the current drag and drop surface. - * - * Return value: the newly created background actor - */ -ClutterActor * -meta_feedback_actor_new (float anchor_x, - float anchor_y) -{ - MetaFeedbackActor *self; - - self = g_object_new (META_TYPE_FEEDBACK_ACTOR, - "anchor-x", anchor_x, - "anchor-y", anchor_y, - NULL); - - return CLUTTER_ACTOR (self); -} - -void -meta_feedback_actor_set_anchor (MetaFeedbackActor *self, - float anchor_x, - float anchor_y) -{ - MetaFeedbackActorPrivate *priv; - - g_return_if_fail (META_IS_FEEDBACK_ACTOR (self)); - - priv = meta_feedback_actor_get_instance_private (self); - - if (priv->anchor_x == anchor_x && priv->anchor_y == anchor_y) - return; - - if (priv->anchor_x != anchor_x) - { - priv->anchor_x = anchor_x; - g_object_notify (G_OBJECT (self), "anchor-x"); - } - - if (priv->anchor_y != anchor_y) - { - priv->anchor_y = anchor_y; - g_object_notify (G_OBJECT (self), "anchor-y"); - } - - meta_feedback_actor_update_position (self); -} - -void -meta_feedback_actor_get_anchor (MetaFeedbackActor *self, - float *anchor_x, - float *anchor_y) -{ - MetaFeedbackActorPrivate *priv; - - g_return_if_fail (META_IS_FEEDBACK_ACTOR (self)); - - priv = meta_feedback_actor_get_instance_private (self); - - if (anchor_x) - *anchor_x = priv->anchor_x; - if (anchor_y) - *anchor_y = priv->anchor_y; -} - -void -meta_feedback_actor_set_position (MetaFeedbackActor *self, - float x, - float y) -{ - MetaFeedbackActorPrivate *priv; - - g_return_if_fail (META_IS_FEEDBACK_ACTOR (self)); - - priv = meta_feedback_actor_get_instance_private (self); - priv->pos_x = x; - priv->pos_y = y; - - meta_feedback_actor_update_position (self); -} - -void -meta_feedback_actor_update (MetaFeedbackActor *self, - const ClutterEvent *event) -{ - graphene_point_t point; - - g_return_if_fail (META_IS_FEEDBACK_ACTOR (self)); - g_return_if_fail (event != NULL); - - clutter_event_get_position (event, &point); - meta_feedback_actor_set_position (self, point.x, point.y); -} - -void -meta_feedback_actor_set_geometry_scale (MetaFeedbackActor *self, - int geometry_scale) -{ - MetaFeedbackActorPrivate *priv = - meta_feedback_actor_get_instance_private (self); - graphene_matrix_t child_transform; - - if (priv->geometry_scale == geometry_scale) - return; - - priv->geometry_scale = geometry_scale; - - graphene_matrix_init_scale (&child_transform, - geometry_scale, - geometry_scale, - 1); - clutter_actor_set_child_transform (CLUTTER_ACTOR (self), - &child_transform); -} - -int -meta_feedback_actor_get_geometry_scale (MetaFeedbackActor *self) -{ - MetaFeedbackActorPrivate *priv = - meta_feedback_actor_get_instance_private (self); - - return priv->geometry_scale; -} diff --git a/src/compositor/meta-later-private.h b/src/compositor/meta-later-private.h deleted file mode 100644 index c8d0f80a8..000000000 --- a/src/compositor/meta-later-private.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2020 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 . - */ - -#ifndef META_LATER_PRIVATE_H -#define META_LATER_PRIVATE_H - -typedef struct _MetaLaters MetaLaters; -typedef struct _MetaCompositor MetaCompositor; - -MetaLaters * meta_laters_new (MetaCompositor *compositor); - -void meta_laters_free (MetaLaters *laters); - -#endif /* META_LATER_PRIVATE_H */ diff --git a/src/compositor/meta-later.c b/src/compositor/meta-later.c deleted file mode 100644 index 43da6d8e6..000000000 --- a/src/compositor/meta-later.c +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2005 Elijah Newren - * Copyright (C) 2020 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 . - */ - -#include "config.h" - -#include "compositor/meta-later-private.h" - -#include "cogl/cogl.h" -#include "compositor/compositor-private.h" -#include "core/display-private.h" -#include "meta/meta-later.h" - -typedef struct _MetaLater -{ - unsigned int id; - unsigned int ref_count; - MetaLaterType when; - - GSourceFunc func; - gpointer user_data; - GDestroyNotify destroy_notify; - - guint source_id; - gboolean run_once; -} MetaLater; - -#define META_LATER_N_TYPES (META_LATER_IDLE + 1) - -struct _MetaLaters -{ - MetaCompositor *compositor; - - unsigned int last_later_id; - - GSList *laters[META_LATER_N_TYPES]; - - gulong before_update_handler_id; -}; - -static MetaLater * -meta_later_ref (MetaLater *later) -{ - later->ref_count++; - return later; -} - -static void -meta_later_unref (MetaLater *later) -{ - if (--later->ref_count == 0) - { - if (later->destroy_notify) - { - later->destroy_notify (later->user_data); - later->destroy_notify = NULL; - } - - g_free (later); - } -} - -static void -meta_later_destroy (MetaLater *later) -{ - g_clear_handle_id (&later->source_id, g_source_remove); - later->func = NULL; - meta_later_unref (later); -} - -#ifdef COGL_HAS_TRACING -static const char * -later_type_to_string (MetaLaterType when) -{ - switch (when) - { - case META_LATER_RESIZE: - return "Later (resize)"; - case META_LATER_CALC_SHOWING: - return "Later (calc-showing)"; - case META_LATER_CHECK_FULLSCREEN: - return "Later (check-fullscreen)"; - case META_LATER_SYNC_STACK: - return "Later (sync-stack)"; - case META_LATER_BEFORE_REDRAW: - return "Later (before-redraw)"; - case META_LATER_IDLE: - return "Later (idle)"; - } - - return "unknown"; -} -#endif - -static gboolean -meta_later_invoke (MetaLater *later) -{ - COGL_TRACE_BEGIN_SCOPED (later, later_type_to_string (later->when)); - return later->func (later->user_data); -} - -static gboolean -remove_later_from_list (unsigned int later_id, - GSList **laters_list) -{ - GSList *l; - - for (l = *laters_list; l; l = l->next) - { - MetaLater *later = l->data; - - if (later->id == later_id) - { - *laters_list = g_slist_delete_link (*laters_list, l); - meta_later_destroy (later); - return TRUE; - } - } - - return FALSE; -} - -static void -run_repaint_laters (GSList **laters_list) -{ - g_autoptr (GSList) laters_copy = NULL; - GSList *l; - - for (l = *laters_list; l; l = l->next) - { - MetaLater *later = l->data; - - if (!later->source_id || - (later->when <= META_LATER_BEFORE_REDRAW && !later->run_once)) - laters_copy = g_slist_prepend (laters_copy, meta_later_ref (later)); - } - laters_copy = g_slist_reverse (laters_copy); - - for (l = laters_copy; l; l = l->next) - { - MetaLater *later = l->data; - - if (!later->func) - remove_later_from_list (later->id, laters_list); - else if (!meta_later_invoke (later)) - remove_later_from_list (later->id, laters_list); - - meta_later_unref (later); - } -} - -static void -on_before_update (ClutterStage *stage, - ClutterStageView *stage_view, - MetaLaters *laters) -{ - unsigned int i; - GSList *l; - gboolean needs_schedule_update = FALSE; - - for (i = 0; i < G_N_ELEMENTS (laters->laters); i++) - run_repaint_laters (&laters->laters[i]); - - for (i = 0; i < G_N_ELEMENTS (laters->laters); i++) - { - for (l = laters->laters[i]; l; l = l->next) - { - MetaLater *later = l->data; - - if (!later->source_id) - needs_schedule_update = TRUE; - } - } - - if (needs_schedule_update) - clutter_stage_schedule_update (stage); -} - -static gboolean -invoke_later_idle (gpointer data) -{ - MetaLater *later = data; - - if (!later->func (later->user_data)) - { - meta_later_remove (later->id); - return FALSE; - } - else - { - later->run_once = TRUE; - return TRUE; - } -} - -static unsigned int -meta_laters_add (MetaLaters *laters, - MetaLaterType when, - GSourceFunc func, - gpointer user_data, - GDestroyNotify notify) -{ - ClutterStage *stage = meta_compositor_get_stage (laters->compositor); - MetaLater *later = g_new0 (MetaLater, 1); - - later->id = ++laters->last_later_id; - later->ref_count = 1; - later->when = when; - later->func = func; - later->user_data = user_data; - later->destroy_notify = notify; - - laters->laters[when] = g_slist_prepend (laters->laters[when], later); - - switch (when) - { - case META_LATER_RESIZE: - later->source_id = g_idle_add_full (META_PRIORITY_RESIZE, - invoke_later_idle, - later, NULL); - g_source_set_name_by_id (later->source_id, "[mutter] invoke_later_idle"); - clutter_stage_schedule_update (stage); - break; - case META_LATER_CALC_SHOWING: - case META_LATER_CHECK_FULLSCREEN: - case META_LATER_SYNC_STACK: - case META_LATER_BEFORE_REDRAW: - clutter_stage_schedule_update (stage); - break; - case META_LATER_IDLE: - later->source_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, - invoke_later_idle, - later, NULL); - g_source_set_name_by_id (later->source_id, "[mutter] invoke_later_idle"); - break; - } - - return later->id; -} - -/** - * meta_later_add: - * @when: enumeration value determining the phase at which to run the callback - * @func: callback to run later - * @data: data to pass to the callback - * @notify: function to call to destroy @data when it is no longer in use, or %NULL - * - * Sets up a callback to be called at some later time. @when determines the - * particular later occasion at which it is called. This is much like g_idle_add(), - * except that the functions interact properly with clutter event handling. - * If a "later" function is added from a clutter event handler, and is supposed - * to be run before the stage is redrawn, it will be run before that redraw - * of the stage, not the next one. - * - * Return value: an integer ID (guaranteed to be non-zero) that can be used - * to cancel the callback and prevent it from being run. - */ -unsigned int -meta_later_add (MetaLaterType when, - GSourceFunc func, - gpointer data, - GDestroyNotify notify) -{ - MetaDisplay *display = meta_get_display (); - MetaCompositor *compositor; - - g_return_val_if_fail (display, 0); - g_return_val_if_fail (display->compositor, 0); - - compositor = display->compositor; - return meta_laters_add (meta_compositor_get_laters (compositor), - when, func, data, notify); -} - -static void -meta_laters_remove (MetaLaters *laters, - unsigned int later_id) -{ - unsigned int i; - - for (i = 0; i < G_N_ELEMENTS (laters->laters); i++) - { - if (remove_later_from_list (later_id, &laters->laters[i])) - return; - } -} - -/** - * meta_later_remove: - * @later_id: the integer ID returned from meta_later_add() - * - * Removes a callback added with meta_later_add() - */ -void -meta_later_remove (unsigned int later_id) -{ - MetaDisplay *display = meta_get_display (); - MetaCompositor *compositor; - - g_return_if_fail (display); - - compositor = display->compositor; - if (!compositor) - return; - - meta_laters_remove (meta_compositor_get_laters (compositor), later_id); -} - -MetaLaters * -meta_laters_new (MetaCompositor *compositor) -{ - ClutterStage *stage = meta_compositor_get_stage (compositor); - MetaLaters *laters; - - laters = g_new0 (MetaLaters, 1); - laters->compositor = compositor; - - laters->before_update_handler_id = - g_signal_connect (stage, "before-update", - G_CALLBACK (on_before_update), - laters); - - return laters; -} - -void -meta_laters_free (MetaLaters *laters) -{ - ClutterStage *stage = meta_compositor_get_stage (laters->compositor); - unsigned int i; - - for (i = 0; i < G_N_ELEMENTS (laters->laters); i++) - g_slist_free_full (laters->laters[i], (GDestroyNotify) meta_later_unref); - - g_clear_signal_handler (&laters->before_update_handler_id, stage); - g_free (laters); -} diff --git a/src/compositor/meta-module.c b/src/compositor/meta-module.c deleted file mode 100644 index a8ed15bae..000000000 --- a/src/compositor/meta-module.c +++ /dev/null @@ -1,193 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (c) 2008 Intel Corp. - * - * Author: Tomas Frydrych - * - * 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 . - */ - -#include "config.h" - -#include "compositor/meta-module.h" - -#include - -#include "meta/meta-plugin.h" - -enum -{ - PROP_0, - PROP_PATH, -}; - -struct _MetaModulePrivate -{ - GModule *lib; - gchar *path; - GType plugin_type; -}; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaModule, meta_module, G_TYPE_TYPE_MODULE); - -static gboolean -meta_module_load (GTypeModule *gmodule) -{ - MetaModulePrivate *priv = META_MODULE (gmodule)->priv; - GType (*register_type) (GTypeModule *) = NULL; - - if (priv->lib && priv->plugin_type) - return TRUE; - - g_assert (priv->path); - - if (!priv->lib && - !(priv->lib = g_module_open (priv->path, 0))) - { - g_warning ("Could not load library [%s (%s)]", - priv->path, g_module_error ()); - return FALSE; - } - - if (g_module_symbol (priv->lib, "meta_plugin_register_type", - (gpointer *)(void *)®ister_type) && - register_type) - { - GType plugin_type; - - if (!(plugin_type = register_type (gmodule))) - { - g_warning ("Could not register type for plugin %s", - priv->path); - return FALSE; - } - else - { - priv->plugin_type = plugin_type; - } - - return TRUE; - } - else - g_warning ("Broken plugin module [%s]", priv->path); - - return FALSE; -} - -static void -meta_module_unload (GTypeModule *gmodule) -{ - MetaModulePrivate *priv = META_MODULE (gmodule)->priv; - - g_module_close (priv->lib); - - priv->lib = NULL; - priv->plugin_type = 0; -} - -static void -meta_module_dispose (GObject *object) -{ - G_OBJECT_CLASS (meta_module_parent_class)->dispose (object); -} - -static void -meta_module_finalize (GObject *object) -{ - MetaModulePrivate *priv = META_MODULE (object)->priv; - - g_free (priv->path); - priv->path = NULL; - - G_OBJECT_CLASS (meta_module_parent_class)->finalize (object); -} - -static void -meta_module_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaModulePrivate *priv = META_MODULE (object)->priv; - - switch (prop_id) - { - case PROP_PATH: - g_free (priv->path); - priv->path = g_value_dup_string (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_module_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaModulePrivate *priv = META_MODULE (object)->priv; - - switch (prop_id) - { - case PROP_PATH: - g_value_set_string (value, priv->path); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_module_class_init (MetaModuleClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GTypeModuleClass *gmodule_class = G_TYPE_MODULE_CLASS (klass); - - gobject_class->finalize = meta_module_finalize; - gobject_class->dispose = meta_module_dispose; - gobject_class->set_property = meta_module_set_property; - gobject_class->get_property = meta_module_get_property; - - gmodule_class->load = meta_module_load; - gmodule_class->unload = meta_module_unload; - - g_object_class_install_property (gobject_class, - PROP_PATH, - g_param_spec_string ("path", - "Path", - "Load path", - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY)); -} - -static void -meta_module_init (MetaModule *self) -{ - self->priv = meta_module_get_instance_private (self); -} - -GType -meta_module_get_plugin_type (MetaModule *module) -{ - MetaModulePrivate *priv = META_MODULE (module)->priv; - - return priv->plugin_type; -} - diff --git a/src/compositor/meta-module.h b/src/compositor/meta-module.h deleted file mode 100644 index dd6d5a685..000000000 --- a/src/compositor/meta-module.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (c) 2008 Intel Corp. - * - * Author: Tomas Frydrych - * - * 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 . - */ - -#ifndef META_MODULE_H_ -#define META_MODULE_H_ - -#include - -#define META_TYPE_MODULE (meta_module_get_type ()) -#define META_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MODULE, MetaModule)) -#define META_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MODULE, MetaModuleClass)) -#define META_IS_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_MODULE_TYPE)) -#define META_IS_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MODULE)) -#define META_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MODULE, MetaModuleClass)) - -typedef struct _MetaModule MetaModule; -typedef struct _MetaModuleClass MetaModuleClass; -typedef struct _MetaModulePrivate MetaModulePrivate; - -struct _MetaModule -{ - GTypeModule parent; - - MetaModulePrivate *priv; -}; - -struct _MetaModuleClass -{ - GTypeModuleClass parent_class; -}; - - -GType meta_module_get_type (void); - -GType meta_module_get_plugin_type (MetaModule *module); - -#endif diff --git a/src/compositor/meta-plugin-manager.c b/src/compositor/meta-plugin-manager.c deleted file mode 100644 index ab7fce663..000000000 --- a/src/compositor/meta-plugin-manager.c +++ /dev/null @@ -1,419 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (c) 2008 Intel Corp. - * - * Author: Tomas Frydrych - * - * 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 . - */ - -#include "config.h" - -#include "compositor/meta-plugin-manager.h" - -#include -#include - -#include "backends/x11/meta-clutter-backend-x11.h" -#include "compositor/compositor-private.h" -#include "compositor/meta-module.h" -#include "core/meta-close-dialog-default-private.h" -#include "core/meta-inhibit-shortcuts-dialog-default-private.h" -#include "core/window-private.h" -#include "meta/meta-x11-errors.h" -#include "meta/prefs.h" -#include "meta/workspace.h" - -static GType plugin_type = G_TYPE_NONE; - -struct MetaPluginManager -{ - MetaCompositor *compositor; - MetaPlugin *plugin; -}; - -void -meta_plugin_manager_set_plugin_type (GType gtype) -{ - if (plugin_type != G_TYPE_NONE) - meta_fatal ("Mutter plugin already set: %s", g_type_name (plugin_type)); - - plugin_type = gtype; -} - -/* - * Loads the given plugin. - */ -void -meta_plugin_manager_load (const gchar *plugin_name) -{ - const gchar *dpath = MUTTER_PLUGIN_DIR "/"; - gchar *path; - MetaModule *module; - - if (g_path_is_absolute (plugin_name)) - path = g_strdup (plugin_name); - else - path = g_strconcat (dpath, plugin_name, ".so", NULL); - - module = g_object_new (META_TYPE_MODULE, "path", path, NULL); - if (!module || !g_type_module_use (G_TYPE_MODULE (module))) - { - /* This is fatal under the assumption that a monitoring - * process like gnome-session will take over and handle - * our untimely exit. - */ - g_printerr ("Unable to load plugin module [%s]: %s", - path, g_module_error()); - exit (1); - } - - meta_plugin_manager_set_plugin_type (meta_module_get_plugin_type (module)); - - g_type_module_unuse (G_TYPE_MODULE (module)); - g_free (path); -} - -static void -on_confirm_display_change (MetaMonitorManager *monitors, - MetaPluginManager *plugin_mgr) -{ - meta_plugin_manager_confirm_display_change (plugin_mgr); -} - -MetaPluginManager * -meta_plugin_manager_new (MetaCompositor *compositor) -{ - MetaPluginManager *plugin_mgr; - MetaPluginClass *klass; - MetaPlugin *plugin; - MetaMonitorManager *monitors; - - plugin_mgr = g_new0 (MetaPluginManager, 1); - plugin_mgr->compositor = compositor; - plugin_mgr->plugin = plugin = g_object_new (plugin_type, NULL); - - _meta_plugin_set_compositor (plugin, compositor); - - klass = META_PLUGIN_GET_CLASS (plugin); - - if (klass->start) - klass->start (plugin); - - monitors = meta_monitor_manager_get (); - g_signal_connect (monitors, "confirm-display-change", - G_CALLBACK (on_confirm_display_change), plugin_mgr); - - return plugin_mgr; -} - -static void -meta_plugin_manager_kill_window_effects (MetaPluginManager *plugin_mgr, - MetaWindowActor *actor) -{ - MetaPlugin *plugin = plugin_mgr->plugin; - MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); - - if (klass->kill_window_effects) - klass->kill_window_effects (plugin, actor); -} - -static void -meta_plugin_manager_kill_switch_workspace (MetaPluginManager *plugin_mgr) -{ - MetaPlugin *plugin = plugin_mgr->plugin; - MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); - - if (klass->kill_switch_workspace) - klass->kill_switch_workspace (plugin); -} - -/* - * Public method that the compositor hooks into for events that require - * no additional parameters. - * - * Returns TRUE if the plugin handled the event type (i.e., - * if the return value is FALSE, there will be no subsequent call to the - * manager completed() callback, and the compositor must ensure that any - * appropriate post-effect cleanup is carried out. - */ -gboolean -meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr, - MetaWindowActor *actor, - MetaPluginEffect event) -{ - MetaPlugin *plugin = plugin_mgr->plugin; - MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); - MetaDisplay *display = meta_compositor_get_display (plugin_mgr->compositor); - gboolean retval = FALSE; - - if (display->display_opening) - return FALSE; - - switch (event) - { - case META_PLUGIN_MINIMIZE: - if (klass->minimize) - { - retval = TRUE; - meta_plugin_manager_kill_window_effects (plugin_mgr, - actor); - klass->minimize (plugin, actor); - } - break; - case META_PLUGIN_UNMINIMIZE: - if (klass->unminimize) - { - retval = TRUE; - meta_plugin_manager_kill_window_effects (plugin_mgr, - actor); - klass->unminimize (plugin, actor); - } - break; - case META_PLUGIN_MAP: - if (klass->map) - { - retval = TRUE; - meta_plugin_manager_kill_window_effects (plugin_mgr, - actor); - klass->map (plugin, actor); - } - break; - case META_PLUGIN_DESTROY: - if (klass->destroy) - { - retval = TRUE; - meta_plugin_manager_kill_window_effects (plugin_mgr, - actor); - klass->destroy (plugin, actor); - } - break; - default: - g_warning ("Incorrect handler called for event %d", event); - } - - return retval; -} - -void -meta_plugin_manager_event_size_changed (MetaPluginManager *plugin_mgr, - MetaWindowActor *actor) -{ - MetaPlugin *plugin = plugin_mgr->plugin; - MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); - - if (klass->size_changed) - klass->size_changed (plugin, actor); -} - -gboolean -meta_plugin_manager_event_size_change (MetaPluginManager *plugin_mgr, - MetaWindowActor *actor, - MetaSizeChange which_change, - MetaRectangle *old_frame_rect, - MetaRectangle *old_buffer_rect) -{ - MetaPlugin *plugin = plugin_mgr->plugin; - MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); - MetaDisplay *display = meta_compositor_get_display (plugin_mgr->compositor); - - if (display->display_opening) - return FALSE; - - if (!klass->size_change) - return FALSE; - - meta_plugin_manager_kill_window_effects (plugin_mgr, actor); - klass->size_change (plugin, actor, which_change, old_frame_rect, old_buffer_rect); - return TRUE; -} - -/* - * The public method that the compositor hooks into for desktop switching. - * - * Returns TRUE if the plugin handled the event type (i.e., - * if the return value is FALSE, there will be no subsequent call to the - * manager completed() callback, and the compositor must ensure that any - * appropriate post-effect cleanup is carried out. - */ -gboolean -meta_plugin_manager_switch_workspace (MetaPluginManager *plugin_mgr, - gint from, - gint to, - MetaMotionDirection direction) -{ - MetaPlugin *plugin = plugin_mgr->plugin; - MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); - MetaDisplay *display = meta_compositor_get_display (plugin_mgr->compositor); - gboolean retval = FALSE; - - if (display->display_opening) - return FALSE; - - if (klass->switch_workspace) - { - retval = TRUE; - meta_plugin_manager_kill_switch_workspace (plugin_mgr); - klass->switch_workspace (plugin, from, to, direction); - } - - return retval; -} - -gboolean -meta_plugin_manager_filter_keybinding (MetaPluginManager *plugin_mgr, - MetaKeyBinding *binding) -{ - MetaPlugin *plugin = plugin_mgr->plugin; - MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); - - if (klass->keybinding_filter) - return klass->keybinding_filter (plugin, binding); - - return FALSE; -} - -gboolean -meta_plugin_manager_xevent_filter (MetaPluginManager *plugin_mgr, - XEvent *xev) -{ - MetaPlugin *plugin = plugin_mgr->plugin; - - return _meta_plugin_xevent_filter (plugin, xev); -} - -void -meta_plugin_manager_confirm_display_change (MetaPluginManager *plugin_mgr) -{ - MetaPlugin *plugin = plugin_mgr->plugin; - MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); - - if (klass->confirm_display_change) - klass->confirm_display_change (plugin); - else - meta_plugin_complete_display_change (plugin, TRUE); -} - -gboolean -meta_plugin_manager_show_tile_preview (MetaPluginManager *plugin_mgr, - MetaWindow *window, - MetaRectangle *tile_rect, - int tile_monitor_number) -{ - MetaPlugin *plugin = plugin_mgr->plugin; - MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); - MetaDisplay *display = meta_compositor_get_display (plugin_mgr->compositor); - - if (display->display_opening) - return FALSE; - - if (klass->show_tile_preview) - { - klass->show_tile_preview (plugin, window, tile_rect, tile_monitor_number); - return TRUE; - } - - return FALSE; -} - -gboolean -meta_plugin_manager_hide_tile_preview (MetaPluginManager *plugin_mgr) -{ - MetaPlugin *plugin = plugin_mgr->plugin; - MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); - MetaDisplay *display = meta_compositor_get_display (plugin_mgr->compositor); - - if (display->display_opening) - return FALSE; - - if (klass->hide_tile_preview) - { - klass->hide_tile_preview (plugin); - return TRUE; - } - - return FALSE; -} - -void -meta_plugin_manager_show_window_menu (MetaPluginManager *plugin_mgr, - MetaWindow *window, - MetaWindowMenuType menu, - int x, - int y) -{ - MetaPlugin *plugin = plugin_mgr->plugin; - MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); - MetaDisplay *display = meta_compositor_get_display (plugin_mgr->compositor); - - if (display->display_opening) - return; - - if (klass->show_window_menu) - klass->show_window_menu (plugin, window, menu, x, y); -} - -void -meta_plugin_manager_show_window_menu_for_rect (MetaPluginManager *plugin_mgr, - MetaWindow *window, - MetaWindowMenuType menu, - MetaRectangle *rect) -{ - MetaPlugin *plugin = plugin_mgr->plugin; - MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); - MetaDisplay *display = meta_compositor_get_display (plugin_mgr->compositor); - - if (display->display_opening) - return; - - if (klass->show_window_menu_for_rect) - klass->show_window_menu_for_rect (plugin, window, menu, rect); -} - -MetaCloseDialog * -meta_plugin_manager_create_close_dialog (MetaPluginManager *plugin_mgr, - MetaWindow *window) -{ - MetaPlugin *plugin = plugin_mgr->plugin; - MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); - - if (klass->create_close_dialog) - return klass->create_close_dialog (plugin, window); - - return meta_close_dialog_default_new (window); -} - -MetaInhibitShortcutsDialog * -meta_plugin_manager_create_inhibit_shortcuts_dialog (MetaPluginManager *plugin_mgr, - MetaWindow *window) -{ - MetaPlugin *plugin = plugin_mgr->plugin; - MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); - - if (klass->create_inhibit_shortcuts_dialog) - return klass->create_inhibit_shortcuts_dialog (plugin, window); - - return meta_inhibit_shortcuts_dialog_default_new (window); -} - -void -meta_plugin_manager_locate_pointer (MetaPluginManager *plugin_mgr) -{ - MetaPlugin *plugin = plugin_mgr->plugin; - MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); - - if (klass->locate_pointer) - klass->locate_pointer (plugin); -} diff --git a/src/compositor/meta-plugin-manager.h b/src/compositor/meta-plugin-manager.h deleted file mode 100644 index d1c007fa1..000000000 --- a/src/compositor/meta-plugin-manager.h +++ /dev/null @@ -1,105 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (c) 2008 Intel Corp. - * - * Author: Tomas Frydrych - * - * 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 . - */ - -#ifndef META_PLUGIN_MANAGER_H_ -#define META_PLUGIN_MANAGER_H_ - -#include "core/util-private.h" -#include "meta/meta-plugin.h" -#include "meta/types.h" - -typedef enum -{ - META_PLUGIN_NONE, - META_PLUGIN_MINIMIZE, - META_PLUGIN_MAP, - META_PLUGIN_DESTROY, - META_PLUGIN_SWITCH_WORKSPACE, - META_PLUGIN_UNMINIMIZE, - META_PLUGIN_SIZE_CHANGE, -} MetaPluginEffect; - -/** - * MetaPluginManager: (skip) - * - */ -typedef struct MetaPluginManager MetaPluginManager; - -MetaPluginManager * meta_plugin_manager_new (MetaCompositor *compositor); - -META_EXPORT_TEST -void meta_plugin_manager_load (const gchar *plugin_name); - -gboolean meta_plugin_manager_event_simple (MetaPluginManager *mgr, - MetaWindowActor *actor, - MetaPluginEffect event); - -void meta_plugin_manager_event_size_changed (MetaPluginManager *mgr, - MetaWindowActor *actor); - -gboolean meta_plugin_manager_event_size_change (MetaPluginManager *mgr, - MetaWindowActor *actor, - MetaSizeChange which_change, - MetaRectangle *old_frame_rect, - MetaRectangle *old_buffer_rect); - -gboolean meta_plugin_manager_switch_workspace (MetaPluginManager *mgr, - gint from, - gint to, - MetaMotionDirection direction); - -gboolean meta_plugin_manager_filter_keybinding (MetaPluginManager *mgr, - MetaKeyBinding *binding); - -gboolean meta_plugin_manager_xevent_filter (MetaPluginManager *mgr, - XEvent *xev); -gboolean _meta_plugin_xevent_filter (MetaPlugin *plugin, - XEvent *xev); - -void meta_plugin_manager_confirm_display_change (MetaPluginManager *mgr); - -gboolean meta_plugin_manager_show_tile_preview (MetaPluginManager *mgr, - MetaWindow *window, - MetaRectangle *tile_rect, - int tile_monitor_number); -gboolean meta_plugin_manager_hide_tile_preview (MetaPluginManager *mgr); - -void meta_plugin_manager_show_window_menu (MetaPluginManager *mgr, - MetaWindow *window, - MetaWindowMenuType menu, - int x, - int y); - -void meta_plugin_manager_show_window_menu_for_rect (MetaPluginManager *mgr, - MetaWindow *window, - MetaWindowMenuType menu, - MetaRectangle *rect); - -MetaCloseDialog * meta_plugin_manager_create_close_dialog (MetaPluginManager *plugin_mgr, - MetaWindow *window); - -MetaInhibitShortcutsDialog * - meta_plugin_manager_create_inhibit_shortcuts_dialog (MetaPluginManager *plugin_mgr, - MetaWindow *window); - -void meta_plugin_manager_locate_pointer (MetaPluginManager *mgr); - -#endif diff --git a/src/compositor/meta-plugin.c b/src/compositor/meta-plugin.c deleted file mode 100644 index 188675a4d..000000000 --- a/src/compositor/meta-plugin.c +++ /dev/null @@ -1,223 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (c) 2008 Intel Corp. - * - * Author: Tomas Frydrych - * - * 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 . - */ - -/** - * SECTION:meta-plugin - * @title: MetaPlugin - * @short_description: Entry point for plugins - * - */ - -#include "config.h" - -#include "meta/meta-plugin.h" - -#include -#include -#include -#include - -#include "backends/meta-monitor-manager-private.h" -#include "backends/x11/meta-clutter-backend-x11.h" -#include "compositor/compositor-private.h" -#include "compositor/meta-window-actor-private.h" -#include "compositor/meta-plugin-manager.h" -#include "meta/display.h" -#include "meta/util.h" - - -typedef struct _MetaPluginPrivate -{ - MetaCompositor *compositor; -} MetaPluginPrivate; - -G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaPlugin, meta_plugin, G_TYPE_OBJECT); - -static void -meta_plugin_class_init (MetaPluginClass *klass) -{ -} - -static void -meta_plugin_init (MetaPlugin *self) -{ -} - -const MetaPluginInfo * -meta_plugin_get_info (MetaPlugin *plugin) -{ - MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); - - if (klass && klass->plugin_info) - return klass->plugin_info (plugin); - - return NULL; -} - -gboolean -_meta_plugin_xevent_filter (MetaPlugin *plugin, - XEvent *xev) -{ - MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin); - - if (klass->xevent_filter) - return klass->xevent_filter (plugin, xev); - else - return FALSE; -} - -void -meta_plugin_switch_workspace_completed (MetaPlugin *plugin) -{ - MetaPluginPrivate *priv = meta_plugin_get_instance_private (plugin); - - meta_switch_workspace_completed (priv->compositor); -} - -static void -meta_plugin_window_effect_completed (MetaPlugin *plugin, - MetaWindowActor *actor, - unsigned long event) -{ - meta_window_actor_effect_completed (actor, event); -} - -void -meta_plugin_minimize_completed (MetaPlugin *plugin, - MetaWindowActor *actor) -{ - meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_MINIMIZE); -} - -void -meta_plugin_unminimize_completed (MetaPlugin *plugin, - MetaWindowActor *actor) -{ - meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_UNMINIMIZE); -} - -void -meta_plugin_size_change_completed (MetaPlugin *plugin, - MetaWindowActor *actor) -{ - meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_SIZE_CHANGE); -} - -void -meta_plugin_map_completed (MetaPlugin *plugin, - MetaWindowActor *actor) -{ - meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_MAP); -} - -void -meta_plugin_destroy_completed (MetaPlugin *plugin, - MetaWindowActor *actor) -{ - meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_DESTROY); -} - -/** - * meta_plugin_begin_modal: - * @plugin: a #MetaPlugin - * @options: flags that modify the behavior of the modal grab - * @timestamp: the timestamp used for establishing grabs - * - * This function is used to grab the keyboard and mouse for the exclusive - * use of the plugin. Correct operation requires that both the keyboard - * and mouse are grabbed, or thing will break. (In particular, other - * passive X grabs in Meta can trigger but not be handled by the normal - * keybinding handling code.) However, the plugin can establish the keyboard - * and/or mouse grabs ahead of time and pass in the - * %META_MODAL_POINTER_ALREADY_GRABBED and/or %META_MODAL_KEYBOARD_ALREADY_GRABBED - * options. This facility is provided for two reasons: first to allow using - * this function to establish modality after a passive grab, and second to - * allow using obscure features of XGrabPointer() and XGrabKeyboard() without - * having to add them to this API. - * - * Return value: whether we successfully grabbed the keyboard and - * mouse and made the plugin modal. - */ -gboolean -meta_plugin_begin_modal (MetaPlugin *plugin, - MetaModalOptions options, - guint32 timestamp) -{ - MetaPluginPrivate *priv = meta_plugin_get_instance_private (plugin); - - return meta_begin_modal_for_plugin (priv->compositor, plugin, - options, timestamp); -} - -/** - * meta_plugin_end_modal: - * @plugin: a #MetaPlugin - * @timestamp: the time used for releasing grabs - * - * Ends the modal operation begun with meta_plugin_begin_modal(). This - * ungrabs both the mouse and keyboard even when - * %META_MODAL_POINTER_ALREADY_GRABBED or - * %META_MODAL_KEYBOARD_ALREADY_GRABBED were provided as options - * when beginnning the modal operation. - */ -void -meta_plugin_end_modal (MetaPlugin *plugin, - guint32 timestamp) -{ - MetaPluginPrivate *priv = meta_plugin_get_instance_private (plugin); - - meta_end_modal_for_plugin (priv->compositor, plugin, timestamp); -} - -/** - * meta_plugin_get_display: - * @plugin: a #MetaPlugin - * - * Gets the #MetaDisplay corresponding to a plugin. - * - * Return value: (transfer none): the #MetaDisplay for the plugin - */ -MetaDisplay * -meta_plugin_get_display (MetaPlugin *plugin) -{ - MetaPluginPrivate *priv = meta_plugin_get_instance_private (plugin); - MetaDisplay *display = meta_compositor_get_display (priv->compositor); - - return display; -} - -void -_meta_plugin_set_compositor (MetaPlugin *plugin, MetaCompositor *compositor) -{ - MetaPluginPrivate *priv = meta_plugin_get_instance_private (plugin); - - priv->compositor = compositor; -} - -void -meta_plugin_complete_display_change (MetaPlugin *plugin, - gboolean ok) -{ - MetaMonitorManager *manager; - - manager = meta_monitor_manager_get (); - meta_monitor_manager_confirm_configuration (manager, ok); -} diff --git a/src/compositor/meta-shadow-factory.c b/src/compositor/meta-shadow-factory.c deleted file mode 100644 index d6424d3be..000000000 --- a/src/compositor/meta-shadow-factory.c +++ /dev/null @@ -1,1066 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * Copyright 2010 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 . - */ - -/** - * SECTION:meta-shadow-factory - * @title: MetaShadowFactory - * @short_description: Create and cache shadow textures for arbitrary window shapes - */ - -#include "config.h" - -#include -#include - -#include "compositor/cogl-utils.h" -#include "compositor/region-utils.h" -#include "meta/meta-shadow-factory.h" -#include "meta/util.h" - -/* This file implements blurring the shape of a window to produce a - * shadow texture. The details are discussed below; a quick summary - * of the optimizations we use: - * - * - If the window shape is along the lines of a rounded rectangle - - * a rectangular center portion with stuff at the corners - then - * the blur of this - the shadow - can also be represented as a - * 9-sliced texture and the same texture can be used for different - * size. - * - * - We use the fact that a Gaussian blur is separable to do a - * 2D blur as 1D blur of the rows followed by a 1D blur of the - * columns. - * - * - For better cache efficiency, we blur rows, transpose the image - * in blocks, blur rows again, and then transpose back. - * - * - We approximate the 1D gaussian blur as 3 successive box filters. - */ - -typedef struct _MetaShadowCacheKey MetaShadowCacheKey; -typedef struct _MetaShadowClassInfo MetaShadowClassInfo; - -struct _MetaShadowCacheKey -{ - MetaWindowShape *shape; - int radius; - int top_fade; -}; - -struct _MetaShadow -{ - int ref_count; - - MetaShadowFactory *factory; - MetaShadowCacheKey key; - CoglTexture *texture; - CoglPipeline *pipeline; - - /* The outer order is the distance the shadow extends outside the window - * shape; the inner border is the unscaled portion inside the window - * shape */ - int outer_border_top; - int inner_border_top; - int outer_border_right; - int inner_border_right; - int outer_border_bottom; - int inner_border_bottom; - int outer_border_left; - int inner_border_left; - - guint scale_width : 1; - guint scale_height : 1; -}; - -struct _MetaShadowClassInfo -{ - const char *name; /* const so we can reuse for static definitions */ - MetaShadowParams focused; - MetaShadowParams unfocused; -}; - -struct _MetaShadowFactory -{ - GObject parent_instance; - - /* MetaShadowCacheKey => MetaShadow; the shadows are not referenced - * by the factory, they are simply removed from the table when freed */ - GHashTable *shadows; - - /* class name => MetaShadowClassInfo */ - GHashTable *shadow_classes; -}; - -enum -{ - CHANGED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -/* The first element in this array also defines the default parameters - * for newly created classes */ -MetaShadowClassInfo default_shadow_classes[] = { - { "normal", { 10, -1, 0, 3, 128 }, { 8, -1, 0, 2, 64 } }, - { "dialog", { 10, -1, 0, 3, 128 }, { 8, -1, 0, 2, 64 } }, - { "modal_dialog", { 10, -1, 0, 3, 128 }, { 8, -1, 0, 2, 64 } }, - { "utility", { 10, -1, 0, 3, 128 }, { 8, -1, 0, 2, 64 } }, - { "border", { 10, -1, 0, 3, 128 }, { 8, -1, 0, 2, 64 } }, - { "menu", { 10, -1, 0, 3, 128 }, { 8, -1, 0, 2, 64 } }, - - { "popup-menu", { 1, -1, 0, 0, 128 }, { 1, -1, 0, 0, 128 } }, - { "dropdown-menu", { 1, -1, 0, 0, 128 }, { 1, -1, 0, 0, 128 } }, - - { "attached", { 10, -1, 0, 3, 128 }, { 8, -1, 0, 2, 64 } } -}; - -G_DEFINE_TYPE (MetaShadowFactory, meta_shadow_factory, G_TYPE_OBJECT); - -static guint -meta_shadow_cache_key_hash (gconstpointer val) -{ - const MetaShadowCacheKey *key = val; - - return 59 * key->radius + 67 * key->top_fade + 73 * meta_window_shape_hash (key->shape); -} - -static gboolean -meta_shadow_cache_key_equal (gconstpointer a, - gconstpointer b) -{ - const MetaShadowCacheKey *key_a = a; - const MetaShadowCacheKey *key_b = b; - - return (key_a->radius == key_b->radius && key_a->top_fade == key_b->top_fade && - meta_window_shape_equal (key_a->shape, key_b->shape)); -} - -MetaShadow * -meta_shadow_ref (MetaShadow *shadow) -{ - shadow->ref_count++; - - return shadow; -} - -void -meta_shadow_unref (MetaShadow *shadow) -{ - shadow->ref_count--; - if (shadow->ref_count == 0) - { - if (shadow->factory) - { - g_hash_table_remove (shadow->factory->shadows, - &shadow->key); - } - - meta_window_shape_unref (shadow->key.shape); - cogl_object_unref (shadow->texture); - cogl_object_unref (shadow->pipeline); - - g_free (shadow); - } -} - -/** - * meta_shadow_paint: - * @window_x: x position of the region to paint a shadow for - * @window_y: y position of the region to paint a shadow for - * @window_width: actual width of the region to paint a shadow for - * @window_height: actual height of the region to paint a shadow for - * @clip: (nullable): if non-%NULL specifies the visible portion - * of the shadow. - * @clip_strictly: if %TRUE, drawing will be clipped strictly - * to @clip, otherwise, it will be only used to optimize - * drawing. - * - * Paints the shadow at the given position, for the specified actual - * size of the region. (Since a #MetaShadow can be shared between - * different sizes with the same extracted #MetaWindowShape the - * size needs to be passed in here.) - */ -void -meta_shadow_paint (MetaShadow *shadow, - CoglFramebuffer *framebuffer, - int window_x, - int window_y, - int window_width, - int window_height, - guint8 opacity, - cairo_region_t *clip, - gboolean clip_strictly) -{ - float texture_width = cogl_texture_get_width (shadow->texture); - float texture_height = cogl_texture_get_height (shadow->texture); - int i, j; - float src_x[4]; - float src_y[4]; - int dest_x[4]; - int dest_y[4]; - int n_x, n_y; - - if (clip && cairo_region_is_empty (clip)) - return; - - cogl_pipeline_set_color4ub (shadow->pipeline, - opacity, opacity, opacity, opacity); - - if (shadow->scale_width) - { - n_x = 3; - - src_x[0] = 0.0; - src_x[1] = (shadow->inner_border_left + shadow->outer_border_left) / texture_width; - src_x[2] = (texture_width - (shadow->inner_border_right + shadow->outer_border_right)) / texture_width; - src_x[3] = 1.0; - - dest_x[0] = window_x - shadow->outer_border_left; - dest_x[1] = window_x + shadow->inner_border_left; - dest_x[2] = window_x + window_width - shadow->inner_border_right; - dest_x[3] = window_x + window_width + shadow->outer_border_right; - } - else - { - n_x = 1; - - src_x[0] = 0.0; - src_x[1] = 1.0; - - dest_x[0] = window_x - shadow->outer_border_left; - dest_x[1] = window_x + window_width + shadow->outer_border_right; - } - - if (shadow->scale_height) - { - n_y = 3; - - src_y[0] = 0.0; - src_y[1] = (shadow->inner_border_top + shadow->outer_border_top) / texture_height; - src_y[2] = (texture_height - (shadow->inner_border_bottom + shadow->outer_border_bottom)) / texture_height; - src_y[3] = 1.0; - - dest_y[0] = window_y - shadow->outer_border_top; - dest_y[1] = window_y + shadow->inner_border_top; - dest_y[2] = window_y + window_height - shadow->inner_border_bottom; - dest_y[3] = window_y + window_height + shadow->outer_border_bottom; - } - else - { - n_y = 1; - - src_y[0] = 0.0; - src_y[1] = 1.0; - - dest_y[0] = window_y - shadow->outer_border_top; - dest_y[1] = window_y + window_height + shadow->outer_border_bottom; - } - - for (j = 0; j < n_y; j++) - { - cairo_rectangle_int_t dest_rect; - dest_rect.y = dest_y[j]; - dest_rect.height = dest_y[j + 1] - dest_y[j]; - - if (dest_rect.height == 0) - continue; - - for (i = 0; i < n_x; i++) - { - cairo_region_overlap_t overlap; - - dest_rect.x = dest_x[i]; - dest_rect.width = dest_x[i + 1] - dest_x[i]; - - if (dest_rect.width == 0) - continue; - - if (clip) - overlap = cairo_region_contains_rectangle (clip, &dest_rect); - else - overlap = CAIRO_REGION_OVERLAP_IN; - - if (overlap == CAIRO_REGION_OVERLAP_OUT) - continue; - - /* There's quite a bit of overhead from allocating a new - * region in order to find an exact intersection and - * generating more geometry - we make the assumption that - * unless we have to clip strictly it will be cheaper to - * just draw the entire rectangle. - */ - if (overlap == CAIRO_REGION_OVERLAP_IN || - (overlap == CAIRO_REGION_OVERLAP_PART && !clip_strictly)) - { - cogl_framebuffer_draw_textured_rectangle (framebuffer, - shadow->pipeline, - dest_x[i], dest_y[j], - dest_x[i + 1], dest_y[j + 1], - src_x[i], src_y[j], - src_x[i + 1], src_y[j + 1]); - } - else if (overlap == CAIRO_REGION_OVERLAP_PART) - { - cairo_region_t *intersection; - int n_rectangles, k; - - intersection = cairo_region_create_rectangle (&dest_rect); - cairo_region_intersect (intersection, clip); - - n_rectangles = cairo_region_num_rectangles (intersection); - for (k = 0; k < n_rectangles; k++) - { - cairo_rectangle_int_t rect; - float src_x1, src_x2, src_y1, src_y2; - - cairo_region_get_rectangle (intersection, k, &rect); - - /* Separately linear interpolate X and Y coordinates in the source - * based on the destination X and Y coordinates */ - - src_x1 = (src_x[i] * (dest_rect.x + dest_rect.width - rect.x) + - src_x[i + 1] * (rect.x - dest_rect.x)) / dest_rect.width; - src_x2 = (src_x[i] * (dest_rect.x + dest_rect.width - (rect.x + rect.width)) + - src_x[i + 1] * (rect.x + rect.width - dest_rect.x)) / dest_rect.width; - - src_y1 = (src_y[j] * (dest_rect.y + dest_rect.height - rect.y) + - src_y[j + 1] * (rect.y - dest_rect.y)) / dest_rect.height; - src_y2 = (src_y[j] * (dest_rect.y + dest_rect.height - (rect.y + rect.height)) + - src_y[j + 1] * (rect.y + rect.height - dest_rect.y)) / dest_rect.height; - - cogl_framebuffer_draw_textured_rectangle (framebuffer, - shadow->pipeline, - rect.x, rect.y, - rect.x + rect.width, rect.y + rect.height, - src_x1, src_y1, src_x2, src_y2); - } - - cairo_region_destroy (intersection); - } - } - } -} - -/** - * meta_shadow_get_bounds: - * @shadow: a #MetaShadow - * @window_x: x position of the region to paint a shadow for - * @window_y: y position of the region to paint a shadow for - * @window_width: actual width of the region to paint a shadow for - * @window_height: actual height of the region to paint a shadow for - * - * Computes the bounds of the pixels that will be affected by - * meta_shadow_paint() - */ -void -meta_shadow_get_bounds (MetaShadow *shadow, - int window_x, - int window_y, - int window_width, - int window_height, - cairo_rectangle_int_t *bounds) -{ - bounds->x = window_x - shadow->outer_border_left; - bounds->y = window_y - shadow->outer_border_top; - bounds->width = window_width + shadow->outer_border_left + shadow->outer_border_right; - bounds->height = window_height + shadow->outer_border_top + shadow->outer_border_bottom; -} - -static void -meta_shadow_class_info_free (MetaShadowClassInfo *class_info) -{ - g_free ((char *)class_info->name); - g_free (class_info); -} - -static void -meta_shadow_factory_init (MetaShadowFactory *factory) -{ - guint i; - - factory->shadows = g_hash_table_new (meta_shadow_cache_key_hash, - meta_shadow_cache_key_equal); - - factory->shadow_classes = g_hash_table_new_full (g_str_hash, - g_str_equal, - NULL, - (GDestroyNotify)meta_shadow_class_info_free); - - for (i = 0; i < G_N_ELEMENTS (default_shadow_classes); i++) - { - MetaShadowClassInfo *class_info = g_new0 (MetaShadowClassInfo, 1); - - *class_info = default_shadow_classes[i]; - class_info->name = g_strdup (class_info->name); - - g_hash_table_insert (factory->shadow_classes, - (char *)class_info->name, class_info); - } -} - -static void -meta_shadow_factory_finalize (GObject *object) -{ - MetaShadowFactory *factory = META_SHADOW_FACTORY (object); - GHashTableIter iter; - gpointer key, value; - - /* Detach from the shadows in the table so we won't try to - * remove them when they're freed. */ - g_hash_table_iter_init (&iter, factory->shadows); - while (g_hash_table_iter_next (&iter, &key, &value)) - { - MetaShadow *shadow = key; - shadow->factory = NULL; - } - - g_hash_table_destroy (factory->shadows); - g_hash_table_destroy (factory->shadow_classes); - - G_OBJECT_CLASS (meta_shadow_factory_parent_class)->finalize (object); -} - -static void -meta_shadow_factory_class_init (MetaShadowFactoryClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_shadow_factory_finalize; - - signals[CHANGED] = - g_signal_new ("changed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); -} - -MetaShadowFactory * -meta_shadow_factory_new (void) -{ - return g_object_new (META_TYPE_SHADOW_FACTORY, NULL); -} - -/** - * meta_shadow_factory_get_default: - * - * Return value: (transfer none): the global singleton shadow factory - */ -MetaShadowFactory * -meta_shadow_factory_get_default (void) -{ - static MetaShadowFactory *factory; - - if (factory == NULL) - factory = meta_shadow_factory_new (); - - return factory; -} - -/* We emulate a 1D Gaussian blur by using 3 consecutive box blurs; - * this produces a result that's within 3% of the original and can be - * implemented much faster for large filter sizes because of the - * efficiency of implementation of a box blur. Idea and formula - * for choosing the box blur size come from: - * - * http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement - * - * The 2D blur is then done by blurring the rows, flipping the - * image and blurring the columns. (This is possible because the - * Gaussian kernel is separable - it's the product of a horizontal - * blur and a vertical blur.) - */ -static int -get_box_filter_size (int radius) -{ - return (int)(0.5 + radius * (0.75 * sqrt(2*M_PI))); -} - -/* The "spread" of the filter is the number of pixels from an original - * pixel that it's blurred image extends. (A no-op blur that doesn't - * blur would have a spread of 0.) See comment in blur_rows() for why the - * odd and even cases are different - */ -static int -get_shadow_spread (int radius) -{ - int d; - - if (radius == 0) - return 0; - - d = get_box_filter_size (radius); - - if (d % 2 == 1) - return 3 * (d / 2); - else - return 3 * (d / 2) - 1; -} - -/* This applies a single box blur pass to a horizontal range of pixels; - * since the box blur has the same weight for all pixels, we can - * implement an efficient sliding window algorithm where we add - * in pixels coming into the window from the right and remove - * them when they leave the windw to the left. - * - * d is the filter width; for even d shift indicates how the blurred - * result is aligned with the original - does ' x ' go to ' yy' (shift=1) - * or 'yy ' (shift=-1) - */ -static void -blur_xspan (guchar *row, - guchar *tmp_buffer, - int row_width, - int x0, - int x1, - int d, - int shift) -{ - int offset; - int sum = 0; - int i; - - if (d % 2 == 1) - offset = d / 2; - else - offset = (d - shift) / 2; - - /* All the conditionals in here look slow, but the branches will - * be well predicted and there are enough different possibilities - * that trying to write this as a series of unconditional loops - * is hard and not an obvious win. The main slow down here seems - * to be the integer division per pixel; one possible optimization - * would be to accumulate into two 16-bit integer buffers and - * only divide down after all three passes. (SSE parallel implementation - * of the divide step is possible.) - */ - for (i = x0 - d + offset; i < x1 + offset; i++) - { - if (i >= 0 && i < row_width) - sum += row[i]; - - if (i >= x0 + offset) - { - if (i >= d) - sum -= row[i - d]; - - tmp_buffer[i - offset] = (sum + d / 2) / d; - } - } - - memcpy (row + x0, tmp_buffer + x0, x1 - x0); -} - -static void -blur_rows (cairo_region_t *convolve_region, - int x_offset, - int y_offset, - guchar *buffer, - int buffer_width, - int buffer_height, - int d) -{ - int i, j; - int n_rectangles; - guchar *tmp_buffer; - - tmp_buffer = g_malloc (buffer_width); - - n_rectangles = cairo_region_num_rectangles (convolve_region); - for (i = 0; i < n_rectangles; i++) - { - cairo_rectangle_int_t rect; - - cairo_region_get_rectangle (convolve_region, i, &rect); - - for (j = y_offset + rect.y; j < y_offset + rect.y + rect.height; j++) - { - guchar *row = buffer + j * buffer_width; - int x0 = x_offset + rect.x; - int x1 = x0 + rect.width; - - /* We want to produce a symmetric blur that spreads a pixel - * equally far to the left and right. If d is odd that happens - * naturally, but for d even, we approximate by using a blur - * on either side and then a centered blur of size d + 1. - * (technique also from the SVG specification) - */ - if (d % 2 == 1) - { - blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 0); - blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 0); - blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 0); - } - else - { - blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 1); - blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, -1); - blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d + 1, 0); - } - } - } - - g_free (tmp_buffer); -} - -static void -fade_bytes (guchar *bytes, - int width, - int distance, - int total) -{ - guint32 multiplier = (distance * 0x10000 + 0x8000) / total; - int i; - - for (i = 0; i < width; i++) - bytes[i] = (bytes[i] * multiplier) >> 16; -} - -/* Swaps width and height. Either swaps in-place and returns the original - * buffer or allocates a new buffer, frees the original buffer and returns - * the new buffer. - */ -static guchar * -flip_buffer (guchar *buffer, - int width, - int height) -{ - /* Working in blocks increases cache efficiency, compared to reading - * or writing an entire column at once */ -#define BLOCK_SIZE 16 - - if (width == height) - { - int i0, j0; - - for (j0 = 0; j0 < height; j0 += BLOCK_SIZE) - for (i0 = 0; i0 <= j0; i0 += BLOCK_SIZE) - { - int max_j = MIN(j0 + BLOCK_SIZE, height); - int max_i = MIN(i0 + BLOCK_SIZE, width); - int i, j; - - if (i0 == j0) - { - for (j = j0; j < max_j; j++) - for (i = i0; i < j; i++) - { - guchar tmp = buffer[j * width + i]; - buffer[j * width + i] = buffer[i * width + j]; - buffer[i * width + j] = tmp; - } - } - else - { - for (j = j0; j < max_j; j++) - for (i = i0; i < max_i; i++) - { - guchar tmp = buffer[j * width + i]; - buffer[j * width + i] = buffer[i * width + j]; - buffer[i * width + j] = tmp; - } - } - } - - return buffer; - } - else - { - guchar *new_buffer = g_malloc (height * width); - int i0, j0; - - for (i0 = 0; i0 < width; i0 += BLOCK_SIZE) - for (j0 = 0; j0 < height; j0 += BLOCK_SIZE) - { - int max_j = MIN(j0 + BLOCK_SIZE, height); - int max_i = MIN(i0 + BLOCK_SIZE, width); - int i, j; - - for (i = i0; i < max_i; i++) - for (j = j0; j < max_j; j++) - new_buffer[i * height + j] = buffer[j * width + i]; - } - - g_free (buffer); - - return new_buffer; - } -#undef BLOCK_SIZE -} - -static void -make_shadow (MetaShadow *shadow, - cairo_region_t *region) -{ - ClutterBackend *backend = clutter_get_default_backend (); - CoglContext *ctx = clutter_backend_get_cogl_context (backend); - GError *error = NULL; - int d = get_box_filter_size (shadow->key.radius); - int spread = get_shadow_spread (shadow->key.radius); - cairo_rectangle_int_t extents; - cairo_region_t *row_convolve_region; - cairo_region_t *column_convolve_region; - guchar *buffer; - int buffer_width; - int buffer_height; - int x_offset; - int y_offset; - int n_rectangles, j, k; - - cairo_region_get_extents (region, &extents); - - /* In the case where top_fade >= 0 and the portion above the top - * edge of the shape will be cropped, it seems like we could create - * a smaller buffer and omit the top portion, but actually, in our - * multi-pass blur algorithm, the blur into the area above the window - * in the first pass will contribute back to the final pixel values - * for the top pixels, so we create a buffer as if we weren't cropping - * and only crop when creating the CoglTexture. - */ - - buffer_width = extents.width + 2 * spread; - buffer_height = extents.height + 2 * spread; - - /* Round up so we have aligned rows/columns */ - buffer_width = (buffer_width + 3) & ~3; - buffer_height = (buffer_height + 3) & ~3; - - /* Square buffer allows in-place swaps, which are roughly 70% faster, but we - * don't want to over-allocate too much memory. - */ - if (buffer_height < buffer_width && buffer_height > (3 * buffer_width) / 4) - buffer_height = buffer_width; - if (buffer_width < buffer_height && buffer_width > (3 * buffer_height) / 4) - buffer_width = buffer_height; - - buffer = g_malloc0 (buffer_width * buffer_height); - - /* Blurring with multiple box-blur passes is fast, but (especially for - * large shadow sizes) we can improve efficiency by restricting the blur - * to the region that actually needs to be blurred. - */ - row_convolve_region = meta_make_border_region (region, spread, spread, FALSE); - column_convolve_region = meta_make_border_region (region, 0, spread, TRUE); - - /* Offsets between coordinates of the regions and coordinates in the buffer */ - x_offset = spread; - y_offset = spread; - - /* Step 1: unblurred image */ - n_rectangles = cairo_region_num_rectangles (region); - for (k = 0; k < n_rectangles; k++) - { - cairo_rectangle_int_t rect; - - cairo_region_get_rectangle (region, k, &rect); - for (j = y_offset + rect.y; j < y_offset + rect.y + rect.height; j++) - memset (buffer + buffer_width * j + x_offset + rect.x, 255, rect.width); - } - - /* Step 2: swap rows and columns */ - buffer = flip_buffer (buffer, buffer_width, buffer_height); - - /* Step 3: blur rows (really columns) */ - blur_rows (column_convolve_region, y_offset, x_offset, - buffer, buffer_height, buffer_width, - d); - - /* Step 4: swap rows and columns */ - buffer = flip_buffer (buffer, buffer_height, buffer_width); - - /* Step 5: blur rows */ - blur_rows (row_convolve_region, x_offset, y_offset, - buffer, buffer_width, buffer_height, - d); - - /* Step 6: fade out the top, if applicable */ - if (shadow->key.top_fade >= 0) - { - for (j = y_offset; j < y_offset + MIN (shadow->key.top_fade, extents.height + shadow->outer_border_bottom); j++) - fade_bytes(buffer + j * buffer_width, buffer_width, j - y_offset, shadow->key.top_fade); - } - - /* We offset the passed in pixels to crop off the extra area we allocated at the top - * in the case of top_fade >= 0. We also account for padding at the left for symmetry - * though that doesn't currently occur. - */ - shadow->texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx, - shadow->outer_border_left + extents.width + shadow->outer_border_right, - shadow->outer_border_top + extents.height + shadow->outer_border_bottom, - COGL_PIXEL_FORMAT_A_8, - buffer_width, - (buffer + - (y_offset - shadow->outer_border_top) * buffer_width + - (x_offset - shadow->outer_border_left)), - &error)); - - if (error) - { - meta_warning ("Failed to allocate shadow texture: %s", error->message); - g_error_free (error); - } - - cairo_region_destroy (row_convolve_region); - cairo_region_destroy (column_convolve_region); - g_free (buffer); - - shadow->pipeline = meta_create_texture_pipeline (shadow->texture); -} - -static MetaShadowParams * -get_shadow_params (MetaShadowFactory *factory, - const char *class_name, - gboolean focused, - gboolean create) -{ - MetaShadowClassInfo *class_info = g_hash_table_lookup (factory->shadow_classes, - class_name); - if (class_info == NULL) - { - if (create) - { - class_info = g_new0 (MetaShadowClassInfo, 1); - *class_info = default_shadow_classes[0]; - class_info->name = g_strdup (class_info->name); - - g_hash_table_insert (factory->shadow_classes, - (char *)class_info->name, class_info); - } - else - { - class_info = &default_shadow_classes[0]; - } - } - - if (focused) - return &class_info->focused; - else - return &class_info->unfocused; -} - -/** - * meta_shadow_factory_get_shadow: - * @factory: a #MetaShadowFactory - * @shape: the size-invariant shape of the window's region - * @width: the actual width of the window's region - * @height: the actual height of the window's region - * @class_name: name of the class of window shadows - * @focused: whether the shadow is for a focused window - * - * Gets the appropriate shadow object for drawing shadows for the - * specified window shape. The region that we are shadowing is specified - * as a combination of a size-invariant extracted shape and the size. - * In some cases, the same shadow object can be shared between sizes; - * in other cases a different shadow object is used for each size. - * - * Return value: (transfer full): a newly referenced #MetaShadow; unref with - * meta_shadow_unref() - */ -MetaShadow * -meta_shadow_factory_get_shadow (MetaShadowFactory *factory, - MetaWindowShape *shape, - int width, - int height, - const char *class_name, - gboolean focused) -{ - MetaShadowParams *params; - MetaShadowCacheKey key; - MetaShadow *shadow; - cairo_region_t *region; - int spread; - int shape_border_top, shape_border_right, shape_border_bottom, shape_border_left; - int inner_border_top, inner_border_right, inner_border_bottom, inner_border_left; - int outer_border_top, outer_border_right, outer_border_bottom, outer_border_left; - gboolean scale_width, scale_height; - gboolean cacheable; - int center_width, center_height; - - g_return_val_if_fail (META_IS_SHADOW_FACTORY (factory), NULL); - g_return_val_if_fail (shape != NULL, NULL); - - /* Using a single shadow texture for different window sizes only works - * when there is a central scaled area that is greater than twice - * the spread of the gaussian blur we are applying to get to the - * shadow image. - * ********* *********** - * /----------\ *###########* *#############* - * | | => **#*********#** => **#***********#** - * | | **#** **#** **#** **#** - * | | **#*********#** **#***********#** - * \----------/ *###########* *#############* - * ********** ************ - * Original Blur Stretched Blur - * - * For smaller sizes, we create a separate shadow image for each size; - * since we assume that there will be little reuse, we don't try to - * cache such images but just recreate them. (Since the current cache - * policy is to only keep around referenced shadows, there wouldn't - * be any harm in caching them, it would just make the book-keeping - * a bit tricker.) - * - * In the case where we are fading a the top, that also has to fit - * within the top unscaled border. - */ - - params = get_shadow_params (factory, class_name, focused, FALSE); - - spread = get_shadow_spread (params->radius); - meta_window_shape_get_borders (shape, - &shape_border_top, - &shape_border_right, - &shape_border_bottom, - &shape_border_left); - - inner_border_top = MAX (shape_border_top + spread, params->top_fade); - outer_border_top = params->top_fade >= 0 ? 0 : spread; - inner_border_right = shape_border_right + spread; - outer_border_right = spread; - inner_border_bottom = shape_border_bottom + spread; - outer_border_bottom = spread; - inner_border_left = shape_border_left + spread; - outer_border_left = spread; - - scale_width = inner_border_left + inner_border_right <= width; - scale_height = inner_border_top + inner_border_bottom <= height; - cacheable = scale_width && scale_height; - - if (cacheable) - { - key.shape = shape; - key.radius = params->radius; - key.top_fade = params->top_fade; - - shadow = g_hash_table_lookup (factory->shadows, &key); - if (shadow) - return meta_shadow_ref (shadow); - } - - shadow = g_new0 (MetaShadow, 1); - - shadow->ref_count = 1; - shadow->factory = factory; - shadow->key.shape = meta_window_shape_ref (shape); - shadow->key.radius = params->radius; - shadow->key.top_fade = params->top_fade; - - shadow->outer_border_top = outer_border_top; - shadow->inner_border_top = inner_border_top; - shadow->outer_border_right = outer_border_right; - shadow->inner_border_right = inner_border_right; - shadow->outer_border_bottom = outer_border_bottom; - shadow->inner_border_bottom = inner_border_bottom; - shadow->outer_border_left = outer_border_left; - shadow->inner_border_left = inner_border_left; - - shadow->scale_width = scale_width; - if (scale_width) - center_width = inner_border_left + inner_border_right - (shape_border_left + shape_border_right); - else - center_width = width - (shape_border_left + shape_border_right); - - shadow->scale_height = scale_height; - if (scale_height) - center_height = inner_border_top + inner_border_bottom - (shape_border_top + shape_border_bottom); - else - center_height = height - (shape_border_top + shape_border_bottom); - - g_assert (center_width >= 0 && center_height >= 0); - - region = meta_window_shape_to_region (shape, center_width, center_height); - make_shadow (shadow, region); - - cairo_region_destroy (region); - - if (cacheable) - g_hash_table_insert (factory->shadows, &shadow->key, shadow); - - return shadow; -} - -/** - * meta_shadow_factory_set_params: - * @factory: a #MetaShadowFactory - * @class_name: name of the class of shadow to set the params for. - * the default shadow classes are the names of the different - * theme frame types (normal, dialog, modal_dialog, utility, - * border, menu, attached) and in addition, popup-menu - * and dropdown-menu. - * @focused: whether the shadow is for a focused window - * @params: new parameter values - * - * Updates the shadow parameters for a particular class of shadows - * for either the focused or unfocused state. If the class name - * does not name an existing class, a new class will be created - * (the other focus state for that class will have default values - * assigned to it.) - */ -void -meta_shadow_factory_set_params (MetaShadowFactory *factory, - const char *class_name, - gboolean focused, - MetaShadowParams *params) -{ - MetaShadowParams *stored_params; - - g_return_if_fail (META_IS_SHADOW_FACTORY (factory)); - g_return_if_fail (class_name != NULL); - g_return_if_fail (params != NULL); - g_return_if_fail (params->radius >= 0); - - stored_params = get_shadow_params (factory, class_name, focused, TRUE); - - *stored_params = *params; - - g_signal_emit (factory, signals[CHANGED], 0); -} - -/** - * meta_shadow_factory_get_params: - * @factory: a #MetaShadowFactory - * @class_name: name of the class of shadow to get the params for - * @focused: whether the shadow is for a focused window - * @params: (out caller-allocates): location to store the current parameter values - * - * Gets the shadow parameters for a particular class of shadows - * for either the focused or unfocused state. If the class name - * does not name an existing class, default values will be returned - * without printing an error. - */ -void -meta_shadow_factory_get_params (MetaShadowFactory *factory, - const char *class_name, - gboolean focused, - MetaShadowParams *params) -{ - MetaShadowParams *stored_params; - - g_return_if_fail (META_IS_SHADOW_FACTORY (factory)); - g_return_if_fail (class_name != NULL); - - stored_params = get_shadow_params (factory, class_name, focused, FALSE); - - if (params) - *params = *stored_params; -} - -G_DEFINE_BOXED_TYPE (MetaShadow, meta_shadow, - meta_shadow_ref, meta_shadow_unref) diff --git a/src/compositor/meta-shaped-texture-private.h b/src/compositor/meta-shaped-texture-private.h deleted file mode 100644 index 2fe1b8ea4..000000000 --- a/src/compositor/meta-shaped-texture-private.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * shaped texture - * - * An actor to draw a texture clipped to a list of rectangles - * - * Authored By Neil Roberts - * - * Copyright (C) 2008 Intel Corporation - * 2013 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef __META_SHAPED_TEXTURE_PRIVATE_H__ -#define __META_SHAPED_TEXTURE_PRIVATE_H__ - -#include "backends/meta-monitor-manager-private.h" -#include "meta/meta-shaped-texture.h" - -MetaShapedTexture *meta_shaped_texture_new (void); -void meta_shaped_texture_set_texture (MetaShapedTexture *stex, - CoglTexture *texture); -void meta_shaped_texture_set_is_y_inverted (MetaShapedTexture *stex, - gboolean is_y_inverted); -void meta_shaped_texture_set_snippet (MetaShapedTexture *stex, - CoglSnippet *snippet); -void meta_shaped_texture_set_fallback_size (MetaShapedTexture *stex, - int fallback_width, - int fallback_height); -cairo_region_t * meta_shaped_texture_get_opaque_region (MetaShapedTexture *stex); -gboolean meta_shaped_texture_is_opaque (MetaShapedTexture *stex); -gboolean meta_shaped_texture_has_alpha (MetaShapedTexture *stex); -void meta_shaped_texture_set_transform (MetaShapedTexture *stex, - MetaMonitorTransform transform); -void meta_shaped_texture_set_viewport_src_rect (MetaShapedTexture *stex, - graphene_rect_t *src_rect); -void meta_shaped_texture_reset_viewport_src_rect (MetaShapedTexture *stex); -void meta_shaped_texture_set_viewport_dst_size (MetaShapedTexture *stex, - int dst_width, - int dst_height); -void meta_shaped_texture_reset_viewport_dst_size (MetaShapedTexture *stex); -void meta_shaped_texture_set_buffer_scale (MetaShapedTexture *stex, - int buffer_scale); -int meta_shaped_texture_get_buffer_scale (MetaShapedTexture *stex); - -gboolean meta_shaped_texture_update_area (MetaShapedTexture *stex, - int x, - int y, - int width, - int height, - cairo_rectangle_int_t *clip); - -int meta_shaped_texture_get_width (MetaShapedTexture *stex); -int meta_shaped_texture_get_height (MetaShapedTexture *stex); - -void meta_shaped_texture_set_clip_region (MetaShapedTexture *stex, - cairo_region_t *clip_region); -void meta_shaped_texture_set_opaque_region (MetaShapedTexture *stex, - cairo_region_t *opaque_region); - -void meta_shaped_texture_ensure_size_valid (MetaShapedTexture *stex); - -#endif diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c deleted file mode 100644 index 6a8af828f..000000000 --- a/src/compositor/meta-shaped-texture.c +++ /dev/null @@ -1,1676 +0,0 @@ -/* - * Authored By Neil Roberts - * and Jasper St. Pierre - * - * Copyright (C) 2008 Intel Corporation - * Copyright (C) 2012 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 . - */ - -/** - * SECTION:meta-shaped-texture - * @title: MetaShapedTexture - * @short_description: A ClutterContent which draws a shaped texture - * - * A MetaShapedTexture draws a #CoglTexture (often provided from a client - * surface) in such a way that it matches any required transformations that - * give its final shape, such as a #MetaMonitorTransform, y-invertedness, or a - * crop-and-scale operation. - */ - -#include "config.h" - -#include "backends/meta-monitor-transform.h" -#include "compositor/meta-shaped-texture-private.h" -#include "core/boxes-private.h" - -#include -#include - -#include "cogl/cogl.h" -#include "compositor/clutter-utils.h" -#include "compositor/meta-texture-tower.h" -#include "compositor/region-utils.h" -#include "core/boxes-private.h" -#include "meta/meta-shaped-texture.h" - -/* MAX_MIPMAPPING_FPS needs to be as small as possible for the best GPU - * performance, but higher than the refresh rate of commonly slow updating - * windows like top or a blinking cursor, so that such windows do get - * mipmapped. - */ -#define MAX_MIPMAPPING_FPS 5 -#define MIN_MIPMAP_AGE_USEC (G_USEC_PER_SEC / MAX_MIPMAPPING_FPS) - -/* MIN_FAST_UPDATES_BEFORE_UNMIPMAP allows windows to update themselves - * occasionally without causing mipmapping to be disabled, so long as such - * an update takes fewer update_area calls than: - */ -#define MIN_FAST_UPDATES_BEFORE_UNMIPMAP 20 - -static void meta_shaped_texture_dispose (GObject *object); - -static void clutter_content_iface_init (ClutterContentInterface *iface); - -enum -{ - SIZE_CHANGED, - - LAST_SIGNAL, -}; - -static guint signals[LAST_SIGNAL]; - -static CoglPipelineKey opaque_overlay_pipeline_key = - "meta-shaped-texture-opaque-pipeline-key"; -static CoglPipelineKey blended_overlay_pipeline_key = - "meta-shaped-texture-blended-pipeline-key"; - -struct _MetaShapedTexture -{ - GObject parent; - - MetaTextureTower *paint_tower; - - CoglTexture *texture; - CoglTexture *mask_texture; - CoglSnippet *snippet; - - CoglPipeline *base_pipeline; - CoglPipeline *masked_pipeline; - CoglPipeline *unblended_pipeline; - - gboolean is_y_inverted; - - /* The region containing only fully opaque pixels */ - cairo_region_t *opaque_region; - - /* MetaCullable regions, see that documentation for more details */ - cairo_region_t *clip_region; - - gboolean size_invalid; - MetaMonitorTransform transform; - gboolean has_viewport_src_rect; - graphene_rect_t viewport_src_rect; - gboolean has_viewport_dst_size; - int viewport_dst_width; - int viewport_dst_height; - - int tex_width, tex_height; - int fallback_width, fallback_height; - int dst_width, dst_height; - - gint64 prev_invalidation, last_invalidation; - guint fast_updates; - guint remipmap_timeout_id; - gint64 earliest_remipmap; - - int buffer_scale; - - guint create_mipmaps : 1; -}; - -G_DEFINE_TYPE_WITH_CODE (MetaShapedTexture, meta_shaped_texture, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTENT, - clutter_content_iface_init)); - -static void -meta_shaped_texture_class_init (MetaShapedTextureClass *klass) -{ - GObjectClass *gobject_class = (GObjectClass *) klass; - - gobject_class->dispose = meta_shaped_texture_dispose; - - signals[SIZE_CHANGED] = g_signal_new ("size-changed", - G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); -} - -static void -invalidate_size (MetaShapedTexture *stex) -{ - stex->size_invalid = TRUE; -} - -static void -meta_shaped_texture_init (MetaShapedTexture *stex) -{ - stex->paint_tower = meta_texture_tower_new (); - - stex->buffer_scale = 1; - stex->texture = NULL; - stex->mask_texture = NULL; - stex->create_mipmaps = TRUE; - stex->is_y_inverted = TRUE; - stex->transform = META_MONITOR_TRANSFORM_NORMAL; -} - -static void -update_size (MetaShapedTexture *stex) -{ - int buffer_scale = stex->buffer_scale; - int dst_width; - int dst_height; - - if (stex->has_viewport_dst_size) - { - dst_width = stex->viewport_dst_width; - dst_height = stex->viewport_dst_height; - } - else if (stex->has_viewport_src_rect) - { - dst_width = stex->viewport_src_rect.size.width; - dst_height = stex->viewport_src_rect.size.height; - } - else - { - if (meta_monitor_transform_is_rotated (stex->transform)) - { - if (stex->texture) - { - dst_width = stex->tex_height / buffer_scale; - dst_height = stex->tex_width / buffer_scale; - } - else - { - dst_width = stex->fallback_height / buffer_scale; - dst_height = stex->fallback_width / buffer_scale; - } - } - else - { - if (stex->texture) - { - dst_width = stex->tex_width / buffer_scale; - dst_height = stex->tex_height / buffer_scale; - } - else - { - dst_width = stex->fallback_width / buffer_scale; - dst_height = stex->fallback_height / buffer_scale; - } - } - } - - stex->size_invalid = FALSE; - - if (stex->dst_width != dst_width || - stex->dst_height != dst_height) - { - stex->dst_width = dst_width; - stex->dst_height = dst_height; - meta_shaped_texture_set_mask_texture (stex, NULL); - clutter_content_invalidate_size (CLUTTER_CONTENT (stex)); - g_signal_emit (stex, signals[SIZE_CHANGED], 0); - } -} - -void -meta_shaped_texture_ensure_size_valid (MetaShapedTexture *stex) -{ - if (stex->size_invalid) - update_size (stex); -} - -void -meta_shaped_texture_set_clip_region (MetaShapedTexture *stex, - cairo_region_t *clip_region) -{ - g_clear_pointer (&stex->clip_region, cairo_region_destroy); - if (clip_region) - stex->clip_region = cairo_region_reference (clip_region); -} - -static void -meta_shaped_texture_reset_pipelines (MetaShapedTexture *stex) -{ - g_clear_pointer (&stex->base_pipeline, cogl_object_unref); - g_clear_pointer (&stex->masked_pipeline, cogl_object_unref); - g_clear_pointer (&stex->unblended_pipeline, cogl_object_unref); -} - -static void -meta_shaped_texture_dispose (GObject *object) -{ - MetaShapedTexture *stex = (MetaShapedTexture *) object; - - g_clear_handle_id (&stex->remipmap_timeout_id, g_source_remove); - - if (stex->paint_tower) - meta_texture_tower_free (stex->paint_tower); - stex->paint_tower = NULL; - - g_clear_pointer (&stex->texture, cogl_object_unref); - - meta_shaped_texture_set_mask_texture (stex, NULL); - meta_shaped_texture_reset_pipelines (stex); - - g_clear_pointer (&stex->opaque_region, cairo_region_destroy); - g_clear_pointer (&stex->clip_region, cairo_region_destroy); - - g_clear_pointer (&stex->snippet, cogl_object_unref); - - G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object); -} - -static CoglPipeline * -get_base_pipeline (MetaShapedTexture *stex, - CoglContext *ctx) -{ - CoglPipeline *pipeline; - graphene_matrix_t matrix; - - if (stex->base_pipeline) - return stex->base_pipeline; - - pipeline = cogl_pipeline_new (ctx); - cogl_pipeline_set_layer_wrap_mode_s (pipeline, 0, - COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); - cogl_pipeline_set_layer_wrap_mode_t (pipeline, 0, - COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); - cogl_pipeline_set_layer_wrap_mode_s (pipeline, 1, - COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); - cogl_pipeline_set_layer_wrap_mode_t (pipeline, 1, - COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); - - graphene_matrix_init_identity (&matrix); - - if (stex->has_viewport_src_rect) - { - float scaled_tex_width = stex->tex_width / (float) stex->buffer_scale; - float scaled_tex_height = stex->tex_height / (float) stex->buffer_scale; - graphene_point3d_t p; - - graphene_point3d_init (&p, - stex->viewport_src_rect.origin.x / - stex->viewport_src_rect.size.width, - stex->viewport_src_rect.origin.y / - stex->viewport_src_rect.size.height, - 0); - graphene_matrix_translate (&matrix, &p); - - if (meta_monitor_transform_is_rotated (stex->transform)) - { - graphene_matrix_scale (&matrix, - stex->viewport_src_rect.size.width / - scaled_tex_height, - stex->viewport_src_rect.size.height / - scaled_tex_width, - 1); - } - else - { - graphene_matrix_scale (&matrix, - stex->viewport_src_rect.size.width / - scaled_tex_width, - stex->viewport_src_rect.size.height / - scaled_tex_height, - 1); - } - } - - if (stex->transform != META_MONITOR_TRANSFORM_NORMAL) - { - graphene_euler_t euler; - - graphene_matrix_translate (&matrix, - &GRAPHENE_POINT3D_INIT (-0.5, -0.5, 0.0)); - switch (stex->transform) - { - case META_MONITOR_TRANSFORM_90: - graphene_euler_init_with_order (&euler, 0.0, 0.0, 90.0, - GRAPHENE_EULER_ORDER_SYXZ); - break; - case META_MONITOR_TRANSFORM_180: - graphene_euler_init_with_order (&euler, 0.0, 0.0, 180.0, - GRAPHENE_EULER_ORDER_SYXZ); - break; - case META_MONITOR_TRANSFORM_270: - graphene_euler_init_with_order (&euler, 0.0, 0.0, 270.0, - GRAPHENE_EULER_ORDER_SYXZ); - break; - case META_MONITOR_TRANSFORM_FLIPPED: - graphene_euler_init_with_order (&euler, 0.0, 180.0, 0.0, - GRAPHENE_EULER_ORDER_SYXZ); - break; - case META_MONITOR_TRANSFORM_FLIPPED_90: - graphene_euler_init_with_order (&euler, 180.0, 0.0, 90.0, - GRAPHENE_EULER_ORDER_SYXZ); - break; - case META_MONITOR_TRANSFORM_FLIPPED_180: - graphene_euler_init_with_order (&euler, 0.0, 180.0, 180.0, - GRAPHENE_EULER_ORDER_SYXZ); - break; - case META_MONITOR_TRANSFORM_FLIPPED_270: - graphene_euler_init_with_order (&euler, 180.0, 0.0, 270.0, - GRAPHENE_EULER_ORDER_SYXZ); - break; - case META_MONITOR_TRANSFORM_NORMAL: - g_assert_not_reached (); - } - graphene_matrix_rotate_euler (&matrix, &euler); - graphene_matrix_translate (&matrix, - &GRAPHENE_POINT3D_INIT (0.5, 0.5, 0.0)); - } - - if (!stex->is_y_inverted) - { - graphene_matrix_translate (&matrix, &GRAPHENE_POINT3D_INIT (0, -1, 0)); - graphene_matrix_scale (&matrix, 1, -1, 1); - cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix); - } - - cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix); - cogl_pipeline_set_layer_matrix (pipeline, 1, &matrix); - - if (stex->snippet) - cogl_pipeline_add_layer_snippet (pipeline, 0, stex->snippet); - - stex->base_pipeline = pipeline; - - return stex->base_pipeline; -} - -static CoglPipeline * -get_unmasked_pipeline (MetaShapedTexture *stex, - CoglContext *ctx) -{ - return get_base_pipeline (stex, ctx); -} - -static CoglPipeline * -get_masked_pipeline (MetaShapedTexture *stex, - CoglContext *ctx) -{ - CoglPipeline *pipeline; - - if (stex->masked_pipeline) - return stex->masked_pipeline; - - pipeline = cogl_pipeline_copy (get_base_pipeline (stex, ctx)); - cogl_pipeline_set_layer_combine (pipeline, 1, - "RGBA = MODULATE (PREVIOUS, TEXTURE[A])", - NULL); - - stex->masked_pipeline = pipeline; - - return pipeline; -} - -static CoglPipeline * -get_unblended_pipeline (MetaShapedTexture *stex, - CoglContext *ctx) -{ - CoglPipeline *pipeline; - - if (stex->unblended_pipeline) - return stex->unblended_pipeline; - - pipeline = cogl_pipeline_copy (get_base_pipeline (stex, ctx)); - cogl_pipeline_set_layer_combine (pipeline, 0, - "RGBA = REPLACE (TEXTURE)", - NULL); - - stex->unblended_pipeline = pipeline; - - return pipeline; -} - -static CoglPipeline * -get_opaque_overlay_pipeline (CoglContext *ctx) -{ - CoglPipeline *pipeline; - - pipeline = cogl_context_get_named_pipeline (ctx, - &opaque_overlay_pipeline_key); - if (!pipeline) - { - pipeline = cogl_pipeline_new (ctx); - cogl_pipeline_set_color4ub (pipeline, 0x00, 0x33, 0x00, 0x33); - - cogl_context_set_named_pipeline (ctx, - &opaque_overlay_pipeline_key, - pipeline); - } - - return pipeline; -} - -static CoglPipeline * -get_blended_overlay_pipeline (CoglContext *ctx) -{ - CoglPipeline *pipeline; - - pipeline = cogl_context_get_named_pipeline (ctx, - &blended_overlay_pipeline_key); - if (!pipeline) - { - pipeline = cogl_pipeline_new (ctx); - cogl_pipeline_set_color4ub (pipeline, 0x33, 0x00, 0x33, 0x33); - - cogl_context_set_named_pipeline (ctx, - &blended_overlay_pipeline_key, - pipeline); - } - - return pipeline; -} - -static void -paint_clipped_rectangle_node (MetaShapedTexture *stex, - ClutterPaintNode *root_node, - CoglPipeline *pipeline, - cairo_rectangle_int_t *rect, - ClutterActorBox *alloc) -{ - g_autoptr (ClutterPaintNode) node = NULL; - float ratio_h, ratio_v; - float x1, y1, x2, y2; - float coords[8]; - float alloc_width; - float alloc_height; - - ratio_h = clutter_actor_box_get_width (alloc) / (float) stex->dst_width; - ratio_v = clutter_actor_box_get_height (alloc) / (float) stex->dst_height; - - x1 = alloc->x1 + rect->x * ratio_h; - y1 = alloc->y1 + rect->y * ratio_v; - x2 = alloc->x1 + (rect->x + rect->width) * ratio_h; - y2 = alloc->y1 + (rect->y + rect->height) * ratio_v; - - alloc_width = alloc->x2 - alloc->x1; - alloc_height = alloc->y2 - alloc->y1; - - coords[0] = rect->x / alloc_width * ratio_h; - coords[1] = rect->y / alloc_height * ratio_v; - coords[2] = (rect->x + rect->width) / alloc_width * ratio_h; - coords[3] = (rect->y + rect->height) / alloc_height * ratio_v; - - coords[4] = coords[0]; - coords[5] = coords[1]; - coords[6] = coords[2]; - coords[7] = coords[3]; - - node = clutter_pipeline_node_new (pipeline); - clutter_paint_node_set_static_name (node, "MetaShapedTexture (clipped)"); - clutter_paint_node_add_child (root_node, node); - - clutter_paint_node_add_multitexture_rectangle (node, - &(ClutterActorBox) { - .x1 = x1, - .y1 = y1, - .x2 = x2, - .y2 = y2, - }, - coords, 8); -} - -static void -set_cogl_texture (MetaShapedTexture *stex, - CoglTexture *cogl_tex) -{ - int width, height; - - cogl_clear_object (&stex->texture); - - if (cogl_tex != NULL) - { - stex->texture = cogl_object_ref (cogl_tex); - width = cogl_texture_get_width (COGL_TEXTURE (cogl_tex)); - height = cogl_texture_get_height (COGL_TEXTURE (cogl_tex)); - } - else - { - width = 0; - height = 0; - } - - if (stex->tex_width != width || - stex->tex_height != height) - { - stex->tex_width = width; - stex->tex_height = height; - update_size (stex); - } - - /* 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 queue a redraw in response to surface - * damage. */ - - if (stex->create_mipmaps) - meta_texture_tower_set_base_texture (stex->paint_tower, cogl_tex); -} - -static gboolean -texture_is_idle_and_not_mipmapped (gpointer user_data) -{ - MetaShapedTexture *stex = META_SHAPED_TEXTURE (user_data); - - if ((g_get_monotonic_time () - stex->earliest_remipmap) < 0) - return G_SOURCE_CONTINUE; - - clutter_content_invalidate (CLUTTER_CONTENT (stex)); - stex->remipmap_timeout_id = 0; - - return G_SOURCE_REMOVE; -} - -static inline void -flip_ints (int *x, - int *y) -{ - int tmp; - - tmp = *x; - *x = *y; - *y = tmp; -} - -static void -do_paint_content (MetaShapedTexture *stex, - ClutterPaintNode *root_node, - ClutterPaintContext *paint_context, - CoglTexture *paint_tex, - ClutterActorBox *alloc, - uint8_t opacity) -{ - int dst_width, dst_height; - cairo_rectangle_int_t content_rect; - gboolean use_opaque_region; - cairo_region_t *blended_tex_region; - CoglContext *ctx; - CoglPipelineFilter filter; - CoglFramebuffer *framebuffer; - int sample_width, sample_height; - gboolean debug_paint_opaque_region; - - meta_shaped_texture_ensure_size_valid (stex); - - dst_width = stex->dst_width; - dst_height = stex->dst_height; - - if (dst_width == 0 || dst_height == 0) /* no contents yet */ - return; - - content_rect = (cairo_rectangle_int_t) { - .x = 0, - .y = 0, - .width = dst_width, - .height = dst_height, - }; - - debug_paint_opaque_region = - meta_get_debug_paint_flags() & META_DEBUG_PAINT_OPAQUE_REGION; - - /* Use nearest-pixel interpolation if the texture is unscaled. This - * improves performance, especially with software rendering. - */ - - framebuffer = clutter_paint_node_get_framebuffer (root_node); - if (!framebuffer) - framebuffer = clutter_paint_context_get_framebuffer (paint_context); - - if (stex->has_viewport_src_rect) - { - sample_width = stex->viewport_src_rect.size.width * stex->buffer_scale; - sample_height = stex->viewport_src_rect.size.height * stex->buffer_scale; - } - else - { - sample_width = cogl_texture_get_width (stex->texture); - sample_height = cogl_texture_get_height (stex->texture); - } - if (meta_monitor_transform_is_rotated (stex->transform)) - flip_ints (&sample_width, &sample_height); - - if (meta_actor_painting_untransformed (framebuffer, - dst_width, dst_height, - sample_width, sample_height, - NULL, NULL)) - filter = COGL_PIPELINE_FILTER_NEAREST; - else - filter = COGL_PIPELINE_FILTER_LINEAR; - - ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); - - use_opaque_region = stex->opaque_region && opacity == 255; - - if (use_opaque_region) - { - if (stex->clip_region) - blended_tex_region = cairo_region_copy (stex->clip_region); - else - blended_tex_region = cairo_region_create_rectangle (&content_rect); - - cairo_region_subtract (blended_tex_region, stex->opaque_region); - } - else - { - if (stex->clip_region) - blended_tex_region = cairo_region_reference (stex->clip_region); - else - blended_tex_region = NULL; - } - - /* Limit to how many separate rectangles we'll draw; beyond this just - * fall back and draw the whole thing */ -#define MAX_RECTS 16 - - if (blended_tex_region) - { - int n_rects = cairo_region_num_rectangles (blended_tex_region); - if (n_rects > MAX_RECTS) - { - /* Fall back to taking the fully blended path. */ - use_opaque_region = FALSE; - - g_clear_pointer (&blended_tex_region, cairo_region_destroy); - } - } - - /* First, paint the unblended parts, which are part of the opaque region. */ - if (use_opaque_region) - { - cairo_region_t *region; - int n_rects; - int i; - - if (stex->clip_region) - { - region = cairo_region_copy (stex->clip_region); - cairo_region_intersect (region, stex->opaque_region); - } - else - { - region = cairo_region_reference (stex->opaque_region); - } - - if (!cairo_region_is_empty (region)) - { - CoglPipeline *opaque_pipeline; - - opaque_pipeline = get_unblended_pipeline (stex, ctx); - cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex); - cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter); - - n_rects = cairo_region_num_rectangles (region); - for (i = 0; i < n_rects; i++) - { - cairo_rectangle_int_t rect; - cairo_region_get_rectangle (region, i, &rect); - paint_clipped_rectangle_node (stex, root_node, - opaque_pipeline, - &rect, alloc); - - if (G_UNLIKELY (debug_paint_opaque_region)) - { - CoglPipeline *opaque_overlay_pipeline; - - opaque_overlay_pipeline = get_opaque_overlay_pipeline (ctx); - paint_clipped_rectangle_node (stex, root_node, - opaque_overlay_pipeline, - &rect, alloc); - } - } - } - - cairo_region_destroy (region); - } - - /* Now, go ahead and paint the blended parts. */ - - /* We have three cases: - * 1) blended_tex_region has rectangles - paint the rectangles. - * 2) blended_tex_region is empty - don't paint anything - * 3) blended_tex_region is NULL - paint fully-blended. - * - * 1) and 3) are the times where we have to paint stuff. This tests - * for 1) and 3). - */ - if (!blended_tex_region || !cairo_region_is_empty (blended_tex_region)) - { - CoglPipeline *blended_pipeline; - - if (stex->mask_texture == NULL) - { - blended_pipeline = get_unmasked_pipeline (stex, ctx); - } - else - { - blended_pipeline = get_masked_pipeline (stex, ctx); - cogl_pipeline_set_layer_texture (blended_pipeline, 1, stex->mask_texture); - cogl_pipeline_set_layer_filters (blended_pipeline, 1, filter, filter); - } - - cogl_pipeline_set_layer_texture (blended_pipeline, 0, paint_tex); - cogl_pipeline_set_layer_filters (blended_pipeline, 0, filter, filter); - - CoglColor color; - cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity); - cogl_pipeline_set_color (blended_pipeline, &color); - - if (blended_tex_region) - { - /* 1) blended_tex_region is not empty. Paint the rectangles. */ - int i; - int n_rects = cairo_region_num_rectangles (blended_tex_region); - - for (i = 0; i < n_rects; i++) - { - cairo_rectangle_int_t rect; - cairo_region_get_rectangle (blended_tex_region, i, &rect); - - if (!gdk_rectangle_intersect (&content_rect, &rect, &rect)) - continue; - - paint_clipped_rectangle_node (stex, root_node, - blended_pipeline, - &rect, alloc); - - if (G_UNLIKELY (debug_paint_opaque_region)) - { - CoglPipeline *blended_overlay_pipeline; - - blended_overlay_pipeline = get_blended_overlay_pipeline (ctx); - paint_clipped_rectangle_node (stex, root_node, - blended_overlay_pipeline, - &rect, alloc); - } - } - } - else - { - g_autoptr (ClutterPaintNode) node = NULL; - - node = clutter_pipeline_node_new (blended_pipeline); - clutter_paint_node_set_static_name (node, "MetaShapedTexture (unclipped)"); - clutter_paint_node_add_child (root_node, node); - - /* 3) blended_tex_region is NULL. Do a full paint. */ - clutter_paint_node_add_rectangle (node, alloc); - - if (G_UNLIKELY (debug_paint_opaque_region)) - { - CoglPipeline *blended_overlay_pipeline; - g_autoptr (ClutterPaintNode) node_overlay = NULL; - - blended_overlay_pipeline = get_blended_overlay_pipeline (ctx); - - node_overlay = clutter_pipeline_node_new (blended_overlay_pipeline); - clutter_paint_node_set_static_name (node_overlay, - "MetaShapedTexture (unclipped overlay)"); - clutter_paint_node_add_child (root_node, node_overlay); - clutter_paint_node_add_rectangle (node_overlay, alloc); - } - } - } - - g_clear_pointer (&blended_tex_region, cairo_region_destroy); -} - -static CoglTexture * -select_texture_for_paint (MetaShapedTexture *stex, - ClutterPaintContext *paint_context) -{ - CoglTexture *texture = NULL; - int64_t now; - - if (!stex->texture) - return NULL; - - now = g_get_monotonic_time (); - - if (stex->create_mipmaps && stex->last_invalidation) - { - int64_t age = now - stex->last_invalidation; - - if (age >= MIN_MIPMAP_AGE_USEC || - stex->fast_updates < MIN_FAST_UPDATES_BEFORE_UNMIPMAP) - { - texture = meta_texture_tower_get_paint_texture (stex->paint_tower, - paint_context); - } - } - - if (!texture) - { - texture = stex->texture; - - if (stex->create_mipmaps) - { - /* Minus 1000 to ensure we don't fail the age test in timeout */ - stex->earliest_remipmap = now + MIN_MIPMAP_AGE_USEC - 1000; - - if (!stex->remipmap_timeout_id) - stex->remipmap_timeout_id = - g_timeout_add (MIN_MIPMAP_AGE_USEC / 1000, - texture_is_idle_and_not_mipmapped, - stex); - } - } - - return texture; -} - -static void -meta_shaped_texture_paint_content (ClutterContent *content, - ClutterActor *actor, - ClutterPaintNode *root_node, - ClutterPaintContext *paint_context) -{ - MetaShapedTexture *stex = META_SHAPED_TEXTURE (content); - ClutterActorBox alloc; - CoglTexture *paint_tex = NULL; - uint8_t opacity; - - if (stex->clip_region && cairo_region_is_empty (stex->clip_region)) - return; - - /* The GL EXT_texture_from_pixmap extension does allow for it to be - * used together with SGIS_generate_mipmap, however this is very - * rarely supported. Also, even when it is supported there - * are distinct performance implications from: - * - * - Updating mipmaps that we don't need - * - Having to reallocate pixmaps on the server into larger buffers - * - * So, we just unconditionally use our mipmap emulation code. If we - * wanted to use SGIS_generate_mipmap, we'd have to query COGL to - * see if it was supported (no API currently), and then if and only - * if that was the case, set the clutter texture quality to HIGH. - * Setting the texture quality to high without SGIS_generate_mipmap - * support for TFP textures will result in fallbacks to XGetImage. - */ - paint_tex = select_texture_for_paint (stex, paint_context); - if (!paint_tex) - return; - - opacity = clutter_actor_get_paint_opacity (actor); - clutter_actor_get_content_box (actor, &alloc); - - do_paint_content (stex, root_node, paint_context, paint_tex, &alloc, opacity); -} - -static gboolean -meta_shaped_texture_get_preferred_size (ClutterContent *content, - float *width, - float *height) -{ - MetaShapedTexture *stex = META_SHAPED_TEXTURE (content); - - meta_shaped_texture_ensure_size_valid (stex); - - if (width) - *width = stex->dst_width; - - if (height) - *height = stex->dst_height; - - return TRUE; -} - -static void -clutter_content_iface_init (ClutterContentInterface *iface) -{ - iface->paint_content = meta_shaped_texture_paint_content; - iface->get_preferred_size = meta_shaped_texture_get_preferred_size; -} - -void -meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex, - gboolean create_mipmaps) -{ - g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); - - create_mipmaps = create_mipmaps != FALSE; - - if (create_mipmaps != stex->create_mipmaps) - { - CoglTexture *base_texture; - stex->create_mipmaps = create_mipmaps; - base_texture = create_mipmaps ? stex->texture : NULL; - meta_texture_tower_set_base_texture (stex->paint_tower, base_texture); - } -} - -void -meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex, - CoglTexture *mask_texture) -{ - g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); - - g_clear_pointer (&stex->mask_texture, cogl_object_unref); - - if (mask_texture != NULL) - { - stex->mask_texture = mask_texture; - cogl_object_ref (stex->mask_texture); - } - - clutter_content_invalidate (CLUTTER_CONTENT (stex)); -} - -/** - * meta_shaped_texture_update_area: - * @stex: #MetaShapedTexture - * @x: the x coordinate of the damaged area - * @y: the y coordinate of the damaged area - * @width: the width of the damaged area - * @height: the height of the damaged area - * @clip: (out): the resulting clip region - * - * Repairs the damaged area indicated by @x, @y, @width and @height - * and potentially queues a redraw. - * - * Return value: Whether a redraw have been queued or not - */ -gboolean -meta_shaped_texture_update_area (MetaShapedTexture *stex, - int x, - int y, - int width, - int height, - cairo_rectangle_int_t *clip) -{ - MetaMonitorTransform inverted_transform; - int scaled_and_transformed_width; - int scaled_and_transformed_height; - - if (stex->texture == NULL) - return FALSE; - - *clip = (cairo_rectangle_int_t) { - .x = x, - .y = y, - .width = width, - .height = height - }; - - meta_rectangle_scale_double (clip, - 1.0 / stex->buffer_scale, - META_ROUNDING_STRATEGY_GROW, - clip); - - if (meta_monitor_transform_is_rotated (stex->transform)) - { - scaled_and_transformed_width = stex->tex_height / stex->buffer_scale; - scaled_and_transformed_height = stex->tex_width / stex->buffer_scale; - } - else - { - scaled_and_transformed_width = stex->tex_width / stex->buffer_scale; - scaled_and_transformed_height = stex->tex_height / stex->buffer_scale; - } - inverted_transform = meta_monitor_transform_invert (stex->transform); - meta_rectangle_transform (clip, - inverted_transform, - scaled_and_transformed_width, - scaled_and_transformed_height, - clip); - - if (stex->has_viewport_src_rect || stex->has_viewport_dst_size) - { - graphene_rect_t viewport; - graphene_rect_t inverted_viewport; - float dst_width; - float dst_height; - int inverted_dst_width; - int inverted_dst_height; - - if (stex->has_viewport_src_rect) - { - viewport = stex->viewport_src_rect; - } - else - { - viewport = (graphene_rect_t) { - .origin.x = 0, - .origin.y = 0, - .size.width = scaled_and_transformed_width, - .size.height = scaled_and_transformed_height, - }; - } - - if (stex->has_viewport_dst_size) - { - dst_width = (float) stex->viewport_dst_width; - dst_height = (float) stex->viewport_dst_height; - } - else - { - dst_width = (float) viewport.size.width; - dst_height = (float) viewport.size.height; - } - - inverted_viewport = (graphene_rect_t) { - .origin.x = -(viewport.origin.x * (dst_width / viewport.size.width)), - .origin.y = -(viewport.origin.y * (dst_height / viewport.size.height)), - .size.width = dst_width, - .size.height = dst_height - }; - inverted_dst_width = ceilf (viewport.size.width); - inverted_dst_height = ceilf (viewport.size.height); - - meta_rectangle_crop_and_scale (clip, - &inverted_viewport, - inverted_dst_width, - inverted_dst_height, - clip); - } - - meta_texture_tower_update_area (stex->paint_tower, - x, - y, - width, - height); - - stex->prev_invalidation = stex->last_invalidation; - stex->last_invalidation = g_get_monotonic_time (); - - if (stex->prev_invalidation) - { - gint64 interval = stex->last_invalidation - stex->prev_invalidation; - gboolean fast_update = interval < MIN_MIPMAP_AGE_USEC; - - if (!fast_update) - stex->fast_updates = 0; - else if (stex->fast_updates < MIN_FAST_UPDATES_BEFORE_UNMIPMAP) - stex->fast_updates++; - } - - return TRUE; -} - -/** - * meta_shaped_texture_set_texture: - * @stex: The #MetaShapedTexture - * @pixmap: The #CoglTexture to display - */ -void -meta_shaped_texture_set_texture (MetaShapedTexture *stex, - CoglTexture *texture) -{ - g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); - - if (stex->texture == texture) - return; - - set_cogl_texture (stex, texture); -} - -/** - * meta_shaped_texture_set_is_y_inverted: (skip) - */ -void -meta_shaped_texture_set_is_y_inverted (MetaShapedTexture *stex, - gboolean is_y_inverted) -{ - if (stex->is_y_inverted == is_y_inverted) - return; - - meta_shaped_texture_reset_pipelines (stex); - - stex->is_y_inverted = is_y_inverted; -} - -/** - * meta_shaped_texture_set_snippet: (skip) - */ -void -meta_shaped_texture_set_snippet (MetaShapedTexture *stex, - CoglSnippet *snippet) -{ - if (stex->snippet == snippet) - return; - - meta_shaped_texture_reset_pipelines (stex); - - g_clear_pointer (&stex->snippet, cogl_object_unref); - if (snippet) - stex->snippet = cogl_object_ref (snippet); -} - -/** - * meta_shaped_texture_get_texture: - * @stex: The #MetaShapedTexture - * - * Returns: (transfer none): the unshaped texture - */ -CoglTexture * -meta_shaped_texture_get_texture (MetaShapedTexture *stex) -{ - g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), NULL); - return COGL_TEXTURE (stex->texture); -} - -/** - * meta_shaped_texture_set_opaque_region: - * @stex: a #MetaShapedTexture - * @opaque_region: (transfer full): the region of the texture that - * can have blending turned off. - * - * As most windows have a large portion that does not require blending, - * we can easily turn off blending if we know the areas that do not - * require blending. This sets the region where we will not blend for - * optimization purposes. - */ -void -meta_shaped_texture_set_opaque_region (MetaShapedTexture *stex, - cairo_region_t *opaque_region) -{ - g_clear_pointer (&stex->opaque_region, cairo_region_destroy); - if (opaque_region) - stex->opaque_region = cairo_region_reference (opaque_region); -} - -cairo_region_t * -meta_shaped_texture_get_opaque_region (MetaShapedTexture *stex) -{ - return stex->opaque_region; -} - -gboolean -meta_shaped_texture_has_alpha (MetaShapedTexture *stex) -{ - CoglTexture *texture; - - texture = stex->texture; - if (!texture) - return TRUE; - - switch (cogl_texture_get_components (texture)) - { - case COGL_TEXTURE_COMPONENTS_A: - case COGL_TEXTURE_COMPONENTS_RGBA: - return TRUE; - case COGL_TEXTURE_COMPONENTS_RG: - case COGL_TEXTURE_COMPONENTS_RGB: - case COGL_TEXTURE_COMPONENTS_DEPTH: - return FALSE; - } - - g_warn_if_reached (); - return FALSE; -} - -gboolean -meta_shaped_texture_is_opaque (MetaShapedTexture *stex) -{ - CoglTexture *texture; - cairo_rectangle_int_t opaque_rect; - - texture = stex->texture; - if (!texture) - return FALSE; - - if (!meta_shaped_texture_has_alpha (stex)) - return TRUE; - - if (!stex->opaque_region) - return FALSE; - - if (cairo_region_num_rectangles (stex->opaque_region) != 1) - return FALSE; - - cairo_region_get_extents (stex->opaque_region, &opaque_rect); - - meta_shaped_texture_ensure_size_valid (stex); - - return meta_rectangle_equal (&opaque_rect, - &(MetaRectangle) { - .width = stex->dst_width, - .height = stex->dst_height - }); -} - -void -meta_shaped_texture_set_transform (MetaShapedTexture *stex, - MetaMonitorTransform transform) -{ - if (stex->transform == transform) - return; - - stex->transform = transform; - - meta_shaped_texture_reset_pipelines (stex); - invalidate_size (stex); -} - -/** - * meta_shaped_texture_set_viewport_src_rect: - * @stex: A #MetaShapedTexture - * @src_rect: The viewport source rectangle - * - * Sets the viewport area that can be used to crop the original texture. The - * cropped result can then be optionally scaled afterwards using - * meta_shaped_texture_set_viewport_dst_size() as part of a crop-and-scale - * operation. - * - * Note that the viewport's geometry should be provided in the coordinate space - * of the texture received by the client, which might've been scaled as noted by - * meta_shaped_texture_set_buffer_scale(). - * - * %NULL is an invalid value for @src_rect. Use - * meta_shaped_texture_reset_viewport_src_rect() if you want to remove the - * cropping source rectangle. - */ -void -meta_shaped_texture_set_viewport_src_rect (MetaShapedTexture *stex, - graphene_rect_t *src_rect) -{ - if (!stex->has_viewport_src_rect || - !G_APPROX_VALUE (stex->viewport_src_rect.origin.x, - src_rect->origin.x, FLT_EPSILON) || - !G_APPROX_VALUE (stex->viewport_src_rect.origin.y, - src_rect->origin.y, FLT_EPSILON) || - !G_APPROX_VALUE (stex->viewport_src_rect.size.width, - src_rect->size.width, FLT_EPSILON) || - !G_APPROX_VALUE (stex->viewport_src_rect.size.height, - src_rect->size.height, FLT_EPSILON)) - { - stex->has_viewport_src_rect = TRUE; - stex->viewport_src_rect = *src_rect; - meta_shaped_texture_reset_pipelines (stex); - invalidate_size (stex); - } -} - -void -meta_shaped_texture_reset_viewport_src_rect (MetaShapedTexture *stex) -{ - if (!stex->has_viewport_src_rect) - return; - - stex->has_viewport_src_rect = FALSE; - meta_shaped_texture_reset_pipelines (stex); - invalidate_size (stex); -} - -/** - * meta_shaped_texture_set_viewport_dst_size: - * @stex: #MetaShapedTexture - * @dst_width: The final viewport width (> 0) - * @dst_height: The final viewport height (> 0) - * - * Sets a viewport size on @stex of the given @width and @height, which may - * lead to scaling the texture. If you need to have cropping, use - * meta_shaped_texture_set_viewport_src_rect() first, after which the scaling - * stemming from this method will be applied. - * - * If you no longer want to have any scaling, use - * meta_shaped_texture_reset_viewport_dst_size() to clear the current - * parameters. - */ -void -meta_shaped_texture_set_viewport_dst_size (MetaShapedTexture *stex, - int dst_width, - int dst_height) -{ - if (!stex->has_viewport_dst_size || - stex->viewport_dst_width != dst_width || - stex->viewport_dst_height != dst_height) - { - stex->has_viewport_dst_size = TRUE; - stex->viewport_dst_width = dst_width; - stex->viewport_dst_height = dst_height; - invalidate_size (stex); - } -} - -void -meta_shaped_texture_reset_viewport_dst_size (MetaShapedTexture *stex) -{ - if (!stex->has_viewport_dst_size) - return; - - stex->has_viewport_dst_size = FALSE; - invalidate_size (stex); -} - -static gboolean -should_get_via_offscreen (MetaShapedTexture *stex) -{ - if (!cogl_texture_is_get_data_supported (stex->texture)) - return TRUE; - - if (stex->has_viewport_src_rect || stex->has_viewport_dst_size) - return TRUE; - - switch (stex->transform) - { - case META_MONITOR_TRANSFORM_90: - case META_MONITOR_TRANSFORM_180: - case META_MONITOR_TRANSFORM_270: - case META_MONITOR_TRANSFORM_FLIPPED: - case META_MONITOR_TRANSFORM_FLIPPED_90: - case META_MONITOR_TRANSFORM_FLIPPED_180: - case META_MONITOR_TRANSFORM_FLIPPED_270: - return TRUE; - case META_MONITOR_TRANSFORM_NORMAL: - break; - } - - return FALSE; -} - -static cairo_surface_t * -get_image_via_offscreen (MetaShapedTexture *stex, - cairo_rectangle_int_t *clip, - int image_width, - int image_height) -{ - g_autoptr (ClutterPaintNode) root_node = NULL; - ClutterBackend *clutter_backend = clutter_get_default_backend (); - CoglContext *cogl_context = - clutter_backend_get_cogl_context (clutter_backend); - CoglTexture *image_texture; - GError *error = NULL; - CoglOffscreen *offscreen; - CoglFramebuffer *fb; - graphene_matrix_t projection_matrix; - cairo_rectangle_int_t fallback_clip; - ClutterColor clear_color; - ClutterPaintContext *paint_context; - cairo_surface_t *surface; - - if (!clip) - { - fallback_clip = (cairo_rectangle_int_t) { - .width = image_width, - .height = image_height, - }; - clip = &fallback_clip; - } - - image_texture = - COGL_TEXTURE (cogl_texture_2d_new_with_size (cogl_context, - image_width, - image_height)); - cogl_primitive_texture_set_auto_mipmap (COGL_PRIMITIVE_TEXTURE (image_texture), - FALSE); - if (!cogl_texture_allocate (COGL_TEXTURE (image_texture), &error)) - { - g_error_free (error); - cogl_object_unref (image_texture); - return FALSE; - } - - offscreen = cogl_offscreen_new_with_texture (COGL_TEXTURE (image_texture)); - fb = COGL_FRAMEBUFFER (offscreen); - cogl_object_unref (image_texture); - if (!cogl_framebuffer_allocate (fb, &error)) - { - g_error_free (error); - g_object_unref (fb); - return FALSE; - } - - cogl_framebuffer_push_matrix (fb); - graphene_matrix_init_translate (&projection_matrix, - &GRAPHENE_POINT3D_INIT (-(image_width / 2.0), - -(image_height / 2.0), - 0)); - graphene_matrix_scale (&projection_matrix, - 1.0 / (image_width / 2.0), - -1.0 / (image_height / 2.0), 0); - - cogl_framebuffer_set_projection_matrix (fb, &projection_matrix); - - clear_color = (ClutterColor) { 0, 0, 0, 0 }; - - root_node = clutter_root_node_new (fb, &clear_color, COGL_BUFFER_BIT_COLOR); - clutter_paint_node_set_static_name (root_node, "MetaShapedTexture.offscreen"); - - paint_context = - clutter_paint_context_new_for_framebuffer (fb, NULL, - CLUTTER_PAINT_FLAG_NONE); - - do_paint_content (stex, root_node, paint_context, - stex->texture, - &(ClutterActorBox) { - 0, 0, - image_width, - image_height, - }, - 255); - - clutter_paint_node_paint (root_node, paint_context); - clutter_paint_context_destroy (paint_context); - - surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - clip->width, clip->height); - cogl_framebuffer_read_pixels (fb, - clip->x, clip->y, - clip->width, clip->height, - CLUTTER_CAIRO_FORMAT_ARGB32, - cairo_image_surface_get_data (surface)); - g_object_unref (fb); - - cairo_surface_mark_dirty (surface); - - return surface; -} - -/** - * meta_shaped_texture_get_image: - * @stex: A #MetaShapedTexture - * @clip: (nullable): A clipping rectangle, to help prevent extra processing. - * In the case that the clipping rectangle is partially or fully - * outside the bounds of the texture, the rectangle will be clipped. - * - * Flattens the two layers of the shaped texture into one ARGB32 - * image by alpha blending the two images, and returns the flattened - * image. - * - * Returns: (nullable) (transfer full): a new cairo surface to be freed with - * cairo_surface_destroy(). - */ -cairo_surface_t * -meta_shaped_texture_get_image (MetaShapedTexture *stex, - cairo_rectangle_int_t *clip) -{ - cairo_rectangle_int_t *image_clip = NULL; - CoglTexture *texture, *mask_texture; - cairo_surface_t *surface; - - g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), NULL); - - texture = COGL_TEXTURE (stex->texture); - - if (texture == NULL) - return NULL; - - meta_shaped_texture_ensure_size_valid (stex); - - if (stex->dst_width == 0 || stex->dst_height == 0) - return NULL; - - if (clip != NULL) - { - cairo_rectangle_int_t dst_rect; - - image_clip = alloca (sizeof (cairo_rectangle_int_t)); - dst_rect = (cairo_rectangle_int_t) { - .width = stex->dst_width, - .height = stex->dst_height, - }; - - if (!meta_rectangle_intersect (&dst_rect, clip, - image_clip)) - return NULL; - - *image_clip = (MetaRectangle) { - .x = image_clip->x * stex->buffer_scale, - .y = image_clip->y * stex->buffer_scale, - .width = image_clip->width * stex->buffer_scale, - .height = image_clip->height * stex->buffer_scale, - }; - } - - if (should_get_via_offscreen (stex)) - { - int image_width; - int image_height; - - image_width = stex->dst_width * stex->buffer_scale; - image_height = stex->dst_height * stex->buffer_scale; - return get_image_via_offscreen (stex, - image_clip, - image_width, - image_height); - } - - if (image_clip) - texture = cogl_texture_new_from_sub_texture (texture, - image_clip->x, - image_clip->y, - image_clip->width, - image_clip->height); - - surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - cogl_texture_get_width (texture), - cogl_texture_get_height (texture)); - - cogl_texture_get_data (texture, CLUTTER_CAIRO_FORMAT_ARGB32, - cairo_image_surface_get_stride (surface), - cairo_image_surface_get_data (surface)); - - cairo_surface_mark_dirty (surface); - - if (image_clip) - cogl_object_unref (texture); - - mask_texture = stex->mask_texture; - if (mask_texture != NULL) - { - cairo_t *cr; - cairo_surface_t *mask_surface; - - if (image_clip) - mask_texture = - cogl_texture_new_from_sub_texture (mask_texture, - image_clip->x, - image_clip->y, - image_clip->width, - image_clip->height); - - mask_surface = cairo_image_surface_create (CAIRO_FORMAT_A8, - cogl_texture_get_width (mask_texture), - cogl_texture_get_height (mask_texture)); - - cogl_texture_get_data (mask_texture, COGL_PIXEL_FORMAT_A_8, - cairo_image_surface_get_stride (mask_surface), - cairo_image_surface_get_data (mask_surface)); - - cairo_surface_mark_dirty (mask_surface); - - cr = cairo_create (surface); - cairo_set_source_surface (cr, mask_surface, 0, 0); - cairo_set_operator (cr, CAIRO_OPERATOR_DEST_IN); - cairo_paint (cr); - cairo_destroy (cr); - - cairo_surface_destroy (mask_surface); - - if (image_clip) - cogl_object_unref (mask_texture); - } - - return surface; -} - -void -meta_shaped_texture_set_fallback_size (MetaShapedTexture *stex, - int fallback_width, - int fallback_height) -{ - stex->fallback_width = fallback_width; - stex->fallback_height = fallback_height; - - invalidate_size (stex); -} - -MetaShapedTexture * -meta_shaped_texture_new (void) -{ - return g_object_new (META_TYPE_SHAPED_TEXTURE, NULL); -} - -/** - * meta_shaped_texture_set_buffer_scale: - * @stex: A #MetaShapedTexture - * @buffer_scale: The scale that should be applied to coorsinate space - * - * Instructs @stex to interpret the geometry of the input texture by scaling it - * with @buffer_scale. This means that the #CoglTexture that is provided by a - * client is already scaled by that factor. - */ -void -meta_shaped_texture_set_buffer_scale (MetaShapedTexture *stex, - int buffer_scale) -{ - g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); - - if (buffer_scale == stex->buffer_scale) - return; - - stex->buffer_scale = buffer_scale; - - invalidate_size (stex); -} - -int -meta_shaped_texture_get_buffer_scale (MetaShapedTexture *stex) -{ - g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), 1.0); - - return stex->buffer_scale; -} - -/** - * meta_shaped_texture_get_width: - * @stex: A #MetaShapedTexture - * - * Returns: The final width of @stex after its shaping operations are applied. - */ -int -meta_shaped_texture_get_width (MetaShapedTexture *stex) -{ - g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), 0); - - meta_shaped_texture_ensure_size_valid (stex); - - return stex->dst_width; -} - -/** - * meta_shaped_texture_get_height: - * @stex: A #MetaShapedTexture - * - * Returns: The final height of @stex after its shaping operations are applied. - */ -int -meta_shaped_texture_get_height (MetaShapedTexture *stex) -{ - g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), 0); - - meta_shaped_texture_ensure_size_valid (stex); - - return stex->dst_height; -} diff --git a/src/compositor/meta-surface-actor-wayland.c b/src/compositor/meta-surface-actor-wayland.c deleted file mode 100644 index a182ad851..000000000 --- a/src/compositor/meta-surface-actor-wayland.c +++ /dev/null @@ -1,198 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2013 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -#include "config.h" - -#include "compositor/meta-surface-actor-wayland.h" - -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-logical-monitor.h" -#include "cogl/cogl-wayland-server.h" -#include "compositor/meta-shaped-texture-private.h" -#include "compositor/region-utils.h" -#include "wayland/meta-wayland-buffer.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-window-wayland.h" - -struct _MetaSurfaceActorWayland -{ - MetaSurfaceActor parent; - - MetaWaylandSurface *surface; -}; - -G_DEFINE_TYPE (MetaSurfaceActorWayland, - meta_surface_actor_wayland, - META_TYPE_SURFACE_ACTOR) - -static void -meta_surface_actor_wayland_process_damage (MetaSurfaceActor *actor, - int x, - int y, - int width, - int height) -{ - meta_surface_actor_update_area (actor, x, y, width, height); -} - -static gboolean -meta_surface_actor_wayland_is_opaque (MetaSurfaceActor *actor) -{ - MetaShapedTexture *stex = meta_surface_actor_get_texture (actor); - - return meta_shaped_texture_is_opaque (stex); -} - -CoglScanout * -meta_surface_actor_wayland_try_acquire_scanout (MetaSurfaceActorWayland *self, - CoglOnscreen *onscreen) -{ - MetaWaylandSurface *surface; - CoglScanout *scanout; - - surface = meta_surface_actor_wayland_get_surface (self); - if (!surface) - return NULL; - - scanout = meta_wayland_surface_try_acquire_scanout (surface, onscreen); - if (!scanout) - return NULL; - - return scanout; -} - -#define UNOBSCURED_TRESHOLD 0.1 - -ClutterStageView * -meta_surface_actor_wayland_get_current_primary_view (MetaSurfaceActor *actor, - ClutterStage *stage) -{ - ClutterStageView *current_primary_view = NULL; - float highest_refresh_rate = 0.f; - float biggest_unobscurred_fraction = 0.f; - GList *l; - - for (l = clutter_stage_peek_stage_views (stage); l; l = l->next) - { - ClutterStageView *stage_view = l->data; - float refresh_rate; - float unobscurred_fraction = 1.f; - - if (clutter_actor_has_mapped_clones (CLUTTER_ACTOR (actor))) - { - if (!clutter_actor_is_effectively_on_stage_view (CLUTTER_ACTOR (actor), - stage_view)) - continue; - } - else - { - if (l->next || biggest_unobscurred_fraction > 0.f) - { - if (meta_surface_actor_is_obscured_on_stage_view (actor, - stage_view, - &unobscurred_fraction)) - continue; - } - else - { - if (meta_surface_actor_is_obscured (actor)) - continue; - } - } - - refresh_rate = clutter_stage_view_get_refresh_rate (stage_view); - - if ((refresh_rate > highest_refresh_rate && - (unobscurred_fraction > UNOBSCURED_TRESHOLD || - biggest_unobscurred_fraction < UNOBSCURED_TRESHOLD)) || - (biggest_unobscurred_fraction < UNOBSCURED_TRESHOLD && - unobscurred_fraction > UNOBSCURED_TRESHOLD)) - { - current_primary_view = stage_view; - highest_refresh_rate = refresh_rate; - biggest_unobscurred_fraction = unobscurred_fraction; - } - } - - return current_primary_view; -} - -static void -meta_surface_actor_wayland_dispose (GObject *object) -{ - MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (object); - MetaShapedTexture *stex; - - stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); - if (stex) - meta_shaped_texture_set_texture (stex, NULL); - - if (self->surface) - { - g_object_remove_weak_pointer (G_OBJECT (self->surface), - (gpointer *) &self->surface); - self->surface = NULL; - } - - G_OBJECT_CLASS (meta_surface_actor_wayland_parent_class)->dispose (object); -} - -static void -meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass) -{ - MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass); - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage; - surface_actor_class->is_opaque = meta_surface_actor_wayland_is_opaque; - - object_class->dispose = meta_surface_actor_wayland_dispose; -} - -static void -meta_surface_actor_wayland_init (MetaSurfaceActorWayland *self) -{ -} - -MetaSurfaceActor * -meta_surface_actor_wayland_new (MetaWaylandSurface *surface) -{ - MetaSurfaceActorWayland *self = g_object_new (META_TYPE_SURFACE_ACTOR_WAYLAND, NULL); - - g_assert (meta_is_wayland_compositor ()); - - self->surface = surface; - g_object_add_weak_pointer (G_OBJECT (self->surface), - (gpointer *) &self->surface); - - return META_SURFACE_ACTOR (self); -} - -MetaWaylandSurface * -meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self) -{ - return self->surface; -} diff --git a/src/compositor/meta-surface-actor-wayland.h b/src/compositor/meta-surface-actor-wayland.h deleted file mode 100644 index 10eb3326a..000000000 --- a/src/compositor/meta-surface-actor-wayland.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2013 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -#ifndef __META_SURFACE_ACTOR_WAYLAND_H__ -#define __META_SURFACE_ACTOR_WAYLAND_H__ - -#include - -#include "backends/meta-monitor-manager-private.h" -#include "compositor/meta-surface-actor.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland.h" - -G_BEGIN_DECLS - -#define META_TYPE_SURFACE_ACTOR_WAYLAND (meta_surface_actor_wayland_get_type ()) -G_DECLARE_FINAL_TYPE (MetaSurfaceActorWayland, - meta_surface_actor_wayland, - META, SURFACE_ACTOR_WAYLAND, - MetaSurfaceActor) - -MetaSurfaceActor * meta_surface_actor_wayland_new (MetaWaylandSurface *surface); -MetaWaylandSurface * meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self); -void meta_surface_actor_wayland_surface_destroyed (MetaSurfaceActorWayland *self); - -double meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor); - -void meta_surface_actor_wayland_get_subsurface_rect (MetaSurfaceActorWayland *self, - MetaRectangle *rect); - -void meta_surface_actor_wayland_add_frame_callbacks (MetaSurfaceActorWayland *self, - struct wl_list *frame_callbacks); - -CoglScanout * meta_surface_actor_wayland_try_acquire_scanout (MetaSurfaceActorWayland *self, - CoglOnscreen *onscreen); - -ClutterStageView * meta_surface_actor_wayland_get_current_primary_view (MetaSurfaceActor *actor, - ClutterStage *stage); - -G_END_DECLS - -#endif /* __META_SURFACE_ACTOR_WAYLAND_H__ */ diff --git a/src/compositor/meta-surface-actor-x11.c b/src/compositor/meta-surface-actor-x11.c deleted file mode 100644 index 41ae2dffb..000000000 --- a/src/compositor/meta-surface-actor-x11.c +++ /dev/null @@ -1,422 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2013 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Owen Taylor - * Jasper St. Pierre - */ - -#include "config.h" - -#include "compositor/meta-surface-actor-x11.h" - -#include - -#include "cogl/winsys/cogl-texture-pixmap-x11.h" -#include "compositor/meta-cullable.h" -#include "compositor/meta-shaped-texture-private.h" -#include "compositor/meta-window-actor-private.h" -#include "core/window-private.h" -#include "meta/meta-x11-errors.h" -#include "x11/meta-x11-display-private.h" -#include "x11/window-x11.h" - -struct _MetaSurfaceActorX11 -{ - MetaSurfaceActor parent; - - MetaWindow *window; - - MetaDisplay *display; - - CoglTexture *texture; - Pixmap pixmap; - Damage damage; - - int last_width; - int last_height; - - /* This is used to detect fullscreen windows that need to be unredirected */ - guint full_damage_frames_count; - guint does_full_damage : 1; - - /* Other state... */ - guint received_damage : 1; - guint size_changed : 1; - - guint unredirected : 1; -}; - -G_DEFINE_TYPE (MetaSurfaceActorX11, - meta_surface_actor_x11, - META_TYPE_SURFACE_ACTOR) - -static void -free_damage (MetaSurfaceActorX11 *self) -{ - MetaDisplay *display = self->display; - Display *xdisplay; - - if (self->damage == None) - return; - - xdisplay = meta_x11_display_get_xdisplay (display->x11_display); - - meta_x11_error_trap_push (display->x11_display); - XDamageDestroy (xdisplay, self->damage); - self->damage = None; - meta_x11_error_trap_pop (display->x11_display); -} - -static void -detach_pixmap (MetaSurfaceActorX11 *self) -{ - MetaDisplay *display = self->display; - MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); - Display *xdisplay; - - if (self->pixmap == None) - return; - - xdisplay = meta_x11_display_get_xdisplay (display->x11_display); - - /* Get rid of all references to the pixmap before freeing it; it's unclear whether - * you are supposed to be able to free a GLXPixmap after freeing the underlying - * pixmap, but it certainly doesn't work with current DRI/Mesa - */ - meta_shaped_texture_set_texture (stex, NULL); - cogl_flush (); - - meta_x11_error_trap_push (display->x11_display); - XFreePixmap (xdisplay, self->pixmap); - self->pixmap = None; - meta_x11_error_trap_pop (display->x11_display); - - g_clear_pointer (&self->texture, cogl_object_unref); -} - -static void -set_pixmap (MetaSurfaceActorX11 *self, - Pixmap pixmap) -{ - CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); - MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); - GError *error = NULL; - CoglTexture *texture; - - g_assert (self->pixmap == None); - self->pixmap = pixmap; - - texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, self->pixmap, FALSE, &error)); - - if (error != NULL) - { - g_warning ("Failed to allocate stex texture: %s", error->message); - g_error_free (error); - } - else if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture)))) - g_warning ("NOTE: Not using GLX TFP!"); - - self->texture = texture; - meta_shaped_texture_set_texture (stex, texture); -} - -static void -update_pixmap (MetaSurfaceActorX11 *self) -{ - MetaDisplay *display = self->display; - Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display); - - if (self->size_changed) - { - detach_pixmap (self); - self->size_changed = FALSE; - } - - if (self->pixmap == None) - { - Pixmap new_pixmap; - Window xwindow = meta_window_x11_get_toplevel_xwindow (self->window); - - meta_x11_error_trap_push (display->x11_display); - new_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow); - - if (meta_x11_error_trap_pop_with_return (display->x11_display) != Success) - { - /* Probably a BadMatch if the window isn't viewable; we could - * GrabServer/GetWindowAttributes/NameWindowPixmap/UngrabServer/Sync - * to avoid this, but there's no reason to take two round trips - * when one will do. (We need that Sync if we want to handle failures - * for any reason other than !viewable. That's unlikely, but maybe - * we'll BadAlloc or something.) - */ - new_pixmap = None; - } - - if (new_pixmap == None) - { - meta_verbose ("Unable to get named pixmap for %s", - meta_window_get_description (self->window)); - return; - } - - set_pixmap (self, new_pixmap); - } -} - -gboolean -meta_surface_actor_x11_is_visible (MetaSurfaceActorX11 *self) -{ - return (self->pixmap != None) && !self->unredirected; -} - -static void -meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor, - int x, int y, int width, int height) -{ - MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); - - self->received_damage = TRUE; - - if (meta_window_is_fullscreen (self->window) && !self->unredirected && !self->does_full_damage) - { - MetaRectangle window_rect; - meta_window_get_frame_rect (self->window, &window_rect); - - if (x == 0 && - y == 0 && - window_rect.width == width && - window_rect.height == height) - self->full_damage_frames_count++; - else - self->full_damage_frames_count = 0; - - if (self->full_damage_frames_count >= 100) - self->does_full_damage = TRUE; - } - - if (!meta_surface_actor_x11_is_visible (self)) - return; - - cogl_texture_pixmap_x11_update_area (COGL_TEXTURE_PIXMAP_X11 (self->texture), - x, y, width, height); - meta_surface_actor_update_area (actor, x, y, width, height); -} - -void -meta_surface_actor_x11_handle_updates (MetaSurfaceActorX11 *self) -{ - MetaDisplay *display = self->display; - Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display); - - if (self->received_damage) - { - meta_x11_error_trap_push (display->x11_display); - XDamageSubtract (xdisplay, self->damage, None, None); - meta_x11_error_trap_pop (display->x11_display); - - self->received_damage = FALSE; - } - - update_pixmap (self); -} - -static gboolean -meta_surface_actor_x11_is_opaque (MetaSurfaceActor *actor) -{ - MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); - MetaShapedTexture *stex = meta_surface_actor_get_texture (actor); - - if (meta_surface_actor_x11_is_unredirected (self)) - return TRUE; - - return meta_shaped_texture_is_opaque (stex); -} - -gboolean -meta_surface_actor_x11_should_unredirect (MetaSurfaceActorX11 *self) -{ - if (!meta_surface_actor_x11_is_opaque (META_SURFACE_ACTOR (self))) - return FALSE; - - if (!self->does_full_damage && - !meta_window_is_override_redirect (self->window)) - return FALSE; - - return TRUE; -} - -static void -sync_unredirected (MetaSurfaceActorX11 *self) -{ - MetaDisplay *display = self->display; - Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display); - Window xwindow = meta_window_x11_get_toplevel_xwindow (self->window); - - meta_x11_error_trap_push (display->x11_display); - - if (self->unredirected) - { - XCompositeUnredirectWindow (xdisplay, xwindow, CompositeRedirectManual); - XSync (xdisplay, False); - detach_pixmap (self); - } - else - { - XCompositeRedirectWindow (xdisplay, xwindow, CompositeRedirectManual); - XSync (xdisplay, False); - clutter_actor_queue_redraw (CLUTTER_ACTOR (self)); - } - - meta_x11_error_trap_pop (display->x11_display); -} - -void -meta_surface_actor_x11_set_unredirected (MetaSurfaceActorX11 *self, - gboolean unredirected) -{ - if (self->unredirected == unredirected) - return; - - self->unredirected = unredirected; - sync_unredirected (self); -} - -gboolean -meta_surface_actor_x11_is_unredirected (MetaSurfaceActorX11 *self) -{ - return self->unredirected; -} - -static void -release_x11_resources (MetaSurfaceActorX11 *self) -{ - detach_pixmap (self); - free_damage (self); -} - -static void -meta_surface_actor_x11_dispose (GObject *object) -{ - MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (object); - - release_x11_resources (self); - - G_OBJECT_CLASS (meta_surface_actor_x11_parent_class)->dispose (object); -} - -static void -meta_surface_actor_x11_class_init (MetaSurfaceActorX11Class *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass); - - object_class->dispose = meta_surface_actor_x11_dispose; - - surface_actor_class->process_damage = meta_surface_actor_x11_process_damage; - surface_actor_class->is_opaque = meta_surface_actor_x11_is_opaque; -} - -static void -meta_surface_actor_x11_init (MetaSurfaceActorX11 *self) -{ - self->last_width = -1; - self->last_height = -1; -} - -static void -create_damage (MetaSurfaceActorX11 *self) -{ - Display *xdisplay = meta_x11_display_get_xdisplay (self->display->x11_display); - Window xwindow = meta_window_x11_get_toplevel_xwindow (self->window); - - self->damage = XDamageCreate (xdisplay, xwindow, XDamageReportBoundingBox); -} - -static void -window_decorated_notify (MetaWindow *window, - GParamSpec *pspec, - gpointer user_data) -{ - MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (user_data); - - release_x11_resources (self); - create_damage (self); -} - -static void -reset_texture (MetaSurfaceActorX11 *self) -{ - MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); - - if (!self->texture) - return; - - /* Setting the texture to NULL will cause all the FBO's cached by the - * shaped texture's MetaTextureTower to be discarded and recreated. - */ - meta_shaped_texture_set_texture (stex, NULL); - meta_shaped_texture_set_texture (stex, self->texture); -} - -MetaSurfaceActor * -meta_surface_actor_x11_new (MetaWindow *window) -{ - MetaSurfaceActorX11 *self = g_object_new (META_TYPE_SURFACE_ACTOR_X11, NULL); - MetaDisplay *display = meta_window_get_display (window); - - g_assert (!meta_is_wayland_compositor ()); - - self->window = window; - self->display = display; - - g_signal_connect_object (self->display, "gl-video-memory-purged", - G_CALLBACK (reset_texture), self, G_CONNECT_SWAPPED); - - create_damage (self); - g_signal_connect_object (self->window, "notify::decorated", - G_CALLBACK (window_decorated_notify), self, 0); - - g_signal_connect_object (meta_window_actor_from_window (window), "destroy", - G_CALLBACK (release_x11_resources), self, - G_CONNECT_SWAPPED); - - self->unredirected = FALSE; - sync_unredirected (self); - - clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE); - return META_SURFACE_ACTOR (self); -} - -void -meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self, - int width, int height) -{ - MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); - - if (self->last_width == width && - self->last_height == height) - return; - - self->size_changed = TRUE; - self->last_width = width; - self->last_height = height; - meta_shaped_texture_set_fallback_size (stex, width, height); -} diff --git a/src/compositor/meta-surface-actor-x11.h b/src/compositor/meta-surface-actor-x11.h deleted file mode 100644 index 0a8517236..000000000 --- a/src/compositor/meta-surface-actor-x11.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2013 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Owen Taylor - * Jasper St. Pierre - */ - -#ifndef __META_SURFACE_ACTOR_X11_H__ -#define __META_SURFACE_ACTOR_X11_H__ - -#include - -#include - -#include "compositor/meta-surface-actor.h" -#include "meta/display.h" -#include "meta/window.h" - -G_BEGIN_DECLS - -#define META_TYPE_SURFACE_ACTOR_X11 (meta_surface_actor_x11_get_type ()) -G_DECLARE_FINAL_TYPE (MetaSurfaceActorX11, - meta_surface_actor_x11, - META, SURFACE_ACTOR_X11, - MetaSurfaceActor) - -MetaSurfaceActor * meta_surface_actor_x11_new (MetaWindow *window); - -void meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self, - int width, int height); -gboolean meta_surface_actor_x11_should_unredirect (MetaSurfaceActorX11 *self); - -void meta_surface_actor_x11_set_unredirected (MetaSurfaceActorX11 *self, - gboolean unredirected); - -gboolean meta_surface_actor_x11_is_unredirected (MetaSurfaceActorX11 *self); - -gboolean meta_surface_actor_x11_is_visible (MetaSurfaceActorX11 *self); - -void meta_surface_actor_x11_handle_updates (MetaSurfaceActorX11 *self); - -G_END_DECLS - -#endif /* __META_SURFACE_ACTOR_X11_H__ */ diff --git a/src/compositor/meta-surface-actor.c b/src/compositor/meta-surface-actor.c deleted file mode 100644 index 48042b227..000000000 --- a/src/compositor/meta-surface-actor.c +++ /dev/null @@ -1,698 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/** - * SECTION:meta-surface-actor - * @title: MetaSurfaceActor - * @short_description: An actor representing a surface in the scene graph - * - * MetaSurfaceActor is an abstract class which represents a surface in the - * Clutter scene graph. A subclass can implement the specifics of a surface - * depending on the way it is handled by a display protocol. - * - * An important feature of #MetaSurfaceActor is that it allows you to set an - * "input region": all events that occur in the surface, but outside of the - * input region are to be explicitly ignored. By default, this region is to - * %NULL, which means events on the whole surface is allowed. - */ - -#include "config.h" - -#include "compositor/meta-surface-actor.h" - -#include "clutter/clutter.h" -#include "compositor/clutter-utils.h" -#include "compositor/meta-cullable.h" -#include "compositor/meta-shaped-texture-private.h" -#include "compositor/meta-window-actor-private.h" -#include "compositor/region-utils.h" -#include "meta/meta-shaped-texture.h" - -typedef struct _MetaSurfaceActorPrivate -{ - MetaShapedTexture *texture; - - cairo_region_t *input_region; - - /* MetaCullable regions, see that documentation for more details */ - cairo_region_t *unobscured_region; - - /* Freeze/thaw accounting */ - cairo_region_t *pending_damage; - guint frozen : 1; -} MetaSurfaceActorPrivate; - -static void cullable_iface_init (MetaCullableInterface *iface); - -G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_TYPE_ACTOR, - G_ADD_PRIVATE (MetaSurfaceActor) - G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init)); - -enum -{ - REPAINT_SCHEDULED, - SIZE_CHANGED, - - LAST_SIGNAL, -}; - -static guint signals[LAST_SIGNAL]; - -typedef enum -{ - IN_STAGE_PERSPECTIVE, - IN_ACTOR_PERSPECTIVE -} ScalePerspectiveType; - -static cairo_region_t * -effective_unobscured_region (MetaSurfaceActor *surface_actor) -{ - MetaSurfaceActorPrivate *priv = - meta_surface_actor_get_instance_private (surface_actor); - ClutterActor *actor = CLUTTER_ACTOR (surface_actor); - - /* Fail if we have any mapped clones. */ - if (clutter_actor_has_mapped_clones (actor)) - return NULL; - - return priv->unobscured_region; -} - -static cairo_region_t* -get_scaled_region (MetaSurfaceActor *surface_actor, - cairo_region_t *region, - ScalePerspectiveType scale_perspective) -{ - MetaWindowActor *window_actor; - cairo_region_t *scaled_region = NULL; - int geometry_scale; - float x, y; - - window_actor = meta_window_actor_from_actor (CLUTTER_ACTOR (surface_actor)); - geometry_scale = meta_window_actor_get_geometry_scale (window_actor); - - clutter_actor_get_position (CLUTTER_ACTOR (surface_actor), &x, &y); - cairo_region_translate (region, x, y); - - switch (scale_perspective) - { - case IN_STAGE_PERSPECTIVE: - scaled_region = meta_region_scale_double (region, - geometry_scale, - META_ROUNDING_STRATEGY_GROW); - break; - case IN_ACTOR_PERSPECTIVE: - scaled_region = meta_region_scale_double (region, - 1.0 / geometry_scale, - META_ROUNDING_STRATEGY_GROW); - break; - } - - g_assert (scaled_region != NULL); - cairo_region_translate (region, -x, -y); - cairo_region_translate (scaled_region, -x, -y); - - return scaled_region; -} - -static void -set_unobscured_region (MetaSurfaceActor *surface_actor, - cairo_region_t *unobscured_region) -{ - MetaSurfaceActorPrivate *priv = - meta_surface_actor_get_instance_private (surface_actor); - - g_clear_pointer (&priv->unobscured_region, cairo_region_destroy); - if (unobscured_region) - { - if (cairo_region_is_empty (unobscured_region)) - { - priv->unobscured_region = cairo_region_reference (unobscured_region); - } - else - { - cairo_rectangle_int_t bounds = { 0, }; - float width, height; - - clutter_content_get_preferred_size (CLUTTER_CONTENT (priv->texture), - &width, - &height); - bounds = (cairo_rectangle_int_t) { - .width = width, - .height = height, - }; - - priv->unobscured_region = get_scaled_region (surface_actor, - unobscured_region, - IN_ACTOR_PERSPECTIVE); - - cairo_region_intersect_rectangle (priv->unobscured_region, &bounds); - } - } -} - -static void -set_clip_region (MetaSurfaceActor *surface_actor, - cairo_region_t *clip_region) -{ - MetaSurfaceActorPrivate *priv = - meta_surface_actor_get_instance_private (surface_actor); - MetaShapedTexture *stex = priv->texture; - - if (clip_region && !cairo_region_is_empty (clip_region)) - { - cairo_region_t *region; - - region = get_scaled_region (surface_actor, - clip_region, - IN_ACTOR_PERSPECTIVE); - meta_shaped_texture_set_clip_region (stex, region); - - cairo_region_destroy (region); - } - else - { - meta_shaped_texture_set_clip_region (stex, clip_region); - } -} - -static void -meta_surface_actor_pick (ClutterActor *actor, - ClutterPickContext *pick_context) -{ - MetaSurfaceActor *self = META_SURFACE_ACTOR (actor); - MetaSurfaceActorPrivate *priv = - meta_surface_actor_get_instance_private (self); - ClutterActorIter iter; - ClutterActor *child; - - if (!clutter_actor_should_pick (actor, pick_context)) - return; - - /* If there is no region then use the regular pick */ - if (priv->input_region == NULL) - { - ClutterActorClass *actor_class = - CLUTTER_ACTOR_CLASS (meta_surface_actor_parent_class); - - actor_class->pick (actor, pick_context); - } - else - { - int n_rects; - int i; - - n_rects = cairo_region_num_rectangles (priv->input_region); - - for (i = 0; i < n_rects; i++) - { - cairo_rectangle_int_t rect; - ClutterActorBox box; - - cairo_region_get_rectangle (priv->input_region, i, &rect); - - box.x1 = rect.x; - box.y1 = rect.y; - box.x2 = rect.x + rect.width; - box.y2 = rect.y + rect.height; - clutter_actor_pick_box (actor, pick_context, &box); - } - } - - clutter_actor_iter_init (&iter, actor); - - while (clutter_actor_iter_next (&iter, &child)) - clutter_actor_pick (child, pick_context); -} - -static gboolean -meta_surface_actor_get_paint_volume (ClutterActor *actor, - ClutterPaintVolume *volume) -{ - return clutter_paint_volume_set_from_allocation (volume, actor); -} - -static void -meta_surface_actor_dispose (GObject *object) -{ - MetaSurfaceActor *self = META_SURFACE_ACTOR (object); - MetaSurfaceActorPrivate *priv = - meta_surface_actor_get_instance_private (self); - - g_clear_pointer (&priv->input_region, cairo_region_destroy); - g_clear_object (&priv->texture); - - set_unobscured_region (self, NULL); - - G_OBJECT_CLASS (meta_surface_actor_parent_class)->dispose (object); -} - -static void -meta_surface_actor_class_init (MetaSurfaceActorClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); - - object_class->dispose = meta_surface_actor_dispose; - actor_class->pick = meta_surface_actor_pick; - actor_class->get_paint_volume = meta_surface_actor_get_paint_volume; - - signals[REPAINT_SCHEDULED] = g_signal_new ("repaint-scheduled", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - signals[SIZE_CHANGED] = g_signal_new ("size-changed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); -} - -gboolean -meta_surface_actor_is_opaque (MetaSurfaceActor *self) -{ - return META_SURFACE_ACTOR_GET_CLASS (self)->is_opaque (self); -} - -static void -meta_surface_actor_cull_out (MetaCullable *cullable, - cairo_region_t *unobscured_region, - cairo_region_t *clip_region) -{ - MetaSurfaceActor *surface_actor = META_SURFACE_ACTOR (cullable); - MetaSurfaceActorPrivate *priv = - meta_surface_actor_get_instance_private (surface_actor); - uint8_t opacity = clutter_actor_get_opacity (CLUTTER_ACTOR (cullable)); - - set_unobscured_region (surface_actor, unobscured_region); - set_clip_region (surface_actor, clip_region); - - if (opacity == 0xff) - { - cairo_region_t *opaque_region; - cairo_region_t *scaled_opaque_region; - - opaque_region = meta_shaped_texture_get_opaque_region (priv->texture); - - if (!opaque_region) - return; - - scaled_opaque_region = get_scaled_region (surface_actor, - opaque_region, - IN_STAGE_PERSPECTIVE); - - if (unobscured_region) - cairo_region_subtract (unobscured_region, scaled_opaque_region); - if (clip_region) - cairo_region_subtract (clip_region, scaled_opaque_region); - - cairo_region_destroy (scaled_opaque_region); - } -} - -static gboolean -meta_surface_actor_is_untransformed (MetaCullable *cullable) -{ - ClutterActor *actor = CLUTTER_ACTOR (cullable); - MetaWindowActor *window_actor; - float width, height; - graphene_point3d_t verts[4]; - int geometry_scale; - - clutter_actor_get_size (actor, &width, &height); - clutter_actor_get_abs_allocation_vertices (actor, verts); - - window_actor = meta_window_actor_from_actor (actor); - geometry_scale = meta_window_actor_get_geometry_scale (window_actor); - - return meta_actor_vertices_are_untransformed (verts, - width * geometry_scale, - height * geometry_scale, - NULL, NULL); -} - -static void -meta_surface_actor_reset_culling (MetaCullable *cullable) -{ - MetaSurfaceActor *surface_actor = META_SURFACE_ACTOR (cullable); - - set_clip_region (surface_actor, NULL); -} - -static void -cullable_iface_init (MetaCullableInterface *iface) -{ - iface->cull_out = meta_surface_actor_cull_out; - iface->is_untransformed = meta_surface_actor_is_untransformed; - iface->reset_culling = meta_surface_actor_reset_culling; -} - -static void -texture_size_changed (MetaShapedTexture *texture, - gpointer user_data) -{ - MetaSurfaceActor *actor = META_SURFACE_ACTOR (user_data); - g_signal_emit (actor, signals[SIZE_CHANGED], 0); -} - -static void -meta_surface_actor_init (MetaSurfaceActor *self) -{ - MetaSurfaceActorPrivate *priv = - meta_surface_actor_get_instance_private (self); - - priv->texture = meta_shaped_texture_new (); - g_signal_connect_object (priv->texture, "size-changed", - G_CALLBACK (texture_size_changed), self, 0); - clutter_actor_set_content (CLUTTER_ACTOR (self), - CLUTTER_CONTENT (priv->texture)); - clutter_actor_set_request_mode (CLUTTER_ACTOR (self), - CLUTTER_REQUEST_CONTENT_SIZE); -} - -/** - * meta_surface_actor_get_image: - * @self: A #MetaSurfaceActor - * @clip: (nullable): A clipping rectangle. The clip region is in - * the same coordinate space as the contents preferred size. - * For a shaped texture of a wl_surface, this means surface - * coordinate space. If NULL, the whole content will be used. - * - * Get the image from the texture content. The resulting size of - * the returned image may be different from the preferred size of - * the shaped texture content. - * - * Returns: (nullable) (transfer full): a new cairo surface to be freed - * with cairo_surface_destroy(). - */ -cairo_surface_t * -meta_surface_actor_get_image (MetaSurfaceActor *self, - cairo_rectangle_int_t *clip) -{ - MetaSurfaceActorPrivate *priv = - meta_surface_actor_get_instance_private (self); - - return meta_shaped_texture_get_image (priv->texture, clip); -} - -MetaShapedTexture * -meta_surface_actor_get_texture (MetaSurfaceActor *self) -{ - MetaSurfaceActorPrivate *priv = - meta_surface_actor_get_instance_private (self); - - return priv->texture; -} - -void -meta_surface_actor_update_area (MetaSurfaceActor *self, - int x, - int y, - int width, - int height) -{ - MetaSurfaceActorPrivate *priv = - meta_surface_actor_get_instance_private (self); - gboolean repaint_scheduled = FALSE; - cairo_rectangle_int_t clip; - - if (meta_shaped_texture_update_area (priv->texture, x, y, width, height, &clip)) - { - cairo_region_t *unobscured_region; - - unobscured_region = effective_unobscured_region (self); - - if (unobscured_region) - { - cairo_region_t *intersection; - - if (cairo_region_is_empty (unobscured_region)) - return; - - intersection = cairo_region_copy (unobscured_region); - cairo_region_intersect_rectangle (intersection, &clip); - - if (!cairo_region_is_empty (intersection)) - { - cairo_rectangle_int_t damage_rect; - - cairo_region_get_extents (intersection, &damage_rect); - clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (self), &damage_rect); - repaint_scheduled = TRUE; - } - - cairo_region_destroy (intersection); - } - else - { - clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (self), &clip); - repaint_scheduled = TRUE; - } - } - - if (repaint_scheduled) - g_signal_emit (self, signals[REPAINT_SCHEDULED], 0); -} - -gboolean -meta_surface_actor_is_obscured (MetaSurfaceActor *self) -{ - cairo_region_t *unobscured_region; - - unobscured_region = effective_unobscured_region (self); - - if (unobscured_region) - return cairo_region_is_empty (unobscured_region); - else - return FALSE; -} - -gboolean -meta_surface_actor_is_obscured_on_stage_view (MetaSurfaceActor *self, - ClutterStageView *stage_view, - float *unobscurred_fraction) -{ - cairo_region_t *unobscured_region; - - unobscured_region = effective_unobscured_region (self); - - if (unobscured_region) - { - MetaSurfaceActorPrivate *priv = - meta_surface_actor_get_instance_private (self); - cairo_region_t *intersection_region; - cairo_rectangle_int_t stage_rect; - float x, y; - float bounds_width, bounds_height; - float bounds_size; - int intersection_size = 0; - int n_rects, i; - - if (cairo_region_is_empty (unobscured_region)) - return TRUE; - - intersection_region = cairo_region_copy (unobscured_region); - clutter_actor_get_transformed_position (CLUTTER_ACTOR (self), &x, &y); - cairo_region_translate (intersection_region, x, y); - - clutter_stage_view_get_layout (stage_view, &stage_rect); - cairo_region_intersect_rectangle (intersection_region, - &stage_rect); - - if (cairo_region_is_empty (intersection_region)) - { - cairo_region_destroy (intersection_region); - return TRUE; - } - else if (!unobscurred_fraction) - { - cairo_region_destroy (intersection_region); - return FALSE; - } - - clutter_content_get_preferred_size (CLUTTER_CONTENT (priv->texture), - &bounds_width, - &bounds_height); - bounds_size = bounds_width * bounds_height; - - n_rects = cairo_region_num_rectangles (intersection_region); - for (i = 0; i < n_rects; i++) - { - cairo_rectangle_int_t rect; - - cairo_region_get_rectangle (intersection_region, i, &rect); - intersection_size += (rect.width - rect.x) * (rect.height - rect.x); - } - cairo_region_destroy (intersection_region); - - g_return_val_if_fail (bounds_size > 0, FALSE); - - *unobscurred_fraction = CLAMP (intersection_size / bounds_size, 0, 1); - return FALSE; - } - - return !clutter_actor_is_effectively_on_stage_view (CLUTTER_ACTOR (self), - stage_view); -} - -void -meta_surface_actor_set_input_region (MetaSurfaceActor *self, - cairo_region_t *region) -{ - MetaSurfaceActorPrivate *priv = - meta_surface_actor_get_instance_private (self); - - if (priv->input_region) - cairo_region_destroy (priv->input_region); - - if (region) - priv->input_region = cairo_region_reference (region); - else - priv->input_region = NULL; -} - -void -meta_surface_actor_set_opaque_region (MetaSurfaceActor *self, - cairo_region_t *region) -{ - MetaSurfaceActorPrivate *priv = - meta_surface_actor_get_instance_private (self); - - meta_shaped_texture_set_opaque_region (priv->texture, region); -} - -cairo_region_t * -meta_surface_actor_get_opaque_region (MetaSurfaceActor *self) -{ - MetaSurfaceActorPrivate *priv = - meta_surface_actor_get_instance_private (self); - - return meta_shaped_texture_get_opaque_region (priv->texture); -} - -void -meta_surface_actor_process_damage (MetaSurfaceActor *self, - int x, int y, int width, int height) -{ - MetaSurfaceActorPrivate *priv = - meta_surface_actor_get_instance_private (self); - - if (meta_surface_actor_is_frozen (self)) - { - /* The window is frozen due to an effect in progress: we ignore damage - * here on the off chance that this will stop the corresponding - * texture_from_pixmap from being update. - * - * pending_damage tracks any damage that happened while the window was - * frozen so that when can apply it when the window becomes unfrozen. - * - * It should be noted that this is an unreliable mechanism since it's - * quite likely that drivers will aim to provide a zero-copy - * implementation of the texture_from_pixmap extension and in those cases - * any drawing done to the window is always immediately reflected in the - * texture regardless of damage event handling. - */ - cairo_rectangle_int_t rect = { .x = x, .y = y, .width = width, .height = height }; - - if (!priv->pending_damage) - priv->pending_damage = cairo_region_create_rectangle (&rect); - else - cairo_region_union_rectangle (priv->pending_damage, &rect); - return; - } - - META_SURFACE_ACTOR_GET_CLASS (self)->process_damage (self, x, y, width, height); -} - -void -meta_surface_actor_set_frozen (MetaSurfaceActor *self, - gboolean frozen) -{ - MetaSurfaceActorPrivate *priv = - meta_surface_actor_get_instance_private (self); - - if (priv->frozen == frozen) - return; - - priv->frozen = frozen; - - if (!frozen && priv->pending_damage) - { - int i, n_rects = cairo_region_num_rectangles (priv->pending_damage); - cairo_rectangle_int_t rect; - - /* Since we ignore damage events while a window is frozen for certain effects - * we need to apply the tracked damage now. */ - - for (i = 0; i < n_rects; i++) - { - cairo_region_get_rectangle (priv->pending_damage, i, &rect); - meta_surface_actor_process_damage (self, rect.x, rect.y, - rect.width, rect.height); - } - g_clear_pointer (&priv->pending_damage, cairo_region_destroy); - } -} - -gboolean -meta_surface_actor_is_frozen (MetaSurfaceActor *self) -{ - MetaSurfaceActorPrivate *priv = - meta_surface_actor_get_instance_private (self); - - return priv->frozen; -} - -void -meta_surface_actor_set_transform (MetaSurfaceActor *self, - MetaMonitorTransform transform) -{ - MetaSurfaceActorPrivate *priv = - meta_surface_actor_get_instance_private (self); - - meta_shaped_texture_set_transform (priv->texture, transform); -} - -void -meta_surface_actor_set_viewport_src_rect (MetaSurfaceActor *self, - graphene_rect_t *src_rect) -{ - MetaSurfaceActorPrivate *priv = - meta_surface_actor_get_instance_private (self); - - meta_shaped_texture_set_viewport_src_rect (priv->texture, src_rect); -} - -void -meta_surface_actor_reset_viewport_src_rect (MetaSurfaceActor *self) -{ - MetaSurfaceActorPrivate *priv = - meta_surface_actor_get_instance_private (self); - - meta_shaped_texture_reset_viewport_src_rect (priv->texture); -} - -void -meta_surface_actor_set_viewport_dst_size (MetaSurfaceActor *self, - int dst_width, - int dst_height) -{ - MetaSurfaceActorPrivate *priv = - meta_surface_actor_get_instance_private (self); - - meta_shaped_texture_set_viewport_dst_size (priv->texture, - dst_width, - dst_height); -} - -void -meta_surface_actor_reset_viewport_dst_size (MetaSurfaceActor *self) -{ - MetaSurfaceActorPrivate *priv = - meta_surface_actor_get_instance_private (self); - - meta_shaped_texture_reset_viewport_dst_size (priv->texture); -} diff --git a/src/compositor/meta-surface-actor.h b/src/compositor/meta-surface-actor.h deleted file mode 100644 index a61251049..000000000 --- a/src/compositor/meta-surface-actor.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -#ifndef META_SURFACE_ACTOR_PRIVATE_H -#define META_SURFACE_ACTOR_PRIVATE_H - -#include "config.h" - -#include "backends/meta-backend-types.h" -#include "meta/meta-shaped-texture.h" -#include "meta/window.h" - -G_BEGIN_DECLS - -#define META_TYPE_SURFACE_ACTOR (meta_surface_actor_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaSurfaceActor, - meta_surface_actor, - META, SURFACE_ACTOR, - ClutterActor) - -struct _MetaSurfaceActorClass -{ - /*< private >*/ - ClutterActorClass parent_class; - - void (* process_damage) (MetaSurfaceActor *actor, - int x, int y, int width, int height); - gboolean (* is_opaque) (MetaSurfaceActor *actor); -}; - -cairo_surface_t *meta_surface_actor_get_image (MetaSurfaceActor *self, - cairo_rectangle_int_t *clip); - -MetaShapedTexture *meta_surface_actor_get_texture (MetaSurfaceActor *self); - -void meta_surface_actor_update_area (MetaSurfaceActor *self, - int x, - int y, - int width, - int height); - -gboolean meta_surface_actor_is_obscured (MetaSurfaceActor *self); -gboolean meta_surface_actor_is_obscured_on_stage_view (MetaSurfaceActor *self, - ClutterStageView *stage_view, - float *unobscurred_fraction); - -void meta_surface_actor_set_input_region (MetaSurfaceActor *self, - cairo_region_t *region); -void meta_surface_actor_set_opaque_region (MetaSurfaceActor *self, - cairo_region_t *region); -cairo_region_t * meta_surface_actor_get_opaque_region (MetaSurfaceActor *self); - -void meta_surface_actor_process_damage (MetaSurfaceActor *actor, - int x, int y, int width, int height); - -gboolean meta_surface_actor_is_opaque (MetaSurfaceActor *actor); - -gboolean meta_surface_actor_is_frozen (MetaSurfaceActor *actor); -void meta_surface_actor_set_frozen (MetaSurfaceActor *actor, - gboolean frozen); - -void meta_surface_actor_set_transform (MetaSurfaceActor *self, - MetaMonitorTransform transform); -void meta_surface_actor_set_viewport_src_rect (MetaSurfaceActor *self, - graphene_rect_t *src_rect); -void meta_surface_actor_reset_viewport_src_rect (MetaSurfaceActor *self); -void meta_surface_actor_set_viewport_dst_size (MetaSurfaceActor *self, - int dst_width, - int dst_height); -void meta_surface_actor_reset_viewport_dst_size (MetaSurfaceActor *self); -G_END_DECLS - -#endif /* META_SURFACE_ACTOR_PRIVATE_H */ diff --git a/src/compositor/meta-sync-ring.c b/src/compositor/meta-sync-ring.c deleted file mode 100644 index 917bf1235..000000000 --- a/src/compositor/meta-sync-ring.c +++ /dev/null @@ -1,592 +0,0 @@ -/* - * This is based on an original C++ implementation for compiz that - * carries the following copyright notice: - * - * - * Copyright © 2011 NVIDIA Corporation - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of NVIDIA - * Corporation not be used in advertising or publicity pertaining to - * distribution of the software without specific, written prior - * permission. NVIDIA Corporation makes no representations about the - * suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * NVIDIA CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - * - * Authors: James Jones - */ - -#include "config.h" - -#include "compositor/meta-sync-ring.h" - -#include -#include -#include -#include - -#include "clutter/clutter.h" -#include "cogl/cogl.h" -#include "meta/util.h" - -/* Theory of operation: - * - * We use a ring of NUM_SYNCS fence objects. On each frame we advance - * to the next fence in the ring. For each fence we do: - * - * 1. fence is XSyncTriggerFence()'d and glWaitSync()'d - * 2. NUM_SYNCS / 2 frames later, fence should be triggered - * 3. fence is XSyncResetFence()'d - * 4. NUM_SYNCS / 2 frames later, fence should be reset - * 5. go back to 1 and re-use fence - * - * glClientWaitSync() and XAlarms are used in steps 2 and 4, - * respectively, to double-check the expectections. - */ - -#define NUM_SYNCS 10 -#define MAX_SYNC_WAIT_TIME (1 * 1000 * 1000 * 1000) /* one sec */ -#define MAX_REBOOT_ATTEMPTS 2 - -typedef enum -{ - META_SYNC_STATE_READY, - META_SYNC_STATE_WAITING, - META_SYNC_STATE_DONE, - META_SYNC_STATE_RESET_PENDING, -} MetaSyncState; - -typedef struct -{ - Display *xdisplay; - - XSyncFence xfence; - GLsync gl_x11_sync; - GLsync gpu_fence; - - XSyncCounter xcounter; - XSyncAlarm xalarm; - XSyncValue next_counter_value; - - MetaSyncState state; -} MetaSync; - -typedef struct -{ - Display *xdisplay; - int xsync_event_base; - int xsync_error_base; - - GHashTable *alarm_to_sync; - - MetaSync *syncs_array[NUM_SYNCS]; - guint current_sync_idx; - MetaSync *current_sync; - guint warmup_syncs; - - guint reboots; -} MetaSyncRing; - -static MetaSyncRing meta_sync_ring = { 0 }; - -static XSyncValue SYNC_VALUE_ZERO; -static XSyncValue SYNC_VALUE_ONE; - -static const char* (*meta_gl_get_string) (GLenum name); -static void (*meta_gl_get_integerv) (GLenum pname, - GLint *params); -static const char* (*meta_gl_get_stringi) (GLenum name, - GLuint index); -static void (*meta_gl_delete_sync) (GLsync sync); -static GLenum (*meta_gl_client_wait_sync) (GLsync sync, - GLbitfield flags, - GLuint64 timeout); -static void (*meta_gl_wait_sync) (GLsync sync, - GLbitfield flags, - GLuint64 timeout); -static GLsync (*meta_gl_import_sync) (GLenum external_sync_type, - GLintptr external_sync, - GLbitfield flags); -static GLsync (*meta_gl_fence_sync) (GLenum condition, - GLbitfield flags); - -static MetaSyncRing * -meta_sync_ring_get (void) -{ - if (meta_sync_ring.reboots > MAX_REBOOT_ATTEMPTS) - return NULL; - - return &meta_sync_ring; -} - -static gboolean -load_gl_symbol (const char *name, - void **func) -{ - *func = cogl_get_proc_address (name); - if (!*func) - { - meta_verbose ("MetaSyncRing: failed to resolve required GL symbol \"%s\"", name); - return FALSE; - } - return TRUE; -} - -static gboolean -check_gl_extensions (void) -{ - ClutterBackend *backend; - CoglContext *cogl_context; - CoglDisplay *cogl_display; - CoglRenderer *cogl_renderer; - - backend = clutter_get_default_backend (); - cogl_context = clutter_backend_get_cogl_context (backend); - cogl_display = cogl_context_get_display (cogl_context); - cogl_renderer = cogl_display_get_renderer (cogl_display); - - switch (cogl_renderer_get_driver (cogl_renderer)) - { - case COGL_DRIVER_GL3: - { - int num_extensions, i; - gboolean arb_sync = FALSE; - gboolean x11_sync_object = FALSE; - - meta_gl_get_integerv (GL_NUM_EXTENSIONS, &num_extensions); - - for (i = 0; i < num_extensions; ++i) - { - const char *ext = meta_gl_get_stringi (GL_EXTENSIONS, i); - - if (g_strcmp0 ("GL_ARB_sync", ext) == 0) - arb_sync = TRUE; - else if (g_strcmp0 ("GL_EXT_x11_sync_object", ext) == 0) - x11_sync_object = TRUE; - } - - return arb_sync && x11_sync_object; - } - case COGL_DRIVER_GL: - { - const char *extensions = meta_gl_get_string (GL_EXTENSIONS); - return (extensions != NULL && - strstr (extensions, "GL_ARB_sync") != NULL && - strstr (extensions, "GL_EXT_x11_sync_object") != NULL); - } - default: - break; - } - - return FALSE; -} - -static gboolean -load_required_symbols (void) -{ - static gboolean success = FALSE; - - if (success) - return TRUE; - - /* We don't link against libGL directly because cogl may want to - * use something else. This assumes that cogl has been initialized - * and dynamically loaded libGL at this point. - */ - - if (!load_gl_symbol ("glGetString", (void **) &meta_gl_get_string)) - goto out; - if (!load_gl_symbol ("glGetIntegerv", (void **) &meta_gl_get_integerv)) - goto out; - if (!load_gl_symbol ("glGetStringi", (void **) &meta_gl_get_stringi)) - goto out; - - if (!check_gl_extensions ()) - { - meta_verbose ("MetaSyncRing: couldn't find required GL extensions"); - goto out; - } - - if (!load_gl_symbol ("glDeleteSync", (void **) &meta_gl_delete_sync)) - goto out; - if (!load_gl_symbol ("glClientWaitSync", (void **) &meta_gl_client_wait_sync)) - goto out; - if (!load_gl_symbol ("glWaitSync", (void **) &meta_gl_wait_sync)) - goto out; - if (!load_gl_symbol ("glImportSyncEXT", (void **) &meta_gl_import_sync)) - goto out; - if (!load_gl_symbol ("glFenceSync", (void **) &meta_gl_fence_sync)) - goto out; - - success = TRUE; - out: - return success; -} - -static void -meta_sync_insert (MetaSync *self) -{ - g_return_if_fail (self->state == META_SYNC_STATE_READY); - - XSyncTriggerFence (self->xdisplay, self->xfence); - XFlush (self->xdisplay); - - meta_gl_wait_sync (self->gl_x11_sync, 0, GL_TIMEOUT_IGNORED); - self->gpu_fence = meta_gl_fence_sync (GL_SYNC_GPU_COMMANDS_COMPLETE, 0); - - self->state = META_SYNC_STATE_WAITING; -} - -static GLenum -meta_sync_check_update_finished (MetaSync *self, - GLuint64 timeout) -{ - GLenum status = GL_WAIT_FAILED; - - switch (self->state) - { - case META_SYNC_STATE_DONE: - status = GL_ALREADY_SIGNALED; - break; - case META_SYNC_STATE_WAITING: - status = meta_gl_client_wait_sync (self->gpu_fence, 0, timeout); - if (status == GL_ALREADY_SIGNALED || status == GL_CONDITION_SATISFIED) - { - self->state = META_SYNC_STATE_DONE; - meta_gl_delete_sync (self->gpu_fence); - self->gpu_fence = 0; - } - break; - default: - break; - } - - g_warn_if_fail (status != GL_WAIT_FAILED); - - return status; -} - -static void -meta_sync_reset (MetaSync *self) -{ - XSyncAlarmAttributes attrs; - int overflow; - - g_return_if_fail (self->state == META_SYNC_STATE_DONE); - - XSyncResetFence (self->xdisplay, self->xfence); - - attrs.trigger.wait_value = self->next_counter_value; - - XSyncChangeAlarm (self->xdisplay, self->xalarm, XSyncCAValue, &attrs); - XSyncSetCounter (self->xdisplay, self->xcounter, self->next_counter_value); - - XSyncValueAdd (&self->next_counter_value, - self->next_counter_value, - SYNC_VALUE_ONE, - &overflow); - - self->state = META_SYNC_STATE_RESET_PENDING; -} - -static void -meta_sync_handle_event (MetaSync *self, - XSyncAlarmNotifyEvent *event) -{ - g_return_if_fail (event->alarm == self->xalarm); - g_return_if_fail (self->state == META_SYNC_STATE_RESET_PENDING); - - self->state = META_SYNC_STATE_READY; -} - -static MetaSync * -meta_sync_new (Display *xdisplay) -{ - MetaSync *self; - XSyncAlarmAttributes attrs; - - self = g_malloc0 (sizeof (MetaSync)); - - self->xdisplay = xdisplay; - - self->xfence = XSyncCreateFence (xdisplay, DefaultRootWindow (xdisplay), FALSE); - self->gl_x11_sync = 0; - self->gpu_fence = 0; - - self->xcounter = XSyncCreateCounter (xdisplay, SYNC_VALUE_ZERO); - - attrs.trigger.counter = self->xcounter; - attrs.trigger.value_type = XSyncAbsolute; - attrs.trigger.wait_value = SYNC_VALUE_ONE; - attrs.trigger.test_type = XSyncPositiveTransition; - attrs.events = TRUE; - self->xalarm = XSyncCreateAlarm (xdisplay, - XSyncCACounter | - XSyncCAValueType | - XSyncCAValue | - XSyncCATestType | - XSyncCAEvents, - &attrs); - - XSyncIntToValue (&self->next_counter_value, 1); - - self->state = META_SYNC_STATE_READY; - - return self; -} - -static void -meta_sync_import (MetaSync *self) -{ - g_return_if_fail (self->gl_x11_sync == 0); - self->gl_x11_sync = meta_gl_import_sync (GL_SYNC_X11_FENCE_EXT, self->xfence, 0); -} - -static Bool -alarm_event_predicate (Display *dpy, - XEvent *event, - XPointer data) -{ - MetaSyncRing *ring = meta_sync_ring_get (); - - if (!ring) - return False; - - if (event->type == ring->xsync_event_base + XSyncAlarmNotify) - { - if (((MetaSync *) data)->xalarm == ((XSyncAlarmNotifyEvent *) event)->alarm) - return True; - } - return False; -} - -static void -meta_sync_free (MetaSync *self) -{ - /* When our assumptions don't hold, something has gone wrong but we - * don't know what, so we reboot the ring. While doing that, we - * trigger fences before deleting them to try to get ourselves out - * of a potentially stuck GPU state. - */ - switch (self->state) - { - case META_SYNC_STATE_WAITING: - meta_gl_delete_sync (self->gpu_fence); - break; - case META_SYNC_STATE_DONE: - /* nothing to do */ - break; - case META_SYNC_STATE_RESET_PENDING: - { - XEvent event; - XIfEvent (self->xdisplay, &event, alarm_event_predicate, (XPointer) self); - meta_sync_handle_event (self, (XSyncAlarmNotifyEvent *) &event); - } - G_GNUC_FALLTHROUGH; - case META_SYNC_STATE_READY: - XSyncTriggerFence (self->xdisplay, self->xfence); - XFlush (self->xdisplay); - break; - default: - break; - } - - meta_gl_delete_sync (self->gl_x11_sync); - XSyncDestroyFence (self->xdisplay, self->xfence); - XSyncDestroyCounter (self->xdisplay, self->xcounter); - XSyncDestroyAlarm (self->xdisplay, self->xalarm); - - g_free (self); -} - -gboolean -meta_sync_ring_init (Display *xdisplay) -{ - gint major, minor; - guint i; - MetaSyncRing *ring = meta_sync_ring_get (); - - if (!ring) - return FALSE; - - g_return_val_if_fail (xdisplay != NULL, FALSE); - g_return_val_if_fail (ring->xdisplay == NULL, FALSE); - - if (!load_required_symbols ()) - return FALSE; - - if (!XSyncQueryExtension (xdisplay, &ring->xsync_event_base, &ring->xsync_error_base) || - !XSyncInitialize (xdisplay, &major, &minor)) - return FALSE; - - XSyncIntToValue (&SYNC_VALUE_ZERO, 0); - XSyncIntToValue (&SYNC_VALUE_ONE, 1); - - ring->xdisplay = xdisplay; - - ring->alarm_to_sync = g_hash_table_new (NULL, NULL); - - for (i = 0; i < NUM_SYNCS; ++i) - { - MetaSync *sync = meta_sync_new (ring->xdisplay); - ring->syncs_array[i] = sync; - g_hash_table_replace (ring->alarm_to_sync, (gpointer) sync->xalarm, sync); - } - /* Since the connection we create the X fences on isn't the same as - * the one used for the GLX context, we need to XSync() here to - * ensure glImportSync() succeeds. */ - XSync (xdisplay, False); - for (i = 0; i < NUM_SYNCS; ++i) - meta_sync_import (ring->syncs_array[i]); - - ring->current_sync_idx = 0; - ring->current_sync = ring->syncs_array[0]; - ring->warmup_syncs = 0; - - return TRUE; -} - -void -meta_sync_ring_destroy (void) -{ - guint i; - MetaSyncRing *ring = meta_sync_ring_get (); - - if (!ring) - return; - - g_return_if_fail (ring->xdisplay != NULL); - - ring->current_sync_idx = 0; - ring->current_sync = NULL; - ring->warmup_syncs = 0; - - for (i = 0; i < NUM_SYNCS; ++i) - meta_sync_free (ring->syncs_array[i]); - - g_hash_table_destroy (ring->alarm_to_sync); - - ring->xsync_event_base = 0; - ring->xsync_error_base = 0; - ring->xdisplay = NULL; -} - -static gboolean -meta_sync_ring_reboot (Display *xdisplay) -{ - MetaSyncRing *ring = meta_sync_ring_get (); - - if (!ring) - return FALSE; - - meta_sync_ring_destroy (); - - ring->reboots += 1; - - if (!meta_sync_ring_get ()) - { - meta_warning ("MetaSyncRing: Too many reboots -- disabling"); - return FALSE; - } - - return meta_sync_ring_init (xdisplay); -} - -gboolean -meta_sync_ring_after_frame (void) -{ - MetaSyncRing *ring = meta_sync_ring_get (); - - if (!ring) - return FALSE; - - g_return_val_if_fail (ring->xdisplay != NULL, FALSE); - - if (ring->warmup_syncs >= NUM_SYNCS / 2) - { - guint reset_sync_idx = (ring->current_sync_idx + NUM_SYNCS - (NUM_SYNCS / 2)) % NUM_SYNCS; - MetaSync *sync_to_reset = ring->syncs_array[reset_sync_idx]; - - GLenum status = meta_sync_check_update_finished (sync_to_reset, 0); - if (status == GL_TIMEOUT_EXPIRED) - { - meta_warning ("MetaSyncRing: We should never wait for a sync -- add more syncs?"); - status = meta_sync_check_update_finished (sync_to_reset, MAX_SYNC_WAIT_TIME); - } - - if (status != GL_ALREADY_SIGNALED && status != GL_CONDITION_SATISFIED) - { - meta_warning ("MetaSyncRing: Timed out waiting for sync object."); - return meta_sync_ring_reboot (ring->xdisplay); - } - - meta_sync_reset (sync_to_reset); - } - else - { - ring->warmup_syncs += 1; - } - - ring->current_sync_idx += 1; - ring->current_sync_idx %= NUM_SYNCS; - - ring->current_sync = ring->syncs_array[ring->current_sync_idx]; - - return TRUE; -} - -gboolean -meta_sync_ring_insert_wait (void) -{ - MetaSyncRing *ring = meta_sync_ring_get (); - - if (!ring) - return FALSE; - - g_return_val_if_fail (ring->xdisplay != NULL, FALSE); - - if (ring->current_sync->state != META_SYNC_STATE_READY) - { - meta_warning ("MetaSyncRing: Sync object is not ready -- were events handled properly?"); - if (!meta_sync_ring_reboot (ring->xdisplay)) - return FALSE; - } - - meta_sync_insert (ring->current_sync); - - return TRUE; -} - -void -meta_sync_ring_handle_event (XEvent *xevent) -{ - XSyncAlarmNotifyEvent *event; - MetaSync *sync; - MetaSyncRing *ring = meta_sync_ring_get (); - - if (!ring) - return; - - g_return_if_fail (ring->xdisplay != NULL); - - if (xevent->type != (ring->xsync_event_base + XSyncAlarmNotify)) - return; - - event = (XSyncAlarmNotifyEvent *) xevent; - - sync = g_hash_table_lookup (ring->alarm_to_sync, (gpointer) event->alarm); - if (sync) - meta_sync_handle_event (sync, event); -} diff --git a/src/compositor/meta-sync-ring.h b/src/compositor/meta-sync-ring.h deleted file mode 100644 index d9739455b..000000000 --- a/src/compositor/meta-sync-ring.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef _META_SYNC_RING_H_ -#define _META_SYNC_RING_H_ - -#include -#include - -gboolean meta_sync_ring_init (Display *dpy); -void meta_sync_ring_destroy (void); -gboolean meta_sync_ring_after_frame (void); -gboolean meta_sync_ring_insert_wait (void); -void meta_sync_ring_handle_event (XEvent *event); - -#endif /* _META_SYNC_RING_H_ */ diff --git a/src/compositor/meta-texture-tower.c b/src/compositor/meta-texture-tower.c deleted file mode 100644 index 1fc4623e5..000000000 --- a/src/compositor/meta-texture-tower.c +++ /dev/null @@ -1,484 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * MetaTextureTower - * - * Mipmap emulation by creation of scaled down images - * - * Copyright (C) 2009 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 . - */ - -#include "config.h" - -#include -#include - -#include "compositor/meta-texture-tower.h" - -#ifndef M_LOG2E -#define M_LOG2E 1.4426950408889634074 -#endif - -#define MAX_TEXTURE_LEVELS 12 - -/* If the texture format in memory doesn't match this, then Mesa - * will do the conversion, so things will still work, but it might - * be slow depending on how efficient Mesa is. These should be the - * native formats unless the display is 16bpp. If conversions - * here are a bottleneck, investigate whether we are converting when - * storing window data *into* the texture before adding extra code - * to handle multiple texture formats. - */ -#if G_BYTE_ORDER == G_LITTLE_ENDIAN -#define TEXTURE_FORMAT COGL_PIXEL_FORMAT_BGRA_8888_PRE -#else -#define TEXTURE_FORMAT COGL_PIXEL_FORMAT_ARGB_8888_PRE -#endif - -typedef struct -{ - guint16 x1; - guint16 y1; - guint16 x2; - guint16 y2; -} Box; - -struct _MetaTextureTower -{ - int n_levels; - CoglTexture *textures[MAX_TEXTURE_LEVELS]; - CoglOffscreen *fbos[MAX_TEXTURE_LEVELS]; - Box invalid[MAX_TEXTURE_LEVELS]; - CoglPipeline *pipeline_template; -}; - -/** - * meta_texture_tower_new: - * - * Creates a new texture tower. The base texture has to be set with - * meta_texture_tower_set_base_texture() before use. - * - * Return value: the new texture tower. Free with meta_texture_tower_free() - */ -MetaTextureTower * -meta_texture_tower_new (void) -{ - MetaTextureTower *tower; - - tower = g_new0 (MetaTextureTower, 1); - - return tower; -} - -/** - * meta_texture_tower_free: - * @tower: a #MetaTextureTower - * - * Frees a texture tower created with meta_texture_tower_new(). - */ -void -meta_texture_tower_free (MetaTextureTower *tower) -{ - g_return_if_fail (tower != NULL); - - if (tower->pipeline_template != NULL) - cogl_object_unref (tower->pipeline_template); - - meta_texture_tower_set_base_texture (tower, NULL); - - g_free (tower); -} - -/** - * meta_texture_tower_set_base_texture: - * @tower: a #MetaTextureTower - * @texture: the new texture used as a base for scaled down versions - * - * Sets the base texture that is the scaled texture that the - * scaled textures of the tower are derived from. The texture itself - * will be used as level 0 of the tower and will be referenced until - * unset or until the tower is freed. - */ -void -meta_texture_tower_set_base_texture (MetaTextureTower *tower, - CoglTexture *texture) -{ - int i; - - g_return_if_fail (tower != NULL); - - if (texture == tower->textures[0]) - return; - - if (tower->textures[0] != NULL) - { - for (i = 1; i < tower->n_levels; i++) - { - cogl_clear_object (&tower->textures[i]); - g_clear_object (&tower->fbos[i]); - } - - cogl_object_unref (tower->textures[0]); - } - - tower->textures[0] = texture; - - if (tower->textures[0] != NULL) - { - int width, height; - - cogl_object_ref (tower->textures[0]); - - width = cogl_texture_get_width (tower->textures[0]); - height = cogl_texture_get_height (tower->textures[0]); - - tower->n_levels = 1 + MAX ((int)(M_LOG2E * log (width)), (int)(M_LOG2E * log (height))); - tower->n_levels = MIN(tower->n_levels, MAX_TEXTURE_LEVELS); - - meta_texture_tower_update_area (tower, 0, 0, width, height); - } - else - { - tower->n_levels = 0; - } -} - -/** - * meta_texture_tower_update_area: - * @tower: a #MetaTextureTower - * @x: X coordinate of upper left of rectangle that changed - * @y: Y coordinate of upper left of rectangle that changed - * @width: width of rectangle that changed - * @height: height rectangle that changed - * - * Mark a region of the base texture as having changed; the next - * time a scaled down version of the base texture is retrieved, - * the appropriate area of the scaled down texture will be updated. - */ -void -meta_texture_tower_update_area (MetaTextureTower *tower, - int x, - int y, - int width, - int height) -{ - int texture_width, texture_height; - Box invalid; - int i; - - g_return_if_fail (tower != NULL); - - if (tower->textures[0] == NULL) - return; - - texture_width = cogl_texture_get_width (tower->textures[0]); - texture_height = cogl_texture_get_height (tower->textures[0]); - - invalid.x1 = x; - invalid.y1 = y; - invalid.x2 = x + width; - invalid.y2 = y + height; - - for (i = 1; i < tower->n_levels; i++) - { - texture_width = MAX (1, texture_width / 2); - texture_height = MAX (1, texture_height / 2); - - invalid.x1 = invalid.x1 / 2; - invalid.y1 = invalid.y1 / 2; - invalid.x2 = MIN (texture_width, (invalid.x2 + 1) / 2); - invalid.y2 = MIN (texture_height, (invalid.y2 + 1) / 2); - - if (tower->invalid[i].x1 == tower->invalid[i].x2 || - tower->invalid[i].y1 == tower->invalid[i].y2) - { - tower->invalid[i] = invalid; - } - else - { - tower->invalid[i].x1 = MIN (tower->invalid[i].x1, invalid.x1); - tower->invalid[i].y1 = MIN (tower->invalid[i].y1, invalid.y1); - tower->invalid[i].x2 = MAX (tower->invalid[i].x2, invalid.x2); - tower->invalid[i].y2 = MAX (tower->invalid[i].y2, invalid.y2); - } - } -} - -/* It generally looks worse if we scale up a window texture by even a - * small amount than if we scale it down using bilinear filtering, so - * we always pick the *larger* adjacent level. */ -#define LOD_BIAS (-0.49) - -/* This determines the appropriate level of detail to use when drawing the - * texture, in a way that corresponds to what the GL specification does - * when mip-mapping. This is probably fancier and slower than what we need, - * but we do the computation only once each time we paint a window, and - * its easier to just use the equations from the specification than to - * come up with something simpler. - * - * If window is being painted at an angle from the viewer, then we have to - * pick a point in the texture; we use the middle of the texture (which is - * why the width/height are passed in.) This is not the normal case for - * Meta. - */ -static int -get_paint_level (ClutterPaintContext *paint_context, - int width, - int height) -{ - CoglFramebuffer *framebuffer; - graphene_matrix_t projection, modelview, pm; - float xx, xy, xw; - float yx, yy, yw; - float wx, wy, ww; - float v[4]; - double viewport_width, viewport_height; - double u0, v0; - double xc, yc, wc; - double dxdu_, dxdv_, dydu_, dydv_; - double det_, det_sq; - double rho_sq; - double lambda; - - /* See - * http://www.opengl.org/registry/doc/glspec32.core.20090803.pdf - * Section 3.8.9, p. 1.6.2. Here we have - * - * u(x,y) = x_o; - * v(x,y) = y_o; - * - * Since we are mapping 1:1 from object coordinates into pixel - * texture coordinates, the clip coordinates are: - * - * (x_c) (x_o) (u) - * (y_c) = (M_projection)(M_modelview) (y_o) = (PM) (v) - * (z_c) (z_o) (0) - * (w_c) (w_o) (1) - */ - - framebuffer = clutter_paint_context_get_framebuffer (paint_context); - cogl_framebuffer_get_projection_matrix (framebuffer, &projection); - cogl_framebuffer_get_modelview_matrix (framebuffer, &modelview); - - graphene_matrix_multiply (&modelview, &projection, &pm); - - xx = graphene_matrix_get_value (&pm, 0, 0); - xy = graphene_matrix_get_value (&pm, 0, 1); - xw = graphene_matrix_get_value (&pm, 0, 3); - yx = graphene_matrix_get_value (&pm, 1, 0); - yy = graphene_matrix_get_value (&pm, 1, 1); - yw = graphene_matrix_get_value (&pm, 1, 3); - wx = graphene_matrix_get_value (&pm, 3, 0); - wy = graphene_matrix_get_value (&pm, 3, 1); - ww = graphene_matrix_get_value (&pm, 3, 3); - - cogl_framebuffer_get_viewport4fv (framebuffer, v); - viewport_width = v[2]; - viewport_height = v[3]; - - u0 = width / 2.; - v0 = height / 2.; - - xc = xx * u0 + yx * v0 + wx; - yc = xy * u0 + yy * v0 + wy; - wc = xw * u0 + yw * v0 + ww; - - /* We'll simplify the equations below for a bit of micro-optimization. - * The commented out code is the unsimplified version. - - // Partial derivates of window coordinates: - // - // x_w = 0.5 * viewport_width * x_c / w_c + viewport_center_x - // y_w = 0.5 * viewport_height * y_c / w_c + viewport_center_y - // - // with respect to u, v, using - // d(a/b)/dx = da/dx * (1/b) - a * db/dx / (b^2) - - dxdu = 0.5 * viewport_width * (xx - xw * (xc/wc)) / wc; - dxdv = 0.5 * viewport_width * (yx - yw * (xc/wc)) / wc; - dydu = 0.5 * viewport_height * (xy - xw * (yc/wc)) / wc; - dydv = 0.5 * viewport_height * (yy - yw * (yc/wc)) / wc; - - // Compute the inverse partials as the matrix inverse - det = dxdu * dydv - dxdv * dydu; - - dudx = dydv / det; - dudy = - dxdv / det; - dvdx = - dydu / det; - dvdy = dvdu / det; - - // Scale factor; maximum of the distance in texels for a change of 1 pixel - // in the X direction or 1 pixel in the Y direction - rho = MAX (sqrt (dudx * dudx + dvdx * dvdx), sqrt(dudy * dudy + dvdy * dvdy)); - - // Level of detail - lambda = log2 (rho) + LOD_BIAS; - */ - - /* dxdu * wc, etc */ - dxdu_ = 0.5 * viewport_width * (xx - xw * (xc/wc)); - dxdv_ = 0.5 * viewport_width * (yx - yw * (xc/wc)); - dydu_ = 0.5 * viewport_height * (xy - xw * (yc/wc)); - dydv_ = 0.5 * viewport_height * (yy - yw * (yc/wc)); - - /* det * wc^2 */ - det_ = dxdu_ * dydv_ - dxdv_ * dydu_; - det_sq = det_ * det_; - if (det_sq == 0.0) - return -1; - - /* (rho * det * wc)^2 */ - rho_sq = MAX (dydv_ * dydv_ + dydu_ * dydu_, dxdv_ * dxdv_ + dxdu_ * dxdu_); - lambda = 0.5 * M_LOG2E * log (rho_sq * wc * wc / det_sq) + LOD_BIAS; - -#if 0 - g_print ("%g %g %g\n", 0.5 * viewport_width * xx / ww, 0.5 * viewport_height * yy / ww, lambda); -#endif - - if (lambda <= 0.) - return 0; - else - return (int)(0.5 + lambda); -} - -static void -texture_tower_create_texture (MetaTextureTower *tower, - int level, - int width, - int height) -{ - tower->textures[level] = cogl_texture_new_with_size (width, height, - COGL_TEXTURE_NO_AUTO_MIPMAP, - TEXTURE_FORMAT); - - tower->invalid[level].x1 = 0; - tower->invalid[level].y1 = 0; - tower->invalid[level].x2 = width; - tower->invalid[level].y2 = height; -} - -static void -texture_tower_revalidate (MetaTextureTower *tower, - int level) -{ - CoglTexture *source_texture = tower->textures[level - 1]; - int source_texture_width = cogl_texture_get_width (source_texture); - int source_texture_height = cogl_texture_get_height (source_texture); - CoglTexture *dest_texture = tower->textures[level]; - int dest_texture_width = cogl_texture_get_width (dest_texture); - int dest_texture_height = cogl_texture_get_height (dest_texture); - Box *invalid = &tower->invalid[level]; - CoglFramebuffer *fb; - GError *catch_error = NULL; - CoglPipeline *pipeline; - - if (tower->fbos[level] == NULL) - tower->fbos[level] = cogl_offscreen_new_with_texture (dest_texture); - - fb = COGL_FRAMEBUFFER (tower->fbos[level]); - - if (!cogl_framebuffer_allocate (fb, &catch_error)) - { - g_error_free (catch_error); - return; - } - - cogl_framebuffer_orthographic (fb, 0, 0, dest_texture_width, dest_texture_height, -1., 1.); - - if (!tower->pipeline_template) - { - CoglContext *ctx = - clutter_backend_get_cogl_context (clutter_get_default_backend ()); - tower->pipeline_template = cogl_pipeline_new (ctx); - cogl_pipeline_set_blend (tower->pipeline_template, "RGBA = ADD (SRC_COLOR, 0)", NULL); - } - - pipeline = cogl_pipeline_copy (tower->pipeline_template); - cogl_pipeline_set_layer_texture (pipeline, 0, tower->textures[level - 1]); - - cogl_framebuffer_draw_textured_rectangle (fb, pipeline, - invalid->x1, invalid->y1, - invalid->x2, invalid->y2, - (2. * invalid->x1) / source_texture_width, - (2. * invalid->y1) / source_texture_height, - (2. * invalid->x2) / source_texture_width, - (2. * invalid->y2) / source_texture_height); - - cogl_object_unref (pipeline); - - tower->invalid[level].x1 = tower->invalid[level].x2 = 0; - tower->invalid[level].y1 = tower->invalid[level].y2 = 0; -} - -/** - * meta_texture_tower_get_paint_texture: - * @tower: a #MetaTextureTower - * @paint_context: a #ClutterPaintContext - * - * Gets the texture from the tower that best matches the current - * rendering scale. (On the assumption here the texture is going to - * be rendered with vertex coordinates that correspond to its - * size in pixels, so a 200x200 texture will be rendered on the - * rectangle (0, 0, 200, 200). - * - * Return value: the COGL texture handle to use for painting, or - * %NULL if no base texture has yet been set. - */ -CoglTexture * -meta_texture_tower_get_paint_texture (MetaTextureTower *tower, - ClutterPaintContext *paint_context) -{ - int texture_width, texture_height; - int level; - - g_return_val_if_fail (tower != NULL, NULL); - - if (tower->textures[0] == NULL) - return NULL; - - texture_width = cogl_texture_get_width (tower->textures[0]); - texture_height = cogl_texture_get_height (tower->textures[0]); - - level = get_paint_level (paint_context, texture_width, texture_height); - if (level < 0) /* singular paint matrix, scaled to nothing */ - return NULL; - level = MIN (level, tower->n_levels - 1); - - if (tower->textures[level] == NULL || - (tower->invalid[level].x2 != tower->invalid[level].x1 && - tower->invalid[level].y2 != tower->invalid[level].y1)) - { - int i; - - for (i = 1; i <= level; i++) - { - /* Use "floor" convention here to be consistent with the NPOT texture extension */ - texture_width = MAX (1, texture_width / 2); - texture_height = MAX (1, texture_height / 2); - - if (tower->textures[i] == NULL) - texture_tower_create_texture (tower, i, texture_width, texture_height); - } - - for (i = 1; i <= level; i++) - { - if (tower->invalid[level].x2 != tower->invalid[level].x1 && - tower->invalid[level].y2 != tower->invalid[level].y1) - texture_tower_revalidate (tower, i); - } - } - - return tower->textures[level]; -} diff --git a/src/compositor/meta-texture-tower.h b/src/compositor/meta-texture-tower.h deleted file mode 100644 index 1f5b37146..000000000 --- a/src/compositor/meta-texture-tower.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * MetaTextureTower - * - * Mipmap emulation by creation of scaled down images - * - * Copyright (C) 2009 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 . - */ - -#ifndef __META_TEXTURE_TOWER_H__ -#define __META_TEXTURE_TOWER_H__ - -#include "clutter/clutter.h" - -G_BEGIN_DECLS - -/** - * SECTION:MetaTextureTower - * @short_description: mipmap emulation by creation of scaled down images - * - * A #MetaTextureTower is used to get good looking scaled down images when - * we can't use the GL drivers mipmap support. There are two separate reasons - * - * - Some cards (including radeon cards <= r5xx) only support - * TEXTURE_RECTANGLE_ARB and not NPOT textures. Rectangular textures - * are defined not to support mipmapping. - * - Even when NPOT textures are available, the combination of NPOT - * textures, texture_from_pixmap, and mipmapping doesn't typically - * work, since the X server doesn't allocate pixmaps in the right - * layout for mipmapping. - * - * So, what we do is create the "mipmap" levels ourselves by successive - * power-of-two scaledowns, and when rendering pick the single texture - * that best matches the scale we are rendering at. (Since we aren't - * typically using perspective transforms, we'll frequently have a single - * scale for the entire texture.) - */ - -typedef struct _MetaTextureTower MetaTextureTower; - -MetaTextureTower *meta_texture_tower_new (void); -void meta_texture_tower_free (MetaTextureTower *tower); -void meta_texture_tower_set_base_texture (MetaTextureTower *tower, - CoglTexture *texture); -void meta_texture_tower_update_area (MetaTextureTower *tower, - int x, - int y, - int width, - int height); -CoglTexture *meta_texture_tower_get_paint_texture (MetaTextureTower *tower, - ClutterPaintContext *paint_context); - -G_END_DECLS - -#endif /* __META_TEXTURE_TOWER_H__ */ diff --git a/src/compositor/meta-window-actor-private.h b/src/compositor/meta-window-actor-private.h deleted file mode 100644 index 64741e416..000000000 --- a/src/compositor/meta-window-actor-private.h +++ /dev/null @@ -1,102 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -#ifndef META_WINDOW_ACTOR_PRIVATE_H -#define META_WINDOW_ACTOR_PRIVATE_H - -#include - -#include "compositor/meta-plugin-manager.h" -#include "compositor/meta-surface-actor.h" -#include "meta/compositor-mutter.h" - -struct _MetaWindowActorClass -{ - ClutterActorClass parent; - - void (*frame_complete) (MetaWindowActor *actor, - ClutterFrameInfo *frame_info, - int64_t presentation_time); - - void (*assign_surface_actor) (MetaWindowActor *actor, - MetaSurfaceActor *surface_actor); - - void (*queue_frame_drawn) (MetaWindowActor *actor, - gboolean skip_sync_delay); - - void (*before_paint) (MetaWindowActor *actor, - ClutterStageView *stage_view); - void (*after_paint) (MetaWindowActor *actor, - ClutterStageView *stage_view); - - void (*queue_destroy) (MetaWindowActor *actor); - void (*set_frozen) (MetaWindowActor *actor, - gboolean frozen); - void (*update_regions) (MetaWindowActor *actor); - gboolean (*can_freeze_commits) (MetaWindowActor *actor); -}; - -typedef enum -{ - META_WINDOW_ACTOR_CHANGE_SIZE = 1 << 0, - META_WINDOW_ACTOR_CHANGE_POSITION = 1 << 1 -} MetaWindowActorChanges; - -void meta_window_actor_queue_destroy (MetaWindowActor *self); - -void meta_window_actor_show (MetaWindowActor *self, - MetaCompEffect effect); -void meta_window_actor_hide (MetaWindowActor *self, - MetaCompEffect effect); - -void meta_window_actor_size_change (MetaWindowActor *self, - MetaSizeChange which_change, - MetaRectangle *old_frame_rect, - MetaRectangle *old_buffer_rect); - -void meta_window_actor_before_paint (MetaWindowActor *self, - ClutterStageView *stage_view); -void meta_window_actor_after_paint (MetaWindowActor *self, - ClutterStageView *stage_view); -void meta_window_actor_frame_complete (MetaWindowActor *self, - ClutterFrameInfo *frame_info, - gint64 presentation_time); - -gboolean meta_window_actor_effect_in_progress (MetaWindowActor *self); - -MetaWindowActorChanges meta_window_actor_sync_actor_geometry (MetaWindowActor *self, - gboolean did_placement); - -void meta_window_actor_update_opacity (MetaWindowActor *self); -void meta_window_actor_mapped (MetaWindowActor *self); -void meta_window_actor_unmapped (MetaWindowActor *self); -void meta_window_actor_sync_updates_frozen (MetaWindowActor *self); -void meta_window_actor_queue_frame_drawn (MetaWindowActor *self, - gboolean no_delay_frame); - -void meta_window_actor_effect_completed (MetaWindowActor *actor, - MetaPluginEffect event); - -MetaSurfaceActor *meta_window_actor_get_surface (MetaWindowActor *self); - -void meta_window_actor_assign_surface_actor (MetaWindowActor *self, - MetaSurfaceActor *surface_actor); - -MetaWindowActor *meta_window_actor_from_window (MetaWindow *window); -MetaWindowActor *meta_window_actor_from_actor (ClutterActor *actor); - -void meta_window_actor_set_geometry_scale (MetaWindowActor *window_actor, - int geometry_scale); - -int meta_window_actor_get_geometry_scale (MetaWindowActor *window_actor); - -void meta_window_actor_notify_damaged (MetaWindowActor *window_actor); - -gboolean meta_window_actor_is_frozen (MetaWindowActor *self); - -gboolean meta_window_actor_is_opaque (MetaWindowActor *self); - -void meta_window_actor_update_regions (MetaWindowActor *self); - -gboolean meta_window_actor_can_freeze_commits (MetaWindowActor *self); - -#endif /* META_WINDOW_ACTOR_PRIVATE_H */ diff --git a/src/compositor/meta-window-actor-wayland.c b/src/compositor/meta-window-actor-wayland.c deleted file mode 100644 index b1fe61641..000000000 --- a/src/compositor/meta-window-actor-wayland.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2018 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. - * - * Written by: - * Georges Basile Stavracas Neto - */ - -#include "compositor/meta-surface-actor-wayland.h" -#include "compositor/meta-window-actor-wayland.h" -#include "meta/meta-window-actor.h" -#include "wayland/meta-wayland-surface.h" - -struct _MetaWindowActorWayland -{ - MetaWindowActor parent; -}; - -G_DEFINE_TYPE (MetaWindowActorWayland, meta_window_actor_wayland, META_TYPE_WINDOW_ACTOR) - -typedef struct _SurfaceTreeTraverseData -{ - MetaWindowActor *window_actor; - int index; -} SurfaceTreeTraverseData; - -static gboolean -set_surface_actor_index (GNode *node, - gpointer data) -{ - MetaWaylandSurface *surface = node->data; - MetaSurfaceActor *surface_actor = meta_wayland_surface_get_actor (surface); - SurfaceTreeTraverseData *traverse_data = data; - - if (clutter_actor_contains (CLUTTER_ACTOR (traverse_data->window_actor), - CLUTTER_ACTOR (surface_actor))) - { - clutter_actor_set_child_at_index ( - CLUTTER_ACTOR (traverse_data->window_actor), - CLUTTER_ACTOR (surface_actor), - traverse_data->index); - } - else - { - clutter_actor_insert_child_at_index ( - CLUTTER_ACTOR (traverse_data->window_actor), - CLUTTER_ACTOR (surface_actor), - traverse_data->index); - } - traverse_data->index++; - - return FALSE; -} - -void -meta_window_actor_wayland_rebuild_surface_tree (MetaWindowActor *actor) -{ - MetaSurfaceActor *surface_actor = - meta_window_actor_get_surface (actor); - MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface ( - META_SURFACE_ACTOR_WAYLAND (surface_actor)); - GNode *root_node = surface->subsurface_branch_node; - SurfaceTreeTraverseData traverse_data; - - traverse_data = (SurfaceTreeTraverseData) { - .window_actor = actor, - .index = 0, - }; - g_node_traverse (root_node, - G_IN_ORDER, - G_TRAVERSE_LEAVES, - -1, - set_surface_actor_index, - &traverse_data); -} - -static void -meta_window_actor_wayland_assign_surface_actor (MetaWindowActor *actor, - MetaSurfaceActor *surface_actor) -{ - MetaWindowActorClass *parent_class = - META_WINDOW_ACTOR_CLASS (meta_window_actor_wayland_parent_class); - - g_warn_if_fail (!meta_window_actor_get_surface (actor)); - - parent_class->assign_surface_actor (actor, surface_actor); - - meta_window_actor_wayland_rebuild_surface_tree (actor); -} - -static void -meta_window_actor_wayland_frame_complete (MetaWindowActor *actor, - ClutterFrameInfo *frame_info, - int64_t presentation_time) -{ -} - -static void -meta_window_actor_wayland_queue_frame_drawn (MetaWindowActor *actor, - gboolean skip_sync_delay) -{ -} - -static void -meta_window_actor_wayland_before_paint (MetaWindowActor *actor, - ClutterStageView *stage_view) -{ -} - -static void -meta_window_actor_wayland_after_paint (MetaWindowActor *actor, - ClutterStageView *stage_view) -{ -} - -static void -meta_window_actor_wayland_queue_destroy (MetaWindowActor *actor) -{ -} - -static void -meta_window_actor_wayland_set_frozen (MetaWindowActor *actor, - gboolean frozen) -{ -} - -static void -meta_window_actor_wayland_update_regions (MetaWindowActor *actor) -{ -} - -static gboolean -meta_window_actor_wayland_can_freeze_commits (MetaWindowActor *actor) -{ - return FALSE; -} - -static void -meta_window_actor_wayland_class_init (MetaWindowActorWaylandClass *klass) -{ - MetaWindowActorClass *window_actor_class = META_WINDOW_ACTOR_CLASS (klass); - - window_actor_class->assign_surface_actor = meta_window_actor_wayland_assign_surface_actor; - window_actor_class->frame_complete = meta_window_actor_wayland_frame_complete; - window_actor_class->queue_frame_drawn = meta_window_actor_wayland_queue_frame_drawn; - window_actor_class->before_paint = meta_window_actor_wayland_before_paint; - window_actor_class->after_paint = meta_window_actor_wayland_after_paint; - window_actor_class->queue_destroy = meta_window_actor_wayland_queue_destroy; - window_actor_class->set_frozen = meta_window_actor_wayland_set_frozen; - window_actor_class->update_regions = meta_window_actor_wayland_update_regions; - window_actor_class->can_freeze_commits = meta_window_actor_wayland_can_freeze_commits; -} - -static void -meta_window_actor_wayland_init (MetaWindowActorWayland *self) -{ -} diff --git a/src/compositor/meta-window-actor-wayland.h b/src/compositor/meta-window-actor-wayland.h deleted file mode 100644 index d94de8106..000000000 --- a/src/compositor/meta-window-actor-wayland.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2018 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. - * - * Written by: - * Georges Basile Stavracas Neto - */ - -#ifndef META_WINDOW_ACTOR_WAYLAND_H -#define META_WINDOW_ACTOR_WAYLAND_H - -#include "compositor/meta-window-actor-private.h" -#include "wayland/meta-wayland-surface.h" - -#define META_TYPE_WINDOW_ACTOR_WAYLAND (meta_window_actor_wayland_get_type()) -G_DECLARE_FINAL_TYPE (MetaWindowActorWayland, - meta_window_actor_wayland, - META, WINDOW_ACTOR_WAYLAND, - MetaWindowActor) - -void meta_window_actor_wayland_rebuild_surface_tree (MetaWindowActor *actor); - -#endif /*META_WINDOW_ACTOR_WAYLAND_H */ diff --git a/src/compositor/meta-window-actor-x11.c b/src/compositor/meta-window-actor-x11.c deleted file mode 100644 index e18b1b28b..000000000 --- a/src/compositor/meta-window-actor-x11.c +++ /dev/null @@ -1,1693 +0,0 @@ -/* - * Copyright (C) 2018 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. - * - * Written by: - * Georges Basile Stavracas Neto - */ - -#include "config.h" - -#include "compositor/meta-window-actor-x11.h" - -#include "backends/meta-logical-monitor.h" -#include "clutter/clutter-frame-clock.h" -#include "compositor/compositor-private.h" -#include "compositor/meta-cullable.h" -#include "compositor/meta-shaped-texture-private.h" -#include "compositor/meta-surface-actor.h" -#include "compositor/meta-surface-actor-x11.h" -#include "compositor/region-utils.h" -#include "core/frame.h" -#include "core/window-private.h" -#include "meta/compositor.h" -#include "meta/meta-enum-types.h" -#include "meta/meta-shadow-factory.h" -#include "meta/meta-window-actor.h" -#include "meta/meta-x11-errors.h" -#include "meta/window.h" -#include "x11/window-x11.h" -#include "x11/meta-x11-display-private.h" -#include "x11/window-x11.h" - -enum -{ - PROP_SHADOW_MODE = 1, - PROP_SHADOW_CLASS -}; - -struct _MetaWindowActorX11 -{ - MetaWindowActor parent; - - /* List of FrameData for recent frames */ - GList *frames; - - guint send_frame_messages_timer; - int64_t frame_drawn_time; - gboolean pending_schedule_update_now; - ClutterFrameClock *frame_clock; - - gulong repaint_scheduled_id; - gulong size_changed_id; - - /* If set, the client needs to be sent a _NET_WM_FRAME_DRAWN - * client message for one or more messages in ->frames */ - gboolean needs_frame_drawn; - gboolean repaint_scheduled; - - /* - * MetaShadowFactory only caches shadows that are actually in use; - * to avoid unnecessary recomputation we do two things: 1) we store - * both a focused and unfocused shadow for the window. If the window - * doesn't have different focused and unfocused shadow parameters, - * these will be the same. 2) when the shadow potentially changes we - * don't immediately unreference the old shadow, we just flag it as - * dirty and recompute it when we next need it (recompute_focused_shadow, - * recompute_unfocused_shadow.) Because of our extraction of - * size-invariant window shape, we'll often find that the new shadow - * is the same as the old shadow. - */ - MetaShadow *focused_shadow; - MetaShadow *unfocused_shadow; - - /* A region that matches the shape of the window, including frame bounds */ - cairo_region_t *shape_region; - /* The region we should clip to when painting the shadow */ - cairo_region_t *shadow_clip; - /* The frame region */ - cairo_region_t *frame_bounds; - - /* Extracted size-invariant shape used for shadows */ - MetaWindowShape *shadow_shape; - char *shadow_class; - - MetaShadowFactory *shadow_factory; - gulong shadow_factory_changed_handler_id; - - MetaShadowMode shadow_mode; - - gboolean needs_reshape; - gboolean recompute_focused_shadow; - gboolean recompute_unfocused_shadow; - gboolean is_frozen; -}; - -static MetaCullableInterface *cullable_parent_iface; - -static void cullable_iface_init (MetaCullableInterface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaWindowActorX11, meta_window_actor_x11, META_TYPE_WINDOW_ACTOR, - G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init)) - -/* Each time the application updates the sync request counter to a new even value - * value, we queue a frame into the windows list of frames. Once we're painting - * an update "in response" to the window, we fill in frame_counter with the - * Cogl counter for that frame, and send _NET_WM_FRAME_DRAWN at the end of the - * frame. _NET_WM_FRAME_TIMINGS is sent when we get a frame_complete callback. - * - * As an exception, if a window is completely obscured, we try to throttle drawning - * to a slower frame rate. In this case, frame_counter stays -1 until - * send_frame_message_timeout() runs, at which point we send both the - * _NET_WM_FRAME_DRAWN and _NET_WM_FRAME_TIMINGS messages. - */ -typedef struct -{ - uint64_t sync_request_serial; - int64_t frame_counter; - int64_t frame_drawn_time; -} FrameData; - -static void -frame_data_free (FrameData *frame) -{ - g_free (frame); -} - -static void -surface_repaint_scheduled (MetaSurfaceActor *actor, - gpointer user_data) -{ - MetaWindowActorX11 *actor_x11 = META_WINDOW_ACTOR_X11 (user_data); - - actor_x11->repaint_scheduled = TRUE; -} - -static void -remove_frame_messages_timer (MetaWindowActorX11 *actor_x11) -{ - g_assert (actor_x11->send_frame_messages_timer != 0); - - g_clear_handle_id (&actor_x11->send_frame_messages_timer, g_source_remove); -} - -static void -do_send_frame_drawn (MetaWindowActorX11 *actor_x11, - FrameData *frame) -{ - MetaWindow *window = - meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); - MetaDisplay *display = meta_window_get_display (window); - Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display); - int64_t now_us; - - XClientMessageEvent ev = { 0, }; - - now_us = g_get_monotonic_time (); - frame->frame_drawn_time = - meta_compositor_monotonic_to_high_res_xserver_time (display->compositor, - now_us); - actor_x11->frame_drawn_time = frame->frame_drawn_time; - - ev.type = ClientMessage; - ev.window = meta_window_get_xwindow (window); - ev.message_type = display->x11_display->atom__NET_WM_FRAME_DRAWN; - ev.format = 32; - ev.data.l[0] = frame->sync_request_serial & G_GUINT64_CONSTANT (0xffffffff); - ev.data.l[1] = frame->sync_request_serial >> 32; - ev.data.l[2] = frame->frame_drawn_time & G_GUINT64_CONSTANT (0xffffffff); - ev.data.l[3] = frame->frame_drawn_time >> 32; - - meta_x11_error_trap_push (display->x11_display); - XSendEvent (xdisplay, ev.window, False, 0, (XEvent *) &ev); - XFlush (xdisplay); - meta_x11_error_trap_pop (display->x11_display); -} - -static void -do_send_frame_timings (MetaWindowActorX11 *actor_x11, - FrameData *frame, - int refresh_interval, - int64_t presentation_time) -{ - MetaWindow *window = - meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); - MetaDisplay *display = meta_window_get_display (window); - Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display); - - XClientMessageEvent ev = { 0, }; - - ev.type = ClientMessage; - ev.window = meta_window_get_xwindow (window); - ev.message_type = display->x11_display->atom__NET_WM_FRAME_TIMINGS; - ev.format = 32; - ev.data.l[0] = frame->sync_request_serial & G_GUINT64_CONSTANT (0xffffffff); - ev.data.l[1] = frame->sync_request_serial >> 32; - - if (presentation_time != 0) - { - MetaCompositor *compositor = display->compositor; - int64_t presentation_time_server; - - presentation_time_server = - meta_compositor_monotonic_to_high_res_xserver_time (compositor, - presentation_time); - int64_t presentation_time_offset = presentation_time_server - frame->frame_drawn_time; - if (presentation_time_offset == 0) - presentation_time_offset = 1; - - if ((int32_t)presentation_time_offset == presentation_time_offset) - ev.data.l[2] = presentation_time_offset; - } - - ev.data.l[3] = refresh_interval; - ev.data.l[4] = 1000 * META_SYNC_DELAY; - - meta_x11_error_trap_push (display->x11_display); - XSendEvent (xdisplay, ev.window, False, 0, (XEvent *) &ev); - XFlush (xdisplay); - meta_x11_error_trap_pop (display->x11_display); -} - -static void -send_frame_timings (MetaWindowActorX11 *actor_x11, - FrameData *frame, - ClutterFrameInfo *frame_info, - int64_t presentation_time) -{ - float refresh_rate; - int refresh_interval; - - refresh_rate = frame_info->refresh_rate; - /* 0.0 is a flag for not known, but sanity-check against other odd numbers */ - if (refresh_rate >= 1.0) - refresh_interval = (int) (0.5 + 1000000 / refresh_rate); - else - refresh_interval = 0; - - do_send_frame_timings (actor_x11, frame, refresh_interval, presentation_time); -} - -static gboolean -send_frame_messages_timeout (gpointer data) -{ - MetaWindowActorX11 *actor_x11 = META_WINDOW_ACTOR_X11 (data); - GList *l; - - for (l = actor_x11->frames; l;) - { - GList *l_next = l->next; - FrameData *frame = l->data; - - if (frame->frame_counter == -1) - { - do_send_frame_drawn (actor_x11, frame); - do_send_frame_timings (actor_x11, frame, 0, 0); - - actor_x11->frames = g_list_delete_link (actor_x11->frames, l); - frame_data_free (frame); - } - - l = l_next; - } - - actor_x11->needs_frame_drawn = FALSE; - actor_x11->send_frame_messages_timer = 0; - - return G_SOURCE_REMOVE; -} - -static void -queue_send_frame_messages_timeout (MetaWindowActorX11 *actor_x11) -{ - MetaWindow *window = - meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); - MetaDisplay *display = meta_window_get_display (window); - MetaLogicalMonitor *logical_monitor; - int64_t now_us; - int64_t current_time; - float refresh_rate; - int interval, offset; - - if (actor_x11->send_frame_messages_timer != 0) - return; - - logical_monitor = meta_window_get_main_logical_monitor (window); - if (logical_monitor) - { - GList *monitors = meta_logical_monitor_get_monitors (logical_monitor); - MetaMonitor *monitor; - MetaMonitorMode *mode; - - monitor = g_list_first (monitors)->data; - mode = meta_monitor_get_current_mode (monitor); - - refresh_rate = meta_monitor_mode_get_refresh_rate (mode); - } - else - { - refresh_rate = 60.0f; - } - - now_us = g_get_monotonic_time (); - current_time = - meta_compositor_monotonic_to_high_res_xserver_time (display->compositor, - now_us); - interval = (int) (1000000 / refresh_rate) * 6; - offset = MAX (0, actor_x11->frame_drawn_time + interval - current_time) / 1000; - - /* The clutter master clock source has already been added with META_PRIORITY_REDRAW, - * so the timer will run *after* the clutter frame handling, if a frame is ready - * to be drawn when the timer expires. - */ - actor_x11->send_frame_messages_timer = - g_timeout_add_full (META_PRIORITY_REDRAW, offset, - send_frame_messages_timeout, - actor_x11, NULL); - g_source_set_name_by_id (actor_x11->send_frame_messages_timer, - "[mutter] send_frame_messages_timeout"); -} - -static void -assign_frame_counter_to_frames (MetaWindowActorX11 *actor_x11) -{ - MetaWindow *window = - meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); - MetaCompositor *compositor = window->display->compositor; - ClutterStage *stage = meta_compositor_get_stage (compositor); - GList *l; - - /* If the window is obscured, then we're expecting to deal with sending - * frame messages in a timeout, rather than in this paint cycle. - */ - if (actor_x11->send_frame_messages_timer != 0) - return; - - for (l = actor_x11->frames; l; l = l->next) - { - FrameData *frame = l->data; - - if (frame->frame_counter == -1) - frame->frame_counter = clutter_stage_get_frame_counter (stage); - } -} - -static void -meta_window_actor_x11_frame_complete (MetaWindowActor *actor, - ClutterFrameInfo *frame_info, - int64_t presentation_time) -{ - MetaWindowActorX11 *actor_x11 = META_WINDOW_ACTOR_X11 (actor); - GList *l; - - if (meta_window_actor_is_destroyed (actor)) - return; - - for (l = actor_x11->frames; l;) - { - GList *l_next = l->next; - FrameData *frame = l->data; - int64_t frame_counter = frame_info->frame_counter; - - if (frame->frame_counter != -1 && frame->frame_counter <= frame_counter) - { - MetaWindow *window = - meta_window_actor_get_meta_window (actor); - - if (G_UNLIKELY (frame->frame_drawn_time == 0)) - g_warning ("%s: Frame has assigned frame counter but no frame drawn time", - window->desc); - if (G_UNLIKELY (frame->frame_counter < frame_counter)) - g_debug ("%s: frame_complete callback never occurred for frame %" G_GINT64_FORMAT, - window->desc, frame->frame_counter); - - actor_x11->frames = g_list_delete_link (actor_x11->frames, l); - send_frame_timings (actor_x11, frame, frame_info, presentation_time); - frame_data_free (frame); - } - - l = l_next; - } -} - -static void -surface_size_changed (MetaSurfaceActor *actor, - gpointer user_data) -{ - MetaWindowActorX11 *actor_x11 = META_WINDOW_ACTOR_X11 (user_data); - - meta_window_actor_x11_update_shape (actor_x11); -} - -static void -meta_window_actor_x11_assign_surface_actor (MetaWindowActor *actor, - MetaSurfaceActor *surface_actor) -{ - MetaWindowActorClass *parent_class = - META_WINDOW_ACTOR_CLASS (meta_window_actor_x11_parent_class); - MetaWindowActorX11 *actor_x11 = META_WINDOW_ACTOR_X11 (actor); - MetaSurfaceActor *prev_surface_actor; - - prev_surface_actor = meta_window_actor_get_surface (actor); - if (prev_surface_actor) - { - g_warn_if_fail (meta_is_wayland_compositor ()); - - g_clear_signal_handler (&actor_x11->size_changed_id, prev_surface_actor); - clutter_actor_remove_child (CLUTTER_ACTOR (actor), - CLUTTER_ACTOR (prev_surface_actor)); - } - - parent_class->assign_surface_actor (actor, surface_actor); - - clutter_actor_add_child (CLUTTER_ACTOR (actor), - CLUTTER_ACTOR (surface_actor)); - - meta_window_actor_x11_update_shape (actor_x11); - - actor_x11->size_changed_id = - g_signal_connect (surface_actor, "size-changed", - G_CALLBACK (surface_size_changed), - actor_x11); - actor_x11->repaint_scheduled_id = - g_signal_connect (surface_actor, "repaint-scheduled", - G_CALLBACK (surface_repaint_scheduled), - actor_x11); -} - -static void -meta_window_actor_x11_queue_frame_drawn (MetaWindowActor *actor, - gboolean skip_sync_delay) -{ - MetaWindowActorX11 *actor_x11 = META_WINDOW_ACTOR_X11 (actor); - MetaWindow *window = - meta_window_actor_get_meta_window (actor); - FrameData *frame; - - if (meta_window_actor_is_destroyed (actor)) - return; - - frame = g_new0 (FrameData, 1); - frame->frame_counter = -1; - frame->sync_request_serial = window->sync_request_serial; - - actor_x11->frames = g_list_prepend (actor_x11->frames, frame); - - actor_x11->needs_frame_drawn = TRUE; - - if (skip_sync_delay) - { - if (actor_x11->frame_clock) - clutter_frame_clock_schedule_update_now (actor_x11->frame_clock); - else - actor_x11->pending_schedule_update_now = TRUE; - } - - if (!actor_x11->repaint_scheduled) - { - MetaSurfaceActor *surface; - gboolean is_obscured; - - surface = meta_window_actor_get_surface (META_WINDOW_ACTOR (actor_x11)); - - if (surface) - is_obscured = meta_surface_actor_is_obscured (surface); - else - is_obscured = FALSE; - - /* A frame was marked by the client without actually doing any - * damage or any unobscured, or while we had the window frozen - * (e.g. during an interactive resize.) We need to make sure that the - * before_paint/after_paint functions get called, enabling us to - * send a _NET_WM_FRAME_DRAWN. We need to do full damage to ensure that - * the window is actually repainted, otherwise any subregion we would pass - * might end up being either outside of any stage view, or be occluded by - * something else, which could potentially result in no frame being drawn - * after all. If the window is completely obscured, or completely off - * screen we fire off the send_frame_messages timeout. - */ - if (is_obscured || - !clutter_actor_peek_stage_views (CLUTTER_ACTOR (actor))) - { - queue_send_frame_messages_timeout (actor_x11); - } - else if (surface) - { - clutter_actor_queue_redraw (CLUTTER_ACTOR (surface)); - actor_x11->repaint_scheduled = TRUE; - } - } -} - -static gboolean -has_shadow (MetaWindowActorX11 *actor_x11) -{ - MetaWindow *window = - meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); - - if (actor_x11->shadow_mode == META_SHADOW_MODE_FORCED_OFF) - return FALSE; - if (actor_x11->shadow_mode == META_SHADOW_MODE_FORCED_ON) - return TRUE; - - /* Leaving out shadows for maximized and fullscreen windows is an efficiency - * win and also prevents the unsightly effect of the shadow of maximized - * window appearing on an adjacent window */ - if ((meta_window_get_maximized (window) == META_MAXIMIZE_BOTH) || - meta_window_is_fullscreen (window)) - return FALSE; - - /* - * If we have two snap-tiled windows, we don't want the shadow to obstruct - * the other window. - */ - if (meta_window_get_tile_match (window)) - return FALSE; - - /* - * Always put a shadow around windows with a frame - This should override - * the restriction about not putting a shadow around ARGB windows. - */ - if (meta_window_get_frame (window)) - return TRUE; - - /* - * Do not add shadows to non-opaque (ARGB32) windows, as we can't easily - * generate shadows for them. - */ - if (!meta_window_actor_is_opaque (META_WINDOW_ACTOR (actor_x11))) - return FALSE; - - /* - * If a window specifies that it has custom frame extents, that likely - * means that it is drawing a shadow itself. Don't draw our own. - */ - if (window->has_custom_frame_extents) - return FALSE; - - /* - * Generate shadows for all other windows. - */ - return TRUE; -} - -gboolean -meta_window_actor_x11_should_unredirect (MetaWindowActorX11 *actor_x11) -{ - MetaWindow *window = - meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaSurfaceActor *surface; - MetaSurfaceActorX11 *surface_x11; - - if (meta_window_actor_is_destroyed (META_WINDOW_ACTOR (actor_x11))) - return FALSE; - - if (!meta_window_x11_can_unredirect (window_x11)) - return FALSE; - - surface = meta_window_actor_get_surface (META_WINDOW_ACTOR (actor_x11)); - if (!surface) - return FALSE; - - if (!META_IS_SURFACE_ACTOR_X11 (surface)) - return FALSE; - - surface_x11 = META_SURFACE_ACTOR_X11 (surface); - return meta_surface_actor_x11_should_unredirect (surface_x11); -} - -void -meta_window_actor_x11_set_unredirected (MetaWindowActorX11 *actor_x11, - gboolean unredirected) -{ - MetaSurfaceActor *surface; - MetaSurfaceActorX11 *surface_x11; - - surface = meta_window_actor_get_surface (META_WINDOW_ACTOR (actor_x11)); - g_assert (surface); - - g_return_if_fail (META_IS_SURFACE_ACTOR_X11 (surface)); - - surface_x11 = META_SURFACE_ACTOR_X11 (surface); - meta_surface_actor_x11_set_unredirected (surface_x11, unredirected); -} - -static const char * -get_shadow_class (MetaWindowActorX11 *actor_x11) -{ - if (actor_x11->shadow_class) - { - return actor_x11->shadow_class; - } - else - { - MetaWindow *window = - meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); - MetaWindowType window_type; - - window_type = meta_window_get_window_type (window); - switch (window_type) - { - case META_WINDOW_DROPDOWN_MENU: - case META_WINDOW_COMBO: - return "dropdown-menu"; - case META_WINDOW_POPUP_MENU: - return "popup-menu"; - default: - { - MetaFrameType frame_type; - - frame_type = meta_window_get_frame_type (window); - return meta_frame_type_to_string (frame_type); - } - } - } -} - -static void -get_shadow_params (MetaWindowActorX11 *actor_x11, - gboolean appears_focused, - MetaShadowParams *params) -{ - const char *shadow_class = get_shadow_class (actor_x11); - - meta_shadow_factory_get_params (actor_x11->shadow_factory, - shadow_class, appears_focused, - params); -} - -static void -get_shape_bounds (MetaWindowActorX11 *actor_x11, - cairo_rectangle_int_t *bounds) -{ - cairo_region_get_extents (actor_x11->shape_region, bounds); -} - -static void -get_shadow_bounds (MetaWindowActorX11 *actor_x11, - gboolean appears_focused, - cairo_rectangle_int_t *bounds) -{ - MetaShadow *shadow; - cairo_rectangle_int_t shape_bounds; - MetaShadowParams params; - - shadow = appears_focused ? actor_x11->focused_shadow - : actor_x11->unfocused_shadow; - - get_shape_bounds (actor_x11, &shape_bounds); - get_shadow_params (actor_x11, appears_focused, ¶ms); - - meta_shadow_get_bounds (shadow, - params.x_offset + shape_bounds.x, - params.y_offset + shape_bounds.y, - shape_bounds.width, - shape_bounds.height, - bounds); -} - -/* If we have an ARGB32 window that we decorate with a frame, it's - * probably something like a translucent terminal - something where - * the alpha channel represents transparency rather than a shape. We - * don't want to show the shadow through the translucent areas since - * the shadow is wrong for translucent windows (it should be - * translucent itself and colored), and not only that, will /look/ - * horribly wrong - a misplaced big black blob. As a hack, what we - * want to do is just draw the shadow as normal outside the frame, and - * inside the frame draw no shadow. This is also not even close to - * the right result, but looks OK. We also apply this approach to - * windows set to be partially translucent with _NET_WM_WINDOW_OPACITY. - */ -static gboolean -clip_shadow_under_window (MetaWindowActorX11 *actor_x11) -{ - MetaWindow *window = - meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); - - if (window->frame) - return TRUE; - - return meta_window_actor_is_opaque (META_WINDOW_ACTOR (actor_x11)); -} - -/** - * set_clip_region_beneath: - * @actor_x11: a #MetaWindowActorX11 - * @clip_region: the region of the screen that isn't completely - * obscured beneath the main window texture. - * - * Provides a hint as to what areas need to be drawn *beneath* - * the main window texture. This is the relevant clip region - * when drawing the shadow, properly accounting for areas of the - * shadow hid by the window itself. This will be set before painting - * then unset afterwards. - */ -static void -set_clip_region_beneath (MetaWindowActorX11 *actor_x11, - cairo_region_t *beneath_region) -{ - MetaWindow *window; - gboolean appears_focused; - - window = meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); - appears_focused = meta_window_appears_focused (window); - if (appears_focused ? actor_x11->focused_shadow : actor_x11->unfocused_shadow) - { - g_clear_pointer (&actor_x11->shadow_clip, cairo_region_destroy); - - if (beneath_region) - { - actor_x11->shadow_clip = cairo_region_copy (beneath_region); - - if (clip_shadow_under_window (actor_x11)) - { - if (actor_x11->frame_bounds) - cairo_region_subtract (actor_x11->shadow_clip, actor_x11->frame_bounds); - } - } - else - { - actor_x11->shadow_clip = NULL; - } - } -} - -static void -check_needs_shadow (MetaWindowActorX11 *actor_x11) -{ - MetaWindow *window = - meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); - MetaShadow *old_shadow = NULL; - MetaShadow **shadow_location; - gboolean recompute_shadow; - gboolean should_have_shadow; - gboolean appears_focused; - - /* Calling has_shadow() here at every pre-paint is cheap - * and avoids the need to explicitly handle window type changes, which - * we would do if tried to keep track of when we might be adding or removing - * a shadow more explicitly. We only keep track of changes to the *shape* of - * the shadow with actor_x11->recompute_shadow. - */ - - should_have_shadow = has_shadow (actor_x11); - appears_focused = meta_window_appears_focused (window); - - if (appears_focused) - { - recompute_shadow = actor_x11->recompute_focused_shadow; - actor_x11->recompute_focused_shadow = FALSE; - shadow_location = &actor_x11->focused_shadow; - } - else - { - recompute_shadow = actor_x11->recompute_unfocused_shadow; - actor_x11->recompute_unfocused_shadow = FALSE; - shadow_location = &actor_x11->unfocused_shadow; - } - - if (!should_have_shadow || recompute_shadow) - { - if (*shadow_location != NULL) - { - old_shadow = *shadow_location; - *shadow_location = NULL; - } - } - - if (!*shadow_location && should_have_shadow) - { - MetaShadowFactory *factory = actor_x11->shadow_factory; - const char *shadow_class = get_shadow_class (actor_x11); - cairo_rectangle_int_t shape_bounds; - - if (!actor_x11->shadow_shape) - { - actor_x11->shadow_shape = - meta_window_shape_new (actor_x11->shape_region); - } - - get_shape_bounds (actor_x11, &shape_bounds); - *shadow_location = - meta_shadow_factory_get_shadow (factory, - actor_x11->shadow_shape, - shape_bounds.width, shape_bounds.height, - shadow_class, appears_focused); - } - - if (old_shadow) - meta_shadow_unref (old_shadow); -} - -void -meta_window_actor_x11_process_damage (MetaWindowActorX11 *actor_x11, - XDamageNotifyEvent *event) -{ - MetaSurfaceActor *surface; - - surface = meta_window_actor_get_surface (META_WINDOW_ACTOR (actor_x11)); - if (surface) - meta_surface_actor_process_damage (surface, - event->area.x, - event->area.y, - event->area.width, - event->area.height); - - meta_window_actor_notify_damaged (META_WINDOW_ACTOR (actor_x11)); -} - -static cairo_region_t * -scan_visible_region (guchar *mask_data, - int stride, - cairo_region_t *scan_area) -{ - int i, n_rects = cairo_region_num_rectangles (scan_area); - MetaRegionBuilder builder; - - meta_region_builder_init (&builder); - - for (i = 0; i < n_rects; i++) - { - int x, y; - cairo_rectangle_int_t rect; - - cairo_region_get_rectangle (scan_area, i, &rect); - - for (y = rect.y; y < (rect.y + rect.height); y++) - { - for (x = rect.x; x < (rect.x + rect.width); x++) - { - int x2 = x; - while (mask_data[y * stride + x2] == 255 && x2 < (rect.x + rect.width)) - x2++; - - if (x2 > x) - { - meta_region_builder_add_rectangle (&builder, x, y, x2 - x, 1); - x = x2; - } - } - } - } - - return meta_region_builder_finish (&builder); -} - -static void -get_client_area_rect_from_texture (MetaWindowActorX11 *actor_x11, - MetaShapedTexture *shaped_texture, - cairo_rectangle_int_t *client_area) -{ - MetaWindow *window = - meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); - cairo_rectangle_int_t surface_rect = { 0 }; - - surface_rect.width = meta_shaped_texture_get_width (shaped_texture); - surface_rect.height = meta_shaped_texture_get_height (shaped_texture); - meta_window_x11_surface_rect_to_client_rect (window, - &surface_rect, - client_area); -} - -static void -get_client_area_rect (MetaWindowActorX11 *actor_x11, - cairo_rectangle_int_t *client_area) -{ - MetaSurfaceActor *surface = - meta_window_actor_get_surface (META_WINDOW_ACTOR (actor_x11)); - MetaWindow *window = - meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); - MetaShapedTexture *stex = meta_surface_actor_get_texture (surface); - - if (!meta_window_x11_always_update_shape (window) || !stex) - { - meta_window_get_client_area_rect (window, client_area); - return; - } - - get_client_area_rect_from_texture (actor_x11, stex, client_area); -} - -static void -build_and_scan_frame_mask (MetaWindowActorX11 *actor_x11, - cairo_region_t *shape_region) -{ - ClutterBackend *backend = clutter_get_default_backend (); - MetaWindow *window = - meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); - CoglContext *ctx = clutter_backend_get_cogl_context (backend); - MetaSurfaceActor *surface = - meta_window_actor_get_surface (META_WINDOW_ACTOR (actor_x11)); - uint8_t *mask_data; - unsigned int tex_width, tex_height; - MetaShapedTexture *stex; - CoglTexture2D *mask_texture; - int stride; - cairo_t *cr; - cairo_surface_t *image; - GError *error = NULL; - - stex = meta_surface_actor_get_texture (surface); - g_return_if_fail (stex); - - meta_shaped_texture_set_mask_texture (stex, NULL); - - tex_width = meta_shaped_texture_get_width (stex); - tex_height = meta_shaped_texture_get_height (stex); - - stride = cairo_format_stride_for_width (CAIRO_FORMAT_A8, tex_width); - - /* Create data for an empty image */ - mask_data = g_malloc0 (stride * tex_height); - - image = cairo_image_surface_create_for_data (mask_data, - CAIRO_FORMAT_A8, - tex_width, - tex_height, - stride); - cr = cairo_create (image); - - gdk_cairo_region (cr, shape_region); - cairo_fill (cr); - - if (window->frame) - { - cairo_region_t *frame_paint_region, *scanned_region; - cairo_rectangle_int_t rect = { 0, 0, tex_width, tex_height }; - cairo_rectangle_int_t client_area; - cairo_rectangle_int_t frame_rect; - - /* If we update the shape regardless of the frozen state of the actor, - * as with Xwayland to avoid the black shadow effect, we ought to base - * the frame size on the buffer size rather than the reported window's - * frame size, as the buffer may not have been committed yet at this - * point. - */ - if (meta_window_x11_always_update_shape (window)) - { - meta_window_x11_surface_rect_to_frame_rect (window, &rect, &frame_rect); - get_client_area_rect_from_texture (actor_x11, stex, &client_area); - } - else - { - meta_window_get_frame_rect (window, &frame_rect); - meta_window_get_client_area_rect (window, &client_area); - } - - /* Make sure we don't paint the frame over the client window. */ - frame_paint_region = cairo_region_create_rectangle (&rect); - cairo_region_subtract_rectangle (frame_paint_region, &client_area); - - gdk_cairo_region (cr, frame_paint_region); - cairo_clip (cr); - - meta_frame_get_mask (window->frame, &frame_rect, cr); - - cairo_surface_flush (image); - scanned_region = scan_visible_region (mask_data, stride, frame_paint_region); - cairo_region_union (shape_region, scanned_region); - cairo_region_destroy (scanned_region); - cairo_region_destroy (frame_paint_region); - } - - cairo_destroy (cr); - cairo_surface_destroy (image); - - mask_texture = cogl_texture_2d_new_from_data (ctx, tex_width, tex_height, - COGL_PIXEL_FORMAT_A_8, - stride, mask_data, &error); - - if (error) - { - g_warning ("Failed to allocate mask texture: %s", error->message); - g_error_free (error); - } - - if (mask_texture) - { - meta_shaped_texture_set_mask_texture (stex, COGL_TEXTURE (mask_texture)); - cogl_object_unref (mask_texture); - } - else - { - meta_shaped_texture_set_mask_texture (stex, NULL); - } - - g_free (mask_data); -} - -static void -invalidate_shadow (MetaWindowActorX11 *actor_x11) -{ - actor_x11->recompute_focused_shadow = TRUE; - actor_x11->recompute_unfocused_shadow = TRUE; - - if (meta_window_actor_is_frozen (META_WINDOW_ACTOR (actor_x11))) - return; - - clutter_actor_queue_redraw (CLUTTER_ACTOR (actor_x11)); - clutter_actor_invalidate_paint_volume (CLUTTER_ACTOR (actor_x11)); -} - -static void -update_shape_region (MetaWindowActorX11 *actor_x11) -{ - MetaWindow *window = - meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); - cairo_region_t *region = NULL; - cairo_rectangle_int_t client_area; - - get_client_area_rect (actor_x11, &client_area); - - if (window->frame && window->shape_region) - { - region = cairo_region_copy (window->shape_region); - cairo_region_translate (region, client_area.x, client_area.y); - } - else if (window->shape_region != NULL) - { - region = cairo_region_reference (window->shape_region); - } - else - { - /* If we don't have a shape on the server, that means that - * we have an implicit shape of one rectangle covering the - * entire window. */ - region = cairo_region_create_rectangle (&client_area); - } - - if (window->shape_region || window->frame) - build_and_scan_frame_mask (actor_x11, region); - - g_clear_pointer (&actor_x11->shape_region, cairo_region_destroy); - actor_x11->shape_region = region; - - g_clear_pointer (&actor_x11->shadow_shape, meta_window_shape_unref); - - invalidate_shadow (actor_x11); -} - -static void -update_input_region (MetaWindowActorX11 *actor_x11) -{ - MetaWindow *window = - meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); - MetaSurfaceActor *surface = - meta_window_actor_get_surface (META_WINDOW_ACTOR (actor_x11)); - cairo_region_t *region; - - if (window->shape_region && window->input_region) - { - region = cairo_region_copy (window->shape_region); - cairo_region_intersect (region, window->input_region); - } - else if (window->shape_region) - { - region = cairo_region_reference (window->shape_region); - } - else if (window->input_region) - { - region = cairo_region_reference (window->input_region); - } - else - { - region = NULL; - } - - meta_surface_actor_set_input_region (surface, region); - cairo_region_destroy (region); -} - -static gboolean -is_actor_maybe_transparent (MetaWindowActorX11 *actor_x11) -{ - MetaSurfaceActor *surface; - MetaShapedTexture *stex; - - surface = meta_window_actor_get_surface (META_WINDOW_ACTOR (actor_x11)); - if (!surface) - return TRUE; - - if (META_IS_SURFACE_ACTOR_X11 (surface) && - meta_surface_actor_x11_is_unredirected (META_SURFACE_ACTOR_X11 (surface))) - return FALSE; - - stex = meta_surface_actor_get_texture (surface); - if (!meta_shaped_texture_has_alpha (stex)) - return FALSE; - - return TRUE; -} - -static void -update_opaque_region (MetaWindowActorX11 *actor_x11) -{ - MetaWindow *window = - meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); - gboolean is_maybe_transparent; - cairo_region_t *opaque_region; - MetaSurfaceActor *surface; - - is_maybe_transparent = is_actor_maybe_transparent (actor_x11); - if (is_maybe_transparent && window->opaque_region) - { - cairo_rectangle_int_t client_area; - - get_client_area_rect (actor_x11, &client_area); - - /* The opaque region is defined to be a part of the - * window which ARGB32 will always paint with opaque - * pixels. For these regions, we want to avoid painting - * windows and shadows beneath them. - * - * If the client gives bad coordinates where it does not - * fully paint, the behavior is defined by the specification - * to be undefined, and considered a client bug. In mutter's - * case, graphical glitches will occur. - */ - opaque_region = cairo_region_copy (window->opaque_region); - cairo_region_translate (opaque_region, client_area.x, client_area.y); - cairo_region_intersect (opaque_region, actor_x11->shape_region); - } - else if (is_maybe_transparent) - { - opaque_region = NULL; - } - else - { - opaque_region = cairo_region_reference (actor_x11->shape_region); - } - - surface = meta_window_actor_get_surface (META_WINDOW_ACTOR (actor_x11)); - meta_surface_actor_set_opaque_region (surface, opaque_region); - cairo_region_destroy (opaque_region); -} - -static void -update_frame_bounds (MetaWindowActorX11 *actor_x11) -{ - MetaWindow *window = - meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); - - g_clear_pointer (&actor_x11->frame_bounds, cairo_region_destroy); - actor_x11->frame_bounds = - cairo_region_copy (meta_window_get_frame_bounds (window)); -} - -static void -update_regions (MetaWindowActorX11 *actor_x11) -{ - if (!actor_x11->needs_reshape) - return; - - update_shape_region (actor_x11); - update_input_region (actor_x11); - update_opaque_region (actor_x11); - - actor_x11->needs_reshape = FALSE; -} - -static void -check_needs_reshape (MetaWindowActorX11 *actor_x11) -{ - MetaWindow *window = - meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); - - if (meta_window_x11_always_update_shape (window)) - return; - - update_regions (actor_x11); -} - -void -meta_window_actor_x11_update_shape (MetaWindowActorX11 *actor_x11) -{ - MetaSurfaceActor *surface = - meta_window_actor_get_surface (META_WINDOW_ACTOR (actor_x11)); - - actor_x11->needs_reshape = TRUE; - - if (meta_window_actor_is_frozen (META_WINDOW_ACTOR (actor_x11))) - return; - - clutter_actor_queue_redraw (CLUTTER_ACTOR (surface)); -} - -static void -handle_updates (MetaWindowActorX11 *actor_x11) -{ - MetaSurfaceActor *surface = - meta_window_actor_get_surface (META_WINDOW_ACTOR (actor_x11)); - MetaWindow *window; - - if (META_IS_SURFACE_ACTOR_X11 (surface) && - meta_surface_actor_x11_is_unredirected (META_SURFACE_ACTOR_X11 (surface))) - return; - - window = meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); - if (meta_window_actor_is_frozen (META_WINDOW_ACTOR (actor_x11))) - { - /* The window is frozen due to a pending animation: we'll wait until - * the animation finishes to repair the window. - * - * However, with Xwayland, we still might need to update the shape - * region as the wl_buffer will be set to plain black on resize, - * which causes the shadows to look bad. - */ - if (surface && meta_window_x11_always_update_shape (window)) - check_needs_reshape (actor_x11); - - return; - } - - if (META_IS_SURFACE_ACTOR_X11 (surface)) - { - MetaSurfaceActorX11 *surface_x11 = META_SURFACE_ACTOR_X11 (surface); - - meta_surface_actor_x11_handle_updates (surface_x11); - } - - if (META_IS_SURFACE_ACTOR_X11 (surface) && - !meta_surface_actor_x11_is_visible (META_SURFACE_ACTOR_X11 (surface))) - return; - - update_frame_bounds (actor_x11); - check_needs_reshape (actor_x11); - check_needs_shadow (actor_x11); -} - -static void -handle_stage_views_changed (MetaWindowActorX11 *actor_x11) -{ - ClutterActor *actor = CLUTTER_ACTOR (actor_x11); - - actor_x11->frame_clock = clutter_actor_pick_frame_clock (actor, NULL); - if (actor_x11->frame_clock && actor_x11->pending_schedule_update_now) - { - clutter_frame_clock_schedule_update_now (actor_x11->frame_clock); - actor_x11->pending_schedule_update_now = FALSE; - } -} - -static void -meta_window_actor_x11_before_paint (MetaWindowActor *actor, - ClutterStageView *stage_view) -{ - MetaWindowActorX11 *actor_x11 = META_WINDOW_ACTOR_X11 (actor); - - handle_updates (actor_x11); - - assign_frame_counter_to_frames (actor_x11); -} - -static void -meta_window_actor_x11_paint (ClutterActor *actor, - ClutterPaintContext *paint_context) -{ - MetaWindowActorX11 *actor_x11 = META_WINDOW_ACTOR_X11 (actor); - MetaWindow *window; - gboolean appears_focused; - MetaShadow *shadow; - - /* This window got damage when obscured; we set up a timer - * to send frame completion events, but since we're drawing - * the window now (for some other reason) cancel the timer - * and send the completion events normally */ - if (actor_x11->send_frame_messages_timer != 0) - { - remove_frame_messages_timer (actor_x11); - assign_frame_counter_to_frames (actor_x11); - } - - window = meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); - appears_focused = meta_window_appears_focused (window); - shadow = appears_focused ? actor_x11->focused_shadow - : actor_x11->unfocused_shadow; - - if (shadow) - { - MetaShadowParams params; - cairo_rectangle_int_t shape_bounds; - cairo_region_t *clip = actor_x11->shadow_clip; - CoglFramebuffer *framebuffer; - - get_shape_bounds (actor_x11, &shape_bounds); - get_shadow_params (actor_x11, appears_focused, ¶ms); - - /* The frame bounds are already subtracted from actor_x11->shadow_clip - * if that exists. - */ - if (!clip && clip_shadow_under_window (actor_x11)) - { - cairo_rectangle_int_t bounds; - - get_shadow_bounds (actor_x11, appears_focused, &bounds); - clip = cairo_region_create_rectangle (&bounds); - - if (actor_x11->frame_bounds) - cairo_region_subtract (clip, actor_x11->frame_bounds); - } - - framebuffer = clutter_paint_context_get_framebuffer (paint_context); - meta_shadow_paint (shadow, - framebuffer, - params.x_offset + shape_bounds.x, - params.y_offset + shape_bounds.y, - shape_bounds.width, - shape_bounds.height, - (clutter_actor_get_paint_opacity (actor) * - params.opacity * window->opacity) / (255 * 255), - clip, - clip_shadow_under_window (actor_x11)); - - if (clip && clip != actor_x11->shadow_clip) - cairo_region_destroy (clip); - } - - CLUTTER_ACTOR_CLASS (meta_window_actor_x11_parent_class)->paint (actor, - paint_context); -} - -static void -meta_window_actor_x11_after_paint (MetaWindowActor *actor, - ClutterStageView *stage_view) -{ - MetaWindowActorX11 *actor_x11 = META_WINDOW_ACTOR_X11 (actor); - MetaWindow *window; - - actor_x11->repaint_scheduled = FALSE; - - if (meta_window_actor_is_destroyed (actor)) - return; - - /* If the window had damage, but wasn't actually redrawn because - * it is obscured, we should wait until timer expiration before - * sending _NET_WM_FRAME_* messages. - */ - if (actor_x11->send_frame_messages_timer == 0 && - actor_x11->needs_frame_drawn) - { - GList *l; - - for (l = actor_x11->frames; l; l = l->next) - { - FrameData *frame = l->data; - - if (frame->frame_drawn_time == 0) - do_send_frame_drawn (actor_x11, frame); - } - - actor_x11->needs_frame_drawn = FALSE; - } - - /* This is for Xwayland, and a no-op on plain Xorg */ - window = meta_window_actor_get_meta_window (actor); - if (meta_window_x11_should_thaw_after_paint (window)) - { - meta_window_x11_thaw_commits (window); - meta_window_x11_set_thaw_after_paint (window, FALSE); - } -} - -static gboolean -meta_window_actor_x11_get_paint_volume (ClutterActor *actor, - ClutterPaintVolume *volume) -{ - MetaWindowActorX11 *actor_x11 = META_WINDOW_ACTOR_X11 (actor); - MetaWindow *window; - gboolean appears_focused; - MetaSurfaceActor *surface; - - /* The paint volume is computed before paint functions are called - * so our bounds might not be updated yet. Force an update. */ - handle_updates (actor_x11); - - window = meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11)); - appears_focused = meta_window_appears_focused (window); - if (appears_focused ? actor_x11->focused_shadow : actor_x11->unfocused_shadow) - { - cairo_rectangle_int_t shadow_bounds; - ClutterActorBox shadow_box; - - /* We could compute an full clip region as we do for the window - * texture, but the shadow is relatively cheap to draw, and - * a little more complex to clip, so we just catch the case where - * the shadow is completely obscured and doesn't need to be drawn - * at all. - */ - - get_shadow_bounds (actor_x11, appears_focused, &shadow_bounds); - shadow_box.x1 = shadow_bounds.x; - shadow_box.x2 = shadow_bounds.x + shadow_bounds.width; - shadow_box.y1 = shadow_bounds.y; - shadow_box.y2 = shadow_bounds.y + shadow_bounds.height; - - clutter_paint_volume_union_box (volume, &shadow_box); - } - - surface = meta_window_actor_get_surface (META_WINDOW_ACTOR (actor_x11)); - if (surface) - { - ClutterActor *surface_actor = CLUTTER_ACTOR (surface); - const ClutterPaintVolume *child_volume; - - child_volume = clutter_actor_get_transformed_paint_volume (surface_actor, - actor); - if (!child_volume) - return FALSE; - - clutter_paint_volume_union (volume, child_volume); - } - - return TRUE; -} - -static void -meta_window_actor_x11_queue_destroy (MetaWindowActor *actor) -{ - MetaWindowActorX11 *actor_x11 = META_WINDOW_ACTOR_X11 (actor); - - if (actor_x11->send_frame_messages_timer != 0) - remove_frame_messages_timer (actor_x11); -} - -static void -meta_window_actor_x11_set_frozen (MetaWindowActor *actor, - gboolean frozen) -{ - MetaWindowActorX11 *actor_x11 = META_WINDOW_ACTOR_X11 (actor); - MetaWindow *window = meta_window_actor_get_meta_window (actor); - - if (actor_x11->is_frozen == frozen) - return; - - actor_x11->is_frozen = frozen; - - if (frozen) - meta_window_x11_freeze_commits (window); - else - meta_window_x11_thaw_commits (window); -} - -static void -meta_window_actor_x11_update_regions (MetaWindowActor *actor) -{ - update_regions (META_WINDOW_ACTOR_X11 (actor)); -} - -static gboolean -meta_window_actor_x11_can_freeze_commits (MetaWindowActor *actor) -{ - ClutterActor *clutter_actor = CLUTTER_ACTOR (actor); - - return clutter_actor_is_mapped (clutter_actor); -} - -static void -meta_window_actor_x11_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaWindowActorX11 *actor_x11 = META_WINDOW_ACTOR_X11 (object); - - switch (prop_id) - { - case PROP_SHADOW_MODE: - { - MetaShadowMode newv = g_value_get_enum (value); - - if (newv == actor_x11->shadow_mode) - return; - - actor_x11->shadow_mode = newv; - - invalidate_shadow (actor_x11); - } - break; - case PROP_SHADOW_CLASS: - { - const char *newv = g_value_get_string (value); - - if (g_strcmp0 (newv, actor_x11->shadow_class) == 0) - return; - - g_free (actor_x11->shadow_class); - actor_x11->shadow_class = g_strdup (newv); - - invalidate_shadow (actor_x11); - } - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_window_actor_x11_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaWindowActorX11 *actor_x11 = META_WINDOW_ACTOR_X11 (object); - - switch (prop_id) - { - case PROP_SHADOW_MODE: - g_value_set_enum (value, actor_x11->shadow_mode); - break; - case PROP_SHADOW_CLASS: - g_value_set_string (value, actor_x11->shadow_class); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_window_actor_x11_constructed (GObject *object) -{ - MetaWindowActorX11 *actor_x11 = META_WINDOW_ACTOR_X11 (object); - MetaWindowActor *actor = META_WINDOW_ACTOR (actor_x11); - MetaWindow *window = meta_window_actor_get_meta_window (actor); - - /* - * Start off with an empty shape region to maintain the invariant that it's - * always set. - */ - actor_x11->shape_region = cairo_region_create (); - - G_OBJECT_CLASS (meta_window_actor_x11_parent_class)->constructed (object); - - /* If a window doesn't start off with updates frozen, we should - * we should send a _NET_WM_FRAME_DRAWN immediately after the first drawn. - */ - if (window->extended_sync_request_counter && - !meta_window_updates_are_frozen (window)) - meta_window_actor_queue_frame_drawn (actor, FALSE); -} - -static void -meta_window_actor_x11_cull_out (MetaCullable *cullable, - cairo_region_t *unobscured_region, - cairo_region_t *clip_region) -{ - MetaWindowActorX11 *self = META_WINDOW_ACTOR_X11 (cullable); - - cullable_parent_iface->cull_out (cullable, unobscured_region, clip_region); - - set_clip_region_beneath (self, clip_region); -} - -static void -meta_window_actor_x11_reset_culling (MetaCullable *cullable) -{ - MetaWindowActorX11 *actor_x11 = META_WINDOW_ACTOR_X11 (cullable); - - g_clear_pointer (&actor_x11->shadow_clip, cairo_region_destroy); - - cullable_parent_iface->reset_culling (cullable); -} - -static void -cullable_iface_init (MetaCullableInterface *iface) -{ - cullable_parent_iface = g_type_interface_peek_parent (iface); - - iface->cull_out = meta_window_actor_x11_cull_out; - iface->reset_culling = meta_window_actor_x11_reset_culling; -} - -static void -meta_window_actor_x11_dispose (GObject *object) -{ - MetaWindowActorX11 *actor_x11 = META_WINDOW_ACTOR_X11 (object); - MetaSurfaceActor *surface_actor; - - g_clear_signal_handler (&actor_x11->shadow_factory_changed_handler_id, - actor_x11->shadow_factory); - - if (actor_x11->send_frame_messages_timer != 0) - remove_frame_messages_timer (actor_x11); - - surface_actor = meta_window_actor_get_surface (META_WINDOW_ACTOR (actor_x11)); - if (surface_actor) - { - g_clear_signal_handler (&actor_x11->repaint_scheduled_id, surface_actor); - g_clear_signal_handler (&actor_x11->size_changed_id, surface_actor); - } - - g_clear_pointer (&actor_x11->shape_region, cairo_region_destroy); - g_clear_pointer (&actor_x11->shadow_clip, cairo_region_destroy); - g_clear_pointer (&actor_x11->frame_bounds, cairo_region_destroy); - - g_clear_pointer (&actor_x11->shadow_class, g_free); - g_clear_pointer (&actor_x11->focused_shadow, meta_shadow_unref); - g_clear_pointer (&actor_x11->unfocused_shadow, meta_shadow_unref); - g_clear_pointer (&actor_x11->shadow_shape, meta_window_shape_unref); - - G_OBJECT_CLASS (meta_window_actor_x11_parent_class)->dispose (object); -} - -static void -meta_window_actor_x11_finalize (GObject *object) -{ - MetaWindowActorX11 *actor_x11 = META_WINDOW_ACTOR_X11 (object); - - g_list_free_full (actor_x11->frames, (GDestroyNotify) frame_data_free); - - G_OBJECT_CLASS (meta_window_actor_x11_parent_class)->finalize (object); -} - -static void -meta_window_actor_x11_class_init (MetaWindowActorX11Class *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); - MetaWindowActorClass *window_actor_class = META_WINDOW_ACTOR_CLASS (klass); - GParamSpec *pspec; - - window_actor_class->frame_complete = meta_window_actor_x11_frame_complete; - window_actor_class->assign_surface_actor = meta_window_actor_x11_assign_surface_actor; - window_actor_class->queue_frame_drawn = meta_window_actor_x11_queue_frame_drawn; - window_actor_class->before_paint = meta_window_actor_x11_before_paint; - window_actor_class->after_paint = meta_window_actor_x11_after_paint; - window_actor_class->queue_destroy = meta_window_actor_x11_queue_destroy; - window_actor_class->set_frozen = meta_window_actor_x11_set_frozen; - window_actor_class->update_regions = meta_window_actor_x11_update_regions; - window_actor_class->can_freeze_commits = meta_window_actor_x11_can_freeze_commits; - - actor_class->paint = meta_window_actor_x11_paint; - actor_class->get_paint_volume = meta_window_actor_x11_get_paint_volume; - - object_class->constructed = meta_window_actor_x11_constructed; - object_class->set_property = meta_window_actor_x11_set_property; - object_class->get_property = meta_window_actor_x11_get_property; - object_class->dispose = meta_window_actor_x11_dispose; - object_class->finalize = meta_window_actor_x11_finalize; - - pspec = g_param_spec_enum ("shadow-mode", - "Shadow mode", - "Decides when to paint shadows", - META_TYPE_SHADOW_MODE, - META_SHADOW_MODE_AUTO, - G_PARAM_READWRITE); - - g_object_class_install_property (object_class, - PROP_SHADOW_MODE, - pspec); - - pspec = g_param_spec_string ("shadow-class", - "Name of the shadow class for this window.", - "NULL means to use the default shadow class for this window type", - NULL, - G_PARAM_READWRITE); - - g_object_class_install_property (object_class, - PROP_SHADOW_CLASS, - pspec); -} - -static void -meta_window_actor_x11_init (MetaWindowActorX11 *self) -{ - /* We do this now since we might be going right back into the frozen state. */ - g_signal_connect (self, "thawed", G_CALLBACK (handle_updates), NULL); - - g_signal_connect (self, "stage-views-changed", - G_CALLBACK (handle_stage_views_changed), NULL); - - self->shadow_factory = meta_shadow_factory_get_default (); - self->shadow_factory_changed_handler_id = - g_signal_connect_swapped (self->shadow_factory, - "changed", - G_CALLBACK (invalidate_shadow), - self); -} diff --git a/src/compositor/meta-window-actor-x11.h b/src/compositor/meta-window-actor-x11.h deleted file mode 100644 index 86b80034d..000000000 --- a/src/compositor/meta-window-actor-x11.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2018 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. - * - * Written by: - * Georges Basile Stavracas Neto - */ - -#ifndef META_WINDOW_ACTOR_X11_H -#define META_WINDOW_ACTOR_X11_H - -#include "compositor/meta-window-actor-private.h" - -#define META_TYPE_WINDOW_ACTOR_X11 (meta_window_actor_x11_get_type()) -G_DECLARE_FINAL_TYPE (MetaWindowActorX11, - meta_window_actor_x11, - META, WINDOW_ACTOR_X11, - MetaWindowActor) - -void meta_window_actor_x11_process_x11_damage (MetaWindowActorX11 *actor_x11, - XDamageNotifyEvent *event); - -gboolean meta_window_actor_x11_should_unredirect (MetaWindowActorX11 *actor_x11); - -void meta_window_actor_x11_set_unredirected (MetaWindowActorX11 *actor_x11, - gboolean unredirected); - -void meta_window_actor_x11_update_shape (MetaWindowActorX11 *actor_x11); - -void meta_window_actor_x11_process_damage (MetaWindowActorX11 *actor_x11, - XDamageNotifyEvent *event); - -#endif /* META_WINDOW_ACTOR_X11_H */ diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c deleted file mode 100644 index d4fc9a43a..000000000 --- a/src/compositor/meta-window-actor.c +++ /dev/null @@ -1,1559 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/** - * SECTION:meta-window-actor - * @title: MetaWindowActor - * @short_description: An actor representing a top-level window in the scene - * graph - * - * #MetaWindowActor is a #ClutterActor that adds a notion of a window to the - * Clutter scene graph. It contains a #MetaWindow which provides the windowing - * API, and the #MetaCompositor that handles it. For the actual content of the - * window, it contains a #MetaSurfaceActor. - * - * #MetaWindowActor takes care of the rendering features you need for your - * window. For example, it will take the windows' requested opacity and use - * that for clutter_actor_set_opacity(). Furthermore, it will also draw a - * shadow around the window (using #MetaShadow) and deal with synchronization - * between events of the window and the actual render loop. See - * MetaWindowActor::first-frame for an example of the latter. - */ - -#include "config.h" - -#include -#include -#include - -#include "backends/meta-screen-cast-window.h" -#include "compositor/compositor-private.h" -#include "compositor/meta-cullable.h" -#include "compositor/meta-shaped-texture-private.h" -#include "compositor/meta-surface-actor-x11.h" -#include "compositor/meta-surface-actor.h" -#include "compositor/meta-window-actor-private.h" -#include "core/boxes-private.h" -#include "core/window-private.h" -#include "meta/window.h" - -#ifdef HAVE_WAYLAND -#include "compositor/meta-surface-actor-wayland.h" -#include "wayland/meta-wayland-surface.h" -#endif - -typedef enum -{ - INITIALLY_FROZEN, - DRAWING_FIRST_FRAME, - EMITTED_FIRST_FRAME -} FirstFrameState; - -typedef struct _MetaWindowActorPrivate -{ - MetaWindow *window; - MetaCompositor *compositor; - - MetaSurfaceActor *surface; - - int geometry_scale; - - /* - * These need to be counters rather than flags, since more plugins - * can implement same effect; the practicality of stacking effects - * might be dubious, but we have to at least handle it correctly. - */ - gint minimize_in_progress; - gint unminimize_in_progress; - gint size_change_in_progress; - gint map_in_progress; - gint destroy_in_progress; - - guint freeze_count; - - guint visible : 1; - guint disposed : 1; - - guint needs_destroy : 1; - - guint updates_frozen : 1; - guint first_frame_state : 2; /* FirstFrameState */ -} MetaWindowActorPrivate; - -enum -{ - FIRST_FRAME, - EFFECTS_COMPLETED, - DAMAGED, - THAWED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -enum -{ - PROP_META_WINDOW = 1, -}; - -static void meta_window_actor_dispose (GObject *object); -static void meta_window_actor_constructed (GObject *object); -static void meta_window_actor_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec); -static void meta_window_actor_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec); - -static void meta_window_actor_real_assign_surface_actor (MetaWindowActor *self, - MetaSurfaceActor *surface_actor); - -static void cullable_iface_init (MetaCullableInterface *iface); - -static void screen_cast_window_iface_init (MetaScreenCastWindowInterface *iface); - -G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaWindowActor, meta_window_actor, CLUTTER_TYPE_ACTOR, - G_ADD_PRIVATE (MetaWindowActor) - G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init) - G_IMPLEMENT_INTERFACE (META_TYPE_SCREEN_CAST_WINDOW, screen_cast_window_iface_init)); - -static void -meta_window_actor_class_init (MetaWindowActorClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GParamSpec *pspec; - - object_class->dispose = meta_window_actor_dispose; - object_class->set_property = meta_window_actor_set_property; - object_class->get_property = meta_window_actor_get_property; - object_class->constructed = meta_window_actor_constructed; - - klass->assign_surface_actor = meta_window_actor_real_assign_surface_actor; - - /** - * MetaWindowActor::first-frame: - * @actor: the #MetaWindowActor instance - * - * The ::first-frame signal will be emitted the first time a frame - * of window contents has been drawn by the application and Mutter - * has had the chance to drawn that frame to the screen. If the - * window starts off initially hidden, obscured, or on on a - * different workspace, the ::first-frame signal will be emitted - * even though the user doesn't see the contents. - * - * MetaDisplay::window-created is a good place to connect to this - * signal - at that point, the MetaWindowActor for the window - * exists, but the window has reliably not yet been drawn. - * Connecting to an existing window that has already been drawn to - * the screen is not useful. - */ - signals[FIRST_FRAME] = - g_signal_new ("first-frame", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - /** - * MetaWindowActor::effects-completed: - * @actor: the #MetaWindowActor instance - * - * The ::effects-completed signal will be emitted once all pending compositor - * effects are completed. - */ - signals[EFFECTS_COMPLETED] = - g_signal_new ("effects-completed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - /** - * MetaWindowActor::damaged: - * @actor: the #MetaWindowActor instance - * - * Notify that one or more of the surfaces of the window have been damaged. - */ - signals[DAMAGED] = - g_signal_new ("damaged", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - /** - * MetaWindowActor::thawed: - * @actor: the #MetaWindowActor instance - */ - signals[THAWED] = - g_signal_new ("thawed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - pspec = g_param_spec_object ("meta-window", - "MetaWindow", - "The displayed MetaWindow", - META_TYPE_WINDOW, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - - g_object_class_install_property (object_class, - PROP_META_WINDOW, - pspec); -} - -static void -meta_window_actor_init (MetaWindowActor *self) -{ - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - - priv->geometry_scale = 1; -} - -static void -window_appears_focused_notify (MetaWindow *mw, - GParamSpec *arg1, - gpointer data) -{ - clutter_actor_queue_redraw (CLUTTER_ACTOR (data)); -} - -gboolean -meta_window_actor_is_opaque (MetaWindowActor *self) -{ - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - MetaWindow *window = priv->window; - - if (window->opacity != 0xff) - return FALSE; - - if (!priv->surface) - return FALSE; - - return meta_surface_actor_is_opaque (priv->surface); -} - -gboolean -meta_window_actor_is_frozen (MetaWindowActor *self) -{ - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - - return priv->surface == NULL || priv->freeze_count > 0; -} - -void -meta_window_actor_update_regions (MetaWindowActor *self) -{ - META_WINDOW_ACTOR_GET_CLASS (self)->update_regions (self); -} - -gboolean -meta_window_actor_can_freeze_commits (MetaWindowActor *self) -{ - g_return_val_if_fail (META_IS_WINDOW_ACTOR (self), FALSE); - - return META_WINDOW_ACTOR_GET_CLASS (self)->can_freeze_commits (self); -} - -static void -meta_window_actor_set_frozen (MetaWindowActor *self, - gboolean frozen) -{ - ClutterActor *child; - ClutterActorIter iter; - - clutter_actor_iter_init (&iter, CLUTTER_ACTOR (self)); - while (clutter_actor_iter_next (&iter, &child)) - { - if (META_IS_SURFACE_ACTOR (child)) - meta_surface_actor_set_frozen (META_SURFACE_ACTOR (child), frozen); - } - - META_WINDOW_ACTOR_GET_CLASS (self)->set_frozen (self, frozen); -} - -/** - * meta_window_actor_freeze: - * @self: The #MetaWindowActor - * - * Freezes the #MetaWindowActor, which inhibits updates and geometry - * changes of the window. This property is refcounted, so make sure - * to call meta_window_actor_thaw() the exact same amount of times - * as this function to allow updates again. - */ -void -meta_window_actor_freeze (MetaWindowActor *self) -{ - MetaWindowActorPrivate *priv; - - g_return_if_fail (META_IS_WINDOW_ACTOR (self)); - - priv = meta_window_actor_get_instance_private (self); - - if (priv->freeze_count == 0 && priv->surface) - meta_window_actor_set_frozen (self, TRUE); - - priv->freeze_count ++; -} - -static void -meta_window_actor_sync_thawed_state (MetaWindowActor *self) -{ - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - - if (priv->first_frame_state == INITIALLY_FROZEN) - priv->first_frame_state = DRAWING_FIRST_FRAME; - - if (priv->surface) - meta_window_actor_set_frozen (self, FALSE); - - /* We sometimes ignore moves and resizes on frozen windows */ - meta_window_actor_sync_actor_geometry (self, FALSE); -} - -/** - * meta_window_actor_thaw: - * @self: The #MetaWindowActor - * - * Thaws/unfreezes the #MetaWindowActor to allow updates and geometry - * changes after a window was frozen using meta_window_actor_freeze(). - */ -void -meta_window_actor_thaw (MetaWindowActor *self) -{ - MetaWindowActorPrivate *priv; - - g_return_if_fail (META_IS_WINDOW_ACTOR (self)); - - priv = meta_window_actor_get_instance_private (self); - - if (priv->freeze_count <= 0) - g_error ("Error in freeze/thaw accounting"); - - priv->freeze_count--; - if (priv->freeze_count > 0) - return; - - /* We still might be frozen due to lack of a MetaSurfaceActor */ - if (meta_window_actor_is_frozen (self)) - return; - - meta_window_actor_sync_thawed_state (self); - - g_signal_emit (self, signals[THAWED], 0); -} - -static void -meta_window_actor_real_assign_surface_actor (MetaWindowActor *self, - MetaSurfaceActor *surface_actor) -{ - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - - g_clear_object (&priv->surface); - priv->surface = g_object_ref_sink (surface_actor); - - if (meta_window_actor_is_frozen (self)) - meta_window_actor_set_frozen (self, TRUE); - else - meta_window_actor_sync_thawed_state (self); -} - -void -meta_window_actor_assign_surface_actor (MetaWindowActor *self, - MetaSurfaceActor *surface_actor) -{ - META_WINDOW_ACTOR_GET_CLASS (self)->assign_surface_actor (self, - surface_actor); -} - -static void -init_surface_actor (MetaWindowActor *self) -{ - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - MetaWindow *window = priv->window; - MetaSurfaceActor *surface_actor; - - if (!meta_is_wayland_compositor ()) - surface_actor = meta_surface_actor_x11_new (window); -#ifdef HAVE_WAYLAND - else if (window->surface) - surface_actor = meta_wayland_surface_get_actor (window->surface); -#endif - else - surface_actor = NULL; - - if (surface_actor) - meta_window_actor_assign_surface_actor (self, surface_actor); -} - -static void -meta_window_actor_constructed (GObject *object) -{ - MetaWindowActor *self = META_WINDOW_ACTOR (object); - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - MetaWindow *window = priv->window; - - priv->compositor = window->display->compositor; - - /* Hang our compositor window state off the MetaWindow for fast retrieval */ - meta_window_set_compositor_private (window, object); - - init_surface_actor (self); - - meta_window_actor_update_opacity (self); - - meta_window_actor_sync_updates_frozen (self); - - if (meta_window_actor_is_frozen (self)) - priv->first_frame_state = INITIALLY_FROZEN; - else - priv->first_frame_state = DRAWING_FIRST_FRAME; - - meta_window_actor_sync_actor_geometry (self, priv->window->placed); -} - -static void -meta_window_actor_dispose (GObject *object) -{ - MetaWindowActor *self = META_WINDOW_ACTOR (object); - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - MetaCompositor *compositor = priv->compositor; - - if (priv->disposed) - { - G_OBJECT_CLASS (meta_window_actor_parent_class)->dispose (object); - return; - } - - priv->disposed = TRUE; - - meta_compositor_remove_window_actor (compositor, self); - - g_clear_object (&priv->window); - - if (priv->surface) - { - clutter_actor_remove_child (CLUTTER_ACTOR (self), - CLUTTER_ACTOR (priv->surface)); - g_clear_object (&priv->surface); - } - - G_OBJECT_CLASS (meta_window_actor_parent_class)->dispose (object); -} - -static void -meta_window_actor_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaWindowActor *self = META_WINDOW_ACTOR (object); - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - - switch (prop_id) - { - case PROP_META_WINDOW: - priv->window = g_value_dup_object (value); - g_signal_connect_object (priv->window, "notify::appears-focused", - G_CALLBACK (window_appears_focused_notify), self, 0); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_window_actor_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaWindowActor *self = META_WINDOW_ACTOR (object); - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - - switch (prop_id) - { - case PROP_META_WINDOW: - g_value_set_object (value, priv->window); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -/** - * meta_window_actor_get_meta_window: - * @self: a #MetaWindowActor - * - * Gets the #MetaWindow object that the the #MetaWindowActor is displaying - * - * Return value: (transfer none): the displayed #MetaWindow - */ -MetaWindow * -meta_window_actor_get_meta_window (MetaWindowActor *self) -{ - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - - return priv->window; -} - -/** - * meta_window_actor_get_texture: - * @self: a #MetaWindowActor - * - * Gets the ClutterActor that is used to display the contents of the window, - * or NULL if no texture is shown yet, because the window is not mapped. - * - * Return value: (transfer none): the #ClutterActor for the contents - */ -MetaShapedTexture * -meta_window_actor_get_texture (MetaWindowActor *self) -{ - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - - if (priv->surface) - return meta_surface_actor_get_texture (priv->surface); - else - return NULL; -} - -/** - * meta_window_actor_get_surface: - * @self: a #MetaWindowActor - * - * Gets the MetaSurfaceActor that draws the content of this window, - * or NULL if there is no surface yet associated with this window. - * - * Return value: (transfer none): the #MetaSurfaceActor for the contents - */ -MetaSurfaceActor * -meta_window_actor_get_surface (MetaWindowActor *self) -{ - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - - return priv->surface; -} - -/** - * meta_window_actor_is_destroyed: - * @self: a #MetaWindowActor - * - * Gets whether the X window that the actor was displaying has been destroyed - * - * Return value: %TRUE when the window is destroyed, otherwise %FALSE - */ -gboolean -meta_window_actor_is_destroyed (MetaWindowActor *self) -{ - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - - return priv->disposed || priv->needs_destroy; -} - -void -meta_window_actor_queue_frame_drawn (MetaWindowActor *self, - gboolean no_delay_frame) -{ - META_WINDOW_ACTOR_GET_CLASS (self)->queue_frame_drawn (self, - no_delay_frame); -} - -gboolean -meta_window_actor_effect_in_progress (MetaWindowActor *self) -{ - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - - return (priv->minimize_in_progress || - priv->size_change_in_progress || - priv->map_in_progress || - priv->destroy_in_progress); -} - -static gboolean -is_freeze_thaw_effect (MetaPluginEffect event) -{ - switch (event) - { - case META_PLUGIN_DESTROY: - return TRUE; - break; - default: - return FALSE; - } -} - -static gboolean -start_simple_effect (MetaWindowActor *self, - MetaPluginEffect event) -{ - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - MetaCompositor *compositor = priv->compositor; - MetaPluginManager *plugin_mgr = - meta_compositor_get_plugin_manager (compositor); - gint *counter = NULL; - gboolean use_freeze_thaw = FALSE; - - g_assert (plugin_mgr != NULL); - - switch (event) - { - case META_PLUGIN_NONE: - return FALSE; - case META_PLUGIN_MINIMIZE: - counter = &priv->minimize_in_progress; - break; - case META_PLUGIN_UNMINIMIZE: - counter = &priv->unminimize_in_progress; - break; - case META_PLUGIN_MAP: - counter = &priv->map_in_progress; - break; - case META_PLUGIN_DESTROY: - counter = &priv->destroy_in_progress; - break; - case META_PLUGIN_SIZE_CHANGE: - case META_PLUGIN_SWITCH_WORKSPACE: - g_assert_not_reached (); - break; - } - - g_assert (counter); - - use_freeze_thaw = is_freeze_thaw_effect (event); - - if (use_freeze_thaw) - meta_window_actor_freeze (self); - - (*counter)++; - - if (!meta_plugin_manager_event_simple (plugin_mgr, self, event)) - { - (*counter)--; - if (use_freeze_thaw) - meta_window_actor_thaw (self); - return FALSE; - } - - return TRUE; -} - -static void -meta_window_actor_after_effects (MetaWindowActor *self) -{ - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - ClutterStage *stage; - ClutterSeat *seat; - - stage = CLUTTER_STAGE (clutter_actor_get_stage (CLUTTER_ACTOR (self))); - seat = clutter_backend_get_default_seat (clutter_get_default_backend ()); - - if (priv->needs_destroy) - { - clutter_actor_destroy (CLUTTER_ACTOR (self)); - } - else - { - g_signal_emit (self, signals[EFFECTS_COMPLETED], 0); - meta_window_actor_sync_visibility (self); - meta_window_actor_sync_actor_geometry (self, FALSE); - } - - clutter_stage_repick_device (stage, clutter_seat_get_pointer (seat)); -} - -void -meta_window_actor_effect_completed (MetaWindowActor *self, - MetaPluginEffect event) -{ - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - gboolean inconsistent = FALSE; - - /* NB: Keep in mind that when effects get completed it possible - * that the corresponding MetaWindow may have be been destroyed. - * In this case priv->window will == NULL */ - - switch (event) - { - case META_PLUGIN_NONE: - break; - case META_PLUGIN_MINIMIZE: - { - priv->minimize_in_progress--; - if (priv->minimize_in_progress < 0) - { - g_warning ("Error in minimize accounting."); - priv->minimize_in_progress = 0; - inconsistent = TRUE; - } - } - break; - case META_PLUGIN_UNMINIMIZE: - { - priv->unminimize_in_progress--; - if (priv->unminimize_in_progress < 0) - { - g_warning ("Error in unminimize accounting."); - priv->unminimize_in_progress = 0; - inconsistent = TRUE; - } - } - break; - case META_PLUGIN_MAP: - /* - * Make sure that the actor is at the correct place in case - * the plugin fscked. - */ - priv->map_in_progress--; - - if (priv->map_in_progress < 0) - { - g_warning ("Error in map accounting."); - priv->map_in_progress = 0; - inconsistent = TRUE; - } - break; - case META_PLUGIN_DESTROY: - priv->destroy_in_progress--; - - if (priv->destroy_in_progress < 0) - { - g_warning ("Error in destroy accounting."); - priv->destroy_in_progress = 0; - inconsistent = TRUE; - } - break; - case META_PLUGIN_SIZE_CHANGE: - priv->size_change_in_progress--; - if (priv->size_change_in_progress < 0) - { - g_warning ("Error in size change accounting."); - priv->size_change_in_progress = 0; - inconsistent = TRUE; - } - break; - case META_PLUGIN_SWITCH_WORKSPACE: - g_assert_not_reached (); - break; - } - - if (is_freeze_thaw_effect (event) && !inconsistent) - meta_window_actor_thaw (self); - - if (!meta_window_actor_effect_in_progress (self)) - meta_window_actor_after_effects (self); -} - -void -meta_window_actor_queue_destroy (MetaWindowActor *self) -{ - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - MetaWindow *window = priv->window; - MetaWindowType window_type = meta_window_get_window_type (window); - - meta_window_set_compositor_private (window, NULL); - - META_WINDOW_ACTOR_GET_CLASS (self)->queue_destroy (self); - - if (window_type == META_WINDOW_DROPDOWN_MENU || - window_type == META_WINDOW_POPUP_MENU || - window_type == META_WINDOW_TOOLTIP || - window_type == META_WINDOW_NOTIFICATION || - window_type == META_WINDOW_COMBO || - window_type == META_WINDOW_DND || - window_type == META_WINDOW_OVERRIDE_OTHER) - { - /* - * No effects, just kill it. - */ - clutter_actor_destroy (CLUTTER_ACTOR (self)); - return; - } - - priv->needs_destroy = TRUE; - - if (!meta_window_actor_effect_in_progress (self)) - clutter_actor_destroy (CLUTTER_ACTOR (self)); -} - -MetaWindowActorChanges -meta_window_actor_sync_actor_geometry (MetaWindowActor *self, - gboolean did_placement) -{ - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - MetaRectangle window_rect; - ClutterActor *actor = CLUTTER_ACTOR (self); - MetaWindowActorChanges changes = 0; - - meta_window_get_buffer_rect (priv->window, &window_rect); - - /* When running as a Wayland compositor we catch size changes when new - * buffers are attached */ - if (META_IS_SURFACE_ACTOR_X11 (priv->surface)) - meta_surface_actor_x11_set_size (META_SURFACE_ACTOR_X11 (priv->surface), - window_rect.width, window_rect.height); - - /* Normally we want freezing a window to also freeze its position; this allows - * windows to atomically move and resize together, either under app control, - * or because the user is resizing from the left/top. But on initial placement - * we need to assign a position, since immediately after the window - * is shown, the map effect will go into effect and prevent further geometry - * updates. - */ - if (meta_window_actor_is_frozen (self) && !did_placement) - return META_WINDOW_ACTOR_CHANGE_POSITION | META_WINDOW_ACTOR_CHANGE_SIZE; - - if (clutter_actor_has_allocation (actor)) - { - ClutterActorBox box; - float old_x, old_y; - float old_width, old_height; - - clutter_actor_get_allocation_box (actor, &box); - - old_x = box.x1; - old_y = box.y1; - old_width = box.x2 - box.x1; - old_height = box.y2 - box.y1; - - if (old_x != window_rect.x || old_y != window_rect.y) - changes |= META_WINDOW_ACTOR_CHANGE_POSITION; - - if (old_width != window_rect.width || old_height != window_rect.height) - changes |= META_WINDOW_ACTOR_CHANGE_SIZE; - } - else - { - changes = META_WINDOW_ACTOR_CHANGE_POSITION | META_WINDOW_ACTOR_CHANGE_SIZE; - } - - if (changes & META_WINDOW_ACTOR_CHANGE_POSITION) - clutter_actor_set_position (actor, window_rect.x, window_rect.y); - - if (changes & META_WINDOW_ACTOR_CHANGE_SIZE) - clutter_actor_set_size (actor, window_rect.width, window_rect.height); - - return changes; -} - -void -meta_window_actor_show (MetaWindowActor *self, - MetaCompEffect effect) -{ - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - MetaCompositor *compositor = priv->compositor; - MetaPluginEffect event; - - g_return_if_fail (!priv->visible); - - priv->visible = TRUE; - - switch (effect) - { - case META_COMP_EFFECT_CREATE: - event = META_PLUGIN_MAP; - break; - case META_COMP_EFFECT_UNMINIMIZE: - event = META_PLUGIN_UNMINIMIZE; - break; - case META_COMP_EFFECT_NONE: - event = META_PLUGIN_NONE; - break; - default: - g_assert_not_reached(); - } - - if (event == META_PLUGIN_MAP) - meta_window_actor_sync_actor_geometry (self, TRUE); - - if (meta_compositor_is_switching_workspace (compositor) || - !start_simple_effect (self, event)) - { - clutter_actor_show (CLUTTER_ACTOR (self)); - } -} - -void -meta_window_actor_hide (MetaWindowActor *self, - MetaCompEffect effect) -{ - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - MetaCompositor *compositor = priv->compositor; - MetaPluginEffect event; - - g_return_if_fail (priv->visible); - - priv->visible = FALSE; - - /* If a plugin is animating a workspace transition, we have to - * hold off on hiding the window, and do it after the workspace - * switch completes - */ - if (meta_compositor_is_switching_workspace (compositor)) - return; - - switch (effect) - { - case META_COMP_EFFECT_DESTROY: - event = META_PLUGIN_DESTROY; - break; - case META_COMP_EFFECT_MINIMIZE: - event = META_PLUGIN_MINIMIZE; - break; - case META_COMP_EFFECT_NONE: - event = META_PLUGIN_NONE; - break; - default: - g_assert_not_reached(); - } - - if (!start_simple_effect (self, event)) - clutter_actor_hide (CLUTTER_ACTOR (self)); -} - -void -meta_window_actor_size_change (MetaWindowActor *self, - MetaSizeChange which_change, - MetaRectangle *old_frame_rect, - MetaRectangle *old_buffer_rect) -{ - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - MetaCompositor *compositor = priv->compositor; - MetaPluginManager *plugin_mgr = - meta_compositor_get_plugin_manager (compositor); - - priv->size_change_in_progress++; - - if (!meta_plugin_manager_event_size_change (plugin_mgr, self, - which_change, old_frame_rect, old_buffer_rect)) - priv->size_change_in_progress--; -} - -#if 0 -/* Print out a region; useful for debugging */ -static void -print_region (cairo_region_t *region) -{ - int n_rects; - int i; - - n_rects = cairo_region_num_rectangles (region); - g_print ("["); - for (i = 0; i < n_rects; i++) - { - cairo_rectangle_int_t rect; - cairo_region_get_rectangle (region, i, &rect); - g_print ("+%d+%dx%dx%d ", - rect.x, rect.y, rect.width, rect.height); - } - g_print ("]\n"); -} -#endif - -#if 0 -/* Dump a region to a PNG file; useful for debugging */ -static void -see_region (cairo_region_t *region, - int width, - int height, - char *filename) -{ - cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height); - cairo_t *cr = cairo_create (surface); - - gdk_cairo_region (cr, region); - cairo_fill (cr); - - cairo_surface_write_to_png (surface, filename); - cairo_destroy (cr); - cairo_surface_destroy (surface); -} -#endif - - -static void -meta_window_actor_cull_out (MetaCullable *cullable, - cairo_region_t *unobscured_region, - cairo_region_t *clip_region) -{ - meta_cullable_cull_out_children (cullable, unobscured_region, clip_region); -} - -static void -meta_window_actor_reset_culling (MetaCullable *cullable) -{ - meta_cullable_reset_culling_children (cullable); -} - -static void -cullable_iface_init (MetaCullableInterface *iface) -{ - iface->cull_out = meta_window_actor_cull_out; - iface->reset_culling = meta_window_actor_reset_culling; -} - -void -meta_window_actor_sync_visibility (MetaWindowActor *self) -{ - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - - if (CLUTTER_ACTOR_IS_VISIBLE (self) != priv->visible) - { - if (priv->visible) - clutter_actor_show (CLUTTER_ACTOR (self)); - else - clutter_actor_hide (CLUTTER_ACTOR (self)); - } -} - -void -meta_window_actor_before_paint (MetaWindowActor *self, - ClutterStageView *stage_view) -{ - if (meta_window_actor_is_destroyed (self)) - return; - - META_WINDOW_ACTOR_GET_CLASS (self)->before_paint (self, stage_view); -} - -void -meta_window_actor_after_paint (MetaWindowActor *self, - ClutterStageView *stage_view) -{ - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - - META_WINDOW_ACTOR_GET_CLASS (self)->after_paint (self, stage_view); - - if (meta_window_actor_is_destroyed (self)) - return; - - if (priv->first_frame_state == DRAWING_FIRST_FRAME) - { - priv->first_frame_state = EMITTED_FIRST_FRAME; - g_signal_emit (self, signals[FIRST_FRAME], 0); - } -} - -void -meta_window_actor_frame_complete (MetaWindowActor *self, - ClutterFrameInfo *frame_info, - gint64 presentation_time) -{ - META_WINDOW_ACTOR_GET_CLASS (self)->frame_complete (self, - frame_info, - presentation_time); -} - -void -meta_window_actor_update_opacity (MetaWindowActor *self) -{ - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - MetaWindow *window = priv->window; - - if (priv->surface) - clutter_actor_set_opacity (CLUTTER_ACTOR (priv->surface), window->opacity); -} - -static void -meta_window_actor_set_updates_frozen (MetaWindowActor *self, - gboolean updates_frozen) -{ - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - - updates_frozen = updates_frozen != FALSE; - - if (priv->updates_frozen != updates_frozen) - { - priv->updates_frozen = updates_frozen; - if (updates_frozen) - meta_window_actor_freeze (self); - else - meta_window_actor_thaw (self); - } -} - -void -meta_window_actor_sync_updates_frozen (MetaWindowActor *self) -{ - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (self); - MetaWindow *window = priv->window; - - meta_window_actor_set_updates_frozen (self, meta_window_updates_are_frozen (window)); -} - -MetaWindowActor * -meta_window_actor_from_window (MetaWindow *window) -{ - return META_WINDOW_ACTOR (meta_window_get_compositor_private (window)); -} - -void -meta_window_actor_set_geometry_scale (MetaWindowActor *window_actor, - int geometry_scale) -{ - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (window_actor); - graphene_matrix_t child_transform; - - if (priv->geometry_scale == geometry_scale) - return; - - priv->geometry_scale = geometry_scale; - - graphene_matrix_init_scale (&child_transform, - geometry_scale, - geometry_scale, - 1); - clutter_actor_set_child_transform (CLUTTER_ACTOR (window_actor), - &child_transform); -} - -int -meta_window_actor_get_geometry_scale (MetaWindowActor *window_actor) -{ - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (window_actor); - - return priv->geometry_scale; -} - -static void -meta_window_actor_get_buffer_bounds (MetaScreenCastWindow *screen_cast_window, - MetaRectangle *bounds) -{ - MetaWindowActor *window_actor = META_WINDOW_ACTOR (screen_cast_window); - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (window_actor); - MetaShapedTexture *stex; - int buffer_scale; - - stex = meta_surface_actor_get_texture (priv->surface); - buffer_scale = meta_shaped_texture_get_buffer_scale (stex); - *bounds = (MetaRectangle) { - .width = meta_shaped_texture_get_width (stex) * buffer_scale, - .height = meta_shaped_texture_get_height (stex) * buffer_scale, - }; -} - -static void -meta_window_actor_transform_relative_position (MetaScreenCastWindow *screen_cast_window, - double x, - double y, - double *x_out, - double *y_out) - -{ - MetaWindowActor *window_actor = META_WINDOW_ACTOR (screen_cast_window); - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (window_actor); - MetaRectangle bounds; - graphene_point3d_t v1 = { 0.f, }, v2 = { 0.f, }; - - meta_window_actor_get_buffer_bounds (screen_cast_window, &bounds); - - v1.x = CLAMP ((float) x, - bounds.x, - bounds.x + bounds.width); - v1.y = CLAMP ((float) y, - bounds.y, - bounds.y + bounds.height); - - clutter_actor_apply_transform_to_point (CLUTTER_ACTOR (priv->surface), - &v1, - &v2); - - *x_out = (double) v2.x; - *y_out = (double) v2.y; -} - -static gboolean -meta_window_actor_transform_cursor_position (MetaScreenCastWindow *screen_cast_window, - MetaCursorSprite *cursor_sprite, - graphene_point_t *cursor_position, - float *out_cursor_scale, - graphene_point_t *out_relative_cursor_position) -{ - MetaWindowActor *window_actor = META_WINDOW_ACTOR (screen_cast_window); - MetaWindowActorPrivate *priv = - meta_window_actor_get_instance_private (window_actor); - MetaWindow *window; - - window = priv->window; - if (!meta_window_has_pointer (window)) - return FALSE; - - if (cursor_sprite && - meta_cursor_sprite_get_cogl_texture (cursor_sprite) && - out_cursor_scale) - { - MetaShapedTexture *stex; - double texture_scale; - float cursor_texture_scale; - - stex = meta_surface_actor_get_texture (priv->surface); - texture_scale = meta_shaped_texture_get_buffer_scale (stex); - cursor_texture_scale = meta_cursor_sprite_get_texture_scale (cursor_sprite); - - *out_cursor_scale = texture_scale / cursor_texture_scale; - } - - if (out_relative_cursor_position) - { - clutter_actor_transform_stage_point (CLUTTER_ACTOR (priv->surface), - cursor_position->x, - cursor_position->y, - &out_relative_cursor_position->x, - &out_relative_cursor_position->y); - } - - return TRUE; -} - -static void -meta_window_actor_capture_into (MetaScreenCastWindow *screen_cast_window, - MetaRectangle *bounds, - uint8_t *data) -{ - MetaWindowActor *window_actor = META_WINDOW_ACTOR (screen_cast_window); - cairo_surface_t *image; - uint8_t *cr_data; - int cr_stride; - int cr_width; - int cr_height; - int bpp = 4; - - if (meta_window_actor_is_destroyed (window_actor)) - return; - - image = meta_window_actor_get_image (window_actor, bounds); - cr_data = cairo_image_surface_get_data (image); - cr_width = cairo_image_surface_get_width (image); - cr_height = cairo_image_surface_get_height (image); - cr_stride = cairo_image_surface_get_stride (image); - - if (cr_width == bounds->width && cr_height == bounds->height) - { - memcpy (data, cr_data, cr_height * cr_stride); - } - else - { - int width = MIN (bounds->width, cr_width); - int height = MIN (bounds->height, cr_height); - int stride = width * bpp; - uint8_t *src, *dst; - - src = cr_data; - dst = data; - - for (int i = 0; i < height; i++) - { - memcpy (dst, src, stride); - if (width < bounds->width) - memset (dst + stride, 0, (bounds->width * bpp) - stride); - - src += cr_stride; - dst += bounds->width * bpp; - } - - for (int i = height; i < bounds->height; i++) - { - memset (dst, 0, bounds->width * bpp); - dst += bounds->width * bpp; - } - } - - cairo_surface_destroy (image); -} - -static gboolean -meta_window_actor_blit_to_framebuffer (MetaScreenCastWindow *screen_cast_window, - MetaRectangle *bounds, - CoglFramebuffer *framebuffer) -{ - MetaWindowActor *window_actor = META_WINDOW_ACTOR (screen_cast_window); - ClutterActor *actor = CLUTTER_ACTOR (window_actor); - ClutterPaintContext *paint_context; - MetaRectangle scaled_clip; - CoglColor clear_color; - float resource_scale; - float width, height; - float x, y; - - if (meta_window_actor_is_destroyed (window_actor)) - return FALSE; - - clutter_actor_get_size (actor, &width, &height); - - if (width == 0 || height == 0) - return FALSE; - - resource_scale = clutter_actor_get_resource_scale (actor); - - clutter_actor_inhibit_culling (actor); - - width = ceilf (width * resource_scale); - height = ceilf (height * resource_scale); - - clutter_actor_get_position (actor, &x, &y); - - cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 0); - cogl_framebuffer_clear (framebuffer, COGL_BUFFER_BIT_COLOR, &clear_color); - cogl_framebuffer_orthographic (framebuffer, 0, 0, width, height, 0, 1.0); - cogl_framebuffer_set_viewport (framebuffer, 0, 0, width, height); - - meta_rectangle_scale_double (bounds, resource_scale, - META_ROUNDING_STRATEGY_GROW, - &scaled_clip); - meta_rectangle_intersect (&scaled_clip, - &(MetaRectangle) { - .width = width, - .height = height, - }, - &scaled_clip); - - cogl_framebuffer_push_rectangle_clip (framebuffer, - scaled_clip.x, scaled_clip.y, - scaled_clip.x + scaled_clip.width, - scaled_clip.y + scaled_clip.height); - - cogl_framebuffer_push_matrix (framebuffer); - cogl_framebuffer_scale (framebuffer, resource_scale, resource_scale, 1); - cogl_framebuffer_translate (framebuffer, -x, -y, 0); - - paint_context = - clutter_paint_context_new_for_framebuffer (framebuffer, NULL, - CLUTTER_PAINT_FLAG_NONE); - clutter_actor_paint (actor, paint_context); - clutter_paint_context_destroy (paint_context); - - cogl_framebuffer_pop_matrix (framebuffer); - cogl_framebuffer_pop_clip (framebuffer); - - clutter_actor_uninhibit_culling (actor); - - return TRUE; -} - -static gboolean -meta_window_actor_has_damage (MetaScreenCastWindow *screen_cast_window) -{ - return clutter_actor_has_damage (CLUTTER_ACTOR (screen_cast_window)); -} - -static void -screen_cast_window_iface_init (MetaScreenCastWindowInterface *iface) -{ - iface->get_buffer_bounds = meta_window_actor_get_buffer_bounds; - iface->transform_relative_position = meta_window_actor_transform_relative_position; - iface->transform_cursor_position = meta_window_actor_transform_cursor_position; - iface->capture_into = meta_window_actor_capture_into; - iface->blit_to_framebuffer = meta_window_actor_blit_to_framebuffer; - iface->has_damage = meta_window_actor_has_damage; -} - -MetaWindowActor * -meta_window_actor_from_actor (ClutterActor *actor) -{ - if (!META_IS_SURFACE_ACTOR (actor)) - return NULL; - - do - { - actor = clutter_actor_get_parent (actor); - - if (META_IS_WINDOW_ACTOR (actor)) - return META_WINDOW_ACTOR (actor); - } - while (actor != NULL); - - return NULL; -} - -void -meta_window_actor_notify_damaged (MetaWindowActor *window_actor) -{ - g_signal_emit (window_actor, signals[DAMAGED], 0); -} - -/** - * meta_window_actor_get_image: - * @self: A #MetaWindowActor - * @clip: (nullable): A clipping rectangle, to help prevent extra processing. - * In the case that the clipping rectangle is partially or fully - * outside the bounds of the actor, the rectangle will be clipped. - * - * Flattens the layers of @self into one ARGB32 image by alpha blending - * the images, and returns the flattened image. - * - * Returns: (nullable) (transfer full): a new cairo surface to be freed with - * cairo_surface_destroy(). - */ -cairo_surface_t * -meta_window_actor_get_image (MetaWindowActor *self, - MetaRectangle *clip) -{ - MetaWindowActorPrivate *priv = meta_window_actor_get_instance_private (self); - ClutterActor *actor = CLUTTER_ACTOR (self); - MetaBackend *backend = meta_get_backend (); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = - clutter_backend_get_cogl_context (clutter_backend); - float resource_scale; - float width, height; - CoglTexture2D *texture; - g_autoptr (GError) error = NULL; - CoglOffscreen *offscreen; - CoglFramebuffer *framebuffer; - CoglColor clear_color; - float x, y; - MetaRectangle scaled_clip; - ClutterPaintContext *paint_context; - cairo_surface_t *surface = NULL; - - if (!priv->surface) - return NULL; - - clutter_actor_inhibit_culling (actor); - - if (clutter_actor_get_n_children (actor) == 1) - { - MetaShapedTexture *stex; - MetaRectangle *surface_clip = NULL; - - if (clip) - { - - int geometry_scale; - - geometry_scale = - meta_window_actor_get_geometry_scale (self); - - surface_clip = g_alloca (sizeof (MetaRectangle)); - surface_clip->x = clip->x / geometry_scale, - surface_clip->y = clip->y / geometry_scale; - surface_clip->width = clip->width / geometry_scale; - surface_clip->height = clip->height / geometry_scale; - } - - stex = meta_surface_actor_get_texture (priv->surface); - surface = meta_shaped_texture_get_image (stex, surface_clip); - goto out; - } - - clutter_actor_get_size (actor, &width, &height); - - if (width == 0 || height == 0) - goto out; - - resource_scale = clutter_actor_get_resource_scale (actor); - - width = ceilf (width * resource_scale); - height = ceilf (height * resource_scale); - - texture = cogl_texture_2d_new_with_size (cogl_context, width, height); - if (!texture) - goto out; - - cogl_primitive_texture_set_auto_mipmap (COGL_PRIMITIVE_TEXTURE (texture), - FALSE); - - offscreen = cogl_offscreen_new_with_texture (COGL_TEXTURE (texture)); - framebuffer = COGL_FRAMEBUFFER (offscreen); - - cogl_object_unref (texture); - - if (!cogl_framebuffer_allocate (framebuffer, &error)) - { - g_warning ("Failed to allocate framebuffer for screenshot: %s", - error->message); - g_object_unref (framebuffer); - cogl_object_unref (texture); - goto out; - } - - cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 0); - clutter_actor_get_position (actor, &x, &y); - - cogl_framebuffer_clear (framebuffer, COGL_BUFFER_BIT_COLOR, &clear_color); - cogl_framebuffer_orthographic (framebuffer, 0, 0, width, height, 0, 1.0); - cogl_framebuffer_scale (framebuffer, resource_scale, resource_scale, 1); - cogl_framebuffer_translate (framebuffer, -x, -y, 0); - - paint_context = - clutter_paint_context_new_for_framebuffer (framebuffer, NULL, - CLUTTER_PAINT_FLAG_NONE); - clutter_actor_paint (actor, paint_context); - clutter_paint_context_destroy (paint_context); - - if (clip) - { - meta_rectangle_scale_double (clip, resource_scale, - META_ROUNDING_STRATEGY_GROW, - &scaled_clip); - meta_rectangle_intersect (&scaled_clip, - &(MetaRectangle) { - .width = width, - .height = height, - }, - &scaled_clip); - } - else - { - scaled_clip = (MetaRectangle) { - .width = width, - .height = height, - }; - } - - surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - scaled_clip.width, scaled_clip.height); - cogl_framebuffer_read_pixels (framebuffer, - scaled_clip.x, scaled_clip.y, - scaled_clip.width, scaled_clip.height, - CLUTTER_CAIRO_FORMAT_ARGB32, - cairo_image_surface_get_data (surface)); - - g_object_unref (framebuffer); - - cairo_surface_mark_dirty (surface); - -out: - clutter_actor_uninhibit_culling (actor); - return surface; -} diff --git a/src/compositor/meta-window-group-private.h b/src/compositor/meta-window-group-private.h deleted file mode 100644 index c3467066b..000000000 --- a/src/compositor/meta-window-group-private.h +++ /dev/null @@ -1,23 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -#ifndef META_WINDOW_GROUP_PRIVATE_H -#define META_WINDOW_GROUP_PRIVATE_H - -#include "meta/display.h" -#include "meta/meta-window-group.h" - -/** - * MetaWindowGroup: - * - * This class is a subclass of ClutterActor with special handling for - * #MetaCullable when painting children. It uses code similar to - * meta_cullable_cull_out_children(), but also has additional special - * cases for the undirected window, and similar. - */ - - -typedef struct _MetaWindowGroupPrivate MetaWindowGroupPrivate; - -ClutterActor *meta_window_group_new (MetaDisplay *display); - -#endif /* META_WINDOW_GROUP_PRIVATE_H */ diff --git a/src/compositor/meta-window-group.c b/src/compositor/meta-window-group.c deleted file mode 100644 index d526805fe..000000000 --- a/src/compositor/meta-window-group.c +++ /dev/null @@ -1,222 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -#include "config.h" - -#include -#include - -#include "compositor/clutter-utils.h" -#include "compositor/compositor-private.h" -#include "compositor/meta-cullable.h" -#include "compositor/meta-window-actor-private.h" -#include "compositor/meta-window-group-private.h" -#include "core/display-private.h" -#include "core/window-private.h" - -struct _MetaWindowGroupClass -{ - ClutterActorClass parent_class; -}; - -struct _MetaWindowGroup -{ - ClutterActor parent; - - MetaDisplay *display; -}; - -static void cullable_iface_init (MetaCullableInterface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaWindowGroup, meta_window_group, CLUTTER_TYPE_ACTOR, - G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init)); - -static void -meta_window_group_cull_out (MetaCullable *cullable, - cairo_region_t *unobscured_region, - cairo_region_t *clip_region) -{ - meta_cullable_cull_out_children (cullable, unobscured_region, clip_region); -} - -static void -meta_window_group_reset_culling (MetaCullable *cullable) -{ - meta_cullable_reset_culling_children (cullable); -} - -static void -cullable_iface_init (MetaCullableInterface *iface) -{ - iface->cull_out = meta_window_group_cull_out; - iface->reset_culling = meta_window_group_reset_culling; -} - -static void -meta_window_group_paint (ClutterActor *actor, - ClutterPaintContext *paint_context) -{ - MetaWindowGroup *window_group = META_WINDOW_GROUP (actor); - ClutterActorClass *parent_actor_class = - CLUTTER_ACTOR_CLASS (meta_window_group_parent_class); - ClutterActor *stage = clutter_actor_get_stage (actor); - const cairo_region_t *redraw_clip; - cairo_region_t *clip_region; - cairo_region_t *unobscured_region; - cairo_rectangle_int_t visible_rect; - int paint_x_origin, paint_y_origin; - int screen_width, screen_height; - - redraw_clip = clutter_paint_context_get_redraw_clip (paint_context); - if (!redraw_clip) - { - parent_actor_class->paint (actor, paint_context); - return; - } - - meta_display_get_size (window_group->display, &screen_width, &screen_height); - - /* Normally we expect an actor to be drawn at it's position on the screen. - * However, if we're inside the paint of a ClutterClone, that won't be the - * case and we need to compensate. We look at the position of the window - * group under the current model-view matrix and the position of the actor. - * If they are both simply integer translations, then we can compensate - * easily, otherwise we give up. - * - * Possible cleanup: work entirely in paint space - we can compute the - * combination of the model-view matrix with the local matrix for each child - * actor and get a total transformation for that actor for how we are - * painting currently, and never worry about how actors are positioned - * on the stage. - */ - if (clutter_actor_is_in_clone_paint (actor)) - { - CoglFramebuffer *fb; - - fb = clutter_paint_context_get_framebuffer (paint_context); - if (!meta_actor_painting_untransformed (fb, - screen_width, - screen_height, - screen_width, - screen_height, - &paint_x_origin, - &paint_y_origin) || - !meta_cullable_is_untransformed (META_CULLABLE (actor))) - { - parent_actor_class->paint (actor, paint_context); - return; - } - } - else - { - paint_x_origin = 0; - paint_y_origin = 0; - } - - visible_rect.x = visible_rect.y = 0; - visible_rect.width = clutter_actor_get_width (CLUTTER_ACTOR (stage)); - visible_rect.height = clutter_actor_get_height (CLUTTER_ACTOR (stage)); - - unobscured_region = cairo_region_create_rectangle (&visible_rect); - - /* Get the clipped redraw bounds so that we can avoid painting shadows on - * windows that don't need to be painted in this frame. In the case of a - * multihead setup with mismatched monitor sizes, we could intersect this - * with an accurate union of the monitors to avoid painting shadows that are - * visible only in the holes. */ - clip_region = cairo_region_copy (redraw_clip); - - cairo_region_translate (clip_region, -paint_x_origin, -paint_y_origin); - - meta_cullable_cull_out (META_CULLABLE (window_group), unobscured_region, clip_region); - - cairo_region_destroy (unobscured_region); - cairo_region_destroy (clip_region); - - parent_actor_class->paint (actor, paint_context); - - meta_cullable_reset_culling (META_CULLABLE (window_group)); -} - -/* Adapted from clutter_actor_update_default_paint_volume() */ -static gboolean -meta_window_group_get_paint_volume (ClutterActor *self, - ClutterPaintVolume *volume) -{ - ClutterActorIter iter; - ClutterActor *child; - - clutter_actor_iter_init (&iter, self); - while (clutter_actor_iter_next (&iter, &child)) - { - const ClutterPaintVolume *child_volume; - - if (!CLUTTER_ACTOR_IS_MAPPED (child)) - continue; - - child_volume = clutter_actor_get_transformed_paint_volume (child, self); - if (child_volume == NULL) - return FALSE; - - clutter_paint_volume_union (volume, child_volume); - } - - return TRUE; -} - -/* This is a workaround for Clutter's awful allocation tracking. - * Without this, any time the window group changed size, which is - * any time windows are dragged around, we'll do a full repaint - * of the window group, which includes the background actor, meaning - * a full-stage repaint. - * - * Since actors are allowed to paint outside their allocation, and - * since child actors are allowed to be outside their parents, this - * doesn't affect anything, but it means that we'll get much more - * sane and consistent clipped repaints from Clutter. */ -static void -meta_window_group_get_preferred_width (ClutterActor *actor, - gfloat for_height, - gfloat *min_width, - gfloat *nat_width) -{ - *min_width = 0; - *nat_width = 0; -} - -static void -meta_window_group_get_preferred_height (ClutterActor *actor, - gfloat for_width, - gfloat *min_height, - gfloat *nat_height) -{ - *min_height = 0; - *nat_height = 0; -} - -static void -meta_window_group_class_init (MetaWindowGroupClass *klass) -{ - ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); - - actor_class->paint = meta_window_group_paint; - actor_class->get_paint_volume = meta_window_group_get_paint_volume; - actor_class->get_preferred_width = meta_window_group_get_preferred_width; - actor_class->get_preferred_height = meta_window_group_get_preferred_height; -} - -static void -meta_window_group_init (MetaWindowGroup *window_group) -{ -} - -ClutterActor * -meta_window_group_new (MetaDisplay *display) -{ - MetaWindowGroup *window_group; - - window_group = g_object_new (META_TYPE_WINDOW_GROUP, NULL); - - window_group->display = display; - - return CLUTTER_ACTOR (window_group); -} diff --git a/src/compositor/meta-window-shape.c b/src/compositor/meta-window-shape.c deleted file mode 100644 index 3bb6409c4..000000000 --- a/src/compositor/meta-window-shape.c +++ /dev/null @@ -1,259 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * MetaWindowShape - * - * Extracted invariant window shape - * - * Copyright (C) 2010 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 . - */ - -#include "config.h" - -#include "meta/meta-window-shape.h" - -#include - -#include "compositor/region-utils.h" - -struct _MetaWindowShape -{ - guint ref_count; - - int top, right, bottom, left; - int n_rectangles; - cairo_rectangle_int_t *rectangles; - guint hash; -}; - -MetaWindowShape * -meta_window_shape_new (cairo_region_t *region) -{ - MetaWindowShape *shape; - MetaRegionIterator iter; - cairo_rectangle_int_t extents; - int max_yspan_y1 = 0; - int max_yspan_y2 = 0; - int max_xspan_x1 = -1; - int max_xspan_x2 = -1; - guint hash; - - shape = g_new0 (MetaWindowShape, 1); - shape->ref_count = 1; - - cairo_region_get_extents (region, &extents); - - shape->n_rectangles = cairo_region_num_rectangles (region); - - if (shape->n_rectangles == 0) - { - shape->rectangles = NULL; - shape->top = shape->right = shape->bottom = shape->left = 0; - shape->hash = 0; - return shape; - } - - for (meta_region_iterator_init (&iter, region); - !meta_region_iterator_at_end (&iter); - meta_region_iterator_next (&iter)) - { - int max_line_xspan_x1 = -1; - int max_line_xspan_x2 = -1; - - if (iter.rectangle.width > max_line_xspan_x2 - max_line_xspan_x1) - { - max_line_xspan_x1 = iter.rectangle.x; - max_line_xspan_x2 = iter.rectangle.x + iter.rectangle.width; - } - - if (iter.line_end) - { - if (iter.rectangle.height > max_yspan_y2 - max_yspan_y1) - { - max_yspan_y1 = iter.rectangle.y; - max_yspan_y2 = iter.rectangle.y + iter.rectangle.height; - } - - if (max_xspan_x1 < 0) /* First line */ - { - max_xspan_x1 = max_line_xspan_x1; - max_xspan_x2 = max_line_xspan_x2; - } - else - { - max_xspan_x1 = MAX (max_xspan_x1, max_line_xspan_x1); - max_xspan_x2 = MIN (max_xspan_x2, max_line_xspan_x2); - - if (max_xspan_x2 < max_xspan_x1) - max_xspan_x2 = max_xspan_x1; - } - } - } - -#if 0 - g_print ("xspan: %d -> %d, yspan: %d -> %d\n", - max_xspan_x1, max_xspan_x2, - max_yspan_y1, max_yspan_y2); -#endif - - shape->top = max_yspan_y1 - extents.y; - shape->right = extents.x + extents.width - max_xspan_x2; - shape->bottom = extents.y + extents.height - max_yspan_y2; - shape->left = max_xspan_x1 - extents.x; - - shape->rectangles = g_new (cairo_rectangle_int_t, shape->n_rectangles); - - hash = 0; - for (meta_region_iterator_init (&iter, region); - !meta_region_iterator_at_end (&iter); - meta_region_iterator_next (&iter)) - { - int x1, x2, y1, y2; - - x1 = iter.rectangle.x; - x2 = iter.rectangle.x + iter.rectangle.width; - y1 = iter.rectangle.y; - y2 = iter.rectangle.y + iter.rectangle.height; - - if (x1 > max_xspan_x1) - x1 -= MIN (x1, max_xspan_x2 - 1) - max_xspan_x1; - if (x2 > max_xspan_x1) - x2 -= MIN (x2, max_xspan_x2 - 1) - max_xspan_x1; - if (y1 > max_yspan_y1) - y1 -= MIN (y1, max_yspan_y2 - 1) - max_yspan_y1; - if (y2 > max_yspan_y1) - y2 -= MIN (y2, max_yspan_y2 - 1) - max_yspan_y1; - - shape->rectangles[iter.i].x = x1 - extents.x; - shape->rectangles[iter.i].y = y1 - extents.y; - shape->rectangles[iter.i].width = x2 - x1; - shape->rectangles[iter.i].height = y2 - y1; - -#if 0 - g_print ("%d: +%d+%dx%dx%d => +%d+%dx%dx%d\n", - iter.i, iter.rectangle.x, iter.rectangle.y, iter.rectangle.width, iter.rectangle.height, - shape->rectangles[iter.i].x, shape->rectangles[iter.i].y, - hape->rectangles[iter.i].width, shape->rectangles[iter.i].height); -#endif - - hash = hash * 31 + x1 * 17 + x2 * 27 + y1 * 37 + y2 * 43; - } - - shape->hash = hash; - -#if 0 - g_print ("%d %d %d %d: %#x\n\n", shape->top, shape->right, shape->bottom, shape->left, shape->hash); -#endif - - return shape; -} - -MetaWindowShape * -meta_window_shape_ref (MetaWindowShape *shape) -{ - shape->ref_count++; - - return shape; -} - -void -meta_window_shape_unref (MetaWindowShape *shape) -{ - shape->ref_count--; - if (shape->ref_count == 0) - { - g_free (shape->rectangles); - g_free (shape); - } -} - -guint -meta_window_shape_hash (MetaWindowShape *shape) -{ - return shape->hash; -} - -gboolean -meta_window_shape_equal (MetaWindowShape *shape_a, - MetaWindowShape *shape_b) -{ - if (shape_a->n_rectangles != shape_b->n_rectangles) - return FALSE; - - return memcmp (shape_a->rectangles, shape_b->rectangles, - sizeof (cairo_rectangle_int_t) * shape_a->n_rectangles) == 0; -} - -void -meta_window_shape_get_borders (MetaWindowShape *shape, - int *border_top, - int *border_right, - int *border_bottom, - int *border_left) -{ - if (border_top) - *border_top = shape->top; - if (border_right) - *border_right = shape->right; - if (border_bottom) - *border_bottom = shape->bottom; - if (border_left) - *border_left = shape->left; -} - -/** - * meta_window_shape_to_region: - * @shape: a #MetaWindowShape - * @center_width: size of the central region horizontally - * @center_height: size of the central region vertically - * - * Converts the shape to to a cairo_region_t using the given width - * and height for the central scaled region. - * - * Return value: a newly created region - */ -cairo_region_t * -meta_window_shape_to_region (MetaWindowShape *shape, - int center_width, - int center_height) -{ - cairo_region_t *region; - int i; - - region = cairo_region_create (); - - for (i = 0; i < shape->n_rectangles; i++) - { - cairo_rectangle_int_t rect = shape->rectangles[i]; - - if (rect.x <= shape->left && rect.x + rect.width >= shape->left + 1) - rect.width += center_width; - else if (rect.x >= shape->left + 1) - rect.x += center_width; - - if (rect.y <= shape->top && rect.y + rect.height >= shape->top + 1) - rect.height += center_height; - else if (rect.y >= shape->top + 1) - rect.y += center_height; - - cairo_region_union_rectangle (region, &rect); - } - - return region; -} - -G_DEFINE_BOXED_TYPE (MetaWindowShape, meta_window_shape, - meta_window_shape_ref, meta_window_shape_unref) diff --git a/src/compositor/plugins/default.c b/src/compositor/plugins/default.c deleted file mode 100644 index c89c84121..000000000 --- a/src/compositor/plugins/default.c +++ /dev/null @@ -1,923 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (c) 2008 Intel Corp. - * - * Author: Tomas Frydrych - * - * 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 . - */ - -#include "config.h" - -#include "meta/display.h" - -#include -#include -#include - -#include "clutter/clutter.h" -#include "meta/meta-backend.h" -#include "meta/meta-background-actor.h" -#include "meta/meta-background-content.h" -#include "meta/meta-background-group.h" -#include "meta/meta-monitor-manager.h" -#include "meta/meta-plugin.h" -#include "meta/util.h" -#include "meta/window.h" - -#define DESTROY_TIMEOUT 100 -#define MINIMIZE_TIMEOUT 250 -#define MAP_TIMEOUT 250 -#define SWITCH_TIMEOUT 500 - -#define ACTOR_DATA_KEY "MCCP-Default-actor-data" -#define DISPLAY_TILE_PREVIEW_DATA_KEY "MCCP-Default-display-tile-preview-data" - -#define META_TYPE_DEFAULT_PLUGIN (meta_default_plugin_get_type ()) -#define META_DEFAULT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEFAULT_PLUGIN, MetaDefaultPlugin)) -#define META_DEFAULT_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEFAULT_PLUGIN, MetaDefaultPluginClass)) -#define META_IS_DEFAULT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_DEFAULT_PLUGIN_TYPE)) -#define META_IS_DEFAULT_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEFAULT_PLUGIN)) -#define META_DEFAULT_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEFAULT_PLUGIN, MetaDefaultPluginClass)) - -typedef struct _MetaDefaultPlugin MetaDefaultPlugin; -typedef struct _MetaDefaultPluginClass MetaDefaultPluginClass; -typedef struct _MetaDefaultPluginPrivate MetaDefaultPluginPrivate; - -struct _MetaDefaultPlugin -{ - MetaPlugin parent; - - MetaDefaultPluginPrivate *priv; -}; - -struct _MetaDefaultPluginClass -{ - MetaPluginClass parent_class; -}; - -static GQuark actor_data_quark = 0; -static GQuark display_tile_preview_data_quark = 0; - -static void start (MetaPlugin *plugin); -static void minimize (MetaPlugin *plugin, - MetaWindowActor *actor); -static void map (MetaPlugin *plugin, - MetaWindowActor *actor); -static void destroy (MetaPlugin *plugin, - MetaWindowActor *actor); - -static void switch_workspace (MetaPlugin *plugin, - gint from, - gint to, - MetaMotionDirection direction); - -static void kill_window_effects (MetaPlugin *plugin, - MetaWindowActor *actor); -static void kill_switch_workspace (MetaPlugin *plugin); - -static void show_tile_preview (MetaPlugin *plugin, - MetaWindow *window, - MetaRectangle *tile_rect, - int tile_monitor_number); -static void hide_tile_preview (MetaPlugin *plugin); - -static void confirm_display_change (MetaPlugin *plugin); - -static const MetaPluginInfo * plugin_info (MetaPlugin *plugin); - -/* - * Plugin private data that we store in the .plugin_private member. - */ -struct _MetaDefaultPluginPrivate -{ - /* Valid only when switch_workspace effect is in progress */ - ClutterTimeline *tml_switch_workspace1; - ClutterTimeline *tml_switch_workspace2; - ClutterActor *desktop1; - ClutterActor *desktop2; - - ClutterActor *background_group; - - MetaPluginInfo info; -}; - -META_PLUGIN_DECLARE_WITH_CODE (MetaDefaultPlugin, meta_default_plugin, - G_ADD_PRIVATE_DYNAMIC (MetaDefaultPlugin)); - -/* - * Per actor private data we attach to each actor. - */ -typedef struct _ActorPrivate -{ - ClutterActor *orig_parent; - - ClutterTimeline *tml_minimize; - ClutterTimeline *tml_destroy; - ClutterTimeline *tml_map; -} ActorPrivate; - -/* callback data for when animations complete */ -typedef struct -{ - ClutterActor *actor; - MetaPlugin *plugin; -} EffectCompleteData; - - -typedef struct _DisplayTilePreview -{ - ClutterActor *actor; - - GdkRGBA *preview_color; - - MetaRectangle tile_rect; -} DisplayTilePreview; - -static void -meta_default_plugin_dispose (GObject *object) -{ - /* MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (object)->priv; - */ - G_OBJECT_CLASS (meta_default_plugin_parent_class)->dispose (object); -} - -static void -meta_default_plugin_finalize (GObject *object) -{ - G_OBJECT_CLASS (meta_default_plugin_parent_class)->finalize (object); -} - -static void -meta_default_plugin_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (prop_id) - { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_default_plugin_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - switch (prop_id) - { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_default_plugin_class_init (MetaDefaultPluginClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - MetaPluginClass *plugin_class = META_PLUGIN_CLASS (klass); - - gobject_class->finalize = meta_default_plugin_finalize; - gobject_class->dispose = meta_default_plugin_dispose; - gobject_class->set_property = meta_default_plugin_set_property; - gobject_class->get_property = meta_default_plugin_get_property; - - plugin_class->start = start; - plugin_class->map = map; - plugin_class->minimize = minimize; - plugin_class->destroy = destroy; - plugin_class->switch_workspace = switch_workspace; - plugin_class->show_tile_preview = show_tile_preview; - plugin_class->hide_tile_preview = hide_tile_preview; - plugin_class->plugin_info = plugin_info; - plugin_class->kill_window_effects = kill_window_effects; - plugin_class->kill_switch_workspace = kill_switch_workspace; - plugin_class->confirm_display_change = confirm_display_change; -} - -static void -meta_default_plugin_init (MetaDefaultPlugin *self) -{ - MetaDefaultPluginPrivate *priv; - - self->priv = priv = meta_default_plugin_get_instance_private (self); - - priv->info.name = "Default Effects"; - priv->info.version = "0.1"; - priv->info.author = "Intel Corp."; - priv->info.license = "GPL"; - priv->info.description = "This is an example of a plugin implementation."; -} - -/* - * Actor private data accessor - */ -static void -free_actor_private (gpointer data) -{ - if (G_LIKELY (data != NULL)) - g_free (data); -} - -static ActorPrivate * -get_actor_private (MetaWindowActor *actor) -{ - ActorPrivate *priv = g_object_get_qdata (G_OBJECT (actor), actor_data_quark); - - if (G_UNLIKELY (actor_data_quark == 0)) - actor_data_quark = g_quark_from_static_string (ACTOR_DATA_KEY); - - if (G_UNLIKELY (!priv)) - { - priv = g_new0 (ActorPrivate, 1); - - g_object_set_qdata_full (G_OBJECT (actor), - actor_data_quark, priv, - free_actor_private); - } - - return priv; -} - -static ClutterTimeline * -actor_animate (ClutterActor *actor, - ClutterAnimationMode mode, - guint duration, - const gchar *first_property, - ...) -{ - va_list args; - ClutterTransition *transition; - - clutter_actor_save_easing_state (actor); - clutter_actor_set_easing_mode (actor, mode); - clutter_actor_set_easing_duration (actor, duration); - - va_start (args, first_property); - g_object_set_valist (G_OBJECT (actor), first_property, args); - va_end (args); - - transition = clutter_actor_get_transition (actor, first_property); - - clutter_actor_restore_easing_state (actor); - - return CLUTTER_TIMELINE (transition); -} - -static void -on_switch_workspace_effect_complete (ClutterTimeline *timeline, gpointer data) -{ - MetaPlugin *plugin = META_PLUGIN (data); - MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (plugin)->priv; - MetaDisplay *display = meta_plugin_get_display (plugin); - GList *l = meta_get_window_actors (display); - - while (l) - { - ClutterActor *a = l->data; - MetaWindowActor *window_actor = META_WINDOW_ACTOR (a); - ActorPrivate *apriv = get_actor_private (window_actor); - - if (apriv->orig_parent) - { - g_object_ref (a); - clutter_actor_remove_child (clutter_actor_get_parent (a), a); - clutter_actor_add_child (apriv->orig_parent, a); - g_object_unref (a); - apriv->orig_parent = NULL; - } - - l = l->next; - } - - clutter_actor_destroy (priv->desktop1); - clutter_actor_destroy (priv->desktop2); - - priv->tml_switch_workspace1 = NULL; - priv->tml_switch_workspace2 = NULL; - priv->desktop1 = NULL; - priv->desktop2 = NULL; - - meta_plugin_switch_workspace_completed (plugin); -} - -static void -on_monitors_changed (MetaMonitorManager *monitor_manager, - MetaPlugin *plugin) -{ - MetaDefaultPlugin *self = META_DEFAULT_PLUGIN (plugin); - MetaDisplay *display = meta_plugin_get_display (plugin); - - int i, n; - GRand *rand = g_rand_new_with_seed (123456); - - clutter_actor_destroy_all_children (self->priv->background_group); - - n = meta_display_get_n_monitors (display); - for (i = 0; i < n; i++) - { - MetaBackgroundContent *background_content; - ClutterContent *content; - MetaRectangle rect; - ClutterActor *background_actor; - MetaBackground *background; - uint8_t red; - uint8_t green; - uint8_t blue; - ClutterColor color; - - meta_display_get_monitor_geometry (display, i, &rect); - - background_actor = meta_background_actor_new (display, i); - content = clutter_actor_get_content (background_actor); - background_content = META_BACKGROUND_CONTENT (content); - - clutter_actor_set_position (background_actor, rect.x, rect.y); - clutter_actor_set_size (background_actor, rect.width, rect.height); - - /* Don't use rand() here, mesa calls srand() internally when - parsing the driconf XML, but it's nice if the colors are - reproducible. - */ - - blue = g_rand_int_range (rand, 0, 255); - green = g_rand_int_range (rand, 0, 255); - red = g_rand_int_range (rand, 0, 255); - clutter_color_init (&color, red, green, blue, 255); - - background = meta_background_new (display); - meta_background_set_color (background, &color); - meta_background_content_set_background (background_content, background); - g_object_unref (background); - - meta_background_content_set_vignette (background_content, TRUE, 0.5, 0.5); - - clutter_actor_add_child (self->priv->background_group, background_actor); - } - - g_rand_free (rand); -} - -static void -init_keymap (MetaDefaultPlugin *self) -{ - g_autoptr (GError) error = NULL; - g_autoptr (GDBusProxy) proxy = NULL; - g_autoptr (GVariant) result = NULL; - g_autoptr (GVariant) props = NULL; - g_autofree char *x11_layout = NULL; - g_autofree char *x11_options = NULL; - g_autofree char *x11_variant = NULL; - - proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.freedesktop.locale1", - "/org/freedesktop/locale1", - "org.freedesktop.DBus.Properties", - NULL, - &error); - if (!proxy) - { - g_message ("Failed to acquire org.freedesktop.locale1 proxy: %s, " - "probably running in CI", - error->message); - return; - } - - result = g_dbus_proxy_call_sync (proxy, - "GetAll", - g_variant_new ("(s)", - "org.freedesktop.locale1"), - G_DBUS_CALL_FLAGS_NONE, - 100, - NULL, - &error); - if (!result) - { - g_warning ("Failed to retrieve locale properties: %s", error->message); - return; - } - - props = g_variant_get_child_value (result, 0); - if (!props) - { - g_warning ("No locale properties found"); - return; - } - - if (!g_variant_lookup (props, "X11Layout", "s", &x11_layout)) - x11_layout = g_strdup ("us"); - - if (!g_variant_lookup (props, "X11Options", "s", &x11_options)) - x11_options = g_strdup (""); - - if (!g_variant_lookup (props, "X11Variant", "s", &x11_variant)) - x11_variant = g_strdup (""); - - meta_backend_set_keymap (meta_get_backend (), - x11_layout, x11_variant, x11_options); -} - -static void -start (MetaPlugin *plugin) -{ - MetaDefaultPlugin *self = META_DEFAULT_PLUGIN (plugin); - MetaDisplay *display = meta_plugin_get_display (plugin); - MetaMonitorManager *monitor_manager = meta_monitor_manager_get (); - - self->priv->background_group = meta_background_group_new (); - clutter_actor_insert_child_below (meta_get_window_group_for_display (display), - self->priv->background_group, NULL); - - g_signal_connect (monitor_manager, "monitors-changed", - G_CALLBACK (on_monitors_changed), plugin); - - on_monitors_changed (monitor_manager, plugin); - - if (meta_is_wayland_compositor ()) - init_keymap (self); - - clutter_actor_show (meta_get_stage_for_display (display)); -} - -static void -switch_workspace (MetaPlugin *plugin, - gint from, gint to, - MetaMotionDirection direction) -{ - MetaDisplay *display; - MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (plugin)->priv; - GList *l; - ClutterActor *workspace0 = clutter_actor_new (); - ClutterActor *workspace1 = clutter_actor_new (); - ClutterActor *stage; - int screen_width, screen_height; - - display = meta_plugin_get_display (plugin); - stage = meta_get_stage_for_display (display); - - meta_display_get_size (display, - &screen_width, - &screen_height); - - clutter_actor_set_pivot_point (workspace1, 1.0, 1.0); - clutter_actor_set_position (workspace1, - screen_width, - screen_height); - - clutter_actor_set_scale (workspace1, 0.0, 0.0); - - clutter_actor_add_child (stage, workspace1); - clutter_actor_add_child (stage, workspace0); - - if (from == to) - { - meta_plugin_switch_workspace_completed (plugin); - return; - } - - l = g_list_last (meta_get_window_actors (display)); - - while (l) - { - MetaWindowActor *window_actor = l->data; - ActorPrivate *apriv = get_actor_private (window_actor); - ClutterActor *actor = CLUTTER_ACTOR (window_actor); - MetaWorkspace *workspace; - gint win_workspace; - - workspace = meta_window_get_workspace (meta_window_actor_get_meta_window (window_actor)); - win_workspace = meta_workspace_index (workspace); - - if (win_workspace == to || win_workspace == from) - { - ClutterActor *parent = win_workspace == to ? workspace1 : workspace0; - apriv->orig_parent = clutter_actor_get_parent (actor); - - g_object_ref (actor); - clutter_actor_remove_child (clutter_actor_get_parent (actor), actor); - clutter_actor_add_child (parent, actor); - clutter_actor_show (actor); - clutter_actor_set_child_below_sibling (parent, actor, NULL); - g_object_unref (actor); - } - else if (win_workspace < 0) - { - /* Sticky window */ - apriv->orig_parent = NULL; - } - else - { - /* Window on some other desktop */ - clutter_actor_hide (actor); - apriv->orig_parent = NULL; - } - - l = l->prev; - } - - priv->desktop1 = workspace0; - priv->desktop2 = workspace1; - - priv->tml_switch_workspace1 = actor_animate (workspace0, CLUTTER_EASE_IN_SINE, - SWITCH_TIMEOUT, - "scale-x", 1.0, - "scale-y", 1.0, - NULL); - g_signal_connect (priv->tml_switch_workspace1, - "completed", - G_CALLBACK (on_switch_workspace_effect_complete), - plugin); - - priv->tml_switch_workspace2 = actor_animate (workspace1, CLUTTER_EASE_IN_SINE, - SWITCH_TIMEOUT, - "scale-x", 0.0, - "scale-y", 0.0, - NULL); -} - - -/* - * Minimize effect completion callback; this function restores actor state, and - * calls the manager callback function. - */ -static void -on_minimize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data) -{ - /* - * Must reverse the effect of the effect; must hide it first to ensure - * that the restoration will not be visible. - */ - MetaPlugin *plugin = data->plugin; - ActorPrivate *apriv; - MetaWindowActor *window_actor = META_WINDOW_ACTOR (data->actor); - - apriv = get_actor_private (META_WINDOW_ACTOR (data->actor)); - apriv->tml_minimize = NULL; - - clutter_actor_hide (data->actor); - - /* FIXME - we shouldn't assume the original scale, it should be saved - * at the start of the effect */ - clutter_actor_set_scale (data->actor, 1.0, 1.0); - - /* Now notify the manager that we are done with this effect */ - meta_plugin_minimize_completed (plugin, window_actor); - - g_free (data); -} - -/* - * Simple minimize handler: it applies a scale effect (which must be reversed on - * completion). - */ -static void -minimize (MetaPlugin *plugin, MetaWindowActor *window_actor) -{ - MetaWindowType type; - MetaRectangle icon_geometry; - MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor); - ClutterTimeline *timeline = NULL; - ClutterActor *actor = CLUTTER_ACTOR (window_actor); - - - type = meta_window_get_window_type (meta_window); - - if (!meta_window_get_icon_geometry(meta_window, &icon_geometry)) - { - icon_geometry.x = 0; - icon_geometry.y = 0; - } - - if (type == META_WINDOW_NORMAL) - { - timeline = actor_animate (actor, - CLUTTER_EASE_IN_SINE, - MINIMIZE_TIMEOUT, - "scale-x", 0.0, - "scale-y", 0.0, - "x", (double)icon_geometry.x, - "y", (double)icon_geometry.y, - NULL); - } - - if (timeline) - { - EffectCompleteData *data = g_new0 (EffectCompleteData, 1); - ActorPrivate *apriv = get_actor_private (window_actor); - - apriv->tml_minimize = timeline; - data->plugin = plugin; - data->actor = actor; - g_signal_connect (apriv->tml_minimize, "completed", - G_CALLBACK (on_minimize_effect_complete), - data); - } - else - meta_plugin_minimize_completed (plugin, window_actor); -} - -static void -on_map_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data) -{ - /* - * Must reverse the effect of the effect. - */ - MetaPlugin *plugin = data->plugin; - MetaWindowActor *window_actor = META_WINDOW_ACTOR (data->actor); - ActorPrivate *apriv = get_actor_private (window_actor); - - apriv->tml_map = NULL; - - /* Now notify the manager that we are done with this effect */ - meta_plugin_map_completed (plugin, window_actor); - - g_free (data); -} - -/* - * Simple map handler: it applies a scale effect which must be reversed on - * completion). - */ -static void -map (MetaPlugin *plugin, MetaWindowActor *window_actor) -{ - MetaWindowType type; - ClutterActor *actor = CLUTTER_ACTOR (window_actor); - MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor); - - type = meta_window_get_window_type (meta_window); - - if (type == META_WINDOW_NORMAL) - { - EffectCompleteData *data = g_new0 (EffectCompleteData, 1); - ActorPrivate *apriv = get_actor_private (window_actor); - - clutter_actor_set_pivot_point (actor, 0.5, 0.5); - clutter_actor_set_opacity (actor, 0); - clutter_actor_set_scale (actor, 0.5, 0.5); - clutter_actor_show (actor); - - apriv->tml_map = actor_animate (actor, - CLUTTER_EASE_OUT_QUAD, - MAP_TIMEOUT, - "opacity", 255, - "scale-x", 1.0, - "scale-y", 1.0, - NULL); - data->actor = actor; - data->plugin = plugin; - g_signal_connect (apriv->tml_map, "completed", - G_CALLBACK (on_map_effect_complete), - data); - } - else - meta_plugin_map_completed (plugin, window_actor); -} - -/* - * Destroy effect completion callback; this is a simple effect that requires no - * further action than notifying the manager that the effect is completed. - */ -static void -on_destroy_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data) -{ - MetaPlugin *plugin = data->plugin; - MetaWindowActor *window_actor = META_WINDOW_ACTOR (data->actor); - ActorPrivate *apriv = get_actor_private (window_actor); - - apriv->tml_destroy = NULL; - - meta_plugin_destroy_completed (plugin, window_actor); -} - -/* - * Simple TV-out like effect. - */ -static void -destroy (MetaPlugin *plugin, MetaWindowActor *window_actor) -{ - MetaWindowType type; - ClutterActor *actor = CLUTTER_ACTOR (window_actor); - MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor); - ClutterTimeline *timeline = NULL; - - type = meta_window_get_window_type (meta_window); - - if (type == META_WINDOW_NORMAL) - { - timeline = actor_animate (actor, - CLUTTER_EASE_OUT_QUAD, - DESTROY_TIMEOUT, - "opacity", 0, - "scale-x", 0.8, - "scale-y", 0.8, - NULL); - } - - if (timeline) - { - EffectCompleteData *data = g_new0 (EffectCompleteData, 1); - ActorPrivate *apriv = get_actor_private (window_actor); - - apriv->tml_destroy = timeline; - data->plugin = plugin; - data->actor = actor; - g_signal_connect (apriv->tml_destroy, "completed", - G_CALLBACK (on_destroy_effect_complete), - data); - } - else - meta_plugin_destroy_completed (plugin, window_actor); -} - -/* - * Tile preview private data accessor - */ -static void -free_display_tile_preview (DisplayTilePreview *preview) -{ - - if (G_LIKELY (preview != NULL)) { - clutter_actor_destroy (preview->actor); - g_free (preview); - } -} - -static void -on_display_closing (MetaDisplay *display, - DisplayTilePreview *preview) -{ - free_display_tile_preview (preview); -} - -static DisplayTilePreview * -get_display_tile_preview (MetaDisplay *display) -{ - DisplayTilePreview *preview; - - if (!display_tile_preview_data_quark) - { - display_tile_preview_data_quark = - g_quark_from_static_string (DISPLAY_TILE_PREVIEW_DATA_KEY); - } - - preview = g_object_get_qdata (G_OBJECT (display), - display_tile_preview_data_quark); - if (!preview) - { - preview = g_new0 (DisplayTilePreview, 1); - - preview->actor = clutter_actor_new (); - clutter_actor_set_background_color (preview->actor, CLUTTER_COLOR_Blue); - clutter_actor_set_opacity (preview->actor, 100); - - clutter_actor_add_child (meta_get_window_group_for_display (display), preview->actor); - g_signal_connect (display, - "closing", - G_CALLBACK (on_display_closing), - preview); - g_object_set_qdata (G_OBJECT (display), - display_tile_preview_data_quark, - preview); - } - - return preview; -} - -static void -show_tile_preview (MetaPlugin *plugin, - MetaWindow *window, - MetaRectangle *tile_rect, - int tile_monitor_number) -{ - MetaDisplay *display = meta_plugin_get_display (plugin); - DisplayTilePreview *preview = get_display_tile_preview (display); - ClutterActor *window_actor; - - if (clutter_actor_is_visible (preview->actor) - && preview->tile_rect.x == tile_rect->x - && preview->tile_rect.y == tile_rect->y - && preview->tile_rect.width == tile_rect->width - && preview->tile_rect.height == tile_rect->height) - return; /* nothing to do */ - - clutter_actor_set_position (preview->actor, tile_rect->x, tile_rect->y); - clutter_actor_set_size (preview->actor, tile_rect->width, tile_rect->height); - - clutter_actor_show (preview->actor); - - window_actor = CLUTTER_ACTOR (meta_window_get_compositor_private (window)); - clutter_actor_set_child_below_sibling (clutter_actor_get_parent (preview->actor), - preview->actor, - window_actor); - - preview->tile_rect = *tile_rect; -} - -static void -hide_tile_preview (MetaPlugin *plugin) -{ - MetaDisplay *display = meta_plugin_get_display (plugin); - DisplayTilePreview *preview = get_display_tile_preview (display); - - clutter_actor_hide (preview->actor); -} - -static void -finish_timeline (ClutterTimeline *timeline) -{ - g_object_ref (timeline); - clutter_timeline_stop (timeline); - g_signal_emit_by_name (timeline, "completed", NULL); - g_object_unref (timeline); -} - -static void -kill_switch_workspace (MetaPlugin *plugin) -{ - MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (plugin)->priv; - - if (priv->tml_switch_workspace1) - { - g_object_ref (priv->tml_switch_workspace1); - clutter_timeline_stop (priv->tml_switch_workspace1); - clutter_timeline_stop (priv->tml_switch_workspace2); - g_signal_emit_by_name (priv->tml_switch_workspace1, "completed", NULL); - g_object_unref (priv->tml_switch_workspace1); - } -} - -static void -kill_window_effects (MetaPlugin *plugin, - MetaWindowActor *window_actor) -{ - ActorPrivate *apriv; - - apriv = get_actor_private (window_actor); - - if (apriv->tml_minimize) - finish_timeline (apriv->tml_minimize); - - if (apriv->tml_map) - finish_timeline (apriv->tml_map); - - if (apriv->tml_destroy) - finish_timeline (apriv->tml_destroy); -} - -static const MetaPluginInfo * -plugin_info (MetaPlugin *plugin) -{ - MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (plugin)->priv; - - return &priv->info; -} - -static void -on_dialog_closed (GPid pid, - gint status, - gpointer user_data) -{ - MetaPlugin *plugin = user_data; - gboolean ok; - - ok = g_spawn_check_exit_status (status, NULL); - meta_plugin_complete_display_change (plugin, ok); -} - -static void -confirm_display_change (MetaPlugin *plugin) -{ - GPid pid; - - pid = meta_show_dialog ("--question", - "Does the display look OK?", - "20", - NULL, - "_Keep This Configuration", - "_Restore Previous Configuration", - "preferences-desktop-display", - 0, - NULL, NULL); - - g_child_watch_add (pid, on_dialog_closed, plugin); -} diff --git a/src/compositor/plugins/meson.build b/src/compositor/plugins/meson.build deleted file mode 100644 index 9dd06814d..000000000 --- a/src/compositor/plugins/meson.build +++ /dev/null @@ -1,20 +0,0 @@ -default_plugin_c_args = [ - '-fPIC', - '-DG_LOG_DOMAIN="mutter"', - '-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name()), -] - -default_plugin = shared_module('default', - sources: ['default.c'], - include_directories: mutter_includes, - c_args: default_plugin_c_args, - dependencies: [ - glib_dep, - gtk3_dep, - json_glib_dep, - gsettings_desktop_schemas_dep, - libmutter_clutter_dep, - ], - install_dir: join_paths(pkglibdir, 'plugins'), - install: true, -) diff --git a/src/compositor/region-utils.c b/src/compositor/region-utils.c deleted file mode 100644 index ac4048a98..000000000 --- a/src/compositor/region-utils.c +++ /dev/null @@ -1,458 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * Utilities for region manipulation - * - * Copyright (C) 2010 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 . - */ - -#include "config.h" - -#include "backends/meta-monitor-transform.h" -#include "compositor/region-utils.h" -#include "core/boxes-private.h" - -#include - -#define META_REGION_MAX_STACK_RECTS 256 - -#define META_REGION_CREATE_RECTANGLE_ARRAY_SCOPED(n_rects, rects) \ - g_autofree cairo_rectangle_int_t *G_PASTE(__n, __LINE__) = NULL; \ - if (n_rects < META_REGION_MAX_STACK_RECTS) \ - rects = g_newa (cairo_rectangle_int_t, n_rects); \ - else \ - rects = G_PASTE(__n, __LINE__) = g_new (cairo_rectangle_int_t, n_rects); - -/* MetaRegionBuilder */ - -/* Various algorithms in this file require unioning together a set of rectangles - * that are unsorted or overlap; unioning such a set of rectangles 1-by-1 - * using cairo_region_union_rectangle() produces O(N^2) behavior (if the union - * adds or removes rectangles in the middle of the region, then it has to - * move all the rectangles after that.) To avoid this behavior, MetaRegionBuilder - * creates regions for small groups of rectangles and merges them together in - * a binary tree. - * - * Possible improvement: From a glance at the code, accumulating all the rectangles - * into a flat array and then calling the (not usefully documented) - * cairo_region_create_rectangles() would have the same behavior and would be - * simpler and a bit more efficient. - */ - -/* Optimium performance seems to be with MAX_CHUNK_RECTANGLES=4; 8 is about 10% slower. - * But using 8 may be more robust to systems with slow malloc(). */ -#define MAX_CHUNK_RECTANGLES 8 - -void -meta_region_builder_init (MetaRegionBuilder *builder) -{ - int i; - for (i = 0; i < META_REGION_BUILDER_MAX_LEVELS; i++) - builder->levels[i] = NULL; - builder->n_levels = 1; -} - -void -meta_region_builder_add_rectangle (MetaRegionBuilder *builder, - int x, - int y, - int width, - int height) -{ - cairo_rectangle_int_t rect; - int i; - - if (builder->levels[0] == NULL) - builder->levels[0] = cairo_region_create (); - - rect.x = x; - rect.y = y; - rect.width = width; - rect.height = height; - - cairo_region_union_rectangle (builder->levels[0], &rect); - if (cairo_region_num_rectangles (builder->levels[0]) >= MAX_CHUNK_RECTANGLES) - { - for (i = 1; i < builder->n_levels + 1; i++) - { - if (builder->levels[i] == NULL) - { - if (i < META_REGION_BUILDER_MAX_LEVELS) - { - builder->levels[i] = builder->levels[i - 1]; - builder->levels[i - 1] = NULL; - if (i == builder->n_levels) - builder->n_levels++; - } - - break; - } - else - { - cairo_region_union (builder->levels[i], builder->levels[i - 1]); - cairo_region_destroy (builder->levels[i - 1]); - builder->levels[i - 1] = NULL; - } - } - } -} - -cairo_region_t * -meta_region_builder_finish (MetaRegionBuilder *builder) -{ - cairo_region_t *result = NULL; - int i; - - for (i = 0; i < builder->n_levels; i++) - { - if (builder->levels[i]) - { - if (result == NULL) - result = builder->levels[i]; - else - { - cairo_region_union(result, builder->levels[i]); - cairo_region_destroy (builder->levels[i]); - } - } - } - - if (result == NULL) - result = cairo_region_create (); - - return result; -} - - -/* MetaRegionIterator */ - -void -meta_region_iterator_init (MetaRegionIterator *iter, - cairo_region_t *region) -{ - iter->region = region; - iter->i = 0; - iter->n_rectangles = cairo_region_num_rectangles (region); - iter->line_start = TRUE; - - if (iter->n_rectangles > 1) - { - cairo_region_get_rectangle (region, 0, &iter->rectangle); - cairo_region_get_rectangle (region, 1, &iter->next_rectangle); - - iter->line_end = iter->next_rectangle.y != iter->rectangle.y; - } - else if (iter->n_rectangles > 0) - { - cairo_region_get_rectangle (region, 0, &iter->rectangle); - iter->line_end = TRUE; - } -} - -gboolean -meta_region_iterator_at_end (MetaRegionIterator *iter) -{ - return iter->i >= iter->n_rectangles; -} - -void -meta_region_iterator_next (MetaRegionIterator *iter) -{ - iter->i++; - iter->rectangle = iter->next_rectangle; - iter->line_start = iter->line_end; - - if (iter->i + 1 < iter->n_rectangles) - { - cairo_region_get_rectangle (iter->region, iter->i + 1, &iter->next_rectangle); - iter->line_end = iter->next_rectangle.y != iter->rectangle.y; - } - else - { - iter->line_end = TRUE; - } -} - -cairo_region_t * -meta_region_scale_double (cairo_region_t *region, - double scale, - MetaRoundingStrategy rounding_strategy) -{ - int n_rects, i; - cairo_rectangle_int_t *rects; - cairo_region_t *scaled_region; - - g_return_val_if_fail (scale > 0.0, NULL); - - if (G_APPROX_VALUE (scale, 1.f, FLT_EPSILON)) - return cairo_region_copy (region); - - n_rects = cairo_region_num_rectangles (region); - META_REGION_CREATE_RECTANGLE_ARRAY_SCOPED (n_rects, rects); - for (i = 0; i < n_rects; i++) - { - cairo_region_get_rectangle (region, i, &rects[i]); - - meta_rectangle_scale_double (&rects[i], scale, rounding_strategy, - &rects[i]); - } - - scaled_region = cairo_region_create_rectangles (rects, n_rects); - - return scaled_region; -} - -cairo_region_t * -meta_region_scale (cairo_region_t *region, int scale) -{ - int n_rects, i; - cairo_rectangle_int_t *rects; - cairo_region_t *scaled_region; - - if (scale == 1) - return cairo_region_copy (region); - - n_rects = cairo_region_num_rectangles (region); - META_REGION_CREATE_RECTANGLE_ARRAY_SCOPED (n_rects, rects); - for (i = 0; i < n_rects; i++) - { - cairo_region_get_rectangle (region, i, &rects[i]); - rects[i].x *= scale; - rects[i].y *= scale; - rects[i].width *= scale; - rects[i].height *= scale; - } - - scaled_region = cairo_region_create_rectangles (rects, n_rects); - - return scaled_region; -} - -static void -add_expanded_rect (MetaRegionBuilder *builder, - int x, - int y, - int width, - int height, - int x_amount, - int y_amount, - gboolean flip) -{ - if (flip) - meta_region_builder_add_rectangle (builder, - y - y_amount, x - x_amount, - height + 2 * y_amount, width + 2 * x_amount); - else - meta_region_builder_add_rectangle (builder, - x - x_amount, y - y_amount, - width + 2 * x_amount, height + 2 * y_amount); -} - -static cairo_region_t * -expand_region (cairo_region_t *region, - int x_amount, - int y_amount, - gboolean flip) -{ - MetaRegionBuilder builder; - int n; - int i; - - meta_region_builder_init (&builder); - - n = cairo_region_num_rectangles (region); - for (i = 0; i < n; i++) - { - cairo_rectangle_int_t rect; - - cairo_region_get_rectangle (region, i, &rect); - add_expanded_rect (&builder, - rect.x, rect.y, rect.width, rect.height, - x_amount, y_amount, flip); - } - - return meta_region_builder_finish (&builder); -} - -/* This computes a (clipped version) of the inverse of the region - * and expands it by the given amount */ -static cairo_region_t * -expand_region_inverse (cairo_region_t *region, - int x_amount, - int y_amount, - gboolean flip) -{ - MetaRegionBuilder builder; - MetaRegionIterator iter; - cairo_rectangle_int_t extents; - - int last_x; - - meta_region_builder_init (&builder); - - cairo_region_get_extents (region, &extents); - add_expanded_rect (&builder, - extents.x, extents.y - 1, extents.width, 1, - x_amount, y_amount, flip); - add_expanded_rect (&builder, - extents.x - 1, extents.y, 1, extents.height, - x_amount, y_amount, flip); - add_expanded_rect (&builder, - extents.x + extents.width, extents.y, 1, extents.height, - x_amount, y_amount, flip); - add_expanded_rect (&builder, - extents.x, extents.y + extents.height, extents.width, 1, - x_amount, y_amount, flip); - - last_x = extents.x; - for (meta_region_iterator_init (&iter, region); - !meta_region_iterator_at_end (&iter); - meta_region_iterator_next (&iter)) - { - if (iter.rectangle.x > last_x) - add_expanded_rect (&builder, - last_x, iter.rectangle.y, - iter.rectangle.x - last_x, iter.rectangle.height, - x_amount, y_amount, flip); - - if (iter.line_end) - { - if (extents.x + extents.width > iter.rectangle.x + iter.rectangle.width) - add_expanded_rect (&builder, - iter.rectangle.x + iter.rectangle.width, iter.rectangle.y, - (extents.x + extents.width) - (iter.rectangle.x + iter.rectangle.width), iter.rectangle.height, - x_amount, y_amount, flip); - last_x = extents.x; - } - else - last_x = iter.rectangle.x + iter.rectangle.width; - } - - return meta_region_builder_finish (&builder); -} - -/** - * meta_make_border_region: - * @region: a #cairo_region_t - * @x_amount: distance from the border to extend horizontally - * @y_amount: distance from the border to extend vertically - * @flip: if true, the result is computed with x and y interchanged - * - * Computes the "border region" of a given region, which is roughly - * speaking the set of points near the boundary of the region. If we - * define the operation of growing a region as computing the set of - * points within a given manhattan distance of the region, then the - * border is 'grow(region) intersect grow(inverse(region))'. - * - * If we create an image by filling the region with a solid color, - * the border is the region affected by blurring the region. - * - * Return value: a new region which is the border of the given region - */ -cairo_region_t * -meta_make_border_region (cairo_region_t *region, - int x_amount, - int y_amount, - gboolean flip) -{ - cairo_region_t *border_region; - cairo_region_t *inverse_region; - - border_region = expand_region (region, x_amount, y_amount, flip); - inverse_region = expand_region_inverse (region, x_amount, y_amount, flip); - cairo_region_intersect (border_region, inverse_region); - cairo_region_destroy (inverse_region); - - return border_region; -} - -cairo_region_t * -meta_region_transform (const cairo_region_t *region, - MetaMonitorTransform transform, - int width, - int height) -{ - int n_rects, i; - cairo_rectangle_int_t *rects; - cairo_region_t *transformed_region; - - if (transform == META_MONITOR_TRANSFORM_NORMAL) - return cairo_region_copy (region); - - n_rects = cairo_region_num_rectangles (region); - META_REGION_CREATE_RECTANGLE_ARRAY_SCOPED (n_rects, rects); - for (i = 0; i < n_rects; i++) - { - cairo_region_get_rectangle (region, i, &rects[i]); - - meta_rectangle_transform (&rects[i], - transform, - width, - height, - &rects[i]); - } - - transformed_region = cairo_region_create_rectangles (rects, n_rects); - - return transformed_region; -} - -cairo_region_t * -meta_region_crop_and_scale (cairo_region_t *region, - graphene_rect_t *src_rect, - int dst_width, - int dst_height) -{ - int n_rects, i; - cairo_rectangle_int_t *rects; - cairo_region_t *viewport_region; - - if (G_APPROX_VALUE (src_rect->size.width, dst_width, FLT_EPSILON) && - G_APPROX_VALUE (src_rect->size.height, dst_height, FLT_EPSILON) && - G_APPROX_VALUE (roundf (src_rect->origin.x), - src_rect->origin.x, FLT_EPSILON) && - G_APPROX_VALUE (roundf (src_rect->origin.y), - src_rect->origin.y, FLT_EPSILON)) - { - viewport_region = cairo_region_copy (region); - - if (!G_APPROX_VALUE (src_rect->origin.x, 0, FLT_EPSILON) || - !G_APPROX_VALUE (src_rect->origin.y, 0, FLT_EPSILON)) - { - cairo_region_translate (viewport_region, - (int) src_rect->origin.x, - (int) src_rect->origin.y); - } - - return viewport_region; - } - - n_rects = cairo_region_num_rectangles (region); - META_REGION_CREATE_RECTANGLE_ARRAY_SCOPED (n_rects, rects); - for (i = 0; i < n_rects; i++) - { - cairo_region_get_rectangle (region, i, &rects[i]); - - meta_rectangle_crop_and_scale (&rects[i], - src_rect, - dst_width, - dst_height, - &rects[i]); - } - - viewport_region = cairo_region_create_rectangles (rects, n_rects); - - return viewport_region; -} diff --git a/src/compositor/region-utils.h b/src/compositor/region-utils.h deleted file mode 100644 index 298c5540e..000000000 --- a/src/compositor/region-utils.h +++ /dev/null @@ -1,119 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * Utilities for region manipulation - * - * Copyright (C) 2010 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 . - */ - -#ifndef __META_REGION_UTILS_H__ -#define __META_REGION_UTILS_H__ - -#include -#include - -#include "backends/meta-backend-types.h" -#include "clutter/clutter.h" -#include "core/boxes-private.h" - -/** - * MetaRegionIterator: - * @region: region being iterated - * @rectangle: current rectangle - * @line_start: whether the current rectangle starts a horizontal band - * @line_end: whether the current rectangle ends a horizontal band - * - * cairo_region_t is a yx banded region; sometimes its useful to iterate through - * such a region treating the start and end of each horizontal band in a distinct - * fashion. - * - * Usage: - * - * MetaRegionIterator iter; - * for (meta_region_iterator_init (&iter, region); - * !meta_region_iterator_at_end (&iter); - * meta_region_iterator_next (&iter)) - * { - * [ Use iter.rectangle, iter.line_start, iter.line_end ] - * } - */ -typedef struct _MetaRegionIterator MetaRegionIterator; - -struct _MetaRegionIterator { - cairo_region_t *region; - cairo_rectangle_int_t rectangle; - gboolean line_start; - gboolean line_end; - int i; - - /*< private >*/ - int n_rectangles; - cairo_rectangle_int_t next_rectangle; -}; - -typedef struct _MetaRegionBuilder MetaRegionBuilder; - -#define META_REGION_BUILDER_MAX_LEVELS 16 -struct _MetaRegionBuilder { - /* To merge regions in binary tree order, we need to keep track of - * the regions that we've already merged together at different - * levels of the tree. We fill in an array in the pattern: - * - * |a | - * |b |a | - * |c | |ab | - * |d |c |ab | - * |e | | |abcd| - */ - cairo_region_t *levels[META_REGION_BUILDER_MAX_LEVELS]; - int n_levels; -}; - -void meta_region_builder_init (MetaRegionBuilder *builder); -void meta_region_builder_add_rectangle (MetaRegionBuilder *builder, - int x, - int y, - int width, - int height); -cairo_region_t * meta_region_builder_finish (MetaRegionBuilder *builder); - -void meta_region_iterator_init (MetaRegionIterator *iter, - cairo_region_t *region); -gboolean meta_region_iterator_at_end (MetaRegionIterator *iter); -void meta_region_iterator_next (MetaRegionIterator *iter); - -cairo_region_t * meta_region_scale (cairo_region_t *region, - int scale); - -cairo_region_t * meta_region_scale_double (cairo_region_t *region, - double scale, - MetaRoundingStrategy rounding_strategy); - -cairo_region_t * meta_make_border_region (cairo_region_t *region, - int x_amount, - int y_amount, - gboolean flip); - -cairo_region_t * meta_region_transform (const cairo_region_t *region, - MetaMonitorTransform transform, - int width, - int height); - -cairo_region_t * meta_region_crop_and_scale (cairo_region_t *region, - graphene_rect_t *src_rect, - int dst_width, - int dst_height); - -#endif /* __META_REGION_UTILS_H__ */ diff --git a/src/core/bell.c b/src/core/bell.c deleted file mode 100644 index f0c6f9463..000000000 --- a/src/core/bell.c +++ /dev/null @@ -1,209 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter visual bell */ - -/* - * Copyright (C) 2002 Sun Microsystems Inc. - * Copyright (C) 2005, 2006 Elijah Newren - * - * 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 . - */ - -/* - * SECTION:bell - * @short_description: Ring the bell or flash the screen - * - * Sometimes, X programs "ring the bell", whatever that means. Mutter lets - * the user configure the bell to be audible or visible (aka visual), and - * if it's visual it can be configured to be frame-flash or fullscreen-flash. - * We never get told about audible bells; X handles them just fine by itself. - * - * Visual bells come in at meta_bell_notify(), which checks we are actually - * in visual mode and calls through to bell_visual_notify(). That - * function then checks what kind of visual flash you like, and calls either - * bell_flash_fullscreen()-- which calls bell_flash_screen() to do - * its work-- or bell_flash_frame(), which flashes the focused window - * using bell_flash_window(), unless there is no such window, in - * which case it flashes the screen instead. - * - * The visual bell was the result of a discussion in Bugzilla here: - * . - * - * Several of the functions in this file are ifdeffed out entirely if we are - * found not to have the XKB extension, which is required to do these clever - * things with bells; some others are entirely no-ops in that case. - */ - -#include "config.h" - -#include "core/bell.h" - -#include "compositor/compositor-private.h" -#include "core/util-private.h" -#include "core/window-private.h" -#include "meta/compositor.h" - -G_DEFINE_TYPE (MetaBell, meta_bell, G_TYPE_OBJECT) - -enum -{ - IS_AUDIBLE_CHANGED, - LAST_SIGNAL -}; - -static guint bell_signals [LAST_SIGNAL] = { 0 }; - -static void -prefs_changed_callback (MetaPreference pref, - gpointer data) -{ - MetaBell *bell = data; - - if (pref == META_PREF_AUDIBLE_BELL) - { - g_signal_emit (bell, bell_signals[IS_AUDIBLE_CHANGED], 0, - meta_prefs_bell_is_audible ()); - } -} - -static void -meta_bell_finalize (GObject *object) -{ - MetaBell *bell = META_BELL (object); - - meta_prefs_remove_listener (prefs_changed_callback, bell); - - G_OBJECT_CLASS (meta_bell_parent_class)->finalize (object); -} - -static void -meta_bell_class_init (MetaBellClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_bell_finalize; - - bell_signals[IS_AUDIBLE_CHANGED] = - g_signal_new ("is-audible-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 1, - G_TYPE_BOOLEAN); -} - -static void -meta_bell_init (MetaBell *bell) -{ - meta_prefs_add_listener (prefs_changed_callback, bell); -} - -MetaBell * -meta_bell_new (MetaDisplay *display) -{ - return g_object_new (META_TYPE_BELL, NULL); -} - -/** - * bell_flash_fullscreen: - * @display: The display the event came in on - * @xkb_ev: The bell event - * - * Flashes one screen, or all screens, in response to a bell event. - * If the event is on a particular window, flash the screen that - * window is on. Otherwise, flash every screen on this display. - * - * If the configure script found we had no XKB, this does not exist. - */ -static void -bell_flash_fullscreen (MetaDisplay *display) -{ - meta_compositor_flash_display (display->compositor, display); -} - -static void -bell_flash_window (MetaWindow *window) -{ - meta_compositor_flash_window (window->display->compositor, window); -} - -/** - * bell_flash_frame: - * @display: The display the bell event came in on - * @xkb_ev: The bell event we just received - * - * Flashes the frame of the focused window. If there is no focused window, - * flashes the screen. - */ -static void -bell_flash_frame (MetaDisplay *display, - MetaWindow *window) -{ - if (window) - bell_flash_window (window); - else - bell_flash_fullscreen (display); -} - -/** - * bell_visual_notify: - * @display: The display the bell event came in on - * @xkb_ev: The bell event we just received - * - * Gives the user some kind of visual bell substitute, in response to a - * bell event. What this is depends on the "visual bell type" pref. - */ -static void -bell_visual_notify (MetaDisplay *display, - MetaWindow *window) -{ - switch (meta_prefs_get_visual_bell_type ()) - { - case G_DESKTOP_VISUAL_BELL_FULLSCREEN_FLASH: - bell_flash_fullscreen (display); - break; - case G_DESKTOP_VISUAL_BELL_FRAME_FLASH: - bell_flash_frame (display, window); - break; - } -} - -static gboolean -bell_audible_notify (MetaDisplay *display, - MetaWindow *window) -{ - MetaSoundPlayer *player; - - player = meta_display_get_sound_player (display); - meta_sound_player_play_from_theme (player, - "bell-window-system", - _("Bell event"), - NULL); - return TRUE; -} - -gboolean -meta_bell_notify (MetaDisplay *display, - MetaWindow *window) -{ - /* flash something */ - if (meta_prefs_get_visual_bell ()) - bell_visual_notify (display, window); - - if (meta_prefs_bell_is_audible ()) - return bell_audible_notify (display, window); - - return TRUE; -} diff --git a/src/core/bell.h b/src/core/bell.h deleted file mode 100644 index f86cbb7c2..000000000 --- a/src/core/bell.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2002 Sun Microsystems 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 . - */ - -#include "core/display-private.h" -#include "core/frame.h" - -struct _MetaBell -{ - GObject parent; -}; - -#define META_TYPE_BELL (meta_bell_get_type ()) -G_DECLARE_FINAL_TYPE (MetaBell, meta_bell, META, BELL, GObject) - -MetaBell * meta_bell_new (MetaDisplay *display); - -/** - * meta_bell_notify: - * @display: The display the bell event came in on - * @window: The window the bell event was received on - * - * Gives the user some kind of aural or visual feedback, such as a bell sound - * or flash. What type of feedback is invoked depends on the configuration. - * If the aural feedback could not be invoked, FALSE is returned. - */ -gboolean meta_bell_notify (MetaDisplay *display, - MetaWindow *window); diff --git a/src/core/boxes-private.h b/src/core/boxes-private.h deleted file mode 100644 index d39816495..000000000 --- a/src/core/boxes-private.h +++ /dev/null @@ -1,288 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Simple box operations */ - -/* - * Copyright (C) 2005, 2006 Elijah Newren - * - * 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 . - */ - -#ifndef META_BOXES_PRIVATE_H -#define META_BOXES_PRIVATE_H - -#include - -#include "backends/meta-backend-types.h" -#include "core/util-private.h" -#include "meta/boxes.h" -#include "meta/common.h" - -#define BOX_LEFT(box) ((box).x) /* Leftmost pixel of rect */ -#define BOX_RIGHT(box) ((box).x + (box).width) /* One pixel past right */ -#define BOX_TOP(box) ((box).y) /* Topmost pixel of rect */ -#define BOX_BOTTOM(box) ((box).y + (box).height) /* One pixel past bottom */ - -typedef enum -{ - FIXED_DIRECTION_NONE = 0, - FIXED_DIRECTION_X = 1 << 0, - FIXED_DIRECTION_Y = 1 << 1, -} FixedDirections; - -typedef enum _MetaRoundingStrategy -{ - META_ROUNDING_STRATEGY_SHRINK, - META_ROUNDING_STRATEGY_GROW, - META_ROUNDING_STRATEGY_ROUND, -} MetaRoundingStrategy; - -/* Output functions -- note that the output buffer had better be big enough: - * rect_to_string: RECT_LENGTH - * region_to_string: (RECT_LENGTH+strlen(separator_string)) * - * g_list_length (region) - * edge_to_string: EDGE_LENGTH - * edge_list_to_...: (EDGE_LENGTH+strlen(separator_string)) * - * g_list_length (edge_list) - */ -#define RECT_LENGTH 27 -#define EDGE_LENGTH 37 -char* meta_rectangle_to_string (const MetaRectangle *rect, - char *output); -char* meta_rectangle_region_to_string (GList *region, - const char *separator_string, - char *output); -char* meta_rectangle_edge_to_string (const MetaEdge *edge, - char *output); -char* meta_rectangle_edge_list_to_string ( - GList *edge_list, - const char *separator_string, - char *output); - -/* Resize old_rect to the given new_width and new_height, but store the - * result in rect. NOTE THAT THIS IS RESIZE ONLY SO IT CANNOT BE USED FOR - * A MOVERESIZE OPERATION (that simplifies the routine a little bit as it - * means there's no difference between META_GRAVITY_NORTH_WEST and - * META_GRAVITY_STATIC. Also, I lied a little bit--technically, you could use - * it in a MoveResize operation if you muck with old_rect just right). - */ -META_EXPORT_TEST -void meta_rectangle_resize_with_gravity (const MetaRectangle *old_rect, - MetaRectangle *rect, - MetaGravity gravity, - int new_width, - int new_height); - -/* find a list of rectangles with the property that a window is contained - * in the given region if and only if it is contained in one of the - * rectangles in the list. - * - * In this case, the region is given by taking basic_rect, removing from - * it the intersections with all the rectangles in the all_struts list, - * then expanding all the rectangles in the resulting list by the given - * amounts on each side. - * - * See boxes.c for more details. - */ -META_EXPORT_TEST -GList* meta_rectangle_get_minimal_spanning_set_for_region ( - const MetaRectangle *basic_rect, - const GSList *all_struts); - -/* Expand all rectangles in region by the given amount on each side */ -GList* meta_rectangle_expand_region (GList *region, - const int left_expand, - const int right_expand, - const int top_expand, - const int bottom_expand); -/* Same as for meta_rectangle_expand_region except that rectangles not at - * least min_x or min_y in size are not expanded in that direction - */ -GList* meta_rectangle_expand_region_conditionally ( - GList *region, - const int left_expand, - const int right_expand, - const int top_expand, - const int bottom_expand, - const int min_x, - const int min_y); - -/* Expand rect in direction to the size of expand_to, and then clip out any - * overlapping struts oriented orthogonal to the expansion direction. (Think - * horizontal or vertical maximization) - */ -META_EXPORT_TEST -void meta_rectangle_expand_to_avoiding_struts ( - MetaRectangle *rect, - const MetaRectangle *expand_to, - const MetaDirection direction, - const GSList *all_struts); - -/* Free the list created by - * meta_rectangle_get_minimal_spanning_set_for_region() - * or - * meta_rectangle_find_onscreen_edges () - * or - * meta_rectangle_find_nonintersected_monitor_edges() - */ -META_EXPORT_TEST -void meta_rectangle_free_list_and_elements (GList *filled_list); - -/* could_fit_in_region determines whether one of the spanning_rects is - * big enough to contain rect. contained_in_region checks whether one - * actually contains it. - */ -META_EXPORT_TEST -gboolean meta_rectangle_could_fit_in_region ( - const GList *spanning_rects, - const MetaRectangle *rect); - -META_EXPORT_TEST -gboolean meta_rectangle_contained_in_region ( - const GList *spanning_rects, - const MetaRectangle *rect); - -META_EXPORT_TEST -gboolean meta_rectangle_overlaps_with_region ( - const GList *spanning_rects, - const MetaRectangle *rect); - -/* Make the rectangle small enough to fit into one of the spanning_rects, - * but make it no smaller than min_size. - */ -META_EXPORT_TEST -void meta_rectangle_clamp_to_fit_into_region ( - const GList *spanning_rects, - FixedDirections fixed_directions, - MetaRectangle *rect, - const MetaRectangle *min_size); - -/* Clip the rectangle so that it fits into one of the spanning_rects, assuming - * it overlaps with at least one of them - */ -META_EXPORT_TEST -void meta_rectangle_clip_to_region (const GList *spanning_rects, - FixedDirections fixed_directions, - MetaRectangle *rect); - -/* Shove the rectangle into one of the spanning_rects, assuming it fits in - * one of them. - */ -META_EXPORT_TEST -void meta_rectangle_shove_into_region( - const GList *spanning_rects, - FixedDirections fixed_directions, - MetaRectangle *rect); - -/* Finds the point on the line connecting (x1,y1) to (x2,y2) which is closest - * to (px, py). Useful for finding an optimal rectangle size when given a - * range between two sizes that are all candidates. - */ -META_EXPORT_TEST -void meta_rectangle_find_linepoint_closest_to_point (double x1, double y1, - double x2, double y2, - double px, double py, - double *valx, double *valy); - -/***************************************************************************/ -/* */ -/* Switching gears to code for edges instead of just rectangles */ -/* */ -/***************************************************************************/ - -/* Return whether an edge overlaps or is adjacent to the rectangle in the - * nonzero-width dimension of the edge. - */ -META_EXPORT_TEST -gboolean meta_rectangle_edge_aligns (const MetaRectangle *rect, - const MetaEdge *edge); - -/* Compare two edges, so that sorting functions can put a list of edges in - * canonical order. - */ -META_EXPORT_TEST -gint meta_rectangle_edge_cmp (gconstpointer a, gconstpointer b); - -/* Compare two edges, so that sorting functions can put a list of edges in - * order. This function doesn't separate left edges first, then right edges, - * etc., but rather compares only upon location. - */ -META_EXPORT_TEST -gint meta_rectangle_edge_cmp_ignore_type (gconstpointer a, gconstpointer b); - -/* Removes an parts of edges in the given list that intersect any box in the - * given rectangle list. Returns the result. - */ -GList* meta_rectangle_remove_intersections_with_boxes_from_edges ( - GList *edges, - const GSList *rectangles); - -/* Finds all the edges of an onscreen region, returning a GList* of - * MetaEdgeRect's. - */ -META_EXPORT_TEST -GList* meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect, - const GSList *all_struts); - -/* Finds edges between adjacent monitors which are not covered by the given - * struts. - */ -META_EXPORT_TEST -GList* meta_rectangle_find_nonintersected_monitor_edges ( - const GList *monitor_rects, - const GSList *all_struts); - -META_EXPORT_TEST -gboolean meta_rectangle_is_adjacent_to (MetaRectangle *rect, - MetaRectangle *other); - -META_EXPORT_TEST -void meta_rectangle_scale_double (const MetaRectangle *rect, - double scale, - MetaRoundingStrategy rounding_strategy, - MetaRectangle *dest); - -static inline graphene_rect_t -meta_rectangle_to_graphene_rect (MetaRectangle *rect) -{ - return (graphene_rect_t) { - .origin = { - .x = rect->x, - .y = rect->y - }, - .size = { - .width = rect->width, - .height = rect->height - } - }; -} - -META_EXPORT_TEST -void meta_rectangle_transform (const MetaRectangle *rect, - MetaMonitorTransform transform, - int width, - int height, - MetaRectangle *dest); - -void meta_rectangle_from_graphene_rect (const graphene_rect_t *rect, - MetaRoundingStrategy rounding_strategy, - MetaRectangle *dest); - -void meta_rectangle_crop_and_scale (const MetaRectangle *rect, - graphene_rect_t *src_rect, - int dst_width, - int dst_height, - MetaRectangle *dest); - -#endif /* META_BOXES_PRIVATE_H */ diff --git a/src/core/boxes.c b/src/core/boxes.c deleted file mode 100644 index 9a9633e05..000000000 --- a/src/core/boxes.c +++ /dev/null @@ -1,2183 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/** - * SECTION:boxes - * @Title: MetaRectangle - * @Short_Description: Simple box operations - */ - -/* - * Copyright (C) 2005, 2006 Elijah Newren - * [meta_rectangle_intersect() is copyright the GTK+ Team according to Havoc, - * see gdkrectangle.c. As far as Havoc knows, he probably wrote - * meta_rectangle_equal(), and I'm guessing it's (C) Red Hat. So...] - * Copyright (C) 1995-2000 GTK+ Team - * Copyright (C) 2002 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 . - */ - -#include "config.h" - -#include "backends/meta-monitor-transform.h" -#include "core/boxes-private.h" - -#include -#include - -#include "meta/util.h" - -/* It would make sense to use GSlice here, but until we clean up the - * rest of this file and the internal API to use these functions, we - * leave it using g_malloc()/g_free() for consistency. - */ - -MetaRectangle * -meta_rectangle_copy (const MetaRectangle *rect) -{ - return g_memdup2 (rect, sizeof (MetaRectangle)); -} - -void -meta_rectangle_free (MetaRectangle *rect) -{ - g_free (rect); -} - -G_DEFINE_BOXED_TYPE (MetaRectangle, meta_rectangle, - meta_rectangle_copy, meta_rectangle_free); - -char* -meta_rectangle_to_string (const MetaRectangle *rect, - char *output) -{ - /* 25 chars: 2 commas, space, plus, trailing \0 + 5 for each digit. - * Should be more than enough space. Note that of this space, the - * trailing \0 will be overwritten for all but the last rectangle. - */ - g_snprintf (output, RECT_LENGTH, "%d,%d +%d,%d", - rect->x, rect->y, rect->width, rect->height); - - return output; -} - -char* -meta_rectangle_region_to_string (GList *region, - const char *separator_string, - char *output) -{ - /* 27 chars: 2 commas, 2 square brackets, space, plus, trailing \0 + 5 - * for each digit. Should be more than enough space. Note that of this - * space, the trailing \0 will be overwritten for all but the last - * rectangle. - */ - char rect_string[RECT_LENGTH]; - - GList *tmp = region; - char *cur = output; - - if (region == NULL) - g_snprintf (output, 10, "(EMPTY)"); - - while (tmp) - { - MetaRectangle *rect = tmp->data; - g_snprintf (rect_string, RECT_LENGTH, "[%d,%d +%d,%d]", - rect->x, rect->y, rect->width, rect->height); - cur = g_stpcpy (cur, rect_string); - tmp = tmp->next; - if (tmp) - cur = g_stpcpy (cur, separator_string); - } - - return output; -} - -char* -meta_rectangle_edge_to_string (const MetaEdge *edge, - char *output) -{ - /* 25 chars: 2 commas, space, plus, trailing \0 + 5 for each digit. - * Should be more than enough space. Note that of this space, the - * trailing \0 will be overwritten for all but the last rectangle. - * - * Plus 2 for parenthesis, 4 for 2 more numbers, 2 more commas, and - * 2 more spaces, for a total of 10 more. - */ - g_snprintf (output, EDGE_LENGTH, "[%d,%d +%d,%d], %2d, %2d", - edge->rect.x, edge->rect.y, edge->rect.width, edge->rect.height, - edge->side_type, edge->edge_type); - - return output; -} - -char* -meta_rectangle_edge_list_to_string (GList *edge_list, - const char *separator_string, - char *output) -{ - /* 27 chars: 2 commas, 2 square brackets, space, plus, trailing \0 + 5 for - * each digit. Should be more than enough space. Note that of this - * space, the trailing \0 will be overwritten for all but the last - * rectangle. - * - * Plus 2 for parenthesis, 4 for 2 more numbers, 2 more commas, and - * 2 more spaces, for a total of 10 more. - */ - char rect_string[EDGE_LENGTH]; - - char *cur = output; - GList *tmp = edge_list; - - if (edge_list == NULL) - g_snprintf (output, 10, "(EMPTY)"); - - while (tmp) - { - MetaEdge *edge = tmp->data; - MetaRectangle *rect = &edge->rect; - g_snprintf (rect_string, EDGE_LENGTH, "([%d,%d +%d,%d], %2d, %2d)", - rect->x, rect->y, rect->width, rect->height, - edge->side_type, edge->edge_type); - cur = g_stpcpy (cur, rect_string); - tmp = tmp->next; - if (tmp) - cur = g_stpcpy (cur, separator_string); - } - - return output; -} - -MetaRectangle -meta_rect (int x, int y, int width, int height) -{ - MetaRectangle temporary; - temporary.x = x; - temporary.y = y; - temporary.width = width; - temporary.height = height; - - return temporary; -} - -int -meta_rectangle_area (const MetaRectangle *rect) -{ - g_return_val_if_fail (rect != NULL, 0); - return rect->width * rect->height; -} - -/** - * meta_rectangle_intersect: - * @src1: a #MetaRectangle - * @src2: another #MetaRectangle - * @dest: (out caller-allocates): an empty #MetaRectangle, to be filled - * with the coordinates of the intersection. - * - * Returns: TRUE is some intersection exists and is not degenerate, FALSE - * otherwise. - */ -gboolean -meta_rectangle_intersect (const MetaRectangle *src1, - const MetaRectangle *src2, - MetaRectangle *dest) -{ - int dest_x, dest_y; - int dest_w, dest_h; - int return_val; - - g_return_val_if_fail (src1 != NULL, FALSE); - g_return_val_if_fail (src2 != NULL, FALSE); - g_return_val_if_fail (dest != NULL, FALSE); - - return_val = FALSE; - - dest_x = MAX (src1->x, src2->x); - dest_y = MAX (src1->y, src2->y); - dest_w = MIN (src1->x + src1->width, src2->x + src2->width) - dest_x; - dest_h = MIN (src1->y + src1->height, src2->y + src2->height) - dest_y; - - if (dest_w > 0 && dest_h > 0) - { - dest->x = dest_x; - dest->y = dest_y; - dest->width = dest_w; - dest->height = dest_h; - return_val = TRUE; - } - else - { - dest->width = 0; - dest->height = 0; - } - - return return_val; -} - -gboolean -meta_rectangle_equal (const MetaRectangle *src1, - const MetaRectangle *src2) -{ - return ((src1->x == src2->x) && - (src1->y == src2->y) && - (src1->width == src2->width) && - (src1->height == src2->height)); -} - -/** - * meta_rectangle_union: - * @rect1: a #MetaRectangle - * @rect2: another #MetaRectangle - * @dest: (out caller-allocates): an empty #MetaRectangle, to be filled - * with the coordinates of the bounding box. - */ -void -meta_rectangle_union (const MetaRectangle *rect1, - const MetaRectangle *rect2, - MetaRectangle *dest) -{ - int dest_x, dest_y; - int dest_w, dest_h; - - dest_x = rect1->x; - dest_y = rect1->y; - dest_w = rect1->width; - dest_h = rect1->height; - - if (rect2->x < dest_x) - { - dest_w += dest_x - rect2->x; - dest_x = rect2->x; - } - if (rect2->y < dest_y) - { - dest_h += dest_y - rect2->y; - dest_y = rect2->y; - } - if (rect2->x + rect2->width > dest_x + dest_w) - dest_w = rect2->x + rect2->width - dest_x; - if (rect2->y + rect2->height > dest_y + dest_h) - dest_h = rect2->y + rect2->height - dest_y; - - dest->x = dest_x; - dest->y = dest_y; - dest->width = dest_w; - dest->height = dest_h; -} - -gboolean -meta_rectangle_overlap (const MetaRectangle *rect1, - const MetaRectangle *rect2) -{ - g_return_val_if_fail (rect1 != NULL, FALSE); - g_return_val_if_fail (rect2 != NULL, FALSE); - - return !((rect1->x + rect1->width <= rect2->x) || - (rect2->x + rect2->width <= rect1->x) || - (rect1->y + rect1->height <= rect2->y) || - (rect2->y + rect2->height <= rect1->y)); -} - -gboolean -meta_rectangle_vert_overlap (const MetaRectangle *rect1, - const MetaRectangle *rect2) -{ - return (rect1->y < rect2->y + rect2->height && - rect2->y < rect1->y + rect1->height); -} - -gboolean -meta_rectangle_horiz_overlap (const MetaRectangle *rect1, - const MetaRectangle *rect2) -{ - return (rect1->x < rect2->x + rect2->width && - rect2->x < rect1->x + rect1->width); -} - -gboolean -meta_rectangle_could_fit_rect (const MetaRectangle *outer_rect, - const MetaRectangle *inner_rect) -{ - return (outer_rect->width >= inner_rect->width && - outer_rect->height >= inner_rect->height); -} - -gboolean -meta_rectangle_contains_rect (const MetaRectangle *outer_rect, - const MetaRectangle *inner_rect) -{ - return - inner_rect->x >= outer_rect->x && - inner_rect->y >= outer_rect->y && - inner_rect->x + inner_rect->width <= outer_rect->x + outer_rect->width && - inner_rect->y + inner_rect->height <= outer_rect->y + outer_rect->height; -} - -void -meta_rectangle_resize_with_gravity (const MetaRectangle *old_rect, - MetaRectangle *rect, - MetaGravity gravity, - int new_width, - int new_height) -{ - /* FIXME: I'm too deep into this to know whether the below comment is - * still clear or not now that I've moved it out of constraints.c. - * boxes.h has a good comment, but I'm not sure if the below info is also - * helpful on top of that (or whether it has superfluous info). - */ - - /* These formulas may look overly simplistic at first but you can work - * everything out with a left_frame_with, right_frame_width, - * border_width, and old and new client area widths (instead of old total - * width and new total width) and you come up with the same formulas. - * - * Also, note that the reason we can treat META_GRAVITY_NORTH_WEST and - * META_GRAVITY_STATIC the same is because we're not given a location at - * which to place the window--the window was already placed - * appropriately before. So, META_GRAVITY_NORTH_WEST for this function - * means to just leave the upper left corner of the outer window - * where it already is, and META_GRAVITY_STATIC for this function means to - * just leave the upper left corner of the inner window where it - * already is. But leaving either of those two corners where they - * already are will ensure that the other corner is fixed as well - * (since frame size doesn't change)--thus making the two - * equivalent. - */ - - /* First, the x direction */ - switch (gravity) - { - case META_GRAVITY_NORTH_WEST: - case META_GRAVITY_WEST: - case META_GRAVITY_SOUTH_WEST: - rect->x = old_rect->x; - break; - - case META_GRAVITY_NORTH: - case META_GRAVITY_CENTER: - case META_GRAVITY_SOUTH: - /* FIXME: Needing to adjust new_width kind of sucks, but not doing so - * would cause drift. - */ - new_width -= (old_rect->width - new_width) % 2; - rect->x = old_rect->x + (old_rect->width - new_width)/2; - break; - - case META_GRAVITY_NORTH_EAST: - case META_GRAVITY_EAST: - case META_GRAVITY_SOUTH_EAST: - rect->x = old_rect->x + (old_rect->width - new_width); - break; - - case META_GRAVITY_STATIC: - default: - rect->x = old_rect->x; - break; - } - rect->width = new_width; - - /* Next, the y direction */ - switch (gravity) - { - case META_GRAVITY_NORTH_WEST: - case META_GRAVITY_NORTH: - case META_GRAVITY_NORTH_EAST: - rect->y = old_rect->y; - break; - - case META_GRAVITY_WEST: - case META_GRAVITY_CENTER: - case META_GRAVITY_EAST: - /* FIXME: Needing to adjust new_height kind of sucks, but not doing so - * would cause drift. - */ - new_height -= (old_rect->height - new_height) % 2; - rect->y = old_rect->y + (old_rect->height - new_height)/2; - break; - - case META_GRAVITY_SOUTH_WEST: - case META_GRAVITY_SOUTH: - case META_GRAVITY_SOUTH_EAST: - rect->y = old_rect->y + (old_rect->height - new_height); - break; - - case META_GRAVITY_STATIC: - default: - rect->y = old_rect->y; - break; - } - rect->height = new_height; -} - -/* Not so simple helper function for get_minimal_spanning_set_for_region() */ -static GList* -merge_spanning_rects_in_region (GList *region) -{ - /* NOTE FOR ANY OPTIMIZATION PEOPLE OUT THERE: Please see the - * documentation of get_minimal_spanning_set_for_region() for performance - * considerations that also apply to this function. - */ - - GList* compare; - compare = region; - - if (region == NULL) - { - g_warning ("Region to merge was empty! Either you have a some " - "pathological STRUT list or there's a bug somewhere!"); - return NULL; - } - - while (compare && compare->next) - { - MetaRectangle *a = compare->data; - GList *other = compare->next; - - g_assert (a->width > 0 && a->height > 0); - - while (other) - { - MetaRectangle *b = other->data; - GList *delete_me = NULL; - - g_assert (b->width > 0 && b->height > 0); - - /* If a contains b, just remove b */ - if (meta_rectangle_contains_rect (a, b)) - { - delete_me = other; - } - /* If b contains a, just remove a */ - else if (meta_rectangle_contains_rect (b, a)) - { - delete_me = compare; - } - /* If a and b might be mergeable horizontally */ - else if (a->y == b->y && a->height == b->height) - { - /* If a and b overlap */ - if (meta_rectangle_overlap (a, b)) - { - int new_x = MIN (a->x, b->x); - a->width = MAX (a->x + a->width, b->x + b->width) - new_x; - a->x = new_x; - delete_me = other; - } - /* If a and b are adjacent */ - else if (a->x + a->width == b->x || a->x == b->x + b->width) - { - int new_x = MIN (a->x, b->x); - a->width = MAX (a->x + a->width, b->x + b->width) - new_x; - a->x = new_x; - delete_me = other; - } - } - /* If a and b might be mergeable vertically */ - else if (a->x == b->x && a->width == b->width) - { - /* If a and b overlap */ - if (meta_rectangle_overlap (a, b)) - { - int new_y = MIN (a->y, b->y); - a->height = MAX (a->y + a->height, b->y + b->height) - new_y; - a->y = new_y; - delete_me = other; - } - /* If a and b are adjacent */ - else if (a->y + a->height == b->y || a->y == b->y + b->height) - { - int new_y = MIN (a->y, b->y); - a->height = MAX (a->y + a->height, b->y + b->height) - new_y; - a->y = new_y; - delete_me = other; - } - } - - other = other->next; - - /* Delete any rectangle in the list that is no longer wanted */ - if (delete_me != NULL) - { - /* Deleting the rect we compare others to is a little tricker */ - if (compare == delete_me) - { - compare = compare->next; - other = compare->next; - a = compare->data; - } - - /* Okay, we can free it now */ - g_free (delete_me->data); - region = g_list_delete_link (region, delete_me); - } - - } - - compare = compare->next; - } - - return region; -} - -/* Simple helper function for get_minimal_spanning_set_for_region()... */ -static gint -compare_rect_areas (gconstpointer a, gconstpointer b) -{ - const MetaRectangle *a_rect = (gconstpointer) a; - const MetaRectangle *b_rect = (gconstpointer) b; - - int a_area = meta_rectangle_area (a_rect); - int b_area = meta_rectangle_area (b_rect); - - return b_area - a_area; /* positive ret value denotes b > a, ... */ -} - -/* ... and another helper for get_minimal_spanning_set_for_region()... */ -static gboolean -check_strut_align (MetaStrut *strut, const MetaRectangle *rect) -{ - /* Check whether @strut actually aligns to the side of @rect it claims */ - switch (strut->side) - { - case META_SIDE_TOP: - return BOX_TOP (strut->rect) <= BOX_TOP (*rect); - case META_SIDE_BOTTOM: - return BOX_BOTTOM (strut->rect) >= BOX_BOTTOM (*rect); - case META_SIDE_LEFT: - return BOX_LEFT (strut->rect) <= BOX_LEFT (*rect); - case META_SIDE_RIGHT: - return BOX_RIGHT (strut->rect) >= BOX_RIGHT (*rect); - default: - return FALSE; - } -} - -/** - * meta_rectangle_get_minimal_spanning_set_for_region: - * @basic_rect: Input rectangle - * @all_struts: (element-type Meta.Rectangle): List of struts - * - * This function is trying to find a "minimal spanning set (of rectangles)" - * for a given region. - * - * The region is given by taking basic_rect, then removing the areas - * covered by all the rectangles in the all_struts list, and then expanding - * the resulting region by the given number of pixels in each direction. - * - * A "minimal spanning set (of rectangles)" is the best name I could come - * up with for the concept I had in mind. Basically, for a given region, I - * want a set of rectangles with the property that a window is contained in - * the region if and only if it is contained within at least one of the - * rectangles. - * - * Returns: (transfer full) (element-type Meta.Rectangle): Minimal spanning set - */ -GList* -meta_rectangle_get_minimal_spanning_set_for_region ( - const MetaRectangle *basic_rect, - const GSList *all_struts) -{ - /* NOTE FOR OPTIMIZERS: This function *might* be somewhat slow, - * especially due to the call to merge_spanning_rects_in_region() (which - * is O(n^2) where n is the size of the list generated in this function). - * This is made more onerous due to the fact that it involves a fair - * number of memory allocation and deallocation calls. However, n is 1 - * for default installations of Gnome (because partial struts aren't used - * by default and only partial struts increase the size of the spanning - * set generated). With one partial strut, n will be 2 or 3. With 2 - * partial struts, n will probably be 4 or 5. So, n probably isn't large - * enough to make this worth bothering. Further, it is only called from - * workspace.c:ensure_work_areas_validated (at least as of the time of - * writing this comment), which in turn should only be called if the - * strut list changes or the screen or monitor size changes. If it ever - * does show up on profiles (most likely because people start using - * ridiculously huge numbers of partial struts), possible optimizations - * include: - * - * (1) rewrite merge_spanning_rects_in_region() to be O(n) or O(nlogn). - * I'm not totally sure it's possible, but with a couple copies of - * the list and sorting them appropriately, I believe it might be. - * (2) only call merge_spanning_rects_in_region() with a subset of the - * full list of rectangles. I believe from some of my preliminary - * debugging and thinking about it that it is possible to figure out - * apriori groups of rectangles which are only merge candidates with - * each other. (See testboxes.c:get_screen_region() when which==2 - * and track the steps of this function carefully to see what gave - * me the hint that this might work) - * (3) figure out how to avoid merge_spanning_rects_in_region(). I think - * it might be possible to modify this function to make that - * possible, and I spent just a little while thinking about it, but n - * wasn't large enough to convince me to care yet. - * (4) Some of the stuff Rob mentioned at http://mail.gnome.org/archives\ - * /metacity-devel-list/2005-November/msg00028.html. (Sorry for the - * URL splitting.) - */ - - GList *ret; - GList *tmp_list; - const GSList *strut_iter; - MetaRectangle *temp_rect; - - /* The algorithm is basically as follows: - * Initialize rectangle_set to basic_rect - * Foreach strut: - * Foreach rectangle in rectangle_set: - * - Split the rectangle into new rectangles that don't overlap the - * strut (but which are as big as possible otherwise) - * - Remove the old (pre-split) rectangle from the rectangle_set, - * and replace it with the new rectangles generated from the - * splitting - */ - - temp_rect = g_new (MetaRectangle, 1); - *temp_rect = *basic_rect; - ret = g_list_prepend (NULL, temp_rect); - - for (strut_iter = all_struts; strut_iter; strut_iter = strut_iter->next) - { - GList *rect_iter; - MetaStrut *strut = (MetaStrut*)strut_iter->data; - MetaRectangle *strut_rect = &strut->rect; - - tmp_list = ret; - ret = NULL; - rect_iter = tmp_list; - while (rect_iter) - { - MetaRectangle *rect = (MetaRectangle*) rect_iter->data; - - if (!meta_rectangle_overlap (strut_rect, rect) || - !check_strut_align (strut, basic_rect)) - ret = g_list_prepend (ret, rect); - else - { - /* If there is area in rect left of strut */ - if (BOX_LEFT (*rect) < BOX_LEFT (*strut_rect)) - { - temp_rect = g_new (MetaRectangle, 1); - *temp_rect = *rect; - temp_rect->width = BOX_LEFT (*strut_rect) - BOX_LEFT (*rect); - ret = g_list_prepend (ret, temp_rect); - } - /* If there is area in rect right of strut */ - if (BOX_RIGHT (*rect) > BOX_RIGHT (*strut_rect)) - { - int new_x; - temp_rect = g_new (MetaRectangle, 1); - *temp_rect = *rect; - new_x = BOX_RIGHT (*strut_rect); - temp_rect->width = BOX_RIGHT(*rect) - new_x; - temp_rect->x = new_x; - ret = g_list_prepend (ret, temp_rect); - } - /* If there is area in rect above strut */ - if (BOX_TOP (*rect) < BOX_TOP (*strut_rect)) - { - temp_rect = g_new (MetaRectangle, 1); - *temp_rect = *rect; - temp_rect->height = BOX_TOP (*strut_rect) - BOX_TOP (*rect); - ret = g_list_prepend (ret, temp_rect); - } - /* If there is area in rect below strut */ - if (BOX_BOTTOM (*rect) > BOX_BOTTOM (*strut_rect)) - { - int new_y; - temp_rect = g_new (MetaRectangle, 1); - *temp_rect = *rect; - new_y = BOX_BOTTOM (*strut_rect); - temp_rect->height = BOX_BOTTOM (*rect) - new_y; - temp_rect->y = new_y; - ret = g_list_prepend (ret, temp_rect); - } - g_free (rect); - } - rect_iter = rect_iter->next; - } - g_list_free (tmp_list); - } - - /* Sort by maximal area, just because I feel like it... */ - ret = g_list_sort (ret, compare_rect_areas); - - /* Merge rectangles if possible so that the list really is minimal */ - ret = merge_spanning_rects_in_region (ret); - - return ret; -} - -/** - * meta_rectangle_expand_region: (skip) - * - */ -GList* -meta_rectangle_expand_region (GList *region, - const int left_expand, - const int right_expand, - const int top_expand, - const int bottom_expand) -{ - return meta_rectangle_expand_region_conditionally (region, - left_expand, - right_expand, - top_expand, - bottom_expand, - 0, - 0); -} - -/** - * meta_rectangle_expand_region_conditionally: (skip) - * - */ -GList* -meta_rectangle_expand_region_conditionally (GList *region, - const int left_expand, - const int right_expand, - const int top_expand, - const int bottom_expand, - const int min_x, - const int min_y) -{ - GList *tmp_list = region; - while (tmp_list) - { - MetaRectangle *rect = (MetaRectangle*) tmp_list->data; - if (rect->width >= min_x) - { - rect->x -= left_expand; - rect->width += (left_expand + right_expand); - } - if (rect->height >= min_y) - { - rect->y -= top_expand; - rect->height += (top_expand + bottom_expand); - } - tmp_list = tmp_list->next; - } - - return region; -} - -void -meta_rectangle_expand_to_avoiding_struts (MetaRectangle *rect, - const MetaRectangle *expand_to, - const MetaDirection direction, - const GSList *all_struts) -{ - const GSList *strut_iter; - - /* If someone wants this function to handle more fine-grained - * direction expanding in the future (e.g. only left, or fully - * horizontal plus upward), feel free. But I'm hard-coding for both - * horizontal directions (exclusive-)or both vertical directions. - */ - g_assert ((direction == META_DIRECTION_HORIZONTAL) ^ - (direction == META_DIRECTION_VERTICAL )); - - if (direction == META_DIRECTION_HORIZONTAL) - { - rect->x = expand_to->x; - rect->width = expand_to->width; - } - else - { - rect->y = expand_to->y; - rect->height = expand_to->height; - } - - - /* Run over all struts */ - for (strut_iter = all_struts; strut_iter; strut_iter = strut_iter->next) - { - MetaStrut *strut = (MetaStrut*) strut_iter->data; - - /* Skip struts that don't overlap */ - if (!meta_rectangle_overlap (&strut->rect, rect)) - continue; - - if (direction == META_DIRECTION_HORIZONTAL) - { - if (strut->side == META_SIDE_LEFT) - { - int offset = BOX_RIGHT(strut->rect) - BOX_LEFT(*rect); - rect->x += offset; - rect->width -= offset; - } - else if (strut->side == META_SIDE_RIGHT) - { - int offset = BOX_RIGHT (*rect) - BOX_LEFT(strut->rect); - rect->width -= offset; - } - /* else ignore the strut */ - } - else /* direction == META_DIRECTION_VERTICAL */ - { - if (strut->side == META_SIDE_TOP) - { - int offset = BOX_BOTTOM(strut->rect) - BOX_TOP(*rect); - rect->y += offset; - rect->height -= offset; - } - else if (strut->side == META_SIDE_BOTTOM) - { - int offset = BOX_BOTTOM(*rect) - BOX_TOP(strut->rect); - rect->height -= offset; - } - /* else ignore the strut */ - } - } /* end loop over struts */ -} /* end meta_rectangle_expand_to_avoiding_struts */ - -void -meta_rectangle_free_list_and_elements (GList *filled_list) -{ - g_list_free_full (filled_list, g_free); -} - -gboolean -meta_rectangle_could_fit_in_region (const GList *spanning_rects, - const MetaRectangle *rect) -{ - const GList *temp; - gboolean could_fit; - - temp = spanning_rects; - could_fit = FALSE; - while (!could_fit && temp != NULL) - { - could_fit = could_fit || meta_rectangle_could_fit_rect (temp->data, rect); - temp = temp->next; - } - - return could_fit; -} - -gboolean -meta_rectangle_contained_in_region (const GList *spanning_rects, - const MetaRectangle *rect) -{ - const GList *temp; - gboolean contained; - - temp = spanning_rects; - contained = FALSE; - while (!contained && temp != NULL) - { - contained = contained || meta_rectangle_contains_rect (temp->data, rect); - temp = temp->next; - } - - return contained; -} - -gboolean -meta_rectangle_overlaps_with_region (const GList *spanning_rects, - const MetaRectangle *rect) -{ - const GList *temp; - gboolean overlaps; - - temp = spanning_rects; - overlaps = FALSE; - while (!overlaps && temp != NULL) - { - overlaps = overlaps || meta_rectangle_overlap (temp->data, rect); - temp = temp->next; - } - - return overlaps; -} - - -void -meta_rectangle_clamp_to_fit_into_region (const GList *spanning_rects, - FixedDirections fixed_directions, - MetaRectangle *rect, - const MetaRectangle *min_size) -{ - const GList *temp; - const MetaRectangle *best_rect = NULL; - int best_overlap = 0; - - /* First, find best rectangle from spanning_rects to which we can clamp - * rect to fit into. - */ - for (temp = spanning_rects; temp; temp = temp->next) - { - MetaRectangle *compare_rect = temp->data; - int maximal_overlap_amount_for_compare; - - /* If x is fixed and the entire width of rect doesn't fit in compare, - * skip this rectangle. - */ - if ((fixed_directions & FIXED_DIRECTION_X) && - (compare_rect->x > rect->x || - compare_rect->x + compare_rect->width < rect->x + rect->width)) - continue; - - /* If y is fixed and the entire height of rect doesn't fit in compare, - * skip this rectangle. - */ - if ((fixed_directions & FIXED_DIRECTION_Y) && - (compare_rect->y > rect->y || - compare_rect->y + compare_rect->height < rect->y + rect->height)) - continue; - - /* If compare can't hold the min_size window, skip this rectangle. */ - if (compare_rect->width < min_size->width || - compare_rect->height < min_size->height) - continue; - - /* Determine maximal overlap amount */ - maximal_overlap_amount_for_compare = - MIN (rect->width, compare_rect->width) * - MIN (rect->height, compare_rect->height); - - /* See if this is the best rect so far */ - if (maximal_overlap_amount_for_compare > best_overlap) - { - best_rect = compare_rect; - best_overlap = maximal_overlap_amount_for_compare; - } - } - - /* Clamp rect appropriately */ - if (best_rect == NULL) - { - g_warning ("No rect whose size to clamp to found!"); - - /* If it doesn't fit, at least make it no bigger than it has to be */ - if (!(fixed_directions & FIXED_DIRECTION_X)) - rect->width = min_size->width; - if (!(fixed_directions & FIXED_DIRECTION_Y)) - rect->height = min_size->height; - } - else - { - rect->width = MIN (rect->width, best_rect->width); - rect->height = MIN (rect->height, best_rect->height); - } -} - -void -meta_rectangle_clip_to_region (const GList *spanning_rects, - FixedDirections fixed_directions, - MetaRectangle *rect) -{ - const GList *temp; - const MetaRectangle *best_rect = NULL; - int best_overlap = 0; - - /* First, find best rectangle from spanning_rects to which we will clip - * rect into. - */ - for (temp = spanning_rects; temp; temp = temp->next) - { - MetaRectangle *compare_rect = temp->data; - MetaRectangle overlap; - int maximal_overlap_amount_for_compare; - - /* If x is fixed and the entire width of rect doesn't fit in compare, - * skip the rectangle. - */ - if ((fixed_directions & FIXED_DIRECTION_X) && - (compare_rect->x > rect->x || - compare_rect->x + compare_rect->width < rect->x + rect->width)) - continue; - - /* If y is fixed and the entire height of rect doesn't fit in compare, - * skip the rectangle. - */ - if ((fixed_directions & FIXED_DIRECTION_Y) && - (compare_rect->y > rect->y || - compare_rect->y + compare_rect->height < rect->y + rect->height)) - continue; - - /* Determine maximal overlap amount */ - meta_rectangle_intersect (rect, compare_rect, &overlap); - maximal_overlap_amount_for_compare = meta_rectangle_area (&overlap); - - /* See if this is the best rect so far */ - if (maximal_overlap_amount_for_compare > best_overlap) - { - best_rect = compare_rect; - best_overlap = maximal_overlap_amount_for_compare; - } - } - - /* Clip rect appropriately */ - if (best_rect == NULL) - { - g_warning ("No rect to clip to found!"); - } - else - { - /* Extra precaution with checking fixed direction shouldn't be needed - * due to logic above, but it shouldn't hurt either. - */ - if (!(fixed_directions & FIXED_DIRECTION_X)) - { - /* Find the new left and right */ - int new_x = MAX (rect->x, best_rect->x); - rect->width = MIN ((rect->x + rect->width) - new_x, - (best_rect->x + best_rect->width) - new_x); - rect->x = new_x; - } - - /* Extra precaution with checking fixed direction shouldn't be needed - * due to logic above, but it shouldn't hurt either. - */ - if (!(fixed_directions & FIXED_DIRECTION_Y)) - { - /* Clip the top, if needed */ - int new_y = MAX (rect->y, best_rect->y); - rect->height = MIN ((rect->y + rect->height) - new_y, - (best_rect->y + best_rect->height) - new_y); - rect->y = new_y; - } - } -} - -void -meta_rectangle_shove_into_region (const GList *spanning_rects, - FixedDirections fixed_directions, - MetaRectangle *rect) -{ - const GList *temp; - const MetaRectangle *best_rect = NULL; - int best_overlap = 0; - int shortest_distance = G_MAXINT; - - /* First, find best rectangle from spanning_rects to which we will shove - * rect into. - */ - - for (temp = spanning_rects; temp; temp = temp->next) - { - MetaRectangle *compare_rect = temp->data; - int maximal_overlap_amount_for_compare; - int dist_to_compare; - - /* If x is fixed and the entire width of rect doesn't fit in compare, - * skip this rectangle. - */ - if ((fixed_directions & FIXED_DIRECTION_X) && - (compare_rect->x > rect->x || - compare_rect->x + compare_rect->width < rect->x + rect->width)) - continue; - - /* If y is fixed and the entire height of rect doesn't fit in compare, - * skip this rectangle. - */ - if ((fixed_directions & FIXED_DIRECTION_Y) && - (compare_rect->y > rect->y || - compare_rect->y + compare_rect->height < rect->y + rect->height)) - continue; - - /* Determine maximal overlap amount between rect & compare_rect */ - maximal_overlap_amount_for_compare = - MIN (rect->width, compare_rect->width) * - MIN (rect->height, compare_rect->height); - - /* Determine distance necessary to put rect into compare_rect */ - dist_to_compare = 0; - if (compare_rect->x > rect->x) - dist_to_compare += compare_rect->x - rect->x; - if (compare_rect->x + compare_rect->width < rect->x + rect->width) - dist_to_compare += (rect->x + rect->width) - - (compare_rect->x + compare_rect->width); - if (compare_rect->y > rect->y) - dist_to_compare += compare_rect->y - rect->y; - if (compare_rect->y + compare_rect->height < rect->y + rect->height) - dist_to_compare += (rect->y + rect->height) - - (compare_rect->y + compare_rect->height); - - /* See if this is the best rect so far */ - if ((maximal_overlap_amount_for_compare > best_overlap) || - (maximal_overlap_amount_for_compare == best_overlap && - dist_to_compare < shortest_distance)) - { - best_rect = compare_rect; - best_overlap = maximal_overlap_amount_for_compare; - shortest_distance = dist_to_compare; - } - } - - /* Shove rect appropriately */ - if (best_rect == NULL) - { - g_warning ("No rect to shove into found!"); - } - else - { - /* Extra precaution with checking fixed direction shouldn't be needed - * due to logic above, but it shouldn't hurt either. - */ - if (!(fixed_directions & FIXED_DIRECTION_X)) - { - /* Shove to the right, if needed */ - if (best_rect->x > rect->x) - rect->x = best_rect->x; - - /* Shove to the left, if needed */ - if (best_rect->x + best_rect->width < rect->x + rect->width) - rect->x = (best_rect->x + best_rect->width) - rect->width; - } - - /* Extra precaution with checking fixed direction shouldn't be needed - * due to logic above, but it shouldn't hurt either. - */ - if (!(fixed_directions & FIXED_DIRECTION_Y)) - { - /* Shove down, if needed */ - if (best_rect->y > rect->y) - rect->y = best_rect->y; - - /* Shove up, if needed */ - if (best_rect->y + best_rect->height < rect->y + rect->height) - rect->y = (best_rect->y + best_rect->height) - rect->height; - } - } -} - -void -meta_rectangle_find_linepoint_closest_to_point (double x1, - double y1, - double x2, - double y2, - double px, - double py, - double *valx, - double *valy) -{ - /* I'll use the shorthand rx, ry for the return values, valx & valy. - * Now, we need (rx,ry) to be on the line between (x1,y1) and (x2,y2). - * For that to happen, we first need the slope of the line from (x1,y1) - * to (rx,ry) must match the slope of (x1,y1) to (x2,y2), i.e.: - * (ry-y1) (y2-y1) - * ------- = ------- - * (rx-x1) (x2-x1) - * If x1==x2, though, this gives divide by zero errors, so we want to - * rewrite the equation by multiplying both sides by (rx-x1)*(x2-x1): - * (ry-y1)(x2-x1) = (y2-y1)(rx-x1) - * This is a valid requirement even when x1==x2 (when x1==x2, this latter - * equation will basically just mean that rx must be equal to both x1 and - * x2) - * - * The other requirement that we have is that the line from (rx,ry) to - * (px,py) must be perpendicular to the line from (x1,y1) to (x2,y2). So - * we just need to get a vector in the direction of each line, take the - * dot product of the two, and ensure that the result is 0: - * (rx-px)*(x2-x1) + (ry-py)*(y2-y1) = 0. - * - * This gives us two equations and two unknowns: - * - * (ry-y1)(x2-x1) = (y2-y1)(rx-x1) - * (rx-px)*(x2-x1) + (ry-py)*(y2-y1) = 0. - * - * This particular pair of equations is always solvable so long as - * (x1,y1) and (x2,y2) are not the same point (and note that anyone who - * calls this function that way is braindead because it means that they - * really didn't specify a line after all). However, the caller should - * be careful to avoid making (x1,y1) and (x2,y2) too close (e.g. like - * 10^{-8} apart in each coordinate), otherwise roundoff error could - * cause issues. Solving these equations by hand (or using Maple(TM) or - * Mathematica(TM) or whatever) results in slightly messy expressions, - * but that's all the below few lines do. - */ - - double diffx, diffy, den; - diffx = x2 - x1; - diffy = y2 - y1; - den = diffx * diffx + diffy * diffy; - - *valx = (py * diffx * diffy + px * diffx * diffx + - y2 * x1 * diffy - y1 * x2 * diffy) / den; - *valy = (px * diffx * diffy + py * diffy * diffy + - x2 * y1 * diffx - x1 * y2 * diffx) / den; -} - -/***************************************************************************/ -/* */ -/* Switching gears to code for edges instead of just rectangles */ -/* */ -/***************************************************************************/ - -gboolean -meta_rectangle_edge_aligns (const MetaRectangle *rect, const MetaEdge *edge) -{ - /* The reason for the usage of <= below instead of < is because we are - * interested in in-the-way-or-adject'ness. So, a left (i.e. vertical - * edge) occupying y positions 0-9 (which has a y of 0 and a height of - * 10) and a rectangle with top at y=10 would be considered to "align" by - * this function. - */ - switch (edge->side_type) - { - case META_SIDE_LEFT: - case META_SIDE_RIGHT: - return BOX_TOP (*rect) <= BOX_BOTTOM (edge->rect) && - BOX_TOP (edge->rect) <= BOX_BOTTOM (*rect); - case META_SIDE_TOP: - case META_SIDE_BOTTOM: - return BOX_LEFT (*rect) <= BOX_RIGHT (edge->rect) && - BOX_LEFT (edge->rect) <= BOX_RIGHT (*rect); - default: - g_assert_not_reached (); - return FALSE; - } -} - -static GList* -get_rect_minus_overlap (const GList *rect_in_list, - MetaRectangle *overlap) -{ - MetaRectangle *temp; - MetaRectangle *rect = rect_in_list->data; - GList *ret = NULL; - - if (BOX_LEFT (*rect) < BOX_LEFT (*overlap)) - { - temp = g_new (MetaRectangle, 1); - *temp = *rect; - temp->width = BOX_LEFT (*overlap) - BOX_LEFT (*rect); - ret = g_list_prepend (ret, temp); - } - if (BOX_RIGHT (*rect) > BOX_RIGHT (*overlap)) - { - temp = g_new (MetaRectangle, 1); - *temp = *rect; - temp->x = BOX_RIGHT (*overlap); - temp->width = BOX_RIGHT (*rect) - BOX_RIGHT (*overlap); - ret = g_list_prepend (ret, temp); - } - if (BOX_TOP (*rect) < BOX_TOP (*overlap)) - { - temp = g_new (MetaRectangle, 1); - temp->x = overlap->x; - temp->width = overlap->width; - temp->y = BOX_TOP (*rect); - temp->height = BOX_TOP (*overlap) - BOX_TOP (*rect); - ret = g_list_prepend (ret, temp); - } - if (BOX_BOTTOM (*rect) > BOX_BOTTOM (*overlap)) - { - temp = g_new (MetaRectangle, 1); - temp->x = overlap->x; - temp->width = overlap->width; - temp->y = BOX_BOTTOM (*overlap); - temp->height = BOX_BOTTOM (*rect) - BOX_BOTTOM (*overlap); - ret = g_list_prepend (ret, temp); - } - - return ret; -} - -static GList* -replace_rect_with_list (GList *old_element, - GList *new_list) -{ - GList *ret; - g_assert (old_element != NULL); - - if (!new_list) - { - /* If there is no new list, just remove the old_element */ - ret = g_list_remove_link (old_element, old_element); - } - else - { - /* Fix up the prev and next pointers everywhere */ - ret = new_list; - if (old_element->prev) - { - old_element->prev->next = new_list; - new_list->prev = old_element->prev; - } - if (old_element->next) - { - GList *tmp = g_list_last (new_list); - old_element->next->prev = tmp; - tmp->next = old_element->next; - } - } - - /* Free the old_element and return the appropriate "next" point */ - g_free (old_element->data); - g_list_free_1 (old_element); - return ret; -} - -/* Make a copy of the strut list, make sure that copy only contains parts - * of the old_struts that intersect with the region rect, and then do some - * magic to make all the new struts disjoint (okay, we we break up struts - * that aren't disjoint in a way that the overlapping part is only included - * once, so it's not really magic...). - */ -static GList* -get_disjoint_strut_rect_list_in_region (const GSList *old_struts, - const MetaRectangle *region) -{ - GList *strut_rects; - GList *tmp; - - /* First, copy the list */ - strut_rects = NULL; - while (old_struts) - { - MetaRectangle *cur = &((MetaStrut*)old_struts->data)->rect; - MetaRectangle *copy = g_new (MetaRectangle, 1); - *copy = *cur; - if (meta_rectangle_intersect (copy, region, copy)) - strut_rects = g_list_prepend (strut_rects, copy); - else - g_free (copy); - - old_struts = old_struts->next; - } - - /* Now, loop over the list and check for intersections, fixing things up - * where they do intersect. - */ - tmp = strut_rects; - while (tmp) - { - GList *compare; - - MetaRectangle *cur = tmp->data; - - compare = tmp->next; - while (compare) - { - MetaRectangle *comp = compare->data; - MetaRectangle overlap; - - if (meta_rectangle_intersect (cur, comp, &overlap)) - { - /* Get a list of rectangles for each strut that don't overlap - * the intersection region. - */ - GList *cur_leftover = get_rect_minus_overlap (tmp, &overlap); - GList *comp_leftover = get_rect_minus_overlap (compare, &overlap); - - /* Add the intersection region to cur_leftover */ - MetaRectangle *overlap_allocated = g_new (MetaRectangle, 1); - *overlap_allocated = overlap; - cur_leftover = g_list_prepend (cur_leftover, overlap_allocated); - - /* Fix up tmp, compare, and cur -- maybe struts too */ - if (strut_rects == tmp) - { - strut_rects = replace_rect_with_list (tmp, cur_leftover); - tmp = strut_rects; - } - else - tmp = replace_rect_with_list (tmp, cur_leftover); - compare = replace_rect_with_list (compare, comp_leftover); - - if (compare == NULL) - break; - - cur = tmp->data; - } - - compare = compare->next; - } - - tmp = tmp->next; - } - - return strut_rects; -} - -gint -meta_rectangle_edge_cmp_ignore_type (gconstpointer a, gconstpointer b) -{ - const MetaEdge *a_edge_rect = (gconstpointer) a; - const MetaEdge *b_edge_rect = (gconstpointer) b; - int a_compare, b_compare; - - /* Edges must be both vertical or both horizontal, or it doesn't make - * sense to compare them. - */ - g_assert ((a_edge_rect->rect.width == 0 && b_edge_rect->rect.width == 0) || - (a_edge_rect->rect.height == 0 && b_edge_rect->rect.height == 0)); - - a_compare = b_compare = 0; /* gcc-3.4.2 sucks at figuring initialized'ness */ - - if (a_edge_rect->side_type == META_SIDE_LEFT || - a_edge_rect->side_type == META_SIDE_RIGHT) - { - a_compare = a_edge_rect->rect.x; - b_compare = b_edge_rect->rect.x; - if (a_compare == b_compare) - { - a_compare = a_edge_rect->rect.y; - b_compare = b_edge_rect->rect.y; - } - } - else if (a_edge_rect->side_type == META_SIDE_TOP || - a_edge_rect->side_type == META_SIDE_BOTTOM) - { - a_compare = a_edge_rect->rect.y; - b_compare = b_edge_rect->rect.y; - if (a_compare == b_compare) - { - a_compare = a_edge_rect->rect.x; - b_compare = b_edge_rect->rect.x; - } - } - else - g_assert ("Some idiot wanted to sort sides of different types."); - - return a_compare - b_compare; /* positive value denotes a > b ... */ -} - -/* To make things easily testable, provide a nice way of sorting edges */ -gint -meta_rectangle_edge_cmp (gconstpointer a, gconstpointer b) -{ - const MetaEdge *a_edge_rect = (gconstpointer) a; - const MetaEdge *b_edge_rect = (gconstpointer) b; - - int a_compare, b_compare; - - a_compare = a_edge_rect->side_type; - b_compare = b_edge_rect->side_type; - - if (a_compare == b_compare) - return meta_rectangle_edge_cmp_ignore_type (a, b); - - return a_compare - b_compare; /* positive value denotes a > b ... */ -} - -/* Determine whether two given edges overlap */ -static gboolean -edges_overlap (const MetaEdge *edge1, - const MetaEdge *edge2) -{ - if (edge1->rect.width == 0 && edge2->rect.width == 0) - { - return meta_rectangle_vert_overlap (&edge1->rect, &edge2->rect) && - edge1->rect.x == edge2->rect.x; - } - else if (edge1->rect.height == 0 && edge2->rect.height == 0) - { - return meta_rectangle_horiz_overlap (&edge1->rect, &edge2->rect) && - edge1->rect.y == edge2->rect.y; - } - else - { - return FALSE; - } -} - -static gboolean -rectangle_and_edge_intersection (const MetaRectangle *rect, - const MetaEdge *edge, - MetaEdge *overlap, - int *handle_type) -{ - const MetaRectangle *rect2 = &edge->rect; - MetaRectangle *result = &overlap->rect; - gboolean intersect = TRUE; - - /* We don't know how to set these, so set them to invalid values */ - overlap->edge_type = -1; - overlap->side_type = -1; - - /* Figure out what the intersection is */ - result->x = MAX (rect->x, rect2->x); - result->y = MAX (rect->y, rect2->y); - result->width = MIN (BOX_RIGHT (*rect), BOX_RIGHT (*rect2)) - result->x; - result->height = MIN (BOX_BOTTOM (*rect), BOX_BOTTOM (*rect2)) - result->y; - - /* Find out if the intersection is empty; have to do it this way since - * edges have a thickness of 0 - */ - if ((result->width < 0 || result->height < 0) || - (result->width == 0 && result->height == 0)) - { - result->width = 0; - result->height = 0; - intersect = FALSE; - } - else - { - /* Need to figure out the handle_type, a somewhat weird quantity: - * 0 - overlap is in middle of rect - * -1 - overlap is at the side of rect, and is on the opposite side - * of rect than the edge->side_type side - * 1 - overlap is at the side of rect, and the side of rect it is - * on is the edge->side_type side - */ - switch (edge->side_type) - { - case META_SIDE_LEFT: - if (result->x == rect->x) - *handle_type = 1; - else if (result->x == BOX_RIGHT (*rect)) - *handle_type = -1; - else - *handle_type = 0; - break; - case META_SIDE_RIGHT: - if (result->x == rect->x) - *handle_type = -1; - else if (result->x == BOX_RIGHT (*rect)) - *handle_type = 1; - else - *handle_type = 0; - break; - case META_SIDE_TOP: - if (result->y == rect->y) - *handle_type = 1; - else if (result->y == BOX_BOTTOM (*rect)) - *handle_type = -1; - else - *handle_type = 0; - break; - case META_SIDE_BOTTOM: - if (result->y == rect->y) - *handle_type = -1; - else if (result->y == BOX_BOTTOM (*rect)) - *handle_type = 1; - else - *handle_type = 0; - break; - default: - g_assert_not_reached (); - } - } - return intersect; -} - -/* Add all edges of the given rect to cur_edges and return the result. If - * rect_is_internal is false, the side types are switched (LEFT<->RIGHT and - * TOP<->BOTTOM). - */ -static GList* -add_edges (GList *cur_edges, - const MetaRectangle *rect, - gboolean rect_is_internal) -{ - MetaEdge *temp_edge; - int i; - - for (i=0; i<4; i++) - { - temp_edge = g_new (MetaEdge, 1); - temp_edge->rect = *rect; - switch (i) - { - case 0: - temp_edge->side_type = - rect_is_internal ? META_SIDE_LEFT : META_SIDE_RIGHT; - temp_edge->rect.width = 0; - break; - case 1: - temp_edge->side_type = - rect_is_internal ? META_SIDE_RIGHT : META_SIDE_LEFT; - temp_edge->rect.x += temp_edge->rect.width; - temp_edge->rect.width = 0; - break; - case 2: - temp_edge->side_type = - rect_is_internal ? META_SIDE_TOP : META_SIDE_BOTTOM; - temp_edge->rect.height = 0; - break; - case 3: - temp_edge->side_type = - rect_is_internal ? META_SIDE_BOTTOM : META_SIDE_TOP; - temp_edge->rect.y += temp_edge->rect.height; - temp_edge->rect.height = 0; - break; - } - temp_edge->edge_type = META_EDGE_SCREEN; - cur_edges = g_list_prepend (cur_edges, temp_edge); - } - - return cur_edges; -} - -/* Remove any part of old_edge that intersects remove and add any resulting - * edges to cur_list. Return cur_list when finished. - */ -static GList* -split_edge (GList *cur_list, - const MetaEdge *old_edge, - const MetaEdge *remove) -{ - MetaEdge *temp_edge; - switch (old_edge->side_type) - { - case META_SIDE_LEFT: - case META_SIDE_RIGHT: - g_assert (meta_rectangle_vert_overlap (&old_edge->rect, &remove->rect)); - if (BOX_TOP (old_edge->rect) < BOX_TOP (remove->rect)) - { - temp_edge = g_new (MetaEdge, 1); - *temp_edge = *old_edge; - temp_edge->rect.height = BOX_TOP (remove->rect) - - BOX_TOP (old_edge->rect); - cur_list = g_list_prepend (cur_list, temp_edge); - } - if (BOX_BOTTOM (old_edge->rect) > BOX_BOTTOM (remove->rect)) - { - temp_edge = g_new (MetaEdge, 1); - *temp_edge = *old_edge; - temp_edge->rect.y = BOX_BOTTOM (remove->rect); - temp_edge->rect.height = BOX_BOTTOM (old_edge->rect) - - BOX_BOTTOM (remove->rect); - cur_list = g_list_prepend (cur_list, temp_edge); - } - break; - case META_SIDE_TOP: - case META_SIDE_BOTTOM: - g_assert (meta_rectangle_horiz_overlap (&old_edge->rect, &remove->rect)); - if (BOX_LEFT (old_edge->rect) < BOX_LEFT (remove->rect)) - { - temp_edge = g_new (MetaEdge, 1); - *temp_edge = *old_edge; - temp_edge->rect.width = BOX_LEFT (remove->rect) - - BOX_LEFT (old_edge->rect); - cur_list = g_list_prepend (cur_list, temp_edge); - } - if (BOX_RIGHT (old_edge->rect) > BOX_RIGHT (remove->rect)) - { - temp_edge = g_new (MetaEdge, 1); - *temp_edge = *old_edge; - temp_edge->rect.x = BOX_RIGHT (remove->rect); - temp_edge->rect.width = BOX_RIGHT (old_edge->rect) - - BOX_RIGHT (remove->rect); - cur_list = g_list_prepend (cur_list, temp_edge); - } - break; - default: - g_assert_not_reached (); - } - - return cur_list; -} - -/* Split up edge and remove preliminary edges from strut_edges depending on - * if and how rect and edge intersect. - */ -static void -fix_up_edges (MetaRectangle *rect, MetaEdge *edge, - GList **strut_edges, GList **edge_splits, - gboolean *edge_needs_removal) -{ - MetaEdge overlap; - int handle_type; - - if (!rectangle_and_edge_intersection (rect, edge, &overlap, &handle_type)) - return; - - if (handle_type == 0 || handle_type == 1) - { - /* Put the result of removing overlap from edge into edge_splits */ - *edge_splits = split_edge (*edge_splits, edge, &overlap); - *edge_needs_removal = TRUE; - } - - if (handle_type == -1 || handle_type == 1) - { - /* Remove the overlap from strut_edges */ - /* First, loop over the edges of the strut */ - GList *tmp = *strut_edges; - while (tmp) - { - MetaEdge *cur = tmp->data; - /* If this is the edge that overlaps, then we need to split it */ - if (edges_overlap (cur, &overlap)) - { - GList *delete_me = tmp; - - /* Split this edge into some new ones */ - *strut_edges = split_edge (*strut_edges, cur, &overlap); - - /* Delete the old one */ - tmp = tmp->next; - g_free (cur); - *strut_edges = g_list_delete_link (*strut_edges, delete_me); - } - else - tmp = tmp->next; - } - } -} - -/** - * meta_rectangle_remove_intersections_with_boxes_from_edges: (skip) - * - * This function removes intersections of edges with the rectangles from the - * list of edges. - */ -GList* -meta_rectangle_remove_intersections_with_boxes_from_edges ( - GList *edges, - const GSList *rectangles) -{ - const GSList *rect_iter; - const int opposing = 1; - - /* Now remove all intersections of rectangles with the edge list */ - rect_iter = rectangles; - while (rect_iter) - { - MetaRectangle *rect = rect_iter->data; - GList *edge_iter = edges; - while (edge_iter) - { - MetaEdge *edge = edge_iter->data; - MetaEdge overlap; - int handle; - gboolean edge_iter_advanced = FALSE; - - /* If this edge overlaps with this rect... */ - if (rectangle_and_edge_intersection (rect, edge, &overlap, &handle)) - { - - /* "Intersections" where the edges touch but are opposite - * sides (e.g. a left edge against the right edge) should not - * be split. Note that the comments in - * rectangle_and_edge_intersection() say that opposing edges - * occur when handle is -1, BUT you need to remember that we - * treat the left side of a window as a right edge because - * it's what the right side of the window being moved should - * be-resisted-by/snap-to. So opposing is really 1. Anyway, - * we just keep track of it in the opposing constant set up - * above and if handle isn't equal to that, then we know the - * edge should be split. - */ - if (handle != opposing) - { - /* Keep track of this edge so we can delete it below */ - GList *delete_me = edge_iter; - edge_iter = edge_iter->next; - edge_iter_advanced = TRUE; - - /* Split the edge and add the result to beginning of edges */ - edges = split_edge (edges, edge, &overlap); - - /* Now free the edge... */ - g_free (edge); - edges = g_list_delete_link (edges, delete_me); - } - } - - if (!edge_iter_advanced) - edge_iter = edge_iter->next; - } - - rect_iter = rect_iter->next; - } - - return edges; -} - -/** - * meta_rectangle_find_onscreen_edges: (skip) - * - * This function is trying to find all the edges of an onscreen region. - */ -GList* -meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect, - const GSList *all_struts) -{ - GList *ret; - GList *fixed_strut_rects; - GList *edge_iter; - const GList *strut_rect_iter; - - /* The algorithm is basically as follows: - * Make sure the struts are disjoint - * Initialize the edge_set to the edges of basic_rect - * Foreach strut: - * Put together a preliminary new edge from the edges of the strut - * Foreach edge in edge_set: - * - Split the edge if it is partially contained inside the strut - * - If the edge matches an edge of the strut (i.e. a strut just - * against the edge of the screen or a not-next-to-edge-of-screen - * strut adjacent to another), then both the edge from the - * edge_set and the preliminary edge for the strut will need to - * be split - * Add any remaining "preliminary" strut edges to the edge_set - */ - - /* Make sure the struts are disjoint */ - fixed_strut_rects = - get_disjoint_strut_rect_list_in_region (all_struts, basic_rect); - - /* Start off the list with the edges of basic_rect */ - ret = add_edges (NULL, basic_rect, TRUE); - - strut_rect_iter = fixed_strut_rects; - while (strut_rect_iter) - { - MetaRectangle *strut_rect = (MetaRectangle*) strut_rect_iter->data; - - /* Get the new possible edges we may need to add from the strut */ - GList *new_strut_edges = add_edges (NULL, strut_rect, FALSE); - - edge_iter = ret; - while (edge_iter) - { - MetaEdge *cur_edge = edge_iter->data; - GList *splits_of_cur_edge = NULL; - gboolean edge_needs_removal = FALSE; - - fix_up_edges (strut_rect, cur_edge, - &new_strut_edges, &splits_of_cur_edge, - &edge_needs_removal); - - if (edge_needs_removal) - { - /* Delete the old edge */ - GList *delete_me = edge_iter; - edge_iter = edge_iter->next; - g_free (cur_edge); - ret = g_list_delete_link (ret, delete_me); - - /* Add the new split parts of the edge */ - ret = g_list_concat (splits_of_cur_edge, ret); - } - else - { - edge_iter = edge_iter->next; - } - - /* edge_iter was already advanced above */ - } - - ret = g_list_concat (new_strut_edges, ret); - strut_rect_iter = strut_rect_iter->next; - } - - /* Sort the list */ - ret = g_list_sort (ret, meta_rectangle_edge_cmp); - - /* Free the fixed struts list */ - meta_rectangle_free_list_and_elements (fixed_strut_rects); - - return ret; -} - -/** - * meta_rectangle_find_nonintersected_monitor_edges: (skip) - * - */ -GList* -meta_rectangle_find_nonintersected_monitor_edges ( - const GList *monitor_rects, - const GSList *all_struts) -{ - /* This function cannot easily be merged with - * meta_rectangle_find_onscreen_edges() because real screen edges - * and strut edges both are of the type "there ain't anything - * immediately on the other side"; monitor edges are different. - */ - GList *ret; - const GList *cur; - GSList *temp_rects; - - /* Initialize the return list to be empty */ - ret = NULL; - - /* start of ret with all the edges of monitors that are adjacent to - * another monitor. - */ - cur = monitor_rects; - while (cur) - { - MetaRectangle *cur_rect = cur->data; - const GList *compare = monitor_rects; - while (compare) - { - MetaRectangle *compare_rect = compare->data; - - /* Check if cur might be horizontally adjacent to compare */ - if (meta_rectangle_vert_overlap(cur_rect, compare_rect)) - { - MetaSide side_type; - int y = MAX (cur_rect->y, compare_rect->y); - int height = MIN (BOX_BOTTOM (*cur_rect) - y, - BOX_BOTTOM (*compare_rect) - y); - int width = 0; - int x; - - if (BOX_LEFT (*cur_rect) == BOX_RIGHT (*compare_rect)) - { - /* compare_rect is to the left of cur_rect */ - x = BOX_LEFT (*cur_rect); - side_type = META_SIDE_LEFT; - } - else if (BOX_RIGHT (*cur_rect) == BOX_LEFT (*compare_rect)) - { - /* compare_rect is to the right of cur_rect */ - x = BOX_RIGHT (*cur_rect); - side_type = META_SIDE_RIGHT; - } - else - /* These rectangles aren't adjacent after all */ - x = INT_MIN; - - /* If the rectangles really are adjacent */ - if (x != INT_MIN) - { - /* We need a left edge for the monitor on the right, and - * a right edge for the monitor on the left. Just fill - * up the edges and stick 'em on the list. - */ - MetaEdge *new_edge = g_new (MetaEdge, 1); - - new_edge->rect = meta_rect (x, y, width, height); - new_edge->side_type = side_type; - new_edge->edge_type = META_EDGE_MONITOR; - - ret = g_list_prepend (ret, new_edge); - } - } - - /* Check if cur might be vertically adjacent to compare */ - if (meta_rectangle_horiz_overlap(cur_rect, compare_rect)) - { - MetaSide side_type; - int x = MAX (cur_rect->x, compare_rect->x); - int width = MIN (BOX_RIGHT (*cur_rect) - x, - BOX_RIGHT (*compare_rect) - x); - int height = 0; - int y; - - if (BOX_TOP (*cur_rect) == BOX_BOTTOM (*compare_rect)) - { - /* compare_rect is to the top of cur_rect */ - y = BOX_TOP (*cur_rect); - side_type = META_SIDE_TOP; - } - else if (BOX_BOTTOM (*cur_rect) == BOX_TOP (*compare_rect)) - { - /* compare_rect is to the bottom of cur_rect */ - y = BOX_BOTTOM (*cur_rect); - side_type = META_SIDE_BOTTOM; - } - else - /* These rectangles aren't adjacent after all */ - y = INT_MIN; - - /* If the rectangles really are adjacent */ - if (y != INT_MIN) - { - /* We need a top edge for the monitor on the bottom, and - * a bottom edge for the monitor on the top. Just fill - * up the edges and stick 'em on the list. - */ - MetaEdge *new_edge = g_new (MetaEdge, 1); - - new_edge->rect = meta_rect (x, y, width, height); - new_edge->side_type = side_type; - new_edge->edge_type = META_EDGE_MONITOR; - - ret = g_list_prepend (ret, new_edge); - } - } - - compare = compare->next; - } - cur = cur->next; - } - - temp_rects = NULL; - for (; all_struts; all_struts = all_struts->next) - temp_rects = g_slist_prepend (temp_rects, - &((MetaStrut*)all_struts->data)->rect); - ret = meta_rectangle_remove_intersections_with_boxes_from_edges (ret, - temp_rects); - g_slist_free (temp_rects); - - /* Sort the list */ - ret = g_list_sort (ret, meta_rectangle_edge_cmp); - - return ret; -} - -gboolean -meta_rectangle_is_adjacent_to (MetaRectangle *rect, - MetaRectangle *other) -{ - int rect_x1 = rect->x; - int rect_y1 = rect->y; - int rect_x2 = rect->x + rect->width; - int rect_y2 = rect->y + rect->height; - int other_x1 = other->x; - int other_y1 = other->y; - int other_x2 = other->x + other->width; - int other_y2 = other->y + other->height; - - if ((rect_x1 == other_x2 || rect_x2 == other_x1) && - !(rect_y2 <= other_y1 || rect_y1 >= other_y2)) - return TRUE; - else if ((rect_y1 == other_y2 || rect_y2 == other_y1) && - !(rect_x2 <= other_x1 || rect_x1 >= other_x2)) - return TRUE; - else - return FALSE; -} - -void -meta_rectangle_scale_double (const MetaRectangle *rect, - double scale, - MetaRoundingStrategy rounding_strategy, - MetaRectangle *dest) -{ - graphene_rect_t tmp = GRAPHENE_RECT_INIT (rect->x, rect->y, - rect->width, rect->height); - - graphene_rect_scale (&tmp, scale, scale, &tmp); - meta_rectangle_from_graphene_rect (&tmp, rounding_strategy, dest); -} - -void -meta_rectangle_transform (const MetaRectangle *rect, - MetaMonitorTransform transform, - int width, - int height, - MetaRectangle *dest) -{ - switch (transform) - { - case META_MONITOR_TRANSFORM_NORMAL: - *dest = *rect; - break; - case META_MONITOR_TRANSFORM_90: - *dest = (MetaRectangle) { - .x = width - (rect->y + rect->height), - .y = rect->x, - .width = rect->height, - .height = rect->width, - }; - break; - case META_MONITOR_TRANSFORM_180: - *dest = (MetaRectangle) { - .x = width - (rect->x + rect->width), - .y = height - (rect->y + rect->height), - .width = rect->width, - .height = rect->height, - }; - break; - case META_MONITOR_TRANSFORM_270: - *dest = (MetaRectangle) { - .x = rect->y, - .y = height - (rect->x + rect->width), - .width = rect->height, - .height = rect->width, - }; - break; - case META_MONITOR_TRANSFORM_FLIPPED: - *dest = (MetaRectangle) { - .x = width - (rect->x + rect->width), - .y = rect->y, - .width = rect->width, - .height = rect->height, - }; - break; - case META_MONITOR_TRANSFORM_FLIPPED_90: - *dest = (MetaRectangle) { - .x = width - (rect->y + rect->height), - .y = height - (rect->x + rect->width), - .width = rect->height, - .height = rect->width, - }; - break; - case META_MONITOR_TRANSFORM_FLIPPED_180: - *dest = (MetaRectangle) { - .x = rect->x, - .y = height - (rect->y + rect->height), - .width = rect->width, - .height = rect->height, - }; - break; - case META_MONITOR_TRANSFORM_FLIPPED_270: - *dest = (MetaRectangle) { - .x = rect->y, - .y = rect->x, - .width = rect->height, - .height = rect->width, - }; - break; - } -} - -void -meta_rectangle_from_graphene_rect (const graphene_rect_t *rect, - MetaRoundingStrategy rounding_strategy, - MetaRectangle *dest) -{ - switch (rounding_strategy) - { - case META_ROUNDING_STRATEGY_SHRINK: - { - *dest = (MetaRectangle) { - .x = ceilf (rect->origin.x), - .y = ceilf (rect->origin.y), - .width = floorf (rect->size.width), - .height = floorf (rect->size.height), - }; - } - break; - case META_ROUNDING_STRATEGY_GROW: - { - graphene_rect_t clamped = *rect; - - graphene_rect_round_extents (&clamped, &clamped); - - *dest = (MetaRectangle) { - .x = clamped.origin.x, - .y = clamped.origin.y, - .width = clamped.size.width, - .height = clamped.size.height, - }; - } - break; - case META_ROUNDING_STRATEGY_ROUND: - { - *dest = (MetaRectangle) { - .x = roundf (rect->origin.x), - .y = roundf (rect->origin.y), - .width = roundf (rect->size.width), - .height = roundf (rect->size.height), - }; - } - } -} - -void -meta_rectangle_crop_and_scale (const MetaRectangle *rect, - graphene_rect_t *src_rect, - int dst_width, - int dst_height, - MetaRectangle *dest) -{ - graphene_rect_t tmp = GRAPHENE_RECT_INIT (rect->x, rect->y, - rect->width, rect->height); - - graphene_rect_scale (&tmp, - src_rect->size.width / dst_width, - src_rect->size.height / dst_height, - &tmp); - graphene_rect_offset (&tmp, src_rect->origin.x, src_rect->origin.y); - - meta_rectangle_from_graphene_rect (&tmp, META_ROUNDING_STRATEGY_GROW, dest); -} diff --git a/src/core/constraints.c b/src/core/constraints.c deleted file mode 100644 index 4b1d95338..000000000 --- a/src/core/constraints.c +++ /dev/null @@ -1,1878 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter size/position constraints */ - -/* - * Copyright (C) 2002, 2003 Red Hat, Inc. - * Copyright (C) 2003, 2004 Rob Adams - * Copyright (C) 2005, 2006 Elijah Newren - * - * 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 . - */ - -#include "config.h" - -#include "core/constraints.h" - -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-logical-monitor.h" -#include "backends/meta-monitor-manager-private.h" -#include "core/boxes-private.h" -#include "core/meta-workspace-manager-private.h" -#include "core/place.h" -#include "core/workspace-private.h" -#include "meta/prefs.h" - -#if 0 - // This is the short and sweet version of how to hack on this file; see - // doc/how-constraints-works.txt for the gory details. The basics of - // understanding this file can be shown by the steps needed to add a new - // constraint, which are: - // 1) Add a new entry in the ConstraintPriority enum; higher values - // have higher priority - // 2) Write a new function following the format of the example below, - // "constrain_whatever". - // 3) Add your function to the all_constraints and all_constraint_names - // arrays (the latter of which is for debugging purposes) - // - // An example constraint function, constrain_whatever: - // - // /* constrain_whatever does the following: - // * Quits (returning true) if priority is higher than PRIORITY_WHATEVER - // * If check_only is TRUE - // * Returns whether the constraint is satisfied or not - // * otherwise - // * Enforces the constraint - // * Note that the value of PRIORITY_WHATEVER is centralized with the - // * priorities of other constraints in the definition of ConstrainPriority - // * for easier maintenance and shuffling of priorities. - // */ - // static gboolean - // constrain_whatever (MetaWindow *window, - // ConstraintInfo *info, - // ConstraintPriority priority, - // gboolean check_only) - // { - // if (priority > PRIORITY_WHATEVER) - // return TRUE; - // - // /* Determine whether constraint applies; note that if the constraint - // * cannot possibly be satisfied, constraint_applies should be set to - // * false. If we don't do this, all constraints with a lesser priority - // * will be dropped along with this one, and we'd rather apply as many as - // * possible. - // */ - // if (!constraint_applies) - // return TRUE; - // - // /* Determine whether constraint is already satisfied; if we're only - // * checking the status of whether the constraint is satisfied, we end - // * here. - // */ - // if (check_only || constraint_already_satisfied) - // return constraint_already_satisfied; - // - // /* Enforce constraints */ - // return TRUE; /* Note that we exited early if check_only is FALSE; also, - // * we know we can return TRUE here because we exited early - // * if the constraint could not be satisfied; not that the - // * return value is heeded in this case... - // */ - // } -#endif - -typedef enum -{ - PRIORITY_MINIMUM = 0, /* Dummy value used for loop start = min(all priorities) */ - PRIORITY_ASPECT_RATIO = 0, - PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_MONITOR = 0, - PRIORITY_ENTIRELY_VISIBLE_ON_WORKAREA = 1, - PRIORITY_SIZE_HINTS_INCREMENTS = 1, - PRIORITY_MAXIMIZATION = 2, - PRIORITY_TILING = 2, - PRIORITY_FULLSCREEN = 2, - PRIORITY_SIZE_HINTS_LIMITS = 3, - PRIORITY_TITLEBAR_VISIBLE = 4, - PRIORITY_PARTIALLY_VISIBLE_ON_WORKAREA = 4, - PRIORITY_CUSTOM_RULE = 4, - PRIORITY_MAXIMUM = 4 /* Dummy value used for loop end = max(all priorities) */ -} ConstraintPriority; - -typedef enum -{ - ACTION_MOVE, - ACTION_RESIZE, - ACTION_MOVE_AND_RESIZE -} ActionType; - -typedef struct -{ - MetaRectangle orig; - MetaRectangle current; - MetaRectangle temporary; - int rel_x; - int rel_y; - ActionType action_type; - gboolean is_user_action; - - /* I know that these two things probably look similar at first, but they - * have much different uses. See doc/how-constraints-works.txt for for - * explanation of the differences and similarity between resize_gravity - * and fixed_directions - */ - MetaGravity resize_gravity; - FixedDirections fixed_directions; - - /* work_area_monitor - current monitor region minus struts - * entire_monitor - current monitor, including strut regions - */ - MetaRectangle work_area_monitor; - MetaRectangle entire_monitor; - - /* Spanning rectangles for the non-covered (by struts) region of the - * screen and also for just the current monitor - */ - GList *usable_screen_region; - GList *usable_monitor_region; - - MetaMoveResizeFlags flags; -} ConstraintInfo; - -static gboolean do_screen_and_monitor_relative_constraints (MetaWindow *window, - GList *region_spanning_rectangles, - ConstraintInfo *info, - gboolean check_only); -static gboolean constrain_custom_rule (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only); -static gboolean constrain_modal_dialog (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only); -static gboolean constrain_maximization (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only); -static gboolean constrain_tiling (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only); -static gboolean constrain_fullscreen (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only); -static gboolean constrain_size_increments (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only); -static gboolean constrain_size_limits (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only); -static gboolean constrain_aspect_ratio (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only); -static gboolean constrain_to_single_monitor (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only); -static gboolean constrain_fully_onscreen (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only); -static gboolean constrain_titlebar_visible (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only); -static gboolean constrain_partially_onscreen (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only); - -static void setup_constraint_info (ConstraintInfo *info, - MetaWindow *window, - MetaMoveResizeFlags flags, - MetaGravity resize_gravity, - const MetaRectangle *orig, - MetaRectangle *new); -static void place_window_if_needed (MetaWindow *window, - ConstraintInfo *info); -static void update_onscreen_requirements (MetaWindow *window, - ConstraintInfo *info); - -typedef gboolean (* ConstraintFunc) (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only); - -typedef struct { - ConstraintFunc func; - const char* name; -} Constraint; - -static const Constraint all_constraints[] = { - {constrain_custom_rule, "constrain_custom_rule"}, - {constrain_modal_dialog, "constrain_modal_dialog"}, - {constrain_maximization, "constrain_maximization"}, - {constrain_tiling, "constrain_tiling"}, - {constrain_fullscreen, "constrain_fullscreen"}, - {constrain_size_increments, "constrain_size_increments"}, - {constrain_size_limits, "constrain_size_limits"}, - {constrain_aspect_ratio, "constrain_aspect_ratio"}, - {constrain_to_single_monitor, "constrain_to_single_monitor"}, - {constrain_fully_onscreen, "constrain_fully_onscreen"}, - {constrain_titlebar_visible, "constrain_titlebar_visible"}, - {constrain_partially_onscreen, "constrain_partially_onscreen"}, - {NULL, NULL} -}; - -static gboolean -do_all_constraints (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only) -{ - const Constraint *constraint; - gboolean satisfied; - - constraint = &all_constraints[0]; - satisfied = TRUE; - while (constraint->func != NULL) - { - satisfied = satisfied && - (*constraint->func) (window, info, priority, check_only); - - if (!check_only) - { - /* Log how the constraint modified the position */ - meta_topic (META_DEBUG_GEOMETRY, - "info->current is %d,%d +%d,%d after %s", - info->current.x, info->current.y, - info->current.width, info->current.height, - constraint->name); - } - else if (!satisfied) - { - /* Log which constraint was not satisfied */ - meta_topic (META_DEBUG_GEOMETRY, - "constraint %s not satisfied.", - constraint->name); - return FALSE; - } - ++constraint; - } - - return TRUE; -} - -void -meta_window_constrain (MetaWindow *window, - MetaMoveResizeFlags flags, - MetaGravity resize_gravity, - const MetaRectangle *orig, - MetaRectangle *new, - MetaRectangle *temporary, - int *rel_x, - int *rel_y) -{ - ConstraintInfo info; - ConstraintPriority priority = PRIORITY_MINIMUM; - gboolean satisfied = FALSE; - - meta_topic (META_DEBUG_GEOMETRY, - "Constraining %s in move from %d,%d %dx%d to %d,%d %dx%d", - window->desc, - orig->x, orig->y, orig->width, orig->height, - new->x, new->y, new->width, new->height); - - setup_constraint_info (&info, - window, - flags, - resize_gravity, - orig, - new); - place_window_if_needed (window, &info); - - while (!satisfied && priority <= PRIORITY_MAXIMUM) { - gboolean check_only = TRUE; - - /* Individually enforce all the high-enough priority constraints */ - do_all_constraints (window, &info, priority, !check_only); - - /* Check if all high-enough priority constraints are simultaneously - * satisfied - */ - satisfied = do_all_constraints (window, &info, priority, check_only); - - /* Drop the least important constraints if we can't satisfy them all */ - priority++; - } - - /* Make sure we use the constrained position */ - *new = info.current; - *temporary = info.temporary; - *rel_x = info.rel_x; - *rel_y = info.rel_y; - - /* We may need to update window->require_fully_onscreen, - * window->require_on_single_monitor, and perhaps other quantities - * if this was a user move or user move-and-resize operation. - */ - update_onscreen_requirements (window, &info); -} - -static void -setup_constraint_info (ConstraintInfo *info, - MetaWindow *window, - MetaMoveResizeFlags flags, - MetaGravity resize_gravity, - const MetaRectangle *orig, - MetaRectangle *new) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaLogicalMonitor *logical_monitor; - MetaWorkspace *cur_workspace; - - info->orig = *orig; - info->current = *new; - info->temporary = *orig; - info->rel_x = 0; - info->rel_y = 0; - info->flags = flags; - - if (info->current.width < 1) - info->current.width = 1; - if (info->current.height < 1) - info->current.height = 1; - - if (flags & META_MOVE_RESIZE_MOVE_ACTION && flags & META_MOVE_RESIZE_RESIZE_ACTION) - info->action_type = ACTION_MOVE_AND_RESIZE; - else if (flags & META_MOVE_RESIZE_RESIZE_ACTION) - info->action_type = ACTION_RESIZE; - else if (flags & META_MOVE_RESIZE_MOVE_ACTION) - info->action_type = ACTION_MOVE; - else - g_error ("BAD, BAD developer! No treat for you! (Fix your calls to " - "meta_window_move_resize_internal())."); - - info->is_user_action = (flags & META_MOVE_RESIZE_USER_ACTION); - - info->resize_gravity = resize_gravity; - - /* FIXME: fixed_directions might be more sane if we (a) made it - * depend on the grab_op type instead of current amount of movement - * (thus implying that it only has effect when user_action is true, - * and (b) ignored it for aspect ratio windows -- at least in those - * cases where both directions do actually change size. - */ - info->fixed_directions = FIXED_DIRECTION_NONE; - /* If x directions don't change but either y direction does */ - if ( orig->x == new->x && orig->x + orig->width == new->x + new->width && - (orig->y != new->y || orig->y + orig->height != new->y + new->height)) - { - info->fixed_directions = FIXED_DIRECTION_X; - } - /* If y directions don't change but either x direction does */ - if ( orig->y == new->y && orig->y + orig->height == new->y + new->height && - (orig->x != new->x || orig->x + orig->width != new->x + new->width )) - { - info->fixed_directions = FIXED_DIRECTION_Y; - } - /* The point of fixed directions is just that "move to nearest valid - * position" is sometimes a poorer choice than "move to nearest - * valid position but only change this coordinate" for windows the - * user is explicitly moving. This isn't ever true for things that - * aren't explicit user interaction, though, so just clear it out. - */ - if (!info->is_user_action) - info->fixed_directions = FIXED_DIRECTION_NONE; - - logical_monitor = - meta_monitor_manager_get_logical_monitor_from_rect (monitor_manager, - &info->current); - meta_window_get_work_area_for_logical_monitor (window, - logical_monitor, - &info->work_area_monitor); - - if (window->fullscreen && meta_window_has_fullscreen_monitors (window)) - { - info->entire_monitor = window->fullscreen_monitors.top->rect; - meta_rectangle_union (&info->entire_monitor, - &window->fullscreen_monitors.bottom->rect, - &info->entire_monitor); - meta_rectangle_union (&info->entire_monitor, - &window->fullscreen_monitors.left->rect, - &info->entire_monitor); - meta_rectangle_union (&info->entire_monitor, - &window->fullscreen_monitors.right->rect, - &info->entire_monitor); - } - else - { - info->entire_monitor = logical_monitor->rect; - if (window->fullscreen) - meta_window_adjust_fullscreen_monitor_rect (window, &info->entire_monitor); - } - - cur_workspace = window->display->workspace_manager->active_workspace; - info->usable_screen_region = - meta_workspace_get_onscreen_region (cur_workspace); - info->usable_monitor_region = - meta_workspace_get_onmonitor_region (cur_workspace, logical_monitor); - - /* Log all this information for debugging */ - meta_topic (META_DEBUG_GEOMETRY, - "Setting up constraint info:\n" - " orig: %d,%d +%d,%d\n" - " new : %d,%d +%d,%d\n" - " action_type : %s\n" - " is_user_action : %s\n" - " resize_gravity : %s\n" - " fixed_directions: %s\n" - " work_area_monitor: %d,%d +%d,%d\n" - " entire_monitor : %d,%d +%d,%d", - info->orig.x, info->orig.y, info->orig.width, info->orig.height, - info->current.x, info->current.y, - info->current.width, info->current.height, - (info->action_type == ACTION_MOVE) ? "Move" : - (info->action_type == ACTION_RESIZE) ? "Resize" : - (info->action_type == ACTION_MOVE_AND_RESIZE) ? "Move&Resize" : - "Freakin' Invalid Stupid", - (info->is_user_action) ? "true" : "false", - meta_gravity_to_string (info->resize_gravity), - (info->fixed_directions == FIXED_DIRECTION_NONE) ? "None" : - (info->fixed_directions == FIXED_DIRECTION_X) ? "X fixed" : - (info->fixed_directions == FIXED_DIRECTION_Y) ? "Y fixed" : - "Freakin' Invalid Stupid", - info->work_area_monitor.x, info->work_area_monitor.y, - info->work_area_monitor.width, - info->work_area_monitor.height, - info->entire_monitor.x, info->entire_monitor.y, - info->entire_monitor.width, info->entire_monitor.height); -} - -static MetaRectangle * -get_start_rect_for_resize (MetaWindow *window, - ConstraintInfo *info) -{ - if (!info->is_user_action && info->action_type == ACTION_MOVE_AND_RESIZE) - return &info->current; - else - return &info->orig; -} - -static void -place_window_if_needed(MetaWindow *window, - ConstraintInfo *info) -{ - gboolean did_placement; - - /* Do placement if any, so we go ahead and apply position - * constraints in a move-only context. Don't place - * maximized/minimized/fullscreen windows until they are - * unmaximized, unminimized and unfullscreened. - */ - did_placement = FALSE; - if (!window->placed && - window->calc_placement && - !(window->maximized_horizontally || - window->maximized_vertically) && - !window->minimized && - !window->fullscreen) - { - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaRectangle orig_rect; - MetaRectangle placed_rect; - MetaWorkspace *cur_workspace; - MetaLogicalMonitor *logical_monitor; - - placed_rect = (MetaRectangle) { - .x = window->rect.x, - .y = window->rect.y, - .width = info->current.width, - .height = info->current.height - }; - - orig_rect = info->orig; - - if (window->placement.rule) - { - meta_window_process_placement (window, - window->placement.rule, - &info->rel_x, &info->rel_y); - placed_rect.x = window->placement.rule->parent_rect.x + info->rel_x; - placed_rect.y = window->placement.rule->parent_rect.y + info->rel_y; - } - else - { - meta_window_place (window, orig_rect.x, orig_rect.y, - &placed_rect.x, &placed_rect.y); - } - did_placement = TRUE; - - /* placing the window may have changed the monitor. Find the - * new monitor and update the ConstraintInfo - */ - logical_monitor = - meta_monitor_manager_get_logical_monitor_from_rect (monitor_manager, - &placed_rect); - info->entire_monitor = logical_monitor->rect; - meta_window_get_work_area_for_logical_monitor (window, - logical_monitor, - &info->work_area_monitor); - cur_workspace = window->display->workspace_manager->active_workspace; - info->usable_monitor_region = - meta_workspace_get_onmonitor_region (cur_workspace, logical_monitor); - - info->current.x = placed_rect.x; - info->current.y = placed_rect.y; - - /* Since we just barely placed the window, there's no reason to - * consider any of the directions fixed. - */ - info->fixed_directions = FIXED_DIRECTION_NONE; - } - - if (window->placed || did_placement) - { - if (window->maximize_horizontally_after_placement || - window->maximize_vertically_after_placement) - { - /* define a sane saved_rect so that the user can unmaximize to - * something reasonable. - */ - if (info->current.width >= info->work_area_monitor.width) - { - info->current.width = .75 * info->work_area_monitor.width; - info->current.x = info->work_area_monitor.x + - .125 * info->work_area_monitor.width; - } - if (info->current.height >= info->work_area_monitor.height) - { - info->current.height = .75 * info->work_area_monitor.height; - info->current.y = info->work_area_monitor.y + - .083 * info->work_area_monitor.height; - } - - /* idle_move_resize() uses the unconstrained_rect, so make sure it - * uses the placed coordinates (bug #556696). - */ - window->unconstrained_rect = info->current; - - if (window->maximize_horizontally_after_placement || - window->maximize_vertically_after_placement) - meta_window_maximize_internal (window, - (window->maximize_horizontally_after_placement ? - META_MAXIMIZE_HORIZONTAL : 0 ) | - (window->maximize_vertically_after_placement ? - META_MAXIMIZE_VERTICAL : 0), &info->current); - - window->maximize_horizontally_after_placement = FALSE; - window->maximize_vertically_after_placement = FALSE; - } - if (window->minimize_after_placement) - { - meta_window_minimize (window); - window->minimize_after_placement = FALSE; - } - } -} - -static void -update_onscreen_requirements (MetaWindow *window, - ConstraintInfo *info) -{ - gboolean old; - - /* We only apply the various onscreen requirements to normal windows */ - if (window->type == META_WINDOW_DESKTOP || - window->type == META_WINDOW_DOCK) - return; - - /* We don't want to update the requirements for fullscreen windows; - * fullscreen windows are specially handled anyway, and it updating - * the requirements when windows enter fullscreen mode mess up the - * handling of the window when it leaves that mode (especially when - * the application sends a bunch of configurerequest events). See - * #353699. - */ - if (window->fullscreen) - return; - - /* USABILITY NOTE: Naturally, I only want the require_fully_onscreen, - * require_on_single_monitor, and require_titlebar_visible flags to - * *become false* due to user interactions (which is allowed since - * certain constraints are ignored for user interactions regardless of - * the setting of these flags). However, whether to make these flags - * *become true* due to just an application interaction is a little - * trickier. It's possible that users may find not doing that strange - * since two application interactions that resize in opposite ways don't - * necessarily end up cancelling--but it may also be strange for the user - * to have an application resize the window so that it's onscreen, the - * user forgets about it, and then later the app is able to resize itself - * off the screen. Anyway, for now, I think the latter is the more - * problematic case but this may need to be revisited. - */ - - /* Update whether we want future constraint runs to require the - * window to be on fully onscreen. - */ - old = window->require_fully_onscreen; - window->require_fully_onscreen = - meta_rectangle_contained_in_region (info->usable_screen_region, - &info->current); - if (old != window->require_fully_onscreen) - meta_topic (META_DEBUG_GEOMETRY, - "require_fully_onscreen for %s toggled to %s", - window->desc, - window->require_fully_onscreen ? "TRUE" : "FALSE"); - - /* Update whether we want future constraint runs to require the - * window to be on a single monitor. - */ - old = window->require_on_single_monitor; - window->require_on_single_monitor = - meta_rectangle_contained_in_region (info->usable_monitor_region, - &info->current); - if (old != window->require_on_single_monitor) - meta_topic (META_DEBUG_GEOMETRY, - "require_on_single_monitor for %s toggled to %s", - window->desc, - window->require_on_single_monitor ? "TRUE" : "FALSE"); - - /* Update whether we want future constraint runs to require the - * titlebar to be visible. - */ - if (window->frame && window->decorated) - { - MetaRectangle titlebar_rect, frame_rect; - - meta_window_get_titlebar_rect (window, &titlebar_rect); - meta_window_get_frame_rect (window, &frame_rect); - - /* translate into screen coordinates */ - titlebar_rect.x = frame_rect.x; - titlebar_rect.y = frame_rect.y; - - old = window->require_titlebar_visible; - window->require_titlebar_visible = - meta_rectangle_overlaps_with_region (info->usable_screen_region, - &titlebar_rect); - if (old != window->require_titlebar_visible) - meta_topic (META_DEBUG_GEOMETRY, - "require_titlebar_visible for %s toggled to %s", - window->desc, - window->require_titlebar_visible ? "TRUE" : "FALSE"); - } -} - -static inline void -get_size_limits (MetaWindow *window, - MetaRectangle *min_size, - MetaRectangle *max_size) -{ - /* We pack the results into MetaRectangle structs just for convenience; we - * don't actually use the position of those rects. - */ - min_size->x = min_size->y = max_size->x = max_size->y = 0; - min_size->width = window->size_hints.min_width; - min_size->height = window->size_hints.min_height; - max_size->width = window->size_hints.max_width; - max_size->height = window->size_hints.max_height; - - meta_window_client_rect_to_frame_rect (window, min_size, min_size); - meta_window_client_rect_to_frame_rect (window, max_size, max_size); -} - -static void -placement_rule_flip_horizontally (MetaPlacementRule *placement_rule) -{ - if (placement_rule->anchor & META_PLACEMENT_ANCHOR_LEFT) - { - placement_rule->anchor &= ~META_PLACEMENT_ANCHOR_LEFT; - placement_rule->anchor |= META_PLACEMENT_ANCHOR_RIGHT; - } - else if (placement_rule->anchor & META_PLACEMENT_ANCHOR_RIGHT) - { - placement_rule->anchor &= ~META_PLACEMENT_ANCHOR_RIGHT; - placement_rule->anchor |= META_PLACEMENT_ANCHOR_LEFT; - } - - if (placement_rule->gravity & META_PLACEMENT_GRAVITY_LEFT) - { - placement_rule->gravity &= ~META_PLACEMENT_GRAVITY_LEFT; - placement_rule->gravity |= META_PLACEMENT_GRAVITY_RIGHT; - } - else if (placement_rule->gravity & META_PLACEMENT_GRAVITY_RIGHT) - { - placement_rule->gravity &= ~META_PLACEMENT_GRAVITY_RIGHT; - placement_rule->gravity |= META_PLACEMENT_GRAVITY_LEFT; - } -} - -static void -placement_rule_flip_vertically (MetaPlacementRule *placement_rule) -{ - if (placement_rule->anchor & META_PLACEMENT_ANCHOR_TOP) - { - placement_rule->anchor &= ~META_PLACEMENT_ANCHOR_TOP; - placement_rule->anchor |= META_PLACEMENT_ANCHOR_BOTTOM; - } - else if (placement_rule->anchor & META_PLACEMENT_ANCHOR_BOTTOM) - { - placement_rule->anchor &= ~META_PLACEMENT_ANCHOR_BOTTOM; - placement_rule->anchor |= META_PLACEMENT_ANCHOR_TOP; - } - - if (placement_rule->gravity & META_PLACEMENT_GRAVITY_TOP) - { - placement_rule->gravity &= ~META_PLACEMENT_GRAVITY_TOP; - placement_rule->gravity |= META_PLACEMENT_GRAVITY_BOTTOM; - } - else if (placement_rule->gravity & META_PLACEMENT_GRAVITY_BOTTOM) - { - placement_rule->gravity &= ~META_PLACEMENT_GRAVITY_BOTTOM; - placement_rule->gravity |= META_PLACEMENT_GRAVITY_TOP; - } -} - -static void -try_flip_window_position (MetaWindow *window, - ConstraintInfo *info, - MetaPlacementRule *placement_rule, - MetaPlacementConstraintAdjustment constraint_adjustment, - int parent_x, - int parent_y, - MetaRectangle *rect, - int *rel_x, - int *rel_y, - MetaRectangle *intersection) -{ - MetaPlacementRule flipped_rule = *placement_rule; - MetaRectangle flipped_rect; - MetaRectangle flipped_intersection; - int flipped_rel_x; - int flipped_rel_y; - - switch (constraint_adjustment) - { - case META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_X: - placement_rule_flip_horizontally (&flipped_rule); - break; - case META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_Y: - placement_rule_flip_vertically (&flipped_rule); - break; - - default: - g_assert_not_reached (); - } - - flipped_rect = info->current; - meta_window_process_placement (window, &flipped_rule, - &flipped_rel_x, &flipped_rel_y); - flipped_rect.x = parent_x + flipped_rel_x; - flipped_rect.y = parent_y + flipped_rel_y; - meta_rectangle_intersect (&flipped_rect, &info->work_area_monitor, - &flipped_intersection); - - if ((constraint_adjustment == META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_X && - flipped_intersection.width == flipped_rect.width) || - (constraint_adjustment == META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_Y && - flipped_intersection.height == flipped_rect.height)) - { - *placement_rule = flipped_rule; - *rect = flipped_rect; - *rel_x = flipped_rel_x; - *rel_y = flipped_rel_y; - *intersection = flipped_intersection; - } -} - -static gboolean -is_custom_rule_satisfied (MetaRectangle *rect, - MetaPlacementRule *placement_rule, - MetaRectangle *intersection) -{ - uint32_t x_constrain_actions, y_constrain_actions; - - x_constrain_actions = (META_PLACEMENT_CONSTRAINT_ADJUSTMENT_SLIDE_X | - META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_X); - y_constrain_actions = (META_PLACEMENT_CONSTRAINT_ADJUSTMENT_SLIDE_Y | - META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_Y); - if ((placement_rule->constraint_adjustment & x_constrain_actions && - rect->width != intersection->width) || - (placement_rule->constraint_adjustment & y_constrain_actions && - rect->height != intersection->height)) - return FALSE; - else - return TRUE; -} - -static gboolean -constrain_custom_rule (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only) -{ - MetaPlacementRule *placement_rule; - MetaRectangle intersection; - gboolean constraint_satisfied; - MetaRectangle temporary_rect; - MetaRectangle adjusted_unconstrained; - int adjusted_rel_x; - int adjusted_rel_y; - MetaPlacementRule current_rule; - MetaWindow *parent; - int parent_x, parent_y; - - if (priority > PRIORITY_CUSTOM_RULE) - return TRUE; - - placement_rule = meta_window_get_placement_rule (window); - if (!placement_rule) - return TRUE; - - parent = meta_window_get_transient_for (window); - if (window->placement.state == META_PLACEMENT_STATE_CONSTRAINED_FINISHED) - { - placement_rule->parent_rect.x = parent->rect.x; - placement_rule->parent_rect.y = parent->rect.y; - } - parent_x = placement_rule->parent_rect.x; - parent_y = placement_rule->parent_rect.y; - - /* - * Calculate the temporary position, meaning a position that will be - * applied if the new constrained position requires asynchronous - * configuration of the window. This happens for example when the parent - * moves, causing this window to change relative position, meaning it can - * only have its newly constrained position applied when the configuration is - * acknowledged. - */ - - switch (window->placement.state) - { - case META_PLACEMENT_STATE_UNCONSTRAINED: - temporary_rect = info->current; - break; - case META_PLACEMENT_STATE_CONSTRAINED_CONFIGURED: - case META_PLACEMENT_STATE_CONSTRAINED_PENDING: - case META_PLACEMENT_STATE_CONSTRAINED_FINISHED: - case META_PLACEMENT_STATE_INVALIDATED: - temporary_rect = (MetaRectangle) { - .x = parent->rect.x + window->placement.current.rel_x, - .y = parent->rect.y + window->placement.current.rel_y, - .width = info->current.width, - .height = info->current.height, - }; - break; - } - - /* - * Calculate an adjusted current position. Depending on the rule - * configuration and placement state, this may result in window being - * reconstrained. - */ - - adjusted_unconstrained = temporary_rect; - - if (window->placement.state == META_PLACEMENT_STATE_INVALIDATED || - window->placement.state == META_PLACEMENT_STATE_UNCONSTRAINED || - (window->placement.state == META_PLACEMENT_STATE_CONSTRAINED_FINISHED && - placement_rule->is_reactive)) - { - meta_window_process_placement (window, placement_rule, - &adjusted_rel_x, - &adjusted_rel_y); - adjusted_unconstrained.x = parent_x + adjusted_rel_x; - adjusted_unconstrained.y = parent_y + adjusted_rel_y; - } - else if (window->placement.state == META_PLACEMENT_STATE_CONSTRAINED_PENDING) - { - adjusted_rel_x = window->placement.pending.rel_x; - adjusted_rel_y = window->placement.pending.rel_y; - adjusted_unconstrained.x = window->placement.pending.x; - adjusted_unconstrained.y = window->placement.pending.y; - } - else - { - adjusted_rel_x = window->placement.current.rel_x; - adjusted_rel_y = window->placement.current.rel_y; - } - - meta_rectangle_intersect (&adjusted_unconstrained, &info->work_area_monitor, - &intersection); - - constraint_satisfied = (meta_rectangle_equal (&info->current, - &adjusted_unconstrained) && - is_custom_rule_satisfied (&adjusted_unconstrained, - placement_rule, - &intersection)); - - if (check_only) - return constraint_satisfied; - - info->current = adjusted_unconstrained; - info->rel_x = adjusted_rel_x; - info->rel_y = adjusted_rel_y; - info->temporary = temporary_rect; - - switch (window->placement.state) - { - case META_PLACEMENT_STATE_CONSTRAINED_FINISHED: - if (!placement_rule->is_reactive) - return TRUE; - break; - case META_PLACEMENT_STATE_CONSTRAINED_PENDING: - case META_PLACEMENT_STATE_CONSTRAINED_CONFIGURED: - return TRUE; - case META_PLACEMENT_STATE_UNCONSTRAINED: - case META_PLACEMENT_STATE_INVALIDATED: - break; - } - - if (constraint_satisfied) - goto done; - - /* - * Process the placement rule in order either until constraints are - * satisfied, or there are no more rules to process. - */ - - current_rule = *placement_rule; - - if (info->current.width != intersection.width && - (current_rule.constraint_adjustment & - META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_X)) - { - try_flip_window_position (window, info, ¤t_rule, - META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_X, - parent_x, - parent_y, - &info->current, - &info->rel_x, - &info->rel_y, - &intersection); - } - if (info->current.height != intersection.height && - (current_rule.constraint_adjustment & - META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_Y)) - { - try_flip_window_position (window, info, ¤t_rule, - META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_Y, - parent_x, - parent_y, - &info->current, - &info->rel_x, - &info->rel_y, - &intersection); - } - - meta_rectangle_intersect (&info->current, &info->work_area_monitor, - &intersection); - constraint_satisfied = is_custom_rule_satisfied (&info->current, - placement_rule, - &intersection); - - if (constraint_satisfied) - goto done; - - if (current_rule.constraint_adjustment & - META_PLACEMENT_CONSTRAINT_ADJUSTMENT_SLIDE_X) - { - int current_x2; - int work_area_monitor_x2; - int new_x; - - current_x2 = info->current.x + info->current.width; - work_area_monitor_x2 = (info->work_area_monitor.x + - info->work_area_monitor.width); - - if (current_x2 > work_area_monitor_x2) - { - new_x = MAX (info->work_area_monitor.x, - work_area_monitor_x2 - info->current.width); - } - else if (info->current.x < info->work_area_monitor.x) - { - new_x = info->work_area_monitor.x; - } - else - { - new_x = info->current.x; - } - - info->rel_x += new_x - info->current.x; - info->current.x = new_x; - } - if (current_rule.constraint_adjustment & - META_PLACEMENT_CONSTRAINT_ADJUSTMENT_SLIDE_Y) - { - int current_y2; - int work_area_monitor_y2; - int new_y; - - current_y2 = info->current.y + info->current.height; - work_area_monitor_y2 = (info->work_area_monitor.y + - info->work_area_monitor.height); - - if (current_y2 > work_area_monitor_y2) - { - new_y = MAX (info->work_area_monitor.y, - work_area_monitor_y2 - info->current.height); - } - else if (info->current.y < info->work_area_monitor.y) - { - new_y = info->work_area_monitor.y; - } - else - { - new_y = info->current.y; - } - - info->rel_y += new_y - info->current.y; - info->current.y = new_y; - } - - meta_rectangle_intersect (&info->current, &info->work_area_monitor, - &intersection); - constraint_satisfied = is_custom_rule_satisfied (&info->current, - placement_rule, - &intersection); - - if (constraint_satisfied) - goto done; - - if (current_rule.constraint_adjustment & - META_PLACEMENT_CONSTRAINT_ADJUSTMENT_RESIZE_X) - { - int new_x; - new_x = intersection.x; - info->current.width = intersection.width; - info->rel_x += new_x - info->current.x; - info->current.x = new_x; - } - if (current_rule.constraint_adjustment & - META_PLACEMENT_CONSTRAINT_ADJUSTMENT_RESIZE_Y) - { - int new_y; - new_y = intersection.y; - info->current.height = intersection.height; - info->rel_y += new_y - info->current.y; - info->current.y = new_y; - } - -done: - window->placement.state = META_PLACEMENT_STATE_CONSTRAINED_PENDING; - - window->placement.pending.rel_x = info->rel_x; - window->placement.pending.rel_y = info->rel_y; - window->placement.pending.x = info->current.x; - window->placement.pending.y = info->current.y; - - return TRUE; -} - -static gboolean -constrain_modal_dialog (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only) -{ - int x, y; - MetaWindow *parent = meta_window_get_transient_for (window); - MetaRectangle child_rect, parent_rect; - gboolean constraint_already_satisfied; - - if (!parent || - !meta_window_is_attached_dialog (window) || - meta_window_get_placement_rule (window)) - return TRUE; - - /* We want to center the dialog on the parent, including the decorations - for both of them. info->current is in client X window coordinates, so we need - to convert them to frame coordinates, apply the centering and then - convert back to client. - */ - - child_rect = info->current; - - meta_window_get_frame_rect (parent, &parent_rect); - - child_rect.x = parent_rect.x + (parent_rect.width / 2 - child_rect.width / 2); - child_rect.y = parent_rect.y + (parent_rect.height / 2 - child_rect.height / 2); - x = child_rect.x; - y = child_rect.y; - - constraint_already_satisfied = (x == info->current.x) && (y == info->current.y); - - if (check_only || constraint_already_satisfied) - return constraint_already_satisfied; - - info->current.y = y; - info->current.x = x; - /* The calculated position above may need adjustment to make sure the - * dialog does not end up partially off-screen */ - return do_screen_and_monitor_relative_constraints (window, - info->usable_screen_region, - info, - check_only); -} - -static gboolean -constrain_maximization (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only) -{ - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - MetaRectangle target_size; - MetaRectangle min_size, max_size; - gboolean hminbad, vminbad; - gboolean horiz_equal, vert_equal; - gboolean constraint_already_satisfied; - - if (priority > PRIORITY_MAXIMIZATION) - return TRUE; - - /* Determine whether constraint applies; exit if it doesn't */ - if ((!window->maximized_horizontally && !window->maximized_vertically) || - META_WINDOW_TILED_SIDE_BY_SIDE (window)) - return TRUE; - - /* Calculate target_size = maximized size of (window + frame) */ - if (META_WINDOW_TILED_MAXIMIZED (window)) - { - meta_window_get_tile_area (window, window->tile_mode, &target_size); - } - else if (META_WINDOW_MAXIMIZED (window)) - { - target_size = info->work_area_monitor; - } - else - { - /* Amount of maximization possible in a single direction depends - * on which struts could occlude the window given its current - * position. For example, a vertical partial strut on the right - * is only relevant for a horizontally maximized window when the - * window is at a vertical position where it could be occluded - * by that partial strut. - */ - MetaDirection direction; - GSList *active_workspace_struts; - - if (window->maximized_horizontally) - direction = META_DIRECTION_HORIZONTAL; - else - direction = META_DIRECTION_VERTICAL; - active_workspace_struts = workspace_manager->active_workspace->all_struts; - - target_size = info->current; - meta_rectangle_expand_to_avoiding_struts (&target_size, - &info->entire_monitor, - direction, - active_workspace_struts); - } - - /* Check min size constraints; max size constraints are ignored for maximized - * windows, as per bug 327543. - */ - get_size_limits (window, &min_size, &max_size); - hminbad = target_size.width < min_size.width && window->maximized_horizontally; - vminbad = target_size.height < min_size.height && window->maximized_vertically; - if (hminbad || vminbad) - return TRUE; - - /* Determine whether constraint is already satisfied; exit if it is */ - horiz_equal = target_size.x == info->current.x && - target_size.width == info->current.width; - vert_equal = target_size.y == info->current.y && - target_size.height == info->current.height; - constraint_already_satisfied = - (horiz_equal || !window->maximized_horizontally) && - (vert_equal || !window->maximized_vertically); - if (check_only || constraint_already_satisfied) - return constraint_already_satisfied; - - /*** Enforce constraint ***/ - if (window->maximized_horizontally) - { - info->current.x = target_size.x; - info->current.width = target_size.width; - } - if (window->maximized_vertically) - { - info->current.y = target_size.y; - info->current.height = target_size.height; - } - return TRUE; -} - -static gboolean -constrain_tiling (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only) -{ - MetaRectangle target_size; - MetaRectangle min_size, max_size; - gboolean hminbad, vminbad; - gboolean horiz_equal, vert_equal; - gboolean constraint_already_satisfied; - - if (priority > PRIORITY_TILING) - return TRUE; - - /* Determine whether constraint applies; exit if it doesn't */ - if (!META_WINDOW_TILED_SIDE_BY_SIDE (window)) - return TRUE; - - /* Calculate target_size - as the tile previews need this as well, we - * use an external function for the actual calculation - */ - meta_window_get_tile_area (window, window->tile_mode, &target_size); - - /* Check min size constraints; max size constraints are ignored as for - * maximized windows. - */ - get_size_limits (window, &min_size, &max_size); - hminbad = target_size.width < min_size.width; - vminbad = target_size.height < min_size.height; - if (hminbad || vminbad) - return TRUE; - - /* Determine whether constraint is already satisfied; exit if it is */ - horiz_equal = target_size.x == info->current.x && - target_size.width == info->current.width; - vert_equal = target_size.y == info->current.y && - target_size.height == info->current.height; - constraint_already_satisfied = horiz_equal && vert_equal; - if (check_only || constraint_already_satisfied) - return constraint_already_satisfied; - - /*** Enforce constraint ***/ - info->current.x = target_size.x; - info->current.width = target_size.width; - info->current.y = target_size.y; - info->current.height = target_size.height; - - return TRUE; -} - - -static gboolean -constrain_fullscreen (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only) -{ - MetaRectangle min_size, max_size, monitor; - gboolean too_big, too_small, constraint_already_satisfied; - - if (priority > PRIORITY_FULLSCREEN) - return TRUE; - - /* Determine whether constraint applies; exit if it doesn't */ - if (!window->fullscreen) - return TRUE; - - monitor = info->entire_monitor; - - get_size_limits (window, &min_size, &max_size); - too_big = !meta_rectangle_could_fit_rect (&monitor, &min_size); - too_small = !meta_rectangle_could_fit_rect (&max_size, &monitor); - if (too_big || too_small) - return TRUE; - - /* Determine whether constraint is already satisfied; exit if it is */ - constraint_already_satisfied = - meta_rectangle_equal (&info->current, &monitor); - if (check_only || constraint_already_satisfied) - return constraint_already_satisfied; - - /*** Enforce constraint ***/ - info->current = monitor; - return TRUE; -} - -static gboolean -constrain_size_increments (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only) -{ - int bh, hi, bw, wi, extra_height, extra_width; - int new_width, new_height; - gboolean constraint_already_satisfied; - MetaRectangle *start_rect; - MetaRectangle client_rect; - - if (priority > PRIORITY_SIZE_HINTS_INCREMENTS) - return TRUE; - - /* Determine whether constraint applies; exit if it doesn't */ - if (META_WINDOW_MAXIMIZED (window) || window->fullscreen || - META_WINDOW_TILED_SIDE_BY_SIDE (window) || - info->action_type == ACTION_MOVE) - return TRUE; - - meta_window_frame_rect_to_client_rect (window, &info->current, &client_rect); - - /* Determine whether constraint is already satisfied; exit if it is */ - bh = window->size_hints.base_height; - hi = window->size_hints.height_inc; - bw = window->size_hints.base_width; - wi = window->size_hints.width_inc; - extra_height = (client_rect.height - bh) % hi; - extra_width = (client_rect.width - bw) % wi; - /* ignore size increments for maximized windows */ - if (window->maximized_horizontally) - extra_width *= 0; - if (window->maximized_vertically) - extra_height *= 0; - /* constraint is satisfied iff there is no extra height or width */ - constraint_already_satisfied = - (extra_height == 0 && extra_width == 0); - - if (check_only || constraint_already_satisfied) - return constraint_already_satisfied; - - /*** Enforce constraint ***/ - new_width = client_rect.width - extra_width; - new_height = client_rect.height - extra_height; - - /* Adjusting down instead of up (as done in the above two lines) may - * violate minimum size constraints; fix the adjustment if this - * happens. - */ - if (new_width < window->size_hints.min_width) - new_width += ((window->size_hints.min_width - new_width)/wi + 1)*wi; - if (new_height < window->size_hints.min_height) - new_height += ((window->size_hints.min_height - new_height)/hi + 1)*hi; - - { - client_rect.width = new_width; - client_rect.height = new_height; - meta_window_client_rect_to_frame_rect (window, &client_rect, &client_rect); - new_width = client_rect.width; - new_height = client_rect.height; - } - - start_rect = get_start_rect_for_resize (window, info); - - /* Resize to the new size */ - meta_rectangle_resize_with_gravity (start_rect, - &info->current, - info->resize_gravity, - new_width, - new_height); - return TRUE; -} - -static gboolean -constrain_size_limits (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only) -{ - MetaRectangle min_size, max_size; - gboolean too_big, too_small, constraint_already_satisfied; - int new_width, new_height; - MetaRectangle *start_rect; - - if (priority > PRIORITY_SIZE_HINTS_LIMITS) - return TRUE; - - /* Determine whether constraint applies; exit if it doesn't. - * - * Note: The old code didn't apply this constraint for fullscreen or - * maximized windows--but that seems odd to me. *shrug* - */ - if (info->action_type == ACTION_MOVE) - return TRUE; - - /* Determine whether constraint is already satisfied; exit if it is */ - get_size_limits (window, &min_size, &max_size); - /* We ignore max-size limits for maximized windows; see #327543 */ - if (window->maximized_horizontally) - max_size.width = MAX (max_size.width, info->current.width); - if (window->maximized_vertically) - max_size.height = MAX (max_size.height, info->current.height); - too_small = !meta_rectangle_could_fit_rect (&info->current, &min_size); - too_big = !meta_rectangle_could_fit_rect (&max_size, &info->current); - constraint_already_satisfied = !too_big && !too_small; - if (check_only || constraint_already_satisfied) - return constraint_already_satisfied; - - /*** Enforce constraint ***/ - new_width = CLAMP (info->current.width, min_size.width, max_size.width); - new_height = CLAMP (info->current.height, min_size.height, max_size.height); - - start_rect = get_start_rect_for_resize (window, info); - - meta_rectangle_resize_with_gravity (start_rect, - &info->current, - info->resize_gravity, - new_width, - new_height); - return TRUE; -} - -static gboolean -constrain_aspect_ratio (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only) -{ - double minr, maxr; - gboolean constraints_are_inconsistent, constraint_already_satisfied; - int fudge, new_width, new_height; - double best_width, best_height; - double alt_width, alt_height; - MetaRectangle *start_rect; - MetaRectangle client_rect; - - if (priority > PRIORITY_ASPECT_RATIO) - return TRUE; - - /* Determine whether constraint applies; exit if it doesn't. */ - minr = window->size_hints.min_aspect.x / - (double)window->size_hints.min_aspect.y; - maxr = window->size_hints.max_aspect.x / - (double)window->size_hints.max_aspect.y; - constraints_are_inconsistent = minr > maxr; - if (constraints_are_inconsistent || - META_WINDOW_MAXIMIZED (window) || window->fullscreen || - META_WINDOW_TILED_SIDE_BY_SIDE (window) || - info->action_type == ACTION_MOVE) - return TRUE; - - /* Determine whether constraint is already satisfied; exit if it is. We - * need the following to hold: - * - * width - * minr <= ------ <= maxr - * height - * - * But we need to allow for some slight fudging since width and height - * are integers instead of floating point numbers (this is particularly - * important when minr == maxr), so we allow width and height to be off - * a little bit from strictly satisfying these equations. For just one - * sided resizing, we have to make the fudge factor a little bigger - * because of how meta_rectangle_resize_with_gravity treats those as - * being a resize increment (FIXME: I should handle real resize - * increments better here...) - */ - switch (info->resize_gravity) - { - case META_GRAVITY_WEST: - case META_GRAVITY_NORTH: - case META_GRAVITY_SOUTH: - case META_GRAVITY_EAST: - fudge = 2; - break; - - case META_GRAVITY_NORTH_WEST: - case META_GRAVITY_SOUTH_WEST: - case META_GRAVITY_CENTER: - case META_GRAVITY_NORTH_EAST: - case META_GRAVITY_SOUTH_EAST: - case META_GRAVITY_STATIC: - default: - fudge = 1; - break; - } - - meta_window_frame_rect_to_client_rect (window, &info->current, &client_rect); - - constraint_already_satisfied = - client_rect.width - (client_rect.height * minr ) > -minr*fudge && - client_rect.width - (client_rect.height * maxr ) < maxr*fudge; - if (check_only || constraint_already_satisfied) - return constraint_already_satisfied; - - /*** Enforce constraint ***/ - new_width = client_rect.width; - new_height = client_rect.height; - - switch (info->resize_gravity) - { - case META_GRAVITY_WEST: - case META_GRAVITY_EAST: - /* Yeah, I suck for doing implicit rounding -- sue me */ - new_height = CLAMP (new_height, new_width / maxr, new_width / minr); - break; - - case META_GRAVITY_NORTH: - case META_GRAVITY_SOUTH: - /* Yeah, I suck for doing implicit rounding -- sue me */ - new_width = CLAMP (new_width, new_height * minr, new_height * maxr); - break; - - case META_GRAVITY_NORTH_WEST: - case META_GRAVITY_SOUTH_WEST: - case META_GRAVITY_CENTER: - case META_GRAVITY_NORTH_EAST: - case META_GRAVITY_SOUTH_EAST: - case META_GRAVITY_STATIC: - default: - /* Find what width would correspond to new_height, and what height would - * correspond to new_width */ - alt_width = CLAMP (new_width, new_height * minr, new_height * maxr); - alt_height = CLAMP (new_height, new_width / maxr, new_width / minr); - - /* The line connecting the points (alt_width, new_height) and - * (new_width, alt_height) provide a range of - * valid-for-the-aspect-ratio-constraint sizes. We want the - * size in that range closest to the value requested, i.e. the - * point on the line which is closest to the point (new_width, - * new_height) - */ - meta_rectangle_find_linepoint_closest_to_point (alt_width, new_height, - new_width, alt_height, - new_width, new_height, - &best_width, &best_height); - - /* Yeah, I suck for doing implicit rounding -- sue me */ - new_width = best_width; - new_height = best_height; - - break; - } - - { - client_rect.width = new_width; - client_rect.height = new_height; - meta_window_client_rect_to_frame_rect (window, &client_rect, &client_rect); - new_width = client_rect.width; - new_height = client_rect.height; - } - - start_rect = get_start_rect_for_resize (window, info); - - meta_rectangle_resize_with_gravity (start_rect, - &info->current, - info->resize_gravity, - new_width, - new_height); - - return TRUE; -} - -static gboolean -do_screen_and_monitor_relative_constraints ( - MetaWindow *window, - GList *region_spanning_rectangles, - ConstraintInfo *info, - gboolean check_only) -{ - gboolean exit_early = FALSE, constraint_satisfied; - MetaRectangle how_far_it_can_be_smushed, min_size, max_size; - -#ifdef WITH_VERBOSE_MODE - if (meta_is_verbose ()) - { - /* First, log some debugging information */ - char spanning_region[1 + 28 * g_list_length (region_spanning_rectangles)]; - - meta_topic (META_DEBUG_GEOMETRY, - "screen/monitor constraint; region_spanning_rectangles: %s", - meta_rectangle_region_to_string (region_spanning_rectangles, ", ", - spanning_region)); - } -#endif - - /* Determine whether constraint applies; exit if it doesn't */ - how_far_it_can_be_smushed = info->current; - get_size_limits (window, &min_size, &max_size); - - if (info->action_type != ACTION_MOVE) - { - if (!(info->fixed_directions & FIXED_DIRECTION_X)) - how_far_it_can_be_smushed.width = min_size.width; - - if (!(info->fixed_directions & FIXED_DIRECTION_Y)) - how_far_it_can_be_smushed.height = min_size.height; - } - if (!meta_rectangle_could_fit_in_region (region_spanning_rectangles, - &how_far_it_can_be_smushed)) - exit_early = TRUE; - - /* Determine whether constraint is already satisfied; exit if it is */ - constraint_satisfied = - meta_rectangle_contained_in_region (region_spanning_rectangles, - &info->current); - if (exit_early || constraint_satisfied || check_only) - return constraint_satisfied; - - /* Enforce constraint */ - - /* Clamp rectangle size for resize or move+resize actions */ - if (info->action_type != ACTION_MOVE) - meta_rectangle_clamp_to_fit_into_region (region_spanning_rectangles, - info->fixed_directions, - &info->current, - &min_size); - - if (info->is_user_action && info->action_type == ACTION_RESIZE) - /* For user resize, clip to the relevant region */ - meta_rectangle_clip_to_region (region_spanning_rectangles, - info->fixed_directions, - &info->current); - else - /* For everything else, shove the rectangle into the relevant region */ - meta_rectangle_shove_into_region (region_spanning_rectangles, - info->fixed_directions, - &info->current); - - return TRUE; -} - -static gboolean -constrain_to_single_monitor (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - - if (priority > PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_MONITOR) - return TRUE; - - /* Exit early if we know the constraint won't apply--note that this constraint - * is only meant for normal windows (e.g. we don't want docks to be shoved - * "onscreen" by their own strut) and we can't apply it to frameless windows - * or else users will be unable to move windows such as XMMS across monitors. - */ - if (window->type == META_WINDOW_DESKTOP || - window->type == META_WINDOW_DOCK || - meta_monitor_manager_get_num_logical_monitors (monitor_manager) == 1 || - !window->require_on_single_monitor || - !window->frame || - info->is_user_action || - meta_window_get_placement_rule (window)) - return TRUE; - - /* Have a helper function handle the constraint for us */ - return do_screen_and_monitor_relative_constraints (window, - info->usable_monitor_region, - info, - check_only); -} - -static gboolean -constrain_fully_onscreen (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only) -{ - if (priority > PRIORITY_ENTIRELY_VISIBLE_ON_WORKAREA) - return TRUE; - - /* Exit early if we know the constraint won't apply--note that this constraint - * is only meant for normal windows (e.g. we don't want docks to be shoved - * "onscreen" by their own strut). - */ - if (window->type == META_WINDOW_DESKTOP || - window->type == META_WINDOW_DOCK || - window->fullscreen || - !window->require_fully_onscreen || - info->is_user_action || - meta_window_get_placement_rule (window)) - return TRUE; - - /* Have a helper function handle the constraint for us */ - return do_screen_and_monitor_relative_constraints (window, - info->usable_screen_region, - info, - check_only); -} - -static gboolean -constrain_titlebar_visible (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only) -{ - gboolean unconstrained_user_action; - gboolean retval; - int bottom_amount; - int horiz_amount_offscreen, vert_amount_offscreen; - int horiz_amount_onscreen, vert_amount_onscreen; - - if (priority > PRIORITY_TITLEBAR_VISIBLE) - return TRUE; - - /* Allow the titlebar beyond the top of the screen only if the user wasn't - * clicking on the frame to start the move. - */ - unconstrained_user_action = - info->is_user_action && !window->display->grab_frame_action; - - /* Exit early if we know the constraint won't apply--note that this constraint - * is only meant for normal windows (e.g. we don't want docks to be shoved - * "onscreen" by their own strut). - */ - if (window->type == META_WINDOW_DESKTOP || - window->type == META_WINDOW_DOCK || - window->fullscreen || - !window->require_titlebar_visible || - unconstrained_user_action || - meta_window_get_placement_rule (window)) - return TRUE; - - /* Determine how much offscreen things are allowed. We first need to - * figure out how much must remain on the screen. For that, we use 25% - * window width/height but clamp to the range of (10,75) pixels. This is - * somewhat of a seat of my pants random guess at what might look good. - * Then, the amount that is allowed off is just the window size minus - * this amount (but no less than 0 for tiny windows). - */ - horiz_amount_onscreen = info->current.width / 4; - vert_amount_onscreen = info->current.height / 4; - horiz_amount_onscreen = CLAMP (horiz_amount_onscreen, 10, 75); - vert_amount_onscreen = CLAMP (vert_amount_onscreen, 10, 75); - horiz_amount_offscreen = info->current.width - horiz_amount_onscreen; - vert_amount_offscreen = info->current.height - vert_amount_onscreen; - horiz_amount_offscreen = MAX (horiz_amount_offscreen, 0); - vert_amount_offscreen = MAX (vert_amount_offscreen, 0); - /* Allow the titlebar to touch the bottom panel; If there is no titlebar, - * require vert_amount to remain on the screen. - */ - if (window->frame) - { - MetaFrameBorders borders; - meta_frame_calc_borders (window->frame, &borders); - - bottom_amount = info->current.height - borders.visible.top; - vert_amount_onscreen = borders.visible.top; - } - else - bottom_amount = vert_amount_offscreen; - - /* Extend the region, have a helper function handle the constraint, - * then return the region to its original size. - */ - meta_rectangle_expand_region_conditionally (info->usable_screen_region, - horiz_amount_offscreen, - horiz_amount_offscreen, - 0, /* Don't let titlebar off */ - bottom_amount, - horiz_amount_onscreen, - vert_amount_onscreen); - retval = - do_screen_and_monitor_relative_constraints (window, - info->usable_screen_region, - info, - check_only); - meta_rectangle_expand_region_conditionally (info->usable_screen_region, - -horiz_amount_offscreen, - -horiz_amount_offscreen, - 0, /* Don't let titlebar off */ - -bottom_amount, - horiz_amount_onscreen, - vert_amount_onscreen); - - return retval; -} - -static gboolean -constrain_partially_onscreen (MetaWindow *window, - ConstraintInfo *info, - ConstraintPriority priority, - gboolean check_only) -{ - gboolean retval; - int top_amount, bottom_amount; - int horiz_amount_offscreen, vert_amount_offscreen; - int horiz_amount_onscreen, vert_amount_onscreen; - - if (priority > PRIORITY_PARTIALLY_VISIBLE_ON_WORKAREA) - return TRUE; - - /* Exit early if we know the constraint won't apply--note that this constraint - * is only meant for normal windows (e.g. we don't want docks to be shoved - * "onscreen" by their own strut). - */ - if (window->type == META_WINDOW_DESKTOP || - window->type == META_WINDOW_DOCK || - meta_window_get_placement_rule (window)) - return TRUE; - - /* Determine how much offscreen things are allowed. We first need to - * figure out how much must remain on the screen. For that, we use 25% - * window width/height but clamp to the range of (10,75) pixels. This is - * somewhat of a seat of my pants random guess at what might look good. - * Then, the amount that is allowed off is just the window size minus - * this amount (but no less than 0 for tiny windows). - */ - horiz_amount_onscreen = info->current.width / 4; - vert_amount_onscreen = info->current.height / 4; - horiz_amount_onscreen = CLAMP (horiz_amount_onscreen, 10, 75); - vert_amount_onscreen = CLAMP (vert_amount_onscreen, 10, 75); - horiz_amount_offscreen = info->current.width - horiz_amount_onscreen; - vert_amount_offscreen = info->current.height - vert_amount_onscreen; - horiz_amount_offscreen = MAX (horiz_amount_offscreen, 0); - vert_amount_offscreen = MAX (vert_amount_offscreen, 0); - top_amount = vert_amount_offscreen; - /* Allow the titlebar to touch the bottom panel; If there is no titlebar, - * require vert_amount to remain on the screen. - */ - if (window->frame) - { - MetaFrameBorders borders; - meta_frame_calc_borders (window->frame, &borders); - - bottom_amount = info->current.height - borders.visible.top; - vert_amount_onscreen = borders.visible.top; - } - else - bottom_amount = vert_amount_offscreen; - - /* Extend the region, have a helper function handle the constraint, - * then return the region to its original size. - */ - meta_rectangle_expand_region_conditionally (info->usable_screen_region, - horiz_amount_offscreen, - horiz_amount_offscreen, - top_amount, - bottom_amount, - horiz_amount_onscreen, - vert_amount_onscreen); - retval = - do_screen_and_monitor_relative_constraints (window, - info->usable_screen_region, - info, - check_only); - meta_rectangle_expand_region_conditionally (info->usable_screen_region, - -horiz_amount_offscreen, - -horiz_amount_offscreen, - -top_amount, - -bottom_amount, - horiz_amount_onscreen, - vert_amount_onscreen); - - return retval; -} diff --git a/src/core/constraints.h b/src/core/constraints.h deleted file mode 100644 index eaa4e4594..000000000 --- a/src/core/constraints.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter size/position constraints */ - -/* - * Copyright (C) 2002 Red Hat, Inc. - * Copyright (C) 2005 Elijah Newren - * - * 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 . - */ - -#ifndef META_CONSTRAINTS_H -#define META_CONSTRAINTS_H - -#include "core/frame.h" -#include "core/window-private.h" -#include "meta/util.h" - -void meta_window_constrain (MetaWindow *window, - MetaMoveResizeFlags flags, - MetaGravity resize_gravity, - const MetaRectangle *orig, - MetaRectangle *new, - MetaRectangle *intermediate, - int *rel_x, - int *rel_y); - -#endif /* META_CONSTRAINTS_H */ diff --git a/src/core/delete.c b/src/core/delete.c deleted file mode 100644 index 058764b08..000000000 --- a/src/core/delete.c +++ /dev/null @@ -1,124 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter window deletion */ - -/* - * Copyright (C) 2001, 2002 Havoc Pennington - * Copyright (C) 2004 Elijah Newren - * - * 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 . - */ - -#define _XOPEN_SOURCE /* for kill() */ - -#include "config.h" - -#include - -#include "compositor/compositor-private.h" -#include "core/util-private.h" -#include "core/window-private.h" -#include "meta/meta-x11-errors.h" -#include "meta/workspace.h" - -static void -close_dialog_response_cb (MetaCloseDialog *dialog, - MetaCloseDialogResponse response, - MetaWindow *window) -{ - if (response == META_CLOSE_DIALOG_RESPONSE_FORCE_CLOSE) - meta_window_kill (window); -} - -static void -meta_window_ensure_close_dialog (MetaWindow *window) -{ - MetaDisplay *display; - - if (window->close_dialog) - return; - - display = window->display; - window->close_dialog = meta_compositor_create_close_dialog (display->compositor, - window); - g_signal_connect (window->close_dialog, "response", - G_CALLBACK (close_dialog_response_cb), window); -} - -void -meta_window_set_alive (MetaWindow *window, - gboolean is_alive) -{ - if (is_alive && window->close_dialog) - { - meta_close_dialog_hide (window->close_dialog); - } - else if (!is_alive) - { - meta_window_ensure_close_dialog (window); - meta_close_dialog_show (window->close_dialog); - - if (window->display && - window->display->event_route == META_EVENT_ROUTE_NORMAL && - window == window->display->focus_window) - meta_close_dialog_focus (window->close_dialog); - } -} - -void -meta_window_check_alive (MetaWindow *window, - guint32 timestamp) -{ - meta_display_ping_window (window, timestamp); -} - -void -meta_window_delete (MetaWindow *window, - guint32 timestamp) -{ - META_WINDOW_GET_CLASS (window)->delete (window, timestamp); - - meta_window_check_alive (window, timestamp); -} - -void -meta_window_kill (MetaWindow *window) -{ - pid_t pid = meta_window_get_pid (window); - - if (pid > 0) - { - meta_topic (META_DEBUG_WINDOW_OPS, - "Killing %s with kill()", - window->desc); - - if (kill (pid, 9) == 0) - return; - - meta_topic (META_DEBUG_WINDOW_OPS, - "Failed to signal %s: %s", - window->desc, strerror (errno)); - } - - META_WINDOW_GET_CLASS (window)->kill (window); -} - -void -meta_window_free_delete_dialog (MetaWindow *window) -{ - if (window->close_dialog && - meta_close_dialog_is_visible (window->close_dialog)) - meta_close_dialog_hide (window->close_dialog); - g_clear_object (&window->close_dialog); -} diff --git a/src/core/display-private.h b/src/core/display-private.h deleted file mode 100644 index 8efac0b49..000000000 --- a/src/core/display-private.h +++ /dev/null @@ -1,434 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter X display handler */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002 Red Hat, Inc. - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * 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 . - */ - -#ifndef META_DISPLAY_PRIVATE_H -#define META_DISPLAY_PRIVATE_H - -#include "meta/display.h" - -#include -#include -#include - -#include "clutter/clutter.h" -#include "core/keybindings-private.h" -#include "core/meta-gesture-tracker-private.h" -#include "core/meta-pad-action-mapper.h" -#include "core/stack-tracker.h" -#include "core/startup-notification-private.h" -#include "meta/barrier.h" -#include "meta/boxes.h" -#include "meta/common.h" -#include "meta/meta-selection.h" -#include "meta/prefs.h" - -typedef struct _MetaBell MetaBell; -typedef struct _MetaStack MetaStack; - -typedef struct MetaEdgeResistanceData MetaEdgeResistanceData; - -typedef enum -{ - META_LIST_DEFAULT = 0, /* normal windows */ - META_LIST_INCLUDE_OVERRIDE_REDIRECT = 1 << 0, /* normal and O-R */ - META_LIST_SORTED = 1 << 1, /* sort list by mru */ -} MetaListWindowsFlags; - -#define _NET_WM_STATE_REMOVE 0 /* remove/unset property */ -#define _NET_WM_STATE_ADD 1 /* add/set property */ -#define _NET_WM_STATE_TOGGLE 2 /* toggle property */ - -/* This is basically a bogus number, just has to be large enough - * to handle the expected case of the alt+tab operation, where - * we want to ignore serials from UnmapNotify on the tab popup, - * and the LeaveNotify/EnterNotify from the pointer ungrab. It - * also has to be big enough to hold ignored serials from the point - * where we reshape the stage to the point where we get events back. - */ -#define N_IGNORED_CROSSING_SERIALS 10 - -typedef enum -{ - META_TILE_NONE, - META_TILE_LEFT, - META_TILE_RIGHT, - META_TILE_MAXIMIZED -} MetaTileMode; - -typedef enum -{ - /* Normal interaction where you're interacting with windows. - * Events go to windows normally. */ - META_EVENT_ROUTE_NORMAL, - - /* In a window operation like moving or resizing. All events - * goes to MetaWindow, but not to the actual client window. */ - META_EVENT_ROUTE_WINDOW_OP, - - /* In a compositor grab operation. All events go to the - * compositor plugin. */ - META_EVENT_ROUTE_COMPOSITOR_GRAB, - - /* A Wayland application has a popup open. All events go to - * the Wayland application. */ - META_EVENT_ROUTE_WAYLAND_POPUP, - - /* The user is clicking on a window button. */ - META_EVENT_ROUTE_FRAME_BUTTON, -} MetaEventRoute; - -typedef void (* MetaDisplayWindowFunc) (MetaWindow *window, - gpointer user_data); - -struct _MetaDisplay -{ - GObject parent_instance; - - MetaX11Display *x11_display; - - int clutter_event_filter; - - /* Our best guess as to the "currently" focused window (that is, the - * window that we expect will be focused at the point when the X - * server processes our next request), and the serial of the request - * or event that caused this. - */ - MetaWindow *focus_window; - - /* last timestamp passed to XSetInputFocus */ - guint32 last_focus_time; - - /* last user interaction time in any app */ - guint32 last_user_time; - - /* whether we're using mousenav (only relevant for sloppy&mouse focus modes; - * !mouse_mode means "keynav mode") - */ - guint mouse_mode : 1; - - /* Helper var used when focus_new_windows setting is 'strict'; only - * relevant in 'strict' mode and if the focus window is a terminal. - * In that case, we don't allow new windows to take focus away from - * a terminal, but if the user explicitly did something that should - * allow a different window to gain focus (e.g. global keybinding or - * clicking on a dock), then we will allow the transfer. - */ - guint allow_terminal_deactivation : 1; - - /*< private-ish >*/ - GHashTable *stamps; - GHashTable *wayland_windows; - - /* serials of leave/unmap events that may - * correspond to an enter event we should - * ignore - */ - unsigned long ignored_crossing_serials[N_IGNORED_CROSSING_SERIALS]; - - guint32 current_time; - - /* We maintain a sequence counter, incremented for each #MetaWindow - * created. This is exposed by meta_window_get_stable_sequence() - * but is otherwise not used inside mutter. - * - * It can be useful to plugins which want to sort windows in a - * stable fashion. - */ - guint32 window_sequence_counter; - - /* Pings which we're waiting for a reply from */ - GSList *pending_pings; - - /* Pending focus change */ - guint focus_timeout_id; - - /* Pending autoraise */ - guint autoraise_timeout_id; - MetaWindow* autoraise_window; - - /* Event routing */ - MetaEventRoute event_route; - - /* current window operation */ - MetaGrabOp grab_op; - MetaWindow *grab_window; - int grab_button; - int grab_anchor_root_x; - int grab_anchor_root_y; - MetaRectangle grab_anchor_window_pos; - MetaTileMode grab_tile_mode; - int grab_tile_monitor_number; - int grab_latest_motion_x; - int grab_latest_motion_y; - guint grab_have_pointer : 1; - guint grab_have_keyboard : 1; - guint grab_frame_action : 1; - MetaRectangle grab_initial_window_pos; - int grab_initial_x, grab_initial_y; /* These are only relevant for */ - gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */ - int64_t grab_last_moveresize_time; - MetaEdgeResistanceData *grab_edge_resistance_data; - unsigned int grab_last_edge_resistance_flags; - - int grab_resize_timeout_id; - - MetaKeyBindingManager key_binding_manager; - - /* Opening the display */ - unsigned int display_opening : 1; - - /* Closing down the display */ - int closing; - - /* Managed by compositor.c */ - MetaCompositor *compositor; - - MetaGestureTracker *gesture_tracker; - ClutterEventSequence *pointer_emulating_sequence; - - ClutterActor *current_pad_osd; - MetaPadActionMapper *pad_action_mapper; - - MetaStartupNotification *startup_notification; - - MetaCursor current_cursor; - - MetaStack *stack; - MetaStackTracker *stack_tracker; - - guint tile_preview_timeout_id; - guint preview_tile_mode : 2; - - GSList *startup_sequences; - - guint work_area_later; - guint check_fullscreen_later; - - MetaBell *bell; - MetaWorkspaceManager *workspace_manager; - - MetaSoundPlayer *sound_player; - - MetaSelectionSource *selection_source; - GBytes *saved_clipboard; - gchar *saved_clipboard_mimetype; - MetaSelection *selection; -}; - -struct _MetaDisplayClass -{ - GObjectClass parent_class; -}; - -#define XSERVER_TIME_IS_BEFORE_ASSUMING_REAL_TIMESTAMPS(time1, time2) \ - ( (( (time1) < (time2) ) && ( (time2) - (time1) < ((guint32)-1)/2 )) || \ - (( (time1) > (time2) ) && ( (time1) - (time2) > ((guint32)-1)/2 )) \ - ) -/** - * XSERVER_TIME_IS_BEFORE: - * - * See the docs for meta_display_xserver_time_is_before(). - */ -#define XSERVER_TIME_IS_BEFORE(time1, time2) \ - ( (time1) == 0 || \ - (XSERVER_TIME_IS_BEFORE_ASSUMING_REAL_TIMESTAMPS(time1, time2) && \ - (time2) != 0) \ - ) - -MetaDisplay * meta_display_new (MetaContext *context, - GError **error); - -void meta_display_manage_all_xwindows (MetaDisplay *display); -void meta_display_unmanage_windows (MetaDisplay *display, - guint32 timestamp); - -/* Utility function to compare the stacking of two windows */ -int meta_display_stack_cmp (const void *a, - const void *b); - -/* Each MetaWindow is uniquely identified by a 64-bit "stamp"; unlike a - * a MetaWindow *, a stamp will never be recycled - */ -MetaWindow* meta_display_lookup_stamp (MetaDisplay *display, - guint64 stamp); -void meta_display_register_stamp (MetaDisplay *display, - guint64 *stampp, - MetaWindow *window); -void meta_display_unregister_stamp (MetaDisplay *display, - guint64 stamp); - -/* A "stack id" is a XID or a stamp */ -#define META_STACK_ID_IS_X11(id) ((id) < G_GUINT64_CONSTANT(0x100000000)) - -META_EXPORT_TEST -MetaWindow* meta_display_lookup_stack_id (MetaDisplay *display, - guint64 stack_id); - -/* for debug logging only; returns a human-description of the stack - * ID - a small number of buffers are recycled, so the result must - * be used immediately or copied */ -const char *meta_display_describe_stack_id (MetaDisplay *display, - guint64 stack_id); - -void meta_display_register_wayland_window (MetaDisplay *display, - MetaWindow *window); -void meta_display_unregister_wayland_window (MetaDisplay *display, - MetaWindow *window); - -void meta_display_notify_window_created (MetaDisplay *display, - MetaWindow *window); - -META_EXPORT_TEST -GSList* meta_display_list_windows (MetaDisplay *display, - MetaListWindowsFlags flags); - -MetaDisplay* meta_display_for_x_display (Display *xdisplay); - -META_EXPORT_TEST -MetaDisplay* meta_get_display (void); - -void meta_display_reload_cursor (MetaDisplay *display); -void meta_display_update_cursor (MetaDisplay *display); - -void meta_display_check_threshold_reached (MetaDisplay *display, - int x, - int y); -void meta_display_grab_window_buttons (MetaDisplay *display, - Window xwindow); -void meta_display_ungrab_window_buttons (MetaDisplay *display, - Window xwindow); - -void meta_display_grab_focus_window_button (MetaDisplay *display, - MetaWindow *window); -void meta_display_ungrab_focus_window_button (MetaDisplay *display, - MetaWindow *window); - -/* Next function is defined in edge-resistance.c */ -void meta_display_cleanup_edges (MetaDisplay *display); - -/* utility goo */ -const char* meta_event_mode_to_string (int m); -const char* meta_event_detail_to_string (int d); - -void meta_display_queue_retheme_all_windows (MetaDisplay *display); - -void meta_display_ping_window (MetaWindow *window, - guint32 serial); -void meta_display_pong_for_serial (MetaDisplay *display, - guint32 serial); - -MetaGravity meta_resize_gravity_from_grab_op (MetaGrabOp op); - -gboolean meta_grab_op_is_moving (MetaGrabOp op); -gboolean meta_grab_op_is_resizing (MetaGrabOp op); -gboolean meta_grab_op_is_mouse (MetaGrabOp op); -gboolean meta_grab_op_is_keyboard (MetaGrabOp op); - -void meta_display_queue_autoraise_callback (MetaDisplay *display, - MetaWindow *window); -void meta_display_remove_autoraise_callback (MetaDisplay *display); - -void meta_display_overlay_key_activate (MetaDisplay *display); -void meta_display_accelerator_activate (MetaDisplay *display, - guint action, - ClutterKeyEvent *event); -gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display); - -void meta_display_sync_wayland_input_focus (MetaDisplay *display); -void meta_display_update_focus_window (MetaDisplay *display, - MetaWindow *window); - -void meta_display_sanity_check_timestamps (MetaDisplay *display, - guint32 timestamp); -gboolean meta_display_timestamp_too_old (MetaDisplay *display, - guint32 *timestamp); - -void meta_display_remove_pending_pings_for_window (MetaDisplay *display, - MetaWindow *window); - -MetaGestureTracker * meta_display_get_gesture_tracker (MetaDisplay *display); - -gboolean meta_display_show_restart_message (MetaDisplay *display, - const char *message); -gboolean meta_display_request_restart (MetaDisplay *display); - -gboolean meta_display_show_resize_popup (MetaDisplay *display, - gboolean show, - MetaRectangle *rect, - int display_w, - int display_h); - -void meta_set_is_restart (gboolean whether); - -void meta_display_cancel_touch (MetaDisplay *display); - -gboolean meta_display_windows_are_interactable (MetaDisplay *display); - -void meta_display_show_tablet_mapping_notification (MetaDisplay *display, - ClutterInputDevice *pad, - const gchar *pretty_name); - -void meta_display_notify_pad_group_switch (MetaDisplay *display, - ClutterInputDevice *pad, - const gchar *pretty_name, - guint n_group, - guint n_mode, - guint n_modes); - -void meta_display_foreach_window (MetaDisplay *display, - MetaListWindowsFlags flags, - MetaDisplayWindowFunc func, - gpointer data); - -void meta_display_restacked (MetaDisplay *display); - - -void meta_display_update_tile_preview (MetaDisplay *display, - gboolean delay); -void meta_display_hide_tile_preview (MetaDisplay *display); - -gboolean meta_display_apply_startup_properties (MetaDisplay *display, - MetaWindow *window); - -void meta_display_queue_workarea_recalc (MetaDisplay *display); -void meta_display_queue_check_fullscreen (MetaDisplay *display); - -MetaWindow *meta_display_get_pointer_window (MetaDisplay *display, - MetaWindow *not_this_one); - -MetaWindow *meta_display_get_window_from_id (MetaDisplay *display, - uint64_t window_id); -uint64_t meta_display_generate_window_id (MetaDisplay *display); - -void meta_display_init_x11 (MetaDisplay *display, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean meta_display_init_x11_finish (MetaDisplay *display, - GAsyncResult *result, - GError **error); - -void meta_display_shutdown_x11 (MetaDisplay *display); - -#endif diff --git a/src/core/display.c b/src/core/display.c deleted file mode 100644 index 5d4a4da21..000000000 --- a/src/core/display.c +++ /dev/null @@ -1,3852 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002, 2003, 2004 Red Hat, Inc. - * Copyright (C) 2003, 2004 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * 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 . - */ - -/** - * SECTION:display - * @title: MetaDisplay - * @short_description: Mutter display representation - * - * The display is represented as a #MetaDisplay struct. - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-cursor-sprite-xcursor.h" -#include "backends/meta-cursor-tracker-private.h" -#include "backends/meta-input-device-private.h" -#include "backends/meta-input-mapper-private.h" -#include "backends/meta-stage-private.h" -#include "backends/x11/meta-backend-x11.h" -#include "backends/x11/meta-clutter-backend-x11.h" -#include "backends/x11/meta-event-x11.h" -#include "backends/x11/cm/meta-backend-x11-cm.h" -#include "backends/x11/nested/meta-backend-x11-nested.h" -#include "compositor/compositor-private.h" -#include "compositor/meta-compositor-x11.h" -#include "cogl/cogl.h" -#include "core/bell.h" -#include "core/boxes-private.h" -#include "core/display-private.h" -#include "core/events.h" -#include "core/frame.h" -#include "core/keybindings-private.h" -#include "core/meta-clipboard-manager.h" -#include "core/meta-workspace-manager-private.h" -#include "core/util-private.h" -#include "core/window-private.h" -#include "core/workspace-private.h" -#include "meta/compositor-mutter.h" -#include "meta/compositor.h" -#include "meta/main.h" -#include "meta/meta-backend.h" -#include "meta/meta-enum-types.h" -#include "meta/meta-sound-player.h" -#include "meta/meta-x11-errors.h" -#include "meta/prefs.h" -#include "x11/meta-startup-notification-x11.h" -#include "x11/meta-x11-display-private.h" -#include "x11/window-x11.h" -#include "x11/xprops.h" - -#ifdef HAVE_WAYLAND -#include "compositor/meta-compositor-native.h" -#include "compositor/meta-compositor-server.h" -#include "wayland/meta-xwayland-private.h" -#include "wayland/meta-wayland-tablet-seat.h" -#include "wayland/meta-wayland-tablet-pad.h" -#endif - -#ifdef HAVE_NATIVE_BACKEND -#include "backends/native/meta-backend-native.h" -#endif - -/* - * SECTION:pings - * - * Sometimes we want to see whether a window is responding, - * so we send it a "ping" message and see whether it sends us back a "pong" - * message within a reasonable time. Here we have a system which lets us - * nominate one function to be called if we get the pong in time and another - * function if we don't. The system is rather more complicated than it needs - * to be, since we only ever use it to destroy windows which are asked to - * close themselves and don't do so within a reasonable amount of time, and - * therefore we always use the same callbacks. It's possible that we might - * use it for other things in future, or on the other hand we might decide - * that we're never going to do so and simplify it a bit. - */ - -/** - * MetaPingData: - * - * Describes a ping on a window. When we send a ping to a window, we build - * one of these structs, and it eventually gets passed to the timeout function - * or to the function which handles the response from the window. If the window - * does or doesn't respond to the ping, we use this information to deal with - * these facts; we have a handler function for each. - */ -typedef struct -{ - MetaWindow *window; - guint32 serial; - guint ping_timeout_id; -} MetaPingData; - -typedef struct _MetaDisplayPrivate -{ - MetaContext *context; -} MetaDisplayPrivate; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaDisplay, meta_display, G_TYPE_OBJECT) - -/* Signals */ -enum -{ - CURSOR_UPDATED, - X11_DISPLAY_SETUP, - X11_DISPLAY_OPENED, - X11_DISPLAY_CLOSING, - OVERLAY_KEY, - ACCELERATOR_ACTIVATED, - MODIFIERS_ACCELERATOR_ACTIVATED, - FOCUS_WINDOW, - WINDOW_CREATED, - WINDOW_DEMANDS_ATTENTION, - WINDOW_MARKED_URGENT, - GRAB_OP_BEGIN, - GRAB_OP_END, - SHOW_RESTART_MESSAGE, - RESTART, - SHOW_RESIZE_POPUP, - GL_VIDEO_MEMORY_PURGED, - SHOW_PAD_OSD, - SHOW_OSD, - PAD_MODE_SWITCH, - WINDOW_ENTERED_MONITOR, - WINDOW_LEFT_MONITOR, - WORKSPACE_ADDED, - WORKSPACE_REMOVED, - WORKSPACE_SWITCHED, - ACTIVE_WORKSPACE_CHANGED, - IN_FULLSCREEN_CHANGED, - SHOWING_DESKTOP_CHANGED, - RESTACKED, - WORKAREAS_CHANGED, - CLOSING, - INIT_XSERVER, - LAST_SIGNAL -}; - -enum -{ - PROP_0, - - PROP_COMPOSITOR_MODIFIERS, - PROP_FOCUS_WINDOW -}; - -static guint display_signals [LAST_SIGNAL] = { 0 }; - -#define META_GRAB_OP_GET_BASE_TYPE(op) (op & 0x00FF) - -/* - * The display we're managing. This is a singleton object. (Historically, - * this was a list of displays, but there was never any way to add more - * than one element to it.) The goofy name is because we don't want it - * to shadow the parameter in its object methods. - */ -static MetaDisplay *the_display = NULL; - -static void on_monitors_changed_internal (MetaMonitorManager *monitor_manager, - MetaDisplay *display); - -static void prefs_changed_callback (MetaPreference pref, - void *data); - -static int mru_cmp (gconstpointer a, - gconstpointer b); - -static void -meta_display_get_property(GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaDisplay *display = META_DISPLAY (object); - - switch (prop_id) - { - case PROP_COMPOSITOR_MODIFIERS: - g_value_set_flags (value, meta_display_get_compositor_modifiers (display)); - break; - case PROP_FOCUS_WINDOW: - g_value_set_object (value, display->focus_window); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_display_set_property(GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (prop_id) - { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_display_class_init (MetaDisplayClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->get_property = meta_display_get_property; - object_class->set_property = meta_display_set_property; - - display_signals[CURSOR_UPDATED] = - g_signal_new ("cursor-updated", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - display_signals[X11_DISPLAY_SETUP] = - g_signal_new ("x11-display-setup", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - display_signals[X11_DISPLAY_OPENED] = - g_signal_new ("x11-display-opened", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - display_signals[X11_DISPLAY_CLOSING] = - g_signal_new ("x11-display-closing", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - display_signals[OVERLAY_KEY] = - g_signal_new ("overlay-key", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - display_signals[ACCELERATOR_ACTIVATED] = - g_signal_new ("accelerator-activated", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 3, G_TYPE_UINT, CLUTTER_TYPE_INPUT_DEVICE, G_TYPE_UINT); - - /** - * MetaDisplay::modifiers-accelerator-activated: - * @display: the #MetaDisplay instance - * - * The ::modifiers-accelerator-activated signal will be emitted when - * a special modifiers-only keybinding is activated. - * - * Returns: %TRUE means that the keyboard device should remain - * frozen and %FALSE for the default behavior of unfreezing the - * keyboard. - */ - display_signals[MODIFIERS_ACCELERATOR_ACTIVATED] = - g_signal_new ("modifiers-accelerator-activated", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - g_signal_accumulator_first_wins, NULL, NULL, - G_TYPE_BOOLEAN, 0); - - display_signals[WINDOW_CREATED] = - g_signal_new ("window-created", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 1, META_TYPE_WINDOW); - - display_signals[WINDOW_DEMANDS_ATTENTION] = - g_signal_new ("window-demands-attention", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 1, META_TYPE_WINDOW); - - display_signals[WINDOW_MARKED_URGENT] = - g_signal_new ("window-marked-urgent", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 1, - META_TYPE_WINDOW); - - display_signals[GRAB_OP_BEGIN] = - g_signal_new ("grab-op-begin", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 2, - META_TYPE_WINDOW, - META_TYPE_GRAB_OP); - - display_signals[GRAB_OP_END] = - g_signal_new ("grab-op-end", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 2, - META_TYPE_WINDOW, - META_TYPE_GRAB_OP); - - /** - * MetaDisplay::show-restart-message: - * @display: the #MetaDisplay instance - * @message: (allow-none): The message to display, or %NULL - * to clear a previous restart message. - * - * The ::show-restart-message signal will be emitted to indicate - * that the compositor should show a message during restart. This is - * emitted when meta_restart() is called, either by Mutter - * internally or by the embedding compositor. The message should be - * immediately added to the Clutter stage in its final form - - * ::restart will be emitted to exit the application and leave the - * stage contents frozen as soon as the the stage is painted again. - * - * On case of failure to restart, this signal will be emitted again - * with %NULL for @message. - * - * Returns: %TRUE means the message was added to the stage; %FALSE - * indicates that the compositor did not show the message. - */ - display_signals[SHOW_RESTART_MESSAGE] = - g_signal_new ("show-restart-message", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - g_signal_accumulator_true_handled, - NULL, NULL, - G_TYPE_BOOLEAN, 1, - G_TYPE_STRING); - - /** - * MetaDisplay::restart: - * @display: the #MetaDisplay instance - * - * The ::restart signal is emitted to indicate that compositor - * should reexec the process. This is - * emitted when meta_restart() is called, either by Mutter - * internally or by the embedding compositor. See also - * ::show-restart-message. - * - * Returns: %FALSE to indicate that the compositor could not - * be restarted. When the compositor is restarted, the signal - * should not return. - */ - display_signals[RESTART] = - g_signal_new ("restart", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - g_signal_accumulator_true_handled, - NULL, NULL, - G_TYPE_BOOLEAN, 0); - - display_signals[SHOW_RESIZE_POPUP] = - g_signal_new ("show-resize-popup", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - g_signal_accumulator_true_handled, - NULL, NULL, - G_TYPE_BOOLEAN, 4, - G_TYPE_BOOLEAN, META_TYPE_RECTANGLE, G_TYPE_INT, G_TYPE_INT); - - display_signals[GL_VIDEO_MEMORY_PURGED] = - g_signal_new ("gl-video-memory-purged", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - /** - * MetaDisplay::show-pad-osd: - * @display: the #MetaDisplay instance - * @pad: the pad device - * @settings: the pad device settings - * @layout_path: path to the layout image - * @edition_mode: Whether the OSD should be shown in edition mode - * @monitor_idx: Monitor to show the OSD on - * - * Requests the pad button mapping OSD to be shown. - * - * Returns: (transfer none) (nullable): The OSD actor - */ - display_signals[SHOW_PAD_OSD] = - g_signal_new ("show-pad-osd", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - CLUTTER_TYPE_ACTOR, 5, CLUTTER_TYPE_INPUT_DEVICE, - G_TYPE_SETTINGS, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_INT); - - display_signals[SHOW_OSD] = - g_signal_new ("show-osd", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 3, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING); - - display_signals[PAD_MODE_SWITCH] = - g_signal_new ("pad-mode-switch", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 3, CLUTTER_TYPE_INPUT_DEVICE, - G_TYPE_UINT, G_TYPE_UINT); - - display_signals[WINDOW_ENTERED_MONITOR] = - g_signal_new ("window-entered-monitor", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 2, - G_TYPE_INT, - META_TYPE_WINDOW); - - display_signals[WINDOW_LEFT_MONITOR] = - g_signal_new ("window-left-monitor", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 2, - G_TYPE_INT, - META_TYPE_WINDOW); - - display_signals[IN_FULLSCREEN_CHANGED] = - g_signal_new ("in-fullscreen-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); - - display_signals[SHOWING_DESKTOP_CHANGED] = - g_signal_new ("showing-desktop-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - display_signals[RESTACKED] = - g_signal_new ("restacked", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); - - display_signals[WORKAREAS_CHANGED] = - g_signal_new ("workareas-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); - display_signals[CLOSING] = - g_signal_new ("closing", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); - - display_signals[INIT_XSERVER] = - g_signal_new ("init-xserver", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, g_signal_accumulator_first_wins, - NULL, NULL, - G_TYPE_BOOLEAN, 1, G_TYPE_TASK); - - g_object_class_install_property (object_class, - PROP_COMPOSITOR_MODIFIERS, - g_param_spec_flags ("compositor-modifiers", - "Compositor modifiers", - "Modifiers reserved for compositor actions", - CLUTTER_TYPE_MODIFIER_TYPE, - 0, - G_PARAM_READABLE)); - - g_object_class_install_property (object_class, - PROP_FOCUS_WINDOW, - g_param_spec_object ("focus-window", - "Focus window", - "Currently focused window", - META_TYPE_WINDOW, - G_PARAM_READABLE)); - -} - - -/** - * ping_data_free: - * - * Destructor for #MetaPingData structs. Will destroy the - * event source for the struct as well. - */ -static void -ping_data_free (MetaPingData *ping_data) -{ - /* Remove the timeout */ - g_clear_handle_id (&ping_data->ping_timeout_id, g_source_remove); - - g_free (ping_data); -} - -void -meta_display_remove_pending_pings_for_window (MetaDisplay *display, - MetaWindow *window) -{ - GSList *tmp; - GSList *dead; - - /* could obviously be more efficient, don't care */ - - /* build list to be removed */ - dead = NULL; - for (tmp = display->pending_pings; tmp; tmp = tmp->next) - { - MetaPingData *ping_data = tmp->data; - - if (ping_data->window == window) - dead = g_slist_prepend (dead, ping_data); - } - - /* remove what we found */ - for (tmp = dead; tmp; tmp = tmp->next) - { - MetaPingData *ping_data = tmp->data; - - display->pending_pings = g_slist_remove (display->pending_pings, ping_data); - ping_data_free (ping_data); - } - - g_slist_free (dead); -} - -static MetaCompositor * -create_compositor (MetaDisplay *display) -{ - MetaBackend *backend = meta_get_backend (); - -#ifdef HAVE_WAYLAND -#ifdef HAVE_NATIVE_BACKEND - if (META_IS_BACKEND_NATIVE (backend)) - return META_COMPOSITOR (meta_compositor_native_new (display, backend)); -#endif - if (META_IS_BACKEND_X11_NESTED (backend)) - return META_COMPOSITOR (meta_compositor_server_new (display, backend)); -#endif - return META_COMPOSITOR (meta_compositor_x11_new (display, backend)); -} - -static void -meta_display_init (MetaDisplay *disp) -{ - /* Some stuff could go in here that's currently in _open, - * but it doesn't really matter. */ -} - -void -meta_display_cancel_touch (MetaDisplay *display) -{ -#ifdef HAVE_WAYLAND - MetaWaylandCompositor *compositor; - - if (!meta_is_wayland_compositor ()) - return; - - compositor = meta_wayland_compositor_get_default (); - meta_wayland_touch_cancel (compositor->seat->touch); -#endif -} - -static void -gesture_tracker_state_changed (MetaGestureTracker *tracker, - ClutterEventSequence *sequence, - MetaSequenceState state, - MetaDisplay *display) -{ - switch (state) - { - case META_SEQUENCE_NONE: - case META_SEQUENCE_PENDING_END: - return; - case META_SEQUENCE_ACCEPTED: - meta_display_cancel_touch (display); - - G_GNUC_FALLTHROUGH; - case META_SEQUENCE_REJECTED: - { - MetaBackend *backend; - - backend = meta_get_backend (); - meta_backend_finish_touch_sequence (backend, sequence, state); - break; - } - } -} - -static void -on_ui_scaling_factor_changed (MetaSettings *settings, - MetaDisplay *display) -{ - meta_display_reload_cursor (display); -} - -static gboolean -meta_display_init_x11_display (MetaDisplay *display, - GError **error) -{ - MetaX11Display *x11_display; - - x11_display = meta_x11_display_new (display, error); - if (!x11_display) - return FALSE; - - display->x11_display = x11_display; - g_signal_emit (display, display_signals[X11_DISPLAY_SETUP], 0); - - meta_x11_display_create_guard_window (x11_display); - - if (!display->display_opening) - { - g_signal_emit (display, display_signals[X11_DISPLAY_OPENED], 0); - meta_display_manage_all_xwindows (display); - meta_compositor_redirect_x11_windows (display->compositor); - } - - return TRUE; -} - -#ifdef HAVE_WAYLAND -gboolean -meta_display_init_x11_finish (MetaDisplay *display, - GAsyncResult *result, - GError **error) -{ - MetaX11Display *x11_display; - - g_assert (g_task_get_source_tag (G_TASK (result)) == meta_display_init_x11); - - if (!g_task_propagate_boolean (G_TASK (result), error)) - { - if (*error == NULL) - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Unknown error"); - - return FALSE; - } - - if (display->x11_display) - return TRUE; - - x11_display = meta_x11_display_new (display, error); - if (!x11_display) - return FALSE; - - display->x11_display = x11_display; - g_signal_emit (display, display_signals[X11_DISPLAY_SETUP], 0); - - meta_x11_display_create_guard_window (x11_display); - - if (!display->display_opening) - { - g_signal_emit (display, display_signals[X11_DISPLAY_OPENED], 0); - meta_x11_display_set_cm_selection (x11_display); - meta_display_manage_all_xwindows (display); - meta_compositor_redirect_x11_windows (display->compositor); - } - - return TRUE; -} - -static void -on_xserver_started (MetaXWaylandManager *manager, - GAsyncResult *result, - gpointer user_data) -{ - g_autoptr (GTask) task = user_data; - MetaDisplay *display = g_task_get_source_object (task); - GError *error = NULL; - gboolean retval = FALSE; - - if (!meta_xwayland_start_xserver_finish (manager, result, &error)) - { - if (error) - g_task_return_error (task, error); - else - g_task_return_boolean (task, FALSE); - - return; - } - - g_signal_emit (display, display_signals[INIT_XSERVER], 0, task, &retval); - - if (!retval) - { - /* No handlers for this signal, proceed right away */ - g_task_return_boolean (task, TRUE); - } -} - -void -meta_display_init_x11 (MetaDisplay *display, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - - g_autoptr (GTask) task = NULL; - - task = g_task_new (display, cancellable, callback, user_data); - g_task_set_source_tag (task, meta_display_init_x11); - - meta_xwayland_start_xserver (&compositor->xwayland_manager, - cancellable, - (GAsyncReadyCallback) on_xserver_started, - g_steal_pointer (&task)); -} - -static void -on_x11_initialized (MetaDisplay *display, - GAsyncResult *result, - gpointer user_data) -{ - g_autoptr (GError) error = NULL; - - if (!meta_display_init_x11_finish (display, result, &error)) - g_critical ("Failed to init X11 display: %s", error->message); -} -#endif - -void -meta_display_shutdown_x11 (MetaDisplay *display) -{ - if (!display->x11_display) - return; - - g_signal_emit (display, display_signals[X11_DISPLAY_CLOSING], 0); - g_object_run_dispose (G_OBJECT (display->x11_display)); - g_clear_object (&display->x11_display); -} - -MetaDisplay * -meta_display_new (MetaContext *context, - GError **error) -{ - MetaDisplay *display; - MetaDisplayPrivate *priv; - int i; - guint32 timestamp; - Window old_active_xwindow = None; - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager; - MetaSettings *settings; - - g_assert (the_display == NULL); - display = the_display = g_object_new (META_TYPE_DISPLAY, NULL); - - priv = meta_display_get_instance_private (display); - priv->context = context; - - display->closing = 0; - display->display_opening = TRUE; - - display->pending_pings = NULL; - display->autoraise_timeout_id = 0; - display->autoraise_window = NULL; - display->focus_window = NULL; - display->workspace_manager = NULL; - display->x11_display = NULL; - - display->current_cursor = -1; /* invalid/unset */ - display->tile_preview_timeout_id = 0; - display->check_fullscreen_later = 0; - display->work_area_later = 0; - - display->mouse_mode = TRUE; /* Only relevant for mouse or sloppy focus */ - display->allow_terminal_deactivation = TRUE; /* Only relevant for when a - terminal has the focus */ - - i = 0; - while (i < N_IGNORED_CROSSING_SERIALS) - { - display->ignored_crossing_serials[i] = 0; - ++i; - } - - display->current_time = META_CURRENT_TIME; - - display->grab_resize_timeout_id = 0; - display->grab_have_keyboard = FALSE; - - display->grab_op = META_GRAB_OP_NONE; - display->grab_window = NULL; - display->grab_tile_mode = META_TILE_NONE; - display->grab_tile_monitor_number = -1; - - meta_display_cleanup_edges (display); - - meta_display_init_keys (display); - - meta_prefs_add_listener (prefs_changed_callback, display); - - /* Get events */ - meta_display_init_events (display); - - display->stamps = g_hash_table_new (g_int64_hash, - g_int64_equal); - display->wayland_windows = g_hash_table_new (NULL, NULL); - - monitor_manager = meta_backend_get_monitor_manager (backend); - g_signal_connect (monitor_manager, "monitors-changed-internal", - G_CALLBACK (on_monitors_changed_internal), display); - - display->pad_action_mapper = meta_pad_action_mapper_new (monitor_manager); - - settings = meta_backend_get_settings (backend); - g_signal_connect (settings, "ui-scaling-factor-changed", - G_CALLBACK (on_ui_scaling_factor_changed), display); - - display->compositor = create_compositor (display); - - meta_display_set_cursor (display, META_CURSOR_DEFAULT); - - display->stack = meta_stack_new (display); - display->stack_tracker = meta_stack_tracker_new (display); - - display->workspace_manager = meta_workspace_manager_new (display); - - display->startup_notification = meta_startup_notification_new (display); - - display->bell = meta_bell_new (display); - - display->selection = meta_selection_new (display); - meta_clipboard_manager_init (display); - -#ifdef HAVE_WAYLAND - if (meta_is_wayland_compositor ()) - { - MetaX11DisplayPolicy x11_display_policy; - - x11_display_policy = meta_context_get_x11_display_policy (context); - if (x11_display_policy == META_X11_DISPLAY_POLICY_MANDATORY) - { - meta_display_init_x11 (display, NULL, - (GAsyncReadyCallback) on_x11_initialized, - NULL); - } - - timestamp = meta_display_get_current_time_roundtrip (display); - } - else -#endif - { - if (!meta_display_init_x11_display (display, error)) - { - g_object_unref (display); - return NULL; - } - - timestamp = display->x11_display->timestamp; - } - - display->last_focus_time = timestamp; - display->last_user_time = timestamp; - - if (!meta_is_wayland_compositor ()) - meta_prop_get_window (display->x11_display, - display->x11_display->xroot, - display->x11_display->atom__NET_ACTIVE_WINDOW, - &old_active_xwindow); - - if (!meta_compositor_do_manage (display->compositor, error)) - { - g_object_unref (display); - return NULL; - } - - if (display->x11_display) - { - g_signal_emit (display, display_signals[X11_DISPLAY_OPENED], 0); - meta_x11_display_restore_active_workspace (display->x11_display); - meta_x11_display_create_guard_window (display->x11_display); - } - - /* Set up touch support */ - display->gesture_tracker = meta_gesture_tracker_new (); - g_signal_connect (display->gesture_tracker, "state-changed", - G_CALLBACK (gesture_tracker_state_changed), display); - - /* We know that if mutter is running as a Wayland compositor, - * we start out with no windows. - */ - if (!meta_is_wayland_compositor ()) - meta_display_manage_all_xwindows (display); - - if (old_active_xwindow != None) - { - MetaWindow *old_active_window; - old_active_window = meta_x11_display_lookup_x_window (display->x11_display, - old_active_xwindow); - if (old_active_window) - meta_window_focus (old_active_window, timestamp); - else - meta_display_unset_input_focus (display, timestamp); - } - else - { - meta_display_unset_input_focus (display, timestamp); - } - - display->sound_player = g_object_new (META_TYPE_SOUND_PLAYER, NULL); - - /* Done opening new display */ - display->display_opening = FALSE; - - return display; -} - -static gint -ptrcmp (gconstpointer a, gconstpointer b) -{ - if (a < b) - return -1; - else if (a > b) - return 1; - else - return 0; -} - -/** - * meta_display_list_windows: - * @display: a #MetaDisplay - * @flags: options for listing - * - * Lists windows for the display, the @flags parameter for - * now determines whether override-redirect windows will be - * included. - * - * Return value: (transfer container): the list of windows. - */ -GSList* -meta_display_list_windows (MetaDisplay *display, - MetaListWindowsFlags flags) -{ - GSList *winlist; - GSList *prev; - GSList *tmp; - GHashTableIter iter; - gpointer key, value; - - winlist = NULL; - - if (display->x11_display) - { - g_hash_table_iter_init (&iter, display->x11_display->xids); - while (g_hash_table_iter_next (&iter, &key, &value)) - { - MetaWindow *window = value; - - if (!META_IS_WINDOW (window) || window->unmanaging) - continue; - - if (!window->override_redirect || - (flags & META_LIST_INCLUDE_OVERRIDE_REDIRECT) != 0) - winlist = g_slist_prepend (winlist, window); - } - } - - g_hash_table_iter_init (&iter, display->wayland_windows); - while (g_hash_table_iter_next (&iter, &key, &value)) - { - MetaWindow *window = value; - - if (!META_IS_WINDOW (window) || window->unmanaging) - continue; - - if (!window->override_redirect || - (flags & META_LIST_INCLUDE_OVERRIDE_REDIRECT) != 0) - winlist = g_slist_prepend (winlist, window); - } - - /* Uniquify the list, since both frame windows and plain - * windows are in the hash - */ - winlist = g_slist_sort (winlist, ptrcmp); - - prev = NULL; - tmp = winlist; - while (tmp != NULL) - { - GSList *next; - - next = tmp->next; - - if (next && - next->data == tmp->data) - { - /* Delete tmp from list */ - - if (prev) - prev->next = next; - - if (tmp == winlist) - winlist = next; - - g_slist_free_1 (tmp); - - /* leave prev unchanged */ - } - else - { - prev = tmp; - } - - tmp = next; - } - - if (flags & META_LIST_SORTED) - winlist = g_slist_sort (winlist, mru_cmp); - - return winlist; -} - -void -meta_display_close (MetaDisplay *display, - guint32 timestamp) -{ - g_assert (display != NULL); - - if (display->closing != 0) - { - /* The display's already been closed. */ - return; - } - - g_assert (display == the_display); - - display->closing += 1; - - g_signal_emit (display, display_signals[CLOSING], 0); - - meta_compositor_unmanage (display->compositor); - - meta_display_unmanage_windows (display, timestamp); - - meta_prefs_remove_listener (prefs_changed_callback, display); - - meta_display_remove_autoraise_callback (display); - - g_clear_object (&display->gesture_tracker); - - g_clear_handle_id (&display->focus_timeout_id, g_source_remove); - g_clear_handle_id (&display->tile_preview_timeout_id, g_source_remove); - - if (display->work_area_later != 0) - meta_later_remove (display->work_area_later); - if (display->check_fullscreen_later != 0) - meta_later_remove (display->check_fullscreen_later); - - /* Stop caring about events */ - meta_display_free_events (display); - - g_clear_pointer (&display->compositor, meta_compositor_destroy); - - meta_display_shutdown_x11 (display); - - g_clear_object (&display->stack); - g_clear_pointer (&display->stack_tracker, - meta_stack_tracker_free); - - /* Must be after all calls to meta_window_unmanage() since they - * unregister windows - */ - g_hash_table_destroy (display->wayland_windows); - g_hash_table_destroy (display->stamps); - - meta_display_shutdown_keys (display); - - g_clear_object (&display->bell); - g_clear_object (&display->startup_notification); - g_clear_object (&display->workspace_manager); - g_clear_object (&display->sound_player); - - meta_clipboard_manager_shutdown (display); - g_clear_object (&display->selection); - g_clear_object (&display->pad_action_mapper); - - the_display = NULL; -} - -/** - * meta_display_for_x_display: - * @xdisplay: An X display - * - * Returns the singleton MetaDisplay if @xdisplay matches the X display it's - * managing; otherwise gives a warning and returns %NULL. When we were claiming - * to be able to manage multiple displays, this was supposed to find the - * display out of the list which matched that display. Now it's merely an - * extra sanity check. - * - * Returns: The singleton X display, or %NULL if @xdisplay isn't the one - * we're managing. - */ -MetaDisplay* -meta_display_for_x_display (Display *xdisplay) -{ - if (the_display->x11_display->xdisplay == xdisplay) - return the_display; - - meta_warning ("Could not find display for X display %p, probably going to crash", - xdisplay); - - return NULL; -} - -/** - * meta_get_display: - * - * Accessor for the singleton MetaDisplay. - * - * Returns: The only #MetaDisplay there is. This can be %NULL, but only - * during startup. - */ -MetaDisplay* -meta_get_display (void) -{ - return the_display; -} - -static inline gboolean -grab_op_is_window (MetaGrabOp op) -{ - return META_GRAB_OP_GET_BASE_TYPE (op) == META_GRAB_OP_WINDOW_BASE; -} - -gboolean -meta_grab_op_is_mouse (MetaGrabOp op) -{ - if (!grab_op_is_window (op)) - return FALSE; - - return (op & META_GRAB_OP_WINDOW_FLAG_KEYBOARD) == 0; -} - -gboolean -meta_grab_op_is_keyboard (MetaGrabOp op) -{ - if (!grab_op_is_window (op)) - return FALSE; - - return (op & META_GRAB_OP_WINDOW_FLAG_KEYBOARD) != 0; -} - -gboolean -meta_grab_op_is_resizing (MetaGrabOp op) -{ - if (!grab_op_is_window (op)) - return FALSE; - - return (op & META_GRAB_OP_WINDOW_DIR_MASK) != 0 || op == META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN; -} - -gboolean -meta_grab_op_is_moving (MetaGrabOp op) -{ - if (!grab_op_is_window (op)) - return FALSE; - - return !meta_grab_op_is_resizing (op); -} - -/** - * meta_display_windows_are_interactable: - * @op: A #MetaGrabOp - * - * Whether windows can be interacted with. - */ -gboolean -meta_display_windows_are_interactable (MetaDisplay *display) -{ - switch (display->event_route) - { - case META_EVENT_ROUTE_NORMAL: - case META_EVENT_ROUTE_WAYLAND_POPUP: - return TRUE; - default: - return FALSE; - } -} - -/** - * meta_display_xserver_time_is_before: - * @display: a #MetaDisplay - * @time1: An event timestamp - * @time2: An event timestamp - * - * Xserver time can wraparound, thus comparing two timestamps needs to take - * this into account. If no wraparound has occurred, this is equivalent to - * time1 < time2 - * Otherwise, we need to account for the fact that wraparound can occur - * and the fact that a timestamp of 0 must be special-cased since it - * means "older than anything else". - * - * Note that this is NOT an equivalent for time1 <= time2; if that's what - * you need then you'll need to swap the order of the arguments and negate - * the result. - */ -gboolean -meta_display_xserver_time_is_before (MetaDisplay *display, - guint32 time1, - guint32 time2) -{ - return XSERVER_TIME_IS_BEFORE(time1, time2); -} - -/** - * meta_display_get_last_user_time: - * @display: a #MetaDisplay - * - * Returns: Timestamp of the last user interaction event with a window - */ -guint32 -meta_display_get_last_user_time (MetaDisplay *display) -{ - return display->last_user_time; -} - -/* Get time of current event, or CurrentTime if none. */ -guint32 -meta_display_get_current_time (MetaDisplay *display) -{ - return display->current_time; -} - -guint32 -meta_display_get_current_time_roundtrip (MetaDisplay *display) -{ - if (meta_is_wayland_compositor ()) - /* Xwayland uses monotonic clock, so lets use it here as well */ - return (guint32) (g_get_monotonic_time () / 1000); - else - return meta_x11_display_get_current_time_roundtrip (display->x11_display); -} - -/** - * meta_display_add_ignored_crossing_serial: - * @display: a #MetaDisplay - * @serial: the serial to ignore - * - * Save the specified serial and ignore crossing events with that - * serial for the purpose of focus-follows-mouse. This can be used - * for certain changes to the window hierarchy that we don't want - * to change the focus window, even if they cause the pointer to - * end up in a new window. - */ -void -meta_display_add_ignored_crossing_serial (MetaDisplay *display, - unsigned long serial) -{ - int i; - - /* don't add the same serial more than once */ - if (display->ignored_crossing_serials[N_IGNORED_CROSSING_SERIALS-1] == serial) - return; - - /* shift serials to the left */ - i = 0; - while (i < (N_IGNORED_CROSSING_SERIALS - 1)) - { - display->ignored_crossing_serials[i] = display->ignored_crossing_serials[i+1]; - ++i; - } - /* put new one on the end */ - display->ignored_crossing_serials[i] = serial; -} - -static gboolean -window_raise_with_delay_callback (void *data) -{ - MetaWindow *window = data; - - window->display->autoraise_timeout_id = 0; - window->display->autoraise_window = NULL; - - /* If we aren't already on top, check whether the pointer is inside - * the window and raise the window if so. - */ - if (meta_stack_get_top (window->display->stack) != window) - { - if (meta_window_has_pointer (window)) - meta_window_raise (window); - else - meta_topic (META_DEBUG_FOCUS, - "Pointer not inside window, not raising %s", - window->desc); - } - - return G_SOURCE_REMOVE; -} - -void -meta_display_queue_autoraise_callback (MetaDisplay *display, - MetaWindow *window) -{ - meta_topic (META_DEBUG_FOCUS, - "Queuing an autoraise timeout for %s with delay %d", - window->desc, - meta_prefs_get_auto_raise_delay ()); - - g_clear_handle_id (&display->autoraise_timeout_id, g_source_remove); - - display->autoraise_timeout_id = - g_timeout_add_full (G_PRIORITY_DEFAULT, - meta_prefs_get_auto_raise_delay (), - window_raise_with_delay_callback, - window, NULL); - g_source_set_name_by_id (display->autoraise_timeout_id, "[mutter] window_raise_with_delay_callback"); - display->autoraise_window = window; -} - -void -meta_display_sync_wayland_input_focus (MetaDisplay *display) -{ -#ifdef HAVE_WAYLAND - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaWindow *focus_window = NULL; - MetaBackend *backend = meta_get_backend (); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - ClutterSeat *seat = clutter_backend_get_default_seat (clutter_backend); - MetaStage *stage = META_STAGE (meta_backend_get_stage (backend)); - gboolean is_no_focus_xwindow = FALSE; - - if (display->x11_display) - is_no_focus_xwindow = meta_x11_display_xwindow_is_a_no_focus_window (display->x11_display, - display->x11_display->focus_xwindow); - - if (!meta_display_windows_are_interactable (display)) - focus_window = NULL; - else if (is_no_focus_xwindow) - focus_window = NULL; - else if (display->focus_window && display->focus_window->surface) - focus_window = display->focus_window; - else - meta_topic (META_DEBUG_FOCUS, "Focus change has no effect, because there is no matching wayland surface"); - - meta_stage_set_active (stage, focus_window == NULL); - meta_wayland_compositor_set_input_focus (compositor, focus_window); - - clutter_stage_repick_device (CLUTTER_STAGE (stage), - clutter_seat_get_pointer (seat)); -#endif -} - -void -meta_display_update_focus_window (MetaDisplay *display, - MetaWindow *window) -{ - if (display->focus_window == window) - return; - - if (display->focus_window) - { - MetaWindow *previous; - - meta_topic (META_DEBUG_FOCUS, - "%s is now the previous focus window due to being focused out or unmapped", - display->focus_window->desc); - - /* Make sure that signals handlers invoked by - * meta_window_set_focused_internal() don't see - * display->focus_window->has_focus == FALSE - */ - previous = display->focus_window; - display->focus_window = NULL; - - meta_window_set_focused_internal (previous, FALSE); - } - - display->focus_window = window; - - if (display->focus_window) - { - meta_topic (META_DEBUG_FOCUS, "* Focus --> %s", - display->focus_window->desc); - meta_window_set_focused_internal (display->focus_window, TRUE); - } - else - meta_topic (META_DEBUG_FOCUS, "* Focus --> NULL"); - - if (meta_is_wayland_compositor ()) - meta_display_sync_wayland_input_focus (display); - - g_object_notify (G_OBJECT (display), "focus-window"); -} - -gboolean -meta_display_timestamp_too_old (MetaDisplay *display, - guint32 *timestamp) -{ - /* FIXME: If Soeren's suggestion in bug 151984 is implemented, it will allow - * us to sanity check the timestamp here and ensure it doesn't correspond to - * a future time (though we would want to rename to - * timestamp_too_old_or_in_future). - */ - - if (*timestamp == META_CURRENT_TIME) - { - *timestamp = meta_display_get_current_time_roundtrip (display); - return FALSE; - } - else if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_focus_time)) - { - if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_user_time)) - return TRUE; - else - { - *timestamp = display->last_focus_time; - return FALSE; - } - } - - return FALSE; -} - -void -meta_display_set_input_focus (MetaDisplay *display, - MetaWindow *window, - gboolean focus_frame, - guint32 timestamp) -{ - if (meta_display_timestamp_too_old (display, ×tamp)) - return; - - if (display->x11_display) - { - meta_x11_display_set_input_focus (display->x11_display, window, - focus_frame, timestamp); - } - - meta_display_update_focus_window (display, window); - - display->last_focus_time = timestamp; - - if (window == NULL || window != display->autoraise_window) - meta_display_remove_autoraise_callback (display); -} - -void -meta_display_unset_input_focus (MetaDisplay *display, - guint32 timestamp) -{ - meta_display_set_input_focus (display, NULL, FALSE, timestamp); -} - -void -meta_display_register_wayland_window (MetaDisplay *display, - MetaWindow *window) -{ - g_hash_table_add (display->wayland_windows, window); -} - -void -meta_display_unregister_wayland_window (MetaDisplay *display, - MetaWindow *window) -{ - g_hash_table_remove (display->wayland_windows, window); -} - -MetaWindow* -meta_display_lookup_stamp (MetaDisplay *display, - guint64 stamp) -{ - return g_hash_table_lookup (display->stamps, &stamp); -} - -void -meta_display_register_stamp (MetaDisplay *display, - guint64 *stampp, - MetaWindow *window) -{ - g_return_if_fail (g_hash_table_lookup (display->stamps, stampp) == NULL); - - g_hash_table_insert (display->stamps, stampp, window); -} - -void -meta_display_unregister_stamp (MetaDisplay *display, - guint64 stamp) -{ - g_return_if_fail (g_hash_table_lookup (display->stamps, &stamp) != NULL); - - g_hash_table_remove (display->stamps, &stamp); -} - -MetaWindow* -meta_display_lookup_stack_id (MetaDisplay *display, - guint64 stack_id) -{ - if (META_STACK_ID_IS_X11 (stack_id)) - { - if (!display->x11_display) - return NULL; - return meta_x11_display_lookup_x_window (display->x11_display, - (Window)stack_id); - } - else - { - return meta_display_lookup_stamp (display, stack_id); - } -} - -/* We return a pointer into a ring of static buffers. This is to make - * using this function for debug-logging convenient and avoid temporary - * strings that must be freed. */ -const char * -meta_display_describe_stack_id (MetaDisplay *display, - guint64 stack_id) -{ - /* 0x<64-bit: 16 characters> (<10 characters of title>)\0' */ - static char buffer[5][32]; - MetaWindow *window; - static int pos = 0; - char *result; - - result = buffer[pos]; - pos = (pos + 1) % 5; - - window = meta_display_lookup_stack_id (display, stack_id); - - if (window && window->title) - snprintf (result, sizeof(buffer[0]), "%#" G_GINT64_MODIFIER "x (%.10s)", stack_id, window->title); - else - snprintf (result, sizeof(buffer[0]), "%#" G_GINT64_MODIFIER "x", stack_id); - - return result; -} - -void -meta_display_notify_window_created (MetaDisplay *display, - MetaWindow *window) -{ - COGL_TRACE_BEGIN_SCOPED (MetaDisplayNotifyWindowCreated, - "Display (notify window created)"); - g_signal_emit (display, display_signals[WINDOW_CREATED], 0, window); -} - -static MetaCursor -meta_cursor_for_grab_op (MetaGrabOp op) -{ - switch (op) - { - case META_GRAB_OP_RESIZING_SE: - case META_GRAB_OP_KEYBOARD_RESIZING_SE: - return META_CURSOR_SE_RESIZE; - break; - case META_GRAB_OP_RESIZING_S: - case META_GRAB_OP_KEYBOARD_RESIZING_S: - return META_CURSOR_SOUTH_RESIZE; - break; - case META_GRAB_OP_RESIZING_SW: - case META_GRAB_OP_KEYBOARD_RESIZING_SW: - return META_CURSOR_SW_RESIZE; - break; - case META_GRAB_OP_RESIZING_N: - case META_GRAB_OP_KEYBOARD_RESIZING_N: - return META_CURSOR_NORTH_RESIZE; - break; - case META_GRAB_OP_RESIZING_NE: - case META_GRAB_OP_KEYBOARD_RESIZING_NE: - return META_CURSOR_NE_RESIZE; - break; - case META_GRAB_OP_RESIZING_NW: - case META_GRAB_OP_KEYBOARD_RESIZING_NW: - return META_CURSOR_NW_RESIZE; - break; - case META_GRAB_OP_RESIZING_W: - case META_GRAB_OP_KEYBOARD_RESIZING_W: - return META_CURSOR_WEST_RESIZE; - break; - case META_GRAB_OP_RESIZING_E: - case META_GRAB_OP_KEYBOARD_RESIZING_E: - return META_CURSOR_EAST_RESIZE; - break; - case META_GRAB_OP_MOVING: - case META_GRAB_OP_KEYBOARD_MOVING: - case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN: - return META_CURSOR_MOVE_OR_RESIZE_WINDOW; - break; - default: - break; - } - - return META_CURSOR_DEFAULT; -} - -static void -root_cursor_prepare_at (MetaCursorSpriteXcursor *sprite_xcursor, - float best_scale, - int x, - int y, - MetaDisplay *display) -{ - MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (sprite_xcursor); - MetaBackend *backend = meta_get_backend (); - - if (meta_is_stage_views_scaled ()) - { - if (best_scale != 0.0f) - { - float ceiled_scale; - - ceiled_scale = ceilf (best_scale); - meta_cursor_sprite_xcursor_set_theme_scale (sprite_xcursor, - (int) ceiled_scale); - meta_cursor_sprite_set_texture_scale (cursor_sprite, - 1.0 / ceiled_scale); - } - } - else - { - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaLogicalMonitor *logical_monitor; - - logical_monitor = - meta_monitor_manager_get_logical_monitor_at (monitor_manager, x, y); - - /* Reload the cursor texture if the scale has changed. */ - if (logical_monitor) - { - meta_cursor_sprite_xcursor_set_theme_scale (sprite_xcursor, - logical_monitor->scale); - meta_cursor_sprite_set_texture_scale (cursor_sprite, 1.0); - } - } -} - -static void -manage_root_cursor_sprite_scale (MetaDisplay *display, - MetaCursorSpriteXcursor *sprite_xcursor) -{ - g_signal_connect_object (sprite_xcursor, - "prepare-at", - G_CALLBACK (root_cursor_prepare_at), - display, - 0); -} - -void -meta_display_reload_cursor (MetaDisplay *display) -{ - MetaCursor cursor = display->current_cursor; - MetaCursorSpriteXcursor *sprite_xcursor; - MetaBackend *backend = meta_get_backend (); - MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); - - sprite_xcursor = meta_cursor_sprite_xcursor_new (cursor); - - if (meta_is_wayland_compositor ()) - manage_root_cursor_sprite_scale (display, sprite_xcursor); - - meta_cursor_tracker_set_root_cursor (cursor_tracker, - META_CURSOR_SPRITE (sprite_xcursor)); - g_object_unref (sprite_xcursor); - - g_signal_emit (display, display_signals[CURSOR_UPDATED], 0, display); -} - -void -meta_display_set_cursor (MetaDisplay *display, - MetaCursor cursor) -{ - if (cursor == display->current_cursor) - return; - - display->current_cursor = cursor; - meta_display_reload_cursor (display); -} - -void -meta_display_update_cursor (MetaDisplay *display) -{ - meta_display_set_cursor (display, meta_cursor_for_grab_op (display->grab_op)); -} - -static MetaWindow * -get_first_freefloating_window (MetaWindow *window) -{ - while (meta_window_is_attached_dialog (window)) - window = meta_window_get_transient_for (window); - - /* Attached dialogs should always have a non-NULL transient-for */ - g_assert (window != NULL); - - return window; -} - -static MetaEventRoute -get_event_route_from_grab_op (MetaGrabOp op) -{ - switch (META_GRAB_OP_GET_BASE_TYPE (op)) - { - case META_GRAB_OP_NONE: - /* begin_grab_op shouldn't be called with META_GRAB_OP_NONE. */ - g_assert_not_reached (); - - case META_GRAB_OP_WINDOW_BASE: - return META_EVENT_ROUTE_WINDOW_OP; - - case META_GRAB_OP_COMPOSITOR: - /* begin_grab_op shouldn't be called with META_GRAB_OP_COMPOSITOR. */ - g_assert_not_reached (); - - case META_GRAB_OP_WAYLAND_POPUP: - return META_EVENT_ROUTE_WAYLAND_POPUP; - - case META_GRAB_OP_FRAME_BUTTON: - return META_EVENT_ROUTE_FRAME_BUTTON; - - default: - g_assert_not_reached (); - return 0; - } -} - -gboolean -meta_display_begin_grab_op (MetaDisplay *display, - MetaWindow *window, - MetaGrabOp op, - gboolean pointer_already_grabbed, - gboolean frame_action, - int button, - gulong modmask, /* XXX - ignored */ - guint32 timestamp, - int root_x, - int root_y) -{ - MetaBackend *backend = meta_get_backend (); - MetaWindow *grab_window = NULL; - MetaEventRoute event_route; - - g_assert (window != NULL); - - meta_topic (META_DEBUG_WINDOW_OPS, - "Doing grab op %u on window %s button %d pointer already grabbed: %d pointer pos %d,%d", - op, window->desc, button, pointer_already_grabbed, - root_x, root_y); - - if (display->grab_op != META_GRAB_OP_NONE) - { - meta_warning ("Attempt to perform window operation %u on window %s when operation %u on %s already in effect", - op, window->desc, display->grab_op, - display->grab_window ? display->grab_window->desc : "none"); - return FALSE; - } - - event_route = get_event_route_from_grab_op (op); - - if (event_route == META_EVENT_ROUTE_WINDOW_OP) - { - if (meta_prefs_get_raise_on_click ()) - meta_window_raise (window); - else - { - display->grab_initial_x = root_x; - display->grab_initial_y = root_y; - display->grab_threshold_movement_reached = FALSE; - } - } - - grab_window = window; - - /* If we're trying to move a window, move the first - * non-attached dialog instead. - */ - if (meta_grab_op_is_moving (op)) - grab_window = get_first_freefloating_window (window); - - g_assert (grab_window != NULL); - g_assert (op != META_GRAB_OP_NONE); - - display->grab_have_pointer = FALSE; - - if (pointer_already_grabbed) - display->grab_have_pointer = TRUE; - - if (META_IS_BACKEND_X11 (meta_get_backend ()) && display->x11_display) - { - /* Since grab operations often happen as a result of implicit - * pointer operations on the display X11 connection, we need - * to ungrab here to ensure that the backend's X11 can take - * the device grab. */ - XIUngrabDevice (display->x11_display->xdisplay, - META_VIRTUAL_CORE_POINTER_ID, - timestamp); - XSync (display->x11_display->xdisplay, False); - } - - if (meta_backend_grab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp)) - display->grab_have_pointer = TRUE; - - if (!display->grab_have_pointer && !meta_grab_op_is_keyboard (op)) - { - meta_topic (META_DEBUG_WINDOW_OPS, "XIGrabDevice() failed"); - return FALSE; - } - - /* Grab keys when beginning window ops; see #126497 */ - if (event_route == META_EVENT_ROUTE_WINDOW_OP) - { - display->grab_have_keyboard = meta_window_grab_all_keys (grab_window, timestamp); - - if (!display->grab_have_keyboard) - { - meta_topic (META_DEBUG_WINDOW_OPS, "grabbing all keys failed, ungrabbing pointer"); - meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp); - display->grab_have_pointer = FALSE; - return FALSE; - } - } - - display->event_route = event_route; - display->grab_op = op; - display->grab_window = grab_window; - display->grab_button = button; - display->grab_tile_mode = grab_window->tile_mode; - display->grab_tile_monitor_number = grab_window->tile_monitor_number; - display->grab_anchor_root_x = root_x; - display->grab_anchor_root_y = root_y; - display->grab_latest_motion_x = root_x; - display->grab_latest_motion_y = root_y; - display->grab_last_moveresize_time = 0; - display->grab_last_edge_resistance_flags = META_EDGE_RESISTANCE_DEFAULT; - display->grab_frame_action = frame_action; - - meta_display_update_cursor (display); - - g_clear_handle_id (&display->grab_resize_timeout_id, g_source_remove); - - meta_topic (META_DEBUG_WINDOW_OPS, - "Grab op %u on window %s successful", - display->grab_op, window ? window->desc : "(null)"); - - meta_window_get_frame_rect (display->grab_window, - &display->grab_initial_window_pos); - display->grab_anchor_window_pos = display->grab_initial_window_pos; - - if (meta_is_wayland_compositor ()) - { - meta_display_sync_wayland_input_focus (display); - meta_display_cancel_touch (display); - } - - g_signal_emit (display, display_signals[GRAB_OP_BEGIN], 0, - display->grab_window, display->grab_op); - - if (display->event_route == META_EVENT_ROUTE_WINDOW_OP) - meta_window_grab_op_began (display->grab_window, display->grab_op); - - return TRUE; -} - -void -meta_display_end_grab_op (MetaDisplay *display, - guint32 timestamp) -{ - MetaWindow *grab_window = display->grab_window; - MetaGrabOp grab_op = display->grab_op; - - meta_topic (META_DEBUG_WINDOW_OPS, - "Ending grab op %u at time %u", grab_op, timestamp); - - if (display->event_route == META_EVENT_ROUTE_NORMAL || - display->event_route == META_EVENT_ROUTE_COMPOSITOR_GRAB) - return; - - g_assert (grab_window != NULL); - - /* We need to reset this early, since the - * meta_window_grab_op_ended callback relies on this being - * up to date. */ - display->grab_op = META_GRAB_OP_NONE; - - if (display->event_route == META_EVENT_ROUTE_WINDOW_OP) - { - /* Clear out the edge cache */ - meta_display_cleanup_edges (display); - - /* Only raise the window in orthogonal raise - * ('do-not-raise-on-click') mode if the user didn't try to move - * or resize the given window by at least a threshold amount. - * For raise on click mode, the window was raised at the - * beginning of the grab_op. - */ - if (!meta_prefs_get_raise_on_click () && - !display->grab_threshold_movement_reached) - meta_window_raise (display->grab_window); - - meta_window_grab_op_ended (grab_window, grab_op); - } - - if (display->grab_have_pointer) - { - MetaBackend *backend = meta_get_backend (); - meta_backend_ungrab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp); - } - - if (display->grab_have_keyboard) - { - meta_topic (META_DEBUG_WINDOW_OPS, - "Ungrabbing all keys timestamp %u", timestamp); - meta_window_ungrab_all_keys (grab_window, timestamp); - } - - display->event_route = META_EVENT_ROUTE_NORMAL; - display->grab_window = NULL; - display->grab_button = 0; - display->grab_tile_mode = META_TILE_NONE; - display->grab_tile_monitor_number = -1; - display->grab_anchor_root_x = 0; - display->grab_anchor_root_y = 0; - display->grab_latest_motion_x = 0; - display->grab_latest_motion_y = 0; - display->grab_last_moveresize_time = 0; - display->grab_last_edge_resistance_flags = META_EDGE_RESISTANCE_DEFAULT; - display->grab_frame_action = FALSE; - - meta_display_update_cursor (display); - - g_clear_handle_id (&display->grab_resize_timeout_id, g_source_remove); - - if (meta_is_wayland_compositor ()) - meta_display_sync_wayland_input_focus (display); - - g_signal_emit (display, display_signals[GRAB_OP_END], 0, - grab_window, grab_op); -} - -/** - * meta_display_get_grab_op: - * @display: The #MetaDisplay that the window is on - - * Gets the current grab operation, if any. - * - * Return value: the current grab operation, or %META_GRAB_OP_NONE if - * Mutter doesn't currently have a grab. %META_GRAB_OP_COMPOSITOR will - * be returned if a compositor-plugin modal operation is in effect - * (See mutter_begin_modal_for_plugin()) - */ -MetaGrabOp -meta_display_get_grab_op (MetaDisplay *display) -{ - return display->grab_op; -} - -void -meta_display_check_threshold_reached (MetaDisplay *display, - int x, - int y) -{ - /* Don't bother doing the check again if we've already reached the threshold */ - if (meta_prefs_get_raise_on_click () || - display->grab_threshold_movement_reached) - return; - - if (ABS (display->grab_initial_x - x) >= 8 || - ABS (display->grab_initial_y - y) >= 8) - display->grab_threshold_movement_reached = TRUE; -} - -void -meta_display_queue_retheme_all_windows (MetaDisplay *display) -{ - GSList* windows; - GSList *tmp; - - windows = meta_display_list_windows (display, META_LIST_DEFAULT); - tmp = windows; - while (tmp != NULL) - { - MetaWindow *window = tmp->data; - - meta_window_queue (window, META_QUEUE_MOVE_RESIZE); - meta_window_frame_size_changed (window); - if (window->frame) - { - meta_frame_queue_draw (window->frame); - } - - tmp = tmp->next; - } - - g_slist_free (windows); -} - -/* - * Stores whether syncing is currently enabled. - */ -static gboolean is_syncing = FALSE; - -/** - * meta_is_syncing: - * - * Returns whether X synchronisation is currently enabled. - * - * FIXME: This is *only* called by meta_display_open(), but by that time - * we have already turned syncing on or off on startup, and we don't - * have any way to do so while Mutter is running, so it's rather - * pointless. - * - * Returns: %TRUE if we must wait for events whenever we send X requests; - * %FALSE otherwise. - */ -gboolean -meta_is_syncing (void) -{ - return is_syncing; -} - -/** - * meta_set_syncing: - * @setting: whether to turn syncing on or off - * - * A handy way to turn on synchronisation on or off for every display. - */ -void -meta_set_syncing (gboolean setting) -{ - if (setting != is_syncing) - { - is_syncing = setting; - if (meta_get_display ()) - XSynchronize (meta_get_display ()->x11_display->xdisplay, is_syncing); - } -} - -/** - * meta_display_ping_timeout: - * @data: All the information about this ping. It is a #MetaPingData - * cast to a #gpointer in order to be passable to a timeout function. - * This function will also free this parameter. - * - * Does whatever it is we decided to do when a window didn't respond - * to a ping. We also remove the ping from the display's list of - * pending pings. This function is called by the event loop when the timeout - * times out which we created at the start of the ping. - * - * Returns: Always returns %FALSE, because this function is called as a - * timeout and we don't want to run the timer again. - */ -static gboolean -meta_display_ping_timeout (gpointer data) -{ - MetaPingData *ping_data = data; - MetaWindow *window = ping_data->window; - MetaDisplay *display = window->display; - - meta_window_set_alive (window, FALSE); - - ping_data->ping_timeout_id = 0; - - meta_topic (META_DEBUG_PING, - "Ping %u on window %s timed out", - ping_data->serial, ping_data->window->desc); - - display->pending_pings = g_slist_remove (display->pending_pings, ping_data); - ping_data_free (ping_data); - - return FALSE; -} - -/** - * meta_display_ping_window: - * @display: The #MetaDisplay that the window is on - * @window: The #MetaWindow to send the ping to - * @timestamp: The timestamp of the ping. Used for uniqueness. - * Cannot be CurrentTime; use a real timestamp! - * - * Sends a ping request to a window. The window must respond to - * the request within a certain amount of time. If it does, we - * will call one callback; if the time passes and we haven't had - * a response, we call a different callback. The window must have - * the hint showing that it can respond to a ping; if it doesn't, - * we call the "got a response" callback immediately and return. - * This function returns straight away after setting things up; - * the callbacks will be called from the event loop. - */ -void -meta_display_ping_window (MetaWindow *window, - guint32 serial) -{ - GSList *l; - MetaDisplay *display = window->display; - MetaPingData *ping_data; - unsigned int check_alive_timeout; - - check_alive_timeout = meta_prefs_get_check_alive_timeout (); - if (check_alive_timeout == 0) - return; - - if (serial == 0) - { - meta_warning ("Tried to ping window %s with a bad serial! Not allowed.", - window->desc); - return; - } - - if (!meta_window_can_ping (window)) - return; - - for (l = display->pending_pings; l; l = l->next) - { - MetaPingData *ping_data = l->data; - - if (window == ping_data->window) - { - meta_topic (META_DEBUG_PING, - "Window %s already is being pinged with serial %u", - window->desc, ping_data->serial); - return; - } - - if (serial == ping_data->serial) - { - meta_warning ("Ping serial %u was reused for window %s, " - "previous use was for window %s.", - serial, window->desc, ping_data->window->desc); - return; - } - } - - ping_data = g_new (MetaPingData, 1); - ping_data->window = window; - ping_data->serial = serial; - ping_data->ping_timeout_id = - g_timeout_add (check_alive_timeout, - meta_display_ping_timeout, - ping_data); - g_source_set_name_by_id (ping_data->ping_timeout_id, "[mutter] meta_display_ping_timeout"); - - display->pending_pings = g_slist_prepend (display->pending_pings, ping_data); - - meta_topic (META_DEBUG_PING, - "Sending ping with serial %u to window %s", - serial, window->desc); - - META_WINDOW_GET_CLASS (window)->ping (window, serial); -} - -/** - * meta_display_pong_for_serial: - * @display: the display we got the pong from - * @serial: the serial in the pong response - * - * Process the pong (the response message) from the ping we sent - * to the window. This involves removing the timeout, calling the - * reply handler function, and freeing memory. - */ -void -meta_display_pong_for_serial (MetaDisplay *display, - guint32 serial) -{ - GSList *tmp; - - meta_topic (META_DEBUG_PING, "Received a pong with serial %u", serial); - - for (tmp = display->pending_pings; tmp; tmp = tmp->next) - { - MetaPingData *ping_data = tmp->data; - - if (serial == ping_data->serial) - { - meta_topic (META_DEBUG_PING, - "Matching ping found for pong %u", - ping_data->serial); - - /* Remove the ping data from the list */ - display->pending_pings = g_slist_remove (display->pending_pings, - ping_data); - - /* Remove the timeout */ - g_clear_handle_id (&ping_data->ping_timeout_id, g_source_remove); - - meta_window_set_alive (ping_data->window, TRUE); - ping_data_free (ping_data); - break; - } - } -} - -static MetaGroup * -get_focused_group (MetaDisplay *display) -{ - if (display->focus_window) - return display->focus_window->group; - else - return NULL; -} - -#define IN_TAB_CHAIN(w,t) (((t) == META_TAB_LIST_NORMAL && META_WINDOW_IN_NORMAL_TAB_CHAIN (w)) \ - || ((t) == META_TAB_LIST_DOCKS && META_WINDOW_IN_DOCK_TAB_CHAIN (w)) \ - || ((t) == META_TAB_LIST_GROUP && META_WINDOW_IN_GROUP_TAB_CHAIN (w, get_focused_group (w->display))) \ - || ((t) == META_TAB_LIST_NORMAL_ALL && META_WINDOW_IN_NORMAL_TAB_CHAIN_TYPE (w))) - -static MetaWindow* -find_tab_forward (MetaDisplay *display, - MetaTabList type, - MetaWorkspace *workspace, - GList *start, - gboolean skip_first) -{ - GList *tmp; - - g_return_val_if_fail (start != NULL, NULL); - g_return_val_if_fail (workspace != NULL, NULL); - - tmp = start; - if (skip_first) - tmp = tmp->next; - - while (tmp != NULL) - { - MetaWindow *window = tmp->data; - - if (IN_TAB_CHAIN (window, type)) - return window; - - tmp = tmp->next; - } - - tmp = workspace->mru_list; - while (tmp != start) - { - MetaWindow *window = tmp->data; - - if (IN_TAB_CHAIN (window, type)) - return window; - - tmp = tmp->next; - } - - return NULL; -} - -static MetaWindow* -find_tab_backward (MetaDisplay *display, - MetaTabList type, - MetaWorkspace *workspace, - GList *start, - gboolean skip_last) -{ - GList *tmp; - - g_return_val_if_fail (start != NULL, NULL); - g_return_val_if_fail (workspace != NULL, NULL); - - tmp = start; - if (skip_last) - tmp = tmp->prev; - while (tmp != NULL) - { - MetaWindow *window = tmp->data; - - if (IN_TAB_CHAIN (window, type)) - return window; - - tmp = tmp->prev; - } - - tmp = g_list_last (workspace->mru_list); - while (tmp != start) - { - MetaWindow *window = tmp->data; - - if (IN_TAB_CHAIN (window, type)) - return window; - - tmp = tmp->prev; - } - - return NULL; -} - -static int -mru_cmp (gconstpointer a, - gconstpointer b) -{ - guint32 time_a, time_b; - - time_a = meta_window_get_user_time ((MetaWindow *)a); - time_b = meta_window_get_user_time ((MetaWindow *)b); - - if (time_a > time_b) - return -1; - else if (time_a < time_b) - return 1; - else - return 0; -} - -/** - * meta_display_get_tab_list: - * @display: a #MetaDisplay - * @type: type of tab list - * @workspace: (nullable): origin workspace - * - * Determine the list of windows that should be displayed for Alt-TAB - * functionality. The windows are returned in most recently used order. - * If @workspace is not %NULL, the list only contains windows that are on - * @workspace or have the demands-attention hint set; otherwise it contains - * all windows. - * - * Returns: (transfer container) (element-type Meta.Window): List of windows - */ -GList* -meta_display_get_tab_list (MetaDisplay *display, - MetaTabList type, - MetaWorkspace *workspace) -{ - GList *tab_list = NULL; - GList *global_mru_list = NULL; - GList *mru_list, *tmp; - GSList *windows = meta_display_list_windows (display, META_LIST_DEFAULT); - GSList *w; - - if (workspace == NULL) - { - /* Yay for mixing GList and GSList in the API */ - for (w = windows; w; w = w->next) - global_mru_list = g_list_prepend (global_mru_list, w->data); - global_mru_list = g_list_sort (global_mru_list, mru_cmp); - } - - mru_list = workspace ? workspace->mru_list : global_mru_list; - - /* Windows sellout mode - MRU order. Collect unminimized windows - * then minimized so minimized windows aren't in the way so much. - */ - for (tmp = mru_list; tmp; tmp = tmp->next) - { - MetaWindow *window = tmp->data; - - if (!window->minimized && IN_TAB_CHAIN (window, type)) - tab_list = g_list_prepend (tab_list, window); - } - - for (tmp = mru_list; tmp; tmp = tmp->next) - { - MetaWindow *window = tmp->data; - - if (window->minimized && IN_TAB_CHAIN (window, type)) - tab_list = g_list_prepend (tab_list, window); - } - - tab_list = g_list_reverse (tab_list); - - /* If filtering by workspace, include windows from - * other workspaces that demand attention - */ - if (workspace) - for (w = windows; w; w = w->next) - { - MetaWindow *l_window = w->data; - - if (l_window->wm_state_demands_attention && - !meta_window_located_on_workspace (l_window, workspace) && - IN_TAB_CHAIN (l_window, type)) - tab_list = g_list_prepend (tab_list, l_window); - } - - g_list_free (global_mru_list); - g_slist_free (windows); - - return tab_list; -} - -/** - * meta_display_get_tab_next: - * @display: a #MetaDisplay - * @type: type of tab list - * @workspace: origin workspace - * @window: (nullable): starting window - * @backward: If %TRUE, look for the previous window. - * - * Determine the next window that should be displayed for Alt-TAB - * functionality. - * - * Returns: (transfer none): Next window - * - */ -MetaWindow* -meta_display_get_tab_next (MetaDisplay *display, - MetaTabList type, - MetaWorkspace *workspace, - MetaWindow *window, - gboolean backward) -{ - gboolean skip; - GList *tab_list; - MetaWindow *ret; - tab_list = meta_display_get_tab_list (display, type, workspace); - - if (tab_list == NULL) - return NULL; - - if (window != NULL) - { - g_assert (window->display == display); - - if (backward) - ret = find_tab_backward (display, type, workspace, g_list_find (tab_list, window), TRUE); - else - ret = find_tab_forward (display, type, workspace, g_list_find (tab_list, window), TRUE); - } - else - { - skip = display->focus_window != NULL && - tab_list->data == display->focus_window; - if (backward) - ret = find_tab_backward (display, type, workspace, tab_list, skip); - else - ret = find_tab_forward (display, type, workspace, tab_list, skip); - } - - g_list_free (tab_list); - return ret; -} - -/** - * meta_display_get_tab_current: - * @display: a #MetaDisplay - * @type: type of tab list - * @workspace: origin workspace - * - * Determine the active window that should be displayed for Alt-TAB. - * - * Returns: (transfer none): Current window - * - */ -MetaWindow* -meta_display_get_tab_current (MetaDisplay *display, - MetaTabList type, - MetaWorkspace *workspace) -{ - MetaWindow *window; - - window = display->focus_window; - - if (window != NULL && - IN_TAB_CHAIN (window, type) && - (workspace == NULL || - meta_window_located_on_workspace (window, workspace))) - return window; - else - return NULL; -} - -MetaGravity -meta_resize_gravity_from_grab_op (MetaGrabOp op) -{ - MetaGravity gravity; - - gravity = -1; - switch (op) - { - case META_GRAB_OP_RESIZING_SE: - case META_GRAB_OP_KEYBOARD_RESIZING_SE: - gravity = META_GRAVITY_NORTH_WEST; - break; - case META_GRAB_OP_KEYBOARD_RESIZING_S: - case META_GRAB_OP_RESIZING_S: - gravity = META_GRAVITY_NORTH; - break; - case META_GRAB_OP_KEYBOARD_RESIZING_SW: - case META_GRAB_OP_RESIZING_SW: - gravity = META_GRAVITY_NORTH_EAST; - break; - case META_GRAB_OP_KEYBOARD_RESIZING_N: - case META_GRAB_OP_RESIZING_N: - gravity = META_GRAVITY_SOUTH; - break; - case META_GRAB_OP_KEYBOARD_RESIZING_NE: - case META_GRAB_OP_RESIZING_NE: - gravity = META_GRAVITY_SOUTH_WEST; - break; - case META_GRAB_OP_KEYBOARD_RESIZING_NW: - case META_GRAB_OP_RESIZING_NW: - gravity = META_GRAVITY_SOUTH_EAST; - break; - case META_GRAB_OP_KEYBOARD_RESIZING_E: - case META_GRAB_OP_RESIZING_E: - gravity = META_GRAVITY_WEST; - break; - case META_GRAB_OP_KEYBOARD_RESIZING_W: - case META_GRAB_OP_RESIZING_W: - gravity = META_GRAVITY_EAST; - break; - case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN: - gravity = META_GRAVITY_CENTER; - break; - default: - break; - } - - return gravity; -} - -void -meta_display_manage_all_xwindows (MetaDisplay *display) -{ - guint64 *_children; - guint64 *children; - int n_children, i; - - meta_stack_freeze (display->stack); - meta_stack_tracker_get_stack (display->stack_tracker, &_children, &n_children); - - /* Copy the stack as it will be modified as part of the loop */ - children = g_memdup2 (_children, sizeof (uint64_t) * n_children); - - for (i = 0; i < n_children; ++i) - { - if (!META_STACK_ID_IS_X11 (children[i])) - continue; - meta_window_x11_new (display, children[i], TRUE, - META_COMP_EFFECT_NONE); - } - - g_free (children); - meta_stack_thaw (display->stack); -} - -void -meta_display_unmanage_windows (MetaDisplay *display, - guint32 timestamp) -{ - GSList *tmp; - GSList *winlist; - - winlist = meta_display_list_windows (display, - META_LIST_INCLUDE_OVERRIDE_REDIRECT); - winlist = g_slist_sort (winlist, meta_display_stack_cmp); - g_slist_foreach (winlist, (GFunc)g_object_ref, NULL); - - /* Unmanage all windows */ - tmp = winlist; - while (tmp != NULL) - { - MetaWindow *window = tmp->data; - - /* Check if already unmanaged for safety - in particular, catch - * the case where unmanaging a parent window can cause attached - * dialogs to be (temporarily) unmanaged. - */ - if (!window->unmanaging) - meta_window_unmanage (window, timestamp); - g_object_unref (window); - - tmp = tmp->next; - } - g_slist_free (winlist); -} - -int -meta_display_stack_cmp (const void *a, - const void *b) -{ - MetaWindow *aw = (void*) a; - MetaWindow *bw = (void*) b; - - return meta_stack_windows_cmp (aw->display->stack, aw, bw); -} - -/** - * meta_display_sort_windows_by_stacking: - * @display: a #MetaDisplay - * @windows: (element-type MetaWindow): Set of windows - * - * Sorts a set of windows according to their current stacking order. If windows - * from multiple screens are present in the set of input windows, then all the - * windows on screen 0 are sorted below all the windows on screen 1, and so forth. - * Since the stacking order of override-redirect windows isn't controlled by - * Metacity, if override-redirect windows are in the input, the result may not - * correspond to the actual stacking order in the X server. - * - * An example of using this would be to sort the list of transient dialogs for a - * window into their current stacking order. - * - * Returns: (transfer container) (element-type MetaWindow): Input windows sorted by stacking order, from lowest to highest - */ -GSList * -meta_display_sort_windows_by_stacking (MetaDisplay *display, - GSList *windows) -{ - GSList *copy = g_slist_copy (windows); - - copy = g_slist_sort (copy, meta_display_stack_cmp); - - return copy; -} - -static void -prefs_changed_callback (MetaPreference pref, - void *data) -{ - MetaDisplay *display = data; - - switch (pref) - { - case META_PREF_DRAGGABLE_BORDER_WIDTH: - meta_display_queue_retheme_all_windows (display); - break; - case META_PREF_CURSOR_THEME: - case META_PREF_CURSOR_SIZE: - meta_display_reload_cursor (display); - break; - default: - break; - } -} - -void -meta_display_sanity_check_timestamps (MetaDisplay *display, - guint32 timestamp) -{ - if (XSERVER_TIME_IS_BEFORE (timestamp, display->last_focus_time)) - { - meta_warning ("last_focus_time (%u) is greater than comparison " - "timestamp (%u). This most likely represents a buggy " - "client sending inaccurate timestamps in messages such as " - "_NET_ACTIVE_WINDOW. Trying to work around...", - display->last_focus_time, timestamp); - display->last_focus_time = timestamp; - } - if (XSERVER_TIME_IS_BEFORE (timestamp, display->last_user_time)) - { - GSList *windows; - GSList *tmp; - - meta_warning ("last_user_time (%u) is greater than comparison " - "timestamp (%u). This most likely represents a buggy " - "client sending inaccurate timestamps in messages such as " - "_NET_ACTIVE_WINDOW. Trying to work around...", - display->last_user_time, timestamp); - display->last_user_time = timestamp; - - windows = meta_display_list_windows (display, META_LIST_DEFAULT); - tmp = windows; - while (tmp != NULL) - { - MetaWindow *window = tmp->data; - - if (XSERVER_TIME_IS_BEFORE (timestamp, window->net_wm_user_time)) - { - meta_warning ("%s appears to be one of the offending windows " - "with a timestamp of %u. Working around...", - window->desc, window->net_wm_user_time); - meta_window_set_user_time (window, timestamp); - } - - tmp = tmp->next; - } - - g_slist_free (windows); - } -} - -void -meta_display_remove_autoraise_callback (MetaDisplay *display) -{ - g_clear_handle_id (&display->autoraise_timeout_id, g_source_remove); - display->autoraise_window = NULL; -} - -void -meta_display_overlay_key_activate (MetaDisplay *display) -{ - g_signal_emit (display, display_signals[OVERLAY_KEY], 0); -} - -void -meta_display_accelerator_activate (MetaDisplay *display, - guint action, - ClutterKeyEvent *event) -{ - g_signal_emit (display, display_signals[ACCELERATOR_ACTIVATED], 0, - action, - clutter_event_get_source_device ((ClutterEvent *) event), - event->time); -} - -gboolean -meta_display_modifiers_accelerator_activate (MetaDisplay *display) -{ - gboolean freeze; - - g_signal_emit (display, display_signals[MODIFIERS_ACCELERATOR_ACTIVATED], 0, &freeze); - - return freeze; -} - -/** - * meta_display_supports_extended_barriers: - * @display: a #MetaDisplay - * - * Returns: whether pointer barriers can be supported. - * - * When running as an X compositor the X server needs XInput 2 - * version 2.3. When running as a display server it is supported - * when running on the native backend. - * - * Clients should use this method to determine whether their - * interfaces should depend on new barrier features. - */ -gboolean -meta_display_supports_extended_barriers (MetaDisplay *display) -{ -#ifdef HAVE_NATIVE_BACKEND - if (META_IS_BACKEND_NATIVE (meta_get_backend ())) - return TRUE; -#endif - - if (META_IS_BACKEND_X11_CM (meta_get_backend ())) - { - if (meta_is_wayland_compositor()) - return FALSE; - - return META_X11_DISPLAY_HAS_XINPUT_23 (display->x11_display); - } - - return FALSE; -} - -/** - * meta_display_get_context: - * @display: a #MetaDisplay - * - * Returns: (transfer none): the #MetaContext - */ -MetaContext * -meta_display_get_context (MetaDisplay *display) -{ - MetaDisplayPrivate *priv = meta_display_get_instance_private (display); - - return priv->context; -} - -/** - * meta_display_get_compositor: (skip) - * @display: a #MetaDisplay - * - */ -MetaCompositor * -meta_display_get_compositor (MetaDisplay *display) -{ - return display->compositor; -} - -/** - * meta_display_get_x11_display: (skip) - * @display: a #MetaDisplay - * - */ -MetaX11Display * -meta_display_get_x11_display (MetaDisplay *display) -{ - return display->x11_display; -} - -/** - * meta_display_get_size: - * @display: A #MetaDisplay - * @width: (out): The width of the screen - * @height: (out): The height of the screen - * - * Retrieve the size of the display. - */ -void -meta_display_get_size (MetaDisplay *display, - int *width, - int *height) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - int display_width, display_height; - - meta_monitor_manager_get_screen_size (monitor_manager, - &display_width, - &display_height); - - if (width != NULL) - *width = display_width; - - if (height != NULL) - *height = display_height; -} - -/** - * meta_display_get_focus_window: - * @display: a #MetaDisplay - * - * Get our best guess as to the "currently" focused window (that is, - * the window that we expect will be focused at the point when the X - * server processes our next request). - * - * Return Value: (transfer none): The current focus window - */ -MetaWindow * -meta_display_get_focus_window (MetaDisplay *display) -{ - return display->focus_window; -} - -/** - * meta_display_clear_mouse_mode: - * @display: a #MetaDisplay - * - * Sets the mouse-mode flag to %FALSE, which means that motion events are - * no longer ignored in mouse or sloppy focus. - * This is an internal function. It should be used only for reimplementing - * keybindings, and only in a manner compatible with core code. - */ -void -meta_display_clear_mouse_mode (MetaDisplay *display) -{ - display->mouse_mode = FALSE; -} - -MetaGestureTracker * -meta_display_get_gesture_tracker (MetaDisplay *display) -{ - return display->gesture_tracker; -} - -gboolean -meta_display_show_restart_message (MetaDisplay *display, - const char *message) -{ - gboolean result = FALSE; - - g_signal_emit (display, - display_signals[SHOW_RESTART_MESSAGE], 0, - message, &result); - - return result; -} - -gboolean -meta_display_request_restart (MetaDisplay *display) -{ - gboolean result = FALSE; - - g_signal_emit (display, - display_signals[RESTART], 0, - &result); - - return result; -} - -gboolean -meta_display_show_resize_popup (MetaDisplay *display, - gboolean show, - MetaRectangle *rect, - int display_w, - int display_h) -{ - gboolean result = FALSE; - - g_signal_emit (display, - display_signals[SHOW_RESIZE_POPUP], 0, - show, rect, display_w, display_h, &result); - - return result; -} - -/** - * meta_display_is_pointer_emulating_sequence: - * @display: the display - * @sequence: (nullable): a #ClutterEventSequence - * - * Tells whether the event sequence is the used for pointer emulation - * and single-touch interaction. - * - * Returns: #TRUE if the sequence emulates pointer behavior - **/ -gboolean -meta_display_is_pointer_emulating_sequence (MetaDisplay *display, - ClutterEventSequence *sequence) -{ - if (!sequence) - return FALSE; - - return display->pointer_emulating_sequence == sequence; -} - -void -meta_display_request_pad_osd (MetaDisplay *display, - ClutterInputDevice *pad, - gboolean edition_mode) -{ - MetaBackend *backend = meta_get_backend (); - MetaInputMapper *input_mapper; - const gchar *layout_path = NULL; - ClutterActor *osd; - MetaLogicalMonitor *logical_monitor; - GSettings *settings; -#ifdef HAVE_LIBWACOM - WacomDevice *wacom_device; -#endif - - /* Avoid emitting the signal while there is an OSD being currently - * displayed, the first OSD will have to be dismissed before showing - * any other one. - */ - if (display->current_pad_osd) - return; - - input_mapper = meta_backend_get_input_mapper (meta_get_backend ()); - - if (input_mapper) - { - settings = meta_input_mapper_get_tablet_settings (input_mapper, pad); - logical_monitor = - meta_input_mapper_get_device_logical_monitor (input_mapper, pad); -#ifdef HAVE_LIBWACOM - wacom_device = meta_input_device_get_wacom_device (META_INPUT_DEVICE (pad)); - layout_path = libwacom_get_layout_filename (wacom_device); -#endif - } - - if (!layout_path || !settings) - return; - - if (!logical_monitor) - logical_monitor = meta_backend_get_current_logical_monitor (backend); - - g_signal_emit (display, display_signals[SHOW_PAD_OSD], 0, - pad, settings, layout_path, - edition_mode, logical_monitor->number, &osd); - - if (osd) - { - display->current_pad_osd = osd; - g_object_add_weak_pointer (G_OBJECT (display->current_pad_osd), - (gpointer *) &display->current_pad_osd); - } -} - -gchar * -meta_display_get_pad_action_label (MetaDisplay *display, - ClutterInputDevice *pad, - MetaPadActionType action_type, - guint action_number) -{ - gchar *label; - - /* First, lookup the action, as imposed by settings */ - label = meta_pad_action_mapper_get_action_label (display->pad_action_mapper, - pad, action_type, - action_number); - if (label) - return label; - -#ifdef HAVE_WAYLAND - /* Second, if this wayland, lookup the actions set by the clients */ - if (meta_is_wayland_compositor ()) - { - MetaWaylandCompositor *compositor; - MetaWaylandTabletSeat *tablet_seat; - MetaWaylandTabletPad *tablet_pad = NULL; - - compositor = meta_wayland_compositor_get_default (); - tablet_seat = meta_wayland_tablet_manager_ensure_seat (compositor->tablet_manager, - compositor->seat); - if (tablet_seat) - tablet_pad = meta_wayland_tablet_seat_lookup_pad (tablet_seat, pad); - - if (tablet_pad) - { - label = meta_wayland_tablet_pad_get_label (tablet_pad, action_type, - action_number); - } - - if (label) - return label; - } -#endif - - return NULL; -} - -static void -meta_display_show_osd (MetaDisplay *display, - gint monitor_idx, - const gchar *icon_name, - const gchar *message) -{ - g_signal_emit (display, display_signals[SHOW_OSD], 0, - monitor_idx, icon_name, message); -} - -static gint -lookup_tablet_monitor (MetaDisplay *display, - ClutterInputDevice *device) -{ - MetaInputMapper *input_mapper; - MetaLogicalMonitor *monitor; - gint monitor_idx = -1; - - input_mapper = meta_backend_get_input_mapper (meta_get_backend ()); - if (!input_mapper) - return -1; - - monitor = meta_input_mapper_get_device_logical_monitor (input_mapper, device); - - if (monitor) - { - monitor_idx = meta_display_get_monitor_index_for_rect (display, - &monitor->rect); - } - - return monitor_idx; -} - -void -meta_display_show_tablet_mapping_notification (MetaDisplay *display, - ClutterInputDevice *pad, - const gchar *pretty_name) -{ - if (!pretty_name) - pretty_name = clutter_input_device_get_device_name (pad); - meta_display_show_osd (display, lookup_tablet_monitor (display, pad), - "input-tablet-symbolic", pretty_name); -} - -void -meta_display_notify_pad_group_switch (MetaDisplay *display, - ClutterInputDevice *pad, - const gchar *pretty_name, - guint n_group, - guint n_mode, - guint n_modes) -{ - GString *message; - guint i; - - if (!pretty_name) - pretty_name = clutter_input_device_get_device_name (pad); - - message = g_string_new (pretty_name); - g_string_append_c (message, '\n'); - for (i = 0; i < n_modes; i++) - g_string_append (message, (i == n_mode) ? "⚫" : "⚪"); - - meta_display_show_osd (display, lookup_tablet_monitor (display, pad), - "input-tablet-symbolic", message->str); - - g_signal_emit (display, display_signals[PAD_MODE_SWITCH], 0, pad, - n_group, n_mode); - - g_string_free (message, TRUE); -} - -void -meta_display_foreach_window (MetaDisplay *display, - MetaListWindowsFlags flags, - MetaDisplayWindowFunc func, - gpointer data) -{ - GSList *windows; - - /* If we end up doing this often, just keeping a list - * of windows might be sensible. - */ - - windows = meta_display_list_windows (display, flags); - - g_slist_foreach (windows, (GFunc) func, data); - - g_slist_free (windows); -} - -static void -meta_display_resize_func (MetaWindow *window, - gpointer user_data) -{ - if (window->struts) - { - meta_window_update_struts (window); - } - meta_window_queue (window, META_QUEUE_MOVE_RESIZE); - - meta_window_recalc_features (window); -} - -static void -on_monitors_changed_internal (MetaMonitorManager *monitor_manager, - MetaDisplay *display) -{ - meta_workspace_manager_reload_work_areas (display->workspace_manager); - - /* Fix up monitor for all windows on this display */ - meta_display_foreach_window (display, META_LIST_INCLUDE_OVERRIDE_REDIRECT, - (MetaDisplayWindowFunc) - meta_window_update_for_monitors_changed, 0); - - /* Queue a resize on all the windows */ - meta_display_foreach_window (display, META_LIST_DEFAULT, - meta_display_resize_func, 0); - - meta_display_queue_check_fullscreen (display); -} - -void -meta_display_restacked (MetaDisplay *display) -{ - g_signal_emit (display, display_signals[RESTACKED], 0); -} - -static gboolean -meta_display_update_tile_preview_timeout (gpointer data) -{ - MetaDisplay *display = data; - MetaWindow *window = display->grab_window; - gboolean needs_preview = FALSE; - - display->tile_preview_timeout_id = 0; - - if (window) - { - switch (display->preview_tile_mode) - { - case META_TILE_LEFT: - case META_TILE_RIGHT: - if (!META_WINDOW_TILED_SIDE_BY_SIDE (window)) - needs_preview = TRUE; - break; - - case META_TILE_MAXIMIZED: - if (!META_WINDOW_MAXIMIZED (window)) - needs_preview = TRUE; - break; - - default: - needs_preview = FALSE; - break; - } - } - - if (needs_preview) - { - MetaRectangle tile_rect; - int monitor; - - monitor = meta_window_get_current_tile_monitor_number (window); - meta_window_get_tile_area (window, display->preview_tile_mode, - &tile_rect); - meta_compositor_show_tile_preview (display->compositor, - window, &tile_rect, monitor); - } - else - meta_compositor_hide_tile_preview (display->compositor); - - return FALSE; -} - -#define TILE_PREVIEW_TIMEOUT_MS 200 - -void -meta_display_update_tile_preview (MetaDisplay *display, - gboolean delay) -{ - if (delay) - { - if (display->tile_preview_timeout_id > 0) - return; - - display->tile_preview_timeout_id = - g_timeout_add (TILE_PREVIEW_TIMEOUT_MS, - meta_display_update_tile_preview_timeout, - display); - g_source_set_name_by_id (display->tile_preview_timeout_id, - "[mutter] meta_display_update_tile_preview_timeout"); - } - else - { - g_clear_handle_id (&display->tile_preview_timeout_id, g_source_remove); - - meta_display_update_tile_preview_timeout ((gpointer)display); - } -} - -void -meta_display_hide_tile_preview (MetaDisplay *display) -{ - g_clear_handle_id (&display->tile_preview_timeout_id, g_source_remove); - - display->preview_tile_mode = META_TILE_NONE; - meta_compositor_hide_tile_preview (display->compositor); -} - -static MetaStartupSequence * -find_startup_sequence_by_wmclass (MetaDisplay *display, - MetaWindow *window) -{ - GSList *startup_sequences, *l; - - startup_sequences = - meta_startup_notification_get_sequences (display->startup_notification); - - for (l = startup_sequences; l; l = l->next) - { - MetaStartupSequence *sequence = l->data; - const char *wmclass; - - wmclass = meta_startup_sequence_get_wmclass (sequence); - - if (wmclass != NULL && - ((window->res_class && - strcmp (wmclass, window->res_class) == 0) || - (window->res_name && - strcmp (wmclass, window->res_name) == 0))) - return sequence; - } - - return NULL; -} - -/* Sets the initial_timestamp and initial_workspace properties - * of a window according to information given us by the - * startup-notification library. - * - * Returns TRUE if startup properties have been applied, and - * FALSE if they have not (for example, if they had already - * been applied.) - */ -gboolean -meta_display_apply_startup_properties (MetaDisplay *display, - MetaWindow *window) -{ - const char *startup_id; - MetaStartupSequence *sequence = NULL; - - /* Does the window have a startup ID stored? */ - startup_id = meta_window_get_startup_id (window); - - meta_topic (META_DEBUG_STARTUP, - "Applying startup props to %s id \"%s\"", - window->desc, - startup_id ? startup_id : "(none)"); - - if (!startup_id) - { - /* No startup ID stored for the window. Let's ask the - * startup-notification library whether there's anything - * stored for the resource name or resource class hints. - */ - sequence = find_startup_sequence_by_wmclass (display, window); - - if (sequence) - { - g_assert (window->startup_id == NULL); - window->startup_id = g_strdup (meta_startup_sequence_get_id (sequence)); - startup_id = window->startup_id; - - meta_topic (META_DEBUG_STARTUP, - "Ending legacy sequence %s due to window %s", - meta_startup_sequence_get_id (sequence), - window->desc); - - meta_startup_sequence_complete (sequence); - } - } - - /* Still no startup ID? Bail. */ - if (!startup_id) - return FALSE; - - /* We might get this far and not know the sequence ID (if the window - * already had a startup ID stored), so let's look for one if we don't - * already know it. - */ - if (sequence == NULL) - { - sequence = - meta_startup_notification_lookup_sequence (display->startup_notification, - startup_id); - } - - if (sequence != NULL) - { - gboolean changed_something = FALSE; - - meta_topic (META_DEBUG_STARTUP, - "Found startup sequence for window %s ID \"%s\"", - window->desc, startup_id); - - if (!window->initial_workspace_set) - { - int space = meta_startup_sequence_get_workspace (sequence); - if (space >= 0) - { - meta_topic (META_DEBUG_STARTUP, - "Setting initial window workspace to %d based on startup info", - space); - - window->initial_workspace_set = TRUE; - window->initial_workspace = space; - changed_something = TRUE; - } - } - - if (!window->initial_timestamp_set) - { - guint32 timestamp = meta_startup_sequence_get_timestamp (sequence); - meta_topic (META_DEBUG_STARTUP, - "Setting initial window timestamp to %u based on startup info", - timestamp); - - window->initial_timestamp_set = TRUE; - window->initial_timestamp = timestamp; - changed_something = TRUE; - } - - return changed_something; - } - else - { - meta_topic (META_DEBUG_STARTUP, - "Did not find startup sequence for window %s ID \"%s\"", - window->desc, startup_id); - } - - return FALSE; -} - -static gboolean -set_work_area_later_func (MetaDisplay *display) -{ - meta_topic (META_DEBUG_WORKAREA, - "Running work area hint computation function"); - - display->work_area_later = 0; - - g_signal_emit (display, display_signals[WORKAREAS_CHANGED], 0); - - return FALSE; -} - -void -meta_display_queue_workarea_recalc (MetaDisplay *display) -{ - /* Recompute work area later before redrawing */ - if (display->work_area_later == 0) - { - meta_topic (META_DEBUG_WORKAREA, - "Adding work area hint computation function"); - display->work_area_later = - meta_later_add (META_LATER_BEFORE_REDRAW, - (GSourceFunc) set_work_area_later_func, - display, - NULL); - } -} - -static gboolean -check_fullscreen_func (gpointer data) -{ - MetaDisplay *display = data; - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - GList *logical_monitors, *l; - MetaWindow *window; - GSList *fullscreen_monitors = NULL; - GSList *obscured_monitors = NULL; - gboolean in_fullscreen_changed = FALSE; - - display->check_fullscreen_later = 0; - - logical_monitors = - meta_monitor_manager_get_logical_monitors (monitor_manager); - - /* We consider a monitor in fullscreen if it contains a fullscreen window; - * however we make an exception for maximized windows above the fullscreen - * one, as in that case window+chrome fully obscure the fullscreen window. - */ - for (window = meta_stack_get_top (display->stack); - window; - window = meta_stack_get_below (display->stack, window, FALSE)) - { - gboolean covers_monitors = FALSE; - - if (window->hidden) - continue; - - if (window->fullscreen) - { - covers_monitors = TRUE; - } - else if (window->override_redirect) - { - /* We want to handle the case where an application is creating an - * override-redirect window the size of the screen (monitor) and treat - * it similarly to a fullscreen window, though it doesn't have fullscreen - * window management behavior. (Being O-R, it's not managed at all.) - */ - if (meta_window_is_monitor_sized (window)) - covers_monitors = TRUE; - } - else if (window->maximized_horizontally && - window->maximized_vertically) - { - MetaLogicalMonitor *logical_monitor; - - logical_monitor = meta_window_get_main_logical_monitor (window); - if (!g_slist_find (obscured_monitors, logical_monitor)) - obscured_monitors = g_slist_prepend (obscured_monitors, - logical_monitor); - } - - if (covers_monitors) - { - MetaRectangle window_rect; - - meta_window_get_frame_rect (window, &window_rect); - - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - - if (meta_rectangle_overlap (&window_rect, - &logical_monitor->rect) && - !g_slist_find (fullscreen_monitors, logical_monitor) && - !g_slist_find (obscured_monitors, logical_monitor)) - fullscreen_monitors = g_slist_prepend (fullscreen_monitors, - logical_monitor); - } - } - } - - g_slist_free (obscured_monitors); - - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - gboolean in_fullscreen; - - in_fullscreen = g_slist_find (fullscreen_monitors, - logical_monitor) != NULL; - if (in_fullscreen != logical_monitor->in_fullscreen) - { - logical_monitor->in_fullscreen = in_fullscreen; - in_fullscreen_changed = TRUE; - } - } - - g_slist_free (fullscreen_monitors); - - if (in_fullscreen_changed) - { - /* DOCK window stacking depends on the monitor's fullscreen - status so we need to trigger a re-layering. */ - MetaWindow *window = meta_stack_get_top (display->stack); - if (window) - meta_stack_update_layer (display->stack, window); - - g_signal_emit (display, display_signals[IN_FULLSCREEN_CHANGED], 0, NULL); - } - - return FALSE; -} - -void -meta_display_queue_check_fullscreen (MetaDisplay *display) -{ - if (!display->check_fullscreen_later) - display->check_fullscreen_later = meta_later_add (META_LATER_CHECK_FULLSCREEN, - check_fullscreen_func, - display, NULL); -} - -int -meta_display_get_monitor_index_for_rect (MetaDisplay *display, - MetaRectangle *rect) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaLogicalMonitor *logical_monitor; - - logical_monitor = - meta_monitor_manager_get_logical_monitor_from_rect (monitor_manager, rect); - if (!logical_monitor) - return -1; - - return logical_monitor->number; -} - -int -meta_display_get_monitor_neighbor_index (MetaDisplay *display, - int which_monitor, - MetaDisplayDirection direction) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaLogicalMonitor *logical_monitor; - MetaLogicalMonitor *neighbor; - - logical_monitor = - meta_monitor_manager_get_logical_monitor_from_number (monitor_manager, - which_monitor); - neighbor = meta_monitor_manager_get_logical_monitor_neighbor (monitor_manager, - logical_monitor, - direction); - return neighbor ? neighbor->number : -1; -} - -/** - * meta_display_get_current_monitor: - * @display: a #MetaDisplay - * - * Gets the index of the monitor that currently has the mouse pointer. - * - * Return value: a monitor index - */ -int -meta_display_get_current_monitor (MetaDisplay *display) -{ - MetaBackend *backend = meta_get_backend (); - MetaLogicalMonitor *logical_monitor; - - logical_monitor = meta_backend_get_current_logical_monitor (backend); - - /* Pretend its the first when there is no actual current monitor. */ - if (!logical_monitor) - return 0; - - return logical_monitor->number; -} - -/** - * meta_display_get_n_monitors: - * @display: a #MetaDisplay - * - * Gets the number of monitors that are joined together to form @display. - * - * Return value: the number of monitors - */ -int -meta_display_get_n_monitors (MetaDisplay *display) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - - g_return_val_if_fail (META_IS_DISPLAY (display), 0); - - return meta_monitor_manager_get_num_logical_monitors (monitor_manager); -} - -/** - * meta_display_get_primary_monitor: - * @display: a #MetaDisplay - * - * Gets the index of the primary monitor on this @display. - * - * Return value: a monitor index - */ -int -meta_display_get_primary_monitor (MetaDisplay *display) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaLogicalMonitor *logical_monitor; - - g_return_val_if_fail (META_IS_DISPLAY (display), 0); - - logical_monitor = - meta_monitor_manager_get_primary_logical_monitor (monitor_manager); - if (logical_monitor) - return logical_monitor->number; - else - return 0; -} - -/** - * meta_display_get_monitor_geometry: - * @display: a #MetaDisplay - * @monitor: the monitor number - * @geometry: (out): location to store the monitor geometry - * - * Stores the location and size of the indicated @monitor in @geometry. - */ -void -meta_display_get_monitor_geometry (MetaDisplay *display, - int monitor, - MetaRectangle *geometry) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaLogicalMonitor *logical_monitor; -#ifndef G_DISABLE_CHECKS - int n_logical_monitors = - meta_monitor_manager_get_num_logical_monitors (monitor_manager); -#endif - - g_return_if_fail (META_IS_DISPLAY (display)); - g_return_if_fail (monitor >= 0 && monitor < n_logical_monitors); - g_return_if_fail (geometry != NULL); - - logical_monitor = - meta_monitor_manager_get_logical_monitor_from_number (monitor_manager, - monitor); - *geometry = logical_monitor->rect; -} - -/** - * meta_display_get_monitor_scale: - * @display: a #MetaDisplay - * @monitor: the monitor number - * - * Gets the monitor scaling value for the given @monitor. - * - * Return value: the monitor scaling value - */ -float -meta_display_get_monitor_scale (MetaDisplay *display, - int monitor) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaLogicalMonitor *logical_monitor; -#ifndef G_DISABLE_CHECKS - int n_logical_monitors = - meta_monitor_manager_get_num_logical_monitors (monitor_manager); -#endif - - g_return_val_if_fail (META_IS_DISPLAY (display), 1.0f); - g_return_val_if_fail (monitor >= 0 && monitor < n_logical_monitors, 1.0f); - - logical_monitor = - meta_monitor_manager_get_logical_monitor_from_number (monitor_manager, - monitor); - return logical_monitor->scale; -} - -/** - * meta_display_get_monitor_in_fullscreen: - * @display: a #MetaDisplay - * @monitor: the monitor number - * - * Determines whether there is a fullscreen window obscuring the specified - * monitor. If there is a fullscreen window, the desktop environment will - * typically hide any controls that might obscure the fullscreen window. - * - * You can get notification when this changes by connecting to - * MetaDisplay::in-fullscreen-changed. - * - * Returns: %TRUE if there is a fullscreen window covering the specified monitor. - */ -gboolean -meta_display_get_monitor_in_fullscreen (MetaDisplay *display, - int monitor) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaLogicalMonitor *logical_monitor; -#ifndef G_DISABLE_CHECKS - int n_logical_monitors = - meta_monitor_manager_get_num_logical_monitors (monitor_manager); -#endif - - g_return_val_if_fail (META_IS_DISPLAY (display), FALSE); - g_return_val_if_fail (monitor >= 0 && - monitor < n_logical_monitors, FALSE); - - logical_monitor = - meta_monitor_manager_get_logical_monitor_from_number (monitor_manager, - monitor); - - /* We use -1 as a flag to mean "not known yet" for notification - purposes */ return logical_monitor->in_fullscreen == TRUE; -} - -MetaWindow * -meta_display_get_pointer_window (MetaDisplay *display, - MetaWindow *not_this_one) -{ - MetaWorkspaceManager *workspace_manager = display->workspace_manager; - MetaBackend *backend = meta_get_backend (); - MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); - MetaWindow *window; - graphene_point_t point; - - if (not_this_one) - meta_topic (META_DEBUG_FOCUS, - "Focusing mouse window excluding %s", not_this_one->desc); - - meta_cursor_tracker_get_pointer (cursor_tracker, &point, NULL); - - window = meta_stack_get_default_focus_window_at_point (display->stack, - workspace_manager->active_workspace, - not_this_one, - point.x, point.y); - - return window; -} - -void -meta_display_focus_default_window (MetaDisplay *display, - guint32 timestamp) -{ - MetaWorkspaceManager *workspace_manager = display->workspace_manager; - - meta_workspace_focus_default_window (workspace_manager->active_workspace, - NULL, - timestamp); -} - -/** - * meta_display_get_workspace_manager: - * @display: a #MetaDisplay - * - * Returns: (transfer none): The workspace manager of the display - */ -MetaWorkspaceManager * -meta_display_get_workspace_manager (MetaDisplay *display) -{ - return display->workspace_manager; -} - -MetaStartupNotification * -meta_display_get_startup_notification (MetaDisplay *display) -{ - return display->startup_notification; -} - -MetaWindow * -meta_display_get_window_from_id (MetaDisplay *display, - uint64_t window_id) -{ - g_autoptr (GSList) windows = NULL; - GSList *l; - - windows = meta_display_list_windows (display, META_LIST_DEFAULT); - for (l = windows; l; l = l->next) - { - MetaWindow *window = l->data; - - if (window->id == window_id) - return window; - } - - return NULL; -} - -uint64_t -meta_display_generate_window_id (MetaDisplay *display) -{ - static uint64_t base_window_id; - static uint64_t last_window_id; - - if (!base_window_id) - base_window_id = g_random_int () + 1; - - /* We can overflow here, that's fine */ - return (base_window_id + last_window_id++); -} - -/** - * meta_display_get_sound_player: - * @display: a #MetaDisplay - * - * Returns: (transfer none): The sound player of the display - */ -MetaSoundPlayer * -meta_display_get_sound_player (MetaDisplay *display) -{ - return display->sound_player; -} - -/** - * meta_display_get_selection: - * @display: a #MetaDisplay - * - * Returns: (transfer none): The selection manager of the display - */ -MetaSelection * -meta_display_get_selection (MetaDisplay *display) -{ - return display->selection; -} diff --git a/src/core/edge-resistance.c b/src/core/edge-resistance.c deleted file mode 100644 index 3e42936e7..000000000 --- a/src/core/edge-resistance.c +++ /dev/null @@ -1,1310 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Edge resistance for move/resize operations */ - -/* - * Copyright (C) 2005, 2006 Elijah Newren - * - * 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 . - */ - -#include "config.h" - -#include "core/edge-resistance.h" - -#include "core/boxes-private.h" -#include "core/display-private.h" -#include "core/meta-workspace-manager-private.h" -#include "core/workspace-private.h" - -/* A simple macro for whether a given window's edges are potentially - * relevant for resistance/snapping during a move/resize operation - */ -#define WINDOW_EDGES_RELEVANT(window, display) \ - meta_window_should_be_showing (window) && \ - window != display->grab_window && \ - window->type != META_WINDOW_DESKTOP && \ - window->type != META_WINDOW_MENU && \ - window->type != META_WINDOW_SPLASHSCREEN - -struct ResistanceDataForAnEdge -{ - gboolean timeout_setup; - guint timeout_id; - int timeout_edge_pos; - gboolean timeout_over; - GSourceFunc timeout_func; - MetaWindow *window; - int keyboard_buildup; -}; -typedef struct ResistanceDataForAnEdge ResistanceDataForAnEdge; - -struct MetaEdgeResistanceData -{ - GArray *left_edges; - GArray *right_edges; - GArray *top_edges; - GArray *bottom_edges; - - ResistanceDataForAnEdge left_data; - ResistanceDataForAnEdge right_data; - ResistanceDataForAnEdge top_data; - ResistanceDataForAnEdge bottom_data; -}; - -static void compute_resistance_and_snapping_edges (MetaDisplay *display); - -/* !WARNING!: this function can return invalid indices (namely, either -1 or - * edges->len); this is by design, but you need to remember this. - */ -static int -find_index_of_edge_near_position (const GArray *edges, - int position, - gboolean want_interval_min, - gboolean horizontal) -{ - /* This is basically like a binary search, except that we're trying to - * find a range instead of an exact value. So, if we have in our array - * Value: 3 27 316 316 316 505 522 800 1213 - * Index: 0 1 2 3 4 5 6 7 8 - * and we call this function with position=500 & want_interval_min=TRUE - * then we should get 5 (because 505 is the first value bigger than 500). - * If we call this function with position=805 and want_interval_min=FALSE - * then we should get 7 (because 800 is the last value smaller than 800). - * A couple more, to make things clear: - * position want_interval_min correct_answer - * 316 TRUE 2 - * 316 FALSE 4 - * 2 FALSE -1 - * 2000 TRUE 9 - */ - int low, high, mid; - int compare; - MetaEdge *edge; - - /* Initialize mid, edge, & compare in the off change that the array only - * has one element. - */ - mid = 0; - edge = g_array_index (edges, MetaEdge*, mid); - compare = horizontal ? edge->rect.x : edge->rect.y; - - /* Begin the search... */ - low = 0; - high = edges->len - 1; - while (low < high) - { - mid = low + (high - low)/2; - edge = g_array_index (edges, MetaEdge*, mid); - compare = horizontal ? edge->rect.x : edge->rect.y; - - if (compare == position) - break; - - if (compare > position) - high = mid - 1; - else - low = mid + 1; - } - - /* mid should now be _really_ close to the index we want, so we start - * linearly searching. However, note that we don't know if mid is less - * than or greater than what we need and it's possible that there are - * several equal values equal to what we were searching for and we ended - * up in the middle of them instead of at the end. So we may need to - * move mid multiple locations over. - */ - if (want_interval_min) - { - while (compare >= position && mid > 0) - { - mid--; - edge = g_array_index (edges, MetaEdge*, mid); - compare = horizontal ? edge->rect.x : edge->rect.y; - } - while (compare < position && mid < (int)edges->len - 1) - { - mid++; - edge = g_array_index (edges, MetaEdge*, mid); - compare = horizontal ? edge->rect.x : edge->rect.y; - } - - /* Special case for no values in array big enough */ - if (compare < position) - return edges->len; - - /* Return the found value */ - return mid; - } - else - { - while (compare <= position && mid < (int)edges->len - 1) - { - mid++; - edge = g_array_index (edges, MetaEdge*, mid); - compare = horizontal ? edge->rect.x : edge->rect.y; - } - while (compare > position && mid > 0) - { - mid--; - edge = g_array_index (edges, MetaEdge*, mid); - compare = horizontal ? edge->rect.x : edge->rect.y; - } - - /* Special case for no values in array small enough */ - if (compare > position) - return -1; - - /* Return the found value */ - return mid; - } -} - -static gboolean -points_on_same_side (int ref, int pt1, int pt2) -{ - return (pt1 - ref) * (pt2 - ref) > 0; -} - -static int -find_nearest_position (const GArray *edges, - int position, - int old_position, - const MetaRectangle *new_rect, - gboolean horizontal, - gboolean only_forward) -{ - /* This is basically just a binary search except that we're looking - * for the value closest to position, rather than finding that - * actual value. Also, we ignore any edges that aren't relevant - * given the horizontal/vertical position of new_rect. - */ - int low, high, mid; - int compare; - MetaEdge *edge; - int best, best_dist, i; - gboolean edges_align; - - /* Initialize mid, edge, & compare in the off change that the array only - * has one element. - */ - mid = 0; - edge = g_array_index (edges, MetaEdge*, mid); - compare = horizontal ? edge->rect.x : edge->rect.y; - - /* Begin the search... */ - low = 0; - high = edges->len - 1; - while (low < high) - { - mid = low + (high - low)/2; - edge = g_array_index (edges, MetaEdge*, mid); - compare = horizontal ? edge->rect.x : edge->rect.y; - - if (compare == position) - break; - - if (compare > position) - high = mid - 1; - else - low = mid + 1; - } - - /* mid should now be _really_ close to the index we want, so we - * start searching nearby for something that overlaps and is closer - * than the original position. - */ - best = old_position; - best_dist = INT_MAX; - - /* Start the search at mid */ - edge = g_array_index (edges, MetaEdge*, mid); - compare = horizontal ? edge->rect.x : edge->rect.y; - edges_align = meta_rectangle_edge_aligns (new_rect, edge); - if (edges_align && - (!only_forward || !points_on_same_side (position, compare, old_position))) - { - int dist = ABS (compare - position); - if (dist < best_dist) - { - best = compare; - best_dist = dist; - } - } - - /* Now start searching higher than mid */ - for (i = mid + 1; i < (int)edges->len; i++) - { - edge = g_array_index (edges, MetaEdge*, i); - compare = horizontal ? edge->rect.x : edge->rect.y; - - edges_align = horizontal ? - meta_rectangle_vert_overlap (&edge->rect, new_rect) : - meta_rectangle_horiz_overlap (&edge->rect, new_rect); - - if (edges_align && - (!only_forward || - !points_on_same_side (position, compare, old_position))) - { - int dist = ABS (compare - position); - if (dist < best_dist) - { - best = compare; - best_dist = dist; - } - break; - } - } - - /* Now start searching lower than mid */ - for (i = mid-1; i >= 0; i--) - { - edge = g_array_index (edges, MetaEdge*, i); - compare = horizontal ? edge->rect.x : edge->rect.y; - - edges_align = horizontal ? - meta_rectangle_vert_overlap (&edge->rect, new_rect) : - meta_rectangle_horiz_overlap (&edge->rect, new_rect); - - if (edges_align && - (!only_forward || - !points_on_same_side (position, compare, old_position))) - { - int dist = ABS (compare - position); - if (dist < best_dist) - { - best = compare; - best_dist = dist; - } - break; - } - } - - /* Return the best one found */ - return best; -} - -static gboolean -movement_towards_edge (MetaSide side, int increment) -{ - switch (side) - { - case META_SIDE_LEFT: - case META_SIDE_TOP: - return increment < 0; - case META_SIDE_RIGHT: - case META_SIDE_BOTTOM: - return increment > 0; - default: - g_assert_not_reached (); - return FALSE; - } -} - -static gboolean -edge_resistance_timeout (gpointer data) -{ - ResistanceDataForAnEdge *resistance_data = data; - - resistance_data->timeout_over = TRUE; - resistance_data->timeout_id = 0; - (*resistance_data->timeout_func)(resistance_data->window); - - return FALSE; -} - -static int -apply_edge_resistance (MetaWindow *window, - int old_pos, - int new_pos, - const MetaRectangle *old_rect, - const MetaRectangle *new_rect, - GArray *edges, - ResistanceDataForAnEdge *resistance_data, - GSourceFunc timeout_func, - gboolean xdir, - gboolean include_windows, - gboolean keyboard_op) -{ - int i, begin, end; - int last_edge; - gboolean increasing = new_pos > old_pos; - int increment = increasing ? 1 : -1; - - const int PIXEL_DISTANCE_THRESHOLD_TOWARDS_WINDOW = 16; - const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_WINDOW = 0; - const int PIXEL_DISTANCE_THRESHOLD_TOWARDS_MONITOR = 32; - const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_MONITOR = 0; - const int PIXEL_DISTANCE_THRESHOLD_TOWARDS_SCREEN = 32; - const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_SCREEN = 0; - const int TIMEOUT_RESISTANCE_LENGTH_MS_WINDOW = 0; - const int TIMEOUT_RESISTANCE_LENGTH_MS_MONITOR = 0; - const int TIMEOUT_RESISTANCE_LENGTH_MS_SCREEN = 0; - - /* Quit if no movement was specified */ - if (old_pos == new_pos) - return new_pos; - - /* Remove the old timeout if it's no longer relevant */ - if (resistance_data->timeout_setup && - ((resistance_data->timeout_edge_pos > old_pos && - resistance_data->timeout_edge_pos > new_pos) || - (resistance_data->timeout_edge_pos < old_pos && - resistance_data->timeout_edge_pos < new_pos))) - { - resistance_data->timeout_setup = FALSE; - g_clear_handle_id (&resistance_data->timeout_id, g_source_remove); - } - - /* Get the range of indices in the edge array that we move past/to. */ - begin = find_index_of_edge_near_position (edges, old_pos, increasing, xdir); - end = find_index_of_edge_near_position (edges, new_pos, !increasing, xdir); - - /* begin and end can be outside the array index, if the window is partially - * off the screen - */ - last_edge = edges->len - 1; - begin = CLAMP (begin, 0, last_edge); - end = CLAMP (end, 0, last_edge); - - /* Loop over all these edges we're moving past/to. */ - i = begin; - while ((increasing && i <= end) || - (!increasing && i >= end)) - { - gboolean edges_align; - MetaEdge *edge = g_array_index (edges, MetaEdge*, i); - int compare = xdir ? edge->rect.x : edge->rect.y; - - /* Find out if this edge is relevant */ - edges_align = meta_rectangle_edge_aligns (new_rect, edge) || - meta_rectangle_edge_aligns (old_rect, edge); - - /* Nothing to do unless the edges align */ - if (!edges_align) - { - /* Go to the next edge in the range */ - i += increment; - continue; - } - - /* Rest is easier to read if we split on keyboard vs. mouse op */ - if (keyboard_op) - { - if ((old_pos < compare && compare < new_pos) || - (old_pos > compare && compare > new_pos)) - return compare; - } - else /* mouse op */ - { - int threshold; - - /* TIMEOUT RESISTANCE: If the edge is relevant and we're moving - * towards it, then we may want to have some kind of time delay - * before the user can move past this edge. - */ - if (movement_towards_edge (edge->side_type, increment)) - { - /* First, determine the length of time for the resistance */ - int timeout_length_ms = 0; - switch (edge->edge_type) - { - case META_EDGE_WINDOW: - if (include_windows) - timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_WINDOW; - break; - case META_EDGE_MONITOR: - timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_MONITOR; - break; - case META_EDGE_SCREEN: - timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_SCREEN; - break; - } - - if (!resistance_data->timeout_setup && - timeout_length_ms != 0) - { - resistance_data->timeout_id = - g_timeout_add (timeout_length_ms, - edge_resistance_timeout, - resistance_data); - g_source_set_name_by_id (resistance_data->timeout_id, - "[mutter] edge_resistance_timeout"); - resistance_data->timeout_setup = TRUE; - resistance_data->timeout_edge_pos = compare; - resistance_data->timeout_over = FALSE; - resistance_data->timeout_func = timeout_func; - resistance_data->window = window; - } - if (!resistance_data->timeout_over && - timeout_length_ms != 0) - return compare; - } - - /* PIXEL DISTANCE MOUSE RESISTANCE: If the edge matters and the - * user hasn't moved at least threshold pixels past this edge, - * stop movement at this edge. (Note that this is different from - * keyboard resistance precisely because keyboard move ops are - * relative to previous positions, whereas mouse move ops are - * relative to differences in mouse position and mouse position - * is an absolute quantity rather than a relative quantity) - */ - - /* First, determine the threshold */ - threshold = 0; - switch (edge->edge_type) - { - case META_EDGE_WINDOW: - if (!include_windows) - break; - if (movement_towards_edge (edge->side_type, increment)) - threshold = PIXEL_DISTANCE_THRESHOLD_TOWARDS_WINDOW; - else - threshold = PIXEL_DISTANCE_THRESHOLD_AWAYFROM_WINDOW; - break; - case META_EDGE_MONITOR: - if (movement_towards_edge (edge->side_type, increment)) - threshold = PIXEL_DISTANCE_THRESHOLD_TOWARDS_MONITOR; - else - threshold = PIXEL_DISTANCE_THRESHOLD_AWAYFROM_MONITOR; - break; - case META_EDGE_SCREEN: - if (movement_towards_edge (edge->side_type, increment)) - threshold = PIXEL_DISTANCE_THRESHOLD_TOWARDS_SCREEN; - else - threshold = PIXEL_DISTANCE_THRESHOLD_AWAYFROM_SCREEN; - break; - } - - if (ABS (compare - new_pos) < threshold) - return compare; - } - - /* Go to the next edge in the range */ - i += increment; - } - - return new_pos; -} - -static int -apply_edge_snapping (int old_pos, - int new_pos, - const MetaRectangle *new_rect, - GArray *edges, - gboolean xdir, - gboolean keyboard_op) -{ - int snap_to; - - if (old_pos == new_pos) - return new_pos; - - snap_to = find_nearest_position (edges, - new_pos, - old_pos, - new_rect, - xdir, - keyboard_op); - - /* If mouse snap-moving, the user could easily accidentally move just a - * couple pixels in a direction they didn't mean to move; so ignore snap - * movement in those cases unless it's only a small number of pixels - * anyway. - */ - if (!keyboard_op && - ABS (snap_to - old_pos) >= 8 && - ABS (new_pos - old_pos) < 8) - return old_pos; - else - /* Otherwise, return the snapping position found */ - return snap_to; -} - -/* This function takes the position (including any frame) of the window and - * a proposed new position (ignoring edge resistance/snapping), and then - * applies edge resistance to EACH edge (separately) updating new_outer. - * It returns true if new_outer is modified, false otherwise. - * - * display->grab_edge_resistance_data MUST already be setup or calling this - * function will cause a crash. - */ -static gboolean -apply_edge_resistance_to_each_side (MetaDisplay *display, - MetaWindow *window, - const MetaRectangle *old_outer, - MetaRectangle *new_outer, - GSourceFunc timeout_func, - MetaEdgeResistanceFlags flags, - gboolean is_resize) -{ - MetaEdgeResistanceData *edge_data; - MetaRectangle modified_rect; - gboolean modified; - int new_left, new_right, new_top, new_bottom; - gboolean auto_snap, keyboard_op; - - auto_snap = flags & META_EDGE_RESISTANCE_SNAP; - keyboard_op = flags & META_EDGE_RESISTANCE_KEYBOARD_OP; - - if (display->grab_edge_resistance_data == NULL) - compute_resistance_and_snapping_edges (display); - - edge_data = display->grab_edge_resistance_data; - - if (auto_snap && !META_WINDOW_TILED_SIDE_BY_SIDE (window)) - { - /* Do the auto snapping instead of normal edge resistance; in all - * cases, we allow snapping to opposite kinds of edges (e.g. left - * sides of windows to both left and right edges. - */ - - new_left = apply_edge_snapping (BOX_LEFT (*old_outer), - BOX_LEFT (*new_outer), - new_outer, - edge_data->left_edges, - TRUE, - keyboard_op); - - new_right = apply_edge_snapping (BOX_RIGHT (*old_outer), - BOX_RIGHT (*new_outer), - new_outer, - edge_data->right_edges, - TRUE, - keyboard_op); - - new_top = apply_edge_snapping (BOX_TOP (*old_outer), - BOX_TOP (*new_outer), - new_outer, - edge_data->top_edges, - FALSE, - keyboard_op); - - new_bottom = apply_edge_snapping (BOX_BOTTOM (*old_outer), - BOX_BOTTOM (*new_outer), - new_outer, - edge_data->bottom_edges, - FALSE, - keyboard_op); - } - else if (auto_snap && META_WINDOW_TILED_SIDE_BY_SIDE (window)) - { - MetaRectangle workarea; - guint i; - - const gfloat tile_edges[] = - { - 1./4., - 1./3., - 1./2., - 2./3., - 3./4., - }; - - meta_window_get_work_area_current_monitor (window, &workarea); - - new_left = new_outer->x; - new_top = new_outer->y; - new_right = new_outer->x + new_outer->width; - new_bottom = new_outer->y + new_outer->height; - - /* When snapping tiled windows, we don't really care about the - * x and y position, only about the width and height. Also, it - * is special-cased (instead of relying on edge_data) because - * we don't really care for other windows when calculating the - * snapping points of tiled windows - we only care about the - * work area and the target position. - */ - for (i = 0; i < G_N_ELEMENTS (tile_edges); i++) - { - guint horizontal_point = workarea.x + floor (workarea.width * tile_edges[i]); - - if (ABS (horizontal_point - new_left) < 16) - { - new_left = horizontal_point; - new_right = workarea.x + workarea.width; - } - else if (ABS (horizontal_point - new_right) < 16) - { - new_left = workarea.x; - new_right = horizontal_point; - } - } - } - else - { - gboolean include_windows = flags & META_EDGE_RESISTANCE_WINDOWS; - - /* Disable edge resistance for resizes when windows have size - * increment hints; see #346782. For all other cases, apply - * them. - */ - if (!is_resize || window->size_hints.width_inc == 1) - { - /* Now, apply the normal horizontal edge resistance */ - new_left = apply_edge_resistance (window, - BOX_LEFT (*old_outer), - BOX_LEFT (*new_outer), - old_outer, - new_outer, - edge_data->left_edges, - &edge_data->left_data, - timeout_func, - TRUE, - include_windows, - keyboard_op); - new_right = apply_edge_resistance (window, - BOX_RIGHT (*old_outer), - BOX_RIGHT (*new_outer), - old_outer, - new_outer, - edge_data->right_edges, - &edge_data->right_data, - timeout_func, - TRUE, - include_windows, - keyboard_op); - } - else - { - new_left = new_outer->x; - new_right = new_outer->x + new_outer->width; - } - /* Same for vertical resizes... */ - if (!is_resize || window->size_hints.height_inc == 1) - { - new_top = apply_edge_resistance (window, - BOX_TOP (*old_outer), - BOX_TOP (*new_outer), - old_outer, - new_outer, - edge_data->top_edges, - &edge_data->top_data, - timeout_func, - FALSE, - include_windows, - keyboard_op); - new_bottom = apply_edge_resistance (window, - BOX_BOTTOM (*old_outer), - BOX_BOTTOM (*new_outer), - old_outer, - new_outer, - edge_data->bottom_edges, - &edge_data->bottom_data, - timeout_func, - FALSE, - include_windows, - keyboard_op); - } - else - { - new_top = new_outer->y; - new_bottom = new_outer->y + new_outer->height; - } - } - - /* Determine whether anything changed, and save the changes */ - modified_rect = meta_rect (new_left, - new_top, - new_right - new_left, - new_bottom - new_top); - modified = !meta_rectangle_equal (new_outer, &modified_rect); - *new_outer = modified_rect; - return modified; -} - -void -meta_display_cleanup_edges (MetaDisplay *display) -{ - guint i,j; - MetaEdgeResistanceData *edge_data = display->grab_edge_resistance_data; - GHashTable *edges_to_be_freed; - - if (edge_data == NULL) /* Not currently cached */ - return; - - /* We first need to clean out any window edges */ - edges_to_be_freed = g_hash_table_new_full (g_direct_hash, g_direct_equal, - g_free, NULL); - for (i = 0; i < 4; i++) - { - GArray *tmp = NULL; - MetaSide side; - switch (i) - { - case 0: - tmp = edge_data->left_edges; - side = META_SIDE_LEFT; - break; - case 1: - tmp = edge_data->right_edges; - side = META_SIDE_RIGHT; - break; - case 2: - tmp = edge_data->top_edges; - side = META_SIDE_TOP; - break; - case 3: - tmp = edge_data->bottom_edges; - side = META_SIDE_BOTTOM; - break; - default: - g_assert_not_reached (); - } - - for (j = 0; j < tmp->len; j++) - { - MetaEdge *edge = g_array_index (tmp, MetaEdge*, j); - if (edge->edge_type == META_EDGE_WINDOW && - edge->side_type == side) - { - /* The same edge will appear in two arrays, and we can't free - * it yet we still need to compare edge->side_type for the other - * array that it is in. So store it in a hash table for later - * freeing. Could also do this in a simple linked list. - */ - g_hash_table_insert (edges_to_be_freed, edge, edge); - } - } - } - - /* Now free all the window edges (the key destroy function is g_free) */ - g_hash_table_destroy (edges_to_be_freed); - - /* Now free the arrays and data */ - g_array_free (edge_data->left_edges, TRUE); - g_array_free (edge_data->right_edges, TRUE); - g_array_free (edge_data->top_edges, TRUE); - g_array_free (edge_data->bottom_edges, TRUE); - edge_data->left_edges = NULL; - edge_data->right_edges = NULL; - edge_data->top_edges = NULL; - edge_data->bottom_edges = NULL; - - /* Cleanup the timeouts */ - if (edge_data->left_data.timeout_setup) - g_clear_handle_id (&edge_data->left_data.timeout_id, g_source_remove); - if (edge_data->right_data.timeout_setup) - g_clear_handle_id (&edge_data->right_data.timeout_id, g_source_remove); - if (edge_data->top_data.timeout_setup) - g_clear_handle_id (&edge_data->top_data.timeout_id, g_source_remove); - if (edge_data->bottom_data.timeout_setup) - g_clear_handle_id (&edge_data->bottom_data.timeout_id, g_source_remove); - - g_free (display->grab_edge_resistance_data); - display->grab_edge_resistance_data = NULL; -} - -static int -stupid_sort_requiring_extra_pointer_dereference (gconstpointer a, - gconstpointer b) -{ - const MetaEdge * const *a_edge = a; - const MetaEdge * const *b_edge = b; - return meta_rectangle_edge_cmp_ignore_type (*a_edge, *b_edge); -} - -static void -cache_edges (MetaDisplay *display, - GList *window_edges, - GList *monitor_edges, - GList *screen_edges) -{ - MetaEdgeResistanceData *edge_data; - GList *tmp; - int num_left, num_right, num_top, num_bottom; - int i; - - /* - * 0th: Print debugging information to the log about the edges - */ -#ifdef WITH_VERBOSE_MODE - if (meta_is_verbose()) - { - int max_edges = MAX (MAX( g_list_length (window_edges), - g_list_length (monitor_edges)), - g_list_length (screen_edges)); - char big_buffer[(EDGE_LENGTH+2)*max_edges]; - - meta_rectangle_edge_list_to_string (window_edges, ", ", big_buffer); - meta_topic (META_DEBUG_EDGE_RESISTANCE, - "Window edges for resistance : %s", big_buffer); - - meta_rectangle_edge_list_to_string (monitor_edges, ", ", big_buffer); - meta_topic (META_DEBUG_EDGE_RESISTANCE, - "Monitor edges for resistance: %s", big_buffer); - - meta_rectangle_edge_list_to_string (screen_edges, ", ", big_buffer); - meta_topic (META_DEBUG_EDGE_RESISTANCE, - "Screen edges for resistance : %s", big_buffer); - } -#endif - - /* - * 1st: Get the total number of each kind of edge - */ - num_left = num_right = num_top = num_bottom = 0; - for (i = 0; i < 3; i++) - { - tmp = NULL; - switch (i) - { - case 0: - tmp = window_edges; - break; - case 1: - tmp = monitor_edges; - break; - case 2: - tmp = screen_edges; - break; - default: - g_assert_not_reached (); - } - - while (tmp) - { - MetaEdge *edge = tmp->data; - switch (edge->side_type) - { - case META_SIDE_LEFT: - num_left++; - break; - case META_SIDE_RIGHT: - num_right++; - break; - case META_SIDE_TOP: - num_top++; - break; - case META_SIDE_BOTTOM: - num_bottom++; - break; - default: - g_assert_not_reached (); - } - tmp = tmp->next; - } - } - - /* - * 2nd: Allocate the edges - */ - g_assert (display->grab_edge_resistance_data == NULL); - display->grab_edge_resistance_data = g_new0 (MetaEdgeResistanceData, 1); - edge_data = display->grab_edge_resistance_data; - edge_data->left_edges = g_array_sized_new (FALSE, - FALSE, - sizeof(MetaEdge*), - num_left + num_right); - edge_data->right_edges = g_array_sized_new (FALSE, - FALSE, - sizeof(MetaEdge*), - num_left + num_right); - edge_data->top_edges = g_array_sized_new (FALSE, - FALSE, - sizeof(MetaEdge*), - num_top + num_bottom); - edge_data->bottom_edges = g_array_sized_new (FALSE, - FALSE, - sizeof(MetaEdge*), - num_top + num_bottom); - - /* - * 3rd: Add the edges to the arrays - */ - for (i = 0; i < 3; i++) - { - tmp = NULL; - switch (i) - { - case 0: - tmp = window_edges; - break; - case 1: - tmp = monitor_edges; - break; - case 2: - tmp = screen_edges; - break; - default: - g_assert_not_reached (); - } - - while (tmp) - { - MetaEdge *edge = tmp->data; - switch (edge->side_type) - { - case META_SIDE_LEFT: - case META_SIDE_RIGHT: - g_array_append_val (edge_data->left_edges, edge); - g_array_append_val (edge_data->right_edges, edge); - break; - case META_SIDE_TOP: - case META_SIDE_BOTTOM: - g_array_append_val (edge_data->top_edges, edge); - g_array_append_val (edge_data->bottom_edges, edge); - break; - default: - g_assert_not_reached (); - } - tmp = tmp->next; - } - } - - /* - * 4th: Sort the arrays (FIXME: This is kinda dumb since the arrays were - * individually sorted earlier and we could have done this faster and - * avoided this sort by sticking them into the array with some simple - * merging of the lists). - */ - g_array_sort (display->grab_edge_resistance_data->left_edges, - stupid_sort_requiring_extra_pointer_dereference); - g_array_sort (display->grab_edge_resistance_data->right_edges, - stupid_sort_requiring_extra_pointer_dereference); - g_array_sort (display->grab_edge_resistance_data->top_edges, - stupid_sort_requiring_extra_pointer_dereference); - g_array_sort (display->grab_edge_resistance_data->bottom_edges, - stupid_sort_requiring_extra_pointer_dereference); -} - -static void -initialize_grab_edge_resistance_data (MetaDisplay *display) -{ - MetaEdgeResistanceData *edge_data = display->grab_edge_resistance_data; - - edge_data->left_data.timeout_setup = FALSE; - edge_data->right_data.timeout_setup = FALSE; - edge_data->top_data.timeout_setup = FALSE; - edge_data->bottom_data.timeout_setup = FALSE; - - edge_data->left_data.keyboard_buildup = 0; - edge_data->right_data.keyboard_buildup = 0; - edge_data->top_data.keyboard_buildup = 0; - edge_data->bottom_data.keyboard_buildup = 0; -} - -static void -compute_resistance_and_snapping_edges (MetaDisplay *display) -{ - GList *stacked_windows; - GList *cur_window_iter; - GList *edges; - /* Lists of window positions (rects) and their relative stacking positions */ - int stack_position; - GSList *obscuring_windows, *window_stacking; - /* The portions of the above lists that still remain at the stacking position - * in the layer that we are working on - */ - GSList *rem_windows, *rem_win_stacking; - MetaWorkspaceManager *workspace_manager = display->workspace_manager; - - g_assert (display->grab_window != NULL); - meta_topic (META_DEBUG_WINDOW_OPS, - "Computing edges to resist-movement or snap-to for %s.", - display->grab_window->desc); - - /* - * 1st: Get the list of relevant windows, from bottom to top - */ - stacked_windows = - meta_stack_list_windows (display->stack, - workspace_manager->active_workspace); - - /* - * 2nd: we need to separate that stacked list into a list of windows that - * can obscure other edges. To make sure we only have windows obscuring - * those below it instead of going both ways, we also need to keep a - * counter list. Messy, I know. - */ - obscuring_windows = window_stacking = NULL; - cur_window_iter = stacked_windows; - stack_position = 0; - while (cur_window_iter != NULL) - { - MetaWindow *cur_window = cur_window_iter->data; - if (WINDOW_EDGES_RELEVANT (cur_window, display)) - { - MetaRectangle *new_rect; - new_rect = g_new (MetaRectangle, 1); - meta_window_get_frame_rect (cur_window, new_rect); - obscuring_windows = g_slist_prepend (obscuring_windows, new_rect); - window_stacking = - g_slist_prepend (window_stacking, GINT_TO_POINTER (stack_position)); - } - - stack_position++; - cur_window_iter = cur_window_iter->next; - } - /* Put 'em in bottom to top order */ - rem_windows = obscuring_windows = g_slist_reverse (obscuring_windows); - rem_win_stacking = window_stacking = g_slist_reverse (window_stacking); - - /* - * 3rd: loop over the windows again, this time getting the edges from - * them and removing intersections with the relevant obscuring_windows & - * obscuring_docks. - */ - edges = NULL; - stack_position = 0; - cur_window_iter = stacked_windows; - while (cur_window_iter != NULL) - { - MetaRectangle cur_rect; - MetaWindow *cur_window = cur_window_iter->data; - meta_window_get_frame_rect (cur_window, &cur_rect); - - /* Check if we want to use this window's edges for edge - * resistance (note that dock edges are considered screen edges - * which are handled separately - */ - if (WINDOW_EDGES_RELEVANT (cur_window, display) && - cur_window->type != META_WINDOW_DOCK) - { - GList *new_edges; - MetaEdge *new_edge; - MetaRectangle display_rect = { 0 }; - MetaRectangle reduced; - - meta_display_get_size (display, - &display_rect.width, &display_rect.height); - - /* We don't care about snapping to any portion of the window that - * is offscreen (we also don't care about parts of edges covered - * by other windows or DOCKS, but that's handled below). - */ - meta_rectangle_intersect (&cur_rect, - &display_rect, - &reduced); - - new_edges = NULL; - - /* Left side of this window is resistance for the right edge of - * the window being moved. - */ - new_edge = g_new (MetaEdge, 1); - new_edge->rect = reduced; - new_edge->rect.width = 0; - new_edge->side_type = META_SIDE_RIGHT; - new_edge->edge_type = META_EDGE_WINDOW; - new_edges = g_list_prepend (new_edges, new_edge); - - /* Right side of this window is resistance for the left edge of - * the window being moved. - */ - new_edge = g_new (MetaEdge, 1); - new_edge->rect = reduced; - new_edge->rect.x += new_edge->rect.width; - new_edge->rect.width = 0; - new_edge->side_type = META_SIDE_LEFT; - new_edge->edge_type = META_EDGE_WINDOW; - new_edges = g_list_prepend (new_edges, new_edge); - - /* Top side of this window is resistance for the bottom edge of - * the window being moved. - */ - new_edge = g_new (MetaEdge, 1); - new_edge->rect = reduced; - new_edge->rect.height = 0; - new_edge->side_type = META_SIDE_BOTTOM; - new_edge->edge_type = META_EDGE_WINDOW; - new_edges = g_list_prepend (new_edges, new_edge); - - /* Top side of this window is resistance for the bottom edge of - * the window being moved. - */ - new_edge = g_new (MetaEdge, 1); - new_edge->rect = reduced; - new_edge->rect.y += new_edge->rect.height; - new_edge->rect.height = 0; - new_edge->side_type = META_SIDE_TOP; - new_edge->edge_type = META_EDGE_WINDOW; - new_edges = g_list_prepend (new_edges, new_edge); - - /* Update the remaining windows to only those at a higher - * stacking position than this one. - */ - while (rem_win_stacking && - stack_position >= GPOINTER_TO_INT (rem_win_stacking->data)) - { - rem_windows = rem_windows->next; - rem_win_stacking = rem_win_stacking->next; - } - - /* Remove edge portions overlapped by rem_windows and rem_docks */ - new_edges = - meta_rectangle_remove_intersections_with_boxes_from_edges ( - new_edges, - rem_windows); - - /* Save the new edges */ - edges = g_list_concat (new_edges, edges); - } - - stack_position++; - cur_window_iter = cur_window_iter->next; - } - - /* - * 4th: Free the extra memory not needed and sort the list - */ - g_list_free (stacked_windows); - /* Free the memory used by the obscuring windows/docks lists */ - g_slist_free (window_stacking); - g_slist_free_full (obscuring_windows, g_free); - - /* Sort the list. FIXME: Should I bother with this sorting? I just - * sort again later in cache_edges() anyway... - */ - edges = g_list_sort (edges, meta_rectangle_edge_cmp); - - /* - * 5th: Cache the combination of these edges with the onscreen and - * monitor edges in an array for quick access. Free the edges since - * they've been cached elsewhere. - */ - cache_edges (display, - edges, - workspace_manager->active_workspace->monitor_edges, - workspace_manager->active_workspace->screen_edges); - g_list_free (edges); - - /* - * 6th: Initialize the resistance timeouts and buildups - */ - initialize_grab_edge_resistance_data (display); -} - -void -meta_window_edge_resistance_for_move (MetaWindow *window, - int *new_x, - int *new_y, - GSourceFunc timeout_func, - MetaEdgeResistanceFlags flags) -{ - MetaRectangle old_outer, proposed_outer, new_outer; - MetaEdgeResistanceFlags saved_flags; - gboolean is_resize, is_keyboard_op, snap; - - meta_window_get_frame_rect (window, &old_outer); - - proposed_outer = old_outer; - proposed_outer.x = *new_x; - proposed_outer.y = *new_y; - new_outer = proposed_outer; - - snap = flags & META_EDGE_RESISTANCE_SNAP; - is_keyboard_op = flags & META_EDGE_RESISTANCE_KEYBOARD_OP; - saved_flags = flags & ~META_EDGE_RESISTANCE_KEYBOARD_OP; - - window->display->grab_last_edge_resistance_flags = saved_flags; - is_resize = FALSE; - if (apply_edge_resistance_to_each_side (window->display, - window, - &old_outer, - &new_outer, - timeout_func, - flags, - is_resize)) - { - /* apply_edge_resistance_to_each_side independently applies - * resistance to both the right and left edges of new_outer as both - * could meet areas of resistance. But we don't want a resize, so we - * just have both edges move according to the stricter of the - * resistances. Same thing goes for top & bottom edges. - */ - MetaRectangle *reference; - int left_change, right_change, smaller_x_change; - int top_change, bottom_change, smaller_y_change; - - if (snap && !is_keyboard_op) - reference = &proposed_outer; - else - reference = &old_outer; - - left_change = BOX_LEFT (new_outer) - BOX_LEFT (*reference); - right_change = BOX_RIGHT (new_outer) - BOX_RIGHT (*reference); - if ( snap && is_keyboard_op && left_change == 0) - smaller_x_change = right_change; - else if (snap && is_keyboard_op && right_change == 0) - smaller_x_change = left_change; - else if (ABS (left_change) < ABS (right_change)) - smaller_x_change = left_change; - else - smaller_x_change = right_change; - - top_change = BOX_TOP (new_outer) - BOX_TOP (*reference); - bottom_change = BOX_BOTTOM (new_outer) - BOX_BOTTOM (*reference); - if ( snap && is_keyboard_op && top_change == 0) - smaller_y_change = bottom_change; - else if (snap && is_keyboard_op && bottom_change == 0) - smaller_y_change = top_change; - else if (ABS (top_change) < ABS (bottom_change)) - smaller_y_change = top_change; - else - smaller_y_change = bottom_change; - - *new_x = old_outer.x + smaller_x_change + - (BOX_LEFT (*reference) - BOX_LEFT (old_outer)); - *new_y = old_outer.y + smaller_y_change + - (BOX_TOP (*reference) - BOX_TOP (old_outer)); - - meta_topic (META_DEBUG_EDGE_RESISTANCE, - "outer x & y move-to coordinate changed from %d,%d to %d,%d", - proposed_outer.x, proposed_outer.y, - *new_x, *new_y); - } -} - -void -meta_window_edge_resistance_for_resize (MetaWindow *window, - int *new_width, - int *new_height, - MetaGravity gravity, - GSourceFunc timeout_func, - MetaEdgeResistanceFlags flags) -{ - MetaRectangle old_outer, new_outer; - MetaEdgeResistanceFlags saved_flags; - int proposed_outer_width, proposed_outer_height; - - meta_window_get_frame_rect (window, &old_outer); - proposed_outer_width = *new_width; - proposed_outer_height = *new_height; - meta_rectangle_resize_with_gravity (&old_outer, - &new_outer, - gravity, - proposed_outer_width, - proposed_outer_height); - - saved_flags = flags & ~META_EDGE_RESISTANCE_KEYBOARD_OP; - window->display->grab_last_edge_resistance_flags = saved_flags; - - if (apply_edge_resistance_to_each_side (window->display, - window, - &old_outer, - &new_outer, - timeout_func, - flags, - TRUE)) - { - *new_width = new_outer.width; - *new_height = new_outer.height; - - meta_topic (META_DEBUG_EDGE_RESISTANCE, - "outer width & height got changed from %d,%d to %d,%d", - proposed_outer_width, proposed_outer_height, - new_outer.width, new_outer.height); - } -} diff --git a/src/core/edge-resistance.h b/src/core/edge-resistance.h deleted file mode 100644 index 4eb6abdca..000000000 --- a/src/core/edge-resistance.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Edge resistance for move/resize operations */ - -/* - * Copyright (C) 2005 Elijah Newren - * - * 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 . - */ - -#ifndef META_EDGE_RESISTANCE_H -#define META_EDGE_RESISTANCE_H - -#include "core/window-private.h" - -void meta_window_edge_resistance_for_move (MetaWindow *window, - int *new_x, - int *new_y, - GSourceFunc timeout_func, - MetaEdgeResistanceFlags flags); -void meta_window_edge_resistance_for_resize (MetaWindow *window, - int *new_width, - int *new_height, - MetaGravity gravity, - GSourceFunc timeout_func, - MetaEdgeResistanceFlags flags); - -#endif /* META_EDGE_RESISTANCE_H */ - diff --git a/src/core/events.c b/src/core/events.c deleted file mode 100644 index 8afc720ef..000000000 --- a/src/core/events.c +++ /dev/null @@ -1,509 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002, 2003, 2004 Red Hat, Inc. - * Copyright (C) 2003, 2004 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * 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 . - */ - -#include "config.h" - -#include "core/events.h" - -#include "backends/meta-cursor-tracker-private.h" -#include "backends/meta-idle-manager.h" -#include "backends/x11/meta-backend-x11.h" -#include "backends/x11/meta-input-device-x11.h" -#include "compositor/meta-window-actor-private.h" -#include "core/display-private.h" -#include "core/window-private.h" -#include "meta/meta-backend.h" - -#ifdef HAVE_NATIVE_BACKEND -#include "backends/native/meta-backend-native.h" -#endif - -#ifdef HAVE_WAYLAND -#include "wayland/meta-wayland-private.h" -#endif - -#define IS_GESTURE_EVENT(e) ((e)->type == CLUTTER_TOUCHPAD_SWIPE || \ - (e)->type == CLUTTER_TOUCHPAD_PINCH || \ - (e)->type == CLUTTER_TOUCH_BEGIN || \ - (e)->type == CLUTTER_TOUCH_UPDATE || \ - (e)->type == CLUTTER_TOUCH_END || \ - (e)->type == CLUTTER_TOUCH_CANCEL) - -#define IS_KEY_EVENT(e) ((e)->type == CLUTTER_KEY_PRESS || \ - (e)->type == CLUTTER_KEY_RELEASE) - -typedef enum -{ - EVENTS_UNFREEZE_SYNC, - EVENTS_UNFREEZE_REPLAY, -} EventsUnfreezeMethod; - -static gboolean -stage_has_key_focus (void) -{ - MetaBackend *backend = meta_get_backend (); - ClutterActor *stage = meta_backend_get_stage (backend); - - return clutter_stage_get_key_focus (CLUTTER_STAGE (stage)) == stage; -} - -static MetaWindow * -get_window_for_event (MetaDisplay *display, - const ClutterEvent *event) -{ - switch (display->event_route) - { - case META_EVENT_ROUTE_NORMAL: - { - ClutterActor *source; - MetaWindowActor *window_actor; - - /* Always use the key focused window for key events. */ - if (IS_KEY_EVENT (event)) - return stage_has_key_focus () ? display->focus_window : NULL; - - source = clutter_event_get_source (event); - window_actor = meta_window_actor_from_actor (source); - if (window_actor) - return meta_window_actor_get_meta_window (window_actor); - else - return NULL; - } - case META_EVENT_ROUTE_WINDOW_OP: - case META_EVENT_ROUTE_COMPOSITOR_GRAB: - case META_EVENT_ROUTE_WAYLAND_POPUP: - case META_EVENT_ROUTE_FRAME_BUTTON: - return display->grab_window; - default: - g_assert_not_reached (); - return NULL; - } -} - -static void -handle_idletime_for_event (const ClutterEvent *event) -{ - MetaBackend *backend = meta_get_backend (); - MetaIdleManager *idle_manager; - - if (clutter_event_get_device (event) == NULL) - return; - - if (event->any.flags & CLUTTER_EVENT_FLAG_SYNTHETIC || - event->type == CLUTTER_ENTER || - event->type == CLUTTER_LEAVE) - return; - - idle_manager = meta_backend_get_idle_manager (backend); - meta_idle_manager_reset_idle_time (idle_manager); -} - -static gboolean -sequence_is_pointer_emulated (MetaDisplay *display, - const ClutterEvent *event) -{ - ClutterEventSequence *sequence; - - sequence = clutter_event_get_event_sequence (event); - - if (!sequence) - return FALSE; - - if (clutter_event_is_pointer_emulated (event)) - return TRUE; - -#ifdef HAVE_NATIVE_BACKEND - MetaBackend *backend = meta_get_backend (); - - /* When using Clutter's native input backend there is no concept of - * pointer emulating sequence, we still must make up our own to be - * able to implement single-touch (hence pointer alike) behavior. - * - * This is implemented similarly to X11, where only the first touch - * on screen gets the "pointer emulated" flag, and it won't get assigned - * to another sequence until the next first touch on an idle touchscreen. - */ - if (META_IS_BACKEND_NATIVE (backend)) - { - MetaGestureTracker *tracker; - - tracker = meta_display_get_gesture_tracker (display); - - if (event->type == CLUTTER_TOUCH_BEGIN && - meta_gesture_tracker_get_n_current_touches (tracker) == 0) - return TRUE; - } -#endif /* HAVE_NATIVE_BACKEND */ - - return FALSE; -} - -static void -maybe_unfreeze_pointer_events (MetaBackend *backend, - const ClutterEvent *event, - EventsUnfreezeMethod unfreeze_method) -{ - ClutterInputDevice *device; - Display *xdisplay; - int event_mode; - int device_id; - - if (event->type != CLUTTER_BUTTON_PRESS) - return; - - if (!META_IS_BACKEND_X11 (backend)) - return; - - device = clutter_event_get_device (event); - device_id = meta_input_device_x11_get_device_id (device); - switch (unfreeze_method) - { - case EVENTS_UNFREEZE_SYNC: - event_mode = XISyncDevice; - meta_verbose ("Syncing events time %u device %i", - (unsigned int) event->button.time, device_id); - break; - case EVENTS_UNFREEZE_REPLAY: - event_mode = XIReplayDevice; - meta_verbose ("Replaying events time %u device %i", - (unsigned int) event->button.time, device_id); - break; - default: - g_assert_not_reached (); - return; - } - - xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); - XIAllowEvents (xdisplay, device_id, event_mode, event->button.time); -} - -static gboolean -meta_display_handle_event (MetaDisplay *display, - const ClutterEvent *event) -{ - MetaBackend *backend = meta_get_backend (); - MetaWindow *window; - gboolean bypass_clutter = FALSE; - G_GNUC_UNUSED gboolean bypass_wayland = FALSE; - MetaGestureTracker *gesture_tracker; - ClutterEventSequence *sequence; - - sequence = clutter_event_get_event_sequence (event); - - /* Set the pointer emulating sequence on touch begin, if eligible */ - if (event->type == CLUTTER_TOUCH_BEGIN) - { - if (sequence_is_pointer_emulated (display, event)) - { - /* This is the new pointer emulating sequence */ - display->pointer_emulating_sequence = sequence; - } - else if (display->pointer_emulating_sequence == sequence) - { - /* This sequence was "pointer emulating" in a prior incarnation, - * but now it isn't. We unset the pointer emulating sequence at - * this point so the current sequence is not mistaken as pointer - * emulating, while we've ensured that it's been deemed - * "pointer emulating" throughout all of the event processing - * of the previous incarnation. - */ - display->pointer_emulating_sequence = NULL; - } - } - -#ifdef HAVE_WAYLAND - MetaWaylandCompositor *compositor = NULL; - if (meta_is_wayland_compositor ()) - { - compositor = meta_wayland_compositor_get_default (); - meta_wayland_compositor_update (compositor, event); - } -#endif - - if (event->type == CLUTTER_PAD_BUTTON_PRESS || - event->type == CLUTTER_PAD_BUTTON_RELEASE || - event->type == CLUTTER_PAD_RING || - event->type == CLUTTER_PAD_STRIP) - { - gboolean handle_pad_event; - gboolean is_mode_switch = FALSE; - - if (event->type == CLUTTER_PAD_BUTTON_PRESS || - event->type == CLUTTER_PAD_BUTTON_RELEASE) - { - ClutterInputDevice *pad; - uint32_t button; - - pad = clutter_event_get_source_device (event); - button = clutter_event_get_button (event); - - is_mode_switch = - clutter_input_device_get_mode_switch_button_group (pad, button) >= 0; - } - - handle_pad_event = !display->current_pad_osd || is_mode_switch; - - if (handle_pad_event && - meta_pad_action_mapper_handle_event (display->pad_action_mapper, event)) - { - bypass_wayland = bypass_clutter = TRUE; - goto out; - } - } - - if (event->type != CLUTTER_DEVICE_ADDED && - event->type != CLUTTER_DEVICE_REMOVED) - { - ClutterInputDevice *source; - - handle_idletime_for_event (event); - source = clutter_event_get_source_device (event); - - if (source) - meta_backend_update_last_device (backend, source); - } - -#ifdef HAVE_WAYLAND - if (meta_is_wayland_compositor () && event->type == CLUTTER_MOTION) - { - MetaCursorRenderer *cursor_renderer; - ClutterInputDevice *device; - - device = clutter_event_get_device (event); - cursor_renderer = meta_backend_get_cursor_renderer_for_device (backend, - device); - if (cursor_renderer) - meta_cursor_renderer_update_position (cursor_renderer); - - if (device == clutter_seat_get_pointer (clutter_input_device_get_seat (device))) - { - MetaCursorTracker *cursor_tracker = - meta_backend_get_cursor_tracker (backend); - - meta_cursor_tracker_invalidate_position (cursor_tracker); - } - } -#endif - - window = get_window_for_event (display, event); - - display->current_time = event->any.time; - - if (window && !window->override_redirect && - (event->type == CLUTTER_KEY_PRESS || - event->type == CLUTTER_BUTTON_PRESS || - event->type == CLUTTER_TOUCH_BEGIN)) - { - if (META_CURRENT_TIME == display->current_time) - { - /* We can't use missing (i.e. invalid) timestamps to set user time, - * nor do we want to use them to sanity check other timestamps. - * See bug 313490 for more details. - */ - meta_warning ("Event has no timestamp! You may be using a broken " - "program such as xse. Please ask the authors of that " - "program to fix it."); - } - else - { - meta_window_set_user_time (window, display->current_time); - meta_display_sanity_check_timestamps (display, display->current_time); - } - } - - gesture_tracker = meta_display_get_gesture_tracker (display); - - if (meta_gesture_tracker_handle_event (gesture_tracker, event)) - { - bypass_wayland = bypass_clutter = TRUE; - goto out; - } - - if (display->event_route == META_EVENT_ROUTE_WINDOW_OP) - { - if (meta_window_handle_mouse_grab_op_event (window, event)) - { - bypass_clutter = TRUE; - bypass_wayland = TRUE; - goto out; - } - } - - /* For key events, it's important to enforce single-handling, or - * we can get into a confused state. So if a keybinding is - * handled (because it's one of our hot-keys, or because we are - * in a keyboard-grabbed mode like moving a window, we don't - * want to pass the key event to the compositor or Wayland at all. - */ - if (meta_keybindings_process_event (display, window, event)) - { - bypass_clutter = TRUE; - bypass_wayland = TRUE; - goto out; - } - - /* Do not pass keyboard events to Wayland if key focus is not on the - * stage in normal mode (e.g. during keynav in the panel) - */ - if (display->event_route == META_EVENT_ROUTE_NORMAL) - { - if (IS_KEY_EVENT (event) && !stage_has_key_focus ()) - { - bypass_wayland = TRUE; - goto out; - } - } - - if (meta_is_wayland_compositor () && - event->type == CLUTTER_SCROLL && - meta_prefs_get_mouse_button_mods () > 0) - { - ClutterModifierType grab_mods; - - grab_mods = meta_display_get_compositor_modifiers (display); - if ((clutter_event_get_state (event) & grab_mods) != 0) - { - bypass_wayland = TRUE; - goto out; - } - } - - if (display->current_pad_osd) - { - bypass_wayland = TRUE; - goto out; - } - - if (window) - { - /* Events that are likely to trigger compositor gestures should - * be known to clutter so they can propagate along the hierarchy. - * Gesture-wise, there's two groups of events we should be getting - * here: - * - CLUTTER_TOUCH_* with a touch sequence that's not yet accepted - * by the gesture tracker, these might trigger gesture actions - * into recognition. Already accepted touch sequences are handled - * directly by meta_gesture_tracker_handle_event(). - * - CLUTTER_TOUCHPAD_* events over windows. These can likewise - * trigger ::captured-event handlers along the way. - */ - bypass_clutter = !IS_GESTURE_EVENT (event); - - /* When double clicking to un-maximize an X11 window under Wayland, - * there is a race between X11 and Wayland protocols and the X11 - * XConfigureWindow may be processed by Xwayland before the button - * press event is forwarded via the Wayland protocol. - * As a result, the second click may reach another X11 window placed - * immediately underneath in the X11 stack. - * The following is to make sure we do not forward the button press - * event to Wayland if it was handled by the frame UI. - * See: https://gitlab.gnome.org/GNOME/mutter/issues/88 - */ - if (meta_window_handle_ui_frame_event (window, event)) - bypass_wayland = (event->type == CLUTTER_BUTTON_PRESS || - event->type == CLUTTER_TOUCH_BEGIN); - else - meta_window_handle_ungrabbed_event (window, event); - - /* This might start a grab op. If it does, then filter out the - * event, and if it doesn't, replay the event to release our - * own sync grab. */ - - if (display->event_route == META_EVENT_ROUTE_WINDOW_OP || - display->event_route == META_EVENT_ROUTE_FRAME_BUTTON) - { - bypass_clutter = TRUE; - bypass_wayland = TRUE; - } - else - { - /* Only replay button press events, since that's where we - * have the synchronous grab. */ - maybe_unfreeze_pointer_events (backend, event, EVENTS_UNFREEZE_REPLAY); - - /* If the focus window has an active close dialog let clutter - * events go through, so fancy clutter dialogs can get to handle - * all events. - */ - if (window->close_dialog && - meta_close_dialog_is_visible (window->close_dialog)) - { - bypass_wayland = TRUE; - bypass_clutter = FALSE; - } - } - - goto out; - } - else - { - /* We could not match the event with a window, make sure we sync - * the pointer to discard the sequence and don't keep events frozen. - */ - maybe_unfreeze_pointer_events (backend, event, EVENTS_UNFREEZE_SYNC); - } - - out: - /* If the compositor has a grab, don't pass that through to Wayland */ - if (display->event_route == META_EVENT_ROUTE_COMPOSITOR_GRAB) - bypass_wayland = TRUE; - - /* If a Wayland client has a grab, don't pass that through to Clutter */ - if (display->event_route == META_EVENT_ROUTE_WAYLAND_POPUP) - bypass_clutter = TRUE; - -#ifdef HAVE_WAYLAND - if (compositor && !bypass_wayland) - { - if (meta_wayland_compositor_handle_event (compositor, event)) - bypass_clutter = TRUE; - } -#endif - - display->current_time = META_CURRENT_TIME; - return bypass_clutter; -} - -static gboolean -event_callback (const ClutterEvent *event, - gpointer data) -{ - MetaDisplay *display = data; - - return meta_display_handle_event (display, event); -} - -void -meta_display_init_events (MetaDisplay *display) -{ - display->clutter_event_filter = clutter_event_add_filter (NULL, - event_callback, - NULL, - display); -} - -void -meta_display_free_events (MetaDisplay *display) -{ - clutter_event_remove_filter (display->clutter_event_filter); - display->clutter_event_filter = 0; -} diff --git a/src/core/events.h b/src/core/events.h deleted file mode 100644 index 6338119ae..000000000 --- a/src/core/events.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002, 2003, 2004 Red Hat, Inc. - * Copyright (C) 2003, 2004 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * 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 . - */ - -#ifndef META_EVENTS_H -#define META_EVENTS_H - -#include "meta/display.h" - -void meta_display_init_events (MetaDisplay *display); -void meta_display_free_events (MetaDisplay *display); - -#endif diff --git a/src/core/frame.c b/src/core/frame.c deleted file mode 100644 index 9c8cbb946..000000000 --- a/src/core/frame.c +++ /dev/null @@ -1,427 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter X window decorations */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2003, 2004 Red Hat, Inc. - * Copyright (C) 2005 Elijah Newren - * - * 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 . - */ - -#include "config.h" - -#include "core/frame.h" - -#include "backends/x11/meta-backend-x11.h" -#include "core/bell.h" -#include "core/keybindings-private.h" -#include "meta/meta-x11-errors.h" -#include "x11/meta-x11-display-private.h" - -#define EVENT_MASK (SubstructureRedirectMask | \ - StructureNotifyMask | SubstructureNotifyMask | \ - ExposureMask | FocusChangeMask) - -void -meta_window_ensure_frame (MetaWindow *window) -{ - MetaFrame *frame; - XSetWindowAttributes attrs; - gulong create_serial; - MetaX11Display *x11_display; - - if (window->frame) - return; - - x11_display = window->display->x11_display; - - frame = g_new (MetaFrame, 1); - - frame->window = window; - frame->xwindow = None; - - frame->rect = window->rect; - frame->child_x = 0; - frame->child_y = 0; - frame->bottom_height = 0; - frame->right_width = 0; - frame->current_cursor = 0; - - frame->borders_cached = FALSE; - - meta_verbose ("Frame geometry %d,%d %dx%d", - frame->rect.x, frame->rect.y, - frame->rect.width, frame->rect.height); - - frame->ui_frame = meta_ui_create_frame (x11_display->ui, - x11_display->xdisplay, - frame->window, - window->xvisual, - frame->rect.x, - frame->rect.y, - frame->rect.width, - frame->rect.height, - &create_serial); - frame->xwindow = frame->ui_frame->xwindow; - - meta_stack_tracker_record_add (window->display->stack_tracker, - frame->xwindow, - create_serial); - - meta_verbose ("Frame for %s is 0x%lx", frame->window->desc, frame->xwindow); - attrs.event_mask = EVENT_MASK; - XChangeWindowAttributes (x11_display->xdisplay, - frame->xwindow, CWEventMask, &attrs); - - meta_x11_display_register_x_window (x11_display, &frame->xwindow, window); - - meta_x11_error_trap_push (x11_display); - if (window->mapped) - { - window->mapped = FALSE; /* the reparent will unmap the window, - * we don't want to take that as a withdraw - */ - meta_topic (META_DEBUG_WINDOW_STATE, - "Incrementing unmaps_pending on %s for reparent", window->desc); - window->unmaps_pending += 1; - } - - meta_stack_tracker_record_remove (window->display->stack_tracker, - window->xwindow, - XNextRequest (x11_display->xdisplay)); - XReparentWindow (x11_display->xdisplay, - window->xwindow, - frame->xwindow, - frame->child_x, - frame->child_y); - window->reparents_pending += 1; - /* FIXME handle this error */ - meta_x11_error_trap_pop (x11_display); - - /* Ensure focus is restored after the unmap/map events triggered - * by XReparentWindow(). - */ - if (meta_window_has_focus (window)) - window->restore_focus_on_map = TRUE; - - /* stick frame to the window */ - window->frame = frame; - - /* Now that frame->xwindow is registered with window, we can set its - * style and background. - */ - meta_frame_update_style (frame); - meta_frame_update_title (frame); - - meta_ui_map_frame (x11_display->ui, frame->xwindow); - - { - MetaBackend *backend = meta_get_backend (); - if (META_IS_BACKEND_X11 (backend)) - { - Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); - - /* Since the backend selects for events on another connection, - * make sure to sync the GTK+ connection to ensure that the - * frame window has been created on the server at this point. */ - XSync (x11_display->xdisplay, False); - - unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 }; - XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits }; - - XISelectEvents (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), - frame->xwindow, &mask, 1); - - XISetMask (mask.mask, XI_ButtonPress); - XISetMask (mask.mask, XI_ButtonRelease); - XISetMask (mask.mask, XI_Motion); - XISetMask (mask.mask, XI_Enter); - XISetMask (mask.mask, XI_Leave); - - XISelectEvents (xdisplay, frame->xwindow, &mask, 1); - } - } - - /* Move keybindings to frame instead of window */ - meta_window_grab_keys (window); -} - -void -meta_window_destroy_frame (MetaWindow *window) -{ - MetaFrame *frame; - MetaFrameBorders borders; - MetaX11Display *x11_display; - - if (window->frame == NULL) - return; - - x11_display = window->display->x11_display; - - meta_verbose ("Unframing window %s", window->desc); - - frame = window->frame; - - meta_frame_calc_borders (frame, &borders); - - /* Unparent the client window; it may be destroyed, - * thus the error trap. - */ - meta_x11_error_trap_push (x11_display); - if (window->mapped) - { - window->mapped = FALSE; /* Keep track of unmapping it, so we - * can identify a withdraw initiated - * by the client. - */ - meta_topic (META_DEBUG_WINDOW_STATE, - "Incrementing unmaps_pending on %s for reparent back to root", window->desc); - window->unmaps_pending += 1; - } - - if (!x11_display->closing) - { - meta_stack_tracker_record_add (window->display->stack_tracker, - window->xwindow, - XNextRequest (x11_display->xdisplay)); - - XReparentWindow (x11_display->xdisplay, - window->xwindow, - x11_display->xroot, - /* Using anything other than client root window coordinates - * coordinates here means we'll need to ensure a configure - * notify event is sent; see bug 399552. - */ - window->frame->rect.x + borders.invisible.left, - window->frame->rect.y + borders.invisible.top); - window->reparents_pending += 1; - } - - meta_x11_error_trap_pop (x11_display); - - meta_ui_frame_unmanage (frame->ui_frame); - - /* Ensure focus is restored after the unmap/map events triggered - * by XReparentWindow(). - */ - if (meta_window_has_focus (window)) - window->restore_focus_on_map = TRUE; - - meta_x11_display_unregister_x_window (x11_display, frame->xwindow); - - window->frame = NULL; - if (window->frame_bounds) - { - cairo_region_destroy (window->frame_bounds); - window->frame_bounds = NULL; - } - - /* Move keybindings to window instead of frame */ - meta_window_grab_keys (window); - - g_free (frame); - - /* Put our state back where it should be */ - meta_window_queue (window, META_QUEUE_CALC_SHOWING); - meta_window_queue (window, META_QUEUE_MOVE_RESIZE); -} - - -MetaFrameFlags -meta_frame_get_flags (MetaFrame *frame) -{ - MetaFrameFlags flags; - - flags = 0; - - if (frame->window->border_only) - { - ; /* FIXME this may disable the _function_ as well as decor - * in some cases, which is sort of wrong. - */ - } - else - { - flags |= META_FRAME_ALLOWS_MENU; - - if (frame->window->has_close_func) - flags |= META_FRAME_ALLOWS_DELETE; - - if (frame->window->has_maximize_func) - flags |= META_FRAME_ALLOWS_MAXIMIZE; - - if (frame->window->has_minimize_func) - flags |= META_FRAME_ALLOWS_MINIMIZE; - - if (frame->window->has_shade_func) - flags |= META_FRAME_ALLOWS_SHADE; - } - - if (META_WINDOW_ALLOWS_MOVE (frame->window)) - flags |= META_FRAME_ALLOWS_MOVE; - - if (META_WINDOW_ALLOWS_HORIZONTAL_RESIZE (frame->window)) - flags |= META_FRAME_ALLOWS_HORIZONTAL_RESIZE; - - if (META_WINDOW_ALLOWS_VERTICAL_RESIZE (frame->window)) - flags |= META_FRAME_ALLOWS_VERTICAL_RESIZE; - - if (meta_window_appears_focused (frame->window)) - flags |= META_FRAME_HAS_FOCUS; - - if (frame->window->shaded) - flags |= META_FRAME_SHADED; - - if (frame->window->on_all_workspaces_requested) - flags |= META_FRAME_STUCK; - - /* FIXME: Should we have some kind of UI for windows that are just vertically - * maximized or just horizontally maximized? - */ - if (META_WINDOW_MAXIMIZED (frame->window)) - flags |= META_FRAME_MAXIMIZED; - - if (META_WINDOW_TILED_LEFT (frame->window)) - flags |= META_FRAME_TILED_LEFT; - - if (META_WINDOW_TILED_RIGHT (frame->window)) - flags |= META_FRAME_TILED_RIGHT; - - if (frame->window->fullscreen) - flags |= META_FRAME_FULLSCREEN; - - if (frame->window->wm_state_above) - flags |= META_FRAME_ABOVE; - - return flags; -} - -void -meta_frame_borders_clear (MetaFrameBorders *self) -{ - self->visible.top = self->invisible.top = self->total.top = 0; - self->visible.bottom = self->invisible.bottom = self->total.bottom = 0; - self->visible.left = self->invisible.left = self->total.left = 0; - self->visible.right = self->invisible.right = self->total.right = 0; -} - -void -meta_frame_calc_borders (MetaFrame *frame, - MetaFrameBorders *borders) -{ - /* Save on if statements and potential uninitialized values - * in callers -- if there's no frame, then zero the borders. */ - if (frame == NULL) - meta_frame_borders_clear (borders); - else - { - if (!frame->borders_cached) - { - meta_ui_frame_get_borders (frame->ui_frame, &frame->cached_borders); - frame->borders_cached = TRUE; - } - - *borders = frame->cached_borders; - } -} - -void -meta_frame_clear_cached_borders (MetaFrame *frame) -{ - frame->borders_cached = FALSE; -} - -gboolean -meta_frame_sync_to_window (MetaFrame *frame, - gboolean need_resize) -{ - meta_topic (META_DEBUG_GEOMETRY, - "Syncing frame geometry %d,%d %dx%d (SE: %d,%d)", - frame->rect.x, frame->rect.y, - frame->rect.width, frame->rect.height, - frame->rect.x + frame->rect.width, - frame->rect.y + frame->rect.height); - - meta_ui_frame_move_resize (frame->ui_frame, - frame->rect.x, - frame->rect.y, - frame->rect.width, - frame->rect.height); - - return need_resize; -} - -cairo_region_t * -meta_frame_get_frame_bounds (MetaFrame *frame) -{ - return meta_ui_frame_get_bounds (frame->ui_frame); -} - -void -meta_frame_get_mask (MetaFrame *frame, - cairo_rectangle_int_t *frame_rect, - cairo_t *cr) -{ - meta_ui_frame_get_mask (frame->ui_frame, frame_rect, cr); -} - -void -meta_frame_queue_draw (MetaFrame *frame) -{ - meta_ui_frame_queue_draw (frame->ui_frame); -} - -void -meta_frame_set_screen_cursor (MetaFrame *frame, - MetaCursor cursor) -{ - MetaX11Display *x11_display; - Cursor xcursor; - if (cursor == frame->current_cursor) - return; - - frame->current_cursor = cursor; - x11_display = frame->window->display->x11_display; - - if (cursor == META_CURSOR_DEFAULT) - XUndefineCursor (x11_display->xdisplay, frame->xwindow); - else - { - xcursor = meta_x11_display_create_x_cursor (x11_display, cursor); - XDefineCursor (x11_display->xdisplay, frame->xwindow, xcursor); - XFlush (x11_display->xdisplay); - XFreeCursor (x11_display->xdisplay, xcursor); - } -} - -Window -meta_frame_get_xwindow (MetaFrame *frame) -{ - return frame->xwindow; -} - -void -meta_frame_update_style (MetaFrame *frame) -{ - meta_ui_frame_update_style (frame->ui_frame); -} - -void -meta_frame_update_title (MetaFrame *frame) -{ - if (frame->window->title) - meta_ui_frame_set_title (frame->ui_frame, frame->window->title); -} diff --git a/src/core/frame.h b/src/core/frame.h deleted file mode 100644 index 61a5ca725..000000000 --- a/src/core/frame.h +++ /dev/null @@ -1,85 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter X window decorations */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * 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 . - */ - -#ifndef META_FRAME_PRIVATE_H -#define META_FRAME_PRIVATE_H - -#include "core/window-private.h" -#include "ui/frames.h" - -struct _MetaFrame -{ - /* window we frame */ - MetaWindow *window; - - /* reparent window */ - Window xwindow; - - MetaCursor current_cursor; - - /* This rect is trusted info from where we put the - * frame, not the result of ConfigureNotify - */ - MetaRectangle rect; - - MetaFrameBorders cached_borders; /* valid if borders_cached is set */ - - /* position of client, size of frame */ - int child_x; - int child_y; - int right_width; - int bottom_height; - - guint need_reapply_frame_shape : 1; - guint borders_cached : 1; - - MetaUIFrame *ui_frame; -}; - -void meta_window_ensure_frame (MetaWindow *window); -void meta_window_destroy_frame (MetaWindow *window); -void meta_frame_queue_draw (MetaFrame *frame); - -MetaFrameFlags meta_frame_get_flags (MetaFrame *frame); -Window meta_frame_get_xwindow (MetaFrame *frame); - -/* These should ONLY be called from meta_window_move_resize_internal */ -void meta_frame_calc_borders (MetaFrame *frame, - MetaFrameBorders *borders); - -gboolean meta_frame_sync_to_window (MetaFrame *frame, - gboolean need_resize); - -void meta_frame_clear_cached_borders (MetaFrame *frame); - -cairo_region_t *meta_frame_get_frame_bounds (MetaFrame *frame); - -void meta_frame_get_mask (MetaFrame *frame, - cairo_rectangle_int_t *frame_rect, - cairo_t *cr); - -void meta_frame_set_screen_cursor (MetaFrame *frame, - MetaCursor cursor); - -void meta_frame_update_style (MetaFrame *frame); -void meta_frame_update_title (MetaFrame *frame); - -#endif diff --git a/src/core/keybindings-private.h b/src/core/keybindings-private.h deleted file mode 100644 index 56792c200..000000000 --- a/src/core/keybindings-private.h +++ /dev/null @@ -1,160 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/** - * \file keybindings.h Grab and ungrab keys, and process the key events - * - * Performs global X grabs on the keys we need to be told about, like - * the one to close a window. It also deals with incoming key events. - */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * 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 . - */ - -#ifndef META_KEYBINDINGS_PRIVATE_H -#define META_KEYBINDINGS_PRIVATE_H - -#include -#include - -#include "core/meta-accel-parse.h" -#include "meta/keybindings.h" - -typedef struct _MetaKeyHandler MetaKeyHandler; -struct _MetaKeyHandler -{ - char *name; - MetaKeyHandlerFunc func; - MetaKeyHandlerFunc default_func; - gint data, flags; - gpointer user_data; - GDestroyNotify user_data_free_func; -}; - -typedef struct _MetaResolvedKeyCombo { - xkb_keycode_t *keycodes; - int len; - xkb_mod_mask_t mask; -} MetaResolvedKeyCombo; - -/** - * MetaKeyCombo: - * @keysym: keysym - * @keycode: keycode - * @modifiers: modifiers - */ -struct _MetaKeyCombo -{ - unsigned int keysym; - unsigned int keycode; - MetaVirtualModifier modifiers; -}; - -struct _MetaKeyBinding -{ - const char *name; - MetaKeyCombo combo; - MetaResolvedKeyCombo resolved_combo; - gint flags; - MetaKeyHandler *handler; -}; - -typedef struct -{ - char *name; - GSettings *settings; - - MetaKeyBindingAction action; - - /* - * A list of MetaKeyCombos. Each of them is bound to - * this keypref. If one has keysym==modifiers==0, it is - * ignored. - */ - GSList *combos; - - /* for keybindings not added with meta_display_add_keybinding() */ - gboolean builtin:1; -} MetaKeyPref; - -typedef struct _MetaKeyBindingKeyboardLayout -{ - struct xkb_keymap *keymap; - xkb_layout_index_t index; - xkb_level_index_t n_levels; -} MetaKeyBindingKeyboardLayout; - -typedef struct -{ - MetaBackend *backend; - - GHashTable *key_bindings; - GHashTable *key_bindings_index; - xkb_mod_mask_t ignored_modifier_mask; - xkb_mod_mask_t hyper_mask; - xkb_mod_mask_t virtual_hyper_mask; - xkb_mod_mask_t super_mask; - xkb_mod_mask_t virtual_super_mask; - xkb_mod_mask_t meta_mask; - xkb_mod_mask_t virtual_meta_mask; - MetaKeyCombo overlay_key_combo; - MetaResolvedKeyCombo overlay_resolved_key_combo; - gboolean overlay_key_only_pressed; - MetaKeyCombo locate_pointer_key_combo; - MetaResolvedKeyCombo locate_pointer_resolved_key_combo; - gboolean locate_pointer_key_only_pressed; - MetaResolvedKeyCombo iso_next_group_combo[2]; - int n_iso_next_group_combos; - - /* - * A primary layout, and an optional secondary layout for when the - * primary layout does not use the latin alphabet. - */ - MetaKeyBindingKeyboardLayout active_layouts[2]; - - /* Alt+click button grabs */ - ClutterModifierType window_grab_modifiers; -} MetaKeyBindingManager; - -void meta_display_init_keys (MetaDisplay *display); -void meta_display_shutdown_keys (MetaDisplay *display); -void meta_window_grab_keys (MetaWindow *window); -void meta_window_ungrab_keys (MetaWindow *window); -gboolean meta_window_grab_all_keys (MetaWindow *window, - guint32 timestamp); -void meta_window_ungrab_all_keys (MetaWindow *window, - guint32 timestamp); -gboolean meta_keybindings_process_event (MetaDisplay *display, - MetaWindow *window, - const ClutterEvent *event); - -gboolean meta_prefs_add_keybinding (const char *name, - GSettings *settings, - MetaKeyBindingAction action, - MetaKeyBindingFlags flags); - -gboolean meta_prefs_remove_keybinding (const char *name); - -GList *meta_prefs_get_keybindings (void); -void meta_prefs_get_overlay_binding (MetaKeyCombo *combo); -void meta_prefs_get_locate_pointer_binding (MetaKeyCombo *combo); -const char *meta_prefs_get_iso_next_group_option (void); -gboolean meta_prefs_is_locate_pointer_enabled (void); - -void meta_x11_display_grab_keys (MetaX11Display *x11_display); -void meta_x11_display_ungrab_keys (MetaX11Display *x11_display); - -#endif diff --git a/src/core/keybindings.c b/src/core/keybindings.c deleted file mode 100644 index a6e16f084..000000000 --- a/src/core/keybindings.c +++ /dev/null @@ -1,4578 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter Keybindings */ -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002 Red Hat Inc. - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * 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 . - */ - -/** - * SECTION:keybindings - * @Title: MetaKeybinding - * @Short_Description: Key bindings - */ - -#include "config.h" - -#include "backends/meta-backend-private.h" -#include "backends/meta-keymap-utils.h" -#include "backends/meta-logical-monitor.h" -#include "backends/meta-monitor-manager-private.h" -#include "backends/x11/meta-backend-x11.h" -#include "backends/x11/meta-input-device-x11.h" -#include "compositor/compositor-private.h" -#include "core/edge-resistance.h" -#include "core/frame.h" -#include "core/keybindings-private.h" -#include "core/meta-accel-parse.h" -#include "core/meta-workspace-manager-private.h" -#include "core/workspace-private.h" -#include "meta/compositor.h" -#include "meta/meta-x11-errors.h" -#include "meta/prefs.h" -#include "x11/meta-x11-display-private.h" -#include "x11/window-x11.h" - -#ifdef HAVE_NATIVE_BACKEND -#include "backends/native/meta-backend-native.h" -#endif - -#ifdef __linux__ -#include -#elif !defined KEY_GRAVE -#define KEY_GRAVE 0x29 /* assume the use of xf86-input-keyboard */ -#endif - -#define SCHEMA_COMMON_KEYBINDINGS "org.gnome.desktop.wm.keybindings" -#define SCHEMA_MUTTER_KEYBINDINGS "org.gnome.mutter.keybindings" -#define SCHEMA_MUTTER_WAYLAND_KEYBINDINGS "org.gnome.mutter.wayland.keybindings" - -#define META_KEY_BINDING_PRIMARY_LAYOUT 0 -#define META_KEY_BINDING_SECONDARY_LAYOUT 1 - -/* Only for special modifier keys */ -#define IGNORED_MODIFIERS (CLUTTER_LOCK_MASK | \ - CLUTTER_MOD2_MASK | \ - CLUTTER_BUTTON1_MASK | \ - CLUTTER_BUTTON2_MASK | \ - CLUTTER_BUTTON3_MASK | \ - CLUTTER_BUTTON4_MASK | \ - CLUTTER_BUTTON5_MASK) - -static gboolean add_builtin_keybinding (MetaDisplay *display, - const char *name, - GSettings *settings, - MetaKeyBindingFlags flags, - MetaKeyBindingAction action, - MetaKeyHandlerFunc handler, - int handler_arg); - -static void -resolved_key_combo_reset (MetaResolvedKeyCombo *resolved_combo) -{ - g_free (resolved_combo->keycodes); - resolved_combo->len = 0; - resolved_combo->keycodes = NULL; -} - -static void -resolved_key_combo_copy (MetaResolvedKeyCombo *from, - MetaResolvedKeyCombo *to) -{ - to->len = from->len; - to->keycodes = g_memdup2 (from->keycodes, - from->len * sizeof (xkb_keycode_t)); -} - -static gboolean -resolved_key_combo_has_keycode (MetaResolvedKeyCombo *resolved_combo, - int keycode) -{ - int i; - - for (i = 0; i < resolved_combo->len; i++) - if ((int) resolved_combo->keycodes[i] == keycode) - return TRUE; - - return FALSE; -} - -static gboolean -resolved_key_combo_intersect (MetaResolvedKeyCombo *a, - MetaResolvedKeyCombo *b) -{ - int i; - - for (i = 0; i < a->len; i++) - if (resolved_key_combo_has_keycode (b, a->keycodes[i])) - return TRUE; - - return FALSE; -} - -static void -meta_key_binding_free (MetaKeyBinding *binding) -{ - resolved_key_combo_reset (&binding->resolved_combo); - g_free (binding); -} - -static MetaKeyBinding * -meta_key_binding_copy (MetaKeyBinding *binding) -{ - MetaKeyBinding *clone = g_memdup2 (binding, sizeof (MetaKeyBinding)); - resolved_key_combo_copy (&binding->resolved_combo, - &clone->resolved_combo); - return clone; -} - -G_DEFINE_BOXED_TYPE(MetaKeyBinding, - meta_key_binding, - meta_key_binding_copy, - meta_key_binding_free) - -const char * -meta_key_binding_get_name (MetaKeyBinding *binding) -{ - return binding->name; -} - -MetaVirtualModifier -meta_key_binding_get_modifiers (MetaKeyBinding *binding) -{ - return binding->combo.modifiers; -} - -gboolean -meta_key_binding_is_reversed (MetaKeyBinding *binding) -{ - return (binding->handler->flags & META_KEY_BINDING_IS_REVERSED) != 0; -} - -guint -meta_key_binding_get_mask (MetaKeyBinding *binding) -{ - return binding->resolved_combo.mask; -} - -gboolean -meta_key_binding_is_builtin (MetaKeyBinding *binding) -{ - return binding->handler->flags & META_KEY_BINDING_BUILTIN; -} - -/* These can't be bound to anything, but they are used to handle - * various other events. TODO: Possibly we should include them as event - * handler functions and have some kind of flag to say they're unbindable. - */ - -static gboolean process_mouse_move_resize_grab (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event); - -static gboolean process_keyboard_move_grab (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event); - -static gboolean process_keyboard_resize_grab (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event); - -static void maybe_update_locate_pointer_keygrab (MetaDisplay *display, - gboolean grab); - -static GHashTable *key_handlers; -static GHashTable *external_grabs; - -#define HANDLER(name) g_hash_table_lookup (key_handlers, (name)) - -static void -key_handler_free (MetaKeyHandler *handler) -{ - g_free (handler->name); - if (handler->user_data_free_func && handler->user_data) - handler->user_data_free_func (handler->user_data); - g_free (handler); -} - -typedef struct _MetaKeyGrab MetaKeyGrab; -struct _MetaKeyGrab { - char *name; - guint action; - MetaKeyCombo combo; - gint flags; -}; - -static void -meta_key_grab_free (MetaKeyGrab *grab) -{ - g_free (grab->name); - g_free (grab); -} - -static guint32 -key_combo_key (MetaResolvedKeyCombo *resolved_combo, - int i) -{ - /* On X, keycodes are only 8 bits while libxkbcommon supports 32 bit - keycodes, but since we're using the same XKB keymaps that X uses, - we won't find keycodes bigger than 8 bits in practice. The bits - that mutter cares about in the modifier mask are also all in the - lower 8 bits both on X and clutter key events. This means that we - can use a 32 bit integer to safely concatenate both keycode and - mask and thus making it easy to use them as an index in a - GHashTable. */ - guint32 key = resolved_combo->keycodes[i] & 0xffff; - return (key << 16) | (resolved_combo->mask & 0xffff); -} - -static void -reload_modmap (MetaKeyBindingManager *keys) -{ - struct xkb_keymap *keymap = meta_backend_get_keymap (keys->backend); - struct xkb_state *scratch_state; - xkb_mod_mask_t scroll_lock_mask; - xkb_mod_mask_t dummy_mask; - - /* Modifiers to find. */ - struct { - const char *name; - xkb_mod_mask_t *mask_p; - xkb_mod_mask_t *virtual_mask_p; - } mods[] = { - { "ScrollLock", &scroll_lock_mask, &dummy_mask }, - { "Meta", &keys->meta_mask, &keys->virtual_meta_mask }, - { "Hyper", &keys->hyper_mask, &keys->virtual_hyper_mask }, - { "Super", &keys->super_mask, &keys->virtual_super_mask }, - }; - - scratch_state = xkb_state_new (keymap); - - gsize i; - for (i = 0; i < G_N_ELEMENTS (mods); i++) - { - xkb_mod_mask_t *mask_p = mods[i].mask_p; - xkb_mod_mask_t *virtual_mask_p = mods[i].virtual_mask_p; - xkb_mod_index_t idx = xkb_keymap_mod_get_index (keymap, mods[i].name); - - if (idx != XKB_MOD_INVALID) - { - xkb_mod_mask_t vmodmask = (1 << idx); - xkb_state_update_mask (scratch_state, vmodmask, 0, 0, 0, 0, 0); - *mask_p = xkb_state_serialize_mods (scratch_state, XKB_STATE_MODS_DEPRESSED) & ~vmodmask; - *virtual_mask_p = vmodmask; - } - else - { - *mask_p = 0; - *virtual_mask_p = 0; - } - } - - xkb_state_unref (scratch_state); - - keys->ignored_modifier_mask = (scroll_lock_mask | Mod2Mask | LockMask); - - meta_topic (META_DEBUG_KEYBINDINGS, - "Ignoring modmask 0x%x scroll lock 0x%x hyper 0x%x super 0x%x meta 0x%x", - keys->ignored_modifier_mask, - scroll_lock_mask, - keys->hyper_mask, - keys->super_mask, - keys->meta_mask); -} - -static gboolean -is_keycode_for_keysym (struct xkb_keymap *keymap, - xkb_layout_index_t layout, - xkb_level_index_t level, - xkb_keycode_t keycode, - xkb_keysym_t keysym) -{ - const xkb_keysym_t *syms; - int num_syms, k; - - num_syms = xkb_keymap_key_get_syms_by_level (keymap, keycode, layout, level, &syms); - for (k = 0; k < num_syms; k++) - { - if (syms[k] == keysym) - return TRUE; - } - - return FALSE; -} - -typedef struct -{ - GArray *keycodes; - xkb_keysym_t keysym; - xkb_layout_index_t layout; - xkb_level_index_t level; -} FindKeysymData; - -static void -get_keycodes_for_keysym_iter (struct xkb_keymap *keymap, - xkb_keycode_t keycode, - void *data) -{ - FindKeysymData *search_data = data; - GArray *keycodes = search_data->keycodes; - xkb_keysym_t keysym = search_data->keysym; - xkb_layout_index_t layout = search_data->layout; - xkb_level_index_t level = search_data->level; - - if (is_keycode_for_keysym (keymap, layout, level, keycode, keysym)) - { - guint i; - gboolean missing = TRUE; - - /* duplicate keycode detection */ - for (i = 0; i < keycodes->len; i++) - if (g_array_index (keycodes, xkb_keysym_t, i) == keycode) - { - missing = FALSE; - break; - } - - if (missing) - g_array_append_val (keycodes, keycode); - } -} - -static void -add_keysym_keycodes_from_layout (int keysym, - MetaKeyBindingKeyboardLayout *layout, - GArray *keycodes) -{ - xkb_level_index_t layout_level; - - for (layout_level = 0; - layout_level < layout->n_levels && keycodes->len == 0; - layout_level++) - { - FindKeysymData search_data = (FindKeysymData) { - .keycodes = keycodes, - .keysym = keysym, - .layout = layout->index, - .level = layout_level - }; - xkb_keymap_key_for_each (layout->keymap, - get_keycodes_for_keysym_iter, - &search_data); - } -} - -/* Original code from gdk_x11_keymap_get_entries_for_keyval() in - * gdkkeys-x11.c */ -static void -get_keycodes_for_keysym (MetaKeyBindingManager *keys, - int keysym, - MetaResolvedKeyCombo *resolved_combo) -{ - unsigned int i; - GArray *keycodes; - int keycode; - - keycodes = g_array_new (FALSE, FALSE, sizeof (xkb_keysym_t)); - - /* Special-case: Fake mutter keysym */ - if (keysym == META_KEY_ABOVE_TAB) - { - keycode = KEY_GRAVE + 8; - g_array_append_val (keycodes, keycode); - goto out; - } - - for (i = 0; i < G_N_ELEMENTS (keys->active_layouts); i++) - { - MetaKeyBindingKeyboardLayout *layout = &keys->active_layouts[i]; - - if (!layout->keymap) - continue; - - add_keysym_keycodes_from_layout (keysym, layout, keycodes); - } - - out: - resolved_combo->len = keycodes->len; - resolved_combo->keycodes = - (xkb_keycode_t *) g_array_free (keycodes, - keycodes->len == 0 ? TRUE : FALSE); -} - -typedef struct _CalculateLayoutLevelsState -{ - struct xkb_keymap *keymap; - xkb_layout_index_t layout_index; - - xkb_level_index_t out_n_levels; -} CalculateLayoutLevelState; - -static void -calculate_n_layout_levels_iter (struct xkb_keymap *keymap, - xkb_keycode_t keycode, - void *data) -{ - CalculateLayoutLevelState *state = data; - xkb_level_index_t n_levels; - - n_levels = xkb_keymap_num_levels_for_key (keymap, - keycode, - state->layout_index); - - state->out_n_levels = MAX (n_levels, state->out_n_levels); -} - -static xkb_level_index_t -calculate_n_layout_levels (struct xkb_keymap *keymap, - xkb_layout_index_t layout_index) - -{ - CalculateLayoutLevelState state = { - .keymap = keymap, - .layout_index = layout_index, - - .out_n_levels = 0 - }; - - xkb_keymap_key_for_each (keymap, calculate_n_layout_levels_iter, &state); - - return state.out_n_levels; -} - -static void -reload_iso_next_group_combos (MetaKeyBindingManager *keys) -{ - const char *iso_next_group_option; - int i; - - for (i = 0; i < keys->n_iso_next_group_combos; i++) - resolved_key_combo_reset (&keys->iso_next_group_combo[i]); - - keys->n_iso_next_group_combos = 0; - - iso_next_group_option = meta_prefs_get_iso_next_group_option (); - if (iso_next_group_option == NULL) - return; - - get_keycodes_for_keysym (keys, XKB_KEY_ISO_Next_Group, keys->iso_next_group_combo); - - if (keys->iso_next_group_combo[0].len == 0) - return; - - keys->n_iso_next_group_combos = 1; - - if (g_str_equal (iso_next_group_option, "toggle") || - g_str_equal (iso_next_group_option, "lalt_toggle") || - g_str_equal (iso_next_group_option, "lwin_toggle") || - g_str_equal (iso_next_group_option, "rwin_toggle") || - g_str_equal (iso_next_group_option, "lshift_toggle") || - g_str_equal (iso_next_group_option, "rshift_toggle") || - g_str_equal (iso_next_group_option, "lctrl_toggle") || - g_str_equal (iso_next_group_option, "rctrl_toggle") || - g_str_equal (iso_next_group_option, "sclk_toggle") || - g_str_equal (iso_next_group_option, "menu_toggle") || - g_str_equal (iso_next_group_option, "caps_toggle")) - { - keys->iso_next_group_combo[0].mask = 0; - } - else if (g_str_equal (iso_next_group_option, "shift_caps_toggle") || - g_str_equal (iso_next_group_option, "shifts_toggle")) - { - keys->iso_next_group_combo[0].mask = ShiftMask; - } - else if (g_str_equal (iso_next_group_option, "alt_caps_toggle") || - g_str_equal (iso_next_group_option, "alt_space_toggle")) - { - keys->iso_next_group_combo[0].mask = Mod1Mask; - } - else if (g_str_equal (iso_next_group_option, "ctrl_shift_toggle") || - g_str_equal (iso_next_group_option, "lctrl_lshift_toggle") || - g_str_equal (iso_next_group_option, "rctrl_rshift_toggle")) - { - resolved_key_combo_copy (&keys->iso_next_group_combo[0], - &keys->iso_next_group_combo[1]); - - keys->iso_next_group_combo[0].mask = ShiftMask; - keys->iso_next_group_combo[1].mask = ControlMask; - keys->n_iso_next_group_combos = 2; - } - else if (g_str_equal (iso_next_group_option, "ctrl_alt_toggle")) - { - resolved_key_combo_copy (&keys->iso_next_group_combo[0], - &keys->iso_next_group_combo[1]); - - keys->iso_next_group_combo[0].mask = Mod1Mask; - keys->iso_next_group_combo[1].mask = ControlMask; - keys->n_iso_next_group_combos = 2; - } - else if (g_str_equal (iso_next_group_option, "alt_shift_toggle") || - g_str_equal (iso_next_group_option, "lalt_lshift_toggle")) - { - resolved_key_combo_copy (&keys->iso_next_group_combo[0], - &keys->iso_next_group_combo[1]); - - keys->iso_next_group_combo[0].mask = Mod1Mask; - keys->iso_next_group_combo[1].mask = ShiftMask; - keys->n_iso_next_group_combos = 2; - } - else - { - resolved_key_combo_reset (keys->iso_next_group_combo); - keys->n_iso_next_group_combos = 0; - } -} - -static void -devirtualize_modifiers (MetaKeyBindingManager *keys, - MetaVirtualModifier modifiers, - unsigned int *mask) -{ - *mask = 0; - - if (modifiers & META_VIRTUAL_SHIFT_MASK) - *mask |= ShiftMask; - if (modifiers & META_VIRTUAL_CONTROL_MASK) - *mask |= ControlMask; - if (modifiers & META_VIRTUAL_ALT_MASK) - *mask |= Mod1Mask; - if (modifiers & META_VIRTUAL_META_MASK) - *mask |= keys->meta_mask; - if (modifiers & META_VIRTUAL_HYPER_MASK) - *mask |= keys->hyper_mask; - if (modifiers & META_VIRTUAL_SUPER_MASK) - *mask |= keys->super_mask; - if (modifiers & META_VIRTUAL_MOD2_MASK) - *mask |= Mod2Mask; - if (modifiers & META_VIRTUAL_MOD3_MASK) - *mask |= Mod3Mask; - if (modifiers & META_VIRTUAL_MOD4_MASK) - *mask |= Mod4Mask; - if (modifiers & META_VIRTUAL_MOD5_MASK) - *mask |= Mod5Mask; -} - -static void -index_binding (MetaKeyBindingManager *keys, - MetaKeyBinding *binding) -{ - int i; - - for (i = 0; i < binding->resolved_combo.len; i++) - { - MetaKeyBinding *existing; - guint32 index_key; - - index_key = key_combo_key (&binding->resolved_combo, i); - - existing = g_hash_table_lookup (keys->key_bindings_index, - GINT_TO_POINTER (index_key)); - if (existing != NULL) - { - /* Overwrite already indexed keycodes only for the first - * keycode, i.e. we give those primary keycodes precedence - * over non-first ones. */ - if (i > 0) - continue; - - meta_warning ("Overwriting existing binding of keysym %x" - " with keysym %x (keycode %x).", - binding->combo.keysym, - existing->combo.keysym, - binding->resolved_combo.keycodes[i]); - } - - g_hash_table_replace (keys->key_bindings_index, - GINT_TO_POINTER (index_key), binding); - } -} - -static void -resolve_key_combo (MetaKeyBindingManager *keys, - MetaKeyCombo *combo, - MetaResolvedKeyCombo *resolved_combo) -{ - - resolved_key_combo_reset (resolved_combo); - - if (combo->keysym != 0) - { - get_keycodes_for_keysym (keys, combo->keysym, resolved_combo); - } - else if (combo->keycode != 0) - { - resolved_combo->keycodes = g_new0 (xkb_keycode_t, 1); - resolved_combo->keycodes[0] = combo->keycode; - resolved_combo->len = 1; - } - - devirtualize_modifiers (keys, combo->modifiers, &resolved_combo->mask); -} - -static void -binding_reload_combos_foreach (gpointer key, - gpointer value, - gpointer data) -{ - MetaKeyBindingManager *keys = data; - MetaKeyBinding *binding = value; - - resolve_key_combo (keys, &binding->combo, &binding->resolved_combo); - index_binding (keys, binding); -} - -typedef struct _FindLatinKeysymsState -{ - MetaKeyBindingKeyboardLayout *layout; - gboolean *required_keysyms_found; - int n_required_keysyms; -} FindLatinKeysymsState; - -static void -find_latin_keysym (struct xkb_keymap *keymap, - xkb_keycode_t key, - void *data) -{ - FindLatinKeysymsState *state = data; - int n_keysyms, i; - const xkb_keysym_t *keysyms; - - n_keysyms = xkb_keymap_key_get_syms_by_level (state->layout->keymap, - key, - state->layout->index, - 0, - &keysyms); - for (i = 0; i < n_keysyms; i++) - { - xkb_keysym_t keysym = keysyms[i]; - - if (keysym >= XKB_KEY_a && keysym <= XKB_KEY_z) - { - unsigned int keysym_index = keysym - XKB_KEY_a; - - if (!state->required_keysyms_found[keysym_index]) - { - state->required_keysyms_found[keysym_index] = TRUE; - state->n_required_keysyms--; - } - } - } -} - -static gboolean -needs_secondary_layout (MetaKeyBindingKeyboardLayout *layout) -{ - gboolean required_keysyms_found[] = { - FALSE, /* XKB_KEY_a */ - FALSE, /* XKB_KEY_b */ - FALSE, /* XKB_KEY_c */ - FALSE, /* XKB_KEY_d */ - FALSE, /* XKB_KEY_e */ - FALSE, /* XKB_KEY_f */ - FALSE, /* XKB_KEY_g */ - FALSE, /* XKB_KEY_h */ - FALSE, /* XKB_KEY_i */ - FALSE, /* XKB_KEY_j */ - FALSE, /* XKB_KEY_k */ - FALSE, /* XKB_KEY_l */ - FALSE, /* XKB_KEY_m */ - FALSE, /* XKB_KEY_n */ - FALSE, /* XKB_KEY_o */ - FALSE, /* XKB_KEY_p */ - FALSE, /* XKB_KEY_q */ - FALSE, /* XKB_KEY_r */ - FALSE, /* XKB_KEY_s */ - FALSE, /* XKB_KEY_t */ - FALSE, /* XKB_KEY_u */ - FALSE, /* XKB_KEY_v */ - FALSE, /* XKB_KEY_w */ - FALSE, /* XKB_KEY_x */ - FALSE, /* XKB_KEY_y */ - FALSE, /* XKB_KEY_z */ - }; - FindLatinKeysymsState state = { - .layout = layout, - .required_keysyms_found = required_keysyms_found, - .n_required_keysyms = G_N_ELEMENTS (required_keysyms_found), - }; - - xkb_keymap_key_for_each (layout->keymap, find_latin_keysym, &state); - - return state.n_required_keysyms != 0; -} - -static void -clear_active_keyboard_layouts (MetaKeyBindingManager *keys) -{ - unsigned int i; - - for (i = 0; i < G_N_ELEMENTS (keys->active_layouts); i++) - { - MetaKeyBindingKeyboardLayout *layout = &keys->active_layouts[i]; - - g_clear_pointer (&layout->keymap, xkb_keymap_unref); - *layout = (MetaKeyBindingKeyboardLayout) { 0 }; - } -} - -static MetaKeyBindingKeyboardLayout -create_us_layout (void) -{ - struct xkb_rule_names names; - struct xkb_keymap *keymap; - struct xkb_context *context; - - names.rules = DEFAULT_XKB_RULES_FILE; - names.model = DEFAULT_XKB_MODEL; - names.layout = "us"; - names.variant = ""; - names.options = ""; - - context = meta_create_xkb_context (); - keymap = xkb_keymap_new_from_names (context, &names, XKB_KEYMAP_COMPILE_NO_FLAGS); - xkb_context_unref (context); - - return (MetaKeyBindingKeyboardLayout) { - .keymap = keymap, - .n_levels = calculate_n_layout_levels (keymap, 0), - }; -} - -static void -reload_active_keyboard_layouts (MetaKeyBindingManager *keys) -{ - struct xkb_keymap *keymap; - xkb_layout_index_t layout_index; - MetaKeyBindingKeyboardLayout primary_layout; - - clear_active_keyboard_layouts (keys); - - keymap = meta_backend_get_keymap (keys->backend); - layout_index = meta_backend_get_keymap_layout_group (keys->backend); - primary_layout = (MetaKeyBindingKeyboardLayout) { - .keymap = xkb_keymap_ref (keymap), - .index = layout_index, - .n_levels = calculate_n_layout_levels (keymap, layout_index), - }; - - keys->active_layouts[META_KEY_BINDING_PRIMARY_LAYOUT] = primary_layout; - - if (needs_secondary_layout (&primary_layout)) - { - MetaKeyBindingKeyboardLayout us_layout; - - us_layout = create_us_layout (); - keys->active_layouts[META_KEY_BINDING_SECONDARY_LAYOUT] = us_layout; - } -} - -static void -reload_combos (MetaKeyBindingManager *keys) -{ - g_hash_table_remove_all (keys->key_bindings_index); - - reload_active_keyboard_layouts (keys); - - resolve_key_combo (keys, - &keys->overlay_key_combo, - &keys->overlay_resolved_key_combo); - - resolve_key_combo (keys, - &keys->locate_pointer_key_combo, - &keys->locate_pointer_resolved_key_combo); - - reload_iso_next_group_combos (keys); - - g_hash_table_foreach (keys->key_bindings, binding_reload_combos_foreach, keys); -} - -static void -rebuild_binding_table (MetaKeyBindingManager *keys, - GList *prefs, - GList *grabs) -{ - MetaKeyBinding *b; - GList *p, *g; - - g_hash_table_remove_all (keys->key_bindings); - - p = prefs; - while (p) - { - MetaKeyPref *pref = (MetaKeyPref*)p->data; - GSList *tmp = pref->combos; - - while (tmp) - { - MetaKeyCombo *combo = tmp->data; - - if (combo && (combo->keysym != None || combo->keycode != 0)) - { - MetaKeyHandler *handler = HANDLER (pref->name); - - b = g_new0 (MetaKeyBinding, 1); - b->name = pref->name; - b->handler = handler; - b->flags = handler->flags; - b->combo = *combo; - - g_hash_table_add (keys->key_bindings, b); - } - - tmp = tmp->next; - } - - p = p->next; - } - - g = grabs; - while (g) - { - MetaKeyGrab *grab = (MetaKeyGrab*)g->data; - if (grab->combo.keysym != None || grab->combo.keycode != 0) - { - MetaKeyHandler *handler = HANDLER ("external-grab"); - - b = g_new0 (MetaKeyBinding, 1); - b->name = grab->name; - b->handler = handler; - b->flags = grab->flags; - b->combo = grab->combo; - - g_hash_table_add (keys->key_bindings, b); - } - - g = g->next; - } - - meta_topic (META_DEBUG_KEYBINDINGS, - " %d bindings in table", - g_hash_table_size (keys->key_bindings)); -} - -static void -rebuild_key_binding_table (MetaKeyBindingManager *keys) -{ - GList *prefs, *grabs; - - meta_topic (META_DEBUG_KEYBINDINGS, - "Rebuilding key binding table from preferences"); - - prefs = meta_prefs_get_keybindings (); - grabs = g_hash_table_get_values (external_grabs); - rebuild_binding_table (keys, prefs, grabs); - g_list_free (prefs); - g_list_free (grabs); -} - -static void -rebuild_special_bindings (MetaKeyBindingManager *keys) -{ - MetaKeyCombo combo; - - meta_prefs_get_overlay_binding (&combo); - keys->overlay_key_combo = combo; - - meta_prefs_get_locate_pointer_binding (&combo); - keys->locate_pointer_key_combo = combo; -} - -static void -ungrab_key_bindings (MetaDisplay *display) -{ - GSList *windows, *l; - - if (display->x11_display) - meta_x11_display_ungrab_keys (display->x11_display); - - windows = meta_display_list_windows (display, META_LIST_DEFAULT); - for (l = windows; l; l = l->next) - { - MetaWindow *w = l->data; - meta_window_ungrab_keys (w); - } - - g_slist_free (windows); -} - -static void -grab_key_bindings (MetaDisplay *display) -{ - GSList *windows, *l; - - if (display->x11_display) - meta_x11_display_grab_keys (display->x11_display); - - windows = meta_display_list_windows (display, META_LIST_DEFAULT); - for (l = windows; l; l = l->next) - { - MetaWindow *w = l->data; - meta_window_grab_keys (w); - } - - g_slist_free (windows); -} - -static MetaKeyBinding * -get_keybinding (MetaKeyBindingManager *keys, - MetaResolvedKeyCombo *resolved_combo) -{ - MetaKeyBinding *binding = NULL; - int i; - - for (i = 0; i < resolved_combo->len; i++) - { - guint32 key; - - key = key_combo_key (resolved_combo, i); - binding = g_hash_table_lookup (keys->key_bindings_index, - GINT_TO_POINTER (key)); - - if (binding != NULL) - break; - } - - return binding; -} - -static guint -next_dynamic_keybinding_action (void) -{ - static guint num_dynamic_bindings = 0; - return META_KEYBINDING_ACTION_LAST + (++num_dynamic_bindings); -} - -static gboolean -add_keybinding_internal (MetaDisplay *display, - const char *name, - GSettings *settings, - MetaKeyBindingFlags flags, - MetaKeyBindingAction action, - MetaKeyHandlerFunc func, - int data, - gpointer user_data, - GDestroyNotify free_data) -{ - MetaKeyHandler *handler; - - if (!meta_prefs_add_keybinding (name, settings, action, flags)) - return FALSE; - - handler = g_new0 (MetaKeyHandler, 1); - handler->name = g_strdup (name); - handler->func = func; - handler->default_func = func; - handler->data = data; - handler->flags = flags; - handler->user_data = user_data; - handler->user_data_free_func = free_data; - - g_hash_table_insert (key_handlers, g_strdup (name), handler); - - return TRUE; -} - -static gboolean -add_builtin_keybinding (MetaDisplay *display, - const char *name, - GSettings *settings, - MetaKeyBindingFlags flags, - MetaKeyBindingAction action, - MetaKeyHandlerFunc handler, - int handler_arg) -{ - return add_keybinding_internal (display, name, settings, - flags | META_KEY_BINDING_BUILTIN, - action, handler, handler_arg, NULL, NULL); -} - -/** - * meta_display_add_keybinding: - * @display: a #MetaDisplay - * @name: the binding's name - * @settings: the #GSettings object where @name is stored - * @flags: flags to specify binding details - * @handler: function to run when the keybinding is invoked - * @user_data: the data to pass to @handler - * @free_data: function to free @user_data - * - * Add a keybinding at runtime. The key @name in @schema needs to be of - * type %G_VARIANT_TYPE_STRING_ARRAY, with each string describing a - * keybinding in the form of "<Control>a" or "<Shift><Alt>F1". The parser - * is fairly liberal and allows lower or upper case, and also abbreviations - * such as "<Ctl>" and "<Ctrl>". If the key is set to the empty list or a - * list with a single element of either "" or "disabled", the keybinding is - * disabled. - * - * Use meta_display_remove_keybinding() to remove the binding. - * - * Returns: the corresponding keybinding action if the keybinding was - * added successfully, otherwise %META_KEYBINDING_ACTION_NONE - */ -guint -meta_display_add_keybinding (MetaDisplay *display, - const char *name, - GSettings *settings, - MetaKeyBindingFlags flags, - MetaKeyHandlerFunc handler, - gpointer user_data, - GDestroyNotify free_data) -{ - guint new_action = next_dynamic_keybinding_action (); - - if (!add_keybinding_internal (display, name, settings, flags, new_action, - handler, 0, user_data, free_data)) - return META_KEYBINDING_ACTION_NONE; - - return new_action; -} - -/** - * meta_display_remove_keybinding: - * @display: the #MetaDisplay - * @name: name of the keybinding to remove - * - * Remove keybinding @name; the function will fail if @name is not a known - * keybinding or has not been added with meta_display_add_keybinding(). - * - * Returns: %TRUE if the binding has been removed successfully, - * otherwise %FALSE - */ -gboolean -meta_display_remove_keybinding (MetaDisplay *display, - const char *name) -{ - if (!meta_prefs_remove_keybinding (name)) - return FALSE; - - g_hash_table_remove (key_handlers, name); - - return TRUE; -} - -static guint -get_keybinding_action (MetaKeyBindingManager *keys, - MetaResolvedKeyCombo *resolved_combo) -{ - MetaKeyBinding *binding; - - /* This is much more vague than the MetaDisplay::overlay-key signal, - * which is only emitted if the overlay-key is the only key pressed; - * as this method is primarily intended for plugins to allow processing - * of mutter keybindings while holding a grab, the overlay-key-only-pressed - * tracking is left to the plugin here. - */ - if (resolved_key_combo_intersect (resolved_combo, - &keys->overlay_resolved_key_combo)) - return META_KEYBINDING_ACTION_OVERLAY_KEY; - - if (resolved_key_combo_intersect (resolved_combo, - &keys->locate_pointer_resolved_key_combo)) - return META_KEYBINDING_ACTION_LOCATE_POINTER_KEY; - - binding = get_keybinding (keys, resolved_combo); - if (binding) - { - MetaKeyGrab *grab = g_hash_table_lookup (external_grabs, binding->name); - if (grab) - return grab->action; - else - return (guint) meta_prefs_get_keybinding_action (binding->name); - } - else - { - return META_KEYBINDING_ACTION_NONE; - } -} - -static xkb_mod_mask_t -mask_from_event_params (MetaKeyBindingManager *keys, - unsigned long mask) -{ - return mask & 0xff & ~keys->ignored_modifier_mask; -} - -/** - * meta_display_get_keybinding_action: - * @display: A #MetaDisplay - * @keycode: Raw keycode - * @mask: Event mask - * - * Get the keybinding action bound to @keycode. Builtin keybindings - * have a fixed associated #MetaKeyBindingAction, for bindings added - * dynamically the function will return the keybinding action - * meta_display_add_keybinding() returns on registration. - * - * Returns: The action that should be taken for the given key, or - * %META_KEYBINDING_ACTION_NONE. - */ -guint -meta_display_get_keybinding_action (MetaDisplay *display, - unsigned int keycode, - unsigned long mask) -{ - MetaKeyBindingManager *keys = &display->key_binding_manager; - xkb_keycode_t code = (xkb_keycode_t) keycode; - MetaResolvedKeyCombo resolved_combo = { &code, 1 }; - - resolved_combo.mask = mask_from_event_params (keys, mask); - return get_keybinding_action (keys, &resolved_combo); -} - -static void -reload_keybindings (MetaDisplay *display) -{ - MetaKeyBindingManager *keys = &display->key_binding_manager; - - ungrab_key_bindings (display); - - /* Deciphering the modmap depends on the loaded keysyms to find out - * what modifiers is Super and so forth, so we need to reload it - * even when only the keymap changes */ - reload_modmap (keys); - - reload_combos (keys); - - grab_key_bindings (display); -} - -static GArray * -calc_grab_modifiers (MetaKeyBindingManager *keys, - unsigned int modmask) -{ - unsigned int ignored_mask; - XIGrabModifiers mods; - GArray *mods_array = g_array_new (FALSE, TRUE, sizeof (XIGrabModifiers)); - - /* The X server crashes if XIAnyModifier gets passed in with any - other bits. It doesn't make sense to ask for a grab of - XIAnyModifier plus other bits anyway so we avoid that. */ - if (modmask & XIAnyModifier) - { - mods = (XIGrabModifiers) { XIAnyModifier, 0 }; - g_array_append_val (mods_array, mods); - return mods_array; - } - - mods = (XIGrabModifiers) { modmask, 0 }; - g_array_append_val (mods_array, mods); - - for (ignored_mask = 1; - ignored_mask <= keys->ignored_modifier_mask; - ++ignored_mask) - { - if (ignored_mask & keys->ignored_modifier_mask) - { - mods = (XIGrabModifiers) { modmask | ignored_mask, 0 }; - g_array_append_val (mods_array, mods); - } - } - - return mods_array; -} - -static void -meta_change_button_grab (MetaKeyBindingManager *keys, - Window xwindow, - gboolean grab, - gboolean sync, - int button, - int modmask) -{ - if (meta_is_wayland_compositor ()) - return; - - MetaBackendX11 *backend = META_BACKEND_X11 (keys->backend); - Display *xdisplay = meta_backend_x11_get_xdisplay (backend); - - unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 }; - XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits }; - GArray *mods; - - XISetMask (mask.mask, XI_ButtonPress); - XISetMask (mask.mask, XI_ButtonRelease); - XISetMask (mask.mask, XI_Motion); - - mods = calc_grab_modifiers (keys, modmask); - - /* GrabModeSync means freeze until XAllowEvents */ - if (grab) - XIGrabButton (xdisplay, - META_VIRTUAL_CORE_POINTER_ID, - button, xwindow, None, - sync ? XIGrabModeSync : XIGrabModeAsync, - XIGrabModeAsync, False, - &mask, mods->len, (XIGrabModifiers *)mods->data); - else - XIUngrabButton (xdisplay, - META_VIRTUAL_CORE_POINTER_ID, - button, xwindow, mods->len, (XIGrabModifiers *)mods->data); - - g_array_free (mods, TRUE); -} - -ClutterModifierType -meta_display_get_compositor_modifiers (MetaDisplay *display) -{ - MetaKeyBindingManager *keys = &display->key_binding_manager; - return keys->window_grab_modifiers; -} - -static void -meta_change_buttons_grab (MetaKeyBindingManager *keys, - Window xwindow, - gboolean grab, - gboolean sync, - int modmask) -{ -#define MAX_BUTTON 3 - - int i; - for (i = 1; i <= MAX_BUTTON; i++) - meta_change_button_grab (keys, xwindow, grab, sync, i, modmask); -} - -void -meta_display_grab_window_buttons (MetaDisplay *display, - Window xwindow) -{ - MetaKeyBindingManager *keys = &display->key_binding_manager; - - /* Grab Alt + button1 for moving window. - * Grab Alt + button2 for resizing window. - * Grab Alt + button3 for popping up window menu. - * Grab Alt + Shift + button1 for snap-moving window. - */ - meta_verbose ("Grabbing window buttons for 0x%lx", xwindow); - - /* FIXME If we ignored errors here instead of spewing, we could - * put one big error trap around the loop and avoid a bunch of - * XSync() - */ - - if (keys->window_grab_modifiers != 0) - { - meta_change_buttons_grab (keys, xwindow, TRUE, FALSE, - keys->window_grab_modifiers); - - /* In addition to grabbing Alt+Button1 for moving the window, - * grab Alt+Shift+Button1 for snap-moving the window. See bug - * 112478. Unfortunately, this doesn't work with - * Shift+Alt+Button1 for some reason; so at least part of the - * order still matters, which sucks (please FIXME). - */ - meta_change_button_grab (keys, xwindow, - TRUE, - FALSE, - 1, keys->window_grab_modifiers | ShiftMask); - } -} - -void -meta_display_ungrab_window_buttons (MetaDisplay *display, - Window xwindow) -{ - MetaKeyBindingManager *keys = &display->key_binding_manager; - - if (keys->window_grab_modifiers == 0) - return; - - meta_change_buttons_grab (keys, xwindow, FALSE, FALSE, - keys->window_grab_modifiers); -} - -static void -update_window_grab_modifiers (MetaDisplay *display) -{ - MetaKeyBindingManager *keys = &display->key_binding_manager; - MetaVirtualModifier virtual_mods; - unsigned int mods; - - virtual_mods = meta_prefs_get_mouse_button_mods (); - devirtualize_modifiers (keys, virtual_mods, &mods); - - if (keys->window_grab_modifiers != mods) - { - keys->window_grab_modifiers = mods; - g_object_notify (G_OBJECT (display), "compositor-modifiers"); - } -} - -void -meta_display_grab_focus_window_button (MetaDisplay *display, - MetaWindow *window) -{ - MetaKeyBindingManager *keys = &display->key_binding_manager; - - /* Grab button 1 for activating unfocused windows */ - meta_verbose ("Grabbing unfocused window buttons for %s", window->desc); - - if (window->have_focus_click_grab) - { - meta_verbose (" (well, not grabbing since we already have the grab)"); - return; - } - - /* FIXME If we ignored errors here instead of spewing, we could - * put one big error trap around the loop and avoid a bunch of - * XSync() - */ - - meta_change_buttons_grab (keys, window->xwindow, TRUE, TRUE, XIAnyModifier); - window->have_focus_click_grab = TRUE; -} - -void -meta_display_ungrab_focus_window_button (MetaDisplay *display, - MetaWindow *window) -{ - MetaKeyBindingManager *keys = &display->key_binding_manager; - - meta_verbose ("Ungrabbing unfocused window buttons for %s", window->desc); - - if (!window->have_focus_click_grab) - return; - - meta_change_buttons_grab (keys, window->xwindow, FALSE, FALSE, XIAnyModifier); - window->have_focus_click_grab = FALSE; -} - -static void -prefs_changed_callback (MetaPreference pref, - void *data) -{ - MetaDisplay *display = data; - MetaKeyBindingManager *keys = &display->key_binding_manager; - - switch (pref) - { - case META_PREF_LOCATE_POINTER: - maybe_update_locate_pointer_keygrab (display, - meta_prefs_is_locate_pointer_enabled()); - break; - case META_PREF_KEYBINDINGS: - ungrab_key_bindings (display); - rebuild_key_binding_table (keys); - rebuild_special_bindings (keys); - reload_combos (keys); - grab_key_bindings (display); - break; - case META_PREF_MOUSE_BUTTON_MODS: - { - GSList *windows, *l; - windows = meta_display_list_windows (display, META_LIST_DEFAULT); - - for (l = windows; l; l = l->next) - { - MetaWindow *w = l->data; - meta_display_ungrab_window_buttons (display, w->xwindow); - } - - update_window_grab_modifiers (display); - - for (l = windows; l; l = l->next) - { - MetaWindow *w = l->data; - if (w->type != META_WINDOW_DOCK) - meta_display_grab_window_buttons (display, w->xwindow); - } - - g_slist_free (windows); - } - default: - break; - } -} - - -void -meta_display_shutdown_keys (MetaDisplay *display) -{ - MetaKeyBindingManager *keys = &display->key_binding_manager; - - meta_prefs_remove_listener (prefs_changed_callback, display); - - g_hash_table_destroy (keys->key_bindings_index); - g_hash_table_destroy (keys->key_bindings); - - clear_active_keyboard_layouts (keys); -} - -/* Grab/ungrab, ignoring all annoying modifiers like NumLock etc. */ -static void -meta_change_keygrab (MetaKeyBindingManager *keys, - Window xwindow, - gboolean grab, - MetaResolvedKeyCombo *resolved_combo) -{ - unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 }; - XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits }; - - XISetMask (mask.mask, XI_KeyPress); - XISetMask (mask.mask, XI_KeyRelease); - - if (meta_is_wayland_compositor ()) - return; - - MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ()); - Display *xdisplay = meta_backend_x11_get_xdisplay (backend); - GArray *mods; - int i; - - /* Grab keycode/modmask, together with - * all combinations of ignored modifiers. - * X provides no better way to do this. - */ - - mods = calc_grab_modifiers (keys, resolved_combo->mask); - - for (i = 0; i < resolved_combo->len; i++) - { - xkb_keycode_t keycode = resolved_combo->keycodes[i]; - - meta_topic (META_DEBUG_KEYBINDINGS, - "%s keybinding keycode %d mask 0x%x on 0x%lx", - grab ? "Grabbing" : "Ungrabbing", - keycode, resolved_combo->mask, xwindow); - - if (grab) - XIGrabKeycode (xdisplay, - META_VIRTUAL_CORE_KEYBOARD_ID, - keycode, xwindow, - XIGrabModeSync, XIGrabModeAsync, - False, &mask, mods->len, (XIGrabModifiers *)mods->data); - else - XIUngrabKeycode (xdisplay, - META_VIRTUAL_CORE_KEYBOARD_ID, - keycode, xwindow, - mods->len, (XIGrabModifiers *)mods->data); - } - - g_array_free (mods, TRUE); -} - -typedef struct -{ - MetaKeyBindingManager *keys; - Window xwindow; - gboolean only_per_window; - gboolean grab; -} ChangeKeygrabData; - -static void -change_keygrab_foreach (gpointer key, - gpointer value, - gpointer user_data) -{ - ChangeKeygrabData *data = user_data; - MetaKeyBinding *binding = value; - gboolean binding_is_per_window = (binding->flags & META_KEY_BINDING_PER_WINDOW) != 0; - - if (data->only_per_window != binding_is_per_window) - return; - - /* Ignore the key bindings marked as META_KEY_BINDING_NO_AUTO_GRAB, - * those are handled separately - */ - if (binding->flags & META_KEY_BINDING_NO_AUTO_GRAB) - return; - - if (binding->resolved_combo.len == 0) - return; - - meta_change_keygrab (data->keys, data->xwindow, data->grab, &binding->resolved_combo); -} - -static void -change_binding_keygrabs (MetaKeyBindingManager *keys, - Window xwindow, - gboolean only_per_window, - gboolean grab) -{ - ChangeKeygrabData data; - - data.keys = keys; - data.xwindow = xwindow; - data.only_per_window = only_per_window; - data.grab = grab; - - g_hash_table_foreach (keys->key_bindings, change_keygrab_foreach, &data); -} - -static void -maybe_update_locate_pointer_keygrab (MetaDisplay *display, - gboolean grab) -{ - MetaKeyBindingManager *keys = &display->key_binding_manager; - - if (!display->x11_display) - return; - - if (keys->locate_pointer_resolved_key_combo.len != 0) - meta_change_keygrab (keys, display->x11_display->xroot, - (!!grab & !!meta_prefs_is_locate_pointer_enabled()), - &keys->locate_pointer_resolved_key_combo); -} - -static void -meta_x11_display_change_keygrabs (MetaX11Display *x11_display, - gboolean grab) -{ - MetaKeyBindingManager *keys = &x11_display->display->key_binding_manager; - int i; - - if (keys->overlay_resolved_key_combo.len != 0) - meta_change_keygrab (keys, x11_display->xroot, - grab, &keys->overlay_resolved_key_combo); - - maybe_update_locate_pointer_keygrab (x11_display->display, grab); - - for (i = 0; i < keys->n_iso_next_group_combos; i++) - meta_change_keygrab (keys, x11_display->xroot, - grab, &keys->iso_next_group_combo[i]); - - change_binding_keygrabs (keys, x11_display->xroot, - FALSE, grab); -} - -void -meta_x11_display_grab_keys (MetaX11Display *x11_display) -{ - if (x11_display->keys_grabbed) - return; - - meta_x11_display_change_keygrabs (x11_display, TRUE); - - x11_display->keys_grabbed = TRUE; -} - -void -meta_x11_display_ungrab_keys (MetaX11Display *x11_display) -{ - if (!x11_display->keys_grabbed) - return; - - meta_x11_display_change_keygrabs (x11_display, FALSE); - - x11_display->keys_grabbed = FALSE; -} - -static void -change_window_keygrabs (MetaKeyBindingManager *keys, - Window xwindow, - gboolean grab) -{ - change_binding_keygrabs (keys, xwindow, TRUE, grab); -} - -void -meta_window_grab_keys (MetaWindow *window) -{ - MetaDisplay *display = window->display; - MetaKeyBindingManager *keys = &display->key_binding_manager; - - if (meta_is_wayland_compositor ()) - return; - if (window->all_keys_grabbed) - return; - - if (window->type == META_WINDOW_DOCK - || window->override_redirect) - { - if (window->keys_grabbed) - change_window_keygrabs (keys, window->xwindow, FALSE); - window->keys_grabbed = FALSE; - return; - } - - if (window->keys_grabbed) - { - if (window->frame && !window->grab_on_frame) - change_window_keygrabs (keys, window->xwindow, FALSE); - else if (window->frame == NULL && - window->grab_on_frame) - ; /* continue to regrab on client window */ - else - return; /* already all good */ - } - - change_window_keygrabs (keys, - meta_window_x11_get_toplevel_xwindow (window), - TRUE); - - window->keys_grabbed = TRUE; - window->grab_on_frame = window->frame != NULL; -} - -void -meta_window_ungrab_keys (MetaWindow *window) -{ - if (!meta_is_wayland_compositor () && window->keys_grabbed) - { - MetaDisplay *display = window->display; - MetaKeyBindingManager *keys = &display->key_binding_manager; - - if (window->grab_on_frame && - window->frame != NULL) - change_window_keygrabs (keys, window->frame->xwindow, FALSE); - else if (!window->grab_on_frame) - change_window_keygrabs (keys, window->xwindow, FALSE); - - window->keys_grabbed = FALSE; - } -} - -static void -handle_external_grab (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer user_data) -{ - MetaKeyBindingManager *keys = &display->key_binding_manager; - guint action = get_keybinding_action (keys, &binding->resolved_combo); - meta_display_accelerator_activate (display, action, event); -} - - -guint -meta_display_grab_accelerator (MetaDisplay *display, - const char *accelerator, - MetaKeyBindingFlags flags) -{ - MetaKeyBindingManager *keys = &display->key_binding_manager; - MetaKeyBinding *binding; - MetaKeyGrab *grab; - MetaKeyCombo combo = { 0 }; - MetaResolvedKeyCombo resolved_combo = { NULL, 0 }; - - if (!meta_parse_accelerator (accelerator, &combo)) - { - meta_topic (META_DEBUG_KEYBINDINGS, - "Failed to parse accelerator"); - meta_warning ("\"%s\" is not a valid accelerator", accelerator); - - return META_KEYBINDING_ACTION_NONE; - } - - resolve_key_combo (keys, &combo, &resolved_combo); - - if (resolved_combo.len == 0) - return META_KEYBINDING_ACTION_NONE; - - if (get_keybinding (keys, &resolved_combo)) - { - resolved_key_combo_reset (&resolved_combo); - return META_KEYBINDING_ACTION_NONE; - } - - if (!meta_is_wayland_compositor ()) - { - meta_change_keygrab (keys, display->x11_display->xroot, - TRUE, &resolved_combo); - } - - grab = g_new0 (MetaKeyGrab, 1); - grab->action = next_dynamic_keybinding_action (); - grab->name = meta_external_binding_name_for_action (grab->action); - grab->combo = combo; - grab->flags = flags; - - g_hash_table_insert (external_grabs, grab->name, grab); - - binding = g_new0 (MetaKeyBinding, 1); - binding->name = grab->name; - binding->handler = HANDLER ("external-grab"); - binding->combo = combo; - binding->resolved_combo = resolved_combo; - binding->flags = flags; - - g_hash_table_add (keys->key_bindings, binding); - index_binding (keys, binding); - - return grab->action; -} - -gboolean -meta_display_ungrab_accelerator (MetaDisplay *display, - guint action) -{ - MetaKeyBindingManager *keys = &display->key_binding_manager; - MetaKeyBinding *binding; - MetaKeyGrab *grab; - g_autofree char *key = NULL; - MetaResolvedKeyCombo resolved_combo = { NULL, 0 }; - - g_return_val_if_fail (action != META_KEYBINDING_ACTION_NONE, FALSE); - - key = meta_external_binding_name_for_action (action); - grab = g_hash_table_lookup (external_grabs, key); - if (!grab) - return FALSE; - - resolve_key_combo (keys, &grab->combo, &resolved_combo); - binding = get_keybinding (keys, &resolved_combo); - if (binding) - { - int i; - - if (!meta_is_wayland_compositor ()) - { - meta_change_keygrab (keys, display->x11_display->xroot, - FALSE, &binding->resolved_combo); - } - - for (i = 0; i < binding->resolved_combo.len; i++) - { - guint32 index_key = key_combo_key (&binding->resolved_combo, i); - g_hash_table_remove (keys->key_bindings_index, GINT_TO_POINTER (index_key)); - } - - g_hash_table_remove (keys->key_bindings, binding); - } - - g_hash_table_remove (external_grabs, key); - resolved_key_combo_reset (&resolved_combo); - - return TRUE; -} - -static gboolean -grab_keyboard (Window xwindow, - guint32 timestamp, - int grab_mode) -{ - int grab_status; - - unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 }; - XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits }; - - XISetMask (mask.mask, XI_KeyPress); - XISetMask (mask.mask, XI_KeyRelease); - - if (meta_is_wayland_compositor ()) - return TRUE; - - /* Grab the keyboard, so we get key releases and all key - * presses - */ - - MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ()); - Display *xdisplay = meta_backend_x11_get_xdisplay (backend); - - /* Strictly, we only need to set grab_mode on the keyboard device - * while the pointer should always be XIGrabModeAsync. Unfortunately - * there is a bug in the X server, only fixed (link below) in 1.15, - * which swaps these arguments for keyboard devices. As such, we set - * both the device and the paired device mode which works around - * that bug and also works on fixed X servers. - * - * http://cgit.freedesktop.org/xorg/xserver/commit/?id=9003399708936481083424b4ff8f18a16b88b7b3 - */ - grab_status = XIGrabDevice (xdisplay, - META_VIRTUAL_CORE_KEYBOARD_ID, - xwindow, - timestamp, - None, - grab_mode, grab_mode, - False, /* owner_events */ - &mask); - - return (grab_status == Success); -} - -static void -ungrab_keyboard (guint32 timestamp) -{ - if (meta_is_wayland_compositor ()) - return; - - MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ()); - Display *xdisplay = meta_backend_x11_get_xdisplay (backend); - - XIUngrabDevice (xdisplay, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp); -} - -gboolean -meta_window_grab_all_keys (MetaWindow *window, - guint32 timestamp) -{ - Window grabwindow; - gboolean retval = TRUE; - - if (window->all_keys_grabbed) - return FALSE; - - if (window->keys_grabbed) - meta_window_ungrab_keys (window); - - /* Make sure the window is focused, otherwise the grab - * won't do a lot of good. - */ - meta_topic (META_DEBUG_FOCUS, - "Focusing %s because we're grabbing all its keys", - window->desc); - meta_window_focus (window, timestamp); - - if (!meta_is_wayland_compositor ()) - { - grabwindow = meta_window_x11_get_toplevel_xwindow (window); - - meta_topic (META_DEBUG_KEYBINDINGS, - "Grabbing all keys on window %s", window->desc); - retval = grab_keyboard (grabwindow, timestamp, XIGrabModeAsync); - } - if (retval) - { - window->keys_grabbed = FALSE; - window->all_keys_grabbed = TRUE; - window->grab_on_frame = window->frame != NULL; - } - - return retval; -} - -void -meta_window_ungrab_all_keys (MetaWindow *window, - guint32 timestamp) -{ - if (window->all_keys_grabbed) - { - if (!meta_is_wayland_compositor()) - ungrab_keyboard (timestamp); - - window->grab_on_frame = FALSE; - window->all_keys_grabbed = FALSE; - window->keys_grabbed = FALSE; - - /* Re-establish our standard bindings */ - meta_window_grab_keys (window); - } -} - -void -meta_display_freeze_keyboard (MetaDisplay *display, guint32 timestamp) -{ - MetaBackend *backend = meta_get_backend (); - - if (!META_IS_BACKEND_X11 (backend)) - return; - - Window window = meta_backend_x11_get_xwindow (META_BACKEND_X11 (backend)); - grab_keyboard (window, timestamp, XIGrabModeSync); -} - -void -meta_display_ungrab_keyboard (MetaDisplay *display, guint32 timestamp) -{ - ungrab_keyboard (timestamp); -} - -void -meta_display_unfreeze_keyboard (MetaDisplay *display, guint32 timestamp) -{ - MetaBackend *backend = meta_get_backend (); - - if (!META_IS_BACKEND_X11 (backend)) - return; - - Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); - - XIAllowEvents (xdisplay, META_VIRTUAL_CORE_KEYBOARD_ID, - XIAsyncDevice, timestamp); - /* We shouldn't need to unfreeze the pointer device here, however we - * have to, due to the workaround we do in grab_keyboard(). - */ - XIAllowEvents (xdisplay, META_VIRTUAL_CORE_POINTER_ID, - XIAsyncDevice, timestamp); -} - -static gboolean -is_modifier (xkb_keysym_t keysym) -{ - switch (keysym) - { - case XKB_KEY_Shift_L: - case XKB_KEY_Shift_R: - case XKB_KEY_Control_L: - case XKB_KEY_Control_R: - case XKB_KEY_Caps_Lock: - case XKB_KEY_Shift_Lock: - case XKB_KEY_Meta_L: - case XKB_KEY_Meta_R: - case XKB_KEY_Alt_L: - case XKB_KEY_Alt_R: - case XKB_KEY_Super_L: - case XKB_KEY_Super_R: - case XKB_KEY_Hyper_L: - case XKB_KEY_Hyper_R: - return TRUE; - default: - return FALSE; - } -} - -static void -invoke_handler (MetaDisplay *display, - MetaKeyHandler *handler, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding) -{ - if (handler->func) - (* handler->func) (display, - handler->flags & META_KEY_BINDING_PER_WINDOW ? - window : NULL, - event, - binding, - handler->user_data); - else - (* handler->default_func) (display, - handler->flags & META_KEY_BINDING_PER_WINDOW ? - window: NULL, - event, - binding, - NULL); -} - -static gboolean -meta_key_binding_has_handler_func (MetaKeyBinding *binding) -{ - return (!!binding->handler->func || !!binding->handler->default_func); -} - -static gboolean -process_event (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event) -{ - MetaKeyBindingManager *keys = &display->key_binding_manager; - xkb_keycode_t keycode = (xkb_keycode_t) event->hardware_keycode; - MetaResolvedKeyCombo resolved_combo = { &keycode, 1 }; - MetaKeyBinding *binding; - - /* we used to have release-based bindings but no longer. */ - if (event->type == CLUTTER_KEY_RELEASE) - return FALSE; - - resolved_combo.mask = mask_from_event_params (keys, event->modifier_state); - - binding = get_keybinding (keys, &resolved_combo); - - if (!binding || - (!window && binding->flags & META_KEY_BINDING_PER_WINDOW)) - goto not_found; - - if (binding->handler == NULL) - meta_bug ("Binding %s has no handler", binding->name); - - if (!meta_key_binding_has_handler_func (binding)) - goto not_found; - - if (display->focus_window && - !(binding->handler->flags & META_KEY_BINDING_NON_MASKABLE)) - { - ClutterInputDevice *source; - - source = clutter_event_get_source_device ((ClutterEvent *) event); - if (meta_window_shortcuts_inhibited (display->focus_window, source)) - goto not_found; - } - - /* If the compositor filtered out the keybindings, that - * means they don't want the binding to trigger, so we do - * the same thing as if the binding didn't exist. */ - if (meta_compositor_filter_keybinding (display->compositor, binding)) - goto not_found; - - if (event->flags & CLUTTER_EVENT_FLAG_REPEATED && - binding->flags & META_KEY_BINDING_IGNORE_AUTOREPEAT) - { - meta_topic (META_DEBUG_KEYBINDINGS, - "Ignore autorepeat for handler %s", - binding->name); - return TRUE; - } - - meta_topic (META_DEBUG_KEYBINDINGS, - "Running handler for %s", - binding->name); - - /* Global keybindings count as a let-the-terminal-lose-focus - * due to new window mapping until the user starts - * interacting with the terminal again. - */ - display->allow_terminal_deactivation = TRUE; - - invoke_handler (display, binding->handler, window, event, binding); - - return TRUE; - - not_found: - meta_topic (META_DEBUG_KEYBINDINGS, - "No handler found for this event in this binding table"); - return FALSE; -} - -static gboolean -process_special_modifier_key (MetaDisplay *display, - ClutterKeyEvent *event, - MetaWindow *window, - gboolean *modifier_press_only, - MetaResolvedKeyCombo *resolved_key_combo, - GFunc trigger_callback) -{ - MetaKeyBindingManager *keys = &display->key_binding_manager; - MetaBackend *backend = keys->backend; - Display *xdisplay; - - if (META_IS_BACKEND_X11 (backend)) - xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); - else - xdisplay = NULL; - - if (*modifier_press_only) - { - if (! resolved_key_combo_has_keycode (resolved_key_combo, - event->hardware_keycode)) - { - *modifier_press_only = FALSE; - - /* If this is a wayland session, we can avoid the shenanigans - * about passive grabs below, and let the event continue to - * be processed through the regular paths. - */ - if (!xdisplay) - return FALSE; - - /* OK, the user hit modifier+key rather than pressing and - * releasing the modifier key alone. We want to handle the key - * sequence "normally". Unfortunately, using - * XAllowEvents(..., ReplayKeyboard, ...) doesn't quite - * work, since global keybindings won't be activated ("this - * time, however, the function ignores any passive grabs at - * above (toward the root of) the grab_window of the grab - * just released.") So, we first explicitly check for one of - * our global keybindings, and if not found, we then replay - * the event. Other clients with global grabs will be out of - * luck. - */ - if (process_event (display, window, event)) - { - /* As normally, after we've handled a global key - * binding, we unfreeze the keyboard but keep the grab - * (this is important for something like cycling - * windows */ - - if (xdisplay) - XIAllowEvents (xdisplay, - meta_input_device_x11_get_device_id (event->device), - XIAsyncDevice, event->time); - } - else - { - /* Replay the event so it gets delivered to our - * per-window key bindings or to the application */ - if (xdisplay) - XIAllowEvents (xdisplay, - meta_input_device_x11_get_device_id (event->device), - XIReplayDevice, event->time); - } - } - else if (event->type == CLUTTER_KEY_RELEASE) - { - MetaKeyBinding *binding; - - *modifier_press_only = FALSE; - - /* We want to unfreeze events, but keep the grab so that if the user - * starts typing into the overlay we get all the keys */ - if (xdisplay) - XIAllowEvents (xdisplay, - meta_input_device_x11_get_device_id (event->device), - XIAsyncDevice, event->time); - - binding = get_keybinding (keys, resolved_key_combo); - if (binding && - meta_compositor_filter_keybinding (display->compositor, binding)) - return TRUE; - trigger_callback (display, NULL); - } - else - { - /* In some rare race condition, mutter might not receive the Super_L - * KeyRelease event because: - * - the compositor might end the modal mode and call XIUngrabDevice - * while the key is still down - * - passive grabs are only activated on KeyPress and not KeyRelease. - * - * In this case, modifier_press_only might be wrong. - * Mutter still ought to acknowledge events, otherwise the X server - * will not send the next events. - * - * https://bugzilla.gnome.org/show_bug.cgi?id=666101 - */ - if (xdisplay) - XIAllowEvents (xdisplay, - meta_input_device_x11_get_device_id (event->device), - XIAsyncDevice, event->time); - } - - return TRUE; - } - else if (event->type == CLUTTER_KEY_PRESS && - ((event->modifier_state & ~(IGNORED_MODIFIERS)) & CLUTTER_MODIFIER_MASK) == 0 && - resolved_key_combo_has_keycode (resolved_key_combo, - event->hardware_keycode)) - { - *modifier_press_only = TRUE; - /* We keep the keyboard frozen - this allows us to use ReplayKeyboard - * on the next event if it's not the release of the modifier key */ - if (xdisplay) - XIAllowEvents (xdisplay, - meta_input_device_x11_get_device_id (event->device), - XISyncDevice, event->time); - - return TRUE; - } - else - return FALSE; -} - - -static gboolean -process_overlay_key (MetaDisplay *display, - ClutterKeyEvent *event, - MetaWindow *window) -{ - MetaKeyBindingManager *keys = &display->key_binding_manager; - - if (display->focus_window && !keys->overlay_key_only_pressed) - { - ClutterInputDevice *source; - - source = clutter_event_get_source_device ((ClutterEvent *) event); - if (meta_window_shortcuts_inhibited (display->focus_window, source)) - return FALSE; - } - - return process_special_modifier_key (display, - event, - window, - &keys->overlay_key_only_pressed, - &keys->overlay_resolved_key_combo, - (GFunc) meta_display_overlay_key_activate); -} - -static void -handle_locate_pointer (MetaDisplay *display) -{ - meta_compositor_locate_pointer (display->compositor); -} - -static gboolean -process_locate_pointer_key (MetaDisplay *display, - ClutterKeyEvent *event, - MetaWindow *window) -{ - MetaKeyBindingManager *keys = &display->key_binding_manager; - - return process_special_modifier_key (display, - event, - window, - &keys->locate_pointer_key_only_pressed, - &keys->locate_pointer_resolved_key_combo, - (GFunc) handle_locate_pointer); -} - -static gboolean -process_iso_next_group (MetaDisplay *display, - ClutterKeyEvent *event) -{ - MetaKeyBindingManager *keys = &display->key_binding_manager; - gboolean activate; - xkb_keycode_t keycode = (xkb_keycode_t) event->hardware_keycode; - xkb_mod_mask_t mask; - int i, j; - - if (event->type == CLUTTER_KEY_RELEASE) - return FALSE; - - activate = FALSE; - mask = mask_from_event_params (keys, event->modifier_state); - - for (i = 0; i < keys->n_iso_next_group_combos; ++i) - { - for (j = 0; j < keys->iso_next_group_combo[i].len; ++j) - { - if (keycode == keys->iso_next_group_combo[i].keycodes[j] && - mask == keys->iso_next_group_combo[i].mask) - { - /* If the signal handler returns TRUE the keyboard will - remain frozen. It's the signal handler's responsibility - to unfreeze it. */ - if (!meta_display_modifiers_accelerator_activate (display)) - meta_display_unfreeze_keyboard (display, event->time); - activate = TRUE; - break; - } - } - } - - return activate; -} - -static gboolean -process_key_event (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event) -{ - gboolean keep_grab; - gboolean all_keys_grabbed; - - all_keys_grabbed = window ? window->all_keys_grabbed : FALSE; - if (!all_keys_grabbed) - { - if (process_overlay_key (display, event, window)) - return TRUE; - - if (process_locate_pointer_key (display, event, window)) - return FALSE; /* Continue with the event even if handled */ - - if (process_iso_next_group (display, event)) - return TRUE; - } - - { - MetaBackend *backend = meta_get_backend (); - if (META_IS_BACKEND_X11 (backend)) - { - Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); - XIAllowEvents (xdisplay, - meta_input_device_x11_get_device_id (event->device), - XIAsyncDevice, event->time); - } - } - - keep_grab = TRUE; - if (all_keys_grabbed) - { - if (display->grab_op == META_GRAB_OP_NONE) - return TRUE; - - /* If we get here we have a global grab, because - * we're in some special keyboard mode such as window move - * mode. - */ - if (window == display->grab_window) - { - if (display->grab_op & META_GRAB_OP_WINDOW_FLAG_KEYBOARD) - { - if (display->grab_op == META_GRAB_OP_KEYBOARD_MOVING) - { - meta_topic (META_DEBUG_KEYBINDINGS, - "Processing event for keyboard move"); - keep_grab = process_keyboard_move_grab (display, window, event); - } - else - { - meta_topic (META_DEBUG_KEYBINDINGS, - "Processing event for keyboard resize"); - keep_grab = process_keyboard_resize_grab (display, window, event); - } - } - else - { - meta_topic (META_DEBUG_KEYBINDINGS, - "Processing event for mouse-only move/resize"); - keep_grab = process_mouse_move_resize_grab (display, window, event); - } - } - if (!keep_grab) - meta_display_end_grab_op (display, event->time); - - return TRUE; - } - - /* Do the normal keybindings */ - return process_event (display, window, event); -} - -/* Handle a key event. May be called recursively: some key events cause - * grabs to be ended and then need to be processed again in their own - * right. This cannot cause infinite recursion because we never call - * ourselves when there wasn't a grab, and we always clear the grab - * first; the invariant is enforced using an assertion. See #112560. - * - * The return value is whether we handled the key event. - * - * FIXME: We need to prove there are no race conditions here. - * FIXME: Does it correctly handle alt-Tab being followed by another - * grabbing keypress without letting go of alt? - * FIXME: An iterative solution would probably be simpler to understand - * (and help us solve the other fixmes). - */ -gboolean -meta_keybindings_process_event (MetaDisplay *display, - MetaWindow *window, - const ClutterEvent *event) -{ - MetaKeyBindingManager *keys = &display->key_binding_manager; - - switch (event->type) - { - case CLUTTER_BUTTON_PRESS: - case CLUTTER_BUTTON_RELEASE: - case CLUTTER_TOUCH_BEGIN: - case CLUTTER_TOUCH_END: - case CLUTTER_SCROLL: - keys->overlay_key_only_pressed = FALSE; - keys->locate_pointer_key_only_pressed = FALSE; - return FALSE; - - case CLUTTER_KEY_PRESS: - case CLUTTER_KEY_RELEASE: - return process_key_event (display, window, (ClutterKeyEvent *) event); - - default: - return FALSE; - } -} - -static gboolean -process_mouse_move_resize_grab (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event) -{ - /* don't care about releases, but eat them, don't end grab */ - if (event->type == CLUTTER_KEY_RELEASE) - return TRUE; - - if (event->keyval == CLUTTER_KEY_Escape) - { - MetaTileMode tile_mode; - - /* Hide the tiling preview if necessary */ - if (display->preview_tile_mode != META_TILE_NONE) - meta_display_hide_tile_preview (display); - - /* Restore the original tile mode */ - tile_mode = display->grab_tile_mode; - window->tile_monitor_number = display->grab_tile_monitor_number; - - /* End move or resize and restore to original state. If the - * window was a maximized window that had been "shaken loose" we - * need to remaximize it. In normal cases, we need to do a - * moveresize now to get the position back to the original. - */ - if (window->shaken_loose || tile_mode == META_TILE_MAXIMIZED) - meta_window_maximize (window, META_MAXIMIZE_BOTH); - else if (tile_mode != META_TILE_NONE) - meta_window_restore_tile (window, - tile_mode, - display->grab_initial_window_pos.width, - display->grab_initial_window_pos.height); - else - meta_window_move_resize_frame (display->grab_window, - TRUE, - display->grab_initial_window_pos.x, - display->grab_initial_window_pos.y, - display->grab_initial_window_pos.width, - display->grab_initial_window_pos.height); - - /* End grab */ - return FALSE; - } - - return TRUE; -} - -static gboolean -process_keyboard_move_grab (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event) -{ - MetaEdgeResistanceFlags flags; - gboolean handled; - MetaRectangle frame_rect; - int x, y; - int incr; - - handled = FALSE; - - /* don't care about releases, but eat them, don't end grab */ - if (event->type == CLUTTER_KEY_RELEASE) - return TRUE; - - /* don't end grab on modifier key presses */ - if (is_modifier (event->keyval)) - return TRUE; - - meta_window_get_frame_rect (window, &frame_rect); - x = frame_rect.x; - y = frame_rect.y; - - flags = META_EDGE_RESISTANCE_KEYBOARD_OP | META_EDGE_RESISTANCE_WINDOWS; - - if ((event->modifier_state & CLUTTER_SHIFT_MASK) != 0) - flags |= META_EDGE_RESISTANCE_SNAP; - -#define SMALL_INCREMENT 1 -#define NORMAL_INCREMENT 10 - - if (flags & META_EDGE_RESISTANCE_SNAP) - incr = 1; - else if (event->modifier_state & CLUTTER_CONTROL_MASK) - incr = SMALL_INCREMENT; - else - incr = NORMAL_INCREMENT; - - if (event->keyval == CLUTTER_KEY_Escape) - { - /* End move and restore to original state. If the window was a - * maximized window that had been "shaken loose" we need to - * remaximize it. In normal cases, we need to do a moveresize - * now to get the position back to the original. - */ - if (window->shaken_loose) - meta_window_maximize (window, META_MAXIMIZE_BOTH); - else - meta_window_move_resize_frame (display->grab_window, - TRUE, - display->grab_initial_window_pos.x, - display->grab_initial_window_pos.y, - display->grab_initial_window_pos.width, - display->grab_initial_window_pos.height); - } - - /* When moving by increments, we still snap to edges if the move - * to the edge is smaller than the increment. This is because - * Shift + arrow to snap is sort of a hidden feature. This way - * people using just arrows shouldn't get too frustrated. - */ - switch (event->keyval) - { - case CLUTTER_KEY_KP_Home: - case CLUTTER_KEY_KP_Prior: - case CLUTTER_KEY_Up: - case CLUTTER_KEY_KP_Up: - y -= incr; - handled = TRUE; - break; - case CLUTTER_KEY_KP_End: - case CLUTTER_KEY_KP_Next: - case CLUTTER_KEY_Down: - case CLUTTER_KEY_KP_Down: - y += incr; - handled = TRUE; - break; - } - - switch (event->keyval) - { - case CLUTTER_KEY_KP_Home: - case CLUTTER_KEY_KP_End: - case CLUTTER_KEY_Left: - case CLUTTER_KEY_KP_Left: - x -= incr; - handled = TRUE; - break; - case CLUTTER_KEY_KP_Prior: - case CLUTTER_KEY_KP_Next: - case CLUTTER_KEY_Right: - case CLUTTER_KEY_KP_Right: - x += incr; - handled = TRUE; - break; - } - - if (handled) - { - meta_topic (META_DEBUG_KEYBINDINGS, - "Computed new window location %d,%d due to keypress", - x, y); - - meta_window_edge_resistance_for_move (window, - &x, - &y, - NULL, - flags); - - meta_window_move_frame (window, TRUE, x, y); - meta_window_update_keyboard_move (window); - } - - return handled; -} - -static gboolean -process_keyboard_resize_grab_op_change (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event) -{ - gboolean handled; - - handled = FALSE; - switch (display->grab_op) - { - case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN: - switch (event->keyval) - { - case CLUTTER_KEY_Up: - case CLUTTER_KEY_KP_Up: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N; - handled = TRUE; - break; - case CLUTTER_KEY_Down: - case CLUTTER_KEY_KP_Down: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S; - handled = TRUE; - break; - case CLUTTER_KEY_Left: - case CLUTTER_KEY_KP_Left: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W; - handled = TRUE; - break; - case CLUTTER_KEY_Right: - case CLUTTER_KEY_KP_Right: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E; - handled = TRUE; - break; - } - break; - - case META_GRAB_OP_KEYBOARD_RESIZING_S: - switch (event->keyval) - { - case CLUTTER_KEY_Left: - case CLUTTER_KEY_KP_Left: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W; - handled = TRUE; - break; - case CLUTTER_KEY_Right: - case CLUTTER_KEY_KP_Right: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E; - handled = TRUE; - break; - } - break; - - case META_GRAB_OP_KEYBOARD_RESIZING_N: - switch (event->keyval) - { - case CLUTTER_KEY_Left: - case CLUTTER_KEY_KP_Left: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W; - handled = TRUE; - break; - case CLUTTER_KEY_Right: - case CLUTTER_KEY_KP_Right: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E; - handled = TRUE; - break; - } - break; - - case META_GRAB_OP_KEYBOARD_RESIZING_W: - switch (event->keyval) - { - case CLUTTER_KEY_Up: - case CLUTTER_KEY_KP_Up: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N; - handled = TRUE; - break; - case CLUTTER_KEY_Down: - case CLUTTER_KEY_KP_Down: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S; - handled = TRUE; - break; - } - break; - - case META_GRAB_OP_KEYBOARD_RESIZING_E: - switch (event->keyval) - { - case CLUTTER_KEY_Up: - case CLUTTER_KEY_KP_Up: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N; - handled = TRUE; - break; - case CLUTTER_KEY_Down: - case CLUTTER_KEY_KP_Down: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S; - handled = TRUE; - break; - } - break; - - case META_GRAB_OP_KEYBOARD_RESIZING_SE: - case META_GRAB_OP_KEYBOARD_RESIZING_NE: - case META_GRAB_OP_KEYBOARD_RESIZING_SW: - case META_GRAB_OP_KEYBOARD_RESIZING_NW: - break; - - default: - g_assert_not_reached (); - break; - } - - if (handled) - { - meta_window_update_keyboard_resize (window, TRUE); - return TRUE; - } - - return FALSE; -} - -static gboolean -process_keyboard_resize_grab (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event) -{ - MetaRectangle frame_rect; - gboolean handled; - int height_inc; - int width_inc; - int width, height; - MetaEdgeResistanceFlags flags; - MetaGravity gravity; - - handled = FALSE; - - /* don't care about releases, but eat them, don't end grab */ - if (event->type == CLUTTER_KEY_RELEASE) - return TRUE; - - /* don't end grab on modifier key presses */ - if (is_modifier (event->keyval)) - return TRUE; - - if (event->keyval == CLUTTER_KEY_Escape) - { - /* End resize and restore to original state. */ - meta_window_move_resize_frame (display->grab_window, - TRUE, - display->grab_initial_window_pos.x, - display->grab_initial_window_pos.y, - display->grab_initial_window_pos.width, - display->grab_initial_window_pos.height); - - return FALSE; - } - - if (process_keyboard_resize_grab_op_change (display, window, event)) - return TRUE; - - width = window->rect.width; - height = window->rect.height; - - meta_window_get_frame_rect (window, &frame_rect); - width = frame_rect.width; - height = frame_rect.height; - - gravity = meta_resize_gravity_from_grab_op (display->grab_op); - - flags = META_EDGE_RESISTANCE_KEYBOARD_OP; - - if ((event->modifier_state & CLUTTER_SHIFT_MASK) != 0) - flags |= META_EDGE_RESISTANCE_SNAP; - -#define SMALL_INCREMENT 1 -#define NORMAL_INCREMENT 10 - - if (flags & META_EDGE_RESISTANCE_SNAP) - { - height_inc = 1; - width_inc = 1; - } - else if (event->modifier_state & CLUTTER_CONTROL_MASK) - { - width_inc = SMALL_INCREMENT; - height_inc = SMALL_INCREMENT; - } - else - { - width_inc = NORMAL_INCREMENT; - height_inc = NORMAL_INCREMENT; - } - - /* If this is a resize increment window, make the amount we resize - * the window by match that amount (well, unless snap resizing...) - */ - if (window->size_hints.width_inc > 1) - width_inc = window->size_hints.width_inc; - if (window->size_hints.height_inc > 1) - height_inc = window->size_hints.height_inc; - - switch (event->keyval) - { - case CLUTTER_KEY_Up: - case CLUTTER_KEY_KP_Up: - switch (gravity) - { - case META_GRAVITY_NORTH: - case META_GRAVITY_NORTH_WEST: - case META_GRAVITY_NORTH_EAST: - /* Move bottom edge up */ - height -= height_inc; - break; - - case META_GRAVITY_SOUTH: - case META_GRAVITY_SOUTH_WEST: - case META_GRAVITY_SOUTH_EAST: - /* Move top edge up */ - height += height_inc; - break; - - case META_GRAVITY_EAST: - case META_GRAVITY_WEST: - case META_GRAVITY_CENTER: - case META_GRAVITY_NONE: - case META_GRAVITY_STATIC: - g_assert_not_reached (); - break; - } - - handled = TRUE; - break; - - case CLUTTER_KEY_Down: - case CLUTTER_KEY_KP_Down: - switch (gravity) - { - case META_GRAVITY_NORTH: - case META_GRAVITY_NORTH_WEST: - case META_GRAVITY_NORTH_EAST: - /* Move bottom edge down */ - height += height_inc; - break; - - case META_GRAVITY_SOUTH: - case META_GRAVITY_SOUTH_WEST: - case META_GRAVITY_SOUTH_EAST: - /* Move top edge down */ - height -= height_inc; - break; - - case META_GRAVITY_EAST: - case META_GRAVITY_WEST: - case META_GRAVITY_CENTER: - case META_GRAVITY_NONE: - case META_GRAVITY_STATIC: - g_assert_not_reached (); - break; - } - - handled = TRUE; - break; - - case CLUTTER_KEY_Left: - case CLUTTER_KEY_KP_Left: - switch (gravity) - { - case META_GRAVITY_EAST: - case META_GRAVITY_SOUTH_EAST: - case META_GRAVITY_NORTH_EAST: - /* Move left edge left */ - width += width_inc; - break; - - case META_GRAVITY_WEST: - case META_GRAVITY_SOUTH_WEST: - case META_GRAVITY_NORTH_WEST: - /* Move right edge left */ - width -= width_inc; - break; - - case META_GRAVITY_NORTH: - case META_GRAVITY_SOUTH: - case META_GRAVITY_CENTER: - case META_GRAVITY_NONE: - case META_GRAVITY_STATIC: - g_assert_not_reached (); - break; - } - - handled = TRUE; - break; - - case CLUTTER_KEY_Right: - case CLUTTER_KEY_KP_Right: - switch (gravity) - { - case META_GRAVITY_EAST: - case META_GRAVITY_SOUTH_EAST: - case META_GRAVITY_NORTH_EAST: - /* Move left edge right */ - width -= width_inc; - break; - - case META_GRAVITY_WEST: - case META_GRAVITY_SOUTH_WEST: - case META_GRAVITY_NORTH_WEST: - /* Move right edge right */ - width += width_inc; - break; - - case META_GRAVITY_NORTH: - case META_GRAVITY_SOUTH: - case META_GRAVITY_CENTER: - case META_GRAVITY_NONE: - case META_GRAVITY_STATIC: - g_assert_not_reached (); - break; - } - - handled = TRUE; - break; - - default: - break; - } - - /* fixup hack (just paranoia, not sure it's required) */ - if (height < 1) - height = 1; - if (width < 1) - width = 1; - - if (handled) - { - meta_topic (META_DEBUG_KEYBINDINGS, - "Computed new window size due to keypress: " - "%dx%d, gravity %s", - width, height, meta_gravity_to_string (gravity)); - - /* Do any edge resistance/snapping */ - meta_window_edge_resistance_for_resize (window, - &width, - &height, - gravity, - NULL, - flags); - - meta_window_resize_frame_with_gravity (window, - TRUE, - width, - height, - gravity); - - meta_window_update_keyboard_resize (window, FALSE); - } - - return handled; -} - -static void -handle_switch_to_last_workspace (MetaDisplay *display, - MetaWindow *event_window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - MetaWorkspaceManager *workspace_manager = display->workspace_manager; - gint target = meta_workspace_manager_get_n_workspaces (workspace_manager) - 1; - MetaWorkspace *workspace = meta_workspace_manager_get_workspace_by_index (workspace_manager, target); - meta_workspace_activate (workspace, event->time); -} - -static void -handle_switch_to_workspace (MetaDisplay *display, - MetaWindow *event_window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - gint which = binding->handler->data; - MetaWorkspaceManager *workspace_manager = display->workspace_manager; - MetaWorkspace *workspace; - - if (which < 0) - { - /* Negative workspace numbers are directions with respect to the - * current workspace. - */ - - workspace = meta_workspace_get_neighbor (workspace_manager->active_workspace, - which); - } - else - { - workspace = meta_workspace_manager_get_workspace_by_index (workspace_manager, which); - } - - if (workspace) - { - meta_workspace_activate (workspace, event->time); - } - else - { - /* We could offer to create it I suppose */ - } -} - - -static void -handle_maximize_vertically (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - if (window->has_resize_func) - { - if (window->maximized_vertically) - meta_window_unmaximize (window, META_MAXIMIZE_VERTICAL); - else - meta_window_maximize (window, META_MAXIMIZE_VERTICAL); - } -} - -static void -handle_maximize_horizontally (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - if (window->has_resize_func) - { - if (window->maximized_horizontally) - meta_window_unmaximize (window, META_MAXIMIZE_HORIZONTAL); - else - meta_window_maximize (window, META_MAXIMIZE_HORIZONTAL); - } -} - -static void -handle_always_on_top (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - if (window->wm_state_above == FALSE) - meta_window_make_above (window); - else - meta_window_unmake_above (window); -} - -static void -handle_move_to_corner_backend (MetaDisplay *display, - MetaWindow *window, - MetaGravity gravity) -{ - MetaRectangle work_area; - MetaRectangle frame_rect; - int new_x, new_y; - - if (!window->monitor) - return; - - meta_window_get_work_area_current_monitor (window, &work_area); - meta_window_get_frame_rect (window, &frame_rect); - - switch (gravity) - { - case META_GRAVITY_NORTH_WEST: - case META_GRAVITY_WEST: - case META_GRAVITY_SOUTH_WEST: - new_x = work_area.x; - break; - case META_GRAVITY_NORTH: - case META_GRAVITY_SOUTH: - new_x = frame_rect.x; - break; - case META_GRAVITY_NORTH_EAST: - case META_GRAVITY_EAST: - case META_GRAVITY_SOUTH_EAST: - new_x = work_area.x + work_area.width - frame_rect.width; - break; - default: - g_assert_not_reached (); - } - - switch (gravity) - { - case META_GRAVITY_NORTH_WEST: - case META_GRAVITY_NORTH: - case META_GRAVITY_NORTH_EAST: - new_y = work_area.y; - break; - case META_GRAVITY_WEST: - case META_GRAVITY_EAST: - new_y = frame_rect.y; - break; - case META_GRAVITY_SOUTH_WEST: - case META_GRAVITY_SOUTH: - case META_GRAVITY_SOUTH_EAST: - new_y = work_area.y + work_area.height - frame_rect.height; - break; - default: - g_assert_not_reached (); - } - - meta_window_move_frame (window, - TRUE, - new_x, - new_y); -} - -static void -handle_move_to_corner_nw (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - handle_move_to_corner_backend (display, window, META_GRAVITY_NORTH_WEST); -} - -static void -handle_move_to_corner_ne (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - handle_move_to_corner_backend (display, window, META_GRAVITY_NORTH_EAST); -} - -static void -handle_move_to_corner_sw (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - handle_move_to_corner_backend (display, window, META_GRAVITY_SOUTH_WEST); -} - -static void -handle_move_to_corner_se (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - handle_move_to_corner_backend (display, window, META_GRAVITY_SOUTH_EAST); -} - -static void -handle_move_to_side_n (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - handle_move_to_corner_backend (display, window, META_GRAVITY_NORTH); -} - -static void -handle_move_to_side_s (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - handle_move_to_corner_backend (display, window, META_GRAVITY_SOUTH); -} - -static void -handle_move_to_side_e (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - handle_move_to_corner_backend (display, window, META_GRAVITY_EAST); -} - -static void -handle_move_to_side_w (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - handle_move_to_corner_backend (display, window, META_GRAVITY_WEST); -} - -static void -handle_move_to_center (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - MetaRectangle work_area; - MetaRectangle frame_rect; - - meta_window_get_work_area_current_monitor (window, &work_area); - meta_window_get_frame_rect (window, &frame_rect); - - meta_window_move_frame (window, - TRUE, - work_area.x + (work_area.width - frame_rect.width ) / 2, - work_area.y + (work_area.height - frame_rect.height) / 2); -} - -static void -handle_show_desktop (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - MetaWorkspaceManager *workspace_manager = display->workspace_manager; - - if (workspace_manager->active_workspace->showing_desktop) - { - meta_workspace_manager_unshow_desktop (workspace_manager); - meta_workspace_focus_default_window (workspace_manager->active_workspace, - NULL, - event->time); - } - else - meta_workspace_manager_show_desktop (workspace_manager, event->time); -} - -static void -handle_panel (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - MetaKeyBindingAction action = binding->handler->data; - MetaX11Display *x11_display = display->x11_display; - Atom action_atom; - XClientMessageEvent ev; - - action_atom = None; - switch (action) - { - /* FIXME: The numbers are wrong */ - case META_KEYBINDING_ACTION_PANEL_MAIN_MENU: - action_atom = x11_display->atom__GNOME_PANEL_ACTION_MAIN_MENU; - break; - case META_KEYBINDING_ACTION_PANEL_RUN_DIALOG: - action_atom = x11_display->atom__GNOME_PANEL_ACTION_RUN_DIALOG; - break; - default: - return; - } - - ev.type = ClientMessage; - ev.window = x11_display->xroot; - ev.message_type = x11_display->atom__GNOME_PANEL_ACTION; - ev.format = 32; - ev.data.l[0] = action_atom; - ev.data.l[1] = event->time; - - meta_topic (META_DEBUG_KEYBINDINGS, - "Sending panel message with timestamp %u, and turning mouse_mode " - "off due to keybinding press", event->time); - display->mouse_mode = FALSE; - - meta_x11_error_trap_push (x11_display); - - /* Release the grab for the panel before sending the event */ - XUngrabKeyboard (x11_display->xdisplay, event->time); - - XSendEvent (x11_display->xdisplay, - x11_display->xroot, - False, - StructureNotifyMask, - (XEvent*) &ev); - - meta_x11_error_trap_pop (x11_display); -} - -static void -handle_activate_window_menu (MetaDisplay *display, - MetaWindow *event_window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - if (display->focus_window) - { - int x, y; - MetaRectangle frame_rect; - cairo_rectangle_int_t child_rect; - - meta_window_get_frame_rect (display->focus_window, &frame_rect); - meta_window_get_client_area_rect (display->focus_window, &child_rect); - - x = frame_rect.x + child_rect.x; - if (meta_get_locale_direction () == META_LOCALE_DIRECTION_RTL) - x += child_rect.width; - - y = frame_rect.y + child_rect.y; - meta_window_show_menu (display->focus_window, META_WINDOW_MENU_WM, x, y); - } -} - -static void -do_choose_window (MetaDisplay *display, - MetaWindow *event_window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gboolean backward) -{ - MetaWorkspaceManager *workspace_manager = display->workspace_manager; - MetaTabList type = binding->handler->data; - MetaWindow *window; - - meta_topic (META_DEBUG_KEYBINDINGS, - "Tab list = %u", type); - - window = meta_display_get_tab_next (display, - type, - workspace_manager->active_workspace, - NULL, - backward); - - if (window) - meta_window_activate (window, event->time); -} - -static void -handle_switch (MetaDisplay *display, - MetaWindow *event_window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - gboolean backwards = meta_key_binding_is_reversed (binding); - do_choose_window (display, event_window, event, binding, backwards); -} - -static void -handle_cycle (MetaDisplay *display, - MetaWindow *event_window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - gboolean backwards = meta_key_binding_is_reversed (binding); - do_choose_window (display, event_window, event, binding, backwards); -} - -static void -handle_toggle_fullscreen (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - if (window->fullscreen) - meta_window_unmake_fullscreen (window); - else if (window->has_fullscreen_func) - meta_window_make_fullscreen (window); -} - -static void -handle_toggle_above (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - if (window->wm_state_above) - meta_window_unmake_above (window); - else - meta_window_make_above (window); -} - -static void -handle_toggle_tiled (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - MetaTileMode mode = binding->handler->data; - - if ((META_WINDOW_TILED_LEFT (window) && mode == META_TILE_LEFT) || - (META_WINDOW_TILED_RIGHT (window) && mode == META_TILE_RIGHT)) - { - meta_window_untile (window); - } - else if (meta_window_can_tile_side_by_side (window)) - { - window->tile_monitor_number = window->monitor->number; - /* Maximization constraints beat tiling constraints, so if the window - * is maximized, tiling won't have any effect unless we unmaximize it - * horizontally first; rather than calling meta_window_unmaximize(), - * we just set the flag and rely on meta_window_tile() syncing it to - * save an additional roundtrip. - */ - window->maximized_horizontally = FALSE; - meta_window_tile (window, mode); - } -} - -static void -handle_toggle_maximized (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - if (META_WINDOW_MAXIMIZED (window)) - meta_window_unmaximize (window, META_MAXIMIZE_BOTH); - else if (window->has_maximize_func) - meta_window_maximize (window, META_MAXIMIZE_BOTH); -} - -static void -handle_maximize (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - if (window->has_maximize_func) - meta_window_maximize (window, META_MAXIMIZE_BOTH); -} - -static void -handle_unmaximize (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - if (window->maximized_vertically || window->maximized_horizontally) - meta_window_unmaximize (window, META_MAXIMIZE_BOTH); -} - -static void -handle_toggle_shaded (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - if (window->shaded) - meta_window_unshade (window, event->time); - else if (window->has_shade_func) - meta_window_shade (window, event->time); -} - -static void -handle_close (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - if (window->has_close_func) - meta_window_delete (window, event->time); -} - -static void -handle_minimize (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - if (window->has_minimize_func) - meta_window_minimize (window); -} - -static void -handle_begin_move (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - if (window->has_move_func) - { - meta_window_begin_grab_op (window, - META_GRAB_OP_KEYBOARD_MOVING, - FALSE, - event->time); - } -} - -static void -handle_begin_resize (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - if (window->has_resize_func) - { - meta_window_begin_grab_op (window, - META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN, - FALSE, - event->time); - } -} - -static void -handle_toggle_on_all_workspaces (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - if (window->on_all_workspaces_requested) - meta_window_unstick (window); - else - meta_window_stick (window); -} - -static void -handle_move_to_workspace_last (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - MetaWorkspaceManager *workspace_manager = display->workspace_manager; - gint which; - MetaWorkspace *workspace; - - if (window->always_sticky) - return; - - which = meta_workspace_manager_get_n_workspaces (workspace_manager) - 1; - workspace = meta_workspace_manager_get_workspace_by_index (workspace_manager, which); - meta_window_change_workspace (window, workspace); -} - - -static void -handle_move_to_workspace (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - MetaWorkspaceManager *workspace_manager = display->workspace_manager; - gint which = binding->handler->data; - gboolean flip = (which < 0); - MetaWorkspace *workspace; - - /* If which is zero or positive, it's a workspace number, and the window - * should move to the workspace with that number. - * - * However, if it's negative, it's a direction with respect to the current - * position; it's expressed as a member of the MetaMotionDirection enum, - * all of whose members are negative. Such a change is called a flip. - */ - - if (window->always_sticky) - return; - - workspace = NULL; - if (flip) - { - workspace = meta_workspace_get_neighbor (workspace_manager->active_workspace, - which); - } - else - { - workspace = meta_workspace_manager_get_workspace_by_index (workspace_manager, which); - } - - if (workspace) - { - /* Activate second, so the window is never unmapped */ - meta_window_change_workspace (window, workspace); - if (flip) - { - meta_topic (META_DEBUG_FOCUS, - "Resetting mouse_mode to FALSE due to " - "handle_move_to_workspace() call with flip set."); - meta_display_clear_mouse_mode (workspace->display); - meta_workspace_activate_with_focus (workspace, - window, - event->time); - } - } - else - { - /* We could offer to create it I suppose */ - } -} - -static void -handle_move_to_monitor (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - gint which = binding->handler->data; - MetaLogicalMonitor *current, *new; - - current = window->monitor; - new = meta_monitor_manager_get_logical_monitor_neighbor (monitor_manager, - current, which); - - if (new == NULL) - return; - - meta_window_move_to_monitor (window, new->number); -} - -static void -handle_raise_or_lower (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - /* Get window at pointer */ - - MetaWindow *above = NULL; - - /* Check if top */ - if (meta_stack_get_top (window->display->stack) == window) - { - meta_window_lower (window); - return; - } - - /* else check if windows in same layer are intersecting it */ - - above = meta_stack_get_above (window->display->stack, window, TRUE); - - while (above) - { - MetaRectangle tmp, win_rect, above_rect; - - if (above->mapped && meta_window_should_be_showing (above)) - { - meta_window_get_frame_rect (window, &win_rect); - meta_window_get_frame_rect (above, &above_rect); - - /* Check if obscured */ - if (meta_rectangle_intersect (&win_rect, &above_rect, &tmp)) - { - meta_window_raise (window); - return; - } - } - - above = meta_stack_get_above (window->display->stack, above, TRUE); - } - - /* window is not obscured */ - meta_window_lower (window); -} - -static void -handle_raise (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - meta_window_raise (window); -} - -static void -handle_lower (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - meta_window_lower (window); -} - -static void -handle_set_spew_mark (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - meta_verbose ("-- MARK MARK MARK MARK --"); -} - -#ifdef HAVE_NATIVE_BACKEND -static void -handle_switch_vt (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - gint vt = binding->handler->data; - GError *error = NULL; - - if (!meta_activate_vt (vt, &error)) - { - g_warning ("Failed to switch VT: %s", error->message); - g_error_free (error); - } -} -#endif /* HAVE_NATIVE_BACKEND */ - -static void -handle_switch_monitor (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorSwitchConfigType config_type = - meta_monitor_manager_get_switch_config (monitor_manager); - - if (!meta_monitor_manager_can_switch_config (monitor_manager)) - return; - - config_type = (config_type + 1) % (META_MONITOR_SWITCH_CONFIG_UNKNOWN); - meta_monitor_manager_switch_config (monitor_manager, config_type); -} - -static void -handle_rotate_monitor (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - - meta_monitor_manager_rotate_monitor (monitor_manager); -} - -static void -handle_restore_shortcuts (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer dummy) -{ - ClutterInputDevice *source; - - if (!display->focus_window) - return; - - source = clutter_event_get_source_device ((ClutterEvent *) event); - - meta_topic (META_DEBUG_KEYBINDINGS, "Restoring normal keyboard shortcuts"); - - meta_window_force_restore_shortcuts (display->focus_window, source); -} - -/** - * meta_keybindings_set_custom_handler: - * @name: The name of the keybinding to set - * @handler: (nullable): The new handler function - * @user_data: User data to pass to the callback - * @free_data: Will be called when this handler is overridden. - * - * Allows users to register a custom handler for a - * builtin key binding. - * - * Returns: %TRUE if the binding known as @name was found, - * %FALSE otherwise. - */ -gboolean -meta_keybindings_set_custom_handler (const gchar *name, - MetaKeyHandlerFunc handler, - gpointer user_data, - GDestroyNotify free_data) -{ - MetaKeyHandler *key_handler = HANDLER (name); - - if (!key_handler) - return FALSE; - - if (key_handler->user_data_free_func && key_handler->user_data) - key_handler->user_data_free_func (key_handler->user_data); - - key_handler->func = handler; - key_handler->user_data = user_data; - key_handler->user_data_free_func = free_data; - - return TRUE; -} - -static void -init_builtin_key_bindings (MetaDisplay *display) -{ - GSettings *common_keybindings = g_settings_new (SCHEMA_COMMON_KEYBINDINGS); - GSettings *mutter_keybindings = g_settings_new (SCHEMA_MUTTER_KEYBINDINGS); - GSettings *mutter_wayland_keybindings = g_settings_new (SCHEMA_MUTTER_WAYLAND_KEYBINDINGS); - - add_builtin_keybinding (display, - "switch-to-workspace-1", - common_keybindings, - META_KEY_BINDING_NONE | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_WORKSPACE_1, - handle_switch_to_workspace, 0); - add_builtin_keybinding (display, - "switch-to-workspace-2", - common_keybindings, - META_KEY_BINDING_NONE | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_WORKSPACE_2, - handle_switch_to_workspace, 1); - add_builtin_keybinding (display, - "switch-to-workspace-3", - common_keybindings, - META_KEY_BINDING_NONE | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_WORKSPACE_3, - handle_switch_to_workspace, 2); - add_builtin_keybinding (display, - "switch-to-workspace-4", - common_keybindings, - META_KEY_BINDING_NONE | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_WORKSPACE_4, - handle_switch_to_workspace, 3); - add_builtin_keybinding (display, - "switch-to-workspace-5", - common_keybindings, - META_KEY_BINDING_NONE | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_WORKSPACE_5, - handle_switch_to_workspace, 4); - add_builtin_keybinding (display, - "switch-to-workspace-6", - common_keybindings, - META_KEY_BINDING_NONE | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_WORKSPACE_6, - handle_switch_to_workspace, 5); - add_builtin_keybinding (display, - "switch-to-workspace-7", - common_keybindings, - META_KEY_BINDING_NONE | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_WORKSPACE_7, - handle_switch_to_workspace, 6); - add_builtin_keybinding (display, - "switch-to-workspace-8", - common_keybindings, - META_KEY_BINDING_NONE | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_WORKSPACE_8, - handle_switch_to_workspace, 7); - add_builtin_keybinding (display, - "switch-to-workspace-9", - common_keybindings, - META_KEY_BINDING_NONE | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_WORKSPACE_9, - handle_switch_to_workspace, 8); - add_builtin_keybinding (display, - "switch-to-workspace-10", - common_keybindings, - META_KEY_BINDING_NONE | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_WORKSPACE_10, - handle_switch_to_workspace, 9); - add_builtin_keybinding (display, - "switch-to-workspace-11", - common_keybindings, - META_KEY_BINDING_NONE | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_WORKSPACE_11, - handle_switch_to_workspace, 10); - add_builtin_keybinding (display, - "switch-to-workspace-12", - common_keybindings, - META_KEY_BINDING_NONE | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_WORKSPACE_12, - handle_switch_to_workspace, 11); - - add_builtin_keybinding (display, - "switch-to-workspace-left", - common_keybindings, - META_KEY_BINDING_NONE, - META_KEYBINDING_ACTION_WORKSPACE_LEFT, - handle_switch_to_workspace, META_MOTION_LEFT); - - add_builtin_keybinding (display, - "switch-to-workspace-right", - common_keybindings, - META_KEY_BINDING_NONE, - META_KEYBINDING_ACTION_WORKSPACE_RIGHT, - handle_switch_to_workspace, META_MOTION_RIGHT); - - add_builtin_keybinding (display, - "switch-to-workspace-up", - common_keybindings, - META_KEY_BINDING_NONE, - META_KEYBINDING_ACTION_WORKSPACE_UP, - handle_switch_to_workspace, META_MOTION_UP); - - add_builtin_keybinding (display, - "switch-to-workspace-down", - common_keybindings, - META_KEY_BINDING_NONE, - META_KEYBINDING_ACTION_WORKSPACE_DOWN, - handle_switch_to_workspace, META_MOTION_DOWN); - - add_builtin_keybinding (display, - "switch-to-workspace-last", - common_keybindings, - META_KEY_BINDING_NONE, - META_KEYBINDING_ACTION_WORKSPACE_LAST, - handle_switch_to_last_workspace, 0); - - - - /* The ones which have inverses. These can't be bound to any keystroke - * containing Shift because Shift will invert their "backward" state. - * - * TODO: "NORMAL" and "DOCKS" should be renamed to the same name as their - * action, for obviousness. - * - * TODO: handle_switch and handle_cycle should probably really be the - * same function checking a bit in the parameter for difference. - */ - - add_builtin_keybinding (display, - "switch-group", - common_keybindings, - META_KEY_BINDING_NONE, - META_KEYBINDING_ACTION_SWITCH_GROUP, - handle_switch, META_TAB_LIST_GROUP); - - add_builtin_keybinding (display, - "switch-group-backward", - common_keybindings, - META_KEY_BINDING_IS_REVERSED, - META_KEYBINDING_ACTION_SWITCH_GROUP_BACKWARD, - handle_switch, META_TAB_LIST_GROUP); - - add_builtin_keybinding (display, - "switch-applications", - common_keybindings, - META_KEY_BINDING_NONE, - META_KEYBINDING_ACTION_SWITCH_APPLICATIONS, - handle_switch, META_TAB_LIST_NORMAL); - - add_builtin_keybinding (display, - "switch-applications-backward", - common_keybindings, - META_KEY_BINDING_IS_REVERSED, - META_KEYBINDING_ACTION_SWITCH_APPLICATIONS_BACKWARD, - handle_switch, META_TAB_LIST_NORMAL); - - add_builtin_keybinding (display, - "switch-windows", - common_keybindings, - META_KEY_BINDING_NONE, - META_KEYBINDING_ACTION_SWITCH_WINDOWS, - handle_switch, META_TAB_LIST_NORMAL); - - add_builtin_keybinding (display, - "switch-windows-backward", - common_keybindings, - META_KEY_BINDING_IS_REVERSED, - META_KEYBINDING_ACTION_SWITCH_WINDOWS_BACKWARD, - handle_switch, META_TAB_LIST_NORMAL); - - add_builtin_keybinding (display, - "switch-panels", - common_keybindings, - META_KEY_BINDING_NONE, - META_KEYBINDING_ACTION_SWITCH_PANELS, - handle_switch, META_TAB_LIST_DOCKS); - - add_builtin_keybinding (display, - "switch-panels-backward", - common_keybindings, - META_KEY_BINDING_IS_REVERSED, - META_KEYBINDING_ACTION_SWITCH_PANELS_BACKWARD, - handle_switch, META_TAB_LIST_DOCKS); - - add_builtin_keybinding (display, - "cycle-group", - common_keybindings, - META_KEY_BINDING_NONE, - META_KEYBINDING_ACTION_CYCLE_GROUP, - handle_cycle, META_TAB_LIST_GROUP); - - add_builtin_keybinding (display, - "cycle-group-backward", - common_keybindings, - META_KEY_BINDING_IS_REVERSED, - META_KEYBINDING_ACTION_CYCLE_GROUP_BACKWARD, - handle_cycle, META_TAB_LIST_GROUP); - - add_builtin_keybinding (display, - "cycle-windows", - common_keybindings, - META_KEY_BINDING_NONE, - META_KEYBINDING_ACTION_CYCLE_WINDOWS, - handle_cycle, META_TAB_LIST_NORMAL); - - add_builtin_keybinding (display, - "cycle-windows-backward", - common_keybindings, - META_KEY_BINDING_IS_REVERSED, - META_KEYBINDING_ACTION_CYCLE_WINDOWS_BACKWARD, - handle_cycle, META_TAB_LIST_NORMAL); - - add_builtin_keybinding (display, - "cycle-panels", - common_keybindings, - META_KEY_BINDING_NONE, - META_KEYBINDING_ACTION_CYCLE_PANELS, - handle_cycle, META_TAB_LIST_DOCKS); - - add_builtin_keybinding (display, - "cycle-panels-backward", - common_keybindings, - META_KEY_BINDING_IS_REVERSED, - META_KEYBINDING_ACTION_CYCLE_PANELS_BACKWARD, - handle_cycle, META_TAB_LIST_DOCKS); - - /***********************************/ - - add_builtin_keybinding (display, - "show-desktop", - common_keybindings, - META_KEY_BINDING_NONE, - META_KEYBINDING_ACTION_SHOW_DESKTOP, - handle_show_desktop, 0); - - add_builtin_keybinding (display, - "panel-main-menu", - common_keybindings, - META_KEY_BINDING_NONE, - META_KEYBINDING_ACTION_PANEL_MAIN_MENU, - handle_panel, META_KEYBINDING_ACTION_PANEL_MAIN_MENU); - - add_builtin_keybinding (display, - "panel-run-dialog", - common_keybindings, - META_KEY_BINDING_NONE, - META_KEYBINDING_ACTION_PANEL_RUN_DIALOG, - handle_panel, META_KEYBINDING_ACTION_PANEL_RUN_DIALOG); - - add_builtin_keybinding (display, - "set-spew-mark", - common_keybindings, - META_KEY_BINDING_NONE, - META_KEYBINDING_ACTION_SET_SPEW_MARK, - handle_set_spew_mark, 0); - - add_builtin_keybinding (display, - "switch-monitor", - mutter_keybindings, - META_KEY_BINDING_NONE, - META_KEYBINDING_ACTION_SWITCH_MONITOR, - handle_switch_monitor, 0); - - add_builtin_keybinding (display, - "rotate-monitor", - mutter_keybindings, - META_KEY_BINDING_NONE, - META_KEYBINDING_ACTION_ROTATE_MONITOR, - handle_rotate_monitor, 0); - -#ifdef HAVE_NATIVE_BACKEND - MetaBackend *backend = meta_get_backend (); - if (META_IS_BACKEND_NATIVE (backend)) - { - add_builtin_keybinding (display, - "switch-to-session-1", - mutter_wayland_keybindings, - META_KEY_BINDING_NON_MASKABLE, - META_KEYBINDING_ACTION_NONE, - handle_switch_vt, 1); - - add_builtin_keybinding (display, - "switch-to-session-2", - mutter_wayland_keybindings, - META_KEY_BINDING_NON_MASKABLE, - META_KEYBINDING_ACTION_NONE, - handle_switch_vt, 2); - - add_builtin_keybinding (display, - "switch-to-session-3", - mutter_wayland_keybindings, - META_KEY_BINDING_NON_MASKABLE, - META_KEYBINDING_ACTION_NONE, - handle_switch_vt, 3); - - add_builtin_keybinding (display, - "switch-to-session-4", - mutter_wayland_keybindings, - META_KEY_BINDING_NON_MASKABLE, - META_KEYBINDING_ACTION_NONE, - handle_switch_vt, 4); - - add_builtin_keybinding (display, - "switch-to-session-5", - mutter_wayland_keybindings, - META_KEY_BINDING_NON_MASKABLE, - META_KEYBINDING_ACTION_NONE, - handle_switch_vt, 5); - - add_builtin_keybinding (display, - "switch-to-session-6", - mutter_wayland_keybindings, - META_KEY_BINDING_NON_MASKABLE, - META_KEYBINDING_ACTION_NONE, - handle_switch_vt, 6); - - add_builtin_keybinding (display, - "switch-to-session-7", - mutter_wayland_keybindings, - META_KEY_BINDING_NON_MASKABLE, - META_KEYBINDING_ACTION_NONE, - handle_switch_vt, 7); - - add_builtin_keybinding (display, - "switch-to-session-8", - mutter_wayland_keybindings, - META_KEY_BINDING_NON_MASKABLE, - META_KEYBINDING_ACTION_NONE, - handle_switch_vt, 8); - - add_builtin_keybinding (display, - "switch-to-session-9", - mutter_wayland_keybindings, - META_KEY_BINDING_NON_MASKABLE, - META_KEYBINDING_ACTION_NONE, - handle_switch_vt, 9); - - add_builtin_keybinding (display, - "switch-to-session-10", - mutter_wayland_keybindings, - META_KEY_BINDING_NON_MASKABLE, - META_KEYBINDING_ACTION_NONE, - handle_switch_vt, 10); - - add_builtin_keybinding (display, - "switch-to-session-11", - mutter_wayland_keybindings, - META_KEY_BINDING_NON_MASKABLE, - META_KEYBINDING_ACTION_NONE, - handle_switch_vt, 11); - - add_builtin_keybinding (display, - "switch-to-session-12", - mutter_wayland_keybindings, - META_KEY_BINDING_NON_MASKABLE, - META_KEYBINDING_ACTION_NONE, - handle_switch_vt, 12); - } -#endif /* HAVE_NATIVE_BACKEND */ - - add_builtin_keybinding (display, - "restore-shortcuts", - mutter_wayland_keybindings, - META_KEY_BINDING_NON_MASKABLE, - META_KEYBINDING_ACTION_NONE, - handle_restore_shortcuts, 0); - - /************************ PER WINDOW BINDINGS ************************/ - - /* These take a window as an extra parameter; they have no effect - * if no window is active. - */ - - add_builtin_keybinding (display, - "activate-window-menu", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_ACTIVATE_WINDOW_MENU, - handle_activate_window_menu, 0); - - add_builtin_keybinding (display, - "toggle-fullscreen", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_TOGGLE_FULLSCREEN, - handle_toggle_fullscreen, 0); - - add_builtin_keybinding (display, - "toggle-maximized", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_TOGGLE_MAXIMIZED, - handle_toggle_maximized, 0); - - add_builtin_keybinding (display, - "toggle-tiled-left", - mutter_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_TOGGLE_TILED_LEFT, - handle_toggle_tiled, META_TILE_LEFT); - - add_builtin_keybinding (display, - "toggle-tiled-right", - mutter_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_TOGGLE_TILED_RIGHT, - handle_toggle_tiled, META_TILE_RIGHT); - - add_builtin_keybinding (display, - "toggle-above", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_TOGGLE_ABOVE, - handle_toggle_above, 0); - - add_builtin_keybinding (display, - "maximize", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_MAXIMIZE, - handle_maximize, 0); - - add_builtin_keybinding (display, - "unmaximize", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_UNMAXIMIZE, - handle_unmaximize, 0); - - add_builtin_keybinding (display, - "toggle-shaded", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_TOGGLE_SHADED, - handle_toggle_shaded, 0); - - add_builtin_keybinding (display, - "minimize", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_MINIMIZE, - handle_minimize, 0); - - add_builtin_keybinding (display, - "close", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_CLOSE, - handle_close, 0); - - add_builtin_keybinding (display, - "begin-move", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_BEGIN_MOVE, - handle_begin_move, 0); - - add_builtin_keybinding (display, - "begin-resize", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_BEGIN_RESIZE, - handle_begin_resize, 0); - - add_builtin_keybinding (display, - "toggle-on-all-workspaces", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_TOGGLE_ON_ALL_WORKSPACES, - handle_toggle_on_all_workspaces, 0); - - add_builtin_keybinding (display, - "move-to-workspace-1", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_1, - handle_move_to_workspace, 0); - - add_builtin_keybinding (display, - "move-to-workspace-2", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_2, - handle_move_to_workspace, 1); - - add_builtin_keybinding (display, - "move-to-workspace-3", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_3, - handle_move_to_workspace, 2); - - add_builtin_keybinding (display, - "move-to-workspace-4", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_4, - handle_move_to_workspace, 3); - - add_builtin_keybinding (display, - "move-to-workspace-5", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_5, - handle_move_to_workspace, 4); - - add_builtin_keybinding (display, - "move-to-workspace-6", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_6, - handle_move_to_workspace, 5); - - add_builtin_keybinding (display, - "move-to-workspace-7", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_7, - handle_move_to_workspace, 6); - - add_builtin_keybinding (display, - "move-to-workspace-8", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_8, - handle_move_to_workspace, 7); - - add_builtin_keybinding (display, - "move-to-workspace-9", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_9, - handle_move_to_workspace, 8); - - add_builtin_keybinding (display, - "move-to-workspace-10", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_10, - handle_move_to_workspace, 9); - - add_builtin_keybinding (display, - "move-to-workspace-11", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_11, - handle_move_to_workspace, 10); - - add_builtin_keybinding (display, - "move-to-workspace-12", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_12, - handle_move_to_workspace, 11); - - add_builtin_keybinding (display, - "move-to-workspace-last", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_LAST, - handle_move_to_workspace_last, 0); - - add_builtin_keybinding (display, - "move-to-workspace-left", - common_keybindings, - META_KEY_BINDING_PER_WINDOW, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_LEFT, - handle_move_to_workspace, META_MOTION_LEFT); - - add_builtin_keybinding (display, - "move-to-workspace-right", - common_keybindings, - META_KEY_BINDING_PER_WINDOW, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_RIGHT, - handle_move_to_workspace, META_MOTION_RIGHT); - - add_builtin_keybinding (display, - "move-to-workspace-up", - common_keybindings, - META_KEY_BINDING_PER_WINDOW, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_UP, - handle_move_to_workspace, META_MOTION_UP); - - add_builtin_keybinding (display, - "move-to-workspace-down", - common_keybindings, - META_KEY_BINDING_PER_WINDOW, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_DOWN, - handle_move_to_workspace, META_MOTION_DOWN); - - add_builtin_keybinding (display, - "move-to-monitor-left", - common_keybindings, - META_KEY_BINDING_PER_WINDOW, - META_KEYBINDING_ACTION_MOVE_TO_MONITOR_LEFT, - handle_move_to_monitor, META_DISPLAY_LEFT); - - add_builtin_keybinding (display, - "move-to-monitor-right", - common_keybindings, - META_KEY_BINDING_PER_WINDOW, - META_KEYBINDING_ACTION_MOVE_TO_MONITOR_RIGHT, - handle_move_to_monitor, META_DISPLAY_RIGHT); - - add_builtin_keybinding (display, - "move-to-monitor-down", - common_keybindings, - META_KEY_BINDING_PER_WINDOW, - META_KEYBINDING_ACTION_MOVE_TO_MONITOR_DOWN, - handle_move_to_monitor, META_DISPLAY_DOWN); - - add_builtin_keybinding (display, - "move-to-monitor-up", - common_keybindings, - META_KEY_BINDING_PER_WINDOW, - META_KEYBINDING_ACTION_MOVE_TO_MONITOR_UP, - handle_move_to_monitor, META_DISPLAY_UP); - - add_builtin_keybinding (display, - "raise-or-lower", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_RAISE_OR_LOWER, - handle_raise_or_lower, 0); - - add_builtin_keybinding (display, - "raise", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_RAISE, - handle_raise, 0); - - add_builtin_keybinding (display, - "lower", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_LOWER, - handle_lower, 0); - - add_builtin_keybinding (display, - "maximize-vertically", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_MAXIMIZE_VERTICALLY, - handle_maximize_vertically, 0); - - add_builtin_keybinding (display, - "maximize-horizontally", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_MAXIMIZE_HORIZONTALLY, - handle_maximize_horizontally, 0); - - add_builtin_keybinding (display, - "always-on-top", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_ALWAYS_ON_TOP, - handle_always_on_top, 0); - - add_builtin_keybinding (display, - "move-to-corner-nw", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_MOVE_TO_CORNER_NW, - handle_move_to_corner_nw, 0); - - add_builtin_keybinding (display, - "move-to-corner-ne", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_MOVE_TO_CORNER_NE, - handle_move_to_corner_ne, 0); - - add_builtin_keybinding (display, - "move-to-corner-sw", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_MOVE_TO_CORNER_SW, - handle_move_to_corner_sw, 0); - - add_builtin_keybinding (display, - "move-to-corner-se", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_MOVE_TO_CORNER_SE, - handle_move_to_corner_se, 0); - - add_builtin_keybinding (display, - "move-to-side-n", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_MOVE_TO_SIDE_N, - handle_move_to_side_n, 0); - - add_builtin_keybinding (display, - "move-to-side-s", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_MOVE_TO_SIDE_S, - handle_move_to_side_s, 0); - - add_builtin_keybinding (display, - "move-to-side-e", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_MOVE_TO_SIDE_E, - handle_move_to_side_e, 0); - - add_builtin_keybinding (display, - "move-to-side-w", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_MOVE_TO_SIDE_W, - handle_move_to_side_w, 0); - - add_builtin_keybinding (display, - "move-to-center", - common_keybindings, - META_KEY_BINDING_PER_WINDOW | - META_KEY_BINDING_IGNORE_AUTOREPEAT, - META_KEYBINDING_ACTION_MOVE_TO_CENTER, - handle_move_to_center, 0); - - g_object_unref (common_keybindings); - g_object_unref (mutter_keybindings); - g_object_unref (mutter_wayland_keybindings); -} - -void -meta_display_init_keys (MetaDisplay *display) -{ - MetaKeyBindingManager *keys = &display->key_binding_manager; - MetaBackend *backend = meta_get_backend (); - MetaKeyHandler *handler; - - keys->backend = backend; - - /* Keybindings */ - keys->ignored_modifier_mask = 0; - keys->hyper_mask = 0; - keys->super_mask = 0; - keys->meta_mask = 0; - - keys->key_bindings = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) meta_key_binding_free); - keys->key_bindings_index = g_hash_table_new (NULL, NULL); - - reload_modmap (keys); - - key_handlers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, - (GDestroyNotify) key_handler_free); - - handler = g_new0 (MetaKeyHandler, 1); - handler->name = g_strdup ("overlay-key"); - handler->flags = META_KEY_BINDING_BUILTIN | META_KEY_BINDING_NO_AUTO_GRAB; - - g_hash_table_insert (key_handlers, g_strdup (handler->name), handler); - - handler = g_new0 (MetaKeyHandler, 1); - handler->name = g_strdup ("locate-pointer-key"); - handler->flags = META_KEY_BINDING_BUILTIN | META_KEY_BINDING_NO_AUTO_GRAB; - - g_hash_table_insert (key_handlers, g_strdup (handler->name), handler); - - handler = g_new0 (MetaKeyHandler, 1); - handler->name = g_strdup ("iso-next-group"); - handler->flags = META_KEY_BINDING_BUILTIN; - - g_hash_table_insert (key_handlers, g_strdup (handler->name), handler); - - handler = g_new0 (MetaKeyHandler, 1); - handler->name = g_strdup ("external-grab"); - handler->func = handle_external_grab; - handler->default_func = handle_external_grab; - - g_hash_table_insert (key_handlers, g_strdup (handler->name), handler); - - external_grabs = g_hash_table_new_full (g_str_hash, g_str_equal, - NULL, - (GDestroyNotify)meta_key_grab_free); - - init_builtin_key_bindings (display); - - rebuild_key_binding_table (keys); - rebuild_special_bindings (keys); - - reload_combos (keys); - - update_window_grab_modifiers (display); - - /* Keys are actually grabbed in meta_screen_grab_keys() */ - - meta_prefs_add_listener (prefs_changed_callback, display); - - g_signal_connect_swapped (backend, "keymap-changed", - G_CALLBACK (reload_keybindings), display); - g_signal_connect_swapped (backend, "keymap-layout-group-changed", - G_CALLBACK (reload_keybindings), display); -} diff --git a/src/core/meta-accel-parse.c b/src/core/meta-accel-parse.c deleted file mode 100644 index 0d34251af..000000000 --- a/src/core/meta-accel-parse.c +++ /dev/null @@ -1,358 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -#include "config.h" - -#include "core/meta-accel-parse.h" - -#include -#include -#include - -#include "core/keybindings-private.h" - -/* This is copied from GTK+ and modified to work with mutter's - * internal structures. Originating code comes from gtk/gtkaccelgroup.c - */ - -static inline gboolean -is_alt (const gchar *string) -{ - return ((string[0] == '<') && - (string[1] == 'a' || string[1] == 'A') && - (string[2] == 'l' || string[2] == 'L') && - (string[3] == 't' || string[3] == 'T') && - (string[4] == '>')); -} - -static inline gboolean -is_ctl (const gchar *string) -{ - return ((string[0] == '<') && - (string[1] == 'c' || string[1] == 'C') && - (string[2] == 't' || string[2] == 'T') && - (string[3] == 'l' || string[3] == 'L') && - (string[4] == '>')); -} - -static inline gboolean -is_modx (const gchar *string) -{ - return ((string[0] == '<') && - (string[1] == 'm' || string[1] == 'M') && - (string[2] == 'o' || string[2] == 'O') && - (string[3] == 'd' || string[3] == 'D') && - (string[4] >= '1' && string[4] <= '5') && - (string[5] == '>')); -} - -static inline gboolean -is_ctrl (const gchar *string) -{ - return ((string[0] == '<') && - (string[1] == 'c' || string[1] == 'C') && - (string[2] == 't' || string[2] == 'T') && - (string[3] == 'r' || string[3] == 'R') && - (string[4] == 'l' || string[4] == 'L') && - (string[5] == '>')); -} - -static inline gboolean -is_shft (const gchar *string) -{ - return ((string[0] == '<') && - (string[1] == 's' || string[1] == 'S') && - (string[2] == 'h' || string[2] == 'H') && - (string[3] == 'f' || string[3] == 'F') && - (string[4] == 't' || string[4] == 'T') && - (string[5] == '>')); -} - -static inline gboolean -is_shift (const gchar *string) -{ - return ((string[0] == '<') && - (string[1] == 's' || string[1] == 'S') && - (string[2] == 'h' || string[2] == 'H') && - (string[3] == 'i' || string[3] == 'I') && - (string[4] == 'f' || string[4] == 'F') && - (string[5] == 't' || string[5] == 'T') && - (string[6] == '>')); -} - -static inline gboolean -is_control (const gchar *string) -{ - return ((string[0] == '<') && - (string[1] == 'c' || string[1] == 'C') && - (string[2] == 'o' || string[2] == 'O') && - (string[3] == 'n' || string[3] == 'N') && - (string[4] == 't' || string[4] == 'T') && - (string[5] == 'r' || string[5] == 'R') && - (string[6] == 'o' || string[6] == 'O') && - (string[7] == 'l' || string[7] == 'L') && - (string[8] == '>')); -} - -static inline gboolean -is_meta (const gchar *string) -{ - return ((string[0] == '<') && - (string[1] == 'm' || string[1] == 'M') && - (string[2] == 'e' || string[2] == 'E') && - (string[3] == 't' || string[3] == 'T') && - (string[4] == 'a' || string[4] == 'A') && - (string[5] == '>')); -} - -static inline gboolean -is_super (const gchar *string) -{ - return ((string[0] == '<') && - (string[1] == 's' || string[1] == 'S') && - (string[2] == 'u' || string[2] == 'U') && - (string[3] == 'p' || string[3] == 'P') && - (string[4] == 'e' || string[4] == 'E') && - (string[5] == 'r' || string[5] == 'R') && - (string[6] == '>')); -} - -static inline gboolean -is_hyper (const gchar *string) -{ - return ((string[0] == '<') && - (string[1] == 'h' || string[1] == 'H') && - (string[2] == 'y' || string[2] == 'Y') && - (string[3] == 'p' || string[3] == 'P') && - (string[4] == 'e' || string[4] == 'E') && - (string[5] == 'r' || string[5] == 'R') && - (string[6] == '>')); -} - -static inline gboolean -is_primary (const gchar *string) -{ - return ((string[0] == '<') && - (string[1] == 'p' || string[1] == 'P') && - (string[2] == 'r' || string[2] == 'R') && - (string[3] == 'i' || string[3] == 'I') && - (string[4] == 'm' || string[4] == 'M') && - (string[5] == 'a' || string[5] == 'A') && - (string[6] == 'r' || string[6] == 'R') && - (string[7] == 'y' || string[7] == 'Y') && - (string[8] == '>')); -} - -static inline gboolean -is_keycode (const gchar *string) -{ - return (string[0] == '0' && - string[1] == 'x' && - g_ascii_isxdigit (string[2]) && - g_ascii_isxdigit (string[3])); -} - -static gboolean -accelerator_parse (const gchar *accelerator, - MetaKeyCombo *combo) -{ - guint keyval, keycode; - MetaVirtualModifier mods; - gint len; - - combo->keysym = 0; - combo->keycode = 0; - combo->modifiers = 0; - - if (accelerator == NULL) - return FALSE; - - keyval = 0; - keycode = 0; - mods = 0; - len = strlen (accelerator); - while (len) - { - if (*accelerator == '<') - { - if (len >= 9 && is_primary (accelerator)) - { - /* Primary is treated the same as Control */ - accelerator += 9; - len -= 9; - mods |= META_VIRTUAL_CONTROL_MASK; - } - else if (len >= 9 && is_control (accelerator)) - { - accelerator += 9; - len -= 9; - mods |= META_VIRTUAL_CONTROL_MASK; - } - else if (len >= 7 && is_shift (accelerator)) - { - accelerator += 7; - len -= 7; - mods |= META_VIRTUAL_SHIFT_MASK; - } - else if (len >= 6 && is_shft (accelerator)) - { - accelerator += 6; - len -= 6; - mods |= META_VIRTUAL_SHIFT_MASK; - } - else if (len >= 6 && is_ctrl (accelerator)) - { - accelerator += 6; - len -= 6; - mods |= META_VIRTUAL_CONTROL_MASK; - } - else if (len >= 6 && is_modx (accelerator)) - { - static const guint mod_vals[] = { - META_VIRTUAL_ALT_MASK, - META_VIRTUAL_MOD2_MASK, - META_VIRTUAL_MOD3_MASK, - META_VIRTUAL_MOD4_MASK, - META_VIRTUAL_MOD5_MASK, - }; - - len -= 6; - accelerator += 4; - mods |= mod_vals[*accelerator - '1']; - accelerator += 2; - } - else if (len >= 5 && is_ctl (accelerator)) - { - accelerator += 5; - len -= 5; - mods |= META_VIRTUAL_CONTROL_MASK; - } - else if (len >= 5 && is_alt (accelerator)) - { - accelerator += 5; - len -= 5; - mods |= META_VIRTUAL_ALT_MASK; - } - else if (len >= 6 && is_meta (accelerator)) - { - accelerator += 6; - len -= 6; - mods |= META_VIRTUAL_META_MASK; - } - else if (len >= 7 && is_hyper (accelerator)) - { - accelerator += 7; - len -= 7; - mods |= META_VIRTUAL_HYPER_MASK; - } - else if (len >= 7 && is_super (accelerator)) - { - accelerator += 7; - len -= 7; - mods |= META_VIRTUAL_SUPER_MASK; - } - else - { - gchar last_ch; - - last_ch = *accelerator; - while (last_ch && last_ch != '>') - { - last_ch = *accelerator; - accelerator += 1; - len -= 1; - } - } - } - else - { - if (len >= 4 && is_keycode (accelerator)) - { - keycode = strtoul (accelerator, NULL, 16); - goto out; - } - else if (strcmp (accelerator, "Above_Tab") == 0) - { - keyval = META_KEY_ABOVE_TAB; - goto out; - } - else - { - keyval = xkb_keysym_from_name (accelerator, XKB_KEYSYM_CASE_INSENSITIVE); - if (keyval == XKB_KEY_NoSymbol) - { - char *with_xf86 = g_strconcat ("XF86", accelerator, NULL); - keyval = xkb_keysym_from_name (with_xf86, XKB_KEYSYM_CASE_INSENSITIVE); - g_free (with_xf86); - - if (keyval == XKB_KEY_NoSymbol) - return FALSE; - } - } - - accelerator += len; - len -= len; - } - } - - out: - combo->keysym = keyval; - combo->keycode = keycode; - combo->modifiers = mods; - return TRUE; -} - -gboolean -meta_parse_accelerator (const char *accel, - MetaKeyCombo *combo) -{ - g_return_val_if_fail (combo != NULL, FALSE); - - *combo = (MetaKeyCombo) { 0 }; - - if (!accel[0] || strcmp (accel, "disabled") == 0) - return TRUE; - - return accelerator_parse (accel, combo); -} - -gboolean -meta_parse_modifier (const char *accel, - MetaVirtualModifier *mask) -{ - MetaKeyCombo combo = { 0 }; - - g_return_val_if_fail (mask != NULL, FALSE); - - *mask = 0; - - if (accel == NULL || !accel[0] || strcmp (accel, "disabled") == 0) - return TRUE; - - if (!accelerator_parse (accel, &combo)) - return FALSE; - - *mask = combo.modifiers; - return TRUE; -} diff --git a/src/core/meta-accel-parse.h b/src/core/meta-accel-parse.h deleted file mode 100644 index 12cf3f982..000000000 --- a/src/core/meta-accel-parse.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -#ifndef META_ACCEL_PARSE_H -#define META_ACCEL_PARSE_H - -#include - -#include "meta/common.h" - -typedef struct _MetaKeyCombo MetaKeyCombo; - -/* Not a real key symbol but means "key above the tab key"; this is - * used as the default keybinding for cycle_group. - * 0x2xxxxxxx is a range not used by GDK or X. the remaining digits are - * randomly chosen */ -#define META_KEY_ABOVE_TAB 0x2f7259c9 - -gboolean meta_parse_accelerator (const char *accel, - MetaKeyCombo *combo); -gboolean meta_parse_modifier (const char *accel, - MetaVirtualModifier *mask); - -#endif /* META_ACCEL_PARSE_H */ diff --git a/src/core/meta-anonymous-file.c b/src/core/meta-anonymous-file.c deleted file mode 100644 index 95b63c9f0..000000000 --- a/src/core/meta-anonymous-file.c +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Copyright (C) 2020 Sebastian Wick - * - * 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: Sebastian Wick - */ - -#include "config.h" - -#include -#include -#include - -#include "core/meta-anonymous-file.h" - -struct _MetaAnonymousFile -{ - int fd; - size_t size; -}; - -#define READONLY_SEALS (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE) - -static int -create_tmpfile_cloexec (char *tmpname) -{ - int fd; - -#if defined(HAVE_MKOSTEMP) - fd = mkostemp (tmpname, O_CLOEXEC); - if (fd >= 0) - unlink (tmpname); -#else - fd = mkstemp (tmpname); - if (fd >= 0) - { - long flags; - - unlink (tmpname); - - flags = fcntl (fd, F_GETFD); - if (flags == -1 || - fcntl (fd, F_SETFD, flags | FD_CLOEXEC) == -1) - { - close (fd); - return -1; - } - } -#endif - - return fd; -} - -/* - * Create a new, unique, anonymous file of the given size, and - * return the file descriptor for it. The file descriptor is set - * CLOEXEC. The file is immediately suitable for mmap()'ing - * the given size at offset zero. - * - * The file should not have a permanent backing store like a disk, - * but may have if XDG_RUNTIME_DIR is not properly implemented in OS. - * - * The file name is deleted from the file system. - * - * The file is suitable for buffer sharing between processes by - * transmitting the file descriptor over Unix sockets using the - * SCM_RIGHTS methods. - * - * If the C library implements posix_fallocate(), it is used to - * guarantee that disk space is available for the file at the - * given size. If disk space is insufficient, errno is set to ENOSPC. - * If posix_fallocate() is not supported, program may receive - * SIGBUS on accessing mmap()'ed file contents instead. - * - * If the C library implements memfd_create(), it is used to create the - * file purely in memory, without any backing file name on the file - * system, and then sealing off the possibility of shrinking it. This - * can then be checked before accessing mmap()'ed file contents, to make - * sure SIGBUS can't happen. It also avoids requiring XDG_RUNTIME_DIR. - */ -static int -create_anonymous_file (off_t size) -{ - int fd, ret; - -#if defined(HAVE_MEMFD_CREATE) - fd = memfd_create ("mutter-shared", MFD_CLOEXEC | MFD_ALLOW_SEALING); - if (fd >= 0) - { - /* We can add this seal before calling posix_fallocate(), as - * the file is currently zero-sized anyway. - * - * There is also no need to check for the return value, we - * couldn't do anything with it anyway. - */ - fcntl (fd, F_ADD_SEALS, F_SEAL_SHRINK); - } - else -#endif - { - static const char template[] = "/mutter-shared-XXXXXX"; - const char *path; - char *name; - - path = getenv ("XDG_RUNTIME_DIR"); - if (!path) - { - errno = ENOENT; - return -1; - } - - name = g_malloc (strlen (path) + sizeof (template)); - if (!name) - return -1; - - strcpy (name, path); - strcat (name, template); - - fd = create_tmpfile_cloexec (name); - - g_free (name); - - if (fd < 0) - return -1; - } - -#if defined(HAVE_POSIX_FALLOCATE) - do - { - ret = posix_fallocate (fd, 0, size); - } - while (ret == EINTR); - - if (ret != 0) - { - close (fd); - errno = ret; - return -1; - } -#else - do - { - ret = ftruncate (fd, size); - } - while (ret < 0 && errno == EINTR); - - if (ret < 0) - { - close (fd); - return -1; - } -#endif - - return fd; -} - -/** - * meta_anonymous_file_new: (skip) - * @size: The size of @data - * @data: The data of the file with the size @size - * - * Create a new anonymous read-only file of the given size and the given data - * The intended use-case is for sending mid-sized data from the compositor - * to clients. - * - * When done, free the data using meta_anonymous_file_free(). - * - * If this function fails errno is set. - * - * Returns: The newly created #MetaAnonymousFile, or NULL on failure. Use - * meta_anonymous_file_free() to free the resources when done. - */ -MetaAnonymousFile * -meta_anonymous_file_new (size_t size, - const uint8_t *data) -{ - MetaAnonymousFile *file; - void *map; - - file = g_malloc0 (sizeof *file); - if (!file) - { - errno = ENOMEM; - return NULL; - } - - file->size = size; - file->fd = create_anonymous_file (size); - if (file->fd == -1) - goto err_free; - - map = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, file->fd, 0); - if (map == MAP_FAILED) - goto err_close; - - memcpy (map, data, size); - - munmap (map, size); - -#if defined(HAVE_MEMFD_CREATE) - /* try to put seals on the file to make it read-only so that we can - * return the fd later directly when MAPMODE_SHARED is not set. - * meta_anonymous_file_open_fd can handle the fd even if it is not - * sealed read-only and will instead create a new anonymous file on - * each invocation. - */ - fcntl (file->fd, F_ADD_SEALS, READONLY_SEALS); -#endif - - return file; - -err_close: - close (file->fd); -err_free: - g_free (file); - return NULL; -} - - -/** - * meta_anonymous_file_free: (skip) - * @file: the #MetaAnonymousFile - * - * Free the resources used by an anonymous read-only file. - */ -void -meta_anonymous_file_free (MetaAnonymousFile *file) -{ - close (file->fd); - g_free (file); -} - -/** - * meta_anonymous_file_size: (skip) - * @file: the #MetaAnonymousFile - * - * Get the size of an anonymous read-only file. - * - * Returns: The size of the anonymous read-only file. - */ -size_t -meta_anonymous_file_size (MetaAnonymousFile *file) -{ - return file->size; -} - -/** - * meta_anonymous_file_open_fd: (skip) - * @file: the #MetaAnonymousFile to get a file descriptor for - * @mapmode: describes the ways in which the returned file descriptor can - * be used with mmap - * - * Returns a file descriptor for the given file, ready to be sent to a client. - * The returned file descriptor must not be shared between multiple clients. - * If @mapmode is %META_ANONYMOUS_FILE_MAPMODE_PRIVATE the file descriptor is - * only guaranteed to be mmapable with MAP_PRIVATE. If @mapmode is - * %META_ANONYMOUS_FILE_MAPMODE_SHARED the file descriptor can be mmaped with - * either MAP_PRIVATE or MAP_SHARED. - * - * In case %META_ANONYMOUS_FILE_MAPMODE_PRIVATE is used, it is important to - * only read the returned fd using mmap() since using read() will move the - * read cursor of the fd and thus may cause read() calls on other returned - * fds to fail. - * - * When done using the fd, it is required to call meta_anonymous_file_close_fd() - * instead of close(). - * - * If this function fails errno is set. - * - * Returns: A file descriptor for the given file that can be sent to a client - * or -1 on failure. Use meta_anonymous_file_close_fd() to release the fd - * when done. - */ -int -meta_anonymous_file_open_fd (MetaAnonymousFile *file, - MetaAnonymousFileMapmode mapmode) -{ - void *src, *dst; - int fd; - -#if defined(HAVE_MEMFD_CREATE) - int seals; - - seals = fcntl (file->fd, F_GET_SEALS); - - /* file was sealed for read-only and we don't have to support MAP_SHARED - * so we can simply pass the memfd fd - */ - if (seals != -1 && mapmode == META_ANONYMOUS_FILE_MAPMODE_PRIVATE && - (seals & READONLY_SEALS) == READONLY_SEALS) - return file->fd; -#endif - - /* for all other cases we create a new anonymous file that can be mapped - * with MAP_SHARED and copy the contents to it and return that instead - */ - fd = create_anonymous_file (file->size); - if (fd == -1) - return fd; - - src = mmap (NULL, file->size, PROT_READ, MAP_PRIVATE, file->fd, 0); - if (src == MAP_FAILED) - { - close (fd); - return -1; - } - - dst = mmap (NULL, file->size, PROT_WRITE, MAP_SHARED, fd, 0); - if (dst == MAP_FAILED) - { - close (fd); - munmap (src, file->size); - return -1; - } - - memcpy (dst, src, file->size); - munmap (src, file->size); - munmap (dst, file->size); - - return fd; -} - -/** - * meta_anonymous_file_close_fd: (skip) - * @fd: A file descriptor obtained using meta_anonymous_file_open_fd() - * - * Release a file descriptor returned by meta_anonymous_file_open_fd(). - * This function must be called for every file descriptor created with - * meta_anonymous_file_open_fd() to not leak any resources. - * - * If this function fails errno is set. - */ -void -meta_anonymous_file_close_fd (int fd) -{ -#if defined(HAVE_MEMFD_CREATE) - int seals; - - seals = fcntl (fd, F_GET_SEALS); - if (seals == -1 && errno != EINVAL) - { - g_warning ("Reading seals of anonymous file %d failed", fd); - return; - } - - /* The only case in which we do NOT have to close the file is when the file - * was sealed for read-only - */ - if (seals != -1 && (seals & READONLY_SEALS) == READONLY_SEALS) - return; -#endif - - close (fd); -} diff --git a/src/core/meta-anonymous-file.h b/src/core/meta-anonymous-file.h deleted file mode 100644 index 5289c7193..000000000 --- a/src/core/meta-anonymous-file.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2020 Sebastian Wick - * - * 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: Sebastian Wick - */ - -#ifndef META_ANONYMOUS_FILE_H -#define META_ANONYMOUS_FILE_H - -#include "meta/common.h" -#include "core/util-private.h" - -typedef struct _MetaAnonymousFile MetaAnonymousFile; - -typedef enum _MetaAnonymousFileMapmode -{ - META_ANONYMOUS_FILE_MAPMODE_PRIVATE, - META_ANONYMOUS_FILE_MAPMODE_SHARED, -} MetaAnonymousFileMapmode; - -META_EXPORT_TEST -MetaAnonymousFile * meta_anonymous_file_new (size_t size, - const uint8_t *data); - -META_EXPORT_TEST -void meta_anonymous_file_free (MetaAnonymousFile *file); - -META_EXPORT_TEST -size_t meta_anonymous_file_size (MetaAnonymousFile *file); - -META_EXPORT_TEST -int meta_anonymous_file_open_fd (MetaAnonymousFile *file, - MetaAnonymousFileMapmode mapmode); - -META_EXPORT_TEST -void meta_anonymous_file_close_fd (int fd); - -#endif /* META_ANONYMOUS_FILE_H */ diff --git a/src/core/meta-border.c b/src/core/meta-border.c deleted file mode 100644 index 3c926c419..000000000 --- a/src/core/meta-border.c +++ /dev/null @@ -1,154 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#include "config.h" - -#include "core/meta-border.h" - -#include - -static inline float -meta_vector2_cross_product (const MetaVector2 a, - const MetaVector2 b) -{ - return a.x * b.y - a.y * b.x; -} - -static inline MetaVector2 -meta_vector2_add (const MetaVector2 a, - const MetaVector2 b) -{ - return (MetaVector2) { - .x = a.x + b.x, - .y = a.y + b.y, - }; -} - -static inline MetaVector2 -meta_vector2_multiply_constant (const float c, - const MetaVector2 a) -{ - return (MetaVector2) { - .x = c * a.x, - .y = c * a.y, - }; -} - -gboolean -meta_line2_intersects_with (const MetaLine2 *line1, - const MetaLine2 *line2, - MetaVector2 *intersection) -{ - MetaVector2 p = line1->a; - MetaVector2 r = meta_vector2_subtract (line1->b, line1->a); - MetaVector2 q = line2->a; - MetaVector2 s = meta_vector2_subtract (line2->b, line2->a); - float rxs; - float sxr; - float t; - float u; - - /* - * The line (p, r) and (q, s) intersects where - * - * p + t r = q + u s - * - * Calculate t: - * - * (p + t r) × s = (q + u s) × s - * p × s + t (r × s) = q × s + u (s × s) - * p × s + t (r × s) = q × s - * t (r × s) = q × s - p × s - * t (r × s) = (q - p) × s - * t = ((q - p) × s) / (r × s) - * - * Using the same method, for u we get: - * - * u = ((p - q) × r) / (s × r) - */ - - rxs = meta_vector2_cross_product (r, s); - sxr = meta_vector2_cross_product (s, r); - - /* If r × s = 0 then the lines are either parallel or collinear. */ - if (fabsf (rxs) < FLT_MIN) - return FALSE; - - t = meta_vector2_cross_product (meta_vector2_subtract (q, p), s) / rxs; - u = meta_vector2_cross_product (meta_vector2_subtract (p, q), r) / sxr; - - /* The lines only intersect if 0 ≤ t ≤ 1 and 0 ≤ u ≤ 1. */ - if (t < 0.0 || t > 1.0 || u < 0.0 || u > 1.0) - return FALSE; - - *intersection = meta_vector2_add (p, meta_vector2_multiply_constant (t, r)); - - return TRUE; -} - -gboolean -meta_border_is_horizontal (MetaBorder *border) -{ - return border->line.a.y == border->line.b.y; -} - -gboolean -meta_border_is_blocking_directions (MetaBorder *border, - MetaBorderMotionDirection directions) -{ - if (meta_border_is_horizontal (border)) - { - if ((directions & (META_BORDER_MOTION_DIRECTION_POSITIVE_Y | - META_BORDER_MOTION_DIRECTION_NEGATIVE_Y)) == 0) - return FALSE; - } - else - { - if ((directions & (META_BORDER_MOTION_DIRECTION_POSITIVE_X | - META_BORDER_MOTION_DIRECTION_NEGATIVE_X)) == 0) - return FALSE; - } - - return (~border->blocking_directions & directions) != directions; -} - -unsigned int -meta_border_get_allows_directions (MetaBorder *border) -{ - return ~border->blocking_directions & - (META_BORDER_MOTION_DIRECTION_POSITIVE_X | - META_BORDER_MOTION_DIRECTION_POSITIVE_Y | - META_BORDER_MOTION_DIRECTION_NEGATIVE_X | - META_BORDER_MOTION_DIRECTION_NEGATIVE_Y); -} - -void -meta_border_set_allows_directions (MetaBorder *border, unsigned int directions) -{ - border->blocking_directions = - ~directions & (META_BORDER_MOTION_DIRECTION_POSITIVE_X | - META_BORDER_MOTION_DIRECTION_POSITIVE_Y | - META_BORDER_MOTION_DIRECTION_NEGATIVE_X | - META_BORDER_MOTION_DIRECTION_NEGATIVE_Y); -} diff --git a/src/core/meta-border.h b/src/core/meta-border.h deleted file mode 100644 index dd76db5c9..000000000 --- a/src/core/meta-border.h +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#ifndef META_BORDER_H -#define META_BORDER_H - -#include - -typedef enum -{ - META_BORDER_MOTION_DIRECTION_POSITIVE_X = 1 << 0, - META_BORDER_MOTION_DIRECTION_POSITIVE_Y = 1 << 1, - META_BORDER_MOTION_DIRECTION_NEGATIVE_X = 1 << 2, - META_BORDER_MOTION_DIRECTION_NEGATIVE_Y = 1 << 3, -} MetaBorderMotionDirection; - -typedef struct _MetaVector2 -{ - float x; - float y; -} MetaVector2; - -typedef struct _MetaLine2 -{ - MetaVector2 a; - MetaVector2 b; -} MetaLine2; - -typedef struct _MetaBorder -{ - MetaLine2 line; - MetaBorderMotionDirection blocking_directions; -} MetaBorder; - -static inline MetaVector2 -meta_vector2_subtract (const MetaVector2 a, - const MetaVector2 b) -{ - return (MetaVector2) { - .x = a.x - b.x, - .y = a.y - b.y, - }; -} - -gboolean -meta_line2_intersects_with (const MetaLine2 *line1, - const MetaLine2 *line2, - MetaVector2 *intersection); - -gboolean -meta_border_is_horizontal (MetaBorder *border); - -gboolean -meta_border_is_blocking_directions (MetaBorder *border, - MetaBorderMotionDirection directions); - -unsigned int -meta_border_get_allows_directions (MetaBorder *border); - -void -meta_border_set_allows_directions (MetaBorder *border, unsigned int directions); - -#endif /* META_BORDER_H */ diff --git a/src/core/meta-clipboard-manager.c b/src/core/meta-clipboard-manager.c deleted file mode 100644 index 794195f41..000000000 --- a/src/core/meta-clipboard-manager.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2018 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: Carlos Garnacho - */ - -#include "config.h" - -#include "core/meta-clipboard-manager.h" -#include "meta/meta-selection-source-memory.h" - -#define MAX_TEXT_SIZE (4 * 1024 * 1024) /* 4MB */ -#define MAX_IMAGE_SIZE (200 * 1024 * 1024) /* 200MB */ - -/* Supported mimetype globs, from least to most preferred */ -static struct { - const char *mimetype_glob; - ssize_t max_transfer_size; -} supported_mimetypes[] = { - { "image/tiff", MAX_IMAGE_SIZE }, - { "image/bmp", MAX_IMAGE_SIZE }, - { "image/gif", MAX_IMAGE_SIZE }, - { "image/jpeg", MAX_IMAGE_SIZE }, - { "image/webp", MAX_IMAGE_SIZE }, - { "image/png", MAX_IMAGE_SIZE }, - { "image/svg+xml", MAX_IMAGE_SIZE }, - { "text/plain", MAX_TEXT_SIZE }, - { "text/plain;charset=utf-8", MAX_TEXT_SIZE }, -}; - -static gboolean -mimetype_match (const char *mimetype, - int *idx, - gssize *max_transfer_size) -{ - int i; - - for (i = 0; i < G_N_ELEMENTS (supported_mimetypes); i++) - { - if (g_pattern_match_simple (supported_mimetypes[i].mimetype_glob, mimetype)) - { - *max_transfer_size = supported_mimetypes[i].max_transfer_size; - *idx = i; - return TRUE; - } - } - - return FALSE; -} - -static void -transfer_cb (MetaSelection *selection, - GAsyncResult *result, - GOutputStream *output) -{ - MetaDisplay *display = meta_get_display (); - GError *error = NULL; - - if (!meta_selection_transfer_finish (selection, result, &error)) - { - g_warning ("Failed to store clipboard: %s", error->message); - g_error_free (error); - g_object_unref (output); - return; - } - - g_output_stream_close (output, NULL, NULL); - display->saved_clipboard = - g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (output)); - g_object_unref (output); -} - -static void -owner_changed_cb (MetaSelection *selection, - MetaSelectionType selection_type, - MetaSelectionSource *new_owner, - MetaDisplay *display) -{ - if (selection_type != META_SELECTION_CLIPBOARD) - return; - - if (new_owner && new_owner != display->selection_source) - { - GOutputStream *output; - GList *mimetypes, *l; - int best_idx = -1; - const char *best = NULL; - ssize_t transfer_size = -1; - - /* New selection source, find the best mimetype in order to - * keep a copy of it. - */ - g_clear_object (&display->selection_source); - g_clear_pointer (&display->saved_clipboard_mimetype, g_free); - g_clear_pointer (&display->saved_clipboard, g_bytes_unref); - - mimetypes = meta_selection_get_mimetypes (selection, selection_type); - - for (l = mimetypes; l; l = l->next) - { - gssize max_transfer_size; - int idx; - - if (!mimetype_match (l->data, &idx, &max_transfer_size)) - continue; - - if (best_idx < idx) - { - best_idx = idx; - best = l->data; - transfer_size = max_transfer_size; - } - } - - if (best_idx < 0) - { - g_list_free_full (mimetypes, g_free); - return; - } - - display->saved_clipboard_mimetype = g_strdup (best); - g_list_free_full (mimetypes, g_free); - output = g_memory_output_stream_new_resizable (); - meta_selection_transfer_async (selection, - META_SELECTION_CLIPBOARD, - display->saved_clipboard_mimetype, - transfer_size, - output, - NULL, - (GAsyncReadyCallback) transfer_cb, - output); - } - else if (!new_owner && display->saved_clipboard) - { - /* Old owner is gone, time to take over */ - new_owner = meta_selection_source_memory_new (display->saved_clipboard_mimetype, - display->saved_clipboard); - g_set_object (&display->selection_source, new_owner); - meta_selection_set_owner (selection, selection_type, new_owner); - g_object_unref (new_owner); - } -} - -void -meta_clipboard_manager_init (MetaDisplay *display) -{ - MetaSelection *selection; - - selection = meta_display_get_selection (display); - g_signal_connect_after (selection, "owner-changed", - G_CALLBACK (owner_changed_cb), display); -} - -void -meta_clipboard_manager_shutdown (MetaDisplay *display) -{ - MetaSelection *selection; - - g_clear_object (&display->selection_source); - g_clear_pointer (&display->saved_clipboard, g_bytes_unref); - g_clear_pointer (&display->saved_clipboard_mimetype, g_free); - selection = meta_display_get_selection (display); - g_signal_handlers_disconnect_by_func (selection, owner_changed_cb, display); -} diff --git a/src/core/meta-clipboard-manager.h b/src/core/meta-clipboard-manager.h deleted file mode 100644 index 2ba130f9b..000000000 --- a/src/core/meta-clipboard-manager.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2018 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: Carlos Garnacho - */ - -#ifndef META_CLIPBOARD_MANAGER_H -#define META_CLIPBOARD_MANAGER_H - -#include "core/display-private.h" - -void meta_clipboard_manager_init (MetaDisplay *display); -void meta_clipboard_manager_shutdown (MetaDisplay *display); - -#endif /* META_CLIPBOARD_MANAGER_H */ diff --git a/src/core/meta-close-dialog-default-private.h b/src/core/meta-close-dialog-default-private.h deleted file mode 100644 index f149d3686..000000000 --- a/src/core/meta-close-dialog-default-private.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 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, see . - * - * Author: Carlos Garnacho - */ - -#ifndef META_CLOSE_DIALOG_DEFAULT_H -#define META_CLOSE_DIALOG_DEFAULT_H - -#include - -#include "meta/meta-plugin.h" - -#define META_TYPE_CLOSE_DIALOG_DEFAULT (meta_close_dialog_default_get_type ()) -G_DECLARE_FINAL_TYPE (MetaCloseDialogDefault, - meta_close_dialog_default, - META, CLOSE_DIALOG_DEFAULT, - GObject) - -MetaCloseDialog * meta_close_dialog_default_new (MetaWindow *window); - -#endif /* META_CLOSE_DIALOG_DEFAULT_H */ diff --git a/src/core/meta-close-dialog-default.c b/src/core/meta-close-dialog-default.c deleted file mode 100644 index 544a5b62d..000000000 --- a/src/core/meta-close-dialog-default.c +++ /dev/null @@ -1,281 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001, 2002 Havoc Pennington - * Copyright (C) 2004 Elijah Newren - * Copyright (C) 2016 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, see . - * - * Author: Carlos Garnacho - */ - -#define _XOPEN_SOURCE /* for kill() */ - -#include "config.h" - -#include "core/meta-close-dialog-default-private.h" -#include "meta/meta-close-dialog.h" - -#include -#include -#include - -#include "core/util-private.h" -#include "core/window-private.h" -#include "x11/meta-x11-display-private.h" - -typedef struct _MetaCloseDialogDefaultPrivate MetaCloseDialogDefaultPrivate; - -struct _MetaCloseDialogDefault -{ - GObject parent_instance; - MetaWindow *window; - int dialog_pid; - guint child_watch_id; -}; - -enum -{ - PROP_0, - PROP_WINDOW, - N_PROPS -}; - -GParamSpec *pspecs[N_PROPS] = { NULL }; - -static void meta_close_dialog_iface_init (MetaCloseDialogInterface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaCloseDialogDefault, meta_close_dialog_default, - G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (META_TYPE_CLOSE_DIALOG, - meta_close_dialog_iface_init)) - -static void -dialog_exited (GPid pid, - int status, - gpointer user_data) -{ - MetaCloseDialogDefault *dialog = user_data; - - dialog->dialog_pid = -1; - - /* exit status of 0 means the user pressed "Force Quit" */ - if (WIFEXITED (status) && WEXITSTATUS (status) == 0) - g_signal_emit_by_name (dialog, "response", META_CLOSE_DIALOG_RESPONSE_FORCE_CLOSE); -} - -static void -present_existing_delete_dialog (MetaCloseDialogDefault *dialog) -{ - MetaWindow *window; - GSList *windows; - GSList *tmp; - - window = dialog->window; - - if (dialog->dialog_pid < 0) - return; - - meta_topic (META_DEBUG_PING, - "Presenting existing ping dialog for %s", - window->desc); - - /* Activate transient for window that belongs to - * mutter-dialog - */ - windows = meta_display_list_windows (window->display, META_LIST_DEFAULT); - tmp = windows; - - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - - if (w->transient_for == window && w->res_class && - g_ascii_strcasecmp (w->res_class, "mutter-dialog") == 0) - { - meta_window_activate (w, CLUTTER_CURRENT_TIME); - break; - } - - tmp = tmp->next; - } - - g_slist_free (windows); -} - -static void -meta_close_dialog_default_show (MetaCloseDialog *dialog) -{ - MetaCloseDialogDefault *dialog_default = META_CLOSE_DIALOG_DEFAULT (dialog); - MetaWindow *window = dialog_default->window; - gchar *window_title, *window_content, *tmp; - GPid dialog_pid; - - if (dialog_default->dialog_pid >= 0) - { - present_existing_delete_dialog (dialog_default); - return; - } - - /* This is to get a better string if the title isn't representable - * in the locale encoding; actual conversion to UTF-8 is done inside - * meta_show_dialog */ - if (window->title && window->title[0]) - { - tmp = g_locale_from_utf8 (window->title, -1, NULL, NULL, NULL); - if (tmp == NULL) - window_title = NULL; - else - window_title = window->title; - g_free (tmp); - } - else - { - window_title = NULL; - } - - if (window_title) - /* Translators: %s is a window title */ - tmp = g_strdup_printf (_("“%s” is not responding."), window_title); - else - tmp = g_strdup (_("Application is not responding.")); - - window_content = g_strdup_printf ( - "%s\n\n%s", - tmp, - _("You may choose to wait a short while for it to " - "continue or force the application to quit entirely.")); - - dialog_pid = - meta_show_dialog ("--question", - window_content, NULL, - window->display->x11_display->screen_name, - _("_Force Quit"), _("_Wait"), - "face-sad-symbolic", window->xwindow, - NULL, NULL); - - g_free (window_content); - g_free (tmp); - - dialog_default->dialog_pid = dialog_pid; - g_child_watch_add (dialog_pid, dialog_exited, dialog); -} - -static void -meta_close_dialog_default_hide (MetaCloseDialog *dialog) -{ - MetaCloseDialogDefault *dialog_default; - - dialog_default = META_CLOSE_DIALOG_DEFAULT (dialog); - - g_clear_handle_id (&dialog_default->child_watch_id, g_source_remove); - - if (dialog_default->dialog_pid > -1) - { - kill (dialog_default->dialog_pid, SIGTERM); - dialog_default->dialog_pid = -1; - } -} - -static void -meta_close_dialog_iface_init (MetaCloseDialogInterface *iface) -{ - iface->show = meta_close_dialog_default_show; - iface->hide = meta_close_dialog_default_hide; -} - -static void -meta_close_dialog_default_finalize (GObject *object) -{ - MetaCloseDialogDefault *dialog; - - dialog = META_CLOSE_DIALOG_DEFAULT (object); - - g_clear_handle_id (&dialog->child_watch_id, g_source_remove); - - if (dialog->dialog_pid > -1) - { - kill (dialog->dialog_pid, SIGKILL); - dialog->dialog_pid = -1; - } - - G_OBJECT_CLASS (meta_close_dialog_default_parent_class)->finalize (object); -} - -static void -meta_close_dialog_default_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaCloseDialogDefault *dialog; - - dialog = META_CLOSE_DIALOG_DEFAULT (object); - - switch (prop_id) - { - case PROP_WINDOW: - dialog->window = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_close_dialog_default_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaCloseDialogDefault *dialog; - - dialog = META_CLOSE_DIALOG_DEFAULT (object); - - switch (prop_id) - { - case PROP_WINDOW: - g_value_set_object (value, dialog->window); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_close_dialog_default_class_init (MetaCloseDialogDefaultClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_close_dialog_default_finalize; - object_class->set_property = meta_close_dialog_default_set_property; - object_class->get_property = meta_close_dialog_default_get_property; - - g_object_class_override_property (object_class, PROP_WINDOW, "window"); -} - -static void -meta_close_dialog_default_init (MetaCloseDialogDefault *dialog) -{ - dialog->dialog_pid = -1; -} - -MetaCloseDialog * -meta_close_dialog_default_new (MetaWindow *window) -{ - return g_object_new (META_TYPE_CLOSE_DIALOG_DEFAULT, - "window", window, - NULL); -} diff --git a/src/core/meta-close-dialog.c b/src/core/meta-close-dialog.c deleted file mode 100644 index 6d24fa570..000000000 --- a/src/core/meta-close-dialog.c +++ /dev/null @@ -1,144 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 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, see . - * - * Author: Carlos Garnacho - */ - -#include "config.h" - -#include "core/window-private.h" -#include "meta/meta-close-dialog.h" -#include "meta/meta-enum-types.h" - -enum -{ - RESPONSE, - N_SIGNALS -}; - -guint dialog_signals[N_SIGNALS] = { 0 }; - -static GQuark quark_visible = 0; - -G_DEFINE_INTERFACE (MetaCloseDialog, meta_close_dialog, G_TYPE_OBJECT) - -static void -meta_close_dialog_default_init (MetaCloseDialogInterface *iface) -{ - g_object_interface_install_property (iface, - g_param_spec_object ("window", - "Window", - "Window", - META_TYPE_WINDOW, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY)); - dialog_signals[RESPONSE] = - g_signal_new ("response", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 1, META_TYPE_CLOSE_DIALOG_RESPONSE); - - quark_visible = g_quark_from_static_string ("meta-close-dialog-visible"); -} - -/** - * meta_close_dialog_show: - * @dialog: a #MetaCloseDialog - * - * Shows the close dialog. - **/ -void -meta_close_dialog_show (MetaCloseDialog *dialog) -{ - MetaCloseDialogInterface *iface; - - g_return_if_fail (META_IS_CLOSE_DIALOG (dialog)); - - iface = META_CLOSE_DIALOG_GET_IFACE (dialog); - iface->show (dialog); - g_object_set_qdata (G_OBJECT (dialog), quark_visible, GINT_TO_POINTER (TRUE)); -} - -/** - * meta_close_dialog_hide: - * @dialog: a #MetaCloseDialog - * - * Hides the close dialog. - **/ -void -meta_close_dialog_hide (MetaCloseDialog *dialog) -{ - MetaCloseDialogInterface *iface; - - g_return_if_fail (META_IS_CLOSE_DIALOG (dialog)); - - iface = META_CLOSE_DIALOG_GET_IFACE (dialog); - iface->hide (dialog); - g_object_steal_qdata (G_OBJECT (dialog), quark_visible); -} - -/** - * meta_close_dialog_response: - * @dialog: a #MetaCloseDialog - * @response: a #MetaCloseDialogResponse - * - * Responds and closes the dialog. To be called by #MetaCloseDialog - * implementations. - **/ -void -meta_close_dialog_response (MetaCloseDialog *dialog, - MetaCloseDialogResponse response) -{ - g_signal_emit (dialog, dialog_signals[RESPONSE], 0, response); - meta_close_dialog_hide (dialog); -} - -/** - * meta_close_dialog_is_visible: - * @dialog: a #MetaCloseDialog - * - * Returns whether @dialog is currently visible. - * - * Returns: #TRUE if @dialog is visible. - **/ -gboolean -meta_close_dialog_is_visible (MetaCloseDialog *dialog) -{ - return GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (dialog), quark_visible)); -} - -/** - * meta_close_dialog_focus: - * @dialog: a #MetaCloseDialog - * - * Call whenever @dialog should receive keyboard focus, - * usually when the window would. - **/ -void -meta_close_dialog_focus (MetaCloseDialog *dialog) -{ - MetaCloseDialogInterface *iface; - - g_return_if_fail (META_IS_CLOSE_DIALOG (dialog)); - - iface = META_CLOSE_DIALOG_GET_IFACE (dialog); - if (iface->focus) - iface->focus (dialog); -} diff --git a/src/core/meta-context-main.c b/src/core/meta-context-main.c deleted file mode 100644 index 8f669151a..000000000 --- a/src/core/meta-context-main.c +++ /dev/null @@ -1,702 +0,0 @@ -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2006 Elijah Newren - * Copyright (C) 2021 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "core/meta-context-main.h" - -#include -#include - -#if defined(HAVE_NATIVE_BACKEND) && defined(HAVE_WAYLAND) -#include -#endif /* HAVE_WAYLAND && HAVE_NATIVE_BACKEND */ - -#include "backends/meta-monitor-manager-private.h" -#include "backends/meta-virtual-monitor.h" -#include "backends/x11/cm/meta-backend-x11-cm.h" -#include "meta/meta-backend.h" -#include "wayland/meta-wayland.h" -#include "x11/session.h" - -#ifdef HAVE_NATIVE_BACKEND -#include "backends/native/meta-backend-native.h" -#endif - -#ifdef HAVE_WAYLAND -#include "backends/x11/nested/meta-backend-x11-nested.h" -#endif - -typedef struct _MetaContextMainOptions -{ - struct { - char *display_name; - gboolean replace; - gboolean sync; - gboolean force; - } x11; - struct { - char *save_file; - char *client_id; - gboolean disable; - } sm; -#ifdef HAVE_WAYLAND - gboolean wayland; - gboolean nested; - gboolean no_x11; - char *wayland_display; -#endif -#ifdef HAVE_NATIVE_BACKEND - gboolean display_server; - gboolean headless; -#endif -#ifdef HAVE_NATIVE_BACKEND - GList *virtual_monitor_infos; -#endif -} MetaContextMainOptions; - -struct _MetaContextMain -{ - GObject parent; - - MetaContextMainOptions options; - - MetaCompositorType compositor_type; - - GList *persistent_virtual_monitors; -}; - -G_DEFINE_TYPE (MetaContextMain, meta_context_main, META_TYPE_CONTEXT) - -static gboolean -check_configuration (MetaContextMain *context_main, - GError **error) -{ -#ifdef HAVE_WAYLAND - if (context_main->options.x11.force && context_main->options.no_x11) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, - "Can't run in X11 mode with no X11"); - return FALSE; - } - if (context_main->options.x11.force && context_main->options.wayland) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, - "Can't run in X11 mode with Wayland enabled"); - return FALSE; - } - if (context_main->options.x11.force && context_main->options.nested) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, - "Can't run in X11 mode nested"); - return FALSE; - } -#endif /* HAVE_WAYLAND */ - -#ifdef HAVE_NATIVE_BACKEND - if (context_main->options.x11.force && context_main->options.display_server) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, - "Can't run in X11 mode as a display server"); - return FALSE; - } - - if (context_main->options.x11.force && context_main->options.headless) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, - "Can't run in X11 mode headlessly"); - return FALSE; - } - - if (context_main->options.display_server && context_main->options.headless) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, - "Can't run in display server mode headlessly"); - return FALSE; - } -#endif /* HAVE_NATIVE_BACKEND */ - - if (context_main->options.sm.save_file && - context_main->options.sm.client_id) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, - "Can't specify both SM save file and SM client id"); - return FALSE; - } - - return TRUE; -} - -#if defined(HAVE_WAYLAND) && defined(HAVE_NATIVE_BACKEND) -static gboolean -session_type_is_supported (const char *session_type) -{ - return (g_strcmp0 (session_type, "x11") == 0) || - (g_strcmp0 (session_type, "wayland") == 0); -} - -static char * -find_session_type (GError **error) -{ - char **sessions = NULL; - char *session_id; - char *session_type; - const char *session_type_env; - gboolean is_tty = FALSE; - int ret, i; - - ret = sd_pid_get_session (0, &session_id); - if (ret == 0 && session_id != NULL) - { - ret = sd_session_get_type (session_id, &session_type); - free (session_id); - - if (ret == 0) - { - if (session_type_is_supported (session_type)) - goto out; - else - is_tty = g_strcmp0 (session_type, "tty") == 0; - free (session_type); - } - } - else if (sd_uid_get_sessions (getuid (), 1, &sessions) > 0) - { - for (i = 0; sessions[i] != NULL; i++) - { - ret = sd_session_get_type (sessions[i], &session_type); - - if (ret < 0) - continue; - - if (session_type_is_supported (session_type)) - { - g_strfreev (sessions); - goto out; - } - - free (session_type); - } - } - g_strfreev (sessions); - - session_type_env = g_getenv ("XDG_SESSION_TYPE"); - if (session_type_is_supported (session_type_env)) - { - /* The string should be freeable */ - session_type = strdup (session_type_env); - goto out; - } - - /* Legacy support for starting through xinit */ - if (is_tty && (g_getenv ("MUTTER_DISPLAY") || g_getenv ("DISPLAY"))) - { - session_type = strdup ("x11"); - goto out; - } - - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Unsupported session type"); - return NULL; - -out: - return session_type; -} -#else /* defined(HAVE_WAYLAND) && defined(HAVE_NATIVE_BACKEND) */ -static char * -find_session_type (GError **error) -{ - return g_strdup ("x11"); -} -#endif /* defined(HAVE_WAYLAND) && defined(HAVE_NATIVE_BACKEND) */ - -static MetaCompositorType -determine_compositor_type (MetaContextMain *context_main, - GError **error) -{ - g_autofree char *session_type = NULL; - -#ifdef HAVE_WAYLAND - if (context_main->options.wayland || -#ifdef HAVE_NATIVE_BACKEND - context_main->options.display_server || - context_main->options.headless || -#endif /* HAVE_NATIVE_BACKEND */ - context_main->options.nested) - return META_COMPOSITOR_TYPE_WAYLAND; -#endif /* HAVE_WAYLAND */ - - if (context_main->options.x11.force) - return META_COMPOSITOR_TYPE_X11; - - session_type = find_session_type (error); - if (!session_type) - return -1; - - if (strcmp (session_type, "x11") == 0) - return META_COMPOSITOR_TYPE_X11; -#ifdef HAVE_WAYLAND - else if (strcmp (session_type, "wayland") == 0) - return META_COMPOSITOR_TYPE_WAYLAND; -#endif - else - g_assert_not_reached (); -} - -static gboolean -meta_context_main_configure (MetaContext *context, - int *argc, - char ***argv, - GError **error) -{ - MetaContextMain *context_main = META_CONTEXT_MAIN (context); - MetaContextClass *context_class = - META_CONTEXT_CLASS (meta_context_main_parent_class); - - if (!context_class->configure (context, argc, argv, error)) - return FALSE; - - if (!check_configuration (context_main, error)) - return FALSE; - - context_main->compositor_type = determine_compositor_type (context_main, - error); - if (context_main->compositor_type == -1) - return FALSE; - -#ifdef HAVE_WAYLAND - if (context_main->options.wayland_display) - meta_wayland_override_display_name (context_main->options.wayland_display); -#endif - - return TRUE; -} - -static MetaCompositorType -meta_context_main_get_compositor_type (MetaContext *context) -{ - MetaContextMain *context_main = META_CONTEXT_MAIN (context); - - return context_main->compositor_type; -} - -static MetaX11DisplayPolicy -meta_context_main_get_x11_display_policy (MetaContext *context) -{ - MetaCompositorType compositor_type; -#ifdef HAVE_WAYLAND - MetaContextMain *context_main = META_CONTEXT_MAIN (context); - char *unit; -#endif - - compositor_type = meta_context_get_compositor_type (context); - switch (compositor_type) - { - case META_COMPOSITOR_TYPE_X11: - return META_X11_DISPLAY_POLICY_MANDATORY; - case META_COMPOSITOR_TYPE_WAYLAND: -#ifdef HAVE_WAYLAND - if (context_main->options.no_x11) - return META_X11_DISPLAY_POLICY_DISABLED; - else if (sd_pid_get_user_unit (0, &unit) < 0) - return META_X11_DISPLAY_POLICY_MANDATORY; - else - return META_X11_DISPLAY_POLICY_ON_DEMAND; -#else /* HAVE_WAYLAND */ - g_assert_not_reached (); -#endif /* HAVE_WAYLAND */ - } - - g_assert_not_reached (); -} - -static gboolean -meta_context_main_is_replacing (MetaContext *context) -{ - MetaContextMain *context_main = META_CONTEXT_MAIN (context); - - return context_main->options.x11.replace; -} - -#ifdef HAVE_NATIVE_BACKEND -static gboolean -add_persistent_virtual_monitors (MetaContextMain *context_main, - GError **error) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - GList *l; - - for (l = context_main->options.virtual_monitor_infos; l; l = l->next) - { - MetaVirtualMonitorInfo *info = l->data; - MetaVirtualMonitor *virtual_monitor; - - virtual_monitor = - meta_monitor_manager_create_virtual_monitor (monitor_manager, - info, - error); - if (!virtual_monitor) - { - g_prefix_error (error, "Failed to add virtual monitor: "); - return FALSE; - } - - context_main->persistent_virtual_monitors = - g_list_append (context_main->persistent_virtual_monitors, virtual_monitor); - } - - if (context_main->options.virtual_monitor_infos) - { - g_list_free_full (context_main->options.virtual_monitor_infos, - (GDestroyNotify) meta_virtual_monitor_info_free); - context_main->options.virtual_monitor_infos = NULL; - - meta_monitor_manager_reload (monitor_manager); - } - - return TRUE; -} -#endif - -static gboolean -meta_context_main_setup (MetaContext *context, - GError **error) -{ - MetaContextMain *context_main = META_CONTEXT_MAIN (context); - - if (!META_CONTEXT_CLASS (meta_context_main_parent_class)->setup (context, - error)) - return FALSE; - - meta_set_syncing (context_main->options.x11.sync || g_getenv ("MUTTER_SYNC")); - -#ifdef HAVE_NATIVE_BACKEND - if (!add_persistent_virtual_monitors (context_main, error)) - return FALSE; -#endif - - return TRUE; -} - -static MetaBackend * -create_x11_cm_backend (MetaContext *context, - GError **error) -{ - MetaContextMain *context_main = META_CONTEXT_MAIN (context); - -#ifdef HAVE_NATIVE_BACKEND - if (context_main->options.virtual_monitor_infos) - g_warning ("Ignoring added virtual monitors in X11 session"); -#endif - - return g_initable_new (META_TYPE_BACKEND_X11_CM, - NULL, error, - "context", context, - "display-name", context_main->options.x11.display_name, - NULL); -} - -#ifdef HAVE_WAYLAND -static MetaBackend * -create_nested_backend (MetaContext *context, - GError **error) -{ - return g_initable_new (META_TYPE_BACKEND_X11_NESTED, - NULL, error, - "context", context, - NULL); -} - -#ifdef HAVE_NATIVE_BACKEND -static MetaBackend * -create_headless_backend (MetaContext *context, - GError **error) -{ - return g_initable_new (META_TYPE_BACKEND_NATIVE, - NULL, error, - "context", context, - "headless", TRUE, - NULL); -} - -static MetaBackend * -create_native_backend (MetaContext *context, - GError **error) -{ - return g_initable_new (META_TYPE_BACKEND_NATIVE, - NULL, error, - "context", context, - NULL); -} -#endif /* HAVE_NATIVE_BACKEND */ -#endif /* HAVE_WAYLAND */ - -static MetaBackend * -meta_context_main_create_backend (MetaContext *context, - GError **error) -{ -#ifdef HAVE_WAYLAND - MetaContextMain *context_main = META_CONTEXT_MAIN (context); -#endif - MetaCompositorType compositor_type; - - compositor_type = meta_context_get_compositor_type (context); - switch (compositor_type) - { - case META_COMPOSITOR_TYPE_X11: - return create_x11_cm_backend (context, error); - case META_COMPOSITOR_TYPE_WAYLAND: -#ifdef HAVE_WAYLAND - if (context_main->options.nested) - return create_nested_backend (context, error); -#ifdef HAVE_NATIVE_BACKEND - else if (context_main->options.headless) - return create_headless_backend (context, error); - else - return create_native_backend (context, error); -#endif /* HAVE_NATIVE_BACKEND */ -#else /* HAVE_WAYLAND */ - g_assert_not_reached (); -#endif /* HAVE_WAYLAND */ - } - - g_assert_not_reached (); -} - -static void -meta_context_main_notify_ready (MetaContext *context) -{ - MetaContextMain *context_main = META_CONTEXT_MAIN (context); - - if (!context_main->options.sm.disable) - { - meta_session_init (context, - context_main->options.sm.client_id, - context_main->options.sm.save_file); - } - g_clear_pointer (&context_main->options.sm.client_id, g_free); - g_clear_pointer (&context_main->options.sm.save_file, g_free); -} - -#ifdef HAVE_NATIVE_BACKEND -static gboolean -add_virtual_monitor_cb (const char *option_name, - const char *value, - gpointer user_data, - GError **error) -{ - MetaContextMain *context_main = user_data; - int width, height; - float refresh_rate = 60.0; - - if (sscanf (value, "%dx%d@%f", - &width, &height, &refresh_rate) == 3 || - sscanf (value, "%dx%d", - &width, &height) == 2) - { - g_autofree char *serial = NULL; - MetaVirtualMonitorInfo *virtual_monitor; - int n_existing_virtual_monitor_infos; - - n_existing_virtual_monitor_infos = - g_list_length (context_main->options.virtual_monitor_infos); - serial = g_strdup_printf ("0x%.2x", n_existing_virtual_monitor_infos); - virtual_monitor = meta_virtual_monitor_info_new (width, - height, - refresh_rate, - "MetaVendor", - "MetaVirtualMonitor", - serial); - context_main->options.virtual_monitor_infos = - g_list_append (context_main->options.virtual_monitor_infos, - virtual_monitor); - return TRUE; - } - else - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, - "Unrecognizable virtual monitor spec '%s'", value); - return FALSE; - } -} -#endif /* HAVE_NATIVE_BACKEND */ - -static void -meta_context_main_add_option_entries (MetaContextMain *context_main) -{ - MetaContext *context = META_CONTEXT (context_main); - GOptionEntry options[] = { - { - "replace", 'r', 0, G_OPTION_ARG_NONE, - &context_main->options.x11.replace, - N_("Replace the running window manager"), - NULL - }, - { - "display", 'd', 0, G_OPTION_ARG_STRING, - &context_main->options.x11.display_name, - N_("X Display to use"), - "DISPLAY" - }, - { - "sm-disable", 0, 0, G_OPTION_ARG_NONE, - &context_main->options.sm.disable, - N_("Disable connection to session manager"), - NULL - }, - { - "sm-client-id", 0, 0, G_OPTION_ARG_STRING, - &context_main->options.sm.client_id, - N_("Specify session management ID"), - "ID" - }, - { - "sm-save-file", 0, 0, G_OPTION_ARG_FILENAME, - &context_main->options.sm.save_file, - N_("Initialize session from savefile"), - "FILE" - }, - { - "sync", 0, 0, G_OPTION_ARG_NONE, - &context_main->options.x11.sync, - N_("Make X calls synchronous"), - NULL - }, -#ifdef HAVE_WAYLAND - { - "wayland", 0, 0, G_OPTION_ARG_NONE, - &context_main->options.wayland, - N_("Run as a wayland compositor"), - NULL - }, - { - "nested", 0, 0, G_OPTION_ARG_NONE, - &context_main->options.nested, - N_("Run as a nested compositor"), - NULL - }, - { - "no-x11", 0, 0, G_OPTION_ARG_NONE, - &context_main->options.no_x11, - N_("Run wayland compositor without starting Xwayland"), - NULL - }, - { - "wayland-display", 0, 0, G_OPTION_ARG_STRING, - &context_main->options.wayland_display, - N_("Specify Wayland display name to use"), - NULL - }, -#endif -#ifdef HAVE_NATIVE_BACKEND - { - "display-server", 0, 0, G_OPTION_ARG_NONE, - &context_main->options.display_server, - N_("Run as a full display server, rather than nested") - }, - { - "headless", 0, 0, G_OPTION_ARG_NONE, - &context_main->options.headless, - N_("Run as a headless display server") - }, - { - "virtual-monitor", 0, 0, G_OPTION_ARG_CALLBACK, - add_virtual_monitor_cb, - N_("Add persistent virtual monitor (WxH or WxH@R)") - }, -#endif - { - "x11", 0, 0, G_OPTION_ARG_NONE, - &context_main->options.x11.force, - N_("Run with X11 backend") - }, - { NULL } - }; - - meta_context_add_option_entries (context, options, GETTEXT_PACKAGE); -} - -/** - * meta_create_context: - * @name: Human readable name of display server or window manager - * - * Create a context. - * - * Returns: (transfer full): A new context instance. - */ -MetaContext * -meta_create_context (const char *name) -{ - return g_object_new (META_TYPE_CONTEXT_MAIN, - "name", name, - NULL); -} - -static void -meta_context_main_finalize (GObject *object) -{ -#ifdef HAVE_NATIVE_BACKEND - MetaContextMain *context_main = META_CONTEXT_MAIN (object); - - g_list_free_full (context_main->persistent_virtual_monitors, g_object_unref); - context_main->persistent_virtual_monitors = NULL; -#endif - - G_OBJECT_CLASS (meta_context_main_parent_class)->finalize (object); -} - -static void -meta_context_main_constructed (GObject *object) -{ - MetaContextMain *context_main = META_CONTEXT_MAIN (object); - - G_OBJECT_CLASS (meta_context_main_parent_class)->constructed (object); - - meta_context_main_add_option_entries (context_main); -} - -static void -meta_context_main_class_init (MetaContextMainClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaContextClass *context_class = META_CONTEXT_CLASS (klass); - - object_class->finalize = meta_context_main_finalize; - object_class->constructed = meta_context_main_constructed; - - context_class->configure = meta_context_main_configure; - context_class->get_compositor_type = meta_context_main_get_compositor_type; - context_class->get_x11_display_policy = - meta_context_main_get_x11_display_policy; - context_class->is_replacing = meta_context_main_is_replacing; - context_class->setup = meta_context_main_setup; - context_class->create_backend = meta_context_main_create_backend; - context_class->notify_ready = meta_context_main_notify_ready; -} - -static void -meta_context_main_init (MetaContextMain *context_main) -{ - context_main->compositor_type = -1; -} diff --git a/src/core/meta-context-main.h b/src/core/meta-context-main.h deleted file mode 100644 index 9a8ce902b..000000000 --- a/src/core/meta-context-main.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2021 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_CONTEXT_MAIN_H -#define META_CONTEXT_MAIN_H - -#include "core/meta-context-private.h" - -#define META_TYPE_CONTEXT_MAIN (meta_context_main_get_type ()) -G_DECLARE_FINAL_TYPE (MetaContextMain, meta_context_main, - META, CONTEXT_MAIN, - MetaContext) - -#endif /* META_CONTEXT_MAIN_H */ diff --git a/src/core/meta-context-private.h b/src/core/meta-context-private.h deleted file mode 100644 index a3b7f9b4b..000000000 --- a/src/core/meta-context-private.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2019 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_CONTEXT_PRIVATE_H -#define META_CONTEXT_PRIVATE_H - -#include "core/meta-private-enums.h" -#include "core/util-private.h" -#include "meta/meta-backend.h" -#include "meta/meta-context.h" -#include "wayland/meta-wayland-types.h" - -struct _MetaContextClass -{ - GObjectClass parent_class; - - gboolean (* configure) (MetaContext *context, - int *argc, - char ***argv, - GError **error); - - MetaCompositorType (* get_compositor_type) (MetaContext *context); - - MetaX11DisplayPolicy (* get_x11_display_policy) (MetaContext *context); - - gboolean (* is_replacing) (MetaContext *context); - - gboolean (* setup) (MetaContext *context, - GError **error); - - MetaBackend * (* create_backend) (MetaContext *context, - GError **error); - - void (* notify_ready) (MetaContext *context); -}; - -const char * meta_context_get_name (MetaContext *context); - -const char * meta_context_get_gnome_wm_keybindings (MetaContext *context); - -META_EXPORT_TEST -MetaWaylandCompositor * meta_context_get_wayland_compositor (MetaContext *context); - -MetaX11DisplayPolicy meta_context_get_x11_display_policy (MetaContext *context); - -#endif /* META_CONTEXT_PRIVATE_H */ diff --git a/src/core/meta-context.c b/src/core/meta-context.c deleted file mode 100644 index 7bb0e5f46..000000000 --- a/src/core/meta-context.c +++ /dev/null @@ -1,568 +0,0 @@ -/* - * Copyright (C) 2019 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "core/meta-context-private.h" - -#include - -#include "backends/meta-backend-private.h" -#include "compositor/meta-plugin-manager.h" -#include "core/display-private.h" -#include "core/prefs-private.h" -#include "core/util-private.h" - -#ifdef HAVE_WAYLAND -#include "wayland/meta-wayland.h" -#endif - -enum -{ - PROP_0, - - PROP_NAME, - - N_PROPS -}; - -static GParamSpec *obj_props[N_PROPS]; - -typedef enum _MetaContextState -{ - META_CONTEXT_STATE_INIT, - META_CONTEXT_STATE_CONFIGURED, - META_CONTEXT_STATE_SETUP, - META_CONTEXT_STATE_STARTED, - META_CONTEXT_STATE_RUNNING, - META_CONTEXT_STATE_TERMINATED, -} MetaContextState; - -typedef struct _MetaContextPrivate -{ - char *name; - char *plugin_name; - GType plugin_gtype; - char *gnome_wm_keybindings; - - MetaContextState state; - - GOptionContext *option_context; - - MetaBackend *backend; - MetaDisplay *display; -#ifdef HAVE_WAYLAND - MetaWaylandCompositor *wayland_compositor; -#endif - - GMainLoop *main_loop; - GError *termination_error; -} MetaContextPrivate; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaContext, meta_context, G_TYPE_OBJECT) - -void -meta_context_add_option_entries (MetaContext *context, - const GOptionEntry *entries, - const char *translation_domain) -{ - MetaContextPrivate *priv = meta_context_get_instance_private (context); - - g_warn_if_fail (priv->state == META_CONTEXT_STATE_INIT); - - g_option_context_add_main_entries (priv->option_context, - entries, - translation_domain); -} - -void -meta_context_add_option_group (MetaContext *context, - GOptionGroup *group) -{ - MetaContextPrivate *priv = meta_context_get_instance_private (context); - - g_warn_if_fail (priv->state == META_CONTEXT_STATE_INIT); - g_return_if_fail (priv->option_context); - - g_option_context_add_group (priv->option_context, group); -} - -void -meta_context_set_plugin_gtype (MetaContext *context, - GType plugin_gtype) -{ - MetaContextPrivate *priv = meta_context_get_instance_private (context); - - g_return_if_fail (priv->state <= META_CONTEXT_STATE_CONFIGURED); - g_return_if_fail (!priv->plugin_name); - - priv->plugin_gtype = plugin_gtype; -} - -void -meta_context_set_plugin_name (MetaContext *context, - const char *plugin_name) -{ - MetaContextPrivate *priv = meta_context_get_instance_private (context); - - g_return_if_fail (priv->state <= META_CONTEXT_STATE_CONFIGURED); - g_return_if_fail (priv->plugin_gtype == G_TYPE_NONE); - - priv->plugin_name = g_strdup (plugin_name); -} - -void -meta_context_set_gnome_wm_keybindings (MetaContext *context, - const char *wm_keybindings) -{ - MetaContextPrivate *priv = meta_context_get_instance_private (context); - - g_return_if_fail (priv->state <= META_CONTEXT_STATE_CONFIGURED); - - g_clear_pointer (&priv->gnome_wm_keybindings, g_free); - priv->gnome_wm_keybindings = g_strdup (wm_keybindings); -} - -const char * -meta_context_get_gnome_wm_keybindings (MetaContext *context) -{ - MetaContextPrivate *priv = meta_context_get_instance_private (context); - - return priv->gnome_wm_keybindings; -} - -void -meta_context_notify_ready (MetaContext *context) -{ - MetaContextPrivate *priv = meta_context_get_instance_private (context); - - g_return_if_fail (priv->state == META_CONTEXT_STATE_STARTED || - priv->state == META_CONTEXT_STATE_RUNNING); - - META_CONTEXT_GET_CLASS (context)->notify_ready (context); -} - -const char * -meta_context_get_name (MetaContext *context) -{ - MetaContextPrivate *priv = meta_context_get_instance_private (context); - - return priv->name; -} - -/** - * meta_context_get_backend: - * @context: The #MetaContext - * - * Returns: (transfer none): the #MetaBackend - */ -MetaBackend * -meta_context_get_backend (MetaContext *context) -{ - MetaContextPrivate *priv = meta_context_get_instance_private (context); - - return priv->backend; -} - -/** - * meta_context_get_display: - * @context: The #MetaContext - * - * Returns: (transfer none): the #MetaDisplay - */ -MetaDisplay * -meta_context_get_display (MetaContext *context) -{ - MetaContextPrivate *priv = meta_context_get_instance_private (context); - - return priv->display; -} - -#ifdef HAVE_WAYLAND -MetaWaylandCompositor * -meta_context_get_wayland_compositor (MetaContext *context) -{ - MetaContextPrivate *priv = meta_context_get_instance_private (context); - - return priv->wayland_compositor; -} -#endif - -MetaCompositorType -meta_context_get_compositor_type (MetaContext *context) -{ - return META_CONTEXT_GET_CLASS (context)->get_compositor_type (context); -} - -gboolean -meta_context_is_replacing (MetaContext *context) -{ - return META_CONTEXT_GET_CLASS (context)->is_replacing (context); -} - -MetaX11DisplayPolicy -meta_context_get_x11_display_policy (MetaContext *context) -{ - return META_CONTEXT_GET_CLASS (context)->get_x11_display_policy (context); -} - -static gboolean -meta_context_real_configure (MetaContext *context, - int *argc, - char ***argv, - GError **error) -{ - MetaContextPrivate *priv = meta_context_get_instance_private (context); - g_autoptr (GOptionContext) option_context = NULL; - - if (!priv->option_context) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Tried to configure multiple times"); - return FALSE; - } - - option_context = g_steal_pointer (&priv->option_context); - return g_option_context_parse (option_context, argc, argv, error); -} - -gboolean -meta_context_configure (MetaContext *context, - int *argc, - char ***argv, - GError **error) -{ - MetaContextPrivate *priv = meta_context_get_instance_private (context); - MetaCompositorType compositor_type; - - g_warn_if_fail (priv->state == META_CONTEXT_STATE_INIT); - - if (!META_CONTEXT_GET_CLASS (context)->configure (context, argc, argv, error)) - { - priv->state = META_CONTEXT_STATE_TERMINATED; - return FALSE; - } - - compositor_type = meta_context_get_compositor_type (context); - switch (compositor_type) - { - case META_COMPOSITOR_TYPE_WAYLAND: - meta_set_is_wayland_compositor (TRUE); - break; - case META_COMPOSITOR_TYPE_X11: - meta_set_is_wayland_compositor (FALSE); - break; - } - - priv->state = META_CONTEXT_STATE_CONFIGURED; - - return TRUE; -} - -static const char * -compositor_type_to_description (MetaCompositorType compositor_type) -{ - switch (compositor_type) - { - case META_COMPOSITOR_TYPE_WAYLAND: - return "Wayland display server"; - case META_COMPOSITOR_TYPE_X11: - return "X11 window and compositing manager"; - } - - g_assert_not_reached (); -} - -static void -init_introspection (MetaContext *context) -{ -#ifdef HAVE_INTROSPECTION - g_irepository_prepend_search_path (MUTTER_PKGLIBDIR); -#endif -} - -static gboolean -meta_context_real_setup (MetaContext *context, - GError **error) -{ - MetaContextPrivate *priv = meta_context_get_instance_private (context); - MetaBackend *backend; - - backend = META_CONTEXT_GET_CLASS (context)->create_backend (context, error); - if (!backend) - return FALSE; - - priv->backend = backend; - return TRUE; -} - -gboolean -meta_context_setup (MetaContext *context, - GError **error) -{ - MetaContextPrivate *priv = meta_context_get_instance_private (context); - MetaCompositorType compositor_type; - - g_warn_if_fail (priv->state == META_CONTEXT_STATE_CONFIGURED); - - if (!priv->plugin_name && priv->plugin_gtype == G_TYPE_NONE) - { - priv->state = META_CONTEXT_STATE_TERMINATED; - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "No compositor plugin set"); - return FALSE; - } - - meta_init_debug_utils (); - - compositor_type = meta_context_get_compositor_type (context); - g_message ("Running %s (using mutter %s) as a %s", - priv->name, VERSION, - compositor_type_to_description (compositor_type)); - - if (priv->plugin_name) - meta_plugin_manager_load (priv->plugin_name); - else - meta_plugin_manager_set_plugin_type (priv->plugin_gtype); - - init_introspection (context); - - if (!META_CONTEXT_GET_CLASS (context)->setup (context, error)) - { - priv->state = META_CONTEXT_STATE_TERMINATED; - return FALSE; - } - - priv->state = META_CONTEXT_STATE_SETUP; - return TRUE; -} - -gboolean -meta_context_start (MetaContext *context, - GError **error) -{ - MetaContextPrivate *priv = meta_context_get_instance_private (context); - - g_warn_if_fail (priv->state == META_CONTEXT_STATE_SETUP); - - meta_prefs_init (); - -#ifdef HAVE_WAYLAND - if (meta_context_get_compositor_type (context) == - META_COMPOSITOR_TYPE_WAYLAND) - priv->wayland_compositor = meta_wayland_compositor_new (context); -#endif - - priv->display = meta_display_new (context, error); - if (!priv->display) - { - priv->state = META_CONTEXT_STATE_TERMINATED; - return FALSE; - } - - priv->main_loop = g_main_loop_new (NULL, FALSE); - - priv->state = META_CONTEXT_STATE_STARTED; - - return TRUE; -} - -gboolean -meta_context_run_main_loop (MetaContext *context, - GError **error) -{ - MetaContextPrivate *priv = meta_context_get_instance_private (context); - - g_warn_if_fail (priv->state == META_CONTEXT_STATE_STARTED); - if (!priv->main_loop) - { - priv->state = META_CONTEXT_STATE_TERMINATED; - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Tried to run main loop without having started"); - return FALSE; - } - - priv->state = META_CONTEXT_STATE_RUNNING; - g_main_loop_run (priv->main_loop); - priv->state = META_CONTEXT_STATE_TERMINATED; - g_clear_pointer (&priv->main_loop, g_main_loop_unref); - - if (priv->termination_error) - { - g_propagate_error (error, g_steal_pointer (&priv->termination_error)); - return FALSE; - } - - return TRUE; -} - -void -meta_context_terminate (MetaContext *context) -{ - MetaContextPrivate *priv = meta_context_get_instance_private (context); - - g_warn_if_fail (priv->state == META_CONTEXT_STATE_RUNNING); - g_warn_if_fail (g_main_loop_is_running (priv->main_loop)); - - g_main_loop_quit (priv->main_loop); -} - -void -meta_context_terminate_with_error (MetaContext *context, - GError *error) -{ - MetaContextPrivate *priv = meta_context_get_instance_private (context); - - priv->termination_error = g_steal_pointer (&error); - meta_context_terminate (context); -} - -void -meta_context_destroy (MetaContext *context) -{ - g_object_run_dispose (G_OBJECT (context)); - g_object_unref (context); -} - -static void -meta_context_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaContext *context = META_CONTEXT (object); - MetaContextPrivate *priv = meta_context_get_instance_private (context); - - switch (prop_id) - { - case PROP_NAME: - g_value_set_string (value, priv->name); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_context_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaContext *context = META_CONTEXT (object); - MetaContextPrivate *priv = meta_context_get_instance_private (context); - - switch (prop_id) - { - case PROP_NAME: - priv->name = g_value_dup_string (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_context_dispose (GObject *object) -{ - MetaContext *context = META_CONTEXT (object); - MetaContextPrivate *priv = meta_context_get_instance_private (context); - - if (priv->backend) - meta_backend_prepare_shutdown (priv->backend); - -#ifdef HAVE_WAYLAND - if (priv->wayland_compositor) - meta_wayland_compositor_prepare_shutdown (priv->wayland_compositor); -#endif - - if (priv->display) - meta_display_close (priv->display, META_CURRENT_TIME); - g_clear_object (&priv->display); - -#ifdef HAVE_WAYLAND - g_clear_object (&priv->wayland_compositor); -#endif - - g_clear_pointer (&priv->backend, meta_backend_destroy); - - g_clear_pointer (&priv->option_context, g_option_context_free); - g_clear_pointer (&priv->main_loop, g_main_loop_unref); - - G_OBJECT_CLASS (meta_context_parent_class)->dispose (object); -} - -static void -meta_context_finalize (GObject *object) -{ - MetaContext *context = META_CONTEXT (object); - MetaContextPrivate *priv = meta_context_get_instance_private (context); - - g_clear_pointer (&priv->gnome_wm_keybindings, g_free); - g_clear_pointer (&priv->plugin_name, g_free); - g_clear_pointer (&priv->name, g_free); - - G_OBJECT_CLASS (meta_context_parent_class)->finalize (object); -} - -static void -meta_context_class_init (MetaContextClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->get_property = meta_context_get_property; - object_class->set_property = meta_context_set_property; - object_class->dispose = meta_context_dispose; - object_class->finalize = meta_context_finalize; - - klass->configure = meta_context_real_configure; - klass->setup = meta_context_real_setup; - - obj_props[PROP_NAME] = - g_param_spec_string ("name", - "name", - "Human readable name", - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, N_PROPS, obj_props); -} - -static void -meta_context_init (MetaContext *context) -{ - MetaContextPrivate *priv = meta_context_get_instance_private (context); - - priv->plugin_gtype = G_TYPE_NONE; - priv->gnome_wm_keybindings = g_strdup ("Mutter"); - - if (!setlocale (LC_ALL, "")) - g_warning ("Locale not understood by C library"); - bindtextdomain (GETTEXT_PACKAGE, MUTTER_LOCALEDIR); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - - priv->option_context = g_option_context_new (NULL); - g_option_context_set_main_group (priv->option_context, - g_option_group_new (NULL, NULL, NULL, - context, NULL)); -} diff --git a/src/core/meta-fraction.c b/src/core/meta-fraction.c deleted file mode 100644 index 8090aa411..000000000 --- a/src/core/meta-fraction.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 1999,2000 Erik Walthinsen - * 2000 Wim Taymans - * 2002 Thomas Vander Stichele - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - * Fraction utility functions in this file comes from gstutils.c in gstreamer. - */ - -#include "config.h" - -#include "core/meta-fraction.h" - -#include -#include - -#define MAX_TERMS 30 -#define MIN_DIVISOR 1.0e-10 -#define MAX_ERROR 1.0e-20 - -static int -greatest_common_divisor (int a, - int b) -{ - while (b != 0) - { - int temp = a; - - a = b; - b = temp % b; - } - - return ABS (a); -} - -MetaFraction -meta_fraction_from_double (double src) -{ - double V, F; /* double being converted */ - int N, D; /* will contain the result */ - int A; /* current term in continued fraction */ - int64_t N1, D1; /* numerator, denominator of last approx */ - int64_t N2, D2; /* numerator, denominator of previous approx */ - int i; - int gcd; - gboolean negative = FALSE; - - /* initialize fraction being converted */ - F = src; - if (F < 0.0) - { - F = -F; - negative = TRUE; - } - - V = F; - /* initialize fractions with 1/0, 0/1 */ - N1 = 1; - D1 = 0; - N2 = 0; - D2 = 1; - N = 1; - D = 1; - - for (i = 0; i < MAX_TERMS; i++) - { - /* get next term */ - A = (gint) F; /* no floor() needed, F is always >= 0 */ - /* get new divisor */ - F = F - A; - - /* calculate new fraction in temp */ - N2 = N1 * A + N2; - D2 = D1 * A + D2; - - /* guard against overflow */ - if (N2 > G_MAXINT || D2 > G_MAXINT) - break; - - N = N2; - D = D2; - - /* save last two fractions */ - N2 = N1; - D2 = D1; - N1 = N; - D1 = D; - - /* quit if dividing by zero or close enough to target */ - if (F < MIN_DIVISOR || fabs (V - ((gdouble) N) / D) < MAX_ERROR) - break; - - /* Take reciprocal */ - F = 1 / F; - } - - /* fix for overflow */ - if (D == 0) - { - N = G_MAXINT; - D = 1; - } - - /* fix for negative */ - if (negative) - N = -N; - - /* simplify */ - gcd = greatest_common_divisor (N, D); - if (gcd) - { - N /= gcd; - D /= gcd; - } - - return (MetaFraction) { - .num = N, - .denom = D - }; -} diff --git a/src/core/meta-fraction.h b/src/core/meta-fraction.h deleted file mode 100644 index f7ab294cd..000000000 --- a/src/core/meta-fraction.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 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 . - */ - -#ifndef META_FRACTION_H -#define META_FRACTION_H - -typedef struct _MetaFraction -{ - int num; - int denom; -} MetaFraction; - -MetaFraction meta_fraction_from_double (double src); - -#endif /* META_FRACTION_H */ diff --git a/src/core/meta-gesture-tracker-private.h b/src/core/meta-gesture-tracker-private.h deleted file mode 100644 index e7bfc5472..000000000 --- a/src/core/meta-gesture-tracker-private.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Author: Carlos Garnacho - */ - -#ifndef META_GESTURE_TRACKER_PRIVATE_H -#define META_GESTURE_TRACKER_PRIVATE_H - -#include - -#include "backends/meta-backend-private.h" -#include "clutter/clutter.h" -#include "meta/window.h" - -#define META_TYPE_GESTURE_TRACKER (meta_gesture_tracker_get_type ()) -#define META_GESTURE_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_GESTURE_TRACKER, MetaGestureTracker)) -#define META_GESTURE_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_GESTURE_TRACKER, MetaGestureTrackerClass)) -#define META_IS_GESTURE_TRACKER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_GESTURE_TRACKER)) -#define META_IS_GESTURE_TRACKER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_GESTURE_TRACKER)) -#define META_GESTURE_TRACKER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_GESTURE_TRACKER, MetaGestureTrackerClass)) - -typedef struct _MetaGestureTracker MetaGestureTracker; -typedef struct _MetaGestureTrackerClass MetaGestureTrackerClass; - -struct _MetaGestureTracker -{ - GObject parent_instance; -}; - -struct _MetaGestureTrackerClass -{ - GObjectClass parent_class; - - void (* state_changed) (MetaGestureTracker *tracker, - ClutterEventSequence *sequence, - MetaSequenceState state); -}; - -GType meta_gesture_tracker_get_type (void) G_GNUC_CONST; - -MetaGestureTracker * meta_gesture_tracker_new (void); - -gboolean meta_gesture_tracker_handle_event (MetaGestureTracker *tracker, - const ClutterEvent *event); -gboolean meta_gesture_tracker_set_sequence_state (MetaGestureTracker *tracker, - ClutterEventSequence *sequence, - MetaSequenceState state); -MetaSequenceState meta_gesture_tracker_get_sequence_state (MetaGestureTracker *tracker, - ClutterEventSequence *sequence); -gint meta_gesture_tracker_get_n_current_touches (MetaGestureTracker *tracker); - -#endif /* META_GESTURE_TRACKER_PRIVATE_H */ diff --git a/src/core/meta-gesture-tracker.c b/src/core/meta-gesture-tracker.c deleted file mode 100644 index 2badf8b82..000000000 --- a/src/core/meta-gesture-tracker.c +++ /dev/null @@ -1,581 +0,0 @@ -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Author: Carlos Garnacho - */ - -/** - * SECTION:gesture-tracker - * @Title: MetaGestureTracker - * @Short_Description: Manages gestures on windows/desktop - * - * Forwards touch events to clutter actors, and accepts/rejects touch sequences - * based on the outcome of those. - */ - -#include "config.h" - -#include "core/meta-gesture-tracker-private.h" - -#include "compositor/meta-surface-actor.h" - -#define DISTANCE_THRESHOLD 30 - -typedef struct _MetaGestureTrackerPrivate MetaGestureTrackerPrivate; -typedef struct _GestureActionData GestureActionData; -typedef struct _MetaSequenceInfo MetaSequenceInfo; - -struct _MetaSequenceInfo -{ - MetaGestureTracker *tracker; - ClutterEventSequence *sequence; - MetaSequenceState state; - guint autodeny_timeout_id; - gfloat start_x; - gfloat start_y; -}; - -struct _GestureActionData -{ - ClutterGestureAction *gesture; - MetaSequenceState state; - gulong gesture_begin_id; - gulong gesture_end_id; - gulong gesture_cancel_id; -}; - -struct _MetaGestureTrackerPrivate -{ - GHashTable *sequences; /* Hashtable of ClutterEventSequence->MetaSequenceInfo */ - - MetaSequenceState stage_state; - GArray *stage_gestures; /* Array of GestureActionData */ - GList *listeners; /* List of ClutterGestureAction */ - guint autodeny_timeout; -}; - -enum -{ - PROP_0, - PROP_AUTODENY_TIMEOUT, - PROP_LAST, -}; - -static GParamSpec *obj_props[PROP_LAST]; - -enum -{ - STATE_CHANGED, - N_SIGNALS -}; - -static guint signals[N_SIGNALS] = { 0 }; - -#define DEFAULT_AUTODENY_TIMEOUT 150 - -static void meta_gesture_tracker_untrack_stage (MetaGestureTracker *tracker); - -G_DEFINE_TYPE_WITH_PRIVATE (MetaGestureTracker, meta_gesture_tracker, G_TYPE_OBJECT) - -static void -meta_gesture_tracker_finalize (GObject *object) -{ - MetaGestureTrackerPrivate *priv; - - priv = meta_gesture_tracker_get_instance_private (META_GESTURE_TRACKER (object)); - - g_hash_table_destroy (priv->sequences); - g_array_free (priv->stage_gestures, TRUE); - g_list_free (priv->listeners); - - G_OBJECT_CLASS (meta_gesture_tracker_parent_class)->finalize (object); -} - -static void -meta_gesture_tracker_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaGestureTrackerPrivate *priv; - - priv = meta_gesture_tracker_get_instance_private (META_GESTURE_TRACKER (object)); - - switch (prop_id) - { - case PROP_AUTODENY_TIMEOUT: - priv->autodeny_timeout = g_value_get_uint (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_gesture_tracker_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaGestureTrackerPrivate *priv; - - priv = meta_gesture_tracker_get_instance_private (META_GESTURE_TRACKER (object)); - - switch (prop_id) - { - case PROP_AUTODENY_TIMEOUT: - g_value_set_uint (value, priv->autodeny_timeout); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_gesture_tracker_class_init (MetaGestureTrackerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_gesture_tracker_finalize; - object_class->set_property = meta_gesture_tracker_set_property; - object_class->get_property = meta_gesture_tracker_get_property; - - obj_props[PROP_AUTODENY_TIMEOUT] = g_param_spec_uint ("autodeny-timeout", - "Auto-deny timeout", - "Auto-deny timeout", - 0, G_MAXUINT, DEFAULT_AUTODENY_TIMEOUT, - G_PARAM_STATIC_STRINGS | - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - - g_object_class_install_properties (object_class, PROP_LAST, obj_props); - - signals[STATE_CHANGED] = - g_signal_new ("state-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (MetaGestureTrackerClass, state_changed), - NULL, NULL, NULL, - G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_UINT); -} - -static gboolean -autodeny_sequence (gpointer user_data) -{ - MetaSequenceInfo *info = user_data; - - /* Deny the sequence automatically after the given timeout */ - if (info->state == META_SEQUENCE_NONE) - meta_gesture_tracker_set_sequence_state (info->tracker, info->sequence, - META_SEQUENCE_REJECTED); - - info->autodeny_timeout_id = 0; - return G_SOURCE_REMOVE; -} - -static MetaSequenceInfo * -meta_sequence_info_new (MetaGestureTracker *tracker, - const ClutterEvent *event) -{ - MetaGestureTrackerPrivate *priv; - MetaSequenceInfo *info; - guint ms; - - priv = meta_gesture_tracker_get_instance_private (tracker); - ms = priv->autodeny_timeout; - - info = g_new0 (MetaSequenceInfo, 1); - info->tracker = tracker; - info->sequence = event->touch.sequence; - info->state = META_SEQUENCE_NONE; - info->autodeny_timeout_id = g_timeout_add (ms, autodeny_sequence, info); - - clutter_event_get_coords (event, &info->start_x, &info->start_y); - - return info; -} - -static void -meta_sequence_info_free (MetaSequenceInfo *info) -{ - g_clear_handle_id (&info->autodeny_timeout_id, g_source_remove); - - if (info->state == META_SEQUENCE_NONE) - meta_gesture_tracker_set_sequence_state (info->tracker, info->sequence, - META_SEQUENCE_REJECTED); - g_free (info); -} - -static gboolean -state_is_applicable (MetaSequenceState prev_state, - MetaSequenceState state) -{ - if (prev_state == META_SEQUENCE_PENDING_END) - return FALSE; - - /* Don't allow reverting to none */ - if (state == META_SEQUENCE_NONE) - return FALSE; - - /* PENDING_END state is final */ - if (prev_state == META_SEQUENCE_PENDING_END) - return FALSE; - - /* Sequences must be accepted/denied before PENDING_END */ - if (prev_state == META_SEQUENCE_NONE && - state == META_SEQUENCE_PENDING_END) - return FALSE; - - /* Make sequences stick to their accepted/denied state */ - if (state != META_SEQUENCE_PENDING_END && - prev_state != META_SEQUENCE_NONE) - return FALSE; - - return TRUE; -} - -static gboolean -meta_gesture_tracker_set_state (MetaGestureTracker *tracker, - MetaSequenceState state) -{ - MetaGestureTrackerPrivate *priv; - ClutterEventSequence *sequence; - GHashTableIter iter; - - priv = meta_gesture_tracker_get_instance_private (tracker); - - if (priv->stage_state != state && - !state_is_applicable (priv->stage_state, state)) - return FALSE; - - g_hash_table_iter_init (&iter, priv->sequences); - priv->stage_state = state; - - while (g_hash_table_iter_next (&iter, (gpointer*) &sequence, NULL)) - meta_gesture_tracker_set_sequence_state (tracker, sequence, state); - - return TRUE; -} - -static gboolean -gesture_begin_cb (ClutterGestureAction *gesture, - ClutterActor *actor, - MetaGestureTracker *tracker) -{ - MetaGestureTrackerPrivate *priv; - - priv = meta_gesture_tracker_get_instance_private (tracker); - - if (!g_list_find (priv->listeners, gesture) && - meta_gesture_tracker_set_state (tracker, META_SEQUENCE_ACCEPTED)) - priv->listeners = g_list_prepend (priv->listeners, gesture); - - return TRUE; -} - -static void -gesture_end_cb (ClutterGestureAction *gesture, - ClutterActor *actor, - MetaGestureTracker *tracker) -{ - MetaGestureTrackerPrivate *priv; - - priv = meta_gesture_tracker_get_instance_private (tracker); - priv->listeners = g_list_remove (priv->listeners, gesture); - - if (!priv->listeners) - meta_gesture_tracker_untrack_stage (tracker); -} - -static void -gesture_cancel_cb (ClutterGestureAction *gesture, - ClutterActor *actor, - MetaGestureTracker *tracker) -{ - MetaGestureTrackerPrivate *priv; - - priv = meta_gesture_tracker_get_instance_private (tracker); - - if (g_list_find (priv->listeners, gesture)) - { - priv->listeners = g_list_remove (priv->listeners, gesture); - - if (!priv->listeners) - meta_gesture_tracker_set_state (tracker, META_SEQUENCE_PENDING_END); - } -} - -static gboolean -cancel_and_unref_gesture_cb (ClutterGestureAction *action) -{ - clutter_gesture_action_cancel (action); - g_object_unref (action); - return G_SOURCE_REMOVE; -} - -static void -clear_gesture_data (GestureActionData *data) -{ - g_clear_signal_handler (&data->gesture_begin_id, data->gesture); - g_clear_signal_handler (&data->gesture_end_id, data->gesture); - g_clear_signal_handler (&data->gesture_cancel_id, data->gesture); - - /* Defer cancellation to an idle, as it may happen within event handling */ - g_idle_add ((GSourceFunc) cancel_and_unref_gesture_cb, data->gesture); -} - -static void -meta_gesture_tracker_init (MetaGestureTracker *tracker) -{ - MetaGestureTrackerPrivate *priv; - - priv = meta_gesture_tracker_get_instance_private (tracker); - priv->sequences = g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) meta_sequence_info_free); - priv->stage_gestures = g_array_new (FALSE, FALSE, sizeof (GestureActionData)); - g_array_set_clear_func (priv->stage_gestures, (GDestroyNotify) clear_gesture_data); -} - -MetaGestureTracker * -meta_gesture_tracker_new (void) -{ - return g_object_new (META_TYPE_GESTURE_TRACKER, NULL); -} - -static void -meta_gesture_tracker_track_stage (MetaGestureTracker *tracker, - ClutterActor *stage) -{ - MetaGestureTrackerPrivate *priv; - GList *actions, *l; - - priv = meta_gesture_tracker_get_instance_private (tracker); - actions = clutter_actor_get_actions (stage); - - for (l = actions; l; l = l->next) - { - GestureActionData data; - - if (!CLUTTER_IS_GESTURE_ACTION (l->data)) - continue; - - data.gesture = g_object_ref (l->data); - data.state = META_SEQUENCE_NONE; - data.gesture_begin_id = - g_signal_connect (data.gesture, "gesture-begin", - G_CALLBACK (gesture_begin_cb), tracker); - data.gesture_end_id = - g_signal_connect (data.gesture, "gesture-end", - G_CALLBACK (gesture_end_cb), tracker); - data.gesture_cancel_id = - g_signal_connect (data.gesture, "gesture-cancel", - G_CALLBACK (gesture_cancel_cb), tracker); - g_array_append_val (priv->stage_gestures, data); - } - - g_list_free (actions); -} - -static void -meta_gesture_tracker_untrack_stage (MetaGestureTracker *tracker) -{ - MetaGestureTrackerPrivate *priv; - - priv = meta_gesture_tracker_get_instance_private (tracker); - priv->stage_state = META_SEQUENCE_NONE; - - g_hash_table_remove_all (priv->sequences); - - if (priv->stage_gestures->len > 0) - g_array_remove_range (priv->stage_gestures, 0, priv->stage_gestures->len); - - g_list_free (priv->listeners); - priv->listeners = NULL; -} - -gboolean -meta_gesture_tracker_handle_event (MetaGestureTracker *tracker, - const ClutterEvent *event) -{ - MetaGestureTrackerPrivate *priv; - ClutterEventSequence *sequence; - MetaSequenceState state; - MetaSequenceInfo *info; - ClutterActor *stage; - gfloat x, y; - - sequence = clutter_event_get_event_sequence (event); - - if (!sequence) - return FALSE; - - priv = meta_gesture_tracker_get_instance_private (tracker); - stage = CLUTTER_ACTOR (clutter_event_get_stage (event)); - - switch (event->type) - { - case CLUTTER_TOUCH_BEGIN: - if (g_hash_table_size (priv->sequences) == 0) - meta_gesture_tracker_track_stage (tracker, stage); - - info = meta_sequence_info_new (tracker, event); - g_hash_table_insert (priv->sequences, sequence, info); - - if (priv->stage_gestures->len == 0) - { - /* If no gestures are attached, reject the sequence right away */ - meta_gesture_tracker_set_sequence_state (tracker, sequence, - META_SEQUENCE_REJECTED); - } - else if (priv->stage_state != META_SEQUENCE_NONE) - { - /* Make the sequence state match the general state */ - meta_gesture_tracker_set_sequence_state (tracker, sequence, - priv->stage_state); - } - state = info->state; - break; - case CLUTTER_TOUCH_END: - info = g_hash_table_lookup (priv->sequences, sequence); - - if (!info) - return FALSE; - - /* If nothing was done yet about the sequence, reject it so X11 - * clients may see it - */ - if (info->state == META_SEQUENCE_NONE) - meta_gesture_tracker_set_sequence_state (tracker, sequence, - META_SEQUENCE_REJECTED); - - state = info->state; - g_hash_table_remove (priv->sequences, sequence); - - if (g_hash_table_size (priv->sequences) == 0) - meta_gesture_tracker_untrack_stage (tracker); - break; - case CLUTTER_TOUCH_UPDATE: - info = g_hash_table_lookup (priv->sequences, sequence); - - if (!info) - return FALSE; - - clutter_event_get_coords (event, &x, &y); - - if (info->state == META_SEQUENCE_NONE && - (ABS (info->start_x - x) > DISTANCE_THRESHOLD || - ABS (info->start_y - y) > DISTANCE_THRESHOLD)) - meta_gesture_tracker_set_sequence_state (tracker, sequence, - META_SEQUENCE_REJECTED); - state = info->state; - break; - default: - return FALSE; - break; - } - - /* As soon as a sequence is accepted, we replay it to - * the stage as a captured event, and make sure it's never - * propagated anywhere else. Since ClutterGestureAction does - * all its event handling from a captured-event handler on - * the stage, this effectively acts as a "sequence grab" on - * gesture actions. - * - * Sequences that aren't (yet or never) in an accepted state - * will go through, these events will get processed through - * the compositor, and eventually through clutter, still - * triggering the gestures capturing events on the stage, and - * possibly resulting in MetaSequenceState changes. - */ - if (state == META_SEQUENCE_ACCEPTED) - { - clutter_actor_event (CLUTTER_ACTOR (clutter_event_get_stage (event)), - event, TRUE); - return TRUE; - } - - return FALSE; -} - -gboolean -meta_gesture_tracker_set_sequence_state (MetaGestureTracker *tracker, - ClutterEventSequence *sequence, - MetaSequenceState state) -{ - MetaGestureTrackerPrivate *priv; - MetaSequenceInfo *info; - - g_return_val_if_fail (META_IS_GESTURE_TRACKER (tracker), FALSE); - - priv = meta_gesture_tracker_get_instance_private (tracker); - info = g_hash_table_lookup (priv->sequences, sequence); - - if (!info) - return FALSE; - else if (state == info->state) - return TRUE; - - if (!state_is_applicable (info->state, state)) - return FALSE; - - /* Unset autodeny timeout */ - g_clear_handle_id (&info->autodeny_timeout_id, g_source_remove); - - info->state = state; - g_signal_emit (tracker, signals[STATE_CHANGED], 0, sequence, info->state); - - /* If the sequence was denied, set immediately to PENDING_END after emission */ - if (state == META_SEQUENCE_REJECTED) - { - info->state = META_SEQUENCE_PENDING_END; - g_signal_emit (tracker, signals[STATE_CHANGED], 0, sequence, info->state); - } - - return TRUE; -} - -MetaSequenceState -meta_gesture_tracker_get_sequence_state (MetaGestureTracker *tracker, - ClutterEventSequence *sequence) -{ - MetaGestureTrackerPrivate *priv; - MetaSequenceInfo *info; - - g_return_val_if_fail (META_IS_GESTURE_TRACKER (tracker), META_SEQUENCE_PENDING_END); - - priv = meta_gesture_tracker_get_instance_private (tracker); - info = g_hash_table_lookup (priv->sequences, sequence); - - if (!info) - return META_SEQUENCE_PENDING_END; - - return info->state; -} - -gint -meta_gesture_tracker_get_n_current_touches (MetaGestureTracker *tracker) -{ - MetaGestureTrackerPrivate *priv; - - g_return_val_if_fail (META_IS_GESTURE_TRACKER (tracker), 0); - - priv = meta_gesture_tracker_get_instance_private (tracker); - return g_hash_table_size (priv->sequences); -} diff --git a/src/core/meta-inhibit-shortcuts-dialog-default-private.h b/src/core/meta-inhibit-shortcuts-dialog-default-private.h deleted file mode 100644 index 7f65494ef..000000000 --- a/src/core/meta-inhibit-shortcuts-dialog-default-private.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2017 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, see . - * - */ - -#ifndef META_INHIBIT_SHORTCUTS_DIALOG_DEFAULT_H -#define META_INHIBIT_SHORTCUTS_DIALOG_DEFAULT_H - -#include - -#include "meta/meta-plugin.h" - -#define META_TYPE_INHIBIT_SHORTCUTS_DIALOG_DEFAULT (meta_inhibit_shortcuts_dialog_default_get_type ()) -G_DECLARE_FINAL_TYPE (MetaInhibitShortcutsDialogDefault, - meta_inhibit_shortcuts_dialog_default, - META, INHIBIT_SHORTCUTS_DIALOG_DEFAULT, - GObject) - -MetaInhibitShortcutsDialog * meta_inhibit_shortcuts_dialog_default_new (MetaWindow *window); - -#endif /* META_INHIBIT_SHORTCUTS_DIALOG_DEFAULT_H */ diff --git a/src/core/meta-inhibit-shortcuts-dialog-default.c b/src/core/meta-inhibit-shortcuts-dialog-default.c deleted file mode 100644 index d90234d6a..000000000 --- a/src/core/meta-inhibit-shortcuts-dialog-default.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2001, 2002 Havoc Pennington - * Copyright (C) 2004 Elijah Newren - * Copyright (C) 2017 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, see . - * - */ - -#include "config.h" - -#include "core/meta-inhibit-shortcuts-dialog-default-private.h" -#include "core/util-private.h" -#include "core/window-private.h" -#include "meta/meta-inhibit-shortcuts-dialog.h" - -typedef struct _MetaInhibitShortcutsDialogDefaultPrivate MetaInhibitShortcutsDialogDefaultPrivate; - -struct _MetaInhibitShortcutsDialogDefault -{ - GObject parent_instance; - MetaWindow *window; -}; - -enum -{ - PROP_0, - PROP_WINDOW, - N_PROPS -}; - -static void meta_inhibit_shortcuts_dialog_iface_init (MetaInhibitShortcutsDialogInterface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaInhibitShortcutsDialogDefault, meta_inhibit_shortcuts_dialog_default, - G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (META_TYPE_INHIBIT_SHORTCUTS_DIALOG, - meta_inhibit_shortcuts_dialog_iface_init)) - -static void -meta_inhibit_shortcuts_dialog_default_show (MetaInhibitShortcutsDialog *dialog) -{ - /* Default to allow shortcuts inhibitor, but complain that no dialog is implemented */ - g_warning ("No MetaInhibitShortcutDialog implementation, falling back on allowing"); - meta_inhibit_shortcuts_dialog_response (dialog, META_INHIBIT_SHORTCUTS_DIALOG_RESPONSE_ALLOW); -} - -static void -meta_inhibit_shortcuts_dialog_default_hide (MetaInhibitShortcutsDialog *dialog) -{ -} - -static void -meta_inhibit_shortcuts_dialog_iface_init (MetaInhibitShortcutsDialogInterface *iface) -{ - iface->show = meta_inhibit_shortcuts_dialog_default_show; - iface->hide = meta_inhibit_shortcuts_dialog_default_hide; -} - -static void -meta_inhibit_shortcuts_dialog_default_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaInhibitShortcutsDialogDefault *dialog; - - dialog = META_INHIBIT_SHORTCUTS_DIALOG_DEFAULT (object); - - switch (prop_id) - { - case PROP_WINDOW: - dialog->window = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_inhibit_shortcuts_dialog_default_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaInhibitShortcutsDialogDefault *dialog; - - dialog = META_INHIBIT_SHORTCUTS_DIALOG_DEFAULT (object); - - switch (prop_id) - { - case PROP_WINDOW: - g_value_set_object (value, dialog->window); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_inhibit_shortcuts_dialog_default_class_init (MetaInhibitShortcutsDialogDefaultClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->set_property = meta_inhibit_shortcuts_dialog_default_set_property; - object_class->get_property = meta_inhibit_shortcuts_dialog_default_get_property; - - g_object_class_override_property (object_class, PROP_WINDOW, "window"); -} - -static void -meta_inhibit_shortcuts_dialog_default_init (MetaInhibitShortcutsDialogDefault *dialog) -{ -} - -MetaInhibitShortcutsDialog * -meta_inhibit_shortcuts_dialog_default_new (MetaWindow *window) -{ - return g_object_new (META_TYPE_INHIBIT_SHORTCUTS_DIALOG_DEFAULT, - "window", window, - NULL); -} diff --git a/src/core/meta-inhibit-shortcuts-dialog.c b/src/core/meta-inhibit-shortcuts-dialog.c deleted file mode 100644 index d5b4e5a05..000000000 --- a/src/core/meta-inhibit-shortcuts-dialog.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2017 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, see . - * - */ - -#include "config.h" - -#include "core/window-private.h" -#include "meta/meta-inhibit-shortcuts-dialog.h" -#include "meta/meta-enum-types.h" - -enum -{ - RESPONSE, - LAST_SIGNAL -}; - -static guint inhibit_dialog_signals[LAST_SIGNAL] = { 0, }; - -G_DEFINE_INTERFACE (MetaInhibitShortcutsDialog, meta_inhibit_shortcuts_dialog, G_TYPE_OBJECT) - -static void -meta_inhibit_shortcuts_dialog_default_init (MetaInhibitShortcutsDialogInterface *iface) -{ - g_object_interface_install_property (iface, - g_param_spec_object ("window", - "Window", - "Window", - META_TYPE_WINDOW, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - inhibit_dialog_signals[RESPONSE] = - g_signal_new ("response", - G_TYPE_FROM_INTERFACE (iface), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 1, META_TYPE_INHIBIT_SHORTCUTS_DIALOG_RESPONSE); -} - -/** - * meta_inhibit_shortcuts_dialog_show: - * @dialog: a #MetaInhibitShortcutsDialog - * - * Shows the inhibit shortcuts dialog. - **/ -void -meta_inhibit_shortcuts_dialog_show (MetaInhibitShortcutsDialog *dialog) -{ - MetaInhibitShortcutsDialogInterface *iface; - - g_return_if_fail (META_IS_INHIBIT_SHORTCUTS_DIALOG (dialog)); - - iface = META_INHIBIT_SHORTCUTS_DIALOG_GET_IFACE (dialog); - iface->show (dialog); -} - -/** - * meta_inhibit_shortcuts_dialog_hide: - * @dialog: a #MetaInhibitShortcutsDialog - * - * Hides the inhibit shortcuts dialog. - **/ -void -meta_inhibit_shortcuts_dialog_hide (MetaInhibitShortcutsDialog *dialog) -{ - MetaInhibitShortcutsDialogInterface *iface; - - g_return_if_fail (META_IS_INHIBIT_SHORTCUTS_DIALOG (dialog)); - - iface = META_INHIBIT_SHORTCUTS_DIALOG_GET_IFACE (dialog); - iface->hide (dialog); -} - -/** - * meta_inhibit_shortcuts_dialog_response: - * @dialog: a #MetaInhibitShortcutsDialog - * @response: a #MetaInhibitShortcutsDialogResponse - * - * Responds and closes the dialog. To be called by #MetaInhibitShortcutsDialog - * implementations. - **/ -void -meta_inhibit_shortcuts_dialog_response (MetaInhibitShortcutsDialog *dialog, - MetaInhibitShortcutsDialogResponse response) -{ - g_signal_emit (dialog, inhibit_dialog_signals[RESPONSE], 0, response); - meta_inhibit_shortcuts_dialog_hide (dialog); -} diff --git a/src/core/meta-launch-context.c b/src/core/meta-launch-context.c deleted file mode 100644 index 984338c1b..000000000 --- a/src/core/meta-launch-context.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright (C) 2018 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: Carlos Garnacho - */ - -#include "config.h" - -#include - -#include "core/display-private.h" -#include "meta/meta-launch-context.h" -#include "x11/meta-startup-notification-x11.h" - -typedef struct _MetaLaunchContext MetaLaunchContext; - -struct _MetaLaunchContext -{ - GAppLaunchContext parent_instance; - MetaDisplay *display; - MetaWorkspace *workspace; - uint32_t timestamp; -}; - -G_DEFINE_TYPE (MetaLaunchContext, meta_launch_context, - G_TYPE_APP_LAUNCH_CONTEXT) - -enum -{ - PROP_DISPLAY = 1, - PROP_WORKSPACE, - PROP_TIMESTAMP, - N_PROPS -}; - -static GParamSpec *props[N_PROPS] = { 0, }; - -static void -meta_launch_context_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaLaunchContext *context = META_LAUNCH_CONTEXT (object); - - switch (prop_id) - { - case PROP_DISPLAY: - context->display = g_value_get_object (value); - break; - case PROP_WORKSPACE: - meta_launch_context_set_workspace (context, - g_value_get_object (value)); - break; - case PROP_TIMESTAMP: - meta_launch_context_set_timestamp (context, - g_value_get_uint (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_launch_context_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaLaunchContext *context = META_LAUNCH_CONTEXT (object); - - switch (prop_id) - { - case PROP_DISPLAY: - g_value_set_object (value, context->display); - break; - case PROP_WORKSPACE: - g_value_set_object (value, context->workspace); - break; - case PROP_TIMESTAMP: - g_value_set_uint (value, context->timestamp); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_launch_context_finalize (GObject *object) -{ - G_OBJECT_CLASS (meta_launch_context_parent_class)->finalize (object); -} - -static void -meta_launch_context_constructed (GObject *object) -{ - MetaLaunchContext *context = META_LAUNCH_CONTEXT (object); - const char *x11_display, *wayland_display; - - G_OBJECT_CLASS (meta_launch_context_parent_class)->constructed (object); - - x11_display = getenv ("DISPLAY"); - wayland_display = getenv ("WAYLAND_DISPLAY"); - - if (x11_display) - { - g_app_launch_context_setenv (G_APP_LAUNCH_CONTEXT (context), - "DISPLAY", x11_display); - } - - if (wayland_display) - { - g_app_launch_context_setenv (G_APP_LAUNCH_CONTEXT (context), - "WAYLAND_DISPLAY", wayland_display); - } -} - -static gchar * -meta_launch_context_get_startup_notify_id (GAppLaunchContext *launch_context, - GAppInfo *info, - GList *files) -{ - MetaLaunchContext *context = META_LAUNCH_CONTEXT (launch_context); - MetaDisplay *display = context->display; - int workspace_idx = -1; - char *startup_id = NULL; - - if (context->workspace) - workspace_idx = meta_workspace_index (context->workspace); - - if (display->x11_display) - { - /* If there is a X11 display, we prefer going entirely through - * libsn, as SnMonitor expects to keep a view of the full lifetime - * of the startup sequence. We can't avoid it when launching and - * expect that a "remove" message from a X11 client will be handled. - */ - startup_id = - meta_x11_startup_notification_launch (display->x11_display, - info, - context->timestamp, - workspace_idx); - } - - if (!startup_id) - { - const char *application_id = NULL; - MetaStartupNotification *sn; - MetaStartupSequence *seq; - - startup_id = g_uuid_string_random (); - - /* Fallback through inserting our own startup sequence, this - * will be enough for wayland clients. - */ - if (G_IS_DESKTOP_APP_INFO (info)) - { - application_id = - g_desktop_app_info_get_filename (G_DESKTOP_APP_INFO (info)); - } - - sn = meta_display_get_startup_notification (context->display); - seq = g_object_new (META_TYPE_STARTUP_SEQUENCE, - "id", startup_id, - "application-id", application_id, - "name", g_app_info_get_name (info), - "workspace", workspace_idx, - "timestamp", context->timestamp, - NULL); - - meta_startup_notification_add_sequence (sn, seq); - g_object_unref (seq); - } - - return startup_id; -} - -static void -meta_launch_context_launch_failed (GAppLaunchContext *launch_context, - const gchar *startup_notify_id) -{ - MetaLaunchContext *context = META_LAUNCH_CONTEXT (launch_context); - MetaStartupNotification *sn; - MetaStartupSequence *seq; - - sn = meta_display_get_startup_notification (context->display); - seq = meta_startup_notification_lookup_sequence (sn, startup_notify_id); - - if (seq) - { - meta_startup_sequence_complete (seq); - meta_startup_notification_remove_sequence (sn, seq); - } -} - -static void -meta_launch_context_class_init (MetaLaunchContextClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GAppLaunchContextClass *ctx_class = G_APP_LAUNCH_CONTEXT_CLASS (klass); - - object_class->finalize = meta_launch_context_finalize; - object_class->constructed = meta_launch_context_constructed; - object_class->set_property = meta_launch_context_set_property; - object_class->get_property = meta_launch_context_get_property; - - ctx_class->get_startup_notify_id = meta_launch_context_get_startup_notify_id; - ctx_class->launch_failed = meta_launch_context_launch_failed; - - props[PROP_DISPLAY] = - g_param_spec_object ("display", - "display", - "Display", - META_TYPE_DISPLAY, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - props[PROP_WORKSPACE] = - g_param_spec_object ("workspace", - "workspace", - "Workspace", - META_TYPE_WORKSPACE, - G_PARAM_READWRITE); - props[PROP_TIMESTAMP] = - g_param_spec_uint ("timestamp", - "timestamp", - "Timestamp", - 0, G_MAXUINT32, 0, - G_PARAM_READWRITE); - - g_object_class_install_properties (object_class, N_PROPS, props); -} - -static void -meta_launch_context_init (MetaLaunchContext *context) -{ -} - -void -meta_launch_context_set_workspace (MetaLaunchContext *context, - MetaWorkspace *workspace) -{ - g_return_if_fail (META_IS_LAUNCH_CONTEXT (context)); - g_return_if_fail (META_IS_WORKSPACE (workspace)); - - g_set_object (&context->workspace, workspace); -} - -void -meta_launch_context_set_timestamp (MetaLaunchContext *context, - uint32_t timestamp) -{ - g_return_if_fail (META_IS_LAUNCH_CONTEXT (context)); - - context->timestamp = timestamp; -} diff --git a/src/core/meta-pad-action-mapper.c b/src/core/meta-pad-action-mapper.c deleted file mode 100644 index 7c78c4014..000000000 --- a/src/core/meta-pad-action-mapper.c +++ /dev/null @@ -1,860 +0,0 @@ -/* - * Copyright (C) 2014-2020 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Carlos Garnacho - */ - -#include "config.h" - -#include -#include - -#ifdef HAVE_LIBWACOM -#include -#endif - -#include "core/meta-pad-action-mapper.h" -#include "backends/meta-input-device-private.h" -#include "backends/meta-logical-monitor.h" -#include "backends/meta-monitor.h" -#include "core/display-private.h" - -typedef struct _PadMappingInfo PadMappingInfo; - -struct _PadMappingInfo -{ - ClutterInputDevice *device; - GSettings *settings; - guint *group_modes; -}; - -typedef enum -{ - META_PAD_DIRECTION_NONE = -1, - META_PAD_DIRECTION_UP = 0, - META_PAD_DIRECTION_DOWN, - META_PAD_DIRECTION_CW, - META_PAD_DIRECTION_CCW, -} MetaPadDirection; - -struct _MetaPadActionMapper -{ - GObject parent_class; - - GHashTable *pads; - ClutterSeat *seat; - ClutterVirtualInputDevice *virtual_pad_keyboard; - MetaMonitorManager *monitor_manager; - - /* Pad ring/strip emission */ - struct { - ClutterInputDevice *pad; - MetaPadActionType action; - guint number; - double value; - } last_pad_action_info; -}; - -G_DEFINE_TYPE (MetaPadActionMapper, meta_pad_action_mapper, G_TYPE_OBJECT) - -static void -meta_pad_action_mapper_finalize (GObject *object) -{ - MetaPadActionMapper *mapper = META_PAD_ACTION_MAPPER (object); - - g_hash_table_unref (mapper->pads); - g_object_unref (mapper->monitor_manager); - g_clear_object (&mapper->virtual_pad_keyboard); - - G_OBJECT_CLASS (meta_pad_action_mapper_parent_class)->finalize (object); -} - -static void -meta_pad_action_mapper_class_init (MetaPadActionMapperClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_pad_action_mapper_finalize; -} - -static GSettings * -lookup_device_settings (ClutterInputDevice *device) -{ - const char *vendor, *product; - GSettings *settings; - char *path; - - vendor = clutter_input_device_get_vendor_id (device); - product = clutter_input_device_get_product_id (device); - path = g_strdup_printf ("/org/gnome/desktop/peripherals/tablets/%s:%s/", - vendor, product); - - settings = g_settings_new_with_path ("org.gnome.desktop.peripherals.tablet", - path); - g_free (path); - - return settings; -} - -static PadMappingInfo * -pad_mapping_info_new (ClutterInputDevice *pad) -{ - PadMappingInfo *info; - - info = g_new0 (PadMappingInfo, 1); - info->device = pad; - info->settings = lookup_device_settings (pad); - info->group_modes = - g_new0 (guint, clutter_input_device_get_n_mode_groups (pad)); - - return info; -} - -static void -pad_mapping_info_free (PadMappingInfo *info) -{ - g_object_unref (info->settings); - g_free (info->group_modes); - g_free (info); -} - -static void -device_added (ClutterSeat *seat, - ClutterInputDevice *device, - MetaPadActionMapper *mapper) -{ - PadMappingInfo *info; - - if (clutter_input_device_get_device_type (device) == CLUTTER_PAD_DEVICE) - { - info = pad_mapping_info_new (device); - g_hash_table_insert (mapper->pads, device, info); - } -} - -static void -device_removed (ClutterSeat *seat, - ClutterInputDevice *device, - MetaPadActionMapper *mapper) -{ - g_hash_table_remove (mapper->pads, device); -} - -static void -meta_pad_action_mapper_init (MetaPadActionMapper *mapper) -{ - mapper->pads = g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) pad_mapping_info_free); - - mapper->seat = clutter_backend_get_default_seat (clutter_get_default_backend ()); - g_signal_connect (mapper->seat, "device-added", - G_CALLBACK (device_added), mapper); - g_signal_connect (mapper->seat, "device-removed", - G_CALLBACK (device_removed), mapper); -} - -MetaPadActionMapper * -meta_pad_action_mapper_new (MetaMonitorManager *monitor_manager) -{ - MetaPadActionMapper *action_mapper; - - action_mapper = g_object_new (META_TYPE_PAD_ACTION_MAPPER, NULL); - g_set_object (&action_mapper->monitor_manager, monitor_manager); - - return action_mapper; -} - -static GSettings * -lookup_pad_action_settings (ClutterInputDevice *device, - MetaPadActionType action, - guint number, - MetaPadDirection direction, - int mode) -{ - const char *vendor, *product, *action_type, *detail_type = NULL; - GSettings *settings; - GString *path; - char action_label; - - vendor = clutter_input_device_get_vendor_id (device); - product = clutter_input_device_get_product_id (device); - - action_label = 'A' + number; - - switch (action) - { - case META_PAD_ACTION_BUTTON: - action_type = "button"; - break; - case META_PAD_ACTION_RING: - g_assert (direction == META_PAD_DIRECTION_CW || - direction == META_PAD_DIRECTION_CCW); - action_type = "ring"; - detail_type = (direction == META_PAD_DIRECTION_CW) ? "cw" : "ccw"; - break; - case META_PAD_ACTION_STRIP: - g_assert (direction == META_PAD_DIRECTION_UP || - direction == META_PAD_DIRECTION_DOWN); - action_type = "strip"; - detail_type = (direction == META_PAD_DIRECTION_UP) ? "up" : "down"; - break; - default: - return NULL; - } - - path = g_string_new (NULL); - g_string_append_printf (path, "/org/gnome/desktop/peripherals/tablets/%s:%s/%s%c", - vendor, product, action_type, action_label); - - if (detail_type) - g_string_append_printf (path, "-%s", detail_type); - - if (mode >= 0) - g_string_append_printf (path, "-mode-%d", mode); - - g_string_append_c (path, '/'); - - settings = g_settings_new_with_path ("org.gnome.desktop.peripherals.tablet.pad-button", - path->str); - g_string_free (path, TRUE); - - return settings; -} - -static GDesktopPadButtonAction -meta_pad_action_mapper_get_button_action (MetaPadActionMapper *mapper, - ClutterInputDevice *pad, - guint button) -{ - GDesktopPadButtonAction action; - GSettings *settings; - - g_return_val_if_fail (META_IS_PAD_ACTION_MAPPER (mapper), - G_DESKTOP_PAD_BUTTON_ACTION_NONE); - g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (pad), - G_DESKTOP_PAD_BUTTON_ACTION_NONE); - - settings = lookup_pad_action_settings (pad, META_PAD_ACTION_BUTTON, - button, META_PAD_DIRECTION_NONE, -1); - action = g_settings_get_enum (settings, "action"); - g_object_unref (settings); - - return action; -} - -static gboolean -cycle_logical_monitors (MetaPadActionMapper *mapper, - gboolean skip_all_monitors, - MetaLogicalMonitor *current_logical_monitor, - MetaLogicalMonitor **next_logical_monitor) -{ - MetaMonitorManager *monitor_manager = mapper->monitor_manager; - GList *logical_monitors; - - /* We cycle between: - * - the span of all monitors (current_output = NULL), only for - * non-integrated devices. - * - each monitor individually. - */ - - logical_monitors = - meta_monitor_manager_get_logical_monitors (monitor_manager); - - if (!current_logical_monitor) - { - *next_logical_monitor = logical_monitors->data; - } - else - { - GList *l; - - l = g_list_find (logical_monitors, current_logical_monitor); - if (l->next) - *next_logical_monitor = l->next->data; - else if (skip_all_monitors) - *next_logical_monitor = logical_monitors->data; - else - *next_logical_monitor = NULL; - } - - return TRUE; -} - -static MetaMonitor * -logical_monitor_find_monitor (MetaLogicalMonitor *logical_monitor, - const char *vendor, - const char *product, - const char *serial) -{ - GList *monitors; - GList *l; - - monitors = meta_logical_monitor_get_monitors (logical_monitor); - for (l = monitors; l; l = l->next) - { - MetaMonitor *monitor = l->data; - - if (g_strcmp0 (meta_monitor_get_vendor (monitor), vendor) == 0 && - g_strcmp0 (meta_monitor_get_product (monitor), product) == 0 && - g_strcmp0 (meta_monitor_get_serial (monitor), serial) == 0) - return monitor; - } - - return NULL; -} - -static void -meta_pad_action_mapper_find_monitor (MetaPadActionMapper *mapper, - GSettings *settings, - ClutterInputDevice *device, - MetaMonitor **out_monitor, - MetaLogicalMonitor **out_logical_monitor) -{ - MetaMonitorManager *monitor_manager; - MetaMonitor *monitor; - guint n_values; - GList *logical_monitors; - GList *l; - char **edid; - - edid = g_settings_get_strv (settings, "output"); - n_values = g_strv_length (edid); - - if (n_values != 3) - { - g_warning ("EDID configuration for device '%s' " - "is incorrect, must have 3 values", - clutter_input_device_get_device_name (device)); - goto out; - } - - if (!*edid[0] && !*edid[1] && !*edid[2]) - goto out; - - monitor_manager = mapper->monitor_manager; - logical_monitors = - meta_monitor_manager_get_logical_monitors (monitor_manager); - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - - monitor = logical_monitor_find_monitor (logical_monitor, - edid[0], edid[1], edid[2]); - if (monitor) - { - if (out_monitor) - *out_monitor = monitor; - if (out_logical_monitor) - *out_logical_monitor = logical_monitor; - break; - } - } - -out: - g_strfreev (edid); -} - -static void -meta_pad_action_mapper_cycle_tablet_output (MetaPadActionMapper *mapper, - ClutterInputDevice *device) -{ - PadMappingInfo *info; - MetaLogicalMonitor *logical_monitor = NULL; - const char *edid[4] = { 0 }, *pretty_name = NULL; - gboolean is_integrated_device = FALSE; -#ifdef HAVE_LIBWACOM - WacomDevice *wacom_device; -#endif - - g_return_if_fail (META_IS_PAD_ACTION_MAPPER (mapper)); - g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device)); - g_return_if_fail (clutter_input_device_get_device_type (device) == CLUTTER_TABLET_DEVICE || - clutter_input_device_get_device_type (device) == CLUTTER_PAD_DEVICE); - - info = g_hash_table_lookup (mapper->pads, device); - g_return_if_fail (info != NULL); - -#ifdef HAVE_LIBWACOM - wacom_device = meta_input_device_get_wacom_device (META_INPUT_DEVICE (device)); - - if (wacom_device) - { - pretty_name = libwacom_get_name (wacom_device); - is_integrated_device = - libwacom_get_integration_flags (wacom_device) != WACOM_DEVICE_INTEGRATED_NONE; - } -#endif - - meta_pad_action_mapper_find_monitor (mapper, info->settings, device, - NULL, &logical_monitor); - - if (!cycle_logical_monitors (mapper, - is_integrated_device, - logical_monitor, - &logical_monitor)) - return; - - if (logical_monitor) - { - MetaMonitor *monitor; - - /* Pick an arbitrary monitor in the logical monitor to represent it. */ - monitor = meta_logical_monitor_get_monitors (logical_monitor)->data; - edid[0] = meta_monitor_get_vendor (monitor); - edid[1] = meta_monitor_get_product (monitor); - edid[2] = meta_monitor_get_serial (monitor); - } - else - { - edid[0] = ""; - edid[1] = ""; - edid[2] = ""; - } - - g_settings_set_strv (info->settings, "output", edid); - meta_display_show_tablet_mapping_notification (meta_get_display (), - device, pretty_name); -} - -gboolean -meta_pad_action_mapper_is_button_grabbed (MetaPadActionMapper *mapper, - ClutterInputDevice *pad, - guint button) -{ - g_return_val_if_fail (META_IS_PAD_ACTION_MAPPER (mapper), FALSE); - g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (pad), FALSE); - g_return_val_if_fail (clutter_input_device_get_device_type (pad) == - CLUTTER_PAD_DEVICE, FALSE); - - return (meta_pad_action_mapper_get_button_action (mapper, pad, button) != - G_DESKTOP_PAD_BUTTON_ACTION_NONE); -} - -static void -emulate_modifiers (ClutterVirtualInputDevice *device, - ClutterModifierType mods, - ClutterKeyState state) -{ - guint i; - struct { - ClutterModifierType mod; - guint keyval; - } mod_map[] = { - { CLUTTER_SHIFT_MASK, CLUTTER_KEY_Shift_L }, - { CLUTTER_CONTROL_MASK, CLUTTER_KEY_Control_L }, - { CLUTTER_MOD1_MASK, CLUTTER_KEY_Meta_L } - }; - - for (i = 0; i < G_N_ELEMENTS (mod_map); i++) - { - if ((mods & mod_map[i].mod) == 0) - continue; - - clutter_virtual_input_device_notify_keyval (device, - clutter_get_current_event_time (), - mod_map[i].keyval, state); - } -} - -static void -meta_pad_action_mapper_emulate_keybinding (MetaPadActionMapper *mapper, - const char *accel, - gboolean is_press) -{ - ClutterKeyState state; - guint key, mods; - - if (!accel || !*accel) - return; - - /* FIXME: This is appalling */ - gtk_accelerator_parse (accel, &key, &mods); - - if (!mapper->virtual_pad_keyboard) - { - ClutterBackend *backend; - ClutterSeat *seat; - - backend = clutter_get_default_backend (); - seat = clutter_backend_get_default_seat (backend); - - mapper->virtual_pad_keyboard = - clutter_seat_create_virtual_device (seat, - CLUTTER_KEYBOARD_DEVICE); - } - - state = is_press ? CLUTTER_KEY_STATE_PRESSED : CLUTTER_KEY_STATE_RELEASED; - - if (is_press) - emulate_modifiers (mapper->virtual_pad_keyboard, mods, state); - - clutter_virtual_input_device_notify_keyval (mapper->virtual_pad_keyboard, - clutter_get_current_event_time (), - key, state); - if (!is_press) - emulate_modifiers (mapper->virtual_pad_keyboard, mods, state); -} - -static gboolean -meta_pad_action_mapper_handle_button (MetaPadActionMapper *mapper, - ClutterInputDevice *pad, - const ClutterPadButtonEvent *event) -{ - GDesktopPadButtonAction action; - int button, group, mode, n_modes = 0; - gboolean is_press; - GSettings *settings; - char *accel; - - g_return_val_if_fail (META_IS_PAD_ACTION_MAPPER (mapper), FALSE); - g_return_val_if_fail (event->type == CLUTTER_PAD_BUTTON_PRESS || - event->type == CLUTTER_PAD_BUTTON_RELEASE, FALSE); - - button = event->button; - mode = event->mode; - group = clutter_input_device_get_mode_switch_button_group (pad, button); - is_press = event->type == CLUTTER_PAD_BUTTON_PRESS; - - if (group >= 0) - n_modes = clutter_input_device_get_group_n_modes (pad, group); - - if (is_press && n_modes > 0) - { - const char *pretty_name = NULL; - PadMappingInfo *info; -#ifdef HAVE_LIBWACOM - WacomDevice *wacom_device; -#endif - - info = g_hash_table_lookup (mapper->pads, pad); - -#ifdef HAVE_LIBWACOM - wacom_device = meta_input_device_get_wacom_device (META_INPUT_DEVICE (pad)); - - if (wacom_device) - pretty_name = libwacom_get_name (wacom_device); -#endif - meta_display_notify_pad_group_switch (meta_get_display (), pad, - pretty_name, group, mode, n_modes); - info->group_modes[group] = mode; - } - - action = meta_pad_action_mapper_get_button_action (mapper, pad, button); - - switch (action) - { - case G_DESKTOP_PAD_BUTTON_ACTION_SWITCH_MONITOR: - if (is_press) - meta_pad_action_mapper_cycle_tablet_output (mapper, pad); - return TRUE; - case G_DESKTOP_PAD_BUTTON_ACTION_HELP: - if (is_press) - meta_display_request_pad_osd (meta_get_display (), pad, FALSE); - return TRUE; - case G_DESKTOP_PAD_BUTTON_ACTION_KEYBINDING: - settings = lookup_pad_action_settings (pad, META_PAD_ACTION_BUTTON, - button, META_PAD_DIRECTION_NONE, -1); - accel = g_settings_get_string (settings, "keybinding"); - meta_pad_action_mapper_emulate_keybinding (mapper, accel, is_press); - g_object_unref (settings); - g_free (accel); - return TRUE; - case G_DESKTOP_PAD_BUTTON_ACTION_NONE: - default: - return FALSE; - } -} - -static gboolean -meta_pad_action_mapper_handle_action (MetaPadActionMapper *mapper, - ClutterInputDevice *pad, - MetaPadActionType action, - guint number, - MetaPadDirection direction, - guint mode) -{ - GSettings *settings; - gboolean handled = FALSE; - char *accel; - - settings = lookup_pad_action_settings (pad, action, number, direction, mode); - accel = g_settings_get_string (settings, "keybinding"); - - if (accel && *accel) - { - meta_pad_action_mapper_emulate_keybinding (mapper, accel, TRUE); - meta_pad_action_mapper_emulate_keybinding (mapper, accel, FALSE); - handled = TRUE; - } - - g_object_unref (settings); - g_free (accel); - - return handled; -} - -static gboolean -meta_pad_action_mapper_get_action_direction (MetaPadActionMapper *mapper, - const ClutterEvent *event, - MetaPadDirection *direction) -{ - ClutterInputDevice *pad = clutter_event_get_device (event); - MetaPadActionType pad_action; - gboolean has_direction = FALSE; - MetaPadDirection inc_dir, dec_dir; - guint number; - double value; - - *direction = META_PAD_DIRECTION_NONE; - - switch (event->type) - { - case CLUTTER_PAD_RING: - pad_action = META_PAD_ACTION_RING; - number = event->pad_ring.ring_number; - value = event->pad_ring.angle; - inc_dir = META_PAD_DIRECTION_CW; - dec_dir = META_PAD_DIRECTION_CCW; - break; - case CLUTTER_PAD_STRIP: - pad_action = META_PAD_ACTION_STRIP; - number = event->pad_strip.strip_number; - value = event->pad_strip.value; - inc_dir = META_PAD_DIRECTION_DOWN; - dec_dir = META_PAD_DIRECTION_UP; - break; - default: - return FALSE; - } - - if (mapper->last_pad_action_info.pad == pad && - mapper->last_pad_action_info.action == pad_action && - mapper->last_pad_action_info.number == number && - value >= 0 && mapper->last_pad_action_info.value >= 0) - { - *direction = (value - mapper->last_pad_action_info.value) > 0 ? - inc_dir : dec_dir; - has_direction = TRUE; - } - - mapper->last_pad_action_info.pad = pad; - mapper->last_pad_action_info.action = pad_action; - mapper->last_pad_action_info.number = number; - mapper->last_pad_action_info.value = value; - return has_direction; -} - -gboolean -meta_pad_action_mapper_handle_event (MetaPadActionMapper *mapper, - const ClutterEvent *event) -{ - ClutterInputDevice *pad; - MetaPadDirection direction = META_PAD_DIRECTION_NONE; - - pad = clutter_event_get_source_device ((ClutterEvent *) event); - - switch (event->type) - { - case CLUTTER_PAD_BUTTON_PRESS: - case CLUTTER_PAD_BUTTON_RELEASE: - return meta_pad_action_mapper_handle_button (mapper, pad, - &event->pad_button); - case CLUTTER_PAD_RING: - if (!meta_pad_action_mapper_get_action_direction (mapper, - event, &direction)) - return FALSE; - return meta_pad_action_mapper_handle_action (mapper, pad, - META_PAD_ACTION_RING, - event->pad_ring.ring_number, - direction, - event->pad_ring.mode); - case CLUTTER_PAD_STRIP: - if (!meta_pad_action_mapper_get_action_direction (mapper, - event, &direction)) - return FALSE; - return meta_pad_action_mapper_handle_action (mapper, pad, - META_PAD_ACTION_STRIP, - event->pad_strip.strip_number, - direction, - event->pad_strip.mode); - default: - return FALSE; - } -} - - -static char * -compose_directional_action_label (GSettings *direction1, - GSettings *direction2) -{ - char *accel1, *accel2, *str = NULL; - - accel1 = g_settings_get_string (direction1, "keybinding"); - accel2 = g_settings_get_string (direction2, "keybinding"); - - if (accel1 && *accel1 && accel2 && *accel2) - str = g_strdup_printf ("%s / %s", accel1, accel2); - - g_free (accel1); - g_free (accel2); - - return str; -} - -static char * -meta_pad_action_mapper_get_ring_label (MetaPadActionMapper *mapper, - ClutterInputDevice *pad, - guint number, - guint mode) -{ - GSettings *settings1, *settings2; - char *label; - - /* We only allow keybinding actions with those */ - settings1 = lookup_pad_action_settings (pad, META_PAD_ACTION_RING, number, - META_PAD_DIRECTION_CW, mode); - settings2 = lookup_pad_action_settings (pad, META_PAD_ACTION_RING, number, - META_PAD_DIRECTION_CCW, mode); - label = compose_directional_action_label (settings1, settings2); - g_object_unref (settings1); - g_object_unref (settings2); - - return label; -} - -static char * -meta_pad_action_mapper_get_strip_label (MetaPadActionMapper *mapper, - ClutterInputDevice *pad, - guint number, - guint mode) -{ - GSettings *settings1, *settings2; - char *label; - - /* We only allow keybinding actions with those */ - settings1 = lookup_pad_action_settings (pad, META_PAD_ACTION_STRIP, number, - META_PAD_DIRECTION_UP, mode); - settings2 = lookup_pad_action_settings (pad, META_PAD_ACTION_STRIP, number, - META_PAD_DIRECTION_DOWN, mode); - label = compose_directional_action_label (settings1, settings2); - g_object_unref (settings1); - g_object_unref (settings2); - - return label; -} - -static char * -meta_pad_action_mapper_get_button_label (MetaPadActionMapper *mapper, - ClutterInputDevice *pad, - guint button) -{ - GDesktopPadButtonAction action; - int group; - - g_return_val_if_fail (META_IS_PAD_ACTION_MAPPER (mapper), NULL); - g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (pad), NULL); - g_return_val_if_fail (clutter_input_device_get_device_type (pad) == - CLUTTER_PAD_DEVICE, NULL); - - group = clutter_input_device_get_mode_switch_button_group (pad, button); - - if (group >= 0) - { - /* TRANSLATORS: This string refers to a button that switches between - * different modes. - */ - return g_strdup_printf (_("Mode Switch (Group %d)"), group); - } - - action = meta_pad_action_mapper_get_button_action (mapper, pad, button); - - switch (action) - { - case G_DESKTOP_PAD_BUTTON_ACTION_KEYBINDING: - { - GSettings *settings; - char *accel; - - settings = lookup_pad_action_settings (pad, META_PAD_ACTION_BUTTON, - button, META_PAD_DIRECTION_NONE, -1); - accel = g_settings_get_string (settings, "keybinding"); - g_object_unref (settings); - - return accel; - } - case G_DESKTOP_PAD_BUTTON_ACTION_SWITCH_MONITOR: - /* TRANSLATORS: This string refers to an action, cycles drawing tablets' - * mapping through the available outputs. - */ - return g_strdup (_("Switch monitor")); - case G_DESKTOP_PAD_BUTTON_ACTION_HELP: - return g_strdup (_("Show on-screen help")); - case G_DESKTOP_PAD_BUTTON_ACTION_NONE: - default: - return NULL; - } -} - -static guint -get_current_pad_mode (MetaPadActionMapper *mapper, - ClutterInputDevice *pad, - MetaPadActionType action_type, - guint number) -{ - PadMappingInfo *info; - guint group = 0, n_groups; - - info = g_hash_table_lookup (mapper->pads, pad); - n_groups = clutter_input_device_get_n_mode_groups (pad); - - if (!info->group_modes || n_groups == 0) - return 0; - - if (action_type == META_PAD_ACTION_RING || - action_type == META_PAD_ACTION_STRIP) - { - /* Assume features are evenly distributed in groups */ - group = number % n_groups; - } - - return info->group_modes[group]; -} - -char * -meta_pad_action_mapper_get_action_label (MetaPadActionMapper *mapper, - ClutterInputDevice *pad, - MetaPadActionType action_type, - guint number) -{ - guint mode; - - switch (action_type) - { - case META_PAD_ACTION_BUTTON: - return meta_pad_action_mapper_get_button_label (mapper, pad, number); - case META_PAD_ACTION_RING: - mode = get_current_pad_mode (mapper, pad, action_type, number); - return meta_pad_action_mapper_get_ring_label (mapper, pad, number, mode); - case META_PAD_ACTION_STRIP: - mode = get_current_pad_mode (mapper, pad, action_type, number); - return meta_pad_action_mapper_get_strip_label (mapper, pad, number, mode); - } - - return NULL; -} diff --git a/src/core/meta-pad-action-mapper.h b/src/core/meta-pad-action-mapper.h deleted file mode 100644 index 63fc2261b..000000000 --- a/src/core/meta-pad-action-mapper.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2020 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Carlos Garnacho - */ - -#ifndef META_PAD_ACTION_MAPPER_H -#define META_PAD_ACTION_MAPPER_H - -#include "clutter/clutter.h" -#include "meta/display.h" -#include "meta/meta-monitor-manager.h" - -#define META_TYPE_PAD_ACTION_MAPPER (meta_pad_action_mapper_get_type ()) -G_DECLARE_FINAL_TYPE (MetaPadActionMapper, meta_pad_action_mapper, - META, PAD_ACTION_MAPPER, GObject) - -MetaPadActionMapper * meta_pad_action_mapper_new (MetaMonitorManager *monitor_manager); - -gboolean meta_pad_action_mapper_is_button_grabbed (MetaPadActionMapper *mapper, - ClutterInputDevice *pad, - guint button); -gboolean meta_pad_action_mapper_handle_event (MetaPadActionMapper *mapper, - const ClutterEvent *event); -gchar * meta_pad_action_mapper_get_action_label (MetaPadActionMapper *mapper, - ClutterInputDevice *pad, - MetaPadActionType action, - guint number); - -#endif /* META_PAD_ACTION_MAPPER_H */ diff --git a/src/core/meta-private-enums.h b/src/core/meta-private-enums.h deleted file mode 100644 index 1a361c782..000000000 --- a/src/core/meta-private-enums.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2019-2021 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_PRIVATE_ENUMS_H -#define META_PRIVATE_ENUMS_H - -typedef enum _MetaX11DisplayPolicy -{ - META_X11_DISPLAY_POLICY_MANDATORY, - META_X11_DISPLAY_POLICY_ON_DEMAND, - META_X11_DISPLAY_POLICY_DISABLED, -} MetaX11DisplayPolicy; - -#endif /* META_PRIVATE_ENUMS_H */ diff --git a/src/core/meta-selection-private.h b/src/core/meta-selection-private.h deleted file mode 100644 index de9caf9bf..000000000 --- a/src/core/meta-selection-private.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2020 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Carlos Garnacho - */ - -#ifndef META_SELECTION_PRIVATE_H -#define META_SELECTION_PRIVATE_H - -#include "meta/meta-selection.h" - -MetaSelectionSource * - meta_selection_get_current_owner (MetaSelection *selection, - MetaSelectionType selection_type); - -#endif /* META_SELECTION_PRIVATE_H */ diff --git a/src/core/meta-selection-source-memory.c b/src/core/meta-selection-source-memory.c deleted file mode 100644 index a52f50861..000000000 --- a/src/core/meta-selection-source-memory.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2018 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: Carlos Garnacho - */ - -#include "config.h" - -#include "meta/meta-selection-source-memory.h" - -struct _MetaSelectionSourceMemory -{ - MetaSelectionSource parent_instance; - char *mimetype; - GBytes *content; -}; - -G_DEFINE_TYPE (MetaSelectionSourceMemory, - meta_selection_source_memory, - META_TYPE_SELECTION_SOURCE) - -static void -meta_selection_source_memory_read_async (MetaSelectionSource *source, - const char *mimetype, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MetaSelectionSourceMemory *source_mem = META_SELECTION_SOURCE_MEMORY (source); - GInputStream *stream; - g_autoptr (GTask) task = NULL; - - if (g_strcmp0 (mimetype, source_mem->mimetype) != 0) - { - g_task_report_new_error (source, callback, user_data, - meta_selection_source_memory_read_async, - G_IO_ERROR, G_IO_ERROR_FAILED, - "Mimetype not in selection"); - return; - } - - task = g_task_new (source, cancellable, callback, user_data); - g_task_set_source_tag (task, meta_selection_source_memory_read_async); - - stream = g_memory_input_stream_new_from_bytes (source_mem->content); - g_task_return_pointer (task, stream, g_object_unref); -} - -static GInputStream * -meta_selection_source_memory_read_finish (MetaSelectionSource *source, - GAsyncResult *result, - GError **error) -{ - g_assert (g_task_get_source_tag (G_TASK (result)) == - meta_selection_source_memory_read_async); - return g_task_propagate_pointer (G_TASK (result), error); -} - -static GList * -meta_selection_source_memory_get_mimetypes (MetaSelectionSource *source) -{ - MetaSelectionSourceMemory *source_mem = META_SELECTION_SOURCE_MEMORY (source); - - if (!source_mem->mimetype) - return NULL; - - return g_list_prepend (NULL, g_strdup (source_mem->mimetype)); -} - -static void -meta_selection_source_memory_finalize (GObject *object) -{ - MetaSelectionSourceMemory *source_mem = META_SELECTION_SOURCE_MEMORY (object); - - g_clear_pointer (&source_mem->content, g_bytes_unref); - g_free (source_mem->mimetype); - - G_OBJECT_CLASS (meta_selection_source_memory_parent_class)->finalize (object); -} - -static void -meta_selection_source_memory_class_init (MetaSelectionSourceMemoryClass *klass) -{ - MetaSelectionSourceClass *source_class = META_SELECTION_SOURCE_CLASS (klass); - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_selection_source_memory_finalize; - - source_class->read_async = meta_selection_source_memory_read_async; - source_class->read_finish = meta_selection_source_memory_read_finish; - source_class->get_mimetypes = meta_selection_source_memory_get_mimetypes; -} - -static void -meta_selection_source_memory_init (MetaSelectionSourceMemory *source) -{ -} - -MetaSelectionSource * -meta_selection_source_memory_new (const char *mimetype, - GBytes *content) -{ - MetaSelectionSourceMemory *source; - - g_return_val_if_fail (mimetype != NULL, NULL); - g_return_val_if_fail (content != NULL, NULL); - - source = g_object_new (META_TYPE_SELECTION_SOURCE_MEMORY, NULL); - source->mimetype = g_strdup (mimetype); - source->content = g_bytes_ref (content); - - return META_SELECTION_SOURCE (source); -} diff --git a/src/core/meta-selection-source-remote.c b/src/core/meta-selection-source-remote.c deleted file mode 100644 index aa9f9e60a..000000000 --- a/src/core/meta-selection-source-remote.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2020 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. - * - */ - -#include "config.h" - -#include "core/meta-selection-source-remote.h" - -#include - -#include "backends/meta-remote-desktop-session.h" - -struct _MetaSelectionSourceRemote -{ - MetaSelectionSource parent; - - MetaRemoteDesktopSession *session; - GList *mime_types; -}; - -G_DEFINE_TYPE (MetaSelectionSourceRemote, - meta_selection_source_remote, - META_TYPE_SELECTION_SOURCE) - -MetaSelectionSourceRemote * -meta_selection_source_remote_new (MetaRemoteDesktopSession *session, - GList *mime_types) -{ - MetaSelectionSourceRemote *source_remote; - - source_remote = g_object_new (META_TYPE_SELECTION_SOURCE_REMOTE, NULL); - source_remote->session = session; - source_remote->mime_types = mime_types; - - return source_remote; -} - -static void -meta_selection_source_remote_read_async (MetaSelectionSource *source, - const char *mimetype, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MetaSelectionSourceRemote *source_remote = - META_SELECTION_SOURCE_REMOTE (source); - GTask *task; - - task = g_task_new (source, cancellable, callback, user_data); - g_task_set_source_tag (task, meta_selection_source_remote_read_async); - - meta_remote_desktop_session_request_transfer (source_remote->session, - mimetype, - task); -} - -static GInputStream * -meta_selection_source_remote_read_finish (MetaSelectionSource *source, - GAsyncResult *result, - GError **error) -{ - g_return_val_if_fail (g_task_is_valid (result, source), FALSE); - g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == - meta_selection_source_remote_read_async, FALSE); - - return g_task_propagate_pointer (G_TASK (result), error); -} - -void -meta_selection_source_remote_complete_transfer (MetaSelectionSourceRemote *source_remote, - int fd, - GTask *task) -{ - GInputStream *stream; - - stream = g_unix_input_stream_new (fd, TRUE); - g_task_return_pointer (task, stream, g_object_unref); - g_object_unref (task); -} - -void -meta_selection_source_remote_cancel_transfer (MetaSelectionSourceRemote *source_remote, - GTask *task) -{ - g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_CANCELLED, - "Remote selection transfer was cancelled"); - g_object_unref (task); -} - -static GList * -meta_selection_source_remote_get_mimetypes (MetaSelectionSource *source) -{ - MetaSelectionSourceRemote *source_remote = - META_SELECTION_SOURCE_REMOTE (source); - - return g_list_copy_deep (source_remote->mime_types, - (GCopyFunc) g_strdup, - NULL); -} - -static void -meta_selection_source_remote_finalize (GObject *object) -{ - MetaSelectionSourceRemote *source_remote = - META_SELECTION_SOURCE_REMOTE (object); - - g_list_free_full (source_remote->mime_types, g_free); - - G_OBJECT_CLASS (meta_selection_source_remote_parent_class)->finalize (object); -} - -static void -meta_selection_source_remote_init (MetaSelectionSourceRemote *source_remote) -{ -} - -static void -meta_selection_source_remote_class_init (MetaSelectionSourceRemoteClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaSelectionSourceClass *source_class = META_SELECTION_SOURCE_CLASS (klass); - - object_class->finalize = meta_selection_source_remote_finalize; - - source_class->read_async = meta_selection_source_remote_read_async; - source_class->read_finish = meta_selection_source_remote_read_finish; - source_class->get_mimetypes = meta_selection_source_remote_get_mimetypes; -} diff --git a/src/core/meta-selection-source-remote.h b/src/core/meta-selection-source-remote.h deleted file mode 100644 index 51e66957b..000000000 --- a/src/core/meta-selection-source-remote.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2020 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_SELECTION_SOURCE_REMOTE_H -#define META_SELECTION_SOURCE_REMOTE_H - -#include "backends/meta-remote-desktop.h" -#include "meta/meta-selection-source.h" - -#define META_TYPE_SELECTION_SOURCE_REMOTE (meta_selection_source_remote_get_type ()) -G_DECLARE_FINAL_TYPE (MetaSelectionSourceRemote, - meta_selection_source_remote, - META, SELECTION_SOURCE_REMOTE, - MetaSelectionSource) - -void meta_selection_source_remote_complete_transfer (MetaSelectionSourceRemote *source_remote, - int fd, - GTask *task); - -void meta_selection_source_remote_cancel_transfer (MetaSelectionSourceRemote *source_remote, - GTask *task); - -MetaSelectionSourceRemote * meta_selection_source_remote_new (MetaRemoteDesktopSession *session, - GList *mime_types); - -#endif /* META_SELECTION_SOURCE_REMOTE_H */ diff --git a/src/core/meta-selection-source.c b/src/core/meta-selection-source.c deleted file mode 100644 index b076391ce..000000000 --- a/src/core/meta-selection-source.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) 2018 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: Carlos Garnacho - */ - -#include "config.h" - -#include "meta/meta-selection.h" -#include "meta/meta-selection-source.h" - -typedef struct MetaSelectionSourcePrivate MetaSelectionSourcePrivate; - -struct MetaSelectionSourcePrivate -{ - guint active : 1; -}; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaSelectionSource, - meta_selection_source, - G_TYPE_OBJECT) - -enum -{ - ACTIVE, - INACTIVE, - N_SIGNALS -}; - -static guint signals[N_SIGNALS] = { 0 }; - -static void -meta_selection_source_activated (MetaSelectionSource *source) -{ - MetaSelectionSourcePrivate *priv = - meta_selection_source_get_instance_private (source); - - priv->active = TRUE; -} - -static void -meta_selection_source_deactivated (MetaSelectionSource *source) -{ - MetaSelectionSourcePrivate *priv = - meta_selection_source_get_instance_private (source); - - priv->active = FALSE; -} - -static void -meta_selection_source_class_init (MetaSelectionSourceClass *klass) -{ - klass->activated = meta_selection_source_activated; - klass->deactivated = meta_selection_source_deactivated; - - signals[ACTIVE] = - g_signal_new ("activated", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (MetaSelectionSourceClass, activated), - NULL, NULL, NULL, - G_TYPE_NONE, 0); - signals[INACTIVE] = - g_signal_new ("deactivated", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (MetaSelectionSourceClass, deactivated), - NULL, NULL, NULL, - G_TYPE_NONE, 0); -} - -static void -meta_selection_source_init (MetaSelectionSource *source) -{ -} - -void -meta_selection_source_read_async (MetaSelectionSource *source, - const gchar *mimetype, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - g_return_if_fail (META_IS_SELECTION_SOURCE (source)); - g_return_if_fail (mimetype != NULL); - g_return_if_fail (callback != NULL); - - META_SELECTION_SOURCE_GET_CLASS (source)->read_async (source, - mimetype, - cancellable, - callback, - user_data); -} - -/** - * meta_selection_source_read_finish: - * @source: The selection source - * @result: The async result - * @error: Location for returned error - * - * Finishes a read from the selection source. - * - * Returns: (transfer full): The resulting #GInputStream - */ -GInputStream * -meta_selection_source_read_finish (MetaSelectionSource *source, - GAsyncResult *result, - GError **error) -{ - g_return_val_if_fail (META_IS_SELECTION_SOURCE (source), NULL); - g_return_val_if_fail (g_task_is_valid (result, source), NULL); - - return META_SELECTION_SOURCE_GET_CLASS (source)->read_finish (source, - result, - error); -} - -/** - * meta_selection_source_get_mimetypes: - * @source: The selection source - * - * Returns the list of supported mimetypes. - * - * Returns: (element-type utf8) (transfer full): The supported mimetypes - */ -GList * -meta_selection_source_get_mimetypes (MetaSelectionSource *source) -{ - g_return_val_if_fail (META_IS_SELECTION_SOURCE (source), NULL); - - return META_SELECTION_SOURCE_GET_CLASS (source)->get_mimetypes (source); -} - -/** - * meta_selection_source_is_active: - * @source: the selection source - * - * Returns #TRUE if the source is active on a selection. - * - * Returns: #TRUE if the source owns a selection. - **/ -gboolean -meta_selection_source_is_active (MetaSelectionSource *source) -{ - MetaSelectionSourcePrivate *priv = - meta_selection_source_get_instance_private (source); - - g_return_val_if_fail (META_IS_SELECTION_SOURCE (source), FALSE); - - return priv->active; -} diff --git a/src/core/meta-selection.c b/src/core/meta-selection.c deleted file mode 100644 index 4e42e59a9..000000000 --- a/src/core/meta-selection.c +++ /dev/null @@ -1,415 +0,0 @@ -/* - * Copyright (C) 2018 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: Carlos Garnacho - */ - -#include "config.h" - -#include "core/meta-selection-private.h" -#include "meta/meta-selection.h" - -typedef struct TransferRequest TransferRequest; - -struct _MetaSelection -{ - GObject parent_instance; - MetaDisplay *display; - MetaSelectionSource *owners[META_N_SELECTION_TYPES]; -}; - -struct TransferRequest -{ - MetaSelectionType selection_type; - GInputStream *istream; - GOutputStream *ostream; - gssize len; -}; - -enum -{ - OWNER_CHANGED, - N_SIGNALS -}; - -static guint signals[N_SIGNALS] = { 0 }; - -G_DEFINE_TYPE (MetaSelection, meta_selection, G_TYPE_OBJECT) - -static void read_selection_source_async (GTask *task, - TransferRequest *request); - -static void -meta_selection_dispose (GObject *object) -{ - MetaSelection *selection = META_SELECTION (object); - guint i; - - for (i = 0; i < META_N_SELECTION_TYPES; i++) - { - g_clear_object (&selection->owners[i]); - } - - G_OBJECT_CLASS (meta_selection_parent_class)->dispose (object); -} - -static void -meta_selection_class_init (MetaSelectionClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = meta_selection_dispose; - - signals[OWNER_CHANGED] = - g_signal_new ("owner-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 2, - G_TYPE_UINT, - META_TYPE_SELECTION_SOURCE); -} - -static void -meta_selection_init (MetaSelection *selection) -{ -} - -MetaSelection * -meta_selection_new (MetaDisplay *display) -{ - return g_object_new (META_TYPE_SELECTION, - NULL); -} - -/** - * meta_selection_set_owner: - * @selection: The selection manager - * @selection_type: Selection type - * @owner: New selection owner - * - * Sets @owner as the owner of the selection given by @selection_type, - * unsets any previous owner there was. - **/ -void -meta_selection_set_owner (MetaSelection *selection, - MetaSelectionType selection_type, - MetaSelectionSource *owner) -{ - g_return_if_fail (META_IS_SELECTION (selection)); - g_return_if_fail (selection_type < META_N_SELECTION_TYPES); - - if (selection->owners[selection_type] == owner) - return; - - if (selection->owners[selection_type]) - g_signal_emit_by_name (selection->owners[selection_type], "deactivated"); - - g_set_object (&selection->owners[selection_type], owner); - g_signal_emit_by_name (owner, "activated"); - g_signal_emit (selection, signals[OWNER_CHANGED], 0, selection_type, owner); -} - -/** - * meta_selection_unset_owner: - * @selection: The selection manager - * @selection_type: Selection type - * @owner: Owner to unset - * - * Unsets @owner as the owner the selection given by @selection_type. If - * @owner does not own the selection, nothing is done. - **/ -void -meta_selection_unset_owner (MetaSelection *selection, - MetaSelectionType selection_type, - MetaSelectionSource *owner) -{ - g_return_if_fail (META_IS_SELECTION (selection)); - g_return_if_fail (selection_type < META_N_SELECTION_TYPES); - - if (selection->owners[selection_type] == owner) - { - g_signal_emit_by_name (owner, "deactivated"); - g_clear_object (&selection->owners[selection_type]); - g_signal_emit (selection, signals[OWNER_CHANGED], 0, - selection_type, NULL); - } -} - -/** - * meta_selection_get_mimetypes: - * @selection: The selection manager - * @selection_type: Selection to query - * - * Returns the list of supported mimetypes for the given selection type. - * - * Returns: (element-type utf8) (transfer full): The supported mimetypes - */ -GList * -meta_selection_get_mimetypes (MetaSelection *selection, - MetaSelectionType selection_type) -{ - g_return_val_if_fail (META_IS_SELECTION (selection), NULL); - g_return_val_if_fail (selection_type < META_N_SELECTION_TYPES, NULL); - - if (!selection->owners[selection_type]) - return NULL; - - return meta_selection_source_get_mimetypes (selection->owners[selection_type]); -} - -static TransferRequest * -transfer_request_new (GOutputStream *ostream, - MetaSelectionType selection_type, - gssize len) -{ - TransferRequest *request; - - request = g_new0 (TransferRequest, 1); - request->ostream = g_object_ref (ostream); - request->selection_type = selection_type; - request->len = len; - return request; -} - -static void -transfer_request_free (TransferRequest *request) -{ - g_clear_object (&request->istream); - g_clear_object (&request->ostream); - g_free (request); -} - -static void -splice_cb (GOutputStream *stream, - GAsyncResult *result, - GTask *task) -{ - GError *error = NULL; - - g_output_stream_splice_finish (stream, result, &error); - if (error) - { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static void -write_cb (GOutputStream *stream, - GAsyncResult *result, - GTask *task) -{ - TransferRequest *request; - GError *error = NULL; - - g_output_stream_write_bytes_finish (stream, result, &error); - if (error) - { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - request = g_task_get_task_data (task); - - if (request->len > 0) - { - read_selection_source_async (task, request); - } - else - { - g_task_return_boolean (task, TRUE); - g_object_unref (task); - } -} - -static void -read_cb (GInputStream *stream, - GAsyncResult *result, - GTask *task) -{ - TransferRequest *request; - GError *error = NULL; - GBytes *bytes; - - bytes = g_input_stream_read_bytes_finish (stream, result, &error); - if (error) - { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - else if (g_bytes_get_size (bytes) == 0) - { - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - - request = g_task_get_task_data (task); - - if (request->len < g_bytes_get_size (bytes)) - { - GBytes *copy; - - /* Trim content */ - copy = g_bytes_new_from_bytes (bytes, 0, request->len); - g_bytes_unref (bytes); - bytes = copy; - } - - request->len -= g_bytes_get_size (bytes); - g_output_stream_write_bytes_async (request->ostream, - bytes, - G_PRIORITY_DEFAULT, - g_task_get_cancellable (task), - (GAsyncReadyCallback) write_cb, - task); - g_bytes_unref (bytes); -} - -static void -read_selection_source_async (GTask *task, - TransferRequest *request) -{ - g_input_stream_read_bytes_async (request->istream, - (gsize) request->len, - G_PRIORITY_DEFAULT, - g_task_get_cancellable (task), - (GAsyncReadyCallback) read_cb, - task); -} - -static void -source_read_cb (MetaSelectionSource *source, - GAsyncResult *result, - GTask *task) -{ - TransferRequest *request; - GInputStream *stream; - GError *error = NULL; - - stream = meta_selection_source_read_finish (source, result, &error); - if (!stream) - { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - request = g_task_get_task_data (task); - request->istream = stream; - - if (request->len < 0) - { - g_output_stream_splice_async (request->ostream, - request->istream, - G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | - G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, - G_PRIORITY_DEFAULT, - g_task_get_cancellable (task), - (GAsyncReadyCallback) splice_cb, - task); - } - else - { - read_selection_source_async (task, request); - } -} - -/** - * meta_selection_transfer_async: - * @selection: The selection manager - * @selection_type: Selection type - * @mimetype: Mimetype to transfer - * @size: Maximum size to transfer, -1 for unlimited - * @output: Output stream to write contents to - * @cancellable: Cancellable - * @callback: User callback - * @user_data: User data - * - * Requests a transfer of @mimetype on the selection given by - * @selection_type. - **/ -void -meta_selection_transfer_async (MetaSelection *selection, - MetaSelectionType selection_type, - const char *mimetype, - gssize size, - GOutputStream *output, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - g_return_if_fail (META_IS_SELECTION (selection)); - g_return_if_fail (selection_type < META_N_SELECTION_TYPES); - g_return_if_fail (G_IS_OUTPUT_STREAM (output)); - g_return_if_fail (mimetype != NULL); - - task = g_task_new (selection, cancellable, callback, user_data); - g_task_set_source_tag (task, meta_selection_transfer_async); - - g_task_set_task_data (task, - transfer_request_new (output, selection_type, size), - (GDestroyNotify) transfer_request_free); - meta_selection_source_read_async (selection->owners[selection_type], - mimetype, - cancellable, - (GAsyncReadyCallback) source_read_cb, - task); -} - -/** - * meta_selection_transfer_finish: - * @selection: The selection manager - * @result: The async result - * @error: Location for returned error, or %NULL - * - * Finishes the transfer of a queried mimetype. - * - * Returns: #TRUE if the transfer was successful. - **/ -gboolean -meta_selection_transfer_finish (MetaSelection *selection, - GAsyncResult *result, - GError **error) -{ - g_return_val_if_fail (g_task_is_valid (result, selection), FALSE); - g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == - meta_selection_transfer_async, FALSE); - - return g_task_propagate_boolean (G_TASK (result), error); -} - -MetaSelectionSource * -meta_selection_get_current_owner (MetaSelection *selection, - MetaSelectionType selection_type) -{ - g_return_val_if_fail (META_IS_SELECTION (selection), NULL); - g_return_val_if_fail (selection_type < META_N_SELECTION_TYPES, NULL); - - return selection->owners[selection_type]; -} diff --git a/src/core/meta-sound-player.c b/src/core/meta-sound-player.c deleted file mode 100644 index e2d103893..000000000 --- a/src/core/meta-sound-player.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright (C) 2018 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: Carlos Garnacho - */ - -#include "config.h" - -#include - -#include "meta/meta-sound-player.h" - -#define EVENT_SOUNDS_KEY "event-sounds" -#define THEME_NAME_KEY "theme-name" - -typedef struct _MetaPlayRequest MetaPlayRequest; - -struct _MetaSoundPlayer -{ - GObject parent; - GThreadPool *queue; - GSettings *settings; - ca_context *context; - uint32_t id_pool; -}; - -struct _MetaPlayRequest -{ - ca_proplist *props; - uint32_t id; - gulong cancel_id; - GCancellable *cancellable; - MetaSoundPlayer *player; -}; - -const char * const cache_allow_list[] = { - "bell-window-system", - "desktop-switch-left", - "desktop-switch-right", - "desktop-switch-up", - "desktop-switch-down", - NULL -}; - -G_DEFINE_TYPE (MetaSoundPlayer, meta_sound_player, G_TYPE_OBJECT) - -static MetaPlayRequest * -meta_play_request_new (MetaSoundPlayer *player, - ca_proplist *props, - GCancellable *cancellable) -{ - MetaPlayRequest *req; - - req = g_new0 (MetaPlayRequest, 1); - req->props = props; - req->player = player; - g_set_object (&req->cancellable, cancellable); - - return req; -} - -static void -meta_play_request_free (MetaPlayRequest *req) -{ - g_clear_object (&req->cancellable); - ca_proplist_destroy (req->props); - g_free (req); -} - -static void -meta_sound_player_finalize (GObject *object) -{ - MetaSoundPlayer *player = META_SOUND_PLAYER (object); - - g_object_unref (player->settings); - g_thread_pool_free (player->queue, FALSE, TRUE); - ca_context_destroy (player->context); - - G_OBJECT_CLASS (meta_sound_player_parent_class)->finalize (object); -} - -static void -meta_sound_player_class_init (MetaSoundPlayerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_sound_player_finalize; -} - -static void -cancelled_cb (GCancellable *cancellable, - MetaPlayRequest *req) -{ - ca_context_cancel (req->player->context, req->id); -} - -static void -finish_cb (ca_context *context, - uint32_t id, - int error_code, - gpointer user_data) -{ - MetaPlayRequest *req = user_data; - - if (error_code != CA_ERROR_CANCELED) - g_cancellable_disconnect (req->cancellable, req->cancel_id); - else if (req->cancellable != NULL) - g_clear_signal_handler (&req->cancel_id, req->cancellable); - - meta_play_request_free (req); -} - -static void -play_sound (MetaPlayRequest *req, - MetaSoundPlayer *player) -{ - req->id = player->id_pool++; - - if (ca_context_play_full (player->context, req->id, req->props, - finish_cb, req) != CA_SUCCESS) - { - meta_play_request_free (req); - return; - } - - if (req->cancellable) - { - gulong cancel_id = - g_cancellable_connect (req->cancellable, - G_CALLBACK (cancelled_cb), req, NULL); - if (cancel_id) - req->cancel_id = cancel_id; - } -} - -static void -settings_changed_cb (GSettings *settings, - const char *key, - MetaSoundPlayer *player) -{ - if (strcmp (key, EVENT_SOUNDS_KEY) == 0) - { - gboolean enabled; - - enabled = g_settings_get_boolean (settings, EVENT_SOUNDS_KEY); - ca_context_change_props (player->context, CA_PROP_CANBERRA_ENABLE, - enabled ? "1" : "0", NULL); - } - else if (strcmp (key, THEME_NAME_KEY) == 0) - { - char *theme_name; - - theme_name = g_settings_get_string (settings, THEME_NAME_KEY); - ca_context_change_props (player->context, CA_PROP_CANBERRA_XDG_THEME_NAME, - theme_name, NULL); - g_free (theme_name); - } -} - -static ca_context * -create_context (GSettings *settings) -{ - ca_context *context; - ca_proplist *props; - gboolean enabled; - char *theme_name; - - if (ca_context_create (&context) != CA_SUCCESS) - return NULL; - - if (ca_proplist_create (&props) != CA_SUCCESS) - { - ca_context_destroy (context); - return NULL; - } - - ca_proplist_sets (props, CA_PROP_APPLICATION_NAME, "Mutter"); - - enabled = g_settings_get_boolean (settings, EVENT_SOUNDS_KEY); - ca_proplist_sets (props, CA_PROP_CANBERRA_ENABLE, enabled ? "1" : "0"); - - theme_name = g_settings_get_string (settings, THEME_NAME_KEY); - ca_proplist_sets (props, CA_PROP_CANBERRA_XDG_THEME_NAME, theme_name); - g_free (theme_name); - - ca_context_change_props_full (context, props); - ca_proplist_destroy (props); - - return context; -} - -static void -meta_sound_player_init (MetaSoundPlayer *player) -{ - player->queue = g_thread_pool_new ((GFunc) play_sound, - player, 1, FALSE, NULL); - player->settings = g_settings_new ("org.gnome.desktop.sound"); - player->context = create_context (player->settings); - - g_signal_connect (player->settings, "changed", - G_CALLBACK (settings_changed_cb), player); -} - -static void -build_ca_proplist (ca_proplist *props, - const char *event_property, - const char *event_id, - const char *event_description) -{ - ca_proplist_sets (props, event_property, event_id); - ca_proplist_sets (props, CA_PROP_EVENT_DESCRIPTION, event_description); -} - -/** - * meta_sound_player_play_from_theme: - * @player: a #MetaSoundPlayer - * @name: sound theme name of the event - * @description: description of the event - * @cancellable: cancellable for the request - * - * Plays a sound from the sound theme. - **/ -void -meta_sound_player_play_from_theme (MetaSoundPlayer *player, - const char *name, - const char *description, - GCancellable *cancellable) -{ - MetaPlayRequest *req; - ca_proplist *props; - - g_return_if_fail (META_IS_SOUND_PLAYER (player)); - g_return_if_fail (name != NULL); - g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); - - ca_proplist_create (&props); - build_ca_proplist (props, CA_PROP_EVENT_ID, name, description); - - if (g_strv_contains (cache_allow_list, name)) - ca_proplist_sets (props, CA_PROP_CANBERRA_CACHE_CONTROL, "permanent"); - else - ca_proplist_sets (props, CA_PROP_CANBERRA_CACHE_CONTROL, "volatile"); - - req = meta_play_request_new (player, props, cancellable); - g_thread_pool_push (player->queue, req, NULL); -} - -/** - * meta_sound_player_play_from_file: - * @player: a #MetaSoundPlayer - * @file: file to play - * @description: description of the played sound - * @cancellable: cancellable for the request - * - * Plays a sound from a file. - **/ -void -meta_sound_player_play_from_file (MetaSoundPlayer *player, - GFile *file, - const char *description, - GCancellable *cancellable) -{ - MetaPlayRequest *req; - ca_proplist *props; - char *path; - - g_return_if_fail (META_IS_SOUND_PLAYER (player)); - g_return_if_fail (G_IS_FILE (file)); - g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); - - path = g_file_get_path (file); - g_return_if_fail (path != NULL); - - ca_proplist_create (&props); - build_ca_proplist (props, CA_PROP_MEDIA_FILENAME, path, description); - ca_proplist_sets (props, CA_PROP_CANBERRA_CACHE_CONTROL, "volatile"); - g_free (path); - - req = meta_play_request_new (player, props, cancellable); - g_thread_pool_push (player->queue, req, NULL); -} diff --git a/src/core/meta-workspace-manager-private.h b/src/core/meta-workspace-manager-private.h deleted file mode 100644 index 261c4d47c..000000000 --- a/src/core/meta-workspace-manager-private.h +++ /dev/null @@ -1,96 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002, 2003, 2004 Red Hat, Inc. - * Copyright (C) 2003, 2004 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * 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 . - */ - -#ifndef META_WORKSPACE_MANAGER_PRIVATE_H -#define META_WORKSPACE_MANAGER_PRIVATE_H - -#include - -#include "core/display-private.h" -#include "meta/common.h" -#include "meta/types.h" -#include "meta/meta-workspace-manager.h" - -struct _MetaWorkspaceManager -{ - GObject parent; - - MetaDisplay *display; - MetaWorkspace *active_workspace; - - GList *workspaces; - - int rows_of_workspaces; - int columns_of_workspaces; - MetaDisplayCorner starting_corner; - guint vertical_workspaces : 1; - guint workspace_layout_overridden : 1; -}; - -MetaWorkspaceManager *meta_workspace_manager_new (MetaDisplay *display); - -void meta_workspace_manager_init_workspaces (MetaWorkspaceManager *workspace_manager); -void meta_workspace_manager_update_workspace_layout (MetaWorkspaceManager *workspace_manager, - MetaDisplayCorner starting_corner, - gboolean vertical_layout, - int n_rows, - int n_columns); - -void meta_workspace_manager_reload_work_areas (MetaWorkspaceManager *workspace_manager); - -typedef struct MetaWorkspaceLayout MetaWorkspaceLayout; - -struct MetaWorkspaceLayout -{ - int rows; - int cols; - int *grid; - int grid_area; - int current_row; - int current_col; -}; - -void meta_workspace_manager_calc_workspace_layout (MetaWorkspaceManager *workspace_manager, - int num_workspaces, - int current_space, - MetaWorkspaceLayout *layout); - -void meta_workspace_manager_free_workspace_layout (MetaWorkspaceLayout *layout); - -void meta_workspace_manager_minimize_all_on_active_workspace_except (MetaWorkspaceManager *workspace_manager, - MetaWindow *keep); - -/* Show/hide the desktop (temporarily hide all windows) */ -void meta_workspace_manager_show_desktop (MetaWorkspaceManager *workspace_manager, - guint32 timestamp); -void meta_workspace_manager_unshow_desktop (MetaWorkspaceManager *workspace_manager); - -void meta_workspace_manager_workspace_switched (MetaWorkspaceManager *workspace_manager, - int from, - int to, - MetaMotionDirection direction); - -void meta_workspace_manager_update_num_workspaces (MetaWorkspaceManager *workspace_manager, - guint32 timestamp, - int new_num); - -#endif /* META_WORKSPACE_MANAGER_PRIVATE_H */ diff --git a/src/core/meta-workspace-manager.c b/src/core/meta-workspace-manager.c deleted file mode 100644 index 61fbc0090..000000000 --- a/src/core/meta-workspace-manager.c +++ /dev/null @@ -1,1060 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002, 2003, 2004 Red Hat, Inc. - * Copyright (C) 2003, 2004 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * 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 . - */ - -#include "config.h" - -#include "core/meta-workspace-manager-private.h" - -#include -#include -#include - -#include "core/window-private.h" -#include "core/workspace-private.h" -#include "meta/meta-enum-types.h" -#include "meta/prefs.h" -#include "meta/util.h" - -G_DEFINE_TYPE (MetaWorkspaceManager, meta_workspace_manager, G_TYPE_OBJECT) - -enum -{ - WORKSPACE_ADDED, - WORKSPACE_REMOVED, - WORKSPACE_SWITCHED, - WORKSPACES_REORDERED, - ACTIVE_WORKSPACE_CHANGED, - SHOWING_DESKTOP_CHANGED, - LAST_SIGNAL -}; - -enum -{ - PROP_0, - - PROP_LAYOUT_COLUMNS, - PROP_LAYOUT_ROWS, - - PROP_N_WORKSPACES -}; - -static guint workspace_manager_signals [LAST_SIGNAL] = { 0 }; - -static void prefs_changed_callback (MetaPreference pref, - gpointer data); - -static void -meta_workspace_manager_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaWorkspaceManager *workspace_manager = META_WORKSPACE_MANAGER (object); - - switch (prop_id) - { - case PROP_LAYOUT_COLUMNS: - g_value_set_int (value, workspace_manager->columns_of_workspaces); - break; - case PROP_LAYOUT_ROWS: - g_value_set_int (value, workspace_manager->rows_of_workspaces); - break; - case PROP_N_WORKSPACES: - g_value_set_int (value, meta_workspace_manager_get_n_workspaces (workspace_manager)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_workspace_manager_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (prop_id) - { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_workspace_manager_finalize (GObject *object) -{ - MetaWorkspaceManager *workspace_manager = META_WORKSPACE_MANAGER (object); - - meta_prefs_remove_listener (prefs_changed_callback, workspace_manager); - - G_OBJECT_CLASS (meta_workspace_manager_parent_class)->finalize (object); -} - -static void -meta_workspace_manager_class_init (MetaWorkspaceManagerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->get_property = meta_workspace_manager_get_property; - object_class->set_property = meta_workspace_manager_set_property; - - object_class->finalize = meta_workspace_manager_finalize; - - workspace_manager_signals[WORKSPACE_ADDED] = - g_signal_new ("workspace-added", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, - 1, - G_TYPE_INT); - - workspace_manager_signals[WORKSPACE_REMOVED] = - g_signal_new ("workspace-removed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, - 1, - G_TYPE_INT); - - workspace_manager_signals[WORKSPACE_SWITCHED] = - g_signal_new ("workspace-switched", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, - 3, - G_TYPE_INT, - G_TYPE_INT, - META_TYPE_MOTION_DIRECTION); - - /* Emitted when calling meta_workspace_manager_reorder_workspace. - * - * This signal is emitted when a workspace has been reordered to - * a different index. Note that other workspaces can change - * their index too when reordering happens. - */ - workspace_manager_signals[WORKSPACES_REORDERED] = - g_signal_new ("workspaces-reordered", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - workspace_manager_signals[ACTIVE_WORKSPACE_CHANGED] = - g_signal_new ("active-workspace-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); - - workspace_manager_signals[SHOWING_DESKTOP_CHANGED] = - g_signal_new ("showing-desktop-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); - - g_object_class_install_property (object_class, - PROP_LAYOUT_COLUMNS, - g_param_spec_int ("layout-columns", - "Layout columns", - "Number of columns in layout", - -1, G_MAXINT, 1, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (object_class, - PROP_LAYOUT_ROWS, - g_param_spec_int ("layout-rows", - "Layout rows", - "Number of rows in layout", - -1, G_MAXINT, -1, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (object_class, - PROP_N_WORKSPACES, - g_param_spec_int ("n-workspaces", - "N Workspaces", - "Number of workspaces", - 1, G_MAXINT, 1, - G_PARAM_READABLE)); -} - -static void -meta_workspace_manager_init (MetaWorkspaceManager *workspace_manager) -{ -} - -void -meta_workspace_manager_reload_work_areas (MetaWorkspaceManager *workspace_manager) -{ - GList *l; - - for (l = workspace_manager->workspaces; l; l = l->next) - { - MetaWorkspace *workspace = l->data; - - meta_workspace_invalidate_work_area (workspace); - } -} - -MetaWorkspaceManager * -meta_workspace_manager_new (MetaDisplay *display) -{ - MetaWorkspaceManager *workspace_manager; - - workspace_manager = g_object_new (META_TYPE_WORKSPACE_MANAGER, NULL); - - workspace_manager->display = display; - workspace_manager->active_workspace = NULL; - workspace_manager->workspaces = NULL; - workspace_manager->rows_of_workspaces = 1; - workspace_manager->columns_of_workspaces = -1; - workspace_manager->vertical_workspaces = FALSE; - workspace_manager->starting_corner = META_DISPLAY_TOPLEFT; - - /* This is the default layout extracted from default - * variable values in update_num_workspaces () - * This can be overridden using _NET_DESKTOP_LAYOUT in - * meta_x11_display_new (), if it's specified */ - meta_workspace_manager_update_workspace_layout (workspace_manager, - META_DISPLAY_TOPLEFT, - FALSE, - 1, - -1); - - /* There must be at least one workspace at all times, - * so create that required workspace. - */ - meta_workspace_new (workspace_manager); - - meta_workspace_manager_init_workspaces (workspace_manager); - - meta_prefs_add_listener (prefs_changed_callback, workspace_manager); - - return workspace_manager; -} - -void -meta_workspace_manager_init_workspaces (MetaWorkspaceManager *workspace_manager) -{ - int num; - - g_return_if_fail (META_IS_WORKSPACE_MANAGER (workspace_manager)); - - if (meta_prefs_get_dynamic_workspaces ()) - /* This will be properly updated using _NET_NUMBER_OF_DESKTOPS - * (if set) in meta_x11_display_new () */ - num = 1; - else - num = meta_prefs_get_num_workspaces (); - - meta_workspace_manager_update_num_workspaces (workspace_manager, META_CURRENT_TIME, num); - - meta_workspace_activate (workspace_manager->workspaces->data, META_CURRENT_TIME); - - meta_workspace_manager_reload_work_areas (workspace_manager); -} - -int -meta_workspace_manager_get_n_workspaces (MetaWorkspaceManager *workspace_manager) -{ - return g_list_length (workspace_manager->workspaces); -} - -/** - * meta_workspace_manager_get_workspace_by_index: - * @workspace_manager: a #MetaWorkspaceManager - * @index: index of one of the display's workspaces - * - * Gets the workspace object for one of a workspace manager's workspaces given the workspace - * index. It's valid to call this function with an out-of-range index and it - * will robustly return %NULL. - * - * Return value: (transfer none) (nullable): the workspace object with specified - * index, or %NULL if the index is out of range. - */ -MetaWorkspace * -meta_workspace_manager_get_workspace_by_index (MetaWorkspaceManager *workspace_manager, - int idx) -{ - return g_list_nth_data (workspace_manager->workspaces, idx); -} - -void -meta_workspace_manager_remove_workspace (MetaWorkspaceManager *workspace_manager, - MetaWorkspace *workspace, - guint32 timestamp) -{ - GList *l; - GList *next; - MetaWorkspace *neighbour = NULL; - int index; - int active_index; - gboolean active_index_changed; - int new_num; - - l = g_list_find (workspace_manager->workspaces, workspace); - if (!l) - return; - - next = l->next; - - if (l->prev) - neighbour = l->prev->data; - else if (l->next) - neighbour = l->next->data; - else - { - /* Cannot remove the only workspace! */ - return; - } - - meta_workspace_relocate_windows (workspace, neighbour); - - if (workspace == workspace_manager->active_workspace) - meta_workspace_activate (neighbour, timestamp); - - /* To emit the signal after removing the workspace */ - index = meta_workspace_index (workspace); - active_index = meta_workspace_manager_get_active_workspace_index (workspace_manager); - active_index_changed = index < active_index; - - /* This also removes the workspace from the displays list */ - meta_workspace_remove (workspace); - - new_num = g_list_length (workspace_manager->workspaces); - - if (!meta_prefs_get_dynamic_workspaces ()) - meta_prefs_set_num_workspaces (new_num); - - /* If deleting a workspace before the current workspace, the active - * workspace index changes, so we need to update that hint */ - if (active_index_changed) - g_signal_emit (workspace_manager, - workspace_manager_signals[ACTIVE_WORKSPACE_CHANGED], - 0, NULL); - - for (l = next; l; l = l->next) - { - MetaWorkspace *w = l->data; - meta_workspace_index_changed (w); - } - - meta_display_queue_workarea_recalc (workspace_manager->display); - - g_signal_emit (workspace_manager, - workspace_manager_signals[WORKSPACE_REMOVED], - 0, index); - g_object_notify (G_OBJECT (workspace_manager), "n-workspaces"); -} - -/** - * meta_workspace_manager_append_new_workspace: - * @workspace_manager: a #MetaWorkspaceManager - * @activate: %TRUE if the workspace should be switched to after creation - * @timestamp: if switching to a new workspace, timestamp to be used when - * focusing a window on the new workspace. (Doesn't hurt to pass a valid - * timestamp when available even if not switching workspaces.) - * - * Append a new workspace to the workspace manager and (optionally) switch to that - * display. - * - * Return value: (transfer none): the newly appended workspace. - */ -MetaWorkspace * -meta_workspace_manager_append_new_workspace (MetaWorkspaceManager *workspace_manager, - gboolean activate, - guint32 timestamp) -{ - MetaWorkspace *w; - int new_num; - - /* This also adds the workspace to the workspace manager list */ - w = meta_workspace_new (workspace_manager); - - if (!w) - return NULL; - - if (activate) - meta_workspace_activate (w, timestamp); - - new_num = g_list_length (workspace_manager->workspaces); - - if (!meta_prefs_get_dynamic_workspaces ()) - meta_prefs_set_num_workspaces (new_num); - - meta_display_queue_workarea_recalc (workspace_manager->display); - - g_signal_emit (workspace_manager, workspace_manager_signals[WORKSPACE_ADDED], - 0, meta_workspace_index (w)); - g_object_notify (G_OBJECT (workspace_manager), "n-workspaces"); - - return w; -} - -void -meta_workspace_manager_update_num_workspaces (MetaWorkspaceManager *workspace_manager, - guint32 timestamp, - int new_num) -{ - int old_num; - GList *l; - int i = 0; - GList *extras = NULL; - MetaWorkspace *last_remaining = NULL; - gboolean need_change_space = FALSE; - - g_assert (new_num > 0); - - if (g_list_length (workspace_manager->workspaces) == (guint) new_num) - return; - - for (l = workspace_manager->workspaces; l; l = l->next) - { - MetaWorkspace *w = l->data; - - if (i >= new_num) - extras = g_list_prepend (extras, w); - else - last_remaining = w; - - ++i; - } - old_num = i; - - g_assert (last_remaining); - - /* Get rid of the extra workspaces by moving all their windows - * to last_remaining, then activating last_remaining if - * one of the removed workspaces was active. This will be a bit - * wacky if the config tool for changing number of workspaces - * is on a removed workspace ;-) - */ - for (l = extras; l; l = l->next) - { - MetaWorkspace *w = l->data; - - meta_workspace_relocate_windows (w, last_remaining); - - if (w == workspace_manager->active_workspace) - need_change_space = TRUE; - } - - if (need_change_space) - meta_workspace_activate (last_remaining, timestamp); - - /* Should now be safe to free the workspaces */ - for (l = extras; l; l = l->next) - { - MetaWorkspace *w = l->data; - - meta_workspace_remove (w); - } - - g_list_free (extras); - - for (i = old_num; i < new_num; i++) - meta_workspace_new (workspace_manager); - - meta_display_queue_workarea_recalc (workspace_manager->display); - - for (i = old_num; i < new_num; i++) - g_signal_emit (workspace_manager, - workspace_manager_signals[WORKSPACE_ADDED], - 0, i); - - g_object_notify (G_OBJECT (workspace_manager), "n-workspaces"); -} - -/** - * meta_workspace_manager_reorder_workspace: - * @workspace_manager: a #MetaWorkspaceManager - * @workspace: a #MetaWorkspace to reorder - * @new_index: the new index of the passed workspace - * - * Reorder a workspace to a new index. If the workspace is currently active - * the "active-workspace-changed" signal will be emitted. - * If the workspace's index is the same as @new_index or the workspace - * will not be found in the list, this function will return. - * - * Calling this function will also emit the "workspaces-reordered" signal. - */ -void -meta_workspace_manager_reorder_workspace (MetaWorkspaceManager *workspace_manager, - MetaWorkspace *workspace, - int new_index) -{ - GList *l; - GList *from, *to; - int index; - int active_index, new_active_index; - - g_return_if_fail (META_IS_WORKSPACE_MANAGER (workspace_manager)); - g_return_if_fail (new_index >= 0 && - new_index < g_list_length (workspace_manager->workspaces)); - - l = g_list_find (workspace_manager->workspaces, workspace); - g_return_if_fail (l); - - index = meta_workspace_index (workspace); - - if (new_index == index) - return; - - active_index = - meta_workspace_manager_get_active_workspace_index (workspace_manager); - - workspace_manager->workspaces = - g_list_remove_link (workspace_manager->workspaces, l); - - workspace_manager->workspaces = - g_list_insert (workspace_manager->workspaces, l->data, new_index); - - g_list_free (l); - - new_active_index = - meta_workspace_manager_get_active_workspace_index (workspace_manager); - - if (active_index != new_active_index) - g_signal_emit (workspace_manager, - workspace_manager_signals[ACTIVE_WORKSPACE_CHANGED], - 0, NULL); - - from = g_list_nth (workspace_manager->workspaces, MIN (new_index, index)); - to = g_list_nth (workspace_manager->workspaces, MAX (new_index, index)); - for (l = from; l != to->next; l = l->next) - { - MetaWorkspace *w = l->data; - - meta_workspace_index_changed (w); - } - - meta_display_queue_workarea_recalc (workspace_manager->display); - g_signal_emit (workspace_manager, - workspace_manager_signals[WORKSPACES_REORDERED], 0, NULL); -} - -void -meta_workspace_manager_update_workspace_layout (MetaWorkspaceManager *workspace_manager, - MetaDisplayCorner starting_corner, - gboolean vertical_layout, - int n_rows, - int n_columns) -{ - g_return_if_fail (META_IS_WORKSPACE_MANAGER (workspace_manager)); - g_return_if_fail (n_rows > 0 || n_columns > 0); - g_return_if_fail (n_rows != 0 && n_columns != 0); - - if (workspace_manager->workspace_layout_overridden) - return; - - workspace_manager->vertical_workspaces = vertical_layout != FALSE; - workspace_manager->starting_corner = starting_corner; - workspace_manager->rows_of_workspaces = n_rows; - workspace_manager->columns_of_workspaces = n_columns; - - meta_verbose ("Workspace layout rows = %d cols = %d orientation = %d starting corner = %u", - workspace_manager->rows_of_workspaces, - workspace_manager->columns_of_workspaces, - workspace_manager->vertical_workspaces, - workspace_manager->starting_corner); - g_object_notify (G_OBJECT (workspace_manager), "layout-columns"); - g_object_notify (G_OBJECT (workspace_manager), "layout-rows"); -} - -/** - * meta_workspace_manager_override_workspace_layout: - * @workspace_manager: a #MetaWorkspaceManager - * @starting_corner: the corner at which the first workspace is found - * @vertical_layout: if %TRUE the workspaces are laid out in columns rather than rows - * @n_rows: number of rows of workspaces, or -1 to determine the number of rows from - * @n_columns and the total number of workspaces - * @n_columns: number of columns of workspaces, or -1 to determine the number of columns from - * @n_rows and the total number of workspaces - * - * Explicitly set the layout of workspaces. Once this has been called, the contents of the - * _NET_DESKTOP_LAYOUT property on the root window are completely ignored. - */ -void -meta_workspace_manager_override_workspace_layout (MetaWorkspaceManager *workspace_manager, - MetaDisplayCorner starting_corner, - gboolean vertical_layout, - int n_rows, - int n_columns) -{ - workspace_manager->workspace_layout_overridden = FALSE; - - meta_workspace_manager_update_workspace_layout (workspace_manager, - starting_corner, - vertical_layout, - n_rows, - n_columns); - - workspace_manager->workspace_layout_overridden = TRUE; -} - -#ifdef WITH_VERBOSE_MODE -static const char * -meta_workspace_manager_corner_to_string (MetaDisplayCorner corner) -{ - switch (corner) - { - case META_DISPLAY_TOPLEFT: - return "TopLeft"; - case META_DISPLAY_TOPRIGHT: - return "TopRight"; - case META_DISPLAY_BOTTOMLEFT: - return "BottomLeft"; - case META_DISPLAY_BOTTOMRIGHT: - return "BottomRight"; - } - - return "Unknown"; -} -#endif /* WITH_VERBOSE_MODE */ - -void -meta_workspace_manager_calc_workspace_layout (MetaWorkspaceManager *workspace_manager, - int num_workspaces, - int current_space, - MetaWorkspaceLayout *layout) -{ - int rows, cols; - int grid_area; - int *grid; - int i, r, c; - int current_row, current_col; - - rows = workspace_manager->rows_of_workspaces; - cols = workspace_manager->columns_of_workspaces; - if (rows <= 0 && cols <= 0) - cols = num_workspaces; - - if (rows <= 0) - rows = num_workspaces / cols + ((num_workspaces % cols) > 0 ? 1 : 0); - if (cols <= 0) - cols = num_workspaces / rows + ((num_workspaces % rows) > 0 ? 1 : 0); - - /* paranoia */ - if (rows < 1) - rows = 1; - if (cols < 1) - cols = 1; - - g_assert (rows != 0 && cols != 0); - - grid_area = rows * cols; - - meta_verbose ("Getting layout rows = %d cols = %d current = %d " - "num_spaces = %d vertical = %s corner = %s", - rows, cols, current_space, num_workspaces, - workspace_manager->vertical_workspaces ? "(true)" : "(false)", - meta_workspace_manager_corner_to_string (workspace_manager->starting_corner)); - - /* ok, we want to setup the distances in the workspace array to go - * in each direction. Remember, there are many ways that a workspace - * array can be setup. - * see http://www.freedesktop.org/standards/wm-spec/1.2/html/x109.html - * and look at the _NET_DESKTOP_LAYOUT section for details. - * For instance: - */ - /* starting_corner = META_DISPLAY_TOPLEFT - * vertical_workspaces = 0 vertical_workspaces=1 - * 1234 1357 - * 5678 2468 - * - * starting_corner = META_DISPLAY_TOPRIGHT - * vertical_workspaces = 0 vertical_workspaces=1 - * 4321 7531 - * 8765 8642 - * - * starting_corner = META_DISPLAY_BOTTOMLEFT - * vertical_workspaces = 0 vertical_workspaces=1 - * 5678 2468 - * 1234 1357 - * - * starting_corner = META_DISPLAY_BOTTOMRIGHT - * vertical_workspaces = 0 vertical_workspaces=1 - * 8765 8642 - * 4321 7531 - * - */ - /* keep in mind that we could have a ragged layout, e.g. the "8" - * in the above grids could be missing - */ - - - grid = g_new (int, grid_area); - - i = 0; - - switch (workspace_manager->starting_corner) - { - case META_DISPLAY_TOPLEFT: - if (workspace_manager->vertical_workspaces) - { - c = 0; - while (c < cols) - { - r = 0; - while (r < rows) - { - grid[r*cols+c] = i; - ++i; - ++r; - } - ++c; - } - } - else - { - r = 0; - while (r < rows) - { - c = 0; - while (c < cols) - { - grid[r*cols+c] = i; - ++i; - ++c; - } - ++r; - } - } - break; - case META_DISPLAY_TOPRIGHT: - if (workspace_manager->vertical_workspaces) - { - c = cols - 1; - while (c >= 0) - { - r = 0; - while (r < rows) - { - grid[r*cols+c] = i; - ++i; - ++r; - } - --c; - } - } - else - { - r = 0; - while (r < rows) - { - c = cols - 1; - while (c >= 0) - { - grid[r*cols+c] = i; - ++i; - --c; - } - ++r; - } - } - break; - case META_DISPLAY_BOTTOMLEFT: - if (workspace_manager->vertical_workspaces) - { - c = 0; - while (c < cols) - { - r = rows - 1; - while (r >= 0) - { - grid[r*cols+c] = i; - ++i; - --r; - } - ++c; - } - } - else - { - r = rows - 1; - while (r >= 0) - { - c = 0; - while (c < cols) - { - grid[r*cols+c] = i; - ++i; - ++c; - } - --r; - } - } - break; - case META_DISPLAY_BOTTOMRIGHT: - if (workspace_manager->vertical_workspaces) - { - c = cols - 1; - while (c >= 0) - { - r = rows - 1; - while (r >= 0) - { - grid[r*cols+c] = i; - ++i; - --r; - } - --c; - } - } - else - { - r = rows - 1; - while (r >= 0) - { - c = cols - 1; - while (c >= 0) - { - grid[r*cols+c] = i; - ++i; - --c; - } - --r; - } - } - break; - } - - if (i != grid_area) - meta_bug ("did not fill in the whole workspace grid in %s (%d filled)", - G_STRFUNC, i); - - current_row = 0; - current_col = 0; - r = 0; - while (r < rows) - { - c = 0; - while (c < cols) - { - if (grid[r*cols+c] == current_space) - { - current_row = r; - current_col = c; - } - else if (grid[r*cols+c] >= num_workspaces) - { - /* flag nonexistent spaces with -1 */ - grid[r*cols+c] = -1; - } - ++c; - } - ++r; - } - - layout->rows = rows; - layout->cols = cols; - layout->grid = grid; - layout->grid_area = grid_area; - layout->current_row = current_row; - layout->current_col = current_col; - -#ifdef WITH_VERBOSE_MODE - if (meta_is_verbose ()) - { - r = 0; - while (r < layout->rows) - { - meta_verbose (" "); - meta_push_no_msg_prefix (); - c = 0; - while (c < layout->cols) - { - if (r == layout->current_row && - c == layout->current_col) - meta_verbose ("*%2d ", layout->grid[r*layout->cols+c]); - else - meta_verbose ("%3d ", layout->grid[r*layout->cols+c]); - ++c; - } - meta_pop_no_msg_prefix (); - ++r; - } - } -#endif /* WITH_VERBOSE_MODE */ -} - -void -meta_workspace_manager_free_workspace_layout (MetaWorkspaceLayout *layout) -{ - g_free (layout->grid); -} - -static void -queue_windows_showing (MetaWorkspaceManager *workspace_manager) -{ - GSList *windows, *l; - - /* Must operate on all windows on display instead of just on the - * active_workspace's window list, because the active_workspace's - * window list may not contain the on_all_workspace windows. - */ - windows = meta_display_list_windows (workspace_manager->display, META_LIST_DEFAULT); - - for (l = windows; l; l = l->next) - { - MetaWindow *w = l->data; - - meta_window_queue (w, META_QUEUE_CALC_SHOWING); - } - - g_slist_free (windows); -} - -void -meta_workspace_manager_minimize_all_on_active_workspace_except (MetaWorkspaceManager *workspace_manager, - MetaWindow *keep) -{ - GList *l; - - for (l = workspace_manager->active_workspace->windows; l; l = l->next) - { - MetaWindow *w = l->data; - - if (w->has_minimize_func && w != keep) - meta_window_minimize (w); - } -} - -void -meta_workspace_manager_show_desktop (MetaWorkspaceManager *workspace_manager, - guint32 timestamp) -{ - GList *l; - - if (workspace_manager->active_workspace->showing_desktop) - return; - - workspace_manager->active_workspace->showing_desktop = TRUE; - - queue_windows_showing (workspace_manager); - - /* Focus the most recently used META_WINDOW_DESKTOP window, if there is one; - * see bug 159257. - */ - for (l = workspace_manager->active_workspace->mru_list; l; l = l->next) - { - MetaWindow *w = l->data; - - if (w->type == META_WINDOW_DESKTOP) - { - meta_window_focus (w, timestamp); - break; - } - } - - g_signal_emit (workspace_manager, - workspace_manager_signals[SHOWING_DESKTOP_CHANGED], - 0, NULL); -} - -void -meta_workspace_manager_unshow_desktop (MetaWorkspaceManager *workspace_manager) -{ - if (!workspace_manager->active_workspace->showing_desktop) - return; - - workspace_manager->active_workspace->showing_desktop = FALSE; - - queue_windows_showing (workspace_manager); - - g_signal_emit (workspace_manager, - workspace_manager_signals[SHOWING_DESKTOP_CHANGED], - 0, NULL); -} - -/** - * meta_workspace_manager_get_workspaces: (skip) - * @workspace_manager: a #MetaWorkspaceManager - * - * Returns: (transfer none) (element-type Meta.Workspace): The workspaces for @display - */ -GList * -meta_workspace_manager_get_workspaces (MetaWorkspaceManager *workspace_manager) -{ - return workspace_manager->workspaces; -} - -int -meta_workspace_manager_get_active_workspace_index (MetaWorkspaceManager *workspace_manager) -{ - MetaWorkspace *active = workspace_manager->active_workspace; - - if (!active) - return -1; - - return meta_workspace_index (active); -} - -/** - * meta_workspace_manager_get_active_workspace: - * @workspace_manager: A #MetaWorkspaceManager - * - * Returns: (transfer none): The current workspace - */ -MetaWorkspace * -meta_workspace_manager_get_active_workspace (MetaWorkspaceManager *workspace_manager) -{ - return workspace_manager->active_workspace; -} - -void -meta_workspace_manager_workspace_switched (MetaWorkspaceManager *workspace_manager, - int from, - int to, - MetaMotionDirection direction) -{ - g_signal_emit (workspace_manager, - workspace_manager_signals[WORKSPACE_SWITCHED], 0, - from, to, direction); -} - -static void -prefs_changed_callback (MetaPreference pref, - gpointer data) -{ - MetaWorkspaceManager *workspace_manager = data; - - if ((pref == META_PREF_NUM_WORKSPACES || - pref == META_PREF_DYNAMIC_WORKSPACES) && - !meta_prefs_get_dynamic_workspaces ()) - { - guint32 timestamp; - int new_num; - - timestamp = - meta_display_get_current_time_roundtrip (workspace_manager->display); - new_num = meta_prefs_get_num_workspaces (); - meta_workspace_manager_update_num_workspaces (workspace_manager, - timestamp, new_num); - } -} diff --git a/src/core/mutter.c b/src/core/mutter.c deleted file mode 100644 index 9d716014a..000000000 --- a/src/core/mutter.c +++ /dev/null @@ -1,97 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright 2011 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 . - */ - -#include "config.h" - -#include -#include -#include - -#include "compositor/meta-plugin-manager.h" -#include "meta/main.h" -#include "meta/meta-context.h" -#include "meta/util.h" - -static gboolean -print_version (const gchar *option_name, - const gchar *value, - gpointer data, - GError **error) -{ - g_print ("mutter %s\n", VERSION); - exit (0); -} - -static const char *plugin = "libdefault"; - -GOptionEntry mutter_options[] = { - { - "version", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, - print_version, - N_("Print version"), - NULL - }, - { - "mutter-plugin", 0, 0, G_OPTION_ARG_STRING, - &plugin, - N_("Mutter plugin to use"), - "PLUGIN", - }, - { NULL } -}; - -int -main (int argc, char **argv) -{ - g_autoptr (MetaContext) context = NULL; - g_autoptr (GError) error = NULL; - - context = meta_create_context ("Mutter"); - - meta_context_add_option_entries (context, mutter_options, GETTEXT_PACKAGE); - if (!meta_context_configure (context, &argc, &argv, &error)) - { - g_printerr ("Failed to configure: %s", error->message); - return EXIT_FAILURE; - } - - meta_context_set_plugin_name (context, plugin); - - if (!meta_context_setup (context, &error)) - { - g_printerr ("Failed to setup: %s", error->message); - return EXIT_FAILURE; - } - - if (!meta_context_start (context, &error)) - { - g_printerr ("Failed to start: %s", error->message); - return EXIT_FAILURE; - } - - meta_context_notify_ready (context); - - if (!meta_context_run_main_loop (context, &error)) - { - g_printerr ("Mutter terminated with a failure: %s", error->message); - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} diff --git a/src/core/place.c b/src/core/place.c deleted file mode 100644 index 1075fe20d..000000000 --- a/src/core/place.c +++ /dev/null @@ -1,942 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter window placement */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002, 2003 Red Hat, Inc. - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2005 Elijah Newren - * - * 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 . - */ - -#include "config.h" - -#include "core/place.h" - -#include -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-logical-monitor.h" -#include "core/boxes-private.h" -#include "meta/meta-backend.h" -#include "meta/prefs.h" -#include "meta/workspace.h" - -typedef enum -{ - META_LEFT, - META_RIGHT, - META_TOP, - META_BOTTOM -} MetaWindowDirection; - -static gint -northwestcmp (gconstpointer a, gconstpointer b) -{ - MetaWindow *aw = (gpointer) a; - MetaWindow *bw = (gpointer) b; - MetaRectangle a_frame; - MetaRectangle b_frame; - int from_origin_a; - int from_origin_b; - int ax, ay, bx, by; - - meta_window_get_frame_rect (aw, &a_frame); - meta_window_get_frame_rect (bw, &b_frame); - ax = a_frame.x; - ay = a_frame.y; - bx = b_frame.x; - by = b_frame.y; - - /* probably there's a fast good-enough-guess we could use here. */ - from_origin_a = sqrt (ax * ax + ay * ay); - from_origin_b = sqrt (bx * bx + by * by); - - if (from_origin_a < from_origin_b) - return -1; - else if (from_origin_a > from_origin_b) - return 1; - else - return 0; -} - -static void -find_next_cascade (MetaWindow *window, - /* visible windows on relevant workspaces */ - GList *windows, - int x, - int y, - int *new_x, - int *new_y) -{ - MetaBackend *backend = meta_get_backend (); - GList *tmp; - GList *sorted; - int cascade_x, cascade_y; - MetaRectangle titlebar_rect; - int x_threshold, y_threshold; - MetaRectangle frame_rect; - int window_width, window_height; - int cascade_stage; - MetaRectangle work_area; - MetaLogicalMonitor *current; - - sorted = g_list_copy (windows); - sorted = g_list_sort (sorted, northwestcmp); - - /* This is a "fuzzy" cascade algorithm. - * For each window in the list, we find where we'd cascade a - * new window after it. If a window is already nearly at that - * position, we move on. - */ - - /* arbitrary-ish threshold, honors user attempts to - * manually cascade. - */ -#define CASCADE_FUZZ 15 - meta_window_get_titlebar_rect (window, &titlebar_rect); - x_threshold = MAX (titlebar_rect.x, CASCADE_FUZZ); - y_threshold = MAX (titlebar_rect.y, CASCADE_FUZZ); - - /* Find furthest-SE origin of all workspaces. - * cascade_x, cascade_y are the target position - * of NW corner of window frame. - */ - - current = meta_backend_get_current_logical_monitor (backend); - meta_window_get_work_area_for_logical_monitor (window, current, &work_area); - - cascade_x = MAX (0, work_area.x); - cascade_y = MAX (0, work_area.y); - - /* Find first cascade position that's not used. */ - - meta_window_get_frame_rect (window, &frame_rect); - window_width = frame_rect.width; - window_height = frame_rect.height; - - cascade_stage = 0; - tmp = sorted; - while (tmp != NULL) - { - MetaWindow *w; - MetaRectangle w_frame_rect; - int wx, wy; - - w = tmp->data; - - /* we want frame position, not window position */ - meta_window_get_frame_rect (w, &w_frame_rect); - wx = w_frame_rect.x; - wy = w_frame_rect.y; - - if (ABS (wx - cascade_x) < x_threshold && - ABS (wy - cascade_y) < y_threshold) - { - meta_window_get_titlebar_rect (w, &titlebar_rect); - - /* Cascade the window evenly by the titlebar height; this isn't a typo. */ - cascade_x = wx + titlebar_rect.height; - cascade_y = wy + titlebar_rect.height; - - /* If we go off the screen, start over with a new cascade */ - if (((cascade_x + window_width) > - (work_area.x + work_area.width)) || - ((cascade_y + window_height) > - (work_area.y + work_area.height))) - { - cascade_x = MAX (0, work_area.x); - cascade_y = MAX (0, work_area.y); - -#define CASCADE_INTERVAL 50 /* space between top-left corners of cascades */ - cascade_stage += 1; - cascade_x += CASCADE_INTERVAL * cascade_stage; - - /* start over with a new cascade translated to the right, unless - * we are out of space - */ - if ((cascade_x + window_width) < - (work_area.x + work_area.width)) - { - tmp = sorted; - continue; - } - else - { - /* All out of space, this cascade_x won't work */ - cascade_x = MAX (0, work_area.x); - break; - } - } - } - else - { - /* Keep searching for a further-down-the-diagonal window. */ - } - - tmp = tmp->next; - } - - /* cascade_x and cascade_y will match the last window in the list - * that was "in the way" (in the approximate cascade diagonal) - */ - - g_list_free (sorted); - - *new_x = cascade_x; - *new_y = cascade_y; -} - -static void -find_most_freespace (MetaWindow *window, - /* visible windows on relevant workspaces */ - MetaWindow *focus_window, - int x, - int y, - int *new_x, - int *new_y) -{ - MetaWindowDirection side; - int max_area; - int max_width, max_height, left, right, top, bottom; - int left_space, right_space, top_space, bottom_space; - MetaRectangle work_area; - MetaRectangle avoid; - MetaRectangle frame_rect; - - meta_window_get_work_area_current_monitor (focus_window, &work_area); - meta_window_get_frame_rect (focus_window, &avoid); - meta_window_get_frame_rect (window, &frame_rect); - - /* Find the areas of choosing the various sides of the focus window */ - max_width = MIN (avoid.width, frame_rect.width); - max_height = MIN (avoid.height, frame_rect.height); - left_space = avoid.x - work_area.x; - right_space = work_area.width - (avoid.x + avoid.width - work_area.x); - top_space = avoid.y - work_area.y; - bottom_space = work_area.height - (avoid.y + avoid.height - work_area.y); - left = MIN (left_space, frame_rect.width); - right = MIN (right_space, frame_rect.width); - top = MIN (top_space, frame_rect.height); - bottom = MIN (bottom_space, frame_rect.height); - - /* Find out which side of the focus_window can show the most of the window */ - side = META_LEFT; - max_area = left*max_height; - if (right*max_height > max_area) - { - side = META_RIGHT; - max_area = right*max_height; - } - if (top*max_width > max_area) - { - side = META_TOP; - max_area = top*max_width; - } - if (bottom*max_width > max_area) - { - side = META_BOTTOM; - max_area = bottom*max_width; - } - - /* Give up if there's no where to put it (i.e. focus window is maximized) */ - if (max_area == 0) - return; - - /* Place the window on the relevant side; if the whole window fits, - * make it adjacent to the focus window; if not, make sure the - * window doesn't go off the edge of the screen. - */ - switch (side) - { - case META_LEFT: - *new_y = avoid.y; - if (left_space > frame_rect.width) - *new_x = avoid.x - frame_rect.width; - else - *new_x = work_area.x; - break; - case META_RIGHT: - *new_y = avoid.y; - if (right_space > frame_rect.width) - *new_x = avoid.x + avoid.width; - else - *new_x = work_area.x + work_area.width - frame_rect.width; - break; - case META_TOP: - *new_x = avoid.x; - if (top_space > frame_rect.height) - *new_y = avoid.y - frame_rect.height; - else - *new_y = work_area.y; - break; - case META_BOTTOM: - *new_x = avoid.x; - if (bottom_space > frame_rect.height) - *new_y = avoid.y + avoid.height; - else - *new_y = work_area.y + work_area.height - frame_rect.height; - break; - } -} - -static gboolean -window_overlaps_focus_window (MetaWindow *window) -{ - MetaWindow *focus_window; - MetaRectangle window_frame, focus_frame, overlap; - - focus_window = window->display->focus_window; - if (focus_window == NULL) - return FALSE; - - meta_window_get_frame_rect (window, &window_frame); - meta_window_get_frame_rect (focus_window, &focus_frame); - - return meta_rectangle_intersect (&window_frame, - &focus_frame, - &overlap); -} - -static gboolean -window_place_centered (MetaWindow *window) -{ - MetaWindowType type; - - type = window->type; - - return (type == META_WINDOW_DIALOG || - type == META_WINDOW_MODAL_DIALOG || - type == META_WINDOW_SPLASHSCREEN || - (type == META_WINDOW_NORMAL && meta_prefs_get_center_new_windows ())); -} - -static void -avoid_being_obscured_as_second_modal_dialog (MetaWindow *window, - int *x, - int *y) -{ - /* We can't center this dialog if it was denied focus and it - * overlaps with the focus window and this dialog is modal and this - * dialog is in the same app as the focus window (*phew*...please - * don't make me say that ten times fast). See bug 307875 comment 11 - * and 12 for details, but basically it means this is probably a - * second modal dialog for some app while the focus window is the - * first modal dialog. We should probably make them simultaneously - * visible in general, but it becomes mandatory to do so due to - * buggy apps (e.g. those using gtk+ *sigh*) because in those cases - * this second modal dialog also happens to be modal to the first - * dialog in addition to the main window, while it has only let us - * know about the modal-to-the-main-window part. - */ - - MetaWindow *focus_window; - - focus_window = window->display->focus_window; - - /* denied_focus_and_not_transient is only set when focus_window != NULL */ - - if (window->denied_focus_and_not_transient && - window->type == META_WINDOW_MODAL_DIALOG && - meta_window_same_application (window, focus_window) && - window_overlaps_focus_window (window)) - { - find_most_freespace (window, focus_window, *x, *y, x, y); - meta_topic (META_DEBUG_PLACEMENT, - "Dialog window %s was denied focus but may be modal " - "to the focus window; had to move it to avoid the " - "focus window", - window->desc); - } -} - -static gboolean -rectangle_overlaps_some_window (MetaRectangle *rect, - GList *windows) -{ - GList *tmp; - MetaRectangle dest; - - tmp = windows; - while (tmp != NULL) - { - MetaWindow *other = tmp->data; - MetaRectangle other_rect; - - switch (other->type) - { - case META_WINDOW_DOCK: - case META_WINDOW_SPLASHSCREEN: - case META_WINDOW_DESKTOP: - case META_WINDOW_DIALOG: - case META_WINDOW_MODAL_DIALOG: - /* override redirect window types: */ - case META_WINDOW_DROPDOWN_MENU: - case META_WINDOW_POPUP_MENU: - case META_WINDOW_TOOLTIP: - case META_WINDOW_NOTIFICATION: - case META_WINDOW_COMBO: - case META_WINDOW_DND: - case META_WINDOW_OVERRIDE_OTHER: - break; - - case META_WINDOW_NORMAL: - case META_WINDOW_UTILITY: - case META_WINDOW_TOOLBAR: - case META_WINDOW_MENU: - meta_window_get_frame_rect (other, &other_rect); - - if (meta_rectangle_intersect (rect, &other_rect, &dest)) - return TRUE; - break; - } - - tmp = tmp->next; - } - - return FALSE; -} - -static gint -leftmost_cmp (gconstpointer a, gconstpointer b) -{ - MetaWindow *aw = (gpointer) a; - MetaWindow *bw = (gpointer) b; - MetaRectangle a_frame; - MetaRectangle b_frame; - int ax, bx; - - meta_window_get_frame_rect (aw, &a_frame); - meta_window_get_frame_rect (bw, &b_frame); - ax = a_frame.x; - bx = b_frame.x; - - if (ax < bx) - return -1; - else if (ax > bx) - return 1; - else - return 0; -} - -static gint -topmost_cmp (gconstpointer a, gconstpointer b) -{ - MetaWindow *aw = (gpointer) a; - MetaWindow *bw = (gpointer) b; - MetaRectangle a_frame; - MetaRectangle b_frame; - int ay, by; - - meta_window_get_frame_rect (aw, &a_frame); - meta_window_get_frame_rect (bw, &b_frame); - ay = a_frame.y; - by = b_frame.y; - - if (ay < by) - return -1; - else if (ay > by) - return 1; - else - return 0; -} - -static void -center_tile_rect_in_area (MetaRectangle *rect, - MetaRectangle *work_area) -{ - int fluff; - - /* The point here is to tile a window such that "extra" - * space is equal on either side (i.e. so a full screen - * of windows tiled this way would center the windows - * as a group) - */ - - fluff = (work_area->width % (rect->width+1)) / 2; - rect->x = work_area->x + fluff; - fluff = (work_area->height % (rect->height+1)) / 3; - rect->y = work_area->y + fluff; -} - -/* Find the leftmost, then topmost, empty area on the workspace - * that can contain the new window. - * - * Cool feature to have: if we can't fit the current window size, - * try shrinking the window (within geometry constraints). But - * beware windows such as Emacs with no sane minimum size, we - * don't want to create a 1x1 Emacs. - */ -static gboolean -find_first_fit (MetaWindow *window, - /* visible windows on relevant workspaces */ - GList *windows, - MetaLogicalMonitor *logical_monitor, - int x, - int y, - int *new_x, - int *new_y) -{ - /* This algorithm is limited - it just brute-force tries - * to fit the window in a small number of locations that are aligned - * with existing windows. It tries to place the window on - * the bottom of each existing window, and then to the right - * of each existing window, aligned with the left/top of the - * existing window in each of those cases. - */ - int retval; - GList *below_sorted; - GList *right_sorted; - GList *tmp; - MetaRectangle rect; - MetaRectangle work_area; - - retval = FALSE; - - /* Below each window */ - below_sorted = g_list_copy (windows); - below_sorted = g_list_sort (below_sorted, leftmost_cmp); - below_sorted = g_list_sort (below_sorted, topmost_cmp); - - /* To the right of each window */ - right_sorted = g_list_copy (windows); - right_sorted = g_list_sort (right_sorted, topmost_cmp); - right_sorted = g_list_sort (right_sorted, leftmost_cmp); - - meta_window_get_frame_rect (window, &rect); - -#ifdef WITH_VERBOSE_MODE - { - char monitor_location_string[RECT_LENGTH]; - - meta_rectangle_to_string (&logical_monitor->rect, - monitor_location_string); - meta_topic (META_DEBUG_PLACEMENT, - "Natural monitor is %s", - monitor_location_string); - } -#endif - - meta_window_get_work_area_for_logical_monitor (window, - logical_monitor, - &work_area); - - center_tile_rect_in_area (&rect, &work_area); - - if (meta_rectangle_contains_rect (&work_area, &rect) && - !rectangle_overlaps_some_window (&rect, windows)) - { - *new_x = rect.x; - *new_y = rect.y; - - retval = TRUE; - - goto out; - } - - /* try below each window */ - tmp = below_sorted; - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - MetaRectangle frame_rect; - - meta_window_get_frame_rect (w, &frame_rect); - - rect.x = frame_rect.x; - rect.y = frame_rect.y + frame_rect.height; - - if (meta_rectangle_contains_rect (&work_area, &rect) && - !rectangle_overlaps_some_window (&rect, below_sorted)) - { - *new_x = rect.x; - *new_y = rect.y; - - retval = TRUE; - - goto out; - } - - tmp = tmp->next; - } - - /* try to the right of each window */ - tmp = right_sorted; - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - MetaRectangle frame_rect; - - meta_window_get_frame_rect (w, &frame_rect); - - rect.x = frame_rect.x + frame_rect.width; - rect.y = frame_rect.y; - - if (meta_rectangle_contains_rect (&work_area, &rect) && - !rectangle_overlaps_some_window (&rect, right_sorted)) - { - *new_x = rect.x; - *new_y = rect.y; - - retval = TRUE; - - goto out; - } - - tmp = tmp->next; - } - - out: - g_list_free (below_sorted); - g_list_free (right_sorted); - return retval; -} - -void -meta_window_process_placement (MetaWindow *window, - MetaPlacementRule *placement_rule, - int *rel_x, - int *rel_y) -{ - MetaRectangle anchor_rect; - int window_width, window_height; - int x, y; - - window_width = placement_rule->width; - window_height = placement_rule->height; - - anchor_rect = placement_rule->anchor_rect; - - /* Place at anchor point. */ - if (placement_rule->anchor & META_PLACEMENT_ANCHOR_LEFT) - x = anchor_rect.x; - else if (placement_rule->anchor & META_PLACEMENT_ANCHOR_RIGHT) - x = anchor_rect.x + anchor_rect.width; - else - x = anchor_rect.x + (anchor_rect.width / 2); - if (placement_rule->anchor & META_PLACEMENT_ANCHOR_TOP) - y = anchor_rect.y; - else if (placement_rule->anchor & META_PLACEMENT_ANCHOR_BOTTOM) - y = anchor_rect.y + anchor_rect.height; - else - y = anchor_rect.y + (anchor_rect.height / 2); - - /* Shift according to gravity. */ - if (placement_rule->gravity & META_PLACEMENT_GRAVITY_LEFT) - x -= window_width; - else if (placement_rule->gravity & META_PLACEMENT_GRAVITY_RIGHT) - x = x; - else - x -= window_width / 2; - if (placement_rule->gravity & META_PLACEMENT_GRAVITY_TOP) - y -= window_height; - else if (placement_rule->gravity & META_PLACEMENT_GRAVITY_BOTTOM) - y = y; - else - y -= window_height / 2; - - /* Offset according to offset. */ - x += placement_rule->offset_x; - y += placement_rule->offset_y; - - *rel_x = x; - *rel_y = y; -} - -void -meta_window_place (MetaWindow *window, - int x, - int y, - int *new_x, - int *new_y) -{ - MetaBackend *backend = meta_get_backend (); - GList *windows = NULL; - MetaLogicalMonitor *logical_monitor; - - meta_topic (META_DEBUG_PLACEMENT, "Placing window %s", window->desc); - - g_return_if_fail (!window->placement.rule); - - switch (window->type) - { - /* Run placement algorithm on these. */ - case META_WINDOW_NORMAL: - case META_WINDOW_DIALOG: - case META_WINDOW_MODAL_DIALOG: - case META_WINDOW_SPLASHSCREEN: - break; - - /* Assume the app knows best how to place these, no placement - * algorithm ever (other than "leave them as-is") - */ - case META_WINDOW_DESKTOP: - case META_WINDOW_DOCK: - case META_WINDOW_TOOLBAR: - case META_WINDOW_MENU: - case META_WINDOW_UTILITY: - /* override redirect window types: */ - case META_WINDOW_DROPDOWN_MENU: - case META_WINDOW_POPUP_MENU: - case META_WINDOW_TOOLTIP: - case META_WINDOW_NOTIFICATION: - case META_WINDOW_COMBO: - case META_WINDOW_DND: - case META_WINDOW_OVERRIDE_OTHER: - goto done; - } - - if (meta_prefs_get_disable_workarounds ()) - { - switch (window->type) - { - /* Only accept USPosition on normal windows because the app is full - * of shit claiming the user set -geometry for a dialog or dock - */ - case META_WINDOW_NORMAL: - if (window->size_hints.flags & USPosition) - { - /* don't constrain with placement algorithm */ - meta_topic (META_DEBUG_PLACEMENT, - "Honoring USPosition for %s instead of using placement algorithm", - window->desc); - - goto done; - } - break; - - /* Ignore even USPosition on dialogs, splashscreen */ - case META_WINDOW_DIALOG: - case META_WINDOW_MODAL_DIALOG: - case META_WINDOW_SPLASHSCREEN: - break; - - /* Assume the app knows best how to place these. */ - case META_WINDOW_DESKTOP: - case META_WINDOW_DOCK: - case META_WINDOW_TOOLBAR: - case META_WINDOW_MENU: - case META_WINDOW_UTILITY: - /* override redirect window types: */ - case META_WINDOW_DROPDOWN_MENU: - case META_WINDOW_POPUP_MENU: - case META_WINDOW_TOOLTIP: - case META_WINDOW_NOTIFICATION: - case META_WINDOW_COMBO: - case META_WINDOW_DND: - case META_WINDOW_OVERRIDE_OTHER: - if (window->size_hints.flags & PPosition) - { - meta_topic (META_DEBUG_PLACEMENT, - "Not placing non-normal non-dialog window with PPosition set"); - goto done; - } - break; - } - } - else - { - /* workarounds enabled */ - - if ((window->size_hints.flags & PPosition) || - (window->size_hints.flags & USPosition)) - { - meta_topic (META_DEBUG_PLACEMENT, - "Not placing window with PPosition or USPosition set"); - avoid_being_obscured_as_second_modal_dialog (window, &x, &y); - goto done; - } - } - - if (window->type == META_WINDOW_DIALOG || - window->type == META_WINDOW_MODAL_DIALOG) - { - MetaWindow *parent = meta_window_get_transient_for (window); - - if (parent) - { - MetaRectangle frame_rect, parent_frame_rect; - - meta_window_get_frame_rect (window, &frame_rect); - meta_window_get_frame_rect (parent, &parent_frame_rect); - - y = parent_frame_rect.y; - - /* center of parent */ - x = parent_frame_rect.x + parent_frame_rect.width / 2; - /* center of child over center of parent */ - x -= frame_rect.width / 2; - - /* "visually" center window over parent, leaving twice as - * much space below as on top. - */ - y += (parent_frame_rect.height - frame_rect.height)/3; - - meta_topic (META_DEBUG_PLACEMENT, - "Centered window %s over transient parent", - window->desc); - - avoid_being_obscured_as_second_modal_dialog (window, &x, &y); - - goto done; - } - } - - /* FIXME UTILITY with transient set should be stacked up - * on the sides of the parent window or something. - */ - - if (window_place_centered (window)) - { - /* Center on current monitor */ - MetaRectangle work_area; - MetaRectangle frame_rect; - - /* Warning, this function is a round trip! */ - logical_monitor = meta_backend_get_current_logical_monitor (backend); - - meta_window_get_work_area_for_logical_monitor (window, - logical_monitor, - &work_area); - meta_window_get_frame_rect (window, &frame_rect); - - x = work_area.x + (work_area.width - frame_rect.width) / 2; - y = work_area.y + (work_area.height - frame_rect.height) / 2; - - meta_topic (META_DEBUG_PLACEMENT, "Centered window %s on monitor %d", - window->desc, logical_monitor->number); - - goto done_check_denied_focus; - } - - /* Find windows that matter (not minimized, on same workspace - * as placed window, may be shaded - if shaded we pretend it isn't - * for placement purposes) - */ - { - GSList *all_windows; - GSList *tmp; - - all_windows = meta_display_list_windows (window->display, META_LIST_DEFAULT); - - tmp = all_windows; - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - - if (w != window && - meta_window_showing_on_its_workspace (w) && - (window->on_all_workspaces || - meta_window_located_on_workspace (w, window->workspace))) - windows = g_list_prepend (windows, w); - - tmp = tmp->next; - } - - g_slist_free (all_windows); - } - - /* Warning, on X11 this might be a round trip! */ - logical_monitor = meta_backend_get_current_logical_monitor (backend); - - /* Maximize windows if they are too big for their work area (bit of - * a hack here). Assume undecorated windows probably don't intend to - * be maximized. - */ - if (window->has_maximize_func && window->decorated && - !window->fullscreen) - { - MetaRectangle workarea; - MetaRectangle frame_rect; - - meta_window_get_work_area_for_logical_monitor (window, - logical_monitor, - &workarea); - meta_window_get_frame_rect (window, &frame_rect); - - /* If the window is bigger than the screen, then automaximize. Do NOT - * auto-maximize the directions independently. See #419810. - */ - if (frame_rect.width >= workarea.width && frame_rect.height >= workarea.height) - { - window->maximize_horizontally_after_placement = TRUE; - window->maximize_vertically_after_placement = TRUE; - } - } - - /* "Origin" placement algorithm */ - x = logical_monitor->rect.x; - y = logical_monitor->rect.y; - - if (find_first_fit (window, windows, - logical_monitor, - x, y, &x, &y)) - goto done_check_denied_focus; - - /* No good fit? Fall back to cascading... */ - find_next_cascade (window, windows, x, y, &x, &y); - - done_check_denied_focus: - /* If the window is being denied focus and isn't a transient of the - * focus window, we do NOT want it to overlap with the focus window - * if at all possible. This is guaranteed to only be called if the - * focus_window is non-NULL, and we try to avoid that window. - */ - if (window->denied_focus_and_not_transient) - { - MetaWindow *focus_window; - gboolean found_fit; - - focus_window = window->display->focus_window; - g_assert (focus_window != NULL); - - /* No need to do anything if the window doesn't overlap at all */ - found_fit = !window_overlaps_focus_window (window); - - /* Try to do a first fit again, this time only taking into account the - * focus window. - */ - if (!found_fit) - { - GList *focus_window_list; - focus_window_list = g_list_prepend (NULL, focus_window); - - /* Reset x and y ("origin" placement algorithm) */ - x = logical_monitor->rect.x; - y = logical_monitor->rect.y; - - found_fit = find_first_fit (window, focus_window_list, - logical_monitor, - x, y, &x, &y); - g_list_free (focus_window_list); - } - - /* If that still didn't work, just place it where we can see as much - * as possible. - */ - if (!found_fit) - find_most_freespace (window, focus_window, x, y, &x, &y); - } - - done: - if (windows) - g_list_free (windows); - - *new_x = x; - *new_y = y; -} diff --git a/src/core/place.h b/src/core/place.h deleted file mode 100644 index 2e2c81141..000000000 --- a/src/core/place.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter window placement */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * 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 . - */ - -#ifndef META_PLACE_H -#define META_PLACE_H - -#include "core/frame.h" -#include "core/window-private.h" - -void meta_window_process_placement (MetaWindow *window, - MetaPlacementRule *placement_rule, - int *rel_x, - int *rel_y); - -void meta_window_place (MetaWindow *window, - int x, - int y, - int *new_x, - int *new_y); - -#endif diff --git a/src/core/prefs-private.h b/src/core/prefs-private.h deleted file mode 100644 index e587bfaa1..000000000 --- a/src/core/prefs-private.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2021 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef PREFS_PRIVATE_H -#define PREFS_PRIVATE_H - -void meta_prefs_init (void); - -#endif /* PREFS_PRIVATE_H */ diff --git a/src/core/prefs.c b/src/core/prefs.c deleted file mode 100644 index 536d9dd57..000000000 --- a/src/core/prefs.c +++ /dev/null @@ -1,2229 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington, Copyright (C) 2002 Red Hat Inc. - * Copyright (C) 2006 Elijah Newren - * Copyright (C) 2008 Thomas Thurman - * Copyright (C) 2010 Milan Bouchet-Valat, Copyright (C) 2011 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 . - */ - -/** - * SECTION:prefs - * @title: Preferences - * @short_description: Mutter preferences - */ - -#include "config.h" - -#include -#include -#include -#include - -#include "compositor/meta-plugin-manager.h" -#include "core/keybindings-private.h" -#include "core/meta-accel-parse.h" -#include "core/prefs-private.h" -#include "core/util-private.h" -#include "meta/prefs.h" -#include "x11/meta-x11-display-private.h" - -/* If you add a key, it needs updating in init() and in the gsettings - * notify listener and of course in the .schemas file. - * - * Keys which are handled by one of the unified handlers below are - * not given a name here, because the purpose of the unified handlers - * is that keys should be referred to exactly once. - */ -#define KEY_TITLEBAR_FONT "titlebar-font" -#define KEY_NUM_WORKSPACES "num-workspaces" -#define KEY_WORKSPACE_NAMES "workspace-names" - -/* Keys from "foreign" schemas */ -#define KEY_GNOME_ACCESSIBILITY "toolkit-accessibility" -#define KEY_GNOME_ANIMATIONS "enable-animations" -#define KEY_GNOME_CURSOR_THEME "cursor-theme" -#define KEY_GNOME_CURSOR_SIZE "cursor-size" -#define KEY_XKB_OPTIONS "xkb-options" - -#define KEY_OVERLAY_KEY "overlay-key" -#define KEY_WORKSPACES_ONLY_ON_PRIMARY "workspaces-only-on-primary" -#define KEY_LOCATE_POINTER "locate-pointer" - -/* These are the different schemas we are keeping - * a GSettings instance for */ -#define SCHEMA_GENERAL "org.gnome.desktop.wm.preferences" -#define SCHEMA_MUTTER "org.gnome.mutter" -#define SCHEMA_INTERFACE "org.gnome.desktop.interface" -#define SCHEMA_INPUT_SOURCES "org.gnome.desktop.input-sources" -#define SCHEMA_MOUSE "org.gnome.desktop.peripherals.mouse" - -#define SETTINGS(s) g_hash_table_lookup (settings_schemas, (s)) - -static GList *changes = NULL; -static guint changed_idle; -static GList *listeners = NULL; -static GHashTable *settings_schemas; - -static gboolean use_system_font = FALSE; -static PangoFontDescription *titlebar_font = NULL; -static MetaVirtualModifier mouse_button_mods = Mod1Mask; -static MetaKeyCombo overlay_key_combo = { 0, 0, 0 }; -static MetaKeyCombo locate_pointer_key_combo = { 0, 0, 0 }; -static GDesktopFocusMode focus_mode = G_DESKTOP_FOCUS_MODE_CLICK; -static GDesktopFocusNewWindows focus_new_windows = G_DESKTOP_FOCUS_NEW_WINDOWS_SMART; -static gboolean raise_on_click = TRUE; -static gboolean center_new_windows = FALSE; -static gboolean attach_modal_dialogs = FALSE; -static int num_workspaces = 4; -static GDesktopTitlebarAction action_double_click_titlebar = G_DESKTOP_TITLEBAR_ACTION_TOGGLE_MAXIMIZE; -static GDesktopTitlebarAction action_middle_click_titlebar = G_DESKTOP_TITLEBAR_ACTION_LOWER; -static GDesktopTitlebarAction action_right_click_titlebar = G_DESKTOP_TITLEBAR_ACTION_MENU; -static gboolean dynamic_workspaces = FALSE; -static gboolean disable_workarounds = FALSE; -static gboolean auto_raise = FALSE; -static gboolean auto_raise_delay = 500; -static gboolean focus_change_on_pointer_rest = FALSE; -static gboolean bell_is_visible = FALSE; -static gboolean bell_is_audible = TRUE; -static gboolean gnome_accessibility = FALSE; -static gboolean gnome_animations = TRUE; -static gboolean locate_pointer_is_enabled = FALSE; -static unsigned int check_alive_timeout = 5000; -static char *cursor_theme = NULL; -/* cursor_size will, when running as an X11 compositing window manager, be the - * actual cursor size, multiplied with the global window scaling factor. On - * Wayland, it will be the actual cursor size retrieved from gsettings. - */ -static int cursor_size = 24; -static int draggable_border_width = 10; -static int drag_threshold; -static gboolean resize_with_right_button = FALSE; -static gboolean edge_tiling = FALSE; -static gboolean force_fullscreen = TRUE; -static gboolean auto_maximize = TRUE; -static gboolean show_fallback_app_menu = TRUE; - -static GDesktopVisualBellType visual_bell_type = G_DESKTOP_VISUAL_BELL_FULLSCREEN_FLASH; -static MetaButtonLayout button_layout; - -/* NULL-terminated array */ -static char **workspace_names = NULL; - -static gboolean workspaces_only_on_primary = FALSE; - -static char *iso_next_group_option = NULL; - -static void handle_preference_update_enum (GSettings *settings, - gchar *key); -static gboolean update_binding (MetaKeyPref *binding, - gchar **strokes); -static gboolean update_key_binding (const char *key, - gchar **strokes); - -static void settings_changed (GSettings *settings, - gchar *key, - gpointer data); -static void bindings_changed (GSettings *settings, - gchar *key, - gpointer data); - -static void queue_changed (MetaPreference pref); - -static void maybe_give_disable_workarounds_warning (void); - -static gboolean titlebar_handler (GVariant*, gpointer*, gpointer); -static gboolean mouse_button_mods_handler (GVariant*, gpointer*, gpointer); -static gboolean button_layout_handler (GVariant*, gpointer*, gpointer); -static gboolean overlay_key_handler (GVariant*, gpointer*, gpointer); -static gboolean locate_pointer_key_handler (GVariant*, gpointer*, gpointer); - -static gboolean iso_next_group_handler (GVariant*, gpointer*, gpointer); - -static void init_bindings (void); - -typedef struct -{ - MetaPrefsChangedFunc func; - gpointer data; -} MetaPrefsListener; - -typedef struct -{ - const char *key; - const char *schema; - MetaPreference pref; -} MetaBasePreference; - -typedef struct -{ - MetaBasePreference base; - gpointer target; -} MetaEnumPreference; - -typedef struct -{ - MetaBasePreference base; - gboolean *target; -} MetaBoolPreference; - - -/** - * MetaStringPreference: - * @handler: (nullable): A handler. Many of the string preferences - * aren't stored as strings and need parsing; others of them have - * default values which can't be solved in the general case. If you - * include a function pointer here, it will be called instead of writing - * the string value out to the target variable. - * The function will be passed to g_settings_get_mapped() and should - * return %TRUE if the mapping was successful and %FALSE otherwise. - * In the former case the function is expected to handle the result - * of the conversion itself and call queue_changed() appropriately; - * in particular the @result (out) parameter as returned by - * g_settings_get_mapped() will be ignored in all cases. - * This may be %NULL. If it is, see "target", below. - * @target: (nullable): Where to write the incoming string. - * This must be %NULL if the handler is non-%NULL. - * If the incoming string is %NULL, no change will be made. - */ -typedef struct -{ - MetaBasePreference base; - GSettingsGetMapping handler; - gchar **target; -} MetaStringPreference; - -typedef struct -{ - MetaBasePreference base; - GSettingsGetMapping handler; - gchar ***target; -} MetaStringArrayPreference; - -typedef struct -{ - MetaBasePreference base; - gint *target; -} MetaIntPreference; - -typedef struct -{ - MetaBasePreference base; - unsigned int *target; -} MetaUintPreference; - - -/* All preferences that are not keybindings must be listed here, - * plus in the GSettings schemas and the MetaPreference enum. - */ - -/* FIXMEs: */ -/* @@@ Don't use NULL lines at the end; glib can tell you how big it is */ - -static MetaEnumPreference preferences_enum[] = - { - { - { "focus-new-windows", - SCHEMA_GENERAL, - META_PREF_FOCUS_NEW_WINDOWS, - }, - &focus_new_windows, - }, - { - { "focus-mode", - SCHEMA_GENERAL, - META_PREF_FOCUS_MODE, - }, - &focus_mode, - }, - { - { "visual-bell-type", - SCHEMA_GENERAL, - META_PREF_VISUAL_BELL_TYPE, - }, - &visual_bell_type, - }, - { - { "action-double-click-titlebar", - SCHEMA_GENERAL, - META_PREF_ACTION_DOUBLE_CLICK_TITLEBAR, - }, - &action_double_click_titlebar, - }, - { - { "action-middle-click-titlebar", - SCHEMA_GENERAL, - META_PREF_ACTION_MIDDLE_CLICK_TITLEBAR, - }, - &action_middle_click_titlebar, - }, - { - { "action-right-click-titlebar", - SCHEMA_GENERAL, - META_PREF_ACTION_RIGHT_CLICK_TITLEBAR, - }, - &action_right_click_titlebar, - }, - { { NULL, 0, 0 }, NULL }, - }; - -static MetaBoolPreference preferences_bool[] = - { - { - { "attach-modal-dialogs", - SCHEMA_MUTTER, - META_PREF_ATTACH_MODAL_DIALOGS, - }, - &attach_modal_dialogs, - }, - { - { "center-new-windows", - SCHEMA_MUTTER, - META_PREF_CENTER_NEW_WINDOWS, - }, - ¢er_new_windows, - }, - { - { "raise-on-click", - SCHEMA_GENERAL, - META_PREF_RAISE_ON_CLICK, - }, - &raise_on_click, - }, - { - { "titlebar-uses-system-font", - SCHEMA_GENERAL, - META_PREF_TITLEBAR_FONT, /* note! shares a pref */ - }, - &use_system_font, - }, - { - { "dynamic-workspaces", - SCHEMA_MUTTER, - META_PREF_DYNAMIC_WORKSPACES, - }, - &dynamic_workspaces, - }, - { - { "disable-workarounds", - SCHEMA_GENERAL, - META_PREF_DISABLE_WORKAROUNDS, - }, - &disable_workarounds, - }, - { - { "auto-raise", - SCHEMA_GENERAL, - META_PREF_AUTO_RAISE, - }, - &auto_raise, - }, - { - { "focus-change-on-pointer-rest", - SCHEMA_MUTTER, - META_PREF_FOCUS_CHANGE_ON_POINTER_REST, - }, - &focus_change_on_pointer_rest - }, - { - { "visual-bell", - SCHEMA_GENERAL, - META_PREF_VISUAL_BELL, - }, - &bell_is_visible, /* FIXME: change the name: it's confusing */ - }, - { - { "audible-bell", - SCHEMA_GENERAL, - META_PREF_AUDIBLE_BELL, - }, - &bell_is_audible, /* FIXME: change the name: it's confusing */ - }, - { - { KEY_GNOME_ACCESSIBILITY, - SCHEMA_INTERFACE, - META_PREF_GNOME_ACCESSIBILITY, - }, - &gnome_accessibility, - }, - { - { KEY_GNOME_ANIMATIONS, - SCHEMA_INTERFACE, - META_PREF_GNOME_ANIMATIONS, - }, - &gnome_animations, - }, - { - { "resize-with-right-button", - SCHEMA_GENERAL, - META_PREF_RESIZE_WITH_RIGHT_BUTTON, - }, - &resize_with_right_button, - }, - { - { "edge-tiling", - SCHEMA_MUTTER, - META_PREF_EDGE_TILING, - }, - &edge_tiling, - }, - { - { "workspaces-only-on-primary", - SCHEMA_MUTTER, - META_PREF_WORKSPACES_ONLY_ON_PRIMARY, - }, - &workspaces_only_on_primary, - }, - { - { "auto-maximize", - SCHEMA_MUTTER, - META_PREF_AUTO_MAXIMIZE, - }, - &auto_maximize, - }, - { - { KEY_LOCATE_POINTER, - SCHEMA_INTERFACE, - META_PREF_LOCATE_POINTER, - }, - &locate_pointer_is_enabled, - }, - { { NULL, 0, 0 }, NULL }, - }; - -static MetaStringPreference preferences_string[] = - { - { - { "mouse-button-modifier", - SCHEMA_GENERAL, - META_PREF_MOUSE_BUTTON_MODS, - }, - mouse_button_mods_handler, - NULL, - }, - { - { KEY_TITLEBAR_FONT, - SCHEMA_GENERAL, - META_PREF_TITLEBAR_FONT, - }, - titlebar_handler, - NULL, - }, - { - { "button-layout", - SCHEMA_GENERAL, - META_PREF_BUTTON_LAYOUT, - }, - button_layout_handler, - NULL, - }, - { - { "cursor-theme", - SCHEMA_INTERFACE, - META_PREF_CURSOR_THEME, - }, - NULL, - &cursor_theme, - }, - { - { "overlay-key", - SCHEMA_MUTTER, - META_PREF_KEYBINDINGS, - }, - overlay_key_handler, - NULL, - }, - { - { "locate-pointer-key", - SCHEMA_MUTTER, - META_PREF_KEYBINDINGS, - }, - locate_pointer_key_handler, - NULL, - }, - { { NULL, 0, 0 }, NULL }, - }; - -static MetaStringArrayPreference preferences_string_array[] = - { - { - { KEY_WORKSPACE_NAMES, - SCHEMA_GENERAL, - META_PREF_WORKSPACE_NAMES, - }, - NULL, - &workspace_names, - }, - { - { KEY_XKB_OPTIONS, - SCHEMA_INPUT_SOURCES, - META_PREF_KEYBINDINGS, - }, - iso_next_group_handler, - NULL, - }, - { { NULL, 0, 0 }, NULL }, - }; - -static MetaIntPreference preferences_int[] = - { - { - { KEY_NUM_WORKSPACES, - SCHEMA_GENERAL, - META_PREF_NUM_WORKSPACES, - }, - &num_workspaces - }, - { - { "auto-raise-delay", - SCHEMA_GENERAL, - META_PREF_AUTO_RAISE_DELAY, - }, - &auto_raise_delay - }, - { - { "draggable-border-width", - SCHEMA_MUTTER, - META_PREF_DRAGGABLE_BORDER_WIDTH, - }, - &draggable_border_width - }, - { - { "drag-threshold", - SCHEMA_MOUSE, - META_PREF_DRAG_THRESHOLD, - }, - &drag_threshold - }, - { - { "cursor-size", - SCHEMA_INTERFACE, - META_PREF_CURSOR_SIZE, - }, - &cursor_size - }, - { { NULL, 0, 0 }, NULL }, - }; - -static MetaUintPreference preferences_uint[] = - { - { - { "check-alive-timeout", - SCHEMA_MUTTER, - META_PREF_CHECK_ALIVE_TIMEOUT, - }, - &check_alive_timeout, - }, - { { NULL, 0, 0 }, NULL }, - }; - -static void -handle_preference_init_enum (void) -{ - MetaEnumPreference *cursor = preferences_enum; - - while (cursor->base.key != NULL) - { - if (cursor->target==NULL) - continue; - - *((gint *) cursor->target) = - g_settings_get_enum (SETTINGS (cursor->base.schema), cursor->base.key); - - ++cursor; - } -} - -static void -handle_preference_init_bool (void) -{ - MetaBoolPreference *cursor = preferences_bool; - - while (cursor->base.key != NULL) - { - if (cursor->target!=NULL) - *cursor->target = - g_settings_get_boolean (SETTINGS (cursor->base.schema), - cursor->base.key); - - ++cursor; - } - - maybe_give_disable_workarounds_warning (); -} - -static void -handle_preference_init_string (void) -{ - MetaStringPreference *cursor = preferences_string; - - while (cursor->base.key != NULL) - { - char *value; - - /* Complex keys have a mapping function to check validity */ - if (cursor->handler) - { - if (cursor->target) - meta_bug ("%s has both a target and a handler", cursor->base.key); - - g_settings_get_mapped (SETTINGS (cursor->base.schema), - cursor->base.key, cursor->handler, NULL); - } - else - { - if (!cursor->target) - meta_bug ("%s must have handler or target", cursor->base.key); - - g_free (*(cursor->target)); - - value = g_settings_get_string (SETTINGS (cursor->base.schema), - cursor->base.key); - - *(cursor->target) = value; - } - - ++cursor; - } -} - -static void -handle_preference_init_string_array (void) -{ - MetaStringArrayPreference *cursor = preferences_string_array; - - while (cursor->base.key != NULL) - { - char **value; - - /* Complex keys have a mapping function to check validity */ - if (cursor->handler) - { - if (cursor->target) - meta_bug ("%s has both a target and a handler", cursor->base.key); - - g_settings_get_mapped (SETTINGS (cursor->base.schema), - cursor->base.key, cursor->handler, NULL); - } - else - { - if (!cursor->target) - meta_bug ("%s must have handler or target", cursor->base.key); - - if (*(cursor->target)) - g_strfreev (*(cursor->target)); - - value = g_settings_get_strv (SETTINGS (cursor->base.schema), - cursor->base.key); - - *(cursor->target) = value; - } - - ++cursor; - } -} - -static void -handle_preference_init_int (void) -{ - MetaIntPreference *cursor = preferences_int; - - - while (cursor->base.key != NULL) - { - if (cursor->target) - *cursor->target = g_settings_get_int (SETTINGS (cursor->base.schema), - cursor->base.key); - - ++cursor; - } -} - -static void -handle_preference_init_uint (void) -{ - MetaUintPreference *cursor = preferences_uint; - - while (cursor->base.key != NULL) - { - if (cursor->target) - *cursor->target = g_settings_get_uint (SETTINGS (cursor->base.schema), - cursor->base.key); - - ++cursor; - } -} - -static void -handle_preference_update_enum (GSettings *settings, - gchar *key) -{ - MetaEnumPreference *cursor = preferences_enum; - gint old_value; - - while (cursor->base.key != NULL && strcmp (key, cursor->base.key) != 0) - ++cursor; - - if (cursor->base.key == NULL) - /* Didn't recognise that key. */ - return; - - /* We need to know whether the value changes, so - * store the current value away. - */ - - old_value = * ((gint *)cursor->target); - *((gint *)cursor->target) = - g_settings_get_enum (SETTINGS (cursor->base.schema), key); - - /* Did it change? If so, tell the listeners about it. */ - if (old_value != *((gint *)cursor->target)) - queue_changed (cursor->base.pref); -} - -static void -handle_preference_update_bool (GSettings *settings, - gchar *key) -{ - MetaBoolPreference *cursor = preferences_bool; - gboolean old_value; - - while (cursor->base.key != NULL && strcmp (key, cursor->base.key) != 0) - ++cursor; - - if (cursor->base.key == NULL || cursor->target == NULL) - /* Unknown key or no work for us to do. */ - return; - - /* We need to know whether the value changes, so - * store the current value away. - */ - old_value = *((gboolean *) cursor->target); - - /* Now look it up... */ - *((gboolean *) cursor->target) = - g_settings_get_boolean (SETTINGS (cursor->base.schema), key); - - /* Did it change? If so, tell the listeners about it. */ - if (old_value != *((gboolean *)cursor->target)) - queue_changed (cursor->base.pref); - - if (cursor->base.pref==META_PREF_DISABLE_WORKAROUNDS) - maybe_give_disable_workarounds_warning (); -} - -static void -handle_preference_update_string (GSettings *settings, - gchar *key) -{ - MetaStringPreference *cursor = preferences_string; - char *value; - gboolean inform_listeners = FALSE; - - while (cursor->base.key != NULL && strcmp (key, cursor->base.key) != 0) - ++cursor; - - if (cursor->base.key==NULL) - /* Didn't recognise that key. */ - return; - - /* Complex keys have a mapping function to check validity */ - if (cursor->handler) - { - if (cursor->target) - meta_bug ("%s has both a target and a handler", cursor->base.key); - - g_settings_get_mapped (SETTINGS (cursor->base.schema), - cursor->base.key, cursor->handler, NULL); - } - else - { - if (!cursor->target) - meta_bug ("%s must have handler or target", cursor->base.key); - - value = g_settings_get_string (SETTINGS (cursor->base.schema), - cursor->base.key); - - inform_listeners = (g_strcmp0 (value, *(cursor->target)) != 0); - - g_free(*(cursor->target)); - - *(cursor->target) = value; - } - - if (inform_listeners) - queue_changed (cursor->base.pref); -} - -static void -handle_preference_update_string_array (GSettings *settings, - gchar *key) -{ - MetaStringArrayPreference *cursor = preferences_string_array; - gboolean inform_listeners = FALSE; - - while (cursor->base.key != NULL && strcmp (key, cursor->base.key) != 0) - ++cursor; - - if (cursor->base.key==NULL) - /* Didn't recognise that key. */ - return; - - /* Complex keys have a mapping function to check validity */ - if (cursor->handler) - { - if (cursor->target) - meta_bug ("%s has both a target and a handler", cursor->base.key); - - g_settings_get_mapped (SETTINGS (cursor->base.schema), - cursor->base.key, cursor->handler, NULL); - } - else - { - char **values, **previous; - int n_values, n_previous, i; - - if (!cursor->target) - meta_bug ("%s must have handler or target", cursor->base.key); - - values = g_settings_get_strv (SETTINGS (cursor->base.schema), - cursor->base.key); - n_values = g_strv_length (values); - previous = *(cursor->target); - n_previous = previous ? g_strv_length (previous) : 0; - - inform_listeners = n_previous != n_values; - for (i = 0; i < n_values && !inform_listeners; i++) - inform_listeners = g_strcmp0 (values[i], previous[i]) != 0; - - if (*(cursor->target)) - g_strfreev (*(cursor->target)); - *(cursor->target) = values; - } - - if (inform_listeners) - queue_changed (cursor->base.pref); -} - -static void -handle_preference_update_int (GSettings *settings, - gchar *key) -{ - MetaIntPreference *cursor = preferences_int; - gint new_value; - - while (cursor->base.key != NULL && strcmp (key, cursor->base.key) != 0) - ++cursor; - - if (cursor->base.key == NULL || cursor->target == NULL) - /* Unknown key or no work for us to do. */ - return; - - new_value = g_settings_get_int (SETTINGS (cursor->base.schema), key); - - /* Did it change? If so, tell the listeners about it. */ - if (*cursor->target != new_value) - { - *cursor->target = new_value; - queue_changed (cursor->base.pref); - } -} - -static void -handle_preference_update_uint (GSettings *settings, - char *key) -{ - MetaUintPreference *cursor = preferences_uint; - unsigned int new_value; - - while (cursor->base.key && strcmp (key, cursor->base.key) != 0) - ++cursor; - - if (!cursor->base.key || !cursor->target) - return; - - new_value = g_settings_get_uint (SETTINGS (cursor->base.schema), key); - - if (*cursor->target != new_value) - { - *cursor->target = new_value; - queue_changed (cursor->base.pref); - } -} - - -/****************************************************************************/ -/* Listeners. */ -/****************************************************************************/ - -/** - * meta_prefs_add_listener: (skip) - * @func: a #MetaPrefsChangedFunc - * @user_data: data passed to the function - * - */ -void -meta_prefs_add_listener (MetaPrefsChangedFunc func, - gpointer user_data) -{ - MetaPrefsListener *l; - - l = g_new (MetaPrefsListener, 1); - l->func = func; - l->data = user_data; - - listeners = g_list_prepend (listeners, l); -} - -/** - * meta_prefs_remove_listener: (skip) - * @func: a #MetaPrefsChangedFunc - * @user_data: data passed to the function - * - */ -void -meta_prefs_remove_listener (MetaPrefsChangedFunc func, - gpointer user_data) -{ - GList *tmp; - - tmp = listeners; - while (tmp != NULL) - { - MetaPrefsListener *l = tmp->data; - - if (l->func == func && - l->data == user_data) - { - g_free (l); - listeners = g_list_delete_link (listeners, tmp); - - return; - } - - tmp = tmp->next; - } -} - -static void -emit_changed (MetaPreference pref) -{ - GList *tmp; - GList *copy; - - meta_topic (META_DEBUG_PREFS, "Notifying listeners that pref %s changed", - meta_preference_to_string (pref)); - - copy = g_list_copy (listeners); - - tmp = copy; - - while (tmp != NULL) - { - MetaPrefsListener *l = tmp->data; - - (* l->func) (pref, l->data); - - tmp = tmp->next; - } - - g_list_free (copy); -} - -static gboolean -changed_idle_handler (gpointer data) -{ - GList *tmp; - GList *copy; - - changed_idle = 0; - - copy = g_list_copy (changes); /* reentrancy paranoia */ - - g_list_free (changes); - changes = NULL; - - tmp = copy; - while (tmp != NULL) - { - MetaPreference pref = GPOINTER_TO_INT (tmp->data); - - emit_changed (pref); - - tmp = tmp->next; - } - - g_list_free (copy); - - return FALSE; -} - -static void -queue_changed (MetaPreference pref) -{ - meta_topic (META_DEBUG_PREFS, "Queueing change of pref %s", - meta_preference_to_string (pref)); - - if (g_list_find (changes, GINT_TO_POINTER (pref)) == NULL) - changes = g_list_prepend (changes, GINT_TO_POINTER (pref)); - else - meta_topic (META_DEBUG_PREFS, "Change of pref %s was already pending", - meta_preference_to_string (pref)); - - if (changed_idle == 0) - { - changed_idle = g_idle_add_full (META_PRIORITY_PREFS_NOTIFY, - changed_idle_handler, NULL, NULL); - g_source_set_name_by_id (changed_idle, "[mutter] changed_idle_handler"); - } -} - - -/****************************************************************************/ -/* Initialisation. */ -/****************************************************************************/ - -void -meta_prefs_init (void) -{ - GSettings *settings; - - settings_schemas = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, g_object_unref); - - settings = g_settings_new (SCHEMA_GENERAL); - g_signal_connect (settings, "changed", G_CALLBACK (settings_changed), NULL); - g_hash_table_insert (settings_schemas, g_strdup (SCHEMA_GENERAL), settings); - - settings = g_settings_new (SCHEMA_MUTTER); - g_signal_connect (settings, "changed", G_CALLBACK (settings_changed), NULL); - g_hash_table_insert (settings_schemas, g_strdup (SCHEMA_MUTTER), settings); - - settings = g_settings_new (SCHEMA_MOUSE); - g_signal_connect (settings, "changed", G_CALLBACK (settings_changed), NULL); - g_hash_table_insert (settings_schemas, g_strdup (SCHEMA_MOUSE), settings); - - /* Individual keys we watch outside of our schemas */ - settings = g_settings_new (SCHEMA_INTERFACE); - g_signal_connect (settings, "changed::" KEY_GNOME_ACCESSIBILITY, - G_CALLBACK (settings_changed), NULL); - g_signal_connect (settings, "changed::" KEY_GNOME_ANIMATIONS, - G_CALLBACK (settings_changed), NULL); - g_signal_connect (settings, "changed::" KEY_GNOME_CURSOR_THEME, - G_CALLBACK (settings_changed), NULL); - g_signal_connect (settings, "changed::" KEY_GNOME_CURSOR_SIZE, - G_CALLBACK (settings_changed), NULL); - g_signal_connect (settings, "changed::" KEY_LOCATE_POINTER, - G_CALLBACK (settings_changed), NULL); - g_hash_table_insert (settings_schemas, g_strdup (SCHEMA_INTERFACE), settings); - - settings = g_settings_new (SCHEMA_INPUT_SOURCES); - g_signal_connect (settings, "changed::" KEY_XKB_OPTIONS, - G_CALLBACK (settings_changed), NULL); - g_hash_table_insert (settings_schemas, g_strdup (SCHEMA_INPUT_SOURCES), settings); - - /* Pick up initial values. */ - - handle_preference_init_enum (); - handle_preference_init_bool (); - handle_preference_init_string (); - handle_preference_init_string_array (); - handle_preference_init_int (); - handle_preference_init_uint (); - - init_bindings (); -} - -static gboolean -find_pref (void *prefs, - size_t pref_size, - const char *search_key, - MetaBasePreference **pref) -{ - void *p = prefs; - - while (TRUE) - { - char **key = p; - if (*key == NULL) - break; - - if (strcmp (*key, search_key) == 0) - { - *pref = p; - return TRUE; - } - - p = (guchar *)p + pref_size; - } - - return FALSE; -} - - -/****************************************************************************/ -/* Updates. */ -/****************************************************************************/ - - -static void -settings_changed (GSettings *settings, - gchar *key, - gpointer data) -{ - GVariant *value; - const GVariantType *type; - MetaEnumPreference *cursor; - gboolean found_enum; - - value = g_settings_get_value (settings, key); - type = g_variant_get_type (value); - - if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN)) - handle_preference_update_bool (settings, key); - else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32)) - handle_preference_update_int (settings, key); - else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32)) - handle_preference_update_uint (settings, key); - else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING_ARRAY)) - handle_preference_update_string_array (settings, key); - else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING)) - { - cursor = preferences_enum; - found_enum = FALSE; - - while (cursor->base.key != NULL) - { - - if (strcmp (key, cursor->base.key) == 0) - found_enum = TRUE; - - cursor++; - } - - if (found_enum) - handle_preference_update_enum (settings, key); - else - handle_preference_update_string (settings, key); - } - else - { - /* Unknown preference type. This quite likely simply isn't - * a preference we track changes to. */ - } - - g_variant_unref (value); -} - -static void -bindings_changed (GSettings *settings, - gchar *key, - gpointer data) -{ - gchar **strokes; - strokes = g_settings_get_strv (settings, key); - - if (update_key_binding (key, strokes)) - queue_changed (META_PREF_KEYBINDINGS); - - g_strfreev (strokes); -} - -/** - * maybe_give_disable_workaround_warning: - * - * Special case: give a warning the first time disable_workarounds - * is turned on. - */ -static void -maybe_give_disable_workarounds_warning (void) -{ - static gboolean first_disable = TRUE; - - if (first_disable && disable_workarounds) - { - first_disable = FALSE; - - meta_warning ("Workarounds for broken applications disabled. " - "Some applications may not behave properly."); - } -} - -MetaVirtualModifier -meta_prefs_get_mouse_button_mods (void) -{ - return mouse_button_mods; -} - -GDesktopFocusMode -meta_prefs_get_focus_mode (void) -{ - return focus_mode; -} - -GDesktopFocusNewWindows -meta_prefs_get_focus_new_windows (void) -{ - return focus_new_windows; -} - -gboolean -meta_prefs_get_center_new_windows (void) -{ - return center_new_windows; -} - -gboolean -meta_prefs_get_attach_modal_dialogs (void) -{ - return attach_modal_dialogs; -} - -gboolean -meta_prefs_get_raise_on_click (void) -{ - return raise_on_click; -} - -gboolean -meta_prefs_get_show_fallback_app_menu (void) -{ - return show_fallback_app_menu; -} - -void -meta_prefs_set_show_fallback_app_menu (gboolean whether) -{ - gboolean changed = FALSE; - - changed = (show_fallback_app_menu == !whether); - - show_fallback_app_menu = whether; - - if (changed) - queue_changed (META_PREF_BUTTON_LAYOUT); -} - -const char* -meta_prefs_get_cursor_theme (void) -{ - return cursor_theme; -} - -int -meta_prefs_get_cursor_size (void) -{ - return cursor_size; -} - - -/****************************************************************************/ -/* Handlers for string preferences. */ -/****************************************************************************/ - -static gboolean -titlebar_handler (GVariant *value, - gpointer *result, - gpointer data) -{ - PangoFontDescription *desc; - const gchar *string_value; - - *result = NULL; /* ignored */ - string_value = g_variant_get_string (value, NULL); - desc = pango_font_description_from_string (string_value); - - if (desc == NULL) - { - meta_warning ("Could not parse font description " - "\"%s\" from GSettings key %s", - string_value ? string_value : "(null)", - KEY_TITLEBAR_FONT); - return FALSE; - } - - /* Is the new description the same as the old? */ - if (titlebar_font && - pango_font_description_equal (desc, titlebar_font)) - { - pango_font_description_free (desc); - } - else - { - if (titlebar_font) - pango_font_description_free (titlebar_font); - - titlebar_font = desc; - queue_changed (META_PREF_TITLEBAR_FONT); - } - - return TRUE; -} - -static gboolean -mouse_button_mods_handler (GVariant *value, - gpointer *result, - gpointer data) -{ - MetaVirtualModifier mods; - const gchar *string_value; - - *result = NULL; /* ignored */ - string_value = g_variant_get_string (value, NULL); - - if (!string_value || !meta_parse_modifier (string_value, &mods)) - { - meta_topic (META_DEBUG_KEYBINDINGS, - "Failed to parse new GSettings value"); - - meta_warning ("\"%s\" found in configuration database is " - "not a valid value for mouse button modifier", - string_value); - - return FALSE; - } - - meta_topic (META_DEBUG_KEYBINDINGS, - "Mouse button modifier has new GSettings value \"%s\"", - string_value); - - if (mods != mouse_button_mods) - { - mouse_button_mods = mods; - queue_changed (META_PREF_MOUSE_BUTTON_MODS); - } - - return TRUE; -} - -static gboolean -button_layout_equal (const MetaButtonLayout *a, - const MetaButtonLayout *b) -{ - int i; - - i = 0; - while (i < MAX_BUTTONS_PER_CORNER) - { - if (a->left_buttons[i] != b->left_buttons[i]) - return FALSE; - if (a->right_buttons[i] != b->right_buttons[i]) - return FALSE; - if (a->left_buttons_has_spacer[i] != b->left_buttons_has_spacer[i]) - return FALSE; - if (a->right_buttons_has_spacer[i] != b->right_buttons_has_spacer[i]) - return FALSE; - ++i; - } - - return TRUE; -} - -/* - * This conversion cannot be handled by GSettings since - * several values are stored in the same key (as a string). - */ -static MetaButtonFunction -button_function_from_string (const char *str) -{ - if (strcmp (str, "menu") == 0) - return META_BUTTON_FUNCTION_MENU; - else if (strcmp (str, "minimize") == 0) - return META_BUTTON_FUNCTION_MINIMIZE; - else if (strcmp (str, "maximize") == 0) - return META_BUTTON_FUNCTION_MAXIMIZE; - else if (strcmp (str, "close") == 0) - return META_BUTTON_FUNCTION_CLOSE; - else - /* don't know; give up */ - return META_BUTTON_FUNCTION_LAST; -} - -static gboolean -button_layout_handler (GVariant *value, - gpointer *result, - gpointer data) -{ - MetaButtonLayout new_layout; - const gchar *string_value; - char **sides = NULL; - int i; - - /* We need to ignore unknown button functions, for - * compat with future versions - */ - - *result = NULL; /* ignored */ - string_value = g_variant_get_string (value, NULL); - - if (string_value) - sides = g_strsplit (string_value, ":", 2); - - i = 0; - if (sides != NULL && sides[0] != NULL) - { - char **buttons; - int b; - gboolean used[META_BUTTON_FUNCTION_LAST]; - - while (i < META_BUTTON_FUNCTION_LAST) - { - used[i] = FALSE; - new_layout.left_buttons_has_spacer[i] = FALSE; - ++i; - } - - buttons = g_strsplit (sides[0], ",", -1); - i = 0; - b = 0; - while (buttons[b] != NULL) - { - MetaButtonFunction f = button_function_from_string (buttons[b]); - if (i > 0 && strcmp("spacer", buttons[b]) == 0) - { - new_layout.left_buttons_has_spacer[i-1] = TRUE; - } - else - { - if (f != META_BUTTON_FUNCTION_LAST && !used[f]) - { - new_layout.left_buttons[i] = f; - used[f] = TRUE; - ++i; - } - else - { - meta_topic (META_DEBUG_PREFS, - "Ignoring unknown or already-used button name \"%s\"", - buttons[b]); - } - } - - ++b; - } - - g_strfreev (buttons); - } - - for (; i < MAX_BUTTONS_PER_CORNER; i++) - { - new_layout.left_buttons[i] = META_BUTTON_FUNCTION_LAST; - new_layout.left_buttons_has_spacer[i] = FALSE; - } - - i = 0; - if (sides != NULL && sides[0] != NULL && sides[1] != NULL) - { - char **buttons; - int b; - gboolean used[META_BUTTON_FUNCTION_LAST]; - - while (i < META_BUTTON_FUNCTION_LAST) - { - used[i] = FALSE; - new_layout.right_buttons_has_spacer[i] = FALSE; - ++i; - } - - buttons = g_strsplit (sides[1], ",", -1); - i = 0; - b = 0; - while (buttons[b] != NULL) - { - MetaButtonFunction f = button_function_from_string (buttons[b]); - if (i > 0 && strcmp("spacer", buttons[b]) == 0) - { - new_layout.right_buttons_has_spacer[i-1] = TRUE; - } - else - { - if (f != META_BUTTON_FUNCTION_LAST && !used[f]) - { - new_layout.right_buttons[i] = f; - used[f] = TRUE; - ++i; - } - else - { - meta_topic (META_DEBUG_PREFS, - "Ignoring unknown or already-used button name \"%s\"", - buttons[b]); - } - } - - ++b; - } - - g_strfreev (buttons); - } - - for (; i < MAX_BUTTONS_PER_CORNER; i++) - { - new_layout.right_buttons[i] = META_BUTTON_FUNCTION_LAST; - new_layout.right_buttons_has_spacer[i] = FALSE; - } - - g_strfreev (sides); - - /* Invert the button layout for RTL languages */ - if (meta_get_locale_direction() == META_LOCALE_DIRECTION_RTL) - { - MetaButtonLayout rtl_layout; - int j; - - for (i = 0; new_layout.left_buttons[i] != META_BUTTON_FUNCTION_LAST; i++); - for (j = 0; j < i; j++) - { - rtl_layout.right_buttons[j] = new_layout.left_buttons[i - j - 1]; - if (j == 0) - rtl_layout.right_buttons_has_spacer[i - 1] = new_layout.left_buttons_has_spacer[i - j - 1]; - else - rtl_layout.right_buttons_has_spacer[j - 1] = new_layout.left_buttons_has_spacer[i - j - 1]; - } - for (; j < MAX_BUTTONS_PER_CORNER; j++) - { - rtl_layout.right_buttons[j] = META_BUTTON_FUNCTION_LAST; - rtl_layout.right_buttons_has_spacer[j] = FALSE; - } - - for (i = 0; new_layout.right_buttons[i] != META_BUTTON_FUNCTION_LAST; i++); - for (j = 0; j < i; j++) - { - rtl_layout.left_buttons[j] = new_layout.right_buttons[i - j - 1]; - if (j == 0) - rtl_layout.left_buttons_has_spacer[i - 1] = new_layout.right_buttons_has_spacer[i - j - 1]; - else - rtl_layout.left_buttons_has_spacer[j - 1] = new_layout.right_buttons_has_spacer[i - j - 1]; - } - for (; j < MAX_BUTTONS_PER_CORNER; j++) - { - rtl_layout.left_buttons[j] = META_BUTTON_FUNCTION_LAST; - rtl_layout.left_buttons_has_spacer[j] = FALSE; - } - - new_layout = rtl_layout; - } - - if (!button_layout_equal (&button_layout, &new_layout)) - { - button_layout = new_layout; - emit_changed (META_PREF_BUTTON_LAYOUT); - } - - return TRUE; -} - -static gboolean -overlay_key_handler (GVariant *value, - gpointer *result, - gpointer data) -{ - MetaKeyCombo combo; - const gchar *string_value; - - *result = NULL; /* ignored */ - string_value = g_variant_get_string (value, NULL); - - if (string_value && meta_parse_accelerator (string_value, &combo)) - ; - else - { - meta_topic (META_DEBUG_KEYBINDINGS, - "Failed to parse value for overlay-key"); - return FALSE; - } - - combo.modifiers = 0; - - if (overlay_key_combo.keysym != combo.keysym || - overlay_key_combo.keycode != combo.keycode) - { - overlay_key_combo = combo; - queue_changed (META_PREF_KEYBINDINGS); - } - - return TRUE; -} - -static gboolean -locate_pointer_key_handler (GVariant *value, - gpointer *result, - gpointer data) -{ - MetaKeyCombo combo; - const gchar *string_value; - - *result = NULL; /* ignored */ - string_value = g_variant_get_string (value, NULL); - - if (!string_value || !meta_parse_accelerator (string_value, &combo)) - { - meta_topic (META_DEBUG_KEYBINDINGS, - "Failed to parse value for locate-pointer-key"); - return FALSE; - } - - combo.modifiers = 0; - - if (locate_pointer_key_combo.keysym != combo.keysym || - locate_pointer_key_combo.keycode != combo.keycode) - { - locate_pointer_key_combo = combo; - queue_changed (META_PREF_KEYBINDINGS); - } - - return TRUE; -} - -static gboolean -iso_next_group_handler (GVariant *value, - gpointer *result, - gpointer data) -{ - const char **xkb_options, **p; - const char *option = NULL; - gboolean changed = FALSE; - - *result = NULL; /* ignored */ - xkb_options = g_variant_get_strv (value, NULL); - - for (p = xkb_options; p && *p; ++p) - if (g_str_has_prefix (*p, "grp:")) - { - option = (*p + 4); - break; - } - - changed = (g_strcmp0 (option, iso_next_group_option) != 0); - - if (changed) - { - g_free (iso_next_group_option); - iso_next_group_option = g_strdup (option); - queue_changed (META_PREF_KEYBINDINGS); - } - - g_free (xkb_options); - - return TRUE; -} - -const PangoFontDescription* -meta_prefs_get_titlebar_font (void) -{ - if (use_system_font) - return NULL; - else - return titlebar_font; -} - -int -meta_prefs_get_num_workspaces (void) -{ - return num_workspaces; -} - -gboolean -meta_prefs_get_dynamic_workspaces (void) -{ - return dynamic_workspaces; -} - -gboolean -meta_prefs_get_disable_workarounds (void) -{ - return disable_workarounds; -} - -#ifdef WITH_VERBOSE_MODE -const char* -meta_preference_to_string (MetaPreference pref) -{ - /* TODO: better handled via GLib enum nicknames */ - switch (pref) - { - case META_PREF_MOUSE_BUTTON_MODS: - return "MOUSE_BUTTON_MODS"; - - case META_PREF_FOCUS_MODE: - return "FOCUS_MODE"; - - case META_PREF_FOCUS_NEW_WINDOWS: - return "FOCUS_NEW_WINDOWS"; - - case META_PREF_CENTER_NEW_WINDOWS: - return "CENTER_NEW_WINDOWS"; - - case META_PREF_ATTACH_MODAL_DIALOGS: - return "ATTACH_MODAL_DIALOGS"; - - case META_PREF_RAISE_ON_CLICK: - return "RAISE_ON_CLICK"; - - case META_PREF_TITLEBAR_FONT: - return "TITLEBAR_FONT"; - - case META_PREF_NUM_WORKSPACES: - return "NUM_WORKSPACES"; - - case META_PREF_KEYBINDINGS: - return "KEYBINDINGS"; - - case META_PREF_DISABLE_WORKAROUNDS: - return "DISABLE_WORKAROUNDS"; - - case META_PREF_ACTION_DOUBLE_CLICK_TITLEBAR: - return "ACTION_DOUBLE_CLICK_TITLEBAR"; - - case META_PREF_ACTION_MIDDLE_CLICK_TITLEBAR: - return "ACTION_MIDDLE_CLICK_TITLEBAR"; - - case META_PREF_ACTION_RIGHT_CLICK_TITLEBAR: - return "ACTION_RIGHT_CLICK_TITLEBAR"; - - case META_PREF_AUTO_RAISE: - return "AUTO_RAISE"; - - case META_PREF_AUTO_RAISE_DELAY: - return "AUTO_RAISE_DELAY"; - - case META_PREF_FOCUS_CHANGE_ON_POINTER_REST: - return "FOCUS_CHANGE_ON_POINTER_REST"; - - case META_PREF_BUTTON_LAYOUT: - return "BUTTON_LAYOUT"; - - case META_PREF_WORKSPACE_NAMES: - return "WORKSPACE_NAMES"; - - case META_PREF_VISUAL_BELL: - return "VISUAL_BELL"; - - case META_PREF_AUDIBLE_BELL: - return "AUDIBLE_BELL"; - - case META_PREF_VISUAL_BELL_TYPE: - return "VISUAL_BELL_TYPE"; - - case META_PREF_GNOME_ACCESSIBILITY: - return "GNOME_ACCESSIBILTY"; - - case META_PREF_GNOME_ANIMATIONS: - return "GNOME_ANIMATIONS"; - - case META_PREF_CURSOR_THEME: - return "CURSOR_THEME"; - - case META_PREF_CURSOR_SIZE: - return "CURSOR_SIZE"; - - case META_PREF_RESIZE_WITH_RIGHT_BUTTON: - return "RESIZE_WITH_RIGHT_BUTTON"; - - case META_PREF_EDGE_TILING: - return "EDGE_TILING"; - - case META_PREF_FORCE_FULLSCREEN: - return "FORCE_FULLSCREEN"; - - case META_PREF_WORKSPACES_ONLY_ON_PRIMARY: - return "WORKSPACES_ONLY_ON_PRIMARY"; - - case META_PREF_DRAGGABLE_BORDER_WIDTH: - return "DRAGGABLE_BORDER_WIDTH"; - - case META_PREF_DRAG_THRESHOLD: - return "DRAG_THRESHOLD"; - - case META_PREF_DYNAMIC_WORKSPACES: - return "DYNAMIC_WORKSPACES"; - - case META_PREF_AUTO_MAXIMIZE: - return "AUTO_MAXIMIZE"; - - case META_PREF_LOCATE_POINTER: - return "LOCATE_POINTER"; - - case META_PREF_CHECK_ALIVE_TIMEOUT: - return "CHECK_ALIVE_TIMEOUT"; - } - - return "(unknown)"; -} -#endif /* WITH_VERBOSE_MODE */ - -void -meta_prefs_set_num_workspaces (int n_workspaces) -{ - MetaBasePreference *pref; - - if (find_pref (preferences_int, sizeof(MetaIntPreference), - KEY_NUM_WORKSPACES, &pref)) - { - g_settings_set_int (SETTINGS (pref->schema), - KEY_NUM_WORKSPACES, - n_workspaces); - } -} - -static GHashTable *key_bindings; - -static void -meta_key_pref_free (MetaKeyPref *pref) -{ - update_binding (pref, NULL); - - g_free (pref->name); - g_object_unref (pref->settings); - - g_free (pref); -} - - -static void -init_bindings (void) -{ - MetaKeyPref *pref; - - key_bindings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, - (GDestroyNotify)meta_key_pref_free); - - pref = g_new0 (MetaKeyPref, 1); - pref->name = g_strdup ("overlay-key"); - pref->action = META_KEYBINDING_ACTION_OVERLAY_KEY; - pref->combos = g_slist_prepend (pref->combos, &overlay_key_combo); - pref->builtin = 1; - - g_hash_table_insert (key_bindings, g_strdup (pref->name), pref); - - pref = g_new0 (MetaKeyPref, 1); - pref->name = g_strdup ("locate-pointer-key"); - pref->action = META_KEYBINDING_ACTION_LOCATE_POINTER_KEY; - pref->combos = g_slist_prepend (pref->combos, &locate_pointer_key_combo); - pref->builtin = 1; - - g_hash_table_insert (key_bindings, g_strdup (pref->name), pref); -} - -static gboolean -update_binding (MetaKeyPref *binding, - gchar **strokes) -{ - GSList *old_combos, *a, *b; - gboolean changed; - int i; - - meta_topic (META_DEBUG_KEYBINDINGS, - "Binding \"%s\" has new GSettings value", - binding->name); - - old_combos = binding->combos; - binding->combos = NULL; - - for (i = 0; strokes && strokes[i]; i++) - { - MetaKeyCombo *combo; - - combo = g_malloc0 (sizeof (MetaKeyCombo)); - - if (!meta_parse_accelerator (strokes[i], combo)) - { - meta_topic (META_DEBUG_KEYBINDINGS, - "Failed to parse new GSettings value"); - meta_warning ("\"%s\" found in configuration database is not a valid value for keybinding \"%s\"", - strokes[i], binding->name); - - g_free (combo); - - /* Value is kept and will thus be removed next time we save the key. - * Changing the key in response to a modification could lead to cyclic calls. */ - continue; - } - - binding->combos = g_slist_prepend (binding->combos, combo); - } - - binding->combos = g_slist_reverse (binding->combos); - - a = old_combos; - b = binding->combos; - while (TRUE) - { - if ((!a && b) || (a && !b)) - { - changed = TRUE; - break; - } - else if (!a && !b) - { - changed = FALSE; - break; - } - else if (memcmp (a->data, b->data, sizeof (MetaKeyCombo)) != 0) - { - changed = TRUE; - break; - } - else - { - a = a->next; - b = b->next; - } - } - - g_slist_free_full (old_combos, g_free); - - return changed; -} - -static gboolean -update_key_binding (const char *key, - gchar **strokes) -{ - MetaKeyPref *pref = g_hash_table_lookup (key_bindings, key); - - if (pref) - return update_binding (pref, strokes); - else - return FALSE; -} - -const char* -meta_prefs_get_workspace_name (int i) -{ - const char *name; - - if (!workspace_names || - g_strv_length (workspace_names) < (guint)i + 1 || - !*workspace_names[i]) - { - char *generated_name = g_strdup_printf (_("Workspace %d"), i + 1); - name = g_intern_string (generated_name); - g_free (generated_name); - } - else - name = workspace_names[i]; - - meta_topic (META_DEBUG_PREFS, - "Getting name of workspace %d: \"%s\"", i, name); - - return name; -} - -void -meta_prefs_change_workspace_name (int num, - const char *name) -{ - GVariantBuilder builder; - int n_workspace_names, i; - - g_return_if_fail (num >= 0); - - meta_topic (META_DEBUG_PREFS, - "Changing name of workspace %d to %s", - num, name ? name : "none"); - - /* NULL and empty string both mean "default" here, - * and we also need to match the name against its default value - * to avoid saving it literally. */ - if (g_strcmp0 (name, meta_prefs_get_workspace_name (num)) == 0) - { - if (!name || !*name) - meta_topic (META_DEBUG_PREFS, - "Workspace %d already uses default name", num); - else - meta_topic (META_DEBUG_PREFS, - "Workspace %d already has name %s", num, name); - return; - } - - g_variant_builder_init (&builder, G_VARIANT_TYPE_STRING_ARRAY); - n_workspace_names = workspace_names ? g_strv_length (workspace_names) : 0; - - for (i = 0; i < MAX (num + 1, n_workspace_names); i++) - { - const char *value; - - if (i == num) - value = name ? name : ""; - else if (i < n_workspace_names) - value = workspace_names[i] ? workspace_names[i] : ""; - else - value = ""; - - g_variant_builder_add (&builder, "s", value); - } - - g_settings_set_value (SETTINGS (SCHEMA_GENERAL), KEY_WORKSPACE_NAMES, - g_variant_builder_end (&builder)); -} - -/** - * meta_prefs_get_button_layout: - * @button_layout: (out): - */ -void -meta_prefs_get_button_layout (MetaButtonLayout *button_layout_p) -{ - *button_layout_p = button_layout; -} - -gboolean -meta_prefs_get_visual_bell (void) -{ - return bell_is_visible; -} - -gboolean -meta_prefs_bell_is_audible (void) -{ - return bell_is_audible; -} - -GDesktopVisualBellType -meta_prefs_get_visual_bell_type (void) -{ - return visual_bell_type; -} - -gboolean -meta_prefs_add_keybinding (const char *name, - GSettings *settings, - MetaKeyBindingAction action, - MetaKeyBindingFlags flags) -{ - MetaKeyPref *pref; - char **strokes; - guint id; - - if (g_hash_table_lookup (key_bindings, name)) - { - meta_warning ("Trying to re-add keybinding \"%s\".", name); - return FALSE; - } - - pref = g_new0 (MetaKeyPref, 1); - pref->name = g_strdup (name); - pref->settings = g_object_ref (settings); - pref->action = action; - pref->combos = NULL; - pref->builtin = (flags & META_KEY_BINDING_BUILTIN) != 0; - - if (pref->builtin) - { - if (g_object_get_data (G_OBJECT (settings), "changed-signal") == NULL) - { - id = g_signal_connect (settings, "changed", - G_CALLBACK (bindings_changed), NULL); - g_object_set_data (G_OBJECT (settings), "changed-signal", GUINT_TO_POINTER (id)); - } - } - else - { - char *changed_signal = g_strdup_printf ("changed::%s", name); - id = g_signal_connect (settings, changed_signal, - G_CALLBACK (bindings_changed), NULL); - g_free (changed_signal); - - g_object_set_data (G_OBJECT (settings), name, GUINT_TO_POINTER (id)); - - queue_changed (META_PREF_KEYBINDINGS); - } - - strokes = g_settings_get_strv (settings, name); - update_binding (pref, strokes); - g_strfreev (strokes); - - g_hash_table_insert (key_bindings, g_strdup (name), pref); - - return TRUE; -} - -gboolean -meta_prefs_remove_keybinding (const char *name) -{ - MetaKeyPref *pref; - gulong id; - - pref = g_hash_table_lookup (key_bindings, name); - if (!pref) - { - meta_warning ("Trying to remove non-existent keybinding \"%s\".", name); - return FALSE; - } - - if (pref->builtin) - { - meta_warning ("Trying to remove builtin keybinding \"%s\".", name); - return FALSE; - } - - id = GPOINTER_TO_UINT (g_object_steal_data (G_OBJECT (pref->settings), name)); - g_clear_signal_handler (&id, pref->settings); - - g_hash_table_remove (key_bindings, name); - - queue_changed (META_PREF_KEYBINDINGS); - - return TRUE; -} - -GList * -meta_prefs_get_keybindings (void) -{ - return g_hash_table_get_values (key_bindings); -} - -void -meta_prefs_get_overlay_binding (MetaKeyCombo *combo) -{ - *combo = overlay_key_combo; -} - -void -meta_prefs_get_locate_pointer_binding (MetaKeyCombo *combo) -{ - *combo = locate_pointer_key_combo; -} - -gboolean -meta_prefs_is_locate_pointer_enabled (void) -{ - return locate_pointer_is_enabled; -} - -unsigned int -meta_prefs_get_check_alive_timeout (void) -{ - return check_alive_timeout; -} - -const char * -meta_prefs_get_iso_next_group_option (void) -{ - return iso_next_group_option; -} - -GDesktopTitlebarAction -meta_prefs_get_action_double_click_titlebar (void) -{ - return action_double_click_titlebar; -} - -GDesktopTitlebarAction -meta_prefs_get_action_middle_click_titlebar (void) -{ - return action_middle_click_titlebar; -} - -GDesktopTitlebarAction -meta_prefs_get_action_right_click_titlebar (void) -{ - return action_right_click_titlebar; -} - -gboolean -meta_prefs_get_auto_raise (void) -{ - return auto_raise; -} - -int -meta_prefs_get_auto_raise_delay (void) -{ - return auto_raise_delay; -} - -gboolean -meta_prefs_get_focus_change_on_pointer_rest (void) -{ - return focus_change_on_pointer_rest; -} - -gboolean -meta_prefs_get_gnome_accessibility (void) -{ - return gnome_accessibility; -} - -gboolean -meta_prefs_get_gnome_animations (void) -{ - return gnome_animations; -} - -gboolean -meta_prefs_get_edge_tiling (void) -{ - return edge_tiling; -} - -gboolean -meta_prefs_get_auto_maximize (void) -{ - return auto_maximize; -} - -MetaKeyBindingAction -meta_prefs_get_keybinding_action (const char *name) -{ - MetaKeyPref *pref = g_hash_table_lookup (key_bindings, name); - - return pref ? pref->action - : META_KEYBINDING_ACTION_NONE; -} - -gint -meta_prefs_get_mouse_button_resize (void) -{ - return resize_with_right_button ? 3: 2; -} - -gint -meta_prefs_get_mouse_button_menu (void) -{ - return resize_with_right_button ? 2: 3; -} - -gboolean -meta_prefs_get_force_fullscreen (void) -{ - return force_fullscreen; -} - -gboolean -meta_prefs_get_workspaces_only_on_primary (void) -{ - return workspaces_only_on_primary; -} - -int -meta_prefs_get_draggable_border_width (void) -{ - return draggable_border_width; -} - -int -meta_prefs_get_drag_threshold (void) -{ - return drag_threshold; -} - -void -meta_prefs_set_force_fullscreen (gboolean whether) -{ - force_fullscreen = whether; -} diff --git a/src/core/restart-helper.c b/src/core/restart-helper.c deleted file mode 100644 index 68ede2671..000000000 --- a/src/core/restart-helper.c +++ /dev/null @@ -1,84 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * SECTION:restart-helper - * @short_description: helper program during a restart - * - * To smoothly restart Mutter, we want to keep the composite - * overlay window enabled during the restart. This is done by - * spawning this program, which keeps a reference to the the composite - * overlay window until Mutter picks it back up. - */ - -/* - * Copyright (C) 2014 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 . - */ - -#include "config.h" - -#include -#include -#include -#include - -int -main (int argc, - char **argv) -{ - Display *display = XOpenDisplay (NULL); - Window selection_window; - XSetWindowAttributes xwa; - unsigned long mask = 0; - - xwa.override_redirect = True; - mask |= CWOverrideRedirect; - - - XCompositeGetOverlayWindow (display, DefaultRootWindow (display)); - - selection_window = XCreateWindow (display, - DefaultRootWindow (display), - -100, -100, 1, 1, 0, - 0, - InputOnly, - DefaultVisual (display, DefaultScreen (display)), - mask, &xwa); - - XSetSelectionOwner (display, - XInternAtom (display, "_MUTTER_RESTART_HELPER", False), - selection_window, - CurrentTime); - - /* Mutter looks for an (arbitrary) line printed to stdout to know that - * we have started and have a reference to the COW. XSync() so that - * everything is set on the X server before Mutter starts restarting. - */ - XSync (display, False); - - printf ("STARTED\n"); - fflush (stdout); - - while (True) - { - XEvent xev; - - XNextEvent (display, &xev); - /* Mutter restarted and unset the selection to indicate that - * it has a reference on the COW again */ - if (xev.xany.type == SelectionClear) - return 0; - } -} diff --git a/src/core/restart.c b/src/core/restart.c deleted file mode 100644 index e9a5bfd27..000000000 --- a/src/core/restart.c +++ /dev/null @@ -1,201 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 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 . - */ - -/* - * SECTION:restart - * @short_description: Smoothly restart the compositor - * - * There are some cases where we need to restart Mutter in order - * to deal with changes in state - the particular case inspiring - * this is enabling or disabling stereo output. To make this - * fairly smooth for the user, we need to do two things: - * - * - Display a message to the user and make sure that it is - * actually painted before we exit. - * - Use a helper program so that the Composite Overlay Window - * isn't unmapped and mapped. - * - * This handles both of these. - */ - -#include "config.h" - -#include - -#include "clutter/clutter.h" -#include "core/display-private.h" -#include "core/util-private.h" -#include "meta/main.h" -#include "ui/ui.h" -#include "x11/meta-x11-display-private.h" - -static gboolean restart_helper_started = FALSE; -static gboolean restart_message_shown = FALSE; -static gboolean is_restart = FALSE; - -void -meta_set_is_restart (gboolean whether) -{ - is_restart = whether; -} - -static void -restart_check_ready (void) -{ - if (restart_helper_started && restart_message_shown) - { - MetaDisplay *display = meta_get_display (); - - if (!meta_display_request_restart (display)) - meta_display_show_restart_message (display, NULL); - } -} - -static void -restart_helper_read_line_callback (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - GError *error = NULL; - gsize length; - char *line = g_data_input_stream_read_line_finish_utf8 (G_DATA_INPUT_STREAM (source_object), - res, - &length, &error); - if (line == NULL) - { - meta_warning ("Failed to read output from restart helper%s%s", - error ? ": " : NULL, - error ? error->message : NULL); - } - else - g_free (line); /* We don't actually care what the restart helper outputs */ - - g_object_unref (source_object); - - restart_helper_started = TRUE; - restart_check_ready (); -} - -static gboolean -restart_message_painted (gpointer data) -{ - restart_message_shown = TRUE; - restart_check_ready (); - - return FALSE; -} - -/** - * meta_restart: - * @message: (allow-none): message to display to the user, or %NULL - * - * Starts the process of restarting the compositor. Note that Mutter's - * involvement here is to make the restart visually smooth for the - * user - it cannot itself safely reexec a program that embeds libmuttter. - * So in order for this to work, the compositor must handle two - * signals - MetaDisplay::show-restart-message, to display the - * message passed here on the Clutter stage, and ::restart to actually - * reexec the compositor. - */ -void -meta_restart (const char *message) -{ - MetaDisplay *display = meta_get_display(); - GInputStream *unix_stream; - GDataInputStream *data_stream; - GError *error = NULL; - int helper_out_fd; - - static const char * const helper_argv[] = { - MUTTER_LIBEXECDIR "/mutter-restart-helper", NULL - }; - - if (message && meta_display_show_restart_message (display, message)) - { - /* Wait until the stage was painted */ - clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT, - restart_message_painted, - NULL, NULL); - } - else - { - /* Can't show the message, show the message as soon as the - * restart helper starts - */ - restart_message_painted (NULL); - } - - /* We also need to wait for the restart helper to get its - * reference to the Composite Overlay Window. - */ - if (!g_spawn_async_with_pipes (NULL, /* working directory */ - (char **)helper_argv, - NULL, /* envp */ - G_SPAWN_DEFAULT, - NULL, NULL, /* child_setup */ - NULL, /* child_pid */ - NULL, /* standard_input */ - &helper_out_fd, - NULL, /* standard_error */ - &error)) - { - meta_warning ("Failed to start restart helper: %s", error->message); - goto error; - } - - unix_stream = g_unix_input_stream_new (helper_out_fd, TRUE); - data_stream = g_data_input_stream_new (unix_stream); - g_object_unref (unix_stream); - - g_data_input_stream_read_line_async (data_stream, G_PRIORITY_DEFAULT, - NULL, restart_helper_read_line_callback, - &error); - if (error != NULL) - { - meta_warning ("Failed to read from restart helper: %s", error->message); - g_object_unref (data_stream); - goto error; - } - - return; - - error: - /* If starting the restart helper fails, then we just go ahead and restart - * immediately. We won't get a smooth transition, since the overlay window - * will be destroyed and recreated, but otherwise it will work fine. - */ - restart_helper_started = TRUE; - restart_check_ready (); - - return; -} - -/** - * meta_is_restart: - * - * Returns %TRUE if this instance of Mutter comes from Mutter - * restarting itself (for example to enable/disable stereo.) - * See meta_restart(). If this is the case, any startup visuals - * or animations should be suppressed. - */ -gboolean -meta_is_restart (void) -{ - return is_restart; -} diff --git a/src/core/stack-tracker.c b/src/core/stack-tracker.c deleted file mode 100644 index fbfef6465..000000000 --- a/src/core/stack-tracker.c +++ /dev/null @@ -1,1293 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * SECTION:stack-tracker - * @short_description: Track stacking order for compositor - * - * #MetaStackTracker maintains the most accurate view we have at a - * given point of time of the ordering of the children of the root - * window (including override-redirect windows.) This is used to order - * the windows when the compositor draws them. - * - * By contrast, #MetaStack is responsible for keeping track of how we - * think that windows *should* be ordered. For windows we manage - * (non-override-redirect windows), the two stacking orders will be - * the same. - */ - -/* - * Copyright (C) 2009 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 . - */ - -#include "config.h" - -#include "core/stack-tracker.h" - -#include - -#include "core/display-private.h" -#include "core/frame.h" -#include "meta/compositor.h" -#include "meta/meta-x11-errors.h" -#include "meta/util.h" -#include "x11/meta-x11-display-private.h" - -/* The complexity here comes from resolving two competing factors: - * - * - We need to have a view of the stacking order that takes into - * account everything we have done without waiting for events - * back from the X server; we don't want to draw intermediate - * partially-stacked stack states just because we haven't received - * some notification yet. - * - * - Only the X server has an accurate view of the complete stacking; - * when we make a request to restack windows, we don't know how - * it will affect override-redirect windows, because at any point - * applications may restack these windows without our involvement. - * - * The technique we use is that we keep three sets of information: - * - * - The stacking order on the server as known from the last - * event we received. - * - A queue of stacking requests that *we* made subsequent to - * that last event. - * - A predicted stacking order, derived from applying the queued - * requests to the last state from the server. - * - * When we receive a new event: a) we compare the serial in the event to - * the serial of the queued requests and remove any that are now - * no longer pending b) if necessary, drop the predicted stacking - * order to recompute it at the next opportunity. - * - * Possible optimizations: - * Keep the stacks as an array + reverse-mapping hash table to avoid - * linear lookups. - * Keep the stacks as a GList + reverse-mapping hash table to avoid - * linear lookups and to make restacking constant-time. - */ - -typedef union _MetaStackOp MetaStackOp; - -typedef enum -{ - STACK_OP_ADD, - STACK_OP_REMOVE, - STACK_OP_RAISE_ABOVE, - STACK_OP_LOWER_BELOW -} MetaStackOpType; - -typedef enum -{ - APPLY_DEFAULT = 0, - /* Only do restacking that we can do locally without changing - * the order of X windows. After we've received any stack - * events from the X server, we apply the locally cached - * ops in this mode to handle the non-X parts */ - NO_RESTACK_X_WINDOWS = 1 << 0, - /* If the stacking operation wouldn't change the order of X - * windows, ignore it. We use this when applying events received - * from X so that a spontaneous ConfigureNotify (for a move, say) - * doesn't change the stacking of X windows with respect to - * Wayland windows. */ - IGNORE_NOOP_X_RESTACK = 1 << 1 -} ApplyFlags; - -/* MetaStackOp represents a "stacking operation" - a change to - * apply to a window stack. Depending on the context, it could - * either reflect a request we have sent to the server, or a - * notification event we received from the X server. - */ -union _MetaStackOp -{ - struct { - MetaStackOpType type; - gulong serial; - guint64 window; - } any; - struct { - MetaStackOpType type; - gulong serial; - guint64 window; - } add; - struct { - MetaStackOpType type; - gulong serial; - guint64 window; - } remove; - struct { - MetaStackOpType type; - gulong serial; - guint64 window; - guint64 sibling; - } raise_above; - struct { - MetaStackOpType type; - gulong serial; - guint64 window; - guint64 sibling; - } lower_below; -}; - -struct _MetaStackTracker -{ - MetaDisplay *display; - - /* This is the serial of the last request we made that was reflected - * in xserver_stack - */ - gulong xserver_serial; - - /* A combined stack containing X and Wayland windows but without - * any unverified operations applied. */ - GArray *verified_stack; - - /* This is a queue of requests we've made to change the stacking order, - * where we haven't yet gotten a reply back from the server. - */ - GQueue *unverified_predictions; - - /* This is how we think the stack is, based on verified_stack, and - * on the unverified_predictions we've made subsequent to - * verified_stack. - */ - GArray *predicted_stack; - - /* Idle function used to sync the compositor's view of the window - * stack up with our best guess before a frame is drawn. - */ - guint sync_stack_later; -}; - -static void -meta_stack_tracker_keep_override_redirect_on_top (MetaStackTracker *tracker); - -static inline const char * -get_window_desc (MetaStackTracker *tracker, - guint64 window) -{ - return meta_display_describe_stack_id (tracker->display, window); -} - -static void -meta_stack_op_dump (MetaStackTracker *tracker, - MetaStackOp *op, - const char *prefix, - const char *suffix) -{ -#ifdef WITH_VERBOSE_MODE - const char *window_desc = get_window_desc (tracker, op->any.window); -#endif - - switch (op->any.type) - { - case STACK_OP_ADD: - meta_topic (META_DEBUG_STACK, "%sADD(%s; %ld)%s", - prefix, window_desc, op->any.serial, suffix); - break; - case STACK_OP_REMOVE: - meta_topic (META_DEBUG_STACK, "%sREMOVE(%s; %ld)%s", - prefix, window_desc, op->any.serial, suffix); - break; - case STACK_OP_RAISE_ABOVE: - { - meta_topic (META_DEBUG_STACK, "%sRAISE_ABOVE(%s, %s; %ld)%s", - prefix, - window_desc, - get_window_desc (tracker, op->raise_above.sibling), - op->any.serial, - suffix); - break; - } - case STACK_OP_LOWER_BELOW: - { - meta_topic (META_DEBUG_STACK, "%sLOWER_BELOW(%s, %s; %ld)%s", - prefix, - window_desc, - get_window_desc (tracker, op->lower_below.sibling), - op->any.serial, - suffix); - break; - } - } -} - -#ifdef WITH_VERBOSE_MODE -static void -stack_dump (MetaStackTracker *tracker, - GArray *stack) -{ - guint i; - - meta_push_no_msg_prefix (); - for (i = 0; i < stack->len; i++) - { - guint64 window = g_array_index (stack, guint64, i); - meta_topic (META_DEBUG_STACK, " %s", get_window_desc (tracker, window)); - } - meta_pop_no_msg_prefix (); -} -#endif /* WITH_VERBOSE_MODE */ - -static void -meta_stack_tracker_dump (MetaStackTracker *tracker) -{ -#ifdef WITH_VERBOSE_MODE - GList *l; - - meta_topic (META_DEBUG_STACK, "MetaStackTracker state"); - meta_push_no_msg_prefix (); - meta_topic (META_DEBUG_STACK, " xserver_serial: %ld", tracker->xserver_serial); - meta_topic (META_DEBUG_STACK, " verified_stack: "); - stack_dump (tracker, tracker->verified_stack); - meta_topic (META_DEBUG_STACK, " unverified_predictions: ["); - for (l = tracker->unverified_predictions->head; l; l = l->next) - { - MetaStackOp *op = l->data; - meta_stack_op_dump (tracker, op, "", l->next ? ", " : ""); - } - meta_topic (META_DEBUG_STACK, "]"); - if (tracker->predicted_stack) - { - meta_topic (META_DEBUG_STACK, " predicted_stack: "); - stack_dump (tracker, tracker->predicted_stack); - } - meta_pop_no_msg_prefix (); -#endif /* WITH_VERBOSE_MODE */ -} - -static void -meta_stack_op_free (MetaStackOp *op) -{ - g_free (op); -} - -static int -find_window (GArray *window_stack, - guint64 window) -{ - guint i; - - for (i = 0; i < window_stack->len; i++) - { - guint64 current = g_array_index (window_stack, guint64, i); - if (current == window) - return i; - } - - return -1; -} - -/* Returns TRUE if stack was changed */ -static gboolean -move_window_above (GArray *stack, - guint64 window, - int old_pos, - int above_pos, - ApplyFlags apply_flags) -{ - int i; - gboolean can_restack_this_window = - (apply_flags & NO_RESTACK_X_WINDOWS) == 0 || !META_STACK_ID_IS_X11 (window); - - if (old_pos < above_pos) - { - if ((apply_flags & IGNORE_NOOP_X_RESTACK) != 0) - { - gboolean found_x_window = FALSE; - for (i = old_pos + 1; i <= above_pos; i++) - if (META_STACK_ID_IS_X11 (g_array_index (stack, guint64, i))) - found_x_window = TRUE; - - if (!found_x_window) - return FALSE; - } - - for (i = old_pos; i < above_pos; i++) - { - if (!can_restack_this_window && - META_STACK_ID_IS_X11 (g_array_index (stack, guint64, i + 1))) - break; - - g_array_index (stack, guint64, i) = - g_array_index (stack, guint64, i + 1); - } - - g_array_index (stack, guint64, i) = window; - - return i != old_pos; - } - else if (old_pos > above_pos + 1) - { - if ((apply_flags & IGNORE_NOOP_X_RESTACK) != 0) - { - gboolean found_x_window = FALSE; - for (i = above_pos + 1; i < old_pos; i++) - if (META_STACK_ID_IS_X11 (g_array_index (stack, guint64, i))) - found_x_window = TRUE; - - if (!found_x_window) - return FALSE; - } - - for (i = old_pos; i > above_pos + 1; i--) - { - if (!can_restack_this_window && - META_STACK_ID_IS_X11 (g_array_index (stack, guint64, i - 1))) - break; - - g_array_index (stack, guint64, i) = - g_array_index (stack, guint64, i - 1); - } - - g_array_index (stack, guint64, i) = window; - - return i != old_pos; - } - else - return FALSE; -} - -/* Returns TRUE if stack was changed */ -static gboolean -meta_stack_op_apply (MetaStackTracker *tracker, - MetaStackOp *op, - GArray *stack, - ApplyFlags apply_flags) -{ - switch (op->any.type) - { - case STACK_OP_ADD: - { - int old_pos; - - if (META_STACK_ID_IS_X11 (op->add.window) && - (apply_flags & NO_RESTACK_X_WINDOWS) != 0) - return FALSE; - - old_pos = find_window (stack, op->add.window); - if (old_pos >= 0) - { - meta_topic (META_DEBUG_STACK, - "STACK_OP_ADD: window %s already in stack", - get_window_desc (tracker, op->add.window)); - return FALSE; - } - - g_array_append_val (stack, op->add.window); - return TRUE; - } - case STACK_OP_REMOVE: - { - int old_pos; - - if (META_STACK_ID_IS_X11 (op->remove.window) && - (apply_flags & NO_RESTACK_X_WINDOWS) != 0) - return FALSE; - - old_pos = find_window (stack, op->remove.window); - if (old_pos < 0) - { - meta_topic (META_DEBUG_STACK, - "STACK_OP_REMOVE: window %s not in stack", - get_window_desc (tracker, op->remove.window)); - return FALSE; - } - - g_array_remove_index (stack, old_pos); - return TRUE; - } - case STACK_OP_RAISE_ABOVE: - { - int old_pos; - int above_pos; - - old_pos = find_window (stack, op->raise_above.window); - if (old_pos < 0) - { - meta_topic (META_DEBUG_STACK, - "STACK_OP_RAISE_ABOVE: window %s not in stack", - get_window_desc (tracker, op->raise_above.window)); - return FALSE; - } - - if (op->raise_above.sibling) - { - above_pos = find_window (stack, op->raise_above.sibling); - if (above_pos < 0) - { - meta_topic (META_DEBUG_STACK, - "STACK_OP_RAISE_ABOVE: sibling window %s not in stack", - get_window_desc (tracker, op->raise_above.sibling)); - return FALSE; - } - } - else - { - above_pos = -1; - } - - return move_window_above (stack, op->raise_above.window, old_pos, above_pos, - apply_flags); - } - case STACK_OP_LOWER_BELOW: - { - int old_pos; - int above_pos; - - old_pos = find_window (stack, op->raise_above.window); - if (old_pos < 0) - { - meta_topic (META_DEBUG_STACK, - "STACK_OP_LOWER_BELOW: window %s not in stack", - get_window_desc (tracker, op->lower_below.window)); - return FALSE; - } - - if (op->lower_below.sibling) - { - int below_pos; - - below_pos = find_window (stack, op->lower_below.sibling); - if (below_pos < 0) - { - meta_topic (META_DEBUG_STACK, - "STACK_OP_LOWER_BELOW: sibling window %s not in stack", - get_window_desc (tracker, op->lower_below.sibling)); - return FALSE; - } - - above_pos = below_pos - 1; - } - else - { - above_pos = stack->len - 1; - } - - return move_window_above (stack, op->lower_below.window, old_pos, above_pos, - apply_flags); - } - } - - g_assert_not_reached (); - return FALSE; -} - -static GArray * -copy_stack (GArray *stack) -{ - GArray *copy = g_array_sized_new (FALSE, FALSE, sizeof (guint64), stack->len); - - g_array_set_size (copy, stack->len); - - memcpy (copy->data, stack->data, sizeof (guint64) * stack->len); - - return copy; -} - -static void -query_xserver_stack (MetaDisplay *display, - MetaStackTracker *tracker) -{ - MetaX11Display *x11_display = display->x11_display; - Window ignored1, ignored2; - Window *children; - guint n_children; - guint i, old_len; - - tracker->xserver_serial = XNextRequest (x11_display->xdisplay); - - XQueryTree (x11_display->xdisplay, - x11_display->xroot, - &ignored1, &ignored2, &children, &n_children); - - old_len = tracker->verified_stack->len; - - g_array_set_size (tracker->verified_stack, old_len + n_children); - - for (i = 0; i < n_children; i++) - g_array_index (tracker->verified_stack, guint64, old_len + i) = children[i]; - - XFree (children); -} - -static void -drop_x11_windows (MetaDisplay *display, - MetaStackTracker *tracker) -{ - GArray *new_stack; - GList *l; - int i; - - tracker->xserver_serial = 0; - - new_stack = g_array_new (FALSE, FALSE, sizeof (guint64)); - - for (i = 0; i < tracker->verified_stack->len; i++) - { - guint64 window = g_array_index (tracker->verified_stack, guint64, i); - - if (!META_STACK_ID_IS_X11 (window)) - g_array_append_val (new_stack, window); - } - - g_array_unref (tracker->verified_stack); - tracker->verified_stack = new_stack; - l = tracker->unverified_predictions->head; - - while (l) - { - MetaStackOp *op = l->data; - GList *next = l->next; - - if (META_STACK_ID_IS_X11 (op->any.window)) - g_queue_remove (tracker->unverified_predictions, op); - - l = next; - } -} - -MetaStackTracker * -meta_stack_tracker_new (MetaDisplay *display) -{ - MetaStackTracker *tracker; - - tracker = g_new0 (MetaStackTracker, 1); - tracker->display = display; - - tracker->verified_stack = g_array_new (FALSE, FALSE, sizeof (guint64)); - tracker->unverified_predictions = g_queue_new (); - - g_signal_connect (display, - "x11-display-setup", - G_CALLBACK (query_xserver_stack), - tracker); - g_signal_connect (display, - "x11-display-closing", - G_CALLBACK (drop_x11_windows), - tracker); - - meta_stack_tracker_dump (tracker); - - return tracker; -} - -void -meta_stack_tracker_free (MetaStackTracker *tracker) -{ - if (tracker->sync_stack_later) - meta_later_remove (tracker->sync_stack_later); - - g_array_free (tracker->verified_stack, TRUE); - if (tracker->predicted_stack) - g_array_free (tracker->predicted_stack, TRUE); - - g_queue_foreach (tracker->unverified_predictions, (GFunc)meta_stack_op_free, NULL); - g_queue_free (tracker->unverified_predictions); - tracker->unverified_predictions = NULL; - - g_signal_handlers_disconnect_by_func (tracker->display, - (gpointer)query_xserver_stack, - tracker); - g_signal_handlers_disconnect_by_func (tracker->display, - drop_x11_windows, - tracker); - - g_free (tracker); -} - -static void -stack_tracker_apply_prediction (MetaStackTracker *tracker, - MetaStackOp *op) -{ - gboolean free_at_end = FALSE; - - /* If this operation doesn't involve restacking X windows then it's - * implicitly verified. We can apply it immediately unless there - * are outstanding X restacks that haven't yet been confirmed. - */ - if (op->any.serial == 0 && - tracker->unverified_predictions->length == 0) - { - if (meta_stack_op_apply (tracker, op, tracker->verified_stack, APPLY_DEFAULT)) - meta_stack_tracker_queue_sync_stack (tracker); - - free_at_end = TRUE; - } - else - { - meta_stack_op_dump (tracker, op, "Predicting: ", ""); - g_queue_push_tail (tracker->unverified_predictions, op); - } - - if (!tracker->predicted_stack || - meta_stack_op_apply (tracker, op, tracker->predicted_stack, APPLY_DEFAULT)) - meta_stack_tracker_queue_sync_stack (tracker); - - if (free_at_end) - meta_stack_op_free (op); - - meta_stack_tracker_dump (tracker); -} - -void -meta_stack_tracker_record_add (MetaStackTracker *tracker, - guint64 window, - gulong serial) -{ - MetaStackOp *op = g_new0 (MetaStackOp, 1); - - op->any.type = STACK_OP_ADD; - op->any.serial = serial; - op->any.window = window; - - stack_tracker_apply_prediction (tracker, op); -} - -void -meta_stack_tracker_record_remove (MetaStackTracker *tracker, - guint64 window, - gulong serial) -{ - MetaStackOp *op = g_new0 (MetaStackOp, 1); - - op->any.type = STACK_OP_REMOVE; - op->any.serial = serial; - op->any.window = window; - - stack_tracker_apply_prediction (tracker, op); -} - -static void -meta_stack_tracker_record_raise_above (MetaStackTracker *tracker, - guint64 window, - guint64 sibling, - gulong serial) -{ - MetaStackOp *op = g_new0 (MetaStackOp, 1); - - op->any.type = STACK_OP_RAISE_ABOVE; - op->any.serial = serial; - op->any.window = window; - op->raise_above.sibling = sibling; - - stack_tracker_apply_prediction (tracker, op); -} - -static void -meta_stack_tracker_record_lower_below (MetaStackTracker *tracker, - guint64 window, - guint64 sibling, - gulong serial) -{ - MetaStackOp *op = g_new0 (MetaStackOp, 1); - - op->any.type = STACK_OP_LOWER_BELOW; - op->any.serial = serial; - op->any.window = window; - op->lower_below.sibling = sibling; - - stack_tracker_apply_prediction (tracker, op); -} - -static void -stack_tracker_event_received (MetaStackTracker *tracker, - MetaStackOp *op) -{ - gboolean need_sync = FALSE; - - /* If the event is older than our initial query, then it's - * already included in our tree. Just ignore it. */ - if (op->any.serial < tracker->xserver_serial) - return; - - meta_stack_op_dump (tracker, op, "Stack op event received: ", ""); - - /* First we apply any operations that we have queued up that depended - * on X operations *older* than what we received .. those operations - * must have been ignored by the X server, so we just apply the - * operations we have as best as possible while not moving windows. - */ - while (tracker->unverified_predictions->head) - { - MetaStackOp *queued_op = tracker->unverified_predictions->head->data; - - if (queued_op->any.serial >= op->any.serial) - break; - - meta_stack_op_apply (tracker, queued_op, tracker->verified_stack, - NO_RESTACK_X_WINDOWS); - - g_queue_pop_head (tracker->unverified_predictions); - meta_stack_op_free (queued_op); - need_sync = TRUE; - } - - /* Then we apply the received event. If it's a spontaneous event - * based on stacking we didn't trigger, this is the only handling. If we - * triggered it, we do the X restacking here, and then any residual - * local-only Wayland stacking below. - */ - if (meta_stack_op_apply (tracker, op, tracker->verified_stack, - IGNORE_NOOP_X_RESTACK)) - need_sync = TRUE; - - /* What is left to process is the prediction corresponding to the event - * (if any), and then any subsequent Wayland-only events we can just - * go ahead and do now. - */ - while (tracker->unverified_predictions->head) - { - MetaStackOp *queued_op = tracker->unverified_predictions->head->data; - - if (queued_op->any.serial > op->any.serial) - break; - - meta_stack_op_apply (tracker, queued_op, tracker->verified_stack, - NO_RESTACK_X_WINDOWS); - - g_queue_pop_head (tracker->unverified_predictions); - meta_stack_op_free (queued_op); - need_sync = TRUE; - } - - if (need_sync) - { - if (tracker->predicted_stack) - { - g_array_free (tracker->predicted_stack, TRUE); - tracker->predicted_stack = NULL; - } - - meta_stack_tracker_queue_sync_stack (tracker); - } - - meta_stack_tracker_dump (tracker); -} - -void -meta_stack_tracker_create_event (MetaStackTracker *tracker, - XCreateWindowEvent *event) -{ - MetaStackOp op; - - op.any.type = STACK_OP_ADD; - op.any.serial = event->serial; - op.add.window = event->window; - - stack_tracker_event_received (tracker, &op); -} - -void -meta_stack_tracker_destroy_event (MetaStackTracker *tracker, - XDestroyWindowEvent *event) -{ - MetaStackOp op; - - op.any.type = STACK_OP_REMOVE; - op.any.serial = event->serial; - op.remove.window = event->window; - - stack_tracker_event_received (tracker, &op); -} - -void -meta_stack_tracker_reparent_event (MetaStackTracker *tracker, - XReparentEvent *event) -{ - if (event->parent == event->event) - { - MetaStackOp op; - - op.any.type = STACK_OP_ADD; - op.any.serial = event->serial; - op.add.window = event->window; - - stack_tracker_event_received (tracker, &op); - } - else - { - MetaStackOp op; - - op.any.type = STACK_OP_REMOVE; - op.any.serial = event->serial; - op.remove.window = event->window; - - stack_tracker_event_received (tracker, &op); - } -} - -void -meta_stack_tracker_configure_event (MetaStackTracker *tracker, - XConfigureEvent *event) -{ - MetaStackOp op; - - op.any.type = STACK_OP_RAISE_ABOVE; - op.any.serial = event->serial; - op.raise_above.window = event->window; - op.raise_above.sibling = event->above; - - stack_tracker_event_received (tracker, &op); -} - -static gboolean -meta_stack_tracker_is_guard_window (MetaStackTracker *tracker, - uint64_t stack_id) -{ - MetaX11Display *x11_display = tracker->display->x11_display; - - if (!x11_display) - return FALSE; - - return stack_id == x11_display->guard_window; -} - -/** - * meta_stack_tracker_get_stack: - * @tracker: a #MetaStackTracker - * @windows: location to store list of windows, or %NULL - * @n_windows: location to store count of windows, or %NULL - * - * @windows will contain the most current view we have of the stacking order - * of the children of the root window. The returned array contains - * everything: InputOnly windows, override-redirect windows, - * hidden windows, etc. Some of these will correspond to MetaWindow - * objects, others won't. - * - * Assuming that no other clients have made requests that change - * the stacking order since we last received a notification, the - * returned list of windows is exactly that you'd get as the - * children when calling XQueryTree() on the root window. - */ -void -meta_stack_tracker_get_stack (MetaStackTracker *tracker, - guint64 **windows, - int *n_windows) -{ - GArray *stack; - - if (tracker->unverified_predictions->length == 0) - { - stack = tracker->verified_stack; - } - else - { - if (tracker->predicted_stack == NULL) - { - GList *l; - - tracker->predicted_stack = copy_stack (tracker->verified_stack); - for (l = tracker->unverified_predictions->head; l; l = l->next) - { - MetaStackOp *op = l->data; - meta_stack_op_apply (tracker, op, tracker->predicted_stack, APPLY_DEFAULT); - } - } - - stack = tracker->predicted_stack; - } - - if (windows) - *windows = (guint64 *)stack->data; - if (n_windows) - *n_windows = stack->len; -} - -/** - * meta_stack_tracker_sync_stack: - * @tracker: a #MetaStackTracker - * - * Informs the compositor of the current stacking order of windows, - * based on the predicted view maintained by the #MetaStackTracker. - */ -void -meta_stack_tracker_sync_stack (MetaStackTracker *tracker) -{ - guint64 *windows; - GList *meta_windows; - int n_windows; - int i; - - if (tracker->sync_stack_later) - { - meta_later_remove (tracker->sync_stack_later); - tracker->sync_stack_later = 0; - } - - meta_stack_tracker_keep_override_redirect_on_top (tracker); - - meta_stack_tracker_get_stack (tracker, &windows, &n_windows); - - meta_windows = NULL; - for (i = 0; i < n_windows; i++) - { - guint64 window = windows[i]; - - if (META_STACK_ID_IS_X11 (window)) - { - MetaX11Display *x11_display = tracker->display->x11_display; - MetaWindow *meta_window = NULL; - - if (x11_display) - meta_window = meta_x11_display_lookup_x_window (x11_display, (Window) window); - - /* When mapping back from xwindow to MetaWindow we have to be a bit careful; - * children of the root could include unmapped windows created by toolkits - * for internal purposes, including ones that we have registered in our - * XID => window table. (Wine uses a toplevel for _NET_WM_USER_TIME_WINDOW; - * see window-prop.c:reload_net_wm_user_time_window() for registration.) - */ - if (meta_window && - ((Window)window == meta_window->xwindow || - (meta_window->frame && (Window)window == meta_window->frame->xwindow))) - meta_windows = g_list_prepend (meta_windows, meta_window); - } - else - meta_windows = g_list_prepend (meta_windows, - meta_display_lookup_stamp (tracker->display, window)); - } - - meta_compositor_sync_stack (tracker->display->compositor, - meta_windows); - g_list_free (meta_windows); - - meta_display_restacked (tracker->display); -} - -static gboolean -stack_tracker_sync_stack_later (gpointer data) -{ - meta_stack_tracker_sync_stack (data); - - return FALSE; -} - -/** - * meta_stack_tracker_queue_sync_stack: - * @tracker: a #MetaStackTracker - * - * Queue informing the compositor of the new stacking order before the - * next redraw. (See meta_stack_tracker_sync_stack()). This is called - * internally when the stack of X windows changes, but also needs be - * called directly when we an undecorated window is first shown or - * withdrawn since the compositor's stacking order (which contains only - * the windows that have a corresponding MetaWindow) will change without - * any change to the stacking order of the X windows, if we are creating - * or destroying MetaWindows. - */ -void -meta_stack_tracker_queue_sync_stack (MetaStackTracker *tracker) -{ - if (tracker->sync_stack_later == 0) - { - tracker->sync_stack_later = meta_later_add (META_LATER_SYNC_STACK, - stack_tracker_sync_stack_later, - tracker, NULL); - } -} - -/* When moving an X window we sometimes need an X based sibling. - * - * If the given sibling is X based this function returns it back - * otherwise it searches downwards looking for the nearest X window. - * - * If no X based sibling could be found return NULL. */ -static Window -find_x11_sibling_downwards (MetaStackTracker *tracker, - guint64 sibling) -{ - guint64 *windows; - int n_windows; - int i; - - if (META_STACK_ID_IS_X11 (sibling)) - return (Window)sibling; - - meta_stack_tracker_get_stack (tracker, - &windows, &n_windows); - - /* NB: Children are in order from bottom to top and we - * want to search downwards for the nearest X window. - */ - - for (i = n_windows - 1; i >= 0; i--) - if (windows[i] == sibling) - break; - - for (; i >= 0; i--) - { - if (META_STACK_ID_IS_X11 (windows[i])) - return (Window)windows[i]; - } - - return None; -} - -static Window -find_x11_sibling_upwards (MetaStackTracker *tracker, - guint64 sibling) -{ - guint64 *windows; - int n_windows; - int i; - - if (META_STACK_ID_IS_X11 (sibling)) - return (Window)sibling; - - meta_stack_tracker_get_stack (tracker, - &windows, &n_windows); - - for (i = 0; i < n_windows; i++) - if (windows[i] == sibling) - break; - - for (; i < n_windows; i++) - { - if (META_STACK_ID_IS_X11 (windows[i])) - return (Window)windows[i]; - } - - return None; -} - -static void -meta_stack_tracker_lower_below (MetaStackTracker *tracker, - guint64 window, - guint64 sibling) -{ - gulong serial = 0; - MetaX11Display *x11_display = tracker->display->x11_display; - - if (META_STACK_ID_IS_X11 (window)) - { - XWindowChanges changes; - changes.sibling = sibling ? find_x11_sibling_upwards (tracker, sibling) : None; - - if (changes.sibling != find_x11_sibling_upwards (tracker, window)) - { - serial = XNextRequest (x11_display->xdisplay); - - meta_x11_error_trap_push (x11_display); - - changes.stack_mode = changes.sibling ? Below : Above; - - XConfigureWindow (x11_display->xdisplay, - window, - (changes.sibling ? CWSibling : 0) | CWStackMode, - &changes); - - meta_x11_error_trap_pop (x11_display); - } - } - - meta_stack_tracker_record_lower_below (tracker, - window, sibling, - serial); -} - -static void -meta_stack_tracker_raise_above (MetaStackTracker *tracker, - guint64 window, - guint64 sibling) -{ - gulong serial = 0; - MetaX11Display *x11_display = tracker->display->x11_display; - - if (META_STACK_ID_IS_X11 (window)) - { - XWindowChanges changes; - changes.sibling = sibling ? find_x11_sibling_downwards (tracker, sibling) : None; - - if (changes.sibling != find_x11_sibling_downwards (tracker, window)) - { - serial = XNextRequest (x11_display->xdisplay); - - meta_x11_error_trap_push (x11_display); - - changes.stack_mode = changes.sibling ? Above : Below; - - XConfigureWindow (x11_display->xdisplay, - (Window)window, - (changes.sibling ? CWSibling : 0) | CWStackMode, - &changes); - - meta_x11_error_trap_pop (x11_display); - } - } - - meta_stack_tracker_record_raise_above (tracker, window, - sibling, serial); -} - -void -meta_stack_tracker_lower (MetaStackTracker *tracker, - guint64 window) -{ - meta_stack_tracker_raise_above (tracker, window, None); -} - -static void -meta_stack_tracker_keep_override_redirect_on_top (MetaStackTracker *tracker) -{ - guint64 *stack; - int n_windows, i; - int topmost_non_or; - - meta_stack_tracker_get_stack (tracker, &stack, &n_windows); - - for (i = n_windows - 1; i >= 0; i--) - { - MetaWindow *window; - - window = meta_display_lookup_stack_id (tracker->display, stack[i]); - if (window && window->layer != META_LAYER_OVERRIDE_REDIRECT) - break; - } - - topmost_non_or = i; - - for (i -= 1; i >= 0; i--) - { - MetaWindow *window; - - if (meta_stack_tracker_is_guard_window (tracker, stack[i])) - break; - - window = meta_display_lookup_stack_id (tracker->display, stack[i]); - if (window && window->layer == META_LAYER_OVERRIDE_REDIRECT) - { - meta_stack_tracker_raise_above (tracker, stack[i], stack[topmost_non_or]); - meta_stack_tracker_get_stack (tracker, &stack, &n_windows); - topmost_non_or -= 1; - } - } -} - -void -meta_stack_tracker_restack_managed (MetaStackTracker *tracker, - const guint64 *managed, - int n_managed) -{ - guint64 *windows; - int n_windows; - int old_pos, new_pos; - - COGL_TRACE_BEGIN_SCOPED (StackTrackerRestackManaged, - "StackTracker: Restack Managed"); - if (n_managed == 0) - return; - - COGL_TRACE_BEGIN (StackTrackerRestackManagedGet, - "StackTracker: Restack Managed (get)"); - meta_stack_tracker_get_stack (tracker, &windows, &n_windows); - - /* If the top window has to be restacked, we don't want to move it to the very - * top of the stack, since apps expect override-redirect windows to stay near - * the top of the X stack; we instead move it above all managed windows (or - * above the guard window if there are no non-hidden managed windows.) - */ - old_pos = n_windows - 1; - for (old_pos = n_windows - 1; old_pos >= 0; old_pos--) - { - MetaWindow *old_window = meta_display_lookup_stack_id (tracker->display, windows[old_pos]); - if ((old_window && !old_window->override_redirect && !old_window->unmanaging) || - meta_stack_tracker_is_guard_window (tracker, windows[old_pos])) - break; - } - g_assert (old_pos >= 0); - COGL_TRACE_END (StackTrackerRestackManagedGet); - - COGL_TRACE_BEGIN (StackTrackerRestackManagedRaise, - "StackTracker: Restack Managed (raise)"); - new_pos = n_managed - 1; - if (managed[new_pos] != windows[old_pos]) - { - /* Move the first managed window in the new stack above all managed windows */ - meta_stack_tracker_raise_above (tracker, managed[new_pos], windows[old_pos]); - meta_stack_tracker_get_stack (tracker, &windows, &n_windows); - /* Moving managed[new_pos] above windows[old_pos], moves the window at old_pos down by one */ - } - COGL_TRACE_END (StackTrackerRestackManagedRaise); - - old_pos--; - new_pos--; - - COGL_TRACE_BEGIN (StackTrackerRestackManagedRestack, - "StackTracker: Restack Managed (restack)"); - while (old_pos >= 0 && new_pos >= 0) - { - if (meta_stack_tracker_is_guard_window (tracker, windows[old_pos])) - break; - - if (windows[old_pos] == managed[new_pos]) - { - old_pos--; - new_pos--; - continue; - } - - MetaWindow *old_window = meta_display_lookup_stack_id (tracker->display, windows[old_pos]); - if (!old_window || old_window->override_redirect || old_window->unmanaging) - { - old_pos--; - continue; - } - - meta_stack_tracker_lower_below (tracker, managed[new_pos], managed[new_pos + 1]); - meta_stack_tracker_get_stack (tracker, &windows, &n_windows); - /* Moving managed[new_pos] above windows[old_pos] moves the window at old_pos down by one, - * we'll examine it again to see if it matches the next new window */ - old_pos--; - new_pos--; - } - COGL_TRACE_END (StackTrackerRestackManagedRestack); - - COGL_TRACE_BEGIN (StackTrackerRestackManagedLower, - "StackTracker: Restack Managed (lower)"); - while (new_pos > 0) - { - meta_stack_tracker_lower_below (tracker, managed[new_pos], managed[new_pos - 1]); - new_pos--; - } - COGL_TRACE_END (StackTrackerRestackManagedLower); -} - -void -meta_stack_tracker_restack_at_bottom (MetaStackTracker *tracker, - const guint64 *new_order, - int n_new_order) -{ - guint64 *windows; - int n_windows; - int pos; - - COGL_TRACE_BEGIN_SCOPED (StackTrackerRestackAtBottom, - "Stack tracker: Restack at bottom"); - meta_stack_tracker_get_stack (tracker, &windows, &n_windows); - - for (pos = 0; pos < n_new_order; pos++) - { - if (pos >= n_windows || windows[pos] != new_order[pos]) - { - if (pos == 0) - meta_stack_tracker_lower (tracker, new_order[pos]); - else - meta_stack_tracker_raise_above (tracker, new_order[pos], new_order[pos - 1]); - - meta_stack_tracker_get_stack (tracker, &windows, &n_windows); - } - } -} diff --git a/src/core/stack-tracker.h b/src/core/stack-tracker.h deleted file mode 100644 index dbffb0e5e..000000000 --- a/src/core/stack-tracker.h +++ /dev/null @@ -1,87 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/** - * \file stack-tracker.h Track stacking order for compositor - * - * MetaStackTracker maintains the most accurate view we have at a - * given point of time of the ordering of the children of the root - * window (including override-redirect windows.) This is used to order - * the windows when the compositor draws them. - * - * By contrast, MetaStack is responsible for keeping track of how we - * think that windows *should* be ordered. For windows we manage - * (non-override-redirect windows), the two stacking orders will be - * the same. - */ - -/* - * Copyright (C) 2009 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 . - */ - -#ifndef META_STACK_TRACKER_H -#define META_STACK_TRACKER_H - -#include "core/util-private.h" -#include "meta/display.h" -#include "meta/window.h" - -typedef struct _MetaStackTracker MetaStackTracker; - -MetaStackTracker *meta_stack_tracker_new (MetaDisplay *display); -void meta_stack_tracker_free (MetaStackTracker *tracker); - -/* These functions are called when we make an X call that changes the - * stacking order; this allows MetaStackTracker to predict stacking - * order before it receives events back from the X server */ -void meta_stack_tracker_record_add (MetaStackTracker *tracker, - guint64 window, - gulong serial); -void meta_stack_tracker_record_remove (MetaStackTracker *tracker, - guint64 window, - gulong serial); - -/* We also have functions that also go ahead and do the work - */ -void meta_stack_tracker_lower (MetaStackTracker *tracker, - guint64 window); - -void meta_stack_tracker_restack_managed (MetaStackTracker *tracker, - const guint64 *windows, - int n_windows); -void meta_stack_tracker_restack_at_bottom (MetaStackTracker *tracker, - const guint64 *new_order, - int n_new_order); - -/* These functions are used to update the stack when we get events - * reflecting changes to the stacking order */ -void meta_stack_tracker_create_event (MetaStackTracker *tracker, - XCreateWindowEvent *event); -void meta_stack_tracker_destroy_event (MetaStackTracker *tracker, - XDestroyWindowEvent *event); -void meta_stack_tracker_reparent_event (MetaStackTracker *tracker, - XReparentEvent *event); -void meta_stack_tracker_configure_event (MetaStackTracker *tracker, - XConfigureEvent *event); - -META_EXPORT_TEST -void meta_stack_tracker_get_stack (MetaStackTracker *tracker, - guint64 **windows, - int *n_entries); - -void meta_stack_tracker_sync_stack (MetaStackTracker *tracker); -void meta_stack_tracker_queue_sync_stack (MetaStackTracker *tracker); - -#endif /* META_STACK_TRACKER_H */ diff --git a/src/core/stack.c b/src/core/stack.c deleted file mode 100644 index 62b8954e8..000000000 --- a/src/core/stack.c +++ /dev/null @@ -1,1340 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * SECTION:stack - * @short_description: Which windows cover which other windows - */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002, 2003 Red Hat, Inc. - * Copyright (C) 2004 Rob Adams - * Copyright (C) 2004, 2005 Elijah Newren - * - * 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 . - */ - -#include "config.h" - -#include "core/stack.h" - -#include "backends/meta-logical-monitor.h" -#include "cogl/cogl.h" -#include "core/frame.h" -#include "core/meta-workspace-manager-private.h" -#include "core/window-private.h" -#include "meta/group.h" -#include "meta/prefs.h" -#include "meta/workspace.h" -#include "x11/meta-x11-display-private.h" - -#define WINDOW_TRANSIENT_FOR_WHOLE_GROUP(w) \ - (meta_window_has_transient_type (w) && w->transient_for == NULL) - -static void meta_window_set_stack_position_no_sync (MetaWindow *window, - int position); -static void stack_do_relayer (MetaStack *stack); -static void stack_do_constrain (MetaStack *stack); -static void stack_do_resort (MetaStack *stack); -static void stack_ensure_sorted (MetaStack *stack); - -enum -{ - PROP_DISPLAY = 1, - N_PROPS -}; - -enum -{ - CHANGED, - WINDOW_ADDED, - WINDOW_REMOVED, - N_SIGNALS -}; - -static GParamSpec *pspecs[N_PROPS] = { 0 }; -static guint signals[N_SIGNALS] = { 0 }; - -G_DEFINE_TYPE (MetaStack, meta_stack, G_TYPE_OBJECT) - -static void -on_stack_changed (MetaStack *stack) -{ - MetaDisplay *display = stack->display; - GArray *all_root_children_stacked; - GList *l; - GArray *hidden_stack_ids; - GList *sorted; - - COGL_TRACE_BEGIN_SCOPED (StackChanged, "Stack changed"); - - meta_topic (META_DEBUG_STACK, "Syncing window stack to server"); - - all_root_children_stacked = g_array_new (FALSE, FALSE, sizeof (uint64_t)); - hidden_stack_ids = g_array_new (FALSE, FALSE, sizeof (uint64_t)); - - meta_topic (META_DEBUG_STACK, "Bottom to top: "); - meta_push_no_msg_prefix (); - - sorted = meta_stack_list_windows (stack, NULL); - - for (l = sorted; l; l = l->next) - { - MetaWindow *w = l->data; - uint64_t top_level_window; - uint64_t stack_id; - - if (w->unmanaging) - continue; - - meta_topic (META_DEBUG_STACK, " %u:%d - %s ", - w->layer, w->stack_position, w->desc); - - if (w->frame) - top_level_window = w->frame->xwindow; - else - top_level_window = w->xwindow; - - if (w->client_type == META_WINDOW_CLIENT_TYPE_X11) - stack_id = top_level_window; - else - stack_id = w->stamp; - - /* We don't restack hidden windows along with the rest, though they are - * reflected in the _NET hints. Hidden windows all get pushed below - * the screens fullscreen guard_window. */ - if (w->hidden) - { - g_array_append_val (hidden_stack_ids, stack_id); - continue; - } - - g_array_append_val (all_root_children_stacked, stack_id); - } - - meta_pop_no_msg_prefix (); - - if (display->x11_display) - { - uint64_t guard_window_id; - - /* The screen guard window sits above all hidden windows and acts as - * a barrier to input reaching these windows. */ - guard_window_id = display->x11_display->guard_window; - g_array_append_val (hidden_stack_ids, guard_window_id); - } - - /* Sync to server */ - - meta_topic (META_DEBUG_STACK, "Restacking %u windows", - all_root_children_stacked->len); - - meta_stack_tracker_restack_managed (display->stack_tracker, - (uint64_t *)all_root_children_stacked->data, - all_root_children_stacked->len); - meta_stack_tracker_restack_at_bottom (display->stack_tracker, - (uint64_t *)hidden_stack_ids->data, - hidden_stack_ids->len); - - g_array_free (hidden_stack_ids, TRUE); - g_array_free (all_root_children_stacked, TRUE); - g_list_free (sorted); -} - -static void -meta_stack_init (MetaStack *stack) -{ - g_signal_connect (stack, "changed", - G_CALLBACK (on_stack_changed), NULL); -} - -static void -meta_stack_finalize (GObject *object) -{ - MetaStack *stack = META_STACK (object); - - g_list_free (stack->sorted); - - G_OBJECT_CLASS (meta_stack_parent_class)->finalize (object); -} - -static void -meta_stack_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaStack *stack = META_STACK (object); - - switch (prop_id) - { - case PROP_DISPLAY: - stack->display = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_stack_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaStack *stack = META_STACK (object); - - switch (prop_id) - { - case PROP_DISPLAY: - g_value_set_object (value, stack->display); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_stack_class_init (MetaStackClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->set_property = meta_stack_set_property; - object_class->get_property = meta_stack_get_property; - object_class->finalize = meta_stack_finalize; - - signals[CHANGED] = - g_signal_new ("changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); - signals[WINDOW_ADDED] = - g_signal_new ("window-added", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, META_TYPE_WINDOW); - signals[WINDOW_REMOVED] = - g_signal_new ("window-removed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, META_TYPE_WINDOW); - - pspecs[PROP_DISPLAY] = - g_param_spec_object ("display", - "Display", - "Display", - META_TYPE_DISPLAY, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - - g_object_class_install_properties (object_class, N_PROPS, pspecs); -} - -MetaStack * -meta_stack_new (MetaDisplay *display) -{ - return g_object_new (META_TYPE_STACK, - "display", display, - NULL); -} - -static void -meta_stack_changed (MetaStack *stack) -{ - /* Bail out if frozen */ - if (stack->freeze_count > 0) - return; - - COGL_TRACE_BEGIN_SCOPED (MetaStackChangedSort, "Stack: Changed"); - - stack_ensure_sorted (stack); - g_signal_emit (stack, signals[CHANGED], 0); -} - -void -meta_stack_add (MetaStack *stack, - MetaWindow *window) -{ - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - - COGL_TRACE_BEGIN_SCOPED (MetaStackAdd, - "Stack (add window)"); - - g_return_if_fail (meta_window_is_stackable (window)); - - meta_topic (META_DEBUG_STACK, "Adding window %s to the stack", window->desc); - - if (meta_window_is_in_stack (window)) - meta_bug ("Window %s had stack position already", window->desc); - - stack->sorted = g_list_prepend (stack->sorted, window); - stack->need_resort = TRUE; /* may not be needed as we add to top */ - stack->need_constrain = TRUE; - stack->need_relayer = TRUE; - - g_signal_emit (stack, signals[WINDOW_ADDED], 0, window); - - window->stack_position = stack->n_positions; - stack->n_positions += 1; - meta_topic (META_DEBUG_STACK, - "Window %s has stack_position initialized to %d", - window->desc, window->stack_position); - - meta_stack_changed (stack); - meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace); -} - -void -meta_stack_remove (MetaStack *stack, - MetaWindow *window) -{ - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - - COGL_TRACE_BEGIN_SCOPED (MetaStackRemove, - "Stack (remove window)"); - - meta_topic (META_DEBUG_STACK, "Removing window %s from the stack", window->desc); - - /* Set window to top position, so removing it will not leave gaps - * in the set of positions - */ - meta_window_set_stack_position_no_sync (window, - stack->n_positions - 1); - window->stack_position = -1; - stack->n_positions -= 1; - - stack->sorted = g_list_remove (stack->sorted, window); - - g_signal_emit (stack, signals[WINDOW_REMOVED], 0, window); - - meta_stack_changed (stack); - meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace); -} - -void -meta_stack_update_layer (MetaStack *stack, - MetaWindow *window) -{ - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - stack->need_relayer = TRUE; - - meta_stack_changed (stack); - meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace); -} - -void -meta_stack_update_transient (MetaStack *stack, - MetaWindow *window) -{ - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - stack->need_constrain = TRUE; - - meta_stack_changed (stack); - meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace); -} - -/* raise/lower within a layer */ -void -meta_stack_raise (MetaStack *stack, - MetaWindow *window) -{ - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - GList *l; - int max_stack_position = window->stack_position; - MetaWorkspace *workspace; - - stack_ensure_sorted (stack); - - workspace = meta_window_get_workspace (window); - for (l = stack->sorted; l; l = l->next) - { - MetaWindow *w = (MetaWindow *) l->data; - if (meta_window_located_on_workspace (w, workspace) && - w->stack_position > max_stack_position) - max_stack_position = w->stack_position; - } - - if (max_stack_position == window->stack_position) - return; - - meta_window_set_stack_position_no_sync (window, max_stack_position); - - meta_stack_changed (stack); - meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace); -} - -void -meta_stack_lower (MetaStack *stack, - MetaWindow *window) -{ - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - GList *l; - int min_stack_position = window->stack_position; - MetaWorkspace *workspace; - - stack_ensure_sorted (stack); - - workspace = meta_window_get_workspace (window); - for (l = stack->sorted; l; l = l->next) - { - MetaWindow *w = (MetaWindow *) l->data; - if (meta_window_located_on_workspace (w, workspace) && - w->stack_position < min_stack_position) - min_stack_position = w->stack_position; - } - - if (min_stack_position == window->stack_position) - return; - - meta_window_set_stack_position_no_sync (window, min_stack_position); - - meta_stack_changed (stack); - meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace); -} - -void -meta_stack_freeze (MetaStack *stack) -{ - stack->freeze_count += 1; -} - -void -meta_stack_thaw (MetaStack *stack) -{ - g_return_if_fail (stack->freeze_count > 0); - - stack->freeze_count -= 1; - meta_stack_changed (stack); - meta_stack_update_window_tile_matches (stack, NULL); -} - -void -meta_stack_update_window_tile_matches (MetaStack *stack, - MetaWorkspace *workspace) -{ - GList *windows, *tmp; - - if (stack->freeze_count > 0) - return; - - windows = meta_stack_list_windows (stack, workspace); - tmp = windows; - while (tmp) - { - meta_window_compute_tile_match ((MetaWindow *) tmp->data); - tmp = tmp->next; - } - - g_list_free (windows); -} - -/* Front of the layer list is the topmost window, - * so the lower stack position is later in the list - */ -static int -compare_window_position (void *a, - void *b) -{ - MetaWindow *window_a = a; - MetaWindow *window_b = b; - - /* Go by layer, then stack_position */ - if (window_a->layer < window_b->layer) - return 1; /* move window_a later in list */ - else if (window_a->layer > window_b->layer) - return -1; - else if (window_a->stack_position < window_b->stack_position) - return 1; /* move window_a later in list */ - else if (window_a->stack_position > window_b->stack_position) - return -1; - else - return 0; /* not reached */ -} - -/* - * Stacking constraints - * - * Assume constraints of the form "AB" meaning "window A must be - * below window B" - * - * If we have windows stacked from bottom to top - * "ABC" then raise A we get "BCA". Say C is - * transient for B is transient for A. So - * we have constraints AB and BC. - * - * After raising A, we need to reapply the constraints. - * If we do this by raising one window at a time - - * - * start: BCA - * apply AB: CAB - * apply BC: ABC - * - * but apply constraints in the wrong order and it breaks: - * - * start: BCA - * apply BC: BCA - * apply AB: CAB - * - * We make a directed graph of the constraints by linking - * from "above windows" to "below windows as follows: - * - * AB -> BC -> CD - * \ - * CE - * - * If we then walk that graph and apply the constraints in the order - * that they appear, we will apply them correctly. Note that the - * graph MAY have cycles, so we have to guard against that. - * - */ - -typedef struct Constraint Constraint; - -struct Constraint -{ - MetaWindow *above; - MetaWindow *below; - - /* used to keep the constraint in the - * list of constraints for window "below" - */ - Constraint *next; - - /* used to create the graph. */ - GSList *next_nodes; - - /* constraint has been applied, used - * to detect cycles. - */ - unsigned int applied : 1; - - /* constraint has a previous node in the graph, - * used to find places to start in the graph. - * (I think this also has the side effect - * of preventing cycles, since cycles will - * have no starting point - so maybe - * the "applied" flag isn't needed.) - */ - unsigned int has_prev : 1; -}; - -/* We index the array of constraints by window - * stack positions, just because the stack - * positions are a convenient index. - */ -static void -add_constraint (Constraint **constraints, - MetaWindow *above, - MetaWindow *below) -{ - Constraint *c; - - /* check if constraint is a duplicate */ - c = constraints[below->stack_position]; - while (c != NULL) - { - if (c->above == above) - return; - c = c->next; - } - - /* if not, add the constraint */ - c = g_new (Constraint, 1); - c->above = above; - c->below = below; - c->next = constraints[below->stack_position]; - c->next_nodes = NULL; - c->applied = FALSE; - c->has_prev = FALSE; - - constraints[below->stack_position] = c; -} - -static void -create_constraints (Constraint **constraints, - GList *windows) -{ - GList *tmp; - - tmp = windows; - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - - if (!meta_window_is_in_stack (w)) - { - meta_topic (META_DEBUG_STACK, "Window %s not in the stack, not constraining it", - w->desc); - tmp = tmp->next; - continue; - } - - if (WINDOW_TRANSIENT_FOR_WHOLE_GROUP (w)) - { - GSList *group_windows; - GSList *tmp2; - MetaGroup *group; - - group = meta_window_get_group (w); - - if (group != NULL) - group_windows = meta_group_list_windows (group); - else - group_windows = NULL; - - tmp2 = group_windows; - - while (tmp2 != NULL) - { - MetaWindow *group_window = tmp2->data; - - if (!meta_window_is_in_stack (group_window) || - group_window->override_redirect) - { - tmp2 = tmp2->next; - continue; - } - -#if 0 - /* old way of doing it */ - if (!(meta_window_is_ancestor_of_transient (w, group_window)) && - !WINDOW_TRANSIENT_FOR_WHOLE_GROUP (group_window)) /* note */;/*note*/ -#else - /* better way I think, so transient-for-group are constrained - * only above non-transient-type windows in their group - */ - if (!meta_window_has_transient_type (group_window)) -#endif - { - meta_topic (META_DEBUG_STACK, - "Constraining %s above %s as it's transient for its group", - w->desc, group_window->desc); - add_constraint (constraints, w, group_window); - } - - tmp2 = tmp2->next; - } - - g_slist_free (group_windows); - } - else if (w->transient_for != NULL) - { - MetaWindow *parent; - - parent = w->transient_for; - - if (parent && meta_window_is_in_stack (parent)) - { - meta_topic (META_DEBUG_STACK, - "Constraining %s above %s due to transiency", - w->desc, parent->desc); - add_constraint (constraints, w, parent); - } - } - - tmp = tmp->next; - } -} - -static void -graph_constraints (Constraint **constraints, - int n_constraints) -{ - int i; - - i = 0; - while (i < n_constraints) - { - Constraint *c; - - /* If we have "A below B" and "B below C" then AB -> BC so we - * add BC to next_nodes in AB. - */ - - c = constraints[i]; - while (c != NULL) - { - Constraint *n; - - g_assert (c->below->stack_position == i); - - /* Constraints where ->above is below are our - * next_nodes and we are their previous - */ - n = constraints[c->above->stack_position]; - while (n != NULL) - { - c->next_nodes = g_slist_prepend (c->next_nodes, - n); - /* c is a previous node of n */ - n->has_prev = TRUE; - - n = n->next; - } - - c = c->next; - } - - ++i; - } -} - -static void -free_constraints (Constraint **constraints, - int n_constraints) -{ - int i; - - i = 0; - while (i < n_constraints) - { - Constraint *c; - - c = constraints[i]; - while (c != NULL) - { - Constraint *next = c->next; - - g_slist_free (c->next_nodes); - - g_free (c); - - c = next; - } - - ++i; - } -} - -static void -ensure_above (MetaWindow *above, - MetaWindow *below) -{ - gboolean is_transient; - - is_transient = meta_window_has_transient_type (above) || - above->transient_for == below; - if (is_transient && above->layer < below->layer) - { - meta_topic (META_DEBUG_STACK, - "Promoting window %s from layer %u to %u due to constraint", - above->desc, above->layer, below->layer); - above->layer = below->layer; - } - - if (above->stack_position < below->stack_position) - { - /* move above to below->stack_position bumping below down the stack */ - meta_window_set_stack_position_no_sync (above, below->stack_position); - g_assert (below->stack_position + 1 == above->stack_position); - } - meta_topic (META_DEBUG_STACK, "%s above at %d > %s below at %d", - above->desc, above->stack_position, - below->desc, below->stack_position); -} - -static void -traverse_constraint (Constraint *c) -{ - GSList *tmp; - - if (c->applied) - return; - - ensure_above (c->above, c->below); - c->applied = TRUE; - - tmp = c->next_nodes; - while (tmp != NULL) - { - traverse_constraint (tmp->data); - - tmp = tmp->next; - } -} - -static void -apply_constraints (Constraint **constraints, - int n_constraints) -{ - GSList *heads; - GSList *tmp; - int i; - - /* List all heads in an ordered constraint chain */ - heads = NULL; - i = 0; - while (i < n_constraints) - { - Constraint *c; - - c = constraints[i]; - while (c != NULL) - { - if (!c->has_prev) - heads = g_slist_prepend (heads, c); - - c = c->next; - } - - ++i; - } - - /* Now traverse the chain and apply constraints */ - tmp = heads; - while (tmp != NULL) - { - Constraint *c = tmp->data; - - traverse_constraint (c); - - tmp = tmp->next; - } - - g_slist_free (heads); -} - -/** - * stack_do_relayer: - * - * Update the layers that windows are in - */ -static void -stack_do_relayer (MetaStack *stack) -{ - GList *tmp; - - if (!stack->need_relayer) - return; - - meta_topic (META_DEBUG_STACK, - "Recomputing layers"); - - tmp = stack->sorted; - - while (tmp != NULL) - { - MetaWindow *w; - MetaStackLayer old_layer; - - w = tmp->data; - old_layer = w->layer; - - w->layer = meta_window_calculate_layer (w); - - if (w->layer != old_layer) - { - meta_topic (META_DEBUG_STACK, - "Window %s moved from layer %u to %u", - w->desc, old_layer, w->layer); - stack->need_resort = TRUE; - stack->need_constrain = TRUE; - /* don't need to constrain as constraining - * purely operates in terms of stack_position - * not layer - */ - } - - tmp = tmp->next; - } - - stack->need_relayer = FALSE; -} - -/** - * stack_do_constrain: - * - * Update stack_position and layer to reflect transiency - * constraints - */ -static void -stack_do_constrain (MetaStack *stack) -{ - Constraint **constraints; - - /* It'd be nice if this were all faster, probably */ - - if (!stack->need_constrain) - return; - - meta_topic (META_DEBUG_STACK, - "Reapplying constraints"); - - constraints = g_new0 (Constraint*, - stack->n_positions); - - create_constraints (constraints, stack->sorted); - - graph_constraints (constraints, stack->n_positions); - - apply_constraints (constraints, stack->n_positions); - - free_constraints (constraints, stack->n_positions); - g_free (constraints); - - stack->need_constrain = FALSE; -} - -/** - * stack_do_resort: - * - * Sort stack->sorted with layers having priority over stack_position. - */ -static void -stack_do_resort (MetaStack *stack) -{ - if (!stack->need_resort) - return; - - meta_topic (META_DEBUG_STACK, - "Sorting stack list"); - - stack->sorted = g_list_sort (stack->sorted, - (GCompareFunc) compare_window_position); - - meta_display_queue_check_fullscreen (stack->display); - - stack->need_resort = FALSE; -} - -/** - * stack_ensure_sorted: - * - * Puts the stack into canonical form. - * - * Honour the removed and added lists of the stack, and then recalculate - * all the layers (if the flag is set), re-run all the constraint calculations - * (if the flag is set), and finally re-sort the stack (if the flag is set, - * and if it wasn't already it might have become so during all the previous - * activity). - */ -static void -stack_ensure_sorted (MetaStack *stack) -{ - stack_do_relayer (stack); - stack_do_constrain (stack); - stack_do_resort (stack); -} - -MetaWindow * -meta_stack_get_top (MetaStack *stack) -{ - stack_ensure_sorted (stack); - - if (stack->sorted) - return stack->sorted->data; - else - return NULL; -} - -MetaWindow * -meta_stack_get_bottom (MetaStack *stack) -{ - GList *link; - - stack_ensure_sorted (stack); - - link = g_list_last (stack->sorted); - if (link != NULL) - return link->data; - else - return NULL; -} - -MetaWindow * -meta_stack_get_above (MetaStack *stack, - MetaWindow *window, - gboolean only_within_layer) -{ - GList *link; - MetaWindow *above; - - stack_ensure_sorted (stack); - - link = g_list_find (stack->sorted, window); - if (link == NULL) - return NULL; - if (link->prev == NULL) - return NULL; - - above = link->prev->data; - - if (only_within_layer && - above->layer != window->layer) - return NULL; - else - return above; -} - -MetaWindow * -meta_stack_get_below (MetaStack *stack, - MetaWindow *window, - gboolean only_within_layer) -{ - GList *link; - MetaWindow *below; - - stack_ensure_sorted (stack); - - link = g_list_find (stack->sorted, window); - - if (link == NULL) - return NULL; - if (link->next == NULL) - return NULL; - - below = link->next->data; - - if (only_within_layer && - below->layer != window->layer) - return NULL; - else - return below; -} - -static gboolean -window_contains_point (MetaWindow *window, - int root_x, - int root_y) -{ - MetaRectangle rect; - - meta_window_get_frame_rect (window, &rect); - - return META_POINT_IN_RECT (root_x, root_y, rect); -} - -static gboolean -window_can_get_default_focus (MetaWindow *window) -{ - if (window->unmaps_pending > 0) - return FALSE; - - if (window->unmanaging) - return FALSE; - - if (!meta_window_is_focusable (window)) - return FALSE; - - if (!meta_window_should_be_showing (window)) - return FALSE; - - if (window->type == META_WINDOW_DOCK) - return FALSE; - - return TRUE; -} - -static MetaWindow * -get_default_focus_window (MetaStack *stack, - MetaWorkspace *workspace, - MetaWindow *not_this_one, - gboolean must_be_at_point, - int root_x, - int root_y) -{ - /* Find the topmost, focusable, mapped, window. - * not_this_one is being unfocused or going away, so exclude it. - */ - - GList *l; - - stack_ensure_sorted (stack); - - /* top of this layer is at the front of the list */ - for (l = stack->sorted; l != NULL; l = l->next) - { - MetaWindow *window = l->data; - - if (!window) - continue; - - if (window == not_this_one) - continue; - - if (!window_can_get_default_focus (window)) - continue; - - if (must_be_at_point && !window_contains_point (window, root_x, root_y)) - continue; - - return window; - } - - return NULL; -} - -MetaWindow * -meta_stack_get_default_focus_window_at_point (MetaStack *stack, - MetaWorkspace *workspace, - MetaWindow *not_this_one, - int root_x, - int root_y) -{ - return get_default_focus_window (stack, workspace, not_this_one, - TRUE, root_x, root_y); -} - -MetaWindow * -meta_stack_get_default_focus_window (MetaStack *stack, - MetaWorkspace *workspace, - MetaWindow *not_this_one) -{ - return get_default_focus_window (stack, workspace, not_this_one, - FALSE, 0, 0); -} - -GList * -meta_stack_list_windows (MetaStack *stack, - MetaWorkspace *workspace) -{ - GList *workspace_windows = NULL; - GList *link; - - stack_ensure_sorted (stack); /* do adds/removes */ - - link = stack->sorted; - - while (link) - { - MetaWindow *window = link->data; - - if (window && - (workspace == NULL || meta_window_located_on_workspace (window, workspace))) - { - workspace_windows = g_list_prepend (workspace_windows, - window); - } - - link = link->next; - } - - return workspace_windows; -} - -GList * -meta_stack_get_default_focus_candidates (MetaStack *stack, - MetaWorkspace *workspace) -{ - GList *windows = meta_stack_list_windows (stack, workspace); - GList *l; - - for (l = windows; l;) - { - GList *next = l->next; - - if (!window_can_get_default_focus (l->data)) - windows = g_list_delete_link (windows, l); - - l = next; - } - - return windows; -} - -int -meta_stack_windows_cmp (MetaStack *stack, - MetaWindow *window_a, - MetaWindow *window_b) -{ - /* -1 means a below b */ - - stack_ensure_sorted (stack); /* update constraints, layers */ - - if (window_a->layer < window_b->layer) - return -1; - else if (window_a->layer > window_b->layer) - return 1; - else if (window_a->stack_position < window_b->stack_position) - return -1; - else if (window_a->stack_position > window_b->stack_position) - return 1; - else - return 0; /* not reached */ -} - -static int -compare_just_window_stack_position (void *a, - void *b) -{ - MetaWindow *window_a = a; - MetaWindow *window_b = b; - - if (window_a->stack_position < window_b->stack_position) - return -1; /* move window_a earlier in list */ - else if (window_a->stack_position > window_b->stack_position) - return 1; - else - return 0; /* not reached */ -} - -GList * -meta_stack_get_positions (MetaStack *stack) -{ - GList *tmp; - - /* Make sure to handle any adds or removes */ - stack_ensure_sorted (stack); - - tmp = g_list_copy (stack->sorted); - tmp = g_list_sort (tmp, (GCompareFunc) compare_just_window_stack_position); - - return tmp; -} - -static gint -compare_pointers (gconstpointer a, - gconstpointer b) -{ - if (a > b) - return 1; - else if (a < b) - return -1; - else - return 0; -} - -static gboolean -lists_contain_same_windows (GList *a, - GList *b) -{ - GList *copy1, *copy2; - GList *tmp1, *tmp2; - - if (g_list_length (a) != g_list_length (b)) - return FALSE; - - tmp1 = copy1 = g_list_sort (g_list_copy (a), compare_pointers); - tmp2 = copy2 = g_list_sort (g_list_copy (b), compare_pointers); - - while (tmp1 && tmp1->data == tmp2->data) /* tmp2 is non-NULL if tmp1 is */ - { - tmp1 = tmp1->next; - tmp2 = tmp2->next; - } - - g_list_free (copy1); - g_list_free (copy2); - - return (tmp1 == NULL); /* tmp2 is non-NULL if tmp1 is */ -} - -void -meta_stack_set_positions (MetaStack *stack, - GList *windows) -{ - int i; - GList *tmp; - - /* Make sure any adds or removes aren't in limbo -- is this needed? */ - stack_ensure_sorted (stack); - - if (!lists_contain_same_windows (windows, stack->sorted)) - { - meta_warning ("This list of windows has somehow changed; not resetting " - "positions of the windows."); - return; - } - - g_list_free (stack->sorted); - stack->sorted = g_list_copy (windows); - - stack->need_resort = TRUE; - stack->need_constrain = TRUE; - - i = 0; - tmp = windows; - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - w->stack_position = i++; - tmp = tmp->next; - } - - meta_topic (META_DEBUG_STACK, - "Reset the stack positions of (nearly) all windows"); - - meta_stack_changed (stack); - meta_stack_update_window_tile_matches (stack, NULL); -} - -void -meta_window_set_stack_position_no_sync (MetaWindow *window, - int position) -{ - int low, high, delta; - GList *tmp; - - g_return_if_fail (window->display->stack != NULL); - g_return_if_fail (window->stack_position >= 0); - g_return_if_fail (position >= 0); - g_return_if_fail (position < window->display->stack->n_positions); - - if (position == window->stack_position) - { - meta_topic (META_DEBUG_STACK, "Window %s already has position %d", - window->desc, position); - return; - } - - window->display->stack->need_resort = TRUE; - window->display->stack->need_constrain = TRUE; - - if (position < window->stack_position) - { - low = position; - high = window->stack_position - 1; - delta = 1; - } - else - { - low = window->stack_position + 1; - high = position; - delta = -1; - } - - tmp = window->display->stack->sorted; - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - - if (w->stack_position >= low && - w->stack_position <= high) - w->stack_position += delta; - - tmp = tmp->next; - } - - window->stack_position = position; - - meta_topic (META_DEBUG_STACK, - "Window %s had stack_position set to %d", - window->desc, window->stack_position); -} - -void -meta_window_set_stack_position (MetaWindow *window, - int position) -{ - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - - meta_window_set_stack_position_no_sync (window, position); - meta_stack_changed (window->display->stack); - meta_stack_update_window_tile_matches (window->display->stack, - workspace_manager->active_workspace); -} diff --git a/src/core/stack.h b/src/core/stack.h deleted file mode 100644 index ec5753fe7..000000000 --- a/src/core/stack.h +++ /dev/null @@ -1,406 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2005 Elijah Newren - * - * 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 . - */ - -#ifndef META_STACK_H -#define META_STACK_H - -/** - * SECTION:stack - * @short_description: Which windows cover which other windows - * - * There are two factors that determine window position. - * - * One is window->stack_position, which is a unique integer - * indicating how windows are ordered with respect to one - * another. The ordering here transcends layers; it isn't changed - * as the window is moved among layers. This allows us to move several - * windows from one layer to another, while preserving the relative - * order of the moved windows. Also, it allows us to restore - * the stacking order from a saved session. - * - * However when actually stacking windows on the screen, the - * layer overrides the stack_position; windows are first sorted - * by layer, then by stack_position within each layer. - */ - -#include "core/display-private.h" - -/** - * A sorted list of windows bearing some level of resemblance to the stack of - * windows on the X server. - * - * (This is only used as a field within a MetaScreen; we treat it as a separate - * class for simplicity.) - */ -struct _MetaStack -{ - GObject parent; - - /** The MetaDisplay containing this stack. */ - MetaDisplay *display; - - /** The MetaWindows of the windows we manage, sorted in order. */ - GList *sorted; - - /** - * If this is zero, the local stack oughtn't to be brought up to date with - * the X server's stack, because it is in the middle of being updated. - * If it is positive, the local stack is said to be "frozen", and will need - * to be thawed that many times before the stack can be brought up to date - * again. You may freeze the stack with meta_stack_freeze() and thaw it - * with meta_stack_thaw(). - */ - int freeze_count; - - /** - * The last-known stack of all windows, bottom to top. We cache it here - * so that subsequent times we'll be able to do incremental moves. - */ - GArray *last_all_root_children_stacked; - - /** - * Number of stack positions; same as the length of added, but - * kept for quick reference. - */ - gint n_positions; - - /** Is the stack in need of re-sorting? */ - unsigned int need_resort : 1; - - /** - * Are the windows in the stack in need of having their - * layers recalculated? - */ - unsigned int need_relayer : 1; - - /** - * Are the windows in the stack in need of having their positions - * recalculated with respect to transiency (parent and child windows)? - */ - unsigned int need_constrain : 1; -}; - -#define META_TYPE_STACK (meta_stack_get_type ()) -G_DECLARE_FINAL_TYPE (MetaStack, meta_stack, META, STACK, GObject) - -/** - * meta_stack_new: - * @display: The MetaDisplay which will be the parent of this stack. - * - * Creates and initialises a MetaStack. - * - * Returns: The new stack. - */ -MetaStack * meta_stack_new (MetaDisplay *display); - -/** - * meta_stack_add: - * @stack: The stack to add it to - * @window: The window to add - * - * Adds a window to the local stack. It is a fatal error to call this - * function on a window which already exists on the stack of any screen. - */ -void meta_stack_add (MetaStack *stack, - MetaWindow *window); - -/** - * meta_stack_remove: - * @stack: The stack to remove it from - * @window: The window to remove - * - * Removes a window from the local stack. It is a fatal error to call this - * function on a window which exists on the stack of any screen. - */ -void meta_stack_remove (MetaStack *stack, - MetaWindow *window); -/** - * meta_stack_update_layer: - * @stack: The stack to recalculate - * @window: Dummy parameter - * - * Recalculates the correct layer for all windows in the stack, - * and moves them about accordingly. - * - */ -void meta_stack_update_layer (MetaStack *stack, - MetaWindow *window); - -/** - * meta_stack_update_transient: - * @stack: The stack to recalculate - * @window: Dummy parameter - * - * Recalculates the correct stacking order for all windows in the stack - * according to their transience, and moves them about accordingly. - * - * FIXME: What's with the dummy parameter? - */ -void meta_stack_update_transient (MetaStack *stack, - MetaWindow *window); - -/** - * meta_stack_raise: - * @stack: The stack to modify. - * @window: The window that's making an ascension. - * (Amulet of Yendor not required.) - * - * Move a window to the top of its layer. - */ -void meta_stack_raise (MetaStack *stack, - MetaWindow *window); -/** - * meta_stack_lower: - * @stack: The stack to modify. - * @window: The window that's on the way downwards. - * - * Move a window to the bottom of its layer. - */ -void meta_stack_lower (MetaStack *stack, - MetaWindow *window); - -/** - * meta_stack_freeze: - * @stack: The stack to freeze. - * - * Prevent syncing to server until the next call of meta_stack_thaw(), - * so that we can carry out multiple operations in one go without having - * everything halfway reflected on the X server. - * - * (Calls to meta_stack_freeze() nest, so that multiple calls to - * meta_stack_freeze will require multiple calls to meta_stack_thaw().) - */ -void meta_stack_freeze (MetaStack *stack); - -/** - * meta_stack_thaw: - * @stack: The stack to thaw. - * - * Undoes a meta_stack_freeze(), and processes anything which has become - * necessary during the freeze. It is an error to call this function if - * the stack has not been frozen. - */ -void meta_stack_thaw (MetaStack *stack); - -/** - * meta_stack_get_top: - * @stack: The stack to examine. - * - * Finds the top window on the stack. - * - * Returns: The top window on the stack, or %NULL in the vanishingly unlikely - * event that you have no windows on your screen whatsoever. - */ -MetaWindow * meta_stack_get_top (MetaStack *stack); - -/** - * meta_stack_get_bottom: - * @stack: The stack to search - * - * Finds the window at the bottom of the stack. Since that's pretty much - * always the desktop, this isn't the most useful of functions, and nobody - * actually calls it. We should probably get rid of it. - */ -MetaWindow * meta_stack_get_bottom (MetaStack *stack); - -/** - * meta_stack_get_above: - * @stack: The stack to search. - * @window: The window to look above. - * @only_within_layer: If %TRUE, will return %NULL if @window is the - * top window in its layer. - * - * Finds the window above a given window in the stack. - * It is not an error to pass in a window which does not exist in - * the stack; the function will merely return %NULL. - * - * Returns: %NULL if there is no such window; - * the window above @window otherwise. - */ -MetaWindow * meta_stack_get_above (MetaStack *stack, - MetaWindow *window, - gboolean only_within_layer); - -/** - * meta_stack_get_below: - * @stack: The stack to search. - * @window: The window to look below. - * @only_within_layer: If %TRUE, will return %NULL if window is the - * bottom window in its layer. - * - * Finds the window below a given window in the stack. - * It is not an error to pass in a window which does not exist in - * the stack; the function will merely return %NULL. - * - * - * Returns: %NULL if there is no such window; - * the window below @window otherwise. - */ -MetaWindow * meta_stack_get_below (MetaStack *stack, - MetaWindow *window, - gboolean only_within_layer); - -/** - * meta_stack_get_default_focus_window: - * @stack: The stack to search. - * @workspace: %NULL to search all workspaces; otherwise only windows - * from that workspace will be returned. - * @not_this_one: Window to ignore because it's being unfocussed or - * going away. - * - * Find the topmost, focusable, mapped, window in a stack. If you supply - * a window as @not_this_one, we won't return that one (presumably - * because it's going to be going away). But if you do supply @not_this_one - * and we find its parent, we'll return that; and if @not_this_one is in - * a group, we'll return the top window of that group. - * - * Also, we are prejudiced against dock windows. Every kind of window, even - * the desktop, will be returned in preference to a dock window. - * - * Returns: The window matching all these constraints or %NULL if none does. - */ -MetaWindow * meta_stack_get_default_focus_window (MetaStack *stack, - MetaWorkspace *workspace, - MetaWindow *not_this_one); - -/** - * meta_stack_get_default_focus_window_at_point: - * @stack: The stack to search. - * @workspace: %NULL to search all workspaces; otherwise only windows - * from that workspace will be returned. - * @not_this_one: Window to ignore because it's being unfocussed or - * going away. - * @root_x: The returned window must contain this point, - * unless it's a dock. - * @root_y: See root_x. - * - * Find the topmost, focusable, mapped, window in a stack. If you supply - * a window as @not_this_one, we won't return that one (presumably - * because it's going to be going away). But if you do supply @not_this_one - * and we find its parent, we'll return that; and if @not_this_one is in - * a group, we'll return the top window of that group. - * - * Also, we are prejudiced against dock windows. Every kind of window, even - * the desktop, will be returned in preference to a dock window. - * - * Returns: The window matching all these constraints or %NULL if none does. - */ -MetaWindow * meta_stack_get_default_focus_window_at_point (MetaStack *stack, - MetaWorkspace *workspace, - MetaWindow *not_this_one, - int root_x, - int root_y); - -/** - * meta_stack_get_default_focus_candidates: - * @stack: The stack to examine. - * @workspace: If not %NULL, only windows on this workspace will be - * returned; otherwise all windows in the stack will be - * returned. - * - * Returns all the focus candidate windows in the stack, in order. - * - * Returns: (transfer container) (element-type Meta.Window): - * A #GList of #MetaWindow, in stacking order, honouring layers. - */ -GList * meta_stack_get_default_focus_candidates (MetaStack *stack, - MetaWorkspace *workspace); - -/** - * meta_stack_list_windows: - * @stack: The stack to examine. - * @workspace: If not %NULL, only windows on this workspace will be - * returned; otherwise all windows in the stack will be - * returned. - * - * Finds all the windows in the stack, in order. - * - * Returns: (transfer container) (element-type Meta.Window): - * A list of windows, in stacking order, honouring layers. - */ -GList * meta_stack_list_windows (MetaStack *stack, - MetaWorkspace *workspace); - -/** - * meta_stack_windows_cmp: - * @stack: A stack containing both window_a and window_b - * @window_a: A window - * @window_b Another window - * - * Comparison function for windows within a stack. This is not directly - * suitable for use within a standard comparison routine, because it takes - * an extra parameter; you will need to wrap it. - * - * (FIXME: We could remove the stack parameter and use the stack of - * the screen of window A, and complain if the stack of the screen of - * window B differed; then this would be a usable general comparison function.) - * - * (FIXME: Apparently identical to compare_window_position(). Merge them.) - * - * \return -1 if window_a is below window_b, honouring layers; 1 if it's - * above it; 0 if you passed in the same window twice! - */ -int meta_stack_windows_cmp (MetaStack *stack, - MetaWindow *window_a, - MetaWindow *window_b); - -/** - * meta_window_set_stack_position: - * @window: The window which is moving. - * @position: Where it should move to (0 is the bottom). - * - * Sets the position of a window within the stack. This will only move it - * up or down within its layer. It is an error to attempt to move this - * below position zero or above the last position in the stack (however, since - * we don't provide a simple way to tell the number of windows in the stack, - * this requirement may not be easy to fulfil). - */ -void meta_window_set_stack_position (MetaWindow *window, - int position); - -/** - * meta_stack_get_positions: - * @stack: The stack to examine. - * - * Returns the current stack state, allowing rudimentary transactions. - * - * Returns: (transfer container) (element-type Meta.Window): - * An opaque #GList representing the current stack sort order; - * it is the caller's responsibility to free it. - * Pass this to meta_stack_set_positions() later if you want to restore - * the state to where it was when you called this function. - */ -GList * meta_stack_get_positions (MetaStack *stack); - -/** - * meta_stack_set_positions: - * @stack: The stack to roll back. - * @windows: The list returned from meta_stack_get_positions(). - * - * Rolls back a transaction, given the list returned from - * meta_stack_get_positions(). - * - */ -void meta_stack_set_positions (MetaStack *stack, - GList *windows); - -void meta_stack_update_window_tile_matches (MetaStack *stack, - MetaWorkspace *workspace); -#endif diff --git a/src/core/startup-notification-private.h b/src/core/startup-notification-private.h deleted file mode 100644 index 5bdf2ac1a..000000000 --- a/src/core/startup-notification-private.h +++ /dev/null @@ -1,52 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001, 2002 Havoc Pennington - * Copyright (C) 2002, 2003 Red Hat Inc. - * Some ICCCM manager selection code derived from fvwm2, - * Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * 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 . - */ - -#ifndef META_STARTUP_NOTIFICATION_PRIVATE_H -#define META_STARTUP_NOTIFICATION_PRIVATE_H - -#include "core/display-private.h" -#include "meta/meta-startup-notification.h" - -struct _MetaStartupSequenceClass -{ - GObjectClass parent_class; - - void (* complete) (MetaStartupSequence *sequence); -}; - -MetaStartupNotification * - meta_startup_notification_new (MetaDisplay *display); - -gboolean meta_startup_notification_handle_xevent (MetaStartupNotification *sn, - XEvent *xevent); - -void meta_startup_notification_add_sequence (MetaStartupNotification *sn, - MetaStartupSequence *seq); -void meta_startup_notification_remove_sequence (MetaStartupNotification *sn, - MetaStartupSequence *seq); -MetaStartupSequence * - meta_startup_notification_lookup_sequence (MetaStartupNotification *sn, - const gchar *id); - -#endif /* META_STARTUP_NOTIFICATION_PRIVATE_H */ diff --git a/src/core/startup-notification.c b/src/core/startup-notification.c deleted file mode 100644 index 85a14e939..000000000 --- a/src/core/startup-notification.c +++ /dev/null @@ -1,696 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001, 2002 Havoc Pennington - * Copyright (C) 2002, 2003 Red Hat Inc. - * Some ICCCM manager selection code derived from fvwm2, - * Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * 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 . - */ - -#include "config.h" - -#include - -#include "core/display-private.h" -#include "core/startup-notification-private.h" -#include "core/util-private.h" -#include "meta/meta-x11-errors.h" -#include "x11/meta-x11-display-private.h" - -/* This should be fairly long, as it should never be required unless - * apps or .desktop files are buggy, and it's confusing if - * OpenOffice or whatever seems to stop launching - people - * might decide they need to launch it again. - */ -#define STARTUP_TIMEOUT_MS 15000 - -enum -{ - PROP_0, - PROP_DISPLAY, - N_PROPS -}; - -enum -{ - PROP_SEQ_0, - PROP_SEQ_ID, - PROP_SEQ_TIMESTAMP, - PROP_SEQ_ICON_NAME, - PROP_SEQ_APPLICATION_ID, - PROP_SEQ_WMCLASS, - PROP_SEQ_WORKSPACE, - PROP_SEQ_NAME, - N_SEQ_PROPS -}; - -enum -{ - SEQ_COMPLETE, - SEQ_TIMEOUT, - N_SEQ_SIGNALS -}; - -enum -{ - CHANGED, - N_SIGNALS -}; - -static guint sn_signals[N_SIGNALS]; -static GParamSpec *sn_props[N_PROPS]; -static guint seq_signals[N_SEQ_SIGNALS]; -static GParamSpec *seq_props[N_SEQ_PROPS]; - -typedef struct -{ - GSList *list; - gint64 now; -} CollectTimedOutData; - -struct _MetaStartupNotification -{ - GObject parent_instance; - MetaDisplay *display; - - - GSList *startup_sequences; - guint startup_sequence_timeout; -}; - -typedef struct { - char *wmclass; - char *name; - char *application_id; - char *icon_name; - char *id; - uint64_t timestamp; - int workspace; - uint completed : 1; -} MetaStartupSequencePrivate; - -G_DEFINE_TYPE (MetaStartupNotification, - meta_startup_notification, - G_TYPE_OBJECT) -G_DEFINE_TYPE_WITH_PRIVATE (MetaStartupSequence, - meta_startup_sequence, - G_TYPE_OBJECT) - - -static void meta_startup_notification_ensure_timeout (MetaStartupNotification *sn); - -static gboolean -meta_startup_notification_has_pending_sequences (MetaStartupNotification *sn) -{ - GSList *l; - - for (l = sn->startup_sequences; l; l = l->next) - { - if (!meta_startup_sequence_get_completed (l->data)) - return TRUE; - } - - return FALSE; -} - -static void -meta_startup_notification_update_feedback (MetaStartupNotification *sn) -{ - MetaDisplay *display = sn->display; - - if (meta_startup_notification_has_pending_sequences (sn)) - { - meta_topic (META_DEBUG_STARTUP, - "Setting busy cursor"); - meta_display_set_cursor (display, META_CURSOR_BUSY); - } - else - { - meta_topic (META_DEBUG_STARTUP, - "Setting default cursor"); - meta_display_set_cursor (display, META_CURSOR_DEFAULT); - } -} - -static void -meta_startup_sequence_init (MetaStartupSequence *seq) -{ -} - -static void -meta_startup_sequence_finalize (GObject *object) -{ - MetaStartupSequence *seq; - MetaStartupSequencePrivate *priv; - - seq = META_STARTUP_SEQUENCE (object); - priv = meta_startup_sequence_get_instance_private (seq); - g_free (priv->id); - g_free (priv->wmclass); - g_free (priv->name); - g_free (priv->application_id); - g_free (priv->icon_name); - - G_OBJECT_CLASS (meta_startup_sequence_parent_class)->finalize (object); -} - -static void -meta_startup_sequence_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaStartupSequence *seq; - MetaStartupSequencePrivate *priv; - - seq = META_STARTUP_SEQUENCE (object); - priv = meta_startup_sequence_get_instance_private (seq); - - switch (prop_id) - { - case PROP_SEQ_ID: - priv->id = g_value_dup_string (value); - break; - case PROP_SEQ_TIMESTAMP: - priv->timestamp = g_value_get_uint64 (value); - break; - case PROP_SEQ_ICON_NAME: - priv->icon_name = g_value_dup_string (value); - break; - case PROP_SEQ_APPLICATION_ID: - priv->application_id = g_value_dup_string (value); - break; - case PROP_SEQ_WMCLASS: - priv->wmclass = g_value_dup_string (value); - break; - case PROP_SEQ_WORKSPACE: - priv->workspace = g_value_get_int (value); - break; - case PROP_SEQ_NAME: - priv->name = g_value_dup_string (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_startup_sequence_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaStartupSequence *seq; - MetaStartupSequencePrivate *priv; - - seq = META_STARTUP_SEQUENCE (object); - priv = meta_startup_sequence_get_instance_private (seq); - - switch (prop_id) - { - case PROP_SEQ_ID: - g_value_set_string (value, priv->id); - break; - case PROP_SEQ_TIMESTAMP: - g_value_set_uint64 (value, priv->timestamp); - break; - case PROP_SEQ_ICON_NAME: - g_value_set_string (value, priv->icon_name); - break; - case PROP_SEQ_APPLICATION_ID: - g_value_set_string (value, priv->application_id); - break; - case PROP_SEQ_WMCLASS: - g_value_set_string (value, priv->wmclass); - break; - case PROP_SEQ_WORKSPACE: - g_value_set_int (value, priv->workspace); - break; - case PROP_SEQ_NAME: - g_value_set_string (value, priv->name); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_startup_sequence_class_init (MetaStartupSequenceClass *klass) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - object_class->finalize = meta_startup_sequence_finalize; - object_class->set_property = meta_startup_sequence_set_property; - object_class->get_property = meta_startup_sequence_get_property; - - seq_signals[SEQ_COMPLETE] = - g_signal_new ("complete", - META_TYPE_STARTUP_SEQUENCE, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (MetaStartupSequenceClass, complete), - NULL, NULL, NULL, - G_TYPE_NONE, 0); - seq_signals[SEQ_TIMEOUT] = - g_signal_new ("timeout", - META_TYPE_STARTUP_SEQUENCE, - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); - - seq_props[PROP_SEQ_ID] = - g_param_spec_string ("id", - "ID", - "ID", - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - seq_props[PROP_SEQ_TIMESTAMP] = - g_param_spec_uint64 ("timestamp", - "Timestamp", - "Timestamp", - 0, G_MAXUINT64, 0, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - seq_props[PROP_SEQ_ICON_NAME] = - g_param_spec_string ("icon-name", - "Icon name", - "Icon name", - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - seq_props[PROP_SEQ_APPLICATION_ID] = - g_param_spec_string ("application-id", - "Application ID", - "Application ID", - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - seq_props[PROP_SEQ_WMCLASS] = - g_param_spec_string ("wmclass", - "WM class", - "WM class", - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - seq_props[PROP_SEQ_WORKSPACE] = - g_param_spec_int ("workspace", - "Workspace", - "Workspace", - G_MININT, G_MAXINT, -1, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - seq_props[PROP_SEQ_NAME] = - g_param_spec_string ("name", - "Name", - "Name", - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - - g_object_class_install_properties (object_class, N_SEQ_PROPS, seq_props); -} - -const char * -meta_startup_sequence_get_id (MetaStartupSequence *seq) -{ - MetaStartupSequencePrivate *priv; - - g_return_val_if_fail (META_IS_STARTUP_SEQUENCE (seq), NULL); - - priv = meta_startup_sequence_get_instance_private (seq); - return priv->id; -} - -uint64_t -meta_startup_sequence_get_timestamp (MetaStartupSequence *seq) -{ - MetaStartupSequencePrivate *priv; - - g_return_val_if_fail (META_IS_STARTUP_SEQUENCE (seq), 0); - - priv = meta_startup_sequence_get_instance_private (seq); - return priv->timestamp; -} - -void -meta_startup_sequence_complete (MetaStartupSequence *seq) -{ - MetaStartupSequencePrivate *priv; - - g_return_if_fail (META_IS_STARTUP_SEQUENCE (seq)); - - priv = meta_startup_sequence_get_instance_private (seq); - if (priv->completed) - return; - - priv->completed = TRUE; - g_signal_emit (seq, seq_signals[SEQ_COMPLETE], 0); -} - -gboolean -meta_startup_sequence_get_completed (MetaStartupSequence *seq) -{ - MetaStartupSequencePrivate *priv; - - g_return_val_if_fail (META_IS_STARTUP_SEQUENCE (seq), FALSE); - - priv = meta_startup_sequence_get_instance_private (seq); - return priv->completed; -} - -const char * -meta_startup_sequence_get_name (MetaStartupSequence *seq) -{ - MetaStartupSequencePrivate *priv; - - g_return_val_if_fail (META_IS_STARTUP_SEQUENCE (seq), NULL); - - priv = meta_startup_sequence_get_instance_private (seq); - return priv->name; -} - -int -meta_startup_sequence_get_workspace (MetaStartupSequence *seq) -{ - MetaStartupSequencePrivate *priv; - - g_return_val_if_fail (META_IS_STARTUP_SEQUENCE (seq), 0); - - priv = meta_startup_sequence_get_instance_private (seq); - return priv->workspace; -} - -const char * -meta_startup_sequence_get_icon_name (MetaStartupSequence *seq) -{ - MetaStartupSequencePrivate *priv; - - g_return_val_if_fail (META_IS_STARTUP_SEQUENCE (seq), NULL); - - priv = meta_startup_sequence_get_instance_private (seq); - return priv->icon_name; -} - -const char * -meta_startup_sequence_get_application_id (MetaStartupSequence *seq) -{ - MetaStartupSequencePrivate *priv; - - g_return_val_if_fail (META_IS_STARTUP_SEQUENCE (seq), NULL); - - priv = meta_startup_sequence_get_instance_private (seq); - return priv->application_id; -} - -const char * -meta_startup_sequence_get_wmclass (MetaStartupSequence *seq) -{ - MetaStartupSequencePrivate *priv; - - g_return_val_if_fail (META_IS_STARTUP_SEQUENCE (seq), NULL); - - priv = meta_startup_sequence_get_instance_private (seq); - return priv->wmclass; -} - -static void -on_sequence_completed (MetaStartupSequence *seq, - MetaStartupNotification *sn) -{ - meta_startup_notification_update_feedback (sn); - g_signal_emit (sn, sn_signals[CHANGED], 0, seq); -} - -void -meta_startup_notification_add_sequence (MetaStartupNotification *sn, - MetaStartupSequence *seq) -{ - sn->startup_sequences = g_slist_prepend (sn->startup_sequences, - g_object_ref (seq)); - g_signal_connect (seq, "complete", - G_CALLBACK (on_sequence_completed), sn); - - meta_startup_notification_ensure_timeout (sn); - meta_startup_notification_update_feedback (sn); - - g_signal_emit (sn, sn_signals[CHANGED], 0, seq); -} - -static void -collect_timed_out_foreach (void *element, - void *data) -{ - MetaStartupSequence *sequence = element; - CollectTimedOutData *ctod = data; - gint64 elapsed, timestamp; - - timestamp = meta_startup_sequence_get_timestamp (sequence); - elapsed = ctod->now - timestamp; - - meta_topic (META_DEBUG_STARTUP, - "Sequence used %" G_GINT64_FORMAT " ms vs. %d max: %s", - elapsed, STARTUP_TIMEOUT_MS, - meta_startup_sequence_get_id (sequence)); - - if (elapsed > STARTUP_TIMEOUT_MS) - ctod->list = g_slist_prepend (ctod->list, sequence); -} - -static gboolean -startup_sequence_timeout (void *data) -{ - MetaStartupNotification *sn = data; - CollectTimedOutData ctod; - GSList *l; - - ctod.list = NULL; - ctod.now = g_get_monotonic_time () / 1000; - g_slist_foreach (sn->startup_sequences, - collect_timed_out_foreach, - &ctod); - - for (l = ctod.list; l != NULL; l = l->next) - { - MetaStartupSequence *sequence = l->data; - - meta_topic (META_DEBUG_STARTUP, - "Timed out sequence %s", - meta_startup_sequence_get_id (sequence)); - - if (!meta_startup_sequence_get_completed (sequence)) - { - g_signal_emit (sequence, seq_signals[SEQ_TIMEOUT], 0, sequence); - meta_startup_sequence_complete (sequence); - } - - meta_startup_notification_remove_sequence (sn, sequence); - } - - g_slist_free (ctod.list); - - if (sn->startup_sequences != NULL) - { - return TRUE; - } - else - { - /* remove */ - sn->startup_sequence_timeout = 0; - return FALSE; - } -} - -static void -meta_startup_notification_ensure_timeout (MetaStartupNotification *sn) -{ - if (sn->startup_sequence_timeout != 0) - return; - - /* our timeout just polls every second, instead of bothering - * to compute exactly when we may next time out - */ - sn->startup_sequence_timeout = g_timeout_add_seconds (1, - startup_sequence_timeout, - sn); - g_source_set_name_by_id (sn->startup_sequence_timeout, - "[mutter] startup_sequence_timeout"); -} - -void -meta_startup_notification_remove_sequence (MetaStartupNotification *sn, - MetaStartupSequence *seq) -{ - sn->startup_sequences = g_slist_remove (sn->startup_sequences, seq); - meta_startup_notification_update_feedback (sn); - - g_signal_handlers_disconnect_by_func (seq, on_sequence_completed, sn); - - if (sn->startup_sequences == NULL) - g_clear_handle_id (&sn->startup_sequence_timeout, g_source_remove); - - g_signal_emit (sn, sn_signals[CHANGED], 0, seq); - g_object_unref (seq); -} - -MetaStartupSequence * -meta_startup_notification_lookup_sequence (MetaStartupNotification *sn, - const gchar *id) -{ - MetaStartupSequence *seq; - const gchar *seq_id; - GSList *l; - - for (l = sn->startup_sequences; l; l = l->next) - { - seq = l->data; - seq_id = meta_startup_sequence_get_id (seq); - - if (g_str_equal (seq_id, id)) - return l->data; - } - - return NULL; -} - -static void -meta_startup_notification_init (MetaStartupNotification *sn) -{ -} - -static void -meta_startup_notification_finalize (GObject *object) -{ - MetaStartupNotification *sn = META_STARTUP_NOTIFICATION (object); - - g_clear_handle_id (&sn->startup_sequence_timeout, g_source_remove); - - g_slist_free_full (sn->startup_sequences, g_object_unref); - sn->startup_sequences = NULL; - - G_OBJECT_CLASS (meta_startup_notification_parent_class)->finalize (object); -} - -static void -meta_startup_notification_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaStartupNotification *sn = META_STARTUP_NOTIFICATION (object); - - switch (prop_id) - { - case PROP_DISPLAY: - sn->display = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_startup_notification_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaStartupNotification *sn = META_STARTUP_NOTIFICATION (object); - - switch (prop_id) - { - case PROP_DISPLAY: - g_value_set_object (value, sn->display); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_startup_notification_constructed (GObject *object) -{ - MetaStartupNotification *sn = META_STARTUP_NOTIFICATION (object); - - g_assert (sn->display != NULL); - - sn->startup_sequences = NULL; - sn->startup_sequence_timeout = 0; -} - -static void -meta_startup_notification_class_init (MetaStartupNotificationClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->constructed = meta_startup_notification_constructed; - object_class->finalize = meta_startup_notification_finalize; - object_class->set_property = meta_startup_notification_set_property; - object_class->get_property = meta_startup_notification_get_property; - - sn_props[PROP_DISPLAY] = - g_param_spec_object ("display", - "Display", - "Display", - META_TYPE_DISPLAY, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - - sn_signals[CHANGED] = - g_signal_new ("changed", - META_TYPE_STARTUP_NOTIFICATION, - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 1, G_TYPE_POINTER); - - g_object_class_install_properties (object_class, N_PROPS, sn_props); -} - -MetaStartupNotification * -meta_startup_notification_new (MetaDisplay *display) -{ - return g_object_new (META_TYPE_STARTUP_NOTIFICATION, - "display", display, - NULL); -} - -GSList * -meta_startup_notification_get_sequences (MetaStartupNotification *sn) -{ - return sn->startup_sequences; -} - -/** - * meta_startup_notification_create_launcher: - * @sn: a #MetaStartupNotification - * - * Creates an app launch context. - * - * Returns: (transfer full): a launch context. - **/ -MetaLaunchContext * -meta_startup_notification_create_launcher (MetaStartupNotification *sn) -{ - return g_object_new (META_TYPE_LAUNCH_CONTEXT, - "display", sn->display, - NULL); -} diff --git a/src/core/util-private.h b/src/core/util-private.h deleted file mode 100644 index 01b663966..000000000 --- a/src/core/util-private.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter utilities */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2005 Elijah Newren - * - * 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_UTIL_PRIVATE_H -#define META_UTIL_PRIVATE_H - -#include - -#include "meta/util.h" -#include "meta/common.h" - -/* META_EXPORT_TEST should be used to export symbols that are exported only - * for testability purposes */ -#define META_EXPORT_TEST META_EXPORT - -void meta_set_verbose (gboolean setting); -void meta_set_debugging (gboolean setting); - -META_EXPORT_TEST -void meta_set_syncing (gboolean setting); - -void meta_set_replace_current_wm (gboolean setting); -void meta_set_is_wayland_compositor (gboolean setting); - -char * meta_generate_random_id (GRand *rand, - int length); - -void meta_init_debug_utils (void); - -#define META_POINT_IN_RECT(xcoord, ycoord, rect) \ - ((xcoord) >= (rect).x && \ - (xcoord) < ((rect).x + (rect).width) && \ - (ycoord) >= (rect).y && \ - (ycoord) < ((rect).y + (rect).height)) - -void meta_get_clutter_debug_flags (ClutterDebugFlag *debug_flags, - ClutterDrawDebugFlag *draw_flags, - ClutterPickDebugFlag *pick_flags); - -#endif diff --git a/src/core/util.c b/src/core/util.c deleted file mode 100644 index 74a884c80..000000000 --- a/src/core/util.c +++ /dev/null @@ -1,796 +0,0 @@ -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2005 Elijah Newren - * - * 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 . - */ - -/** - * SECTION:util - * @title: Utility functions - * @short_description: Miscellaneous utility functions - */ - -#define _POSIX_C_SOURCE 200112L /* for fdopen() */ - -#include "config.h" - -#include "core/util-private.h" - -#include -#include -#include -#include -#include -#include /* must explicitly be included for Solaris; #326746 */ -#include /* Just for the definition of the various gravities */ - -#ifdef HAVE_SYS_PRCTL -#include -#endif - -#include "clutter/clutter-mutter.h" -#include "cogl/cogl.h" -#include "meta/common.h" -#include "meta/main.h" - -static const GDebugKey meta_debug_keys[] = { - { "focus", META_DEBUG_FOCUS }, - { "workarea", META_DEBUG_WORKAREA }, - { "stack", META_DEBUG_STACK }, - { "sm", META_DEBUG_SM }, - { "events", META_DEBUG_EVENTS }, - { "window-state", META_DEBUG_WINDOW_STATE }, - { "window-ops", META_DEBUG_WINDOW_OPS }, - { "geometry", META_DEBUG_GEOMETRY }, - { "placement", META_DEBUG_PLACEMENT }, - { "ping", META_DEBUG_PING }, - { "keybindings", META_DEBUG_KEYBINDINGS }, - { "sync", META_DEBUG_SYNC }, - { "startup", META_DEBUG_STARTUP }, - { "prefs", META_DEBUG_PREFS }, - { "groups", META_DEBUG_GROUPS }, - { "resizing", META_DEBUG_RESIZING }, - { "shapes", META_DEBUG_SHAPES }, - { "edge-resistance", META_DEBUG_EDGE_RESISTANCE }, - { "dbus", META_DEBUG_DBUS }, - { "input", META_DEBUG_INPUT }, - { "wayland", META_DEBUG_WAYLAND }, - { "kms", META_DEBUG_KMS }, - { "screen-cast", META_DEBUG_SCREEN_CAST }, - { "remote-desktop", META_DEBUG_REMOTE_DESKTOP }, - { "backend", META_DEBUG_BACKEND }, -}; - -#ifdef WITH_VERBOSE_MODE -static void -meta_topic_real_valist (MetaDebugTopic topic, - const char *format, - va_list args) G_GNUC_PRINTF(2, 0); -#endif - -static gint verbose_topics = 0; -static int no_prefix = 0; -static gboolean is_wayland_compositor = FALSE; -static int debug_paint_flags = 0; - -#ifdef WITH_VERBOSE_MODE -static FILE* logfile = NULL; - -static void -ensure_logfile (void) -{ - if (logfile == NULL && g_getenv ("MUTTER_USE_LOGFILE")) - { - char *filename = NULL; - char *tmpl; - int fd; - GError *err; - - tmpl = g_strdup_printf ("mutter-%d-debug-log-XXXXXX", - (int) getpid ()); - - err = NULL; - fd = g_file_open_tmp (tmpl, - &filename, - &err); - - g_free (tmpl); - - if (err != NULL) - { - meta_warning ("Failed to open debug log: %s", - err->message); - g_error_free (err); - return; - } - - logfile = fdopen (fd, "w"); - - if (logfile == NULL) - { - meta_warning ("Failed to fdopen() log file %s: %s", - filename, strerror (errno)); - close (fd); - } - else - { - g_printerr ("Opened log file %s", filename); - } - - g_free (filename); - } -} -#endif - -gboolean -meta_is_verbose (void) -{ - return verbose_topics != 0; -} - -void -meta_set_verbose (gboolean setting) -{ -#ifndef WITH_VERBOSE_MODE - if (setting) - meta_fatal (_("Mutter was compiled without support for verbose mode")); -#endif - - if (setting) - meta_add_verbose_topic (META_DEBUG_VERBOSE); - else - meta_remove_verbose_topic (META_DEBUG_VERBOSE); -} - -/** - * meta_add_verbose_topic: - * @topic: Topic for which logging will be started - * - * Ensure log messages for the given topic @topic - * will be printed. - */ -void -meta_add_verbose_topic (MetaDebugTopic topic) -{ - if (verbose_topics == META_DEBUG_VERBOSE) - return; - - ensure_logfile (); - - if (topic == META_DEBUG_VERBOSE) - verbose_topics = META_DEBUG_VERBOSE; - else - verbose_topics |= topic; -} - -/** - * meta_remove_verbose_topic: - * @topic: Topic for which logging will be stopped - * - * Stop printing log messages for the given topic @topic. Note - * that this method does not stack with meta_add_verbose_topic(); - * i.e. if two calls to meta_add_verbose_topic() for the same - * topic are made, one call to meta_remove_verbose_topic() will - * remove it. - */ -void -meta_remove_verbose_topic (MetaDebugTopic topic) -{ - if (topic == META_DEBUG_VERBOSE) - verbose_topics = 0; - else - verbose_topics &= ~topic; -} - -void -meta_init_debug_utils (void) -{ - const char *debug_env; - -#ifdef HAVE_SYS_PRCTL - prctl (PR_SET_DUMPABLE, 1); -#endif - - if (g_getenv ("MUTTER_VERBOSE")) - meta_set_verbose (TRUE); - - debug_env = g_getenv ("MUTTER_DEBUG"); - if (debug_env) - { - MetaDebugTopic topics; - - topics = g_parse_debug_string (debug_env, - meta_debug_keys, - G_N_ELEMENTS (meta_debug_keys)); - meta_add_verbose_topic (topics); - } -} - -gboolean -meta_is_wayland_compositor (void) -{ - return is_wayland_compositor; -} - -void -meta_set_is_wayland_compositor (gboolean value) -{ - is_wayland_compositor = value; -} - -char * -meta_g_utf8_strndup (const gchar *src, - gsize n) -{ - const gchar *s = src; - while (n && *s) - { - s = g_utf8_next_char (s); - n--; - } - - return g_strndup (src, s - src); -} - -static int -utf8_fputs (const char *str, - FILE *f) -{ - char *l; - int retval; - - l = g_locale_from_utf8 (str, -1, NULL, NULL, NULL); - - if (l == NULL) - retval = fputs (str, f); /* just print it anyway, better than nothing */ - else - retval = fputs (l, f); - - g_free (l); - - return retval; -} - -#ifdef WITH_VERBOSE_MODE -void -meta_verbose_real (const char *format, ...) -{ - va_list args; - - va_start (args, format); - meta_topic_real_valist (META_DEBUG_VERBOSE, format, args); - va_end (args); -} - -static const char* -topic_name (MetaDebugTopic topic) -{ - switch (topic) - { - case META_DEBUG_FOCUS: - return "FOCUS"; - case META_DEBUG_WORKAREA: - return "WORKAREA"; - case META_DEBUG_STACK: - return "STACK"; - case META_DEBUG_SM: - return "SM"; - case META_DEBUG_EVENTS: - return "EVENTS"; - case META_DEBUG_WINDOW_STATE: - return "WINDOW_STATE"; - case META_DEBUG_WINDOW_OPS: - return "WINDOW_OPS"; - case META_DEBUG_PLACEMENT: - return "PLACEMENT"; - case META_DEBUG_GEOMETRY: - return "GEOMETRY"; - case META_DEBUG_PING: - return "PING"; - case META_DEBUG_KEYBINDINGS: - return "KEYBINDINGS"; - case META_DEBUG_SYNC: - return "SYNC"; - case META_DEBUG_STARTUP: - return "STARTUP"; - case META_DEBUG_PREFS: - return "PREFS"; - case META_DEBUG_GROUPS: - return "GROUPS"; - case META_DEBUG_RESIZING: - return "RESIZING"; - case META_DEBUG_SHAPES: - return "SHAPES"; - case META_DEBUG_EDGE_RESISTANCE: - return "EDGE_RESISTANCE"; - case META_DEBUG_DBUS: - return "DBUS"; - case META_DEBUG_INPUT: - return "INPUT"; - case META_DEBUG_KMS: - return "KMS"; - case META_DEBUG_SCREEN_CAST: - return "SCREEN_CAST"; - case META_DEBUG_REMOTE_DESKTOP: - return "REMOTE_DESKTOP"; - case META_DEBUG_BACKEND: - return "BACKEND"; - case META_DEBUG_VERBOSE: - return "VERBOSE"; - case META_DEBUG_WAYLAND: - return "WAYLAND"; - } - - return "WM"; -} - -static int sync_count = 0; - -gboolean -meta_is_topic_enabled (MetaDebugTopic topic) -{ - if (verbose_topics == 0) - return FALSE; - - if (topic == META_DEBUG_VERBOSE && verbose_topics != META_DEBUG_VERBOSE) - return FALSE; - - return !!(verbose_topics & topic); -} - -static void -meta_topic_real_valist (MetaDebugTopic topic, - const char *format, - va_list args) -{ - gchar *str; - FILE *out; - - g_return_if_fail (format != NULL); - - if (!meta_is_topic_enabled (topic)) - return; - - str = g_strdup_vprintf (format, args); - - out = logfile ? logfile : stderr; - - if (no_prefix == 0) - fprintf (out, "%s: ", topic_name (topic)); - - if (topic == META_DEBUG_SYNC) - { - ++sync_count; - fprintf (out, "%d: ", sync_count); - } - - utf8_fputs (str, out); - utf8_fputs ("\n", out); - - fflush (out); - - g_free (str); -} - -void -meta_topic_real (MetaDebugTopic topic, - const char *format, - ...) -{ - va_list args; - - va_start (args, format); - meta_topic_real_valist (topic, format, args); - va_end (args); -} -#endif /* WITH_VERBOSE_MODE */ - -void -meta_bug (const char *format, ...) -{ - va_list args; - gchar *str; - FILE *out; - - g_return_if_fail (format != NULL); - - va_start (args, format); - str = g_strdup_vprintf (format, args); - va_end (args); - -#ifdef WITH_VERBOSE_MODE - out = logfile ? logfile : stderr; -#else - out = stderr; -#endif - - if (no_prefix == 0) - utf8_fputs ("Bug in window manager: ", out); - utf8_fputs (str, out); - utf8_fputs ("\n", out); - - fflush (out); - - g_free (str); - - /* stop us in a debugger */ - abort (); -} - -void -meta_warning (const char *format, ...) -{ - va_list args; - gchar *str; - FILE *out; - - g_return_if_fail (format != NULL); - - va_start (args, format); - str = g_strdup_vprintf (format, args); - va_end (args); - -#ifdef WITH_VERBOSE_MODE - out = logfile ? logfile : stderr; -#else - out = stderr; -#endif - - if (no_prefix == 0) - utf8_fputs ("Window manager warning: ", out); - utf8_fputs (str, out); - utf8_fputs ("\n", out); - - fflush (out); - - g_free (str); -} - -void -meta_fatal (const char *format, ...) -{ - va_list args; - gchar *str; - FILE *out; - - g_warn_if_fail (format); - if (!format) - meta_exit (META_EXIT_ERROR); - - va_start (args, format); - str = g_strdup_vprintf (format, args); - va_end (args); - -#ifdef WITH_VERBOSE_MODE - out = logfile ? logfile : stderr; -#else - out = stderr; -#endif - - if (no_prefix == 0) - utf8_fputs ("Window manager error: ", out); - utf8_fputs (str, out); - utf8_fputs ("\n", out); - - fflush (out); - - g_free (str); - - meta_exit (META_EXIT_ERROR); -} - -void -meta_push_no_msg_prefix (void) -{ - ++no_prefix; -} - -void -meta_pop_no_msg_prefix (void) -{ - g_return_if_fail (no_prefix > 0); - - --no_prefix; -} - -void -meta_exit (MetaExitCode code) -{ - - exit (code); -} - -gint -meta_unsigned_long_equal (gconstpointer v1, - gconstpointer v2) -{ - return *((const gulong*) v1) == *((const gulong*) v2); -} - -guint -meta_unsigned_long_hash (gconstpointer v) -{ - gulong val = * (const gulong *) v; - - /* I'm not sure this works so well. */ -#if GLIB_SIZEOF_LONG > 4 - return (guint) (val ^ (val >> 32)); -#else - return val; -#endif -} - -const char* -meta_gravity_to_string (MetaGravity gravity) -{ - switch (gravity) - { - case META_GRAVITY_NORTH_WEST: - return "META_GRAVITY_NORTH_WEST"; - break; - case META_GRAVITY_NORTH: - return "META_GRAVITY_NORTH"; - break; - case META_GRAVITY_NORTH_EAST: - return "META_GRAVITY_NORTH_EAST"; - break; - case META_GRAVITY_WEST: - return "META_GRAVITY_WEST"; - break; - case META_GRAVITY_CENTER: - return "META_GRAVITY_CENTER"; - break; - case META_GRAVITY_EAST: - return "META_GRAVITY_EAST"; - break; - case META_GRAVITY_SOUTH_WEST: - return "META_GRAVITY_SOUTH_WEST"; - break; - case META_GRAVITY_SOUTH: - return "META_GRAVITY_SOUTH"; - break; - case META_GRAVITY_SOUTH_EAST: - return "META_GRAVITY_SOUTH_EAST"; - break; - case META_GRAVITY_STATIC: - return "META_GRAVITY_STATIC"; - break; - default: - return "META_GRAVITY_NORTH_WEST"; - break; - } -} - -char* -meta_external_binding_name_for_action (guint keybinding_action) -{ - return g_strdup_printf ("external-grab-%u", keybinding_action); -} - -/* Command line arguments are passed in the locale encoding; in almost - * all cases, we'd hope that is UTF-8 and no conversion is necessary. - * If it's not UTF-8, then it's possible that the message isn't - * representable in the locale encoding. - */ -static void -append_argument (GPtrArray *args, - const char *arg) -{ - char *locale_arg = g_locale_from_utf8 (arg, -1, NULL, NULL, NULL); - - /* This is cheesy, but it's better to have a few ???'s in the dialog - * for an unresponsive application than no dialog at all appear */ - if (!locale_arg) - locale_arg = g_strdup ("???"); - - g_ptr_array_add (args, locale_arg); -} - -/** - * meta_show_dialog: (skip) - * @type: type of dialog - * @message: message - * @timeout: timeout - * @display: display - * @ok_text: text for Ok button - * @cancel_text: text for Cancel button - * @icon_name: icon name - * @transient_for: window XID of parent - * @columns: columns - * @entries: entries - * - */ -GPid -meta_show_dialog (const char *type, - const char *message, - const char *timeout, - const char *display, - const char *ok_text, - const char *cancel_text, - const char *icon_name, - const int transient_for, - GSList *columns, - GSList *entries) -{ - GError *error = NULL; - GSList *tmp; - GPid child_pid; - GPtrArray *args; - - args = g_ptr_array_new (); - - append_argument (args, "zenity"); - append_argument (args, type); - - if (display) - { - append_argument (args, "--display"); - append_argument (args, display); - } - - append_argument (args, "--class"); - append_argument (args, "mutter-dialog"); - append_argument (args, "--title"); - append_argument (args, ""); - append_argument (args, "--text"); - append_argument (args, message); - - if (timeout) - { - append_argument (args, "--timeout"); - append_argument (args, timeout); - } - - if (ok_text) - { - append_argument (args, "--ok-label"); - append_argument (args, ok_text); - } - - if (cancel_text) - { - append_argument (args, "--cancel-label"); - append_argument (args, cancel_text); - } - - if (icon_name) - { - append_argument (args, "--icon-name"); - append_argument (args, icon_name); - } - - tmp = columns; - while (tmp) - { - append_argument (args, "--column"); - append_argument (args, tmp->data); - tmp = tmp->next; - } - - tmp = entries; - while (tmp) - { - append_argument (args, tmp->data); - tmp = tmp->next; - } - - if (transient_for) - { - gchar *env = g_strdup_printf("%d", transient_for); - setenv ("WINDOWID", env, 1); - g_free (env); - - append_argument (args, "--modal"); - } - - g_ptr_array_add (args, NULL); /* NULL-terminate */ - - g_spawn_async ( - "/", - (gchar**) args->pdata, - NULL, - G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, - NULL, NULL, - &child_pid, - &error - ); - - if (transient_for) - unsetenv ("WINDOWID"); - - g_ptr_array_free (args, TRUE); - - if (error) - { - meta_warning ("%s", error->message); - g_error_free (error); - } - - return child_pid; -} - -MetaLocaleDirection -meta_get_locale_direction (void) -{ - switch (gtk_get_locale_direction ()) - { - case GTK_TEXT_DIR_LTR: - return META_LOCALE_DIRECTION_LTR; - case GTK_TEXT_DIR_RTL: - return META_LOCALE_DIRECTION_RTL; - default: - g_assert_not_reached (); - return 0; - } -} - -char * -meta_generate_random_id (GRand *rand, - int length) -{ - char *id; - int i; - - /* Generate a random string of printable ASCII characters. */ - - id = g_new0 (char, length + 1); - for (i = 0; i < length; i++) - id[i] = (char) g_rand_int_range (rand, 32, 127); - - return id; -} - - -void -meta_add_clutter_debug_flags (ClutterDebugFlag debug_flags, - ClutterDrawDebugFlag draw_flags, - ClutterPickDebugFlag pick_flags) -{ - clutter_add_debug_flags (debug_flags, draw_flags, pick_flags); -} - -void -meta_remove_clutter_debug_flags (ClutterDebugFlag debug_flags, - ClutterDrawDebugFlag draw_flags, - ClutterPickDebugFlag pick_flags) -{ - clutter_remove_debug_flags (debug_flags, draw_flags, pick_flags); -} - -void -meta_get_clutter_debug_flags (ClutterDebugFlag *debug_flags, - ClutterDrawDebugFlag *draw_flags, - ClutterPickDebugFlag *pick_flags) -{ - clutter_get_debug_flags (debug_flags, draw_flags, pick_flags); -} - -void -meta_add_debug_paint_flag (MetaDebugPaintFlag flag) -{ - debug_paint_flags |= flag; -} - -void -meta_remove_debug_paint_flag (MetaDebugPaintFlag flag) -{ - debug_paint_flags &= ~flag; -} - -MetaDebugPaintFlag -meta_get_debug_paint_flags (void) -{ - return debug_paint_flags; -} diff --git a/src/core/window-private.h b/src/core/window-private.h deleted file mode 100644 index d1730c988..000000000 --- a/src/core/window-private.h +++ /dev/null @@ -1,888 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/** - * \file window-private.h Windows which Mutter manages - * - * Managing X windows. - * This file contains methods on this class which are available to - * routines in core but not outside it. (See window.h for the routines - * which the rest of the world is allowed to use.) - */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002 Red Hat, Inc. - * Copyright (C) 2003, 2004 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * 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 . - */ - -#ifndef META_WINDOW_PRIVATE_H -#define META_WINDOW_PRIVATE_H - -#include -#include -#include - -#include "backends/meta-logical-monitor.h" -#include "clutter/clutter.h" -#include "core/stack.h" -#include "meta/compositor.h" -#include "meta/meta-close-dialog.h" -#include "meta/util.h" -#include "meta/window.h" -#include "wayland/meta-wayland-types.h" -#include "x11/group-private.h" - -typedef struct _MetaWindowQueue MetaWindowQueue; - -typedef enum -{ - META_CLIENT_TYPE_UNKNOWN = 0, - META_CLIENT_TYPE_APPLICATION = 1, - META_CLIENT_TYPE_PAGER = 2, - META_CLIENT_TYPE_MAX_RECOGNIZED = 2 -} MetaClientType; - -typedef enum -{ - META_QUEUE_CALC_SHOWING = 1 << 0, - META_QUEUE_MOVE_RESIZE = 1 << 1, - META_QUEUE_UPDATE_ICON = 1 << 2, -} MetaQueueType; - -#define NUMBER_OF_QUEUES 3 - -typedef enum -{ - META_MOVE_RESIZE_CONFIGURE_REQUEST = 1 << 0, - META_MOVE_RESIZE_USER_ACTION = 1 << 1, - META_MOVE_RESIZE_MOVE_ACTION = 1 << 2, - META_MOVE_RESIZE_RESIZE_ACTION = 1 << 3, - META_MOVE_RESIZE_WAYLAND_FINISH_MOVE_RESIZE = 1 << 4, - META_MOVE_RESIZE_STATE_CHANGED = 1 << 5, - META_MOVE_RESIZE_UNMAXIMIZE = 1 << 6, - META_MOVE_RESIZE_UNFULLSCREEN = 1 << 7, - META_MOVE_RESIZE_FORCE_MOVE = 1 << 8, - META_MOVE_RESIZE_WAYLAND_STATE_CHANGED = 1 << 9, - META_MOVE_RESIZE_FORCE_UPDATE_MONITOR = 1 << 10, - META_MOVE_RESIZE_PLACEMENT_CHANGED = 1 << 11, -} MetaMoveResizeFlags; - -typedef enum -{ - META_MOVE_RESIZE_RESULT_MOVED = 1 << 0, - META_MOVE_RESIZE_RESULT_RESIZED = 1 << 1, - META_MOVE_RESIZE_RESULT_FRAME_SHAPE_CHANGED = 1 << 2, - META_MOVE_RESIZE_RESULT_STATE_CHANGED = 1 << 3, -} MetaMoveResizeResultFlags; - -typedef enum -{ - META_PLACEMENT_GRAVITY_NONE = 0, - META_PLACEMENT_GRAVITY_TOP = 1 << 0, - META_PLACEMENT_GRAVITY_BOTTOM = 1 << 1, - META_PLACEMENT_GRAVITY_LEFT = 1 << 2, - META_PLACEMENT_GRAVITY_RIGHT = 1 << 3, -} MetaPlacementGravity; - -typedef enum -{ - META_PLACEMENT_ANCHOR_NONE = 0, - META_PLACEMENT_ANCHOR_TOP = 1 << 0, - META_PLACEMENT_ANCHOR_BOTTOM = 1 << 1, - META_PLACEMENT_ANCHOR_LEFT = 1 << 2, - META_PLACEMENT_ANCHOR_RIGHT = 1 << 3, -} MetaPlacementAnchor; - -typedef enum -{ - META_PLACEMENT_CONSTRAINT_ADJUSTMENT_NONE = 0, - META_PLACEMENT_CONSTRAINT_ADJUSTMENT_SLIDE_X = 1 << 0, - META_PLACEMENT_CONSTRAINT_ADJUSTMENT_SLIDE_Y = 1 << 1, - META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_X = 1 << 2, - META_PLACEMENT_CONSTRAINT_ADJUSTMENT_FLIP_Y = 1 << 3, - META_PLACEMENT_CONSTRAINT_ADJUSTMENT_RESIZE_X = 1 << 4, - META_PLACEMENT_CONSTRAINT_ADJUSTMENT_RESIZE_Y = 1 << 5, -} MetaPlacementConstraintAdjustment; - -typedef enum _MetaWindowUpdateMonitorFlags -{ - META_WINDOW_UPDATE_MONITOR_FLAGS_NONE = 0, - META_WINDOW_UPDATE_MONITOR_FLAGS_USER_OP = 1 << 0, - META_WINDOW_UPDATE_MONITOR_FLAGS_FORCE = 1 << 1, -} MetaWindowUpdateMonitorFlags; - -typedef struct _MetaPlacementRule -{ - MetaRectangle anchor_rect; - MetaPlacementGravity gravity; - MetaPlacementAnchor anchor; - MetaPlacementConstraintAdjustment constraint_adjustment; - int offset_x; - int offset_y; - int width; - int height; - - gboolean is_reactive; - - MetaRectangle parent_rect; -} MetaPlacementRule; - -typedef enum _MetaPlacementState -{ - META_PLACEMENT_STATE_UNCONSTRAINED, - META_PLACEMENT_STATE_CONSTRAINED_PENDING, - META_PLACEMENT_STATE_CONSTRAINED_CONFIGURED, - META_PLACEMENT_STATE_CONSTRAINED_FINISHED, - META_PLACEMENT_STATE_INVALIDATED, -} MetaPlacementState; - -typedef enum -{ - META_EDGE_CONSTRAINT_NONE = 0, - META_EDGE_CONSTRAINT_WINDOW = 1, - META_EDGE_CONSTRAINT_MONITOR = 2, -} MetaEdgeConstraint; - -typedef enum -{ - META_EDGE_RESISTANCE_DEFAULT = 0, - META_EDGE_RESISTANCE_SNAP = 1 << 0, - META_EDGE_RESISTANCE_KEYBOARD_OP = 1 << 1, - META_EDGE_RESISTANCE_WINDOWS = 1 << 2, -} MetaEdgeResistanceFlags; - -struct _MetaWindow -{ - GObject parent_instance; - - MetaDisplay *display; - uint64_t id; - guint64 stamp; - MetaLogicalMonitor *monitor; - MetaWorkspace *workspace; - MetaWindowClientType client_type; - MetaWaylandSurface *surface; - Window xwindow; - /* may be NULL! not all windows get decorated */ - MetaFrame *frame; - int depth; - Visual *xvisual; - char *desc; /* used in debug spew */ - char *title; - - cairo_surface_t *icon; - cairo_surface_t *mini_icon; - - MetaWindowType type; - - /* NOTE these five are not in UTF-8, we just treat them as random - * binary data - */ - char *res_class; - char *res_name; - char *role; - char *sm_client_id; - char *wm_client_machine; - - char *startup_id; - char *mutter_hints; - char *sandboxed_app_id; - char *gtk_theme_variant; - char *gtk_application_id; - char *gtk_unique_bus_name; - char *gtk_application_object_path; - char *gtk_window_object_path; - char *gtk_app_menu_object_path; - char *gtk_menubar_object_path; - - Window xtransient_for; - Window xgroup_leader; - Window xclient_leader; - MetaWindow *transient_for; - - /* Initial workspace property */ - int initial_workspace; - - /* Initial timestamp property */ - guint32 initial_timestamp; - - /* Whether this is an override redirect window or not */ - guint override_redirect : 1; - - /* Whether we're maximized */ - guint maximized_horizontally : 1; - guint maximized_vertically : 1; - - /* Whether we have to maximize/minimize after placement */ - guint maximize_horizontally_after_placement : 1; - guint maximize_vertically_after_placement : 1; - guint minimize_after_placement : 1; - - /* The current tile mode */ - MetaTileMode tile_mode; - - /* The last "full" maximized/unmaximized state. We need to keep track of - * that to toggle between normal/tiled or maximized/tiled states. */ - guint saved_maximize : 1; - int tile_monitor_number; - - struct { - MetaEdgeConstraint top; - MetaEdgeConstraint right; - MetaEdgeConstraint bottom; - MetaEdgeConstraint left; - } edge_constraints; - - double tile_hfraction; - - uint64_t preferred_output_winsys_id; - - /* Whether we're shaded */ - guint shaded : 1; - - /* Whether we're fullscreen */ - guint fullscreen : 1; - - /* Whether the window is marked as urgent */ - guint urgent : 1; - - /* Area to cover when in fullscreen mode. If _NET_WM_FULLSCREEN_MONITORS has - * been overridden (via a client message), the window will cover the union of - * these monitors. If not, this is the single monitor which the window's - * origin is on. */ - struct { - MetaLogicalMonitor *top; - MetaLogicalMonitor *bottom; - MetaLogicalMonitor *left; - MetaLogicalMonitor *right; - } fullscreen_monitors; - - /* Whether we're trying to constrain the window to be fully onscreen */ - guint require_fully_onscreen : 1; - - /* Whether we're trying to constrain the window to be on a single monitor */ - guint require_on_single_monitor : 1; - - /* Whether we're trying to constrain the window's titlebar to be onscreen */ - guint require_titlebar_visible : 1; - - /* Whether we're sticky in the multi-workspace sense - * (vs. the not-scroll-with-viewport sense, we don't - * have no stupid viewports) - */ - guint on_all_workspaces : 1; - - /* This is true if the client requested sticky, and implies on_all_workspaces == TRUE, - * however on_all_workspaces can be set TRUE for other internal reasons too, such as - * being override_redirect or being on the non-primary monitor. */ - guint on_all_workspaces_requested : 1; - - /* Minimize is the state controlled by the minimize button */ - guint minimized : 1; - guint tab_unminimized : 1; - - /* Whether the window is mapped; actual server-side state - * see also unmaps_pending - */ - guint mapped : 1; - - /* Whether window has been hidden from view by lowering it to the bottom - * of window stack. - */ - guint hidden : 1; - - /* Whether the compositor thinks the window is visible. - * This should match up with calls to meta_compositor_show_window / - * meta_compositor_hide_window. - */ - guint visible_to_compositor : 1; - - /* Whether the compositor knows about the window. - * This should match up with calls to meta_compositor_add_window / - * meta_compositor_remove_window. - */ - guint known_to_compositor : 1; - - /* When we next show or hide the window, what effect we should - * tell the compositor to perform. - */ - guint pending_compositor_effect : 4; /* MetaCompEffect */ - - /* Iconic is the state in WM_STATE; happens for workspaces/shading - * in addition to minimize - */ - guint iconic : 1; - /* initially_iconic is the WM_HINTS setting when we first manage - * the window. It's taken to mean initially minimized. - */ - guint initially_iconic : 1; - - /* whether an initial workspace was explicitly set */ - guint initial_workspace_set : 1; - - /* whether an initial timestamp was explicitly set */ - guint initial_timestamp_set : 1; - - /* whether net_wm_user_time has been set yet */ - guint net_wm_user_time_set : 1; - - /* whether net_wm_icon_geometry has been set */ - guint icon_geometry_set : 1; - - /* Globally active / No input */ - guint input : 1; - - /* MWM hints about features of window */ - guint mwm_decorated : 1; - guint mwm_border_only : 1; - guint mwm_has_close_func : 1; - guint mwm_has_minimize_func : 1; - guint mwm_has_maximize_func : 1; - guint mwm_has_move_func : 1; - guint mwm_has_resize_func : 1; - - /* Computed features of window */ - guint decorated : 1; - guint border_only : 1; - guint always_sticky : 1; - guint has_close_func : 1; - guint has_minimize_func : 1; - guint has_maximize_func : 1; - guint has_shade_func : 1; - guint has_move_func : 1; - guint has_resize_func : 1; - guint has_fullscreen_func : 1; - - /* Computed whether to skip taskbar or not */ - guint skip_taskbar : 1; - guint skip_pager : 1; - guint skip_from_window_list : 1; - - /* TRUE if client set these */ - guint wm_state_above : 1; - guint wm_state_below : 1; - - /* EWHH demands attention flag */ - guint wm_state_demands_attention : 1; - - /* TRUE iff window == window->display->focus_window */ - guint has_focus : 1; - - /* Have we placed this window? */ - guint placed : 1; - - /* Is this not a transient of the focus window which is being denied focus? */ - guint denied_focus_and_not_transient : 1; - - /* Has this window not ever been shown yet? */ - guint showing_for_first_time : 1; - - /* Are we in meta_window_unmanage()? */ - guint unmanaging : 1; - - /* Are we in meta_window_new()? */ - guint constructing : 1; - - /* Are we in the various queues? (Bitfield: see META_WINDOW_IS_IN_QUEUE) */ - guint is_in_queues : NUMBER_OF_QUEUES; - - /* Used by keybindings.c */ - guint keys_grabbed : 1; /* normal keybindings grabbed */ - guint grab_on_frame : 1; /* grabs are on the frame */ - guint all_keys_grabbed : 1; /* AnyKey grabbed */ - - /* Set if the reason for unmanaging the window is that - * it was withdrawn - */ - guint withdrawn : 1; - - /* TRUE if constrain_position should calc placement. - * only relevant if !window->placed - */ - guint calc_placement : 1; - - /* if TRUE, window was maximized at start of current grab op */ - guint shaken_loose : 1; - - /* if TRUE we have a grab on the focus click buttons */ - guint have_focus_click_grab : 1; - - /* if TRUE, application is buggy and SYNC resizing is turned off */ - guint disable_sync : 1; - - /* if TRUE, window is attached to its parent */ - guint attached : 1; - - /* whether or not the window is from a program running on another machine */ - guint is_remote : 1; - - /* whether focus should be restored on map */ - guint restore_focus_on_map : 1; - - /* if non-NULL, the bounds of the window frame */ - cairo_region_t *frame_bounds; - - /* if non-NULL, the bounding shape region of the window. Relative to - * the server-side client window. */ - cairo_region_t *shape_region; - - /* if non-NULL, the opaque region _NET_WM_OPAQUE_REGION */ - cairo_region_t *opaque_region; - - /* the input shape region for picking */ - cairo_region_t *input_region; - - /* _NET_WM_WINDOW_OPACITY rescaled to 0xFF */ - guint8 opacity; - - /* if TRUE, the we have the new form of sync request counter which - * also handles application frames */ - guint extended_sync_request_counter : 1; - - /* Note: can be NULL */ - GSList *struts; - - /* XSync update counter */ - XSyncCounter sync_request_counter; - gint64 sync_request_serial; - gint64 sync_request_wait_serial; - guint sync_request_timeout_id; - /* alarm monitoring client's _NET_WM_SYNC_REQUEST_COUNTER */ - XSyncAlarm sync_request_alarm; - - /* Number of UnmapNotify that are caused by us, if - * we get UnmapNotify with none pending then the client - * is withdrawing the window. - */ - int unmaps_pending; - - /* Number of XReparentWindow requests that we have queued. - */ - int reparents_pending; - - /* See docs for meta_window_get_stable_sequence() */ - guint32 stable_sequence; - - /* set to the most recent user-interaction event timestamp that we - know about for this window */ - guint32 net_wm_user_time; - - /* window that gets updated net_wm_user_time values */ - Window user_time_window; - - gboolean has_custom_frame_extents; - GtkBorder custom_frame_extents; - - /* The rectangles here are in "frame rect" coordinates. See the - * comment at the top of meta_window_move_resize_internal() for more - * information. */ - - /* The current window geometry of the window. */ - MetaRectangle rect; - - /* The geometry to restore when we unmaximize. */ - MetaRectangle saved_rect; - - /* The geometry to restore when we unfullscreen. */ - MetaRectangle saved_rect_fullscreen; - - /* This is the geometry the window will have if no constraints have - * applied. We use this whenever we are moving implicitly (for example, - * if we move to avoid a panel, we can snap back to this position if - * the panel moves again). - */ - MetaRectangle unconstrained_rect; - - /* The rectangle of the "server-side" geometry of the buffer, - * in root coordinates. - * - * For X11 windows, this matches XGetGeometry of the toplevel. - * - * For Wayland windows, the position matches the position of the - * surface associated with shell surface (wl_shell_surface, xdg_surface - * etc). The size matches the size surface size as displayed in the stage. - */ - MetaRectangle buffer_rect; - - /* Cached net_wm_icon_geometry */ - MetaRectangle icon_geometry; - - /* x/y/w/h here get filled with ConfigureRequest values */ - XSizeHints size_hints; - - /* Managed by stack.c */ - MetaStackLayer layer; - int stack_position; /* see comment in stack.h */ - - /* Managed by delete.c */ - MetaCloseDialog *close_dialog; - - /* maintained by group.c */ - MetaGroup *group; - - GObject *compositor_private; - - /* Focused window that is (directly or indirectly) attached to this one */ - MetaWindow *attached_focus_window; - - /* The currently complementary tiled window, if any */ - MetaWindow *tile_match; - - struct { - MetaPlacementRule *rule; - MetaPlacementState state; - - struct { - int x; - int y; - int rel_x; - int rel_y; - } pending; - - struct { - int rel_x; - int rel_y; - } current; - } placement; - - guint unmanage_idle_id; - - pid_t client_pid; -}; - -struct _MetaWindowClass -{ - GObjectClass parent_class; - - void (*manage) (MetaWindow *window); - void (*unmanage) (MetaWindow *window); - void (*ping) (MetaWindow *window, - guint32 serial); - void (*delete) (MetaWindow *window, - guint32 timestamp); - void (*kill) (MetaWindow *window); - void (*focus) (MetaWindow *window, - guint32 timestamp); - void (*grab_op_began) (MetaWindow *window, - MetaGrabOp op); - void (*grab_op_ended) (MetaWindow *window, - MetaGrabOp op); - void (*current_workspace_changed) (MetaWindow *window); - void (*move_resize_internal) (MetaWindow *window, - MetaGravity gravity, - MetaRectangle unconstrained_rect, - MetaRectangle constrained_rect, - MetaRectangle temporary_rect, - int rel_x, - int rel_y, - MetaMoveResizeFlags flags, - MetaMoveResizeResultFlags *result); - gboolean (*update_struts) (MetaWindow *window); - void (*get_default_skip_hints) (MetaWindow *window, - gboolean *skip_taskbar_out, - gboolean *skip_pager_out); - gboolean (*update_icon) (MetaWindow *window, - cairo_surface_t **icon, - cairo_surface_t **mini_icon); - pid_t (*get_client_pid) (MetaWindow *window); - void (*update_main_monitor) (MetaWindow *window, - MetaWindowUpdateMonitorFlags flags); - void (*main_monitor_changed) (MetaWindow *window, - const MetaLogicalMonitor *old); - void (*adjust_fullscreen_monitor_rect) (MetaWindow *window, - MetaRectangle *monitor_rect); - void (*force_restore_shortcuts) (MetaWindow *window, - ClutterInputDevice *source); - gboolean (*shortcuts_inhibited) (MetaWindow *window, - ClutterInputDevice *source); - gboolean (*is_focusable) (MetaWindow *window); - gboolean (*is_stackable) (MetaWindow *window); - gboolean (*can_ping) (MetaWindow *window); - gboolean (*are_updates_frozen) (MetaWindow *window); - gboolean (*is_focus_async) (MetaWindow *window); - - MetaStackLayer (*calculate_layer) (MetaWindow *window); - - void (* map) (MetaWindow *window); - void (* unmap) (MetaWindow *window); -}; - -/* These differ from window->has_foo_func in that they consider - * the dynamic window state such as "maximized", not just the - * window's type - */ -#define META_WINDOW_MAXIMIZED(w) ((w)->maximized_horizontally && \ - (w)->maximized_vertically) -#define META_WINDOW_MAXIMIZED_VERTICALLY(w) ((w)->maximized_vertically) -#define META_WINDOW_MAXIMIZED_HORIZONTALLY(w) ((w)->maximized_horizontally) -#define META_WINDOW_TILED_SIDE_BY_SIDE(w) ((w)->maximized_vertically && \ - !(w)->maximized_horizontally && \ - (w)->tile_mode != META_TILE_NONE) -#define META_WINDOW_TILED_LEFT(w) (META_WINDOW_TILED_SIDE_BY_SIDE(w) && \ - (w)->tile_mode == META_TILE_LEFT) -#define META_WINDOW_TILED_RIGHT(w) (META_WINDOW_TILED_SIDE_BY_SIDE(w) && \ - (w)->tile_mode == META_TILE_RIGHT) -#define META_WINDOW_TILED_MAXIMIZED(w)(META_WINDOW_MAXIMIZED(w) && \ - (w)->tile_mode == META_TILE_MAXIMIZED) -#define META_WINDOW_ALLOWS_MOVE(w) ((w)->has_move_func && !(w)->fullscreen) -#define META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS(w) ((w)->has_resize_func && !META_WINDOW_MAXIMIZED (w) && !(w)->fullscreen && !(w)->shaded) -#define META_WINDOW_ALLOWS_RESIZE(w) (META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS (w) && \ - (((w)->size_hints.min_width < (w)->size_hints.max_width) || \ - ((w)->size_hints.min_height < (w)->size_hints.max_height))) -#define META_WINDOW_ALLOWS_HORIZONTAL_RESIZE(w) (META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS (w) && (w)->size_hints.min_width < (w)->size_hints.max_width) -#define META_WINDOW_ALLOWS_VERTICAL_RESIZE(w) (META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS (w) && (w)->size_hints.min_height < (w)->size_hints.max_height) - -MetaWindow * _meta_window_shared_new (MetaDisplay *display, - MetaWindowClientType client_type, - MetaWaylandSurface *surface, - Window xwindow, - gulong existing_wm_state, - MetaCompEffect effect, - XWindowAttributes *attrs); - -void meta_window_unmanage (MetaWindow *window, - guint32 timestamp); -void meta_window_unmanage_on_idle (MetaWindow *window); -void meta_window_queue (MetaWindow *window, - guint queuebits); -META_EXPORT_TEST -void meta_window_untile (MetaWindow *window); - -META_EXPORT_TEST -void meta_window_tile (MetaWindow *window, - MetaTileMode mode); -MetaTileMode meta_window_get_tile_mode (MetaWindow *window); -void meta_window_restore_tile (MetaWindow *window, - MetaTileMode mode, - int width, - int height); -void meta_window_maximize_internal (MetaWindow *window, - MetaMaximizeFlags directions, - MetaRectangle *saved_rect); - -void meta_window_make_fullscreen_internal (MetaWindow *window); -void meta_window_update_fullscreen_monitors (MetaWindow *window, - MetaLogicalMonitor *top, - MetaLogicalMonitor *bottom, - MetaLogicalMonitor *left, - MetaLogicalMonitor *right); - -gboolean meta_window_has_fullscreen_monitors (MetaWindow *window); - -void meta_window_adjust_fullscreen_monitor_rect (MetaWindow *window, - MetaRectangle *monitor_rect); - -void meta_window_resize_frame_with_gravity (MetaWindow *window, - gboolean user_op, - int w, - int h, - MetaGravity gravity); - -/* Return whether the window should be currently mapped */ -gboolean meta_window_should_be_showing (MetaWindow *window); - -void meta_window_update_struts (MetaWindow *window); - -/* gets position we need to set to stay in current position, - * assuming position will be gravity-compensated. i.e. - * this is the position a client would send in a configure - * request. - */ -void meta_window_get_gravity_position (MetaWindow *window, - MetaGravity gravity, - int *x, - int *y); -/* Get geometry for saving in the session; x/y are gravity - * position, and w/h are in resize inc above the base size. - */ -void meta_window_get_session_geometry (MetaWindow *window, - int *x, - int *y, - int *width, - int *height); - -void meta_window_update_unfocused_button_grabs (MetaWindow *window); - -void meta_window_set_focused_internal (MetaWindow *window, - gboolean focused); - -gboolean meta_window_is_focusable (MetaWindow *window); - -gboolean meta_window_can_ping (MetaWindow *window); - -MetaStackLayer meta_window_calculate_layer (MetaWindow *window); - -void meta_window_current_workspace_changed (MetaWindow *window); - -void meta_window_show_menu (MetaWindow *window, - MetaWindowMenuType menu, - int x, - int y); - -void meta_window_show_menu_for_rect (MetaWindow *window, - MetaWindowMenuType menu, - MetaRectangle *rect); - -gboolean meta_window_handle_mouse_grab_op_event (MetaWindow *window, - const ClutterEvent *event); - -GList* meta_window_get_workspaces (MetaWindow *window); - -void meta_window_get_work_area_for_logical_monitor (MetaWindow *window, - MetaLogicalMonitor *logical_monitor, - MetaRectangle *area); - -int meta_window_get_current_tile_monitor_number (MetaWindow *window); -void meta_window_get_tile_area (MetaWindow *window, - MetaTileMode mode, - MetaRectangle *tile_area); - - -gboolean meta_window_same_application (MetaWindow *window, - MetaWindow *other_window); - -#define META_WINDOW_IN_NORMAL_TAB_CHAIN_TYPE(w) \ - ((w)->type != META_WINDOW_DOCK && (w)->type != META_WINDOW_DESKTOP) -#define META_WINDOW_IN_NORMAL_TAB_CHAIN(w) \ - (meta_window_is_focusable (w) && META_WINDOW_IN_NORMAL_TAB_CHAIN_TYPE (w) && (!(w)->skip_taskbar)) -#define META_WINDOW_IN_DOCK_TAB_CHAIN(w) \ - (meta_window_is_focusable (w) && (! META_WINDOW_IN_NORMAL_TAB_CHAIN_TYPE (w) || (w)->skip_taskbar)) -#define META_WINDOW_IN_GROUP_TAB_CHAIN(w, g) \ - (meta_window_is_focusable (w) && (!g || meta_window_get_group(w)==g)) - -void meta_window_free_delete_dialog (MetaWindow *window); - -void meta_window_update_keyboard_resize (MetaWindow *window, - gboolean update_cursor); -void meta_window_update_keyboard_move (MetaWindow *window); - -MetaStackLayer meta_window_get_default_layer (MetaWindow *window); -void meta_window_update_layer (MetaWindow *window); - -void meta_window_recalc_features (MetaWindow *window); - -void meta_window_set_type (MetaWindow *window, - MetaWindowType type); - -void meta_window_frame_size_changed (MetaWindow *window); - -gboolean meta_window_is_in_stack (MetaWindow *window); - -void meta_window_stack_just_below (MetaWindow *window, - MetaWindow *below_this_one); - -void meta_window_stack_just_above (MetaWindow *window, - MetaWindow *above_this_one); - -void meta_window_set_user_time (MetaWindow *window, - guint32 timestamp); - -void meta_window_update_for_monitors_changed (MetaWindow *window); -void meta_window_on_all_workspaces_changed (MetaWindow *window); - -gboolean meta_window_should_attach_to_parent (MetaWindow *window); -gboolean meta_window_can_tile_side_by_side (MetaWindow *window); - -void meta_window_compute_tile_match (MetaWindow *window); - -gboolean meta_window_updates_are_frozen (MetaWindow *window); - -void meta_window_set_title (MetaWindow *window, - const char *title); -void meta_window_set_wm_class (MetaWindow *window, - const char *wm_class, - const char *wm_instance); -void meta_window_set_gtk_dbus_properties (MetaWindow *window, - const char *application_id, - const char *unique_bus_name, - const char *appmenu_path, - const char *menubar_path, - const char *application_object_path, - const char *window_object_path); - -gboolean meta_window_has_transient_type (MetaWindow *window); - -void meta_window_set_transient_for (MetaWindow *window, - MetaWindow *parent); - -void meta_window_set_opacity (MetaWindow *window, - guint8 opacity); - -void meta_window_handle_enter (MetaWindow *window, - guint32 timestamp, - guint root_x, - guint root_y); -void meta_window_handle_leave (MetaWindow *window); - -gboolean meta_window_handle_ui_frame_event (MetaWindow *window, - const ClutterEvent *event); - -void meta_window_handle_ungrabbed_event (MetaWindow *window, - const ClutterEvent *event); - -void meta_window_get_client_area_rect (const MetaWindow *window, - cairo_rectangle_int_t *rect); -void meta_window_get_titlebar_rect (MetaWindow *window, - MetaRectangle *titlebar_rect); - -void meta_window_activate_full (MetaWindow *window, - guint32 timestamp, - MetaClientType source_indication, - MetaWorkspace *workspace); - -META_EXPORT_TEST -MetaLogicalMonitor * meta_window_calculate_main_logical_monitor (MetaWindow *window); - -MetaLogicalMonitor * meta_window_get_main_logical_monitor (MetaWindow *window); -void meta_window_update_monitor (MetaWindow *window, - MetaWindowUpdateMonitorFlags flags); - -void meta_window_set_urgent (MetaWindow *window, - gboolean urgent); - -void meta_window_update_resize (MetaWindow *window, - MetaEdgeResistanceFlags flags, - int x, int y, - gboolean force); - -void meta_window_move_resize_internal (MetaWindow *window, - MetaMoveResizeFlags flags, - MetaGravity gravity, - MetaRectangle frame_rect); - -void meta_window_grab_op_began (MetaWindow *window, MetaGrabOp op); -void meta_window_grab_op_ended (MetaWindow *window, MetaGrabOp op); - -void meta_window_set_alive (MetaWindow *window, gboolean is_alive); - -gboolean meta_window_has_pointer (MetaWindow *window); - -void meta_window_emit_size_changed (MetaWindow *window); - -MetaPlacementRule *meta_window_get_placement_rule (MetaWindow *window); - -void meta_window_force_placement (MetaWindow *window, - gboolean force_move); - -void meta_window_force_restore_shortcuts (MetaWindow *window, - ClutterInputDevice *source); - -gboolean meta_window_shortcuts_inhibited (MetaWindow *window, - ClutterInputDevice *source); -gboolean meta_window_is_stackable (MetaWindow *window); -gboolean meta_window_is_focus_async (MetaWindow *window); -#endif diff --git a/src/core/window.c b/src/core/window.c deleted file mode 100644 index ea56f3328..000000000 --- a/src/core/window.c +++ /dev/null @@ -1,8665 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington, Anders Carlsson - * Copyright (C) 2002, 2003 Red Hat, Inc. - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * 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 . - */ - -/** - * SECTION:meta-window - * @title: MetaWindow - * @short_description: A display-agnostic abstraction for a window. - * - * #MetaWindow is the core abstraction in Mutter of a window. It has the - * properties you'd expect, such as a title, an icon, whether it's fullscreen, - * has decorations, etc. - * - * Since a lot of different kinds of windows exist, each window also a - * #MetaWindowType which denotes which kind of window we're exactly dealing - * with. For example, one expects slightly different behaviour from a dialog - * than a "normal" window. The type of a window can be queried with - * meta_window_get_type(). - * - * Common API for windows include: - * - Minimizing: meta_window_minimize() / meta_window_unminimize() - * - Maximizing: meta_window_maximize() / meta_window_unmaximize() - * - Fullscreen: meta_window_make_fullscreen() / meta_window_unmake_fullscreen() - * / meta_window_is_fullscreen() - * - * Each #MetaWindow is part of either one or all #MetaWorkspaces of the - * desktop. You can activate a window on a certain workspace using - * meta_window_activate_with_workspace(), and query on which workspace it is - * located using meta_window_located_on_workspace(). The workspace it is part - * of can be obtained using meta_window_get_workspace(). - * - * Each display protocol should make a subclass to be compatible with that - * protocols' specifics, for example #MetaWindowX11 and #MetaWindowWayland. - * This is independent of the protocol that the client uses, which is modeled - * using the #MetaWindowClientType enum. - * - * To integrate within the Clutter scene graph, which deals with the actual - * rendering, each #MetaWindow will be part of a #MetaWindowActor. - */ - -#include "config.h" - -#include "core/window-private.h" - -#include -#include -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-logical-monitor.h" -#include "cogl/cogl.h" -#include "core/boxes-private.h" -#include "core/constraints.h" -#include "core/edge-resistance.h" -#include "core/frame.h" -#include "core/keybindings-private.h" -#include "core/meta-workspace-manager-private.h" -#include "core/place.h" -#include "core/stack.h" -#include "core/util-private.h" -#include "core/workspace-private.h" -#include "meta/compositor-mutter.h" -#include "meta/group.h" -#include "meta/meta-cursor-tracker.h" -#include "meta/meta-enum-types.h" -#include "meta/meta-x11-errors.h" -#include "meta/prefs.h" -#include "ui/ui.h" -#include "x11/meta-x11-display-private.h" -#include "x11/window-props.h" -#include "x11/window-x11.h" -#include "x11/xprops.h" - -#ifdef HAVE_WAYLAND -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-surface.h" -#include "wayland/meta-window-wayland.h" -#include "wayland/meta-window-xwayland.h" -#endif - -/* Windows that unmaximize to a size bigger than that fraction of the workarea - * will be scaled down to that size (while maintaining aspect ratio). - * Windows that cover an area greater then this size are automaximized on map. - */ -#define MAX_UNMAXIMIZED_WINDOW_AREA .8 - -#define SNAP_SECURITY_LABEL_PREFIX "snap." - -static int destroying_windows_disallowed = 0; - -/* Each window has a "stamp" which is a non-recycled 64-bit ID. They - * start after the end of the XID space so that, for stacking - * we can keep a guint64 that represents one or the other - */ -static guint64 next_window_stamp = G_GUINT64_CONSTANT(0x100000000); - -static void invalidate_work_areas (MetaWindow *window); -static void set_wm_state (MetaWindow *window); -static void set_net_wm_state (MetaWindow *window); -static void meta_window_set_above (MetaWindow *window, - gboolean new_value); - -static void meta_window_show (MetaWindow *window); -static void meta_window_hide (MetaWindow *window); - -static void meta_window_save_rect (MetaWindow *window); - -static void ensure_mru_position_after (MetaWindow *window, - MetaWindow *after_this_one); - -static void meta_window_move_resize_now (MetaWindow *window); - -static void meta_window_unqueue (MetaWindow *window, guint queuebits); - -static void update_move (MetaWindow *window, - MetaEdgeResistanceFlags flags, - int x, - int y); -static gboolean update_move_timeout (gpointer data); -static void update_resize (MetaWindow *window, - MetaEdgeResistanceFlags flags, - int x, - int y, - gboolean force); -static gboolean update_resize_timeout (gpointer data); -static gboolean should_be_on_all_workspaces (MetaWindow *window); - -static void meta_window_flush_calc_showing (MetaWindow *window); - -static gboolean queue_calc_showing_func (MetaWindow *window, - void *data); - -static void meta_window_move_between_rects (MetaWindow *window, - MetaMoveResizeFlags move_resize_flags, - const MetaRectangle *old_area, - const MetaRectangle *new_area); - -static void unmaximize_window_before_freeing (MetaWindow *window); -static void unminimize_window_and_all_transient_parents (MetaWindow *window); - -static void meta_window_propagate_focus_appearance (MetaWindow *window, - gboolean focused); -static void meta_window_update_icon_now (MetaWindow *window, - gboolean force); - -static void set_workspace_state (MetaWindow *window, - gboolean on_all_workspaces, - MetaWorkspace *workspace); - -static MetaWindow * meta_window_find_tile_match (MetaWindow *window, - MetaTileMode mode); -static void update_edge_constraints (MetaWindow *window); - -/* Idle handlers for the three queues (run with meta_later_add()). The - * "data" parameter in each case will be a GINT_TO_POINTER of the - * index into the queue arrays to use. - * - * TODO: Possibly there is still some code duplication among these, which we - * need to sort out at some point. - */ -static gboolean idle_calc_showing (gpointer data); -static gboolean idle_move_resize (gpointer data); -static gboolean idle_update_icon (gpointer data); - -G_DEFINE_ABSTRACT_TYPE (MetaWindow, meta_window, G_TYPE_OBJECT); - -enum -{ - PROP_0, - - PROP_TITLE, - PROP_ICON, - PROP_MINI_ICON, - PROP_DECORATED, - PROP_FULLSCREEN, - PROP_MAXIMIZED_HORIZONTALLY, - PROP_MAXIMIZED_VERTICALLY, - PROP_MINIMIZED, - PROP_WINDOW_TYPE, - PROP_USER_TIME, - PROP_DEMANDS_ATTENTION, - PROP_URGENT, - PROP_SKIP_TASKBAR, - PROP_MUTTER_HINTS, - PROP_APPEARS_FOCUSED, - PROP_RESIZEABLE, - PROP_ABOVE, - PROP_WM_CLASS, - PROP_GTK_APPLICATION_ID, - PROP_GTK_UNIQUE_BUS_NAME, - PROP_GTK_APPLICATION_OBJECT_PATH, - PROP_GTK_WINDOW_OBJECT_PATH, - PROP_GTK_APP_MENU_OBJECT_PATH, - PROP_GTK_MENUBAR_OBJECT_PATH, - PROP_ON_ALL_WORKSPACES, - - PROP_LAST, -}; - -static GParamSpec *obj_props[PROP_LAST]; - -enum -{ - WORKSPACE_CHANGED, - FOCUS, - RAISED, - UNMANAGING, - UNMANAGED, - SIZE_CHANGED, - POSITION_CHANGED, - SHOWN, - - LAST_SIGNAL -}; - -static guint window_signals[LAST_SIGNAL] = { 0 }; - -static void -prefs_changed_callback (MetaPreference pref, - gpointer data) -{ - MetaWindow *window = data; - - if (pref == META_PREF_WORKSPACES_ONLY_ON_PRIMARY) - { - meta_window_on_all_workspaces_changed (window); - } - else if (pref == META_PREF_ATTACH_MODAL_DIALOGS && - window->type == META_WINDOW_MODAL_DIALOG) - { - window->attached = meta_window_should_attach_to_parent (window); - meta_window_recalc_features (window); - meta_window_queue (window, META_QUEUE_MOVE_RESIZE); - } -} - -static void -meta_window_real_grab_op_began (MetaWindow *window, - MetaGrabOp op) -{ -} - -static void -meta_window_real_grab_op_ended (MetaWindow *window, - MetaGrabOp op) -{ - window->shaken_loose = FALSE; -} - -static void -meta_window_real_current_workspace_changed (MetaWindow *window) -{ -} - -static gboolean -meta_window_real_update_struts (MetaWindow *window) -{ - return FALSE; -} - -static void -meta_window_real_get_default_skip_hints (MetaWindow *window, - gboolean *skip_taskbar_out, - gboolean *skip_pager_out) -{ - *skip_taskbar_out = FALSE; - *skip_pager_out = FALSE; -} - -static gboolean -meta_window_real_update_icon (MetaWindow *window, - cairo_surface_t **icon, - cairo_surface_t **mini_icon) -{ - *icon = NULL; - *mini_icon = NULL; - return FALSE; -} - -static pid_t -meta_window_real_get_client_pid (MetaWindow *window) -{ - return 0; -} - -static void -meta_window_finalize (GObject *object) -{ - MetaWindow *window = META_WINDOW (object); - - if (window->icon) - cairo_surface_destroy (window->icon); - - if (window->mini_icon) - cairo_surface_destroy (window->mini_icon); - - if (window->frame_bounds) - cairo_region_destroy (window->frame_bounds); - - if (window->shape_region) - cairo_region_destroy (window->shape_region); - - if (window->opaque_region) - cairo_region_destroy (window->opaque_region); - - if (window->input_region) - cairo_region_destroy (window->input_region); - - if (window->transient_for) - g_object_unref (window->transient_for); - - g_free (window->sm_client_id); - g_free (window->wm_client_machine); - g_free (window->startup_id); - g_free (window->role); - g_free (window->res_class); - g_free (window->res_name); - g_free (window->title); - g_free (window->desc); - g_free (window->sandboxed_app_id); - g_free (window->gtk_theme_variant); - g_free (window->gtk_application_id); - g_free (window->gtk_unique_bus_name); - g_free (window->gtk_application_object_path); - g_free (window->gtk_window_object_path); - g_free (window->gtk_app_menu_object_path); - g_free (window->gtk_menubar_object_path); - g_free (window->placement.rule); - - G_OBJECT_CLASS (meta_window_parent_class)->finalize (object); -} - -static void -meta_window_get_property(GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaWindow *win = META_WINDOW (object); - - switch (prop_id) - { - case PROP_TITLE: - g_value_set_string (value, win->title); - break; - case PROP_ICON: - g_value_set_pointer (value, win->icon); - break; - case PROP_MINI_ICON: - g_value_set_pointer (value, win->mini_icon); - break; - case PROP_DECORATED: - g_value_set_boolean (value, win->decorated); - break; - case PROP_FULLSCREEN: - g_value_set_boolean (value, win->fullscreen); - break; - case PROP_MAXIMIZED_HORIZONTALLY: - g_value_set_boolean (value, win->maximized_horizontally); - break; - case PROP_MAXIMIZED_VERTICALLY: - g_value_set_boolean (value, win->maximized_vertically); - break; - case PROP_MINIMIZED: - g_value_set_boolean (value, win->minimized); - break; - case PROP_WINDOW_TYPE: - g_value_set_enum (value, win->type); - break; - case PROP_USER_TIME: - g_value_set_uint (value, win->net_wm_user_time); - break; - case PROP_DEMANDS_ATTENTION: - g_value_set_boolean (value, win->wm_state_demands_attention); - break; - case PROP_URGENT: - g_value_set_boolean (value, win->urgent); - break; - case PROP_SKIP_TASKBAR: - g_value_set_boolean (value, win->skip_taskbar); - break; - case PROP_MUTTER_HINTS: - g_value_set_string (value, win->mutter_hints); - break; - case PROP_APPEARS_FOCUSED: - g_value_set_boolean (value, meta_window_appears_focused (win)); - break; - case PROP_WM_CLASS: - g_value_set_string (value, win->res_class); - break; - case PROP_RESIZEABLE: - g_value_set_boolean (value, win->has_resize_func); - break; - case PROP_ABOVE: - g_value_set_boolean (value, win->wm_state_above); - break; - case PROP_GTK_APPLICATION_ID: - g_value_set_string (value, win->gtk_application_id); - break; - case PROP_GTK_UNIQUE_BUS_NAME: - g_value_set_string (value, win->gtk_unique_bus_name); - break; - case PROP_GTK_APPLICATION_OBJECT_PATH: - g_value_set_string (value, win->gtk_application_object_path); - break; - case PROP_GTK_WINDOW_OBJECT_PATH: - g_value_set_string (value, win->gtk_window_object_path); - break; - case PROP_GTK_APP_MENU_OBJECT_PATH: - g_value_set_string (value, win->gtk_app_menu_object_path); - break; - case PROP_GTK_MENUBAR_OBJECT_PATH: - g_value_set_string (value, win->gtk_menubar_object_path); - break; - case PROP_ON_ALL_WORKSPACES: - g_value_set_boolean (value, win->on_all_workspaces); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_window_set_property(GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (prop_id) - { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_window_class_init (MetaWindowClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_window_finalize; - - object_class->get_property = meta_window_get_property; - object_class->set_property = meta_window_set_property; - - klass->grab_op_began = meta_window_real_grab_op_began; - klass->grab_op_ended = meta_window_real_grab_op_ended; - klass->current_workspace_changed = meta_window_real_current_workspace_changed; - klass->update_struts = meta_window_real_update_struts; - klass->get_default_skip_hints = meta_window_real_get_default_skip_hints; - klass->update_icon = meta_window_real_update_icon; - klass->get_client_pid = meta_window_real_get_client_pid; - - obj_props[PROP_TITLE] = - g_param_spec_string ("title", - "Title", - "The title of the window", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_props[PROP_ICON] = - g_param_spec_pointer ("icon", - "Icon", - "Normal icon, usually 96x96 pixels", - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_props[PROP_MINI_ICON] = - g_param_spec_pointer ("mini-icon", - "Mini Icon", - "Mini icon, usually 16x16 pixels", - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_props[PROP_DECORATED] = - g_param_spec_boolean ("decorated", - "Decorated", - "Whether window is decorated", - TRUE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_props[PROP_FULLSCREEN] = - g_param_spec_boolean ("fullscreen", - "Fullscreen", - "Whether window is fullscreened", - FALSE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_props[PROP_MAXIMIZED_HORIZONTALLY] = - g_param_spec_boolean ("maximized-horizontally", - "Maximized horizontally", - "Whether window is maximized horizontally", - FALSE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_props[PROP_MAXIMIZED_VERTICALLY] = - g_param_spec_boolean ("maximized-vertically", - "Maximizing vertically", - "Whether window is maximized vertically", - FALSE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_props[PROP_MINIMIZED] = - g_param_spec_boolean ("minimized", - "Minimizing", - "Whether window is minimized", - FALSE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_props[PROP_WINDOW_TYPE] = - g_param_spec_enum ("window-type", - "Window Type", - "The type of the window", - META_TYPE_WINDOW_TYPE, - META_WINDOW_NORMAL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_props[PROP_USER_TIME] = - g_param_spec_uint ("user-time", - "User time", - "Timestamp of last user interaction", - 0, - G_MAXUINT, - 0, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_props[PROP_DEMANDS_ATTENTION] = - g_param_spec_boolean ("demands-attention", - "Demands Attention", - "Whether the window has _NET_WM_STATE_DEMANDS_ATTENTION set", - FALSE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_props[PROP_URGENT] = - g_param_spec_boolean ("urgent", - "Urgent", - "Whether the urgent flag of WM_HINTS is set", - FALSE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_props[PROP_SKIP_TASKBAR] = - g_param_spec_boolean ("skip-taskbar", - "Skip taskbar", - "Whether the skip-taskbar flag of WM_HINTS is set", - FALSE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_props[PROP_MUTTER_HINTS] = - g_param_spec_string ("mutter-hints", - "_MUTTER_HINTS", - "Contents of the _MUTTER_HINTS property of this window", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_props[PROP_APPEARS_FOCUSED] = - g_param_spec_boolean ("appears-focused", - "Appears focused", - "Whether the window is drawn as being focused", - FALSE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_props[PROP_RESIZEABLE] = - g_param_spec_boolean ("resizeable", - "Resizeable", - "Whether the window can be resized", - FALSE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_props[PROP_ABOVE] = - g_param_spec_boolean ("above", - "Above", - "Whether the window is shown as always-on-top", - FALSE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_props[PROP_WM_CLASS] = - g_param_spec_string ("wm-class", - "WM_CLASS", - "Contents of the WM_CLASS property of this window", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_props[PROP_GTK_APPLICATION_ID] = - g_param_spec_string ("gtk-application-id", - "_GTK_APPLICATION_ID", - "Contents of the _GTK_APPLICATION_ID property of this window", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_props[PROP_GTK_UNIQUE_BUS_NAME] = - g_param_spec_string ("gtk-unique-bus-name", - "_GTK_UNIQUE_BUS_NAME", - "Contents of the _GTK_UNIQUE_BUS_NAME property of this window", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_props[PROP_GTK_APPLICATION_OBJECT_PATH] = - g_param_spec_string ("gtk-application-object-path", - "_GTK_APPLICATION_OBJECT_PATH", - "Contents of the _GTK_APPLICATION_OBJECT_PATH property of this window", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_props[PROP_GTK_WINDOW_OBJECT_PATH] = - g_param_spec_string ("gtk-window-object-path", - "_GTK_WINDOW_OBJECT_PATH", - "Contents of the _GTK_WINDOW_OBJECT_PATH property of this window", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_props[PROP_GTK_APP_MENU_OBJECT_PATH] = - g_param_spec_string ("gtk-app-menu-object-path", - "_GTK_APP_MENU_OBJECT_PATH", - "Contents of the _GTK_APP_MENU_OBJECT_PATH property of this window", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_props[PROP_GTK_MENUBAR_OBJECT_PATH] = - g_param_spec_string ("gtk-menubar-object-path", - "_GTK_MENUBAR_OBJECT_PATH", - "Contents of the _GTK_MENUBAR_OBJECT_PATH property of this window", - NULL, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_props[PROP_ON_ALL_WORKSPACES] = - g_param_spec_boolean ("on-all-workspaces", - "On all workspaces", - "Whether the window is set to appear on all workspaces", - FALSE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties (object_class, PROP_LAST, obj_props); - - window_signals[WORKSPACE_CHANGED] = - g_signal_new ("workspace-changed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - window_signals[FOCUS] = - g_signal_new ("focus", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - window_signals[RAISED] = - g_signal_new ("raised", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - window_signals[UNMANAGING] = - g_signal_new ("unmanaging", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - window_signals[UNMANAGED] = - g_signal_new ("unmanaged", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - /** - * MetaWindow::position-changed: - * @window: a #MetaWindow - * - * This is emitted when the position of a window might - * have changed. Specifically, this is emitted when the - * position of the toplevel window has changed, or when - * the position of the client window has changed. - */ - window_signals[POSITION_CHANGED] = - g_signal_new ("position-changed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - /** - * MetaWindow::shown: - * @window: a #MetaWindow - * - * This is emitted after a window has been shown. - */ - window_signals[SHOWN] = - g_signal_new ("shown", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - /** - * MetaWindow::size-changed: - * @window: a #MetaWindow - * - * This is emitted when the size of a window might - * have changed. Specifically, this is emitted when the - * size of the toplevel window has changed, or when the - * size of the client window has changed. - */ - window_signals[SIZE_CHANGED] = - g_signal_new ("size-changed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); -} - -static void -meta_window_init (MetaWindow *self) -{ - self->stamp = next_window_stamp++; - meta_prefs_add_listener (prefs_changed_callback, self); -} - -static gboolean -is_desktop_or_dock_foreach (MetaWindow *window, - void *data) -{ - gboolean *result = data; - - *result = - window->type == META_WINDOW_DESKTOP || - window->type == META_WINDOW_DOCK || - window->skip_from_window_list; - if (*result) - return FALSE; /* stop as soon as we find one */ - else - return TRUE; -} - -/* window is the window that's newly mapped provoking - * the possible change - */ -static void -maybe_leave_show_desktop_mode (MetaWindow *window) -{ - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - gboolean is_desktop_or_dock; - - if (!workspace_manager->active_workspace->showing_desktop) - return; - - /* If the window is a transient for the dock or desktop, don't - * leave show desktop mode when the window opens. That's - * so you can e.g. hide all windows, manipulate a file on - * the desktop via a dialog, then unshow windows again. - */ - is_desktop_or_dock = FALSE; - is_desktop_or_dock_foreach (window, - &is_desktop_or_dock); - - meta_window_foreach_ancestor (window, is_desktop_or_dock_foreach, - &is_desktop_or_dock); - - if (!is_desktop_or_dock) - { - meta_workspace_manager_minimize_all_on_active_workspace_except (workspace_manager, - window); - meta_workspace_manager_unshow_desktop (workspace_manager); - } -} - -gboolean -meta_window_should_attach_to_parent (MetaWindow *window) -{ - MetaWindow *parent; - - if (!meta_prefs_get_attach_modal_dialogs () || - window->type != META_WINDOW_MODAL_DIALOG) - return FALSE; - - parent = meta_window_get_transient_for (window); - if (!parent) - return FALSE; - - switch (parent->type) - { - case META_WINDOW_NORMAL: - case META_WINDOW_DIALOG: - case META_WINDOW_MODAL_DIALOG: - return TRUE; - - default: - return FALSE; - } -} - -static gboolean -client_window_should_be_mapped (MetaWindow *window) -{ -#ifdef HAVE_WAYLAND - if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND && - !meta_wayland_surface_get_buffer (window->surface)) - return FALSE; -#endif - - return !window->shaded; -} - -static void -sync_client_window_mapped (MetaWindow *window) -{ - gboolean should_be_mapped = client_window_should_be_mapped (window); - - g_return_if_fail (!window->override_redirect); - - if (window->mapped == should_be_mapped) - return; - - window->mapped = should_be_mapped; - - if (window->mapped) - META_WINDOW_GET_CLASS (window)->map (window); - else - META_WINDOW_GET_CLASS (window)->unmap (window); -} - -static gboolean -meta_window_update_flatpak_id (MetaWindow *window, - uint32_t pid) -{ - g_autoptr(GKeyFile) key_file = NULL; - g_autofree char *info_filename = NULL; - - g_return_val_if_fail (pid != 0, FALSE); - g_return_val_if_fail (window->sandboxed_app_id == NULL, FALSE); - - key_file = g_key_file_new (); - info_filename = g_strdup_printf ("/proc/%u/root/.flatpak-info", pid); - - if (!g_key_file_load_from_file (key_file, info_filename, G_KEY_FILE_NONE, NULL)) - return FALSE; - - window->sandboxed_app_id = g_key_file_get_string (key_file, "Application", "name", NULL); - - return TRUE; -} - -static gboolean -meta_window_update_snap_id (MetaWindow *window, - uint32_t pid) -{ - g_autofree char *security_label_filename = NULL; - g_autofree char *security_label_contents = NULL; - gsize i, security_label_contents_size = 0; - char *contents_start; - char *contents_end; - char *sandboxed_app_id; - - g_return_val_if_fail (pid != 0, FALSE); - g_return_val_if_fail (window->sandboxed_app_id == NULL, FALSE); - - security_label_filename = g_strdup_printf ("/proc/%u/attr/current", pid); - - if (!g_file_get_contents (security_label_filename, - &security_label_contents, - &security_label_contents_size, - NULL)) - return FALSE; - - if (!g_str_has_prefix (security_label_contents, SNAP_SECURITY_LABEL_PREFIX)) - return FALSE; - - /* We need to translate the security profile into the desktop-id. - * The profile is in the form of 'snap.name-space.binary-name (current)' - * while the desktop id will be name-space_binary-name. - */ - security_label_contents_size -= sizeof (SNAP_SECURITY_LABEL_PREFIX) - 1; - contents_start = security_label_contents + sizeof (SNAP_SECURITY_LABEL_PREFIX) - 1; - contents_end = strchr (contents_start, ' '); - - if (contents_end) - security_label_contents_size = contents_end - contents_start; - - for (i = 0; i < security_label_contents_size; ++i) - { - if (contents_start[i] == '.') - contents_start[i] = '_'; - } - - sandboxed_app_id = g_malloc0 (security_label_contents_size + 1); - memcpy (sandboxed_app_id, contents_start, security_label_contents_size); - - window->sandboxed_app_id = sandboxed_app_id; - - return TRUE; -} - -static void -meta_window_update_sandboxed_app_id (MetaWindow *window) -{ - pid_t pid; - - g_clear_pointer (&window->sandboxed_app_id, g_free); - - pid = meta_window_get_pid (window); - - if (pid < 1) - return; - - if (meta_window_update_flatpak_id (window, pid)) - return; - - if (meta_window_update_snap_id (window, pid)) - return; -} - -static void -meta_window_update_desc (MetaWindow *window) -{ - g_clear_pointer (&window->desc, g_free); - - if (window->client_type == META_WINDOW_CLIENT_TYPE_X11) - window->desc = g_strdup_printf ("0x%lx", window->xwindow); - else - { - guint64 small_stamp = window->stamp - G_GUINT64_CONSTANT(0x100000000); - - window->desc = g_strdup_printf ("W%" G_GUINT64_FORMAT , small_stamp); - } -} - -static void -meta_window_main_monitor_changed (MetaWindow *window, - const MetaLogicalMonitor *old) -{ - META_WINDOW_GET_CLASS (window)->main_monitor_changed (window, old); - - if (old) - g_signal_emit_by_name (window->display, "window-left-monitor", - old->number, window); - if (window->monitor) - g_signal_emit_by_name (window->display, "window-entered-monitor", - window->monitor->number, window); -} - -MetaLogicalMonitor * -meta_window_calculate_main_logical_monitor (MetaWindow *window) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaRectangle window_rect; - - meta_window_get_frame_rect (window, &window_rect); - return meta_monitor_manager_get_logical_monitor_from_rect (monitor_manager, - &window_rect); -} - -static void -meta_window_manage (MetaWindow *window) -{ - COGL_TRACE_BEGIN_SCOPED (MetaWindowManage, - "Window (manage)"); - - META_WINDOW_GET_CLASS (window)->manage (window); -} - -MetaWindow * -_meta_window_shared_new (MetaDisplay *display, - MetaWindowClientType client_type, - MetaWaylandSurface *surface, - Window xwindow, - gulong existing_wm_state, - MetaCompEffect effect, - XWindowAttributes *attrs) -{ - MetaWorkspaceManager *workspace_manager = display->workspace_manager; - MetaWindow *window; - - COGL_TRACE_BEGIN_SCOPED (MetaWindowSharedNew, - "Window (new)"); - - g_assert (attrs != NULL); - - meta_verbose ("attrs->map_state = %d (%s)", - attrs->map_state, - (attrs->map_state == IsUnmapped) ? - "IsUnmapped" : - (attrs->map_state == IsViewable) ? - "IsViewable" : - (attrs->map_state == IsUnviewable) ? - "IsUnviewable" : - "(unknown)"); - - if (client_type == META_WINDOW_CLIENT_TYPE_X11 && !meta_is_wayland_compositor ()) - window = g_object_new (META_TYPE_WINDOW_X11, NULL); -#ifdef HAVE_WAYLAND - else if (client_type == META_WINDOW_CLIENT_TYPE_X11) - window = g_object_new (META_TYPE_WINDOW_XWAYLAND, NULL); - else if (client_type == META_WINDOW_CLIENT_TYPE_WAYLAND) - window = g_object_new (META_TYPE_WINDOW_WAYLAND, NULL); -#endif - else - g_assert_not_reached (); - - window->constructing = TRUE; - - window->client_type = client_type; - window->surface = surface; - window->xwindow = xwindow; - - window->display = display; - meta_display_register_stamp (window->display, &window->stamp, window); - - window->workspace = NULL; - - window->sync_request_counter = None; - window->sync_request_serial = 0; - window->sync_request_timeout_id = 0; - window->sync_request_alarm = None; - - meta_window_update_sandboxed_app_id (window); - meta_window_update_desc (window); - - window->override_redirect = attrs->override_redirect; - - /* avoid tons of stack updates */ - meta_stack_freeze (window->display->stack); - - window->rect.x = attrs->x; - window->rect.y = attrs->y; - window->rect.width = attrs->width; - window->rect.height = attrs->height; - - /* size_hints are the "request" */ - window->size_hints.x = attrs->x; - window->size_hints.y = attrs->y; - window->size_hints.width = attrs->width; - window->size_hints.height = attrs->height; - /* initialize the remaining size_hints as if size_hints.flags were zero */ - meta_set_normal_hints (window, NULL); - - /* And this is our unmaximized size */ - window->saved_rect = window->rect; - window->unconstrained_rect = window->rect; - - window->depth = attrs->depth; - window->xvisual = attrs->visual; - - window->title = NULL; - window->icon = NULL; - window->mini_icon = NULL; - - window->frame = NULL; - window->has_focus = FALSE; - window->attached_focus_window = NULL; - - window->maximized_horizontally = FALSE; - window->maximized_vertically = FALSE; - window->maximize_horizontally_after_placement = FALSE; - window->maximize_vertically_after_placement = FALSE; - window->minimize_after_placement = FALSE; - window->fullscreen = FALSE; - window->require_fully_onscreen = TRUE; - window->require_on_single_monitor = TRUE; - window->require_titlebar_visible = TRUE; - window->on_all_workspaces = FALSE; - window->on_all_workspaces_requested = FALSE; - window->tile_mode = META_TILE_NONE; - window->tile_monitor_number = -1; - window->tile_hfraction = -1.; - window->shaded = FALSE; - window->initially_iconic = FALSE; - window->minimized = FALSE; - window->tab_unminimized = FALSE; - window->iconic = FALSE; - window->mapped = attrs->map_state != IsUnmapped; - window->known_to_compositor = FALSE; - window->visible_to_compositor = FALSE; - window->pending_compositor_effect = effect; - /* if already mapped, no need to worry about focus-on-first-time-showing */ - window->showing_for_first_time = !window->mapped; - /* if already mapped we don't want to do the placement thing; - * override-redirect windows are placed by the app */ - window->placed = ((window->mapped && !window->hidden) || window->override_redirect); - window->denied_focus_and_not_transient = FALSE; - window->unmanaging = FALSE; - window->is_in_queues = 0; - window->keys_grabbed = FALSE; - window->grab_on_frame = FALSE; - window->all_keys_grabbed = FALSE; - window->withdrawn = FALSE; - window->initial_workspace_set = FALSE; - window->initial_timestamp_set = FALSE; - window->net_wm_user_time_set = FALSE; - window->user_time_window = None; - window->input = TRUE; - window->calc_placement = FALSE; - window->shaken_loose = FALSE; - window->have_focus_click_grab = FALSE; - window->disable_sync = FALSE; - - window->unmaps_pending = 0; - window->reparents_pending = 0; - - window->mwm_decorated = TRUE; - window->mwm_border_only = FALSE; - window->mwm_has_close_func = TRUE; - window->mwm_has_minimize_func = TRUE; - window->mwm_has_maximize_func = TRUE; - window->mwm_has_move_func = TRUE; - window->mwm_has_resize_func = TRUE; - - switch (client_type) - { - case META_WINDOW_CLIENT_TYPE_X11: - window->decorated = TRUE; - window->hidden = FALSE; - break; - case META_WINDOW_CLIENT_TYPE_WAYLAND: - window->decorated = FALSE; - window->hidden = TRUE; - break; - } - - window->has_close_func = TRUE; - window->has_minimize_func = TRUE; - window->has_maximize_func = TRUE; - window->has_move_func = TRUE; - window->has_resize_func = TRUE; - - window->has_shade_func = TRUE; - - window->has_fullscreen_func = TRUE; - - window->always_sticky = FALSE; - - window->skip_taskbar = FALSE; - window->skip_pager = FALSE; - window->skip_from_window_list = FALSE; - window->wm_state_above = FALSE; - window->wm_state_below = FALSE; - window->wm_state_demands_attention = FALSE; - - window->res_class = NULL; - window->res_name = NULL; - window->role = NULL; - window->sm_client_id = NULL; - window->wm_client_machine = NULL; - window->is_remote = FALSE; - window->startup_id = NULL; - - window->client_pid = 0; - - window->xtransient_for = None; - window->xclient_leader = None; - - window->type = META_WINDOW_NORMAL; - - window->struts = NULL; - - window->layer = META_LAYER_LAST; /* invalid value */ - window->stack_position = -1; - window->initial_workspace = 0; /* not used */ - window->initial_timestamp = 0; /* not used */ - - window->compositor_private = NULL; - - window->monitor = meta_window_calculate_main_logical_monitor (window); - if (window->monitor) - window->preferred_output_winsys_id = window->monitor->winsys_id; - else - window->preferred_output_winsys_id = UINT_MAX; - - window->tile_match = NULL; - - /* Assign this #MetaWindow a sequence number which can be used - * for sorting. - */ - window->stable_sequence = ++display->window_sequence_counter; - - window->opacity = 0xFF; - - if (window->override_redirect) - { - window->decorated = FALSE; - window->always_sticky = TRUE; - window->has_close_func = FALSE; - window->has_shade_func = FALSE; - window->has_move_func = FALSE; - window->has_resize_func = FALSE; - } - - window->id = meta_display_generate_window_id (display); - - meta_window_manage (window); - - if (!window->override_redirect) - meta_window_update_icon_now (window, TRUE); - - if (window->initially_iconic) - { - /* WM_HINTS said minimized */ - window->minimized = TRUE; - meta_verbose ("Window %s asked to start out minimized", window->desc); - } - - if (existing_wm_state == IconicState) - { - /* WM_STATE said minimized */ - window->minimized = TRUE; - meta_verbose ("Window %s had preexisting WM_STATE = IconicState, minimizing", - window->desc); - - /* Assume window was previously placed, though perhaps it's - * been iconic its whole life, we have no way of knowing. - */ - window->placed = TRUE; - } - - /* Apply any window attributes such as initial workspace - * based on startup notification - */ - meta_display_apply_startup_properties (window->display, window); - - /* Try to get a "launch timestamp" for the window. If the window is - * a transient, we'd like to be able to get a last-usage timestamp - * from the parent window. If the window has no parent, there isn't - * much we can do...except record the current time so that any children - * can use this time as a fallback. - */ - if (!window->override_redirect && !window->net_wm_user_time_set) { - /* First, maybe the app was launched with startup notification using an - * obsolete version of the spec; use that timestamp if it exists. - */ - if (window->initial_timestamp_set) - /* NOTE: Do NOT toggle net_wm_user_time_set to true; this is just - * being recorded as a fallback for potential transients - */ - window->net_wm_user_time = window->initial_timestamp; - else if (window->transient_for != NULL) - meta_window_set_user_time (window, window->transient_for->net_wm_user_time); - else - /* NOTE: Do NOT toggle net_wm_user_time_set to true; this is just - * being recorded as a fallback for potential transients - */ - window->net_wm_user_time = - meta_display_get_current_time_roundtrip (window->display); - } - - window->attached = meta_window_should_attach_to_parent (window); - if (window->attached) - meta_window_recalc_features (window); - - if (window->type == META_WINDOW_DESKTOP || - window->type == META_WINDOW_DOCK) - { - /* Change the default, but don't enforce this if the user - * focuses the dock/desktop and unsticks it using key shortcuts. - * Need to set this before adding to the workspaces so the MRU - * lists will be updated. - */ - window->on_all_workspaces_requested = TRUE; - } - - window->on_all_workspaces = should_be_on_all_workspaces (window); - - /* For the workspace, first honor hints, - * if that fails put transients with parents, - * otherwise put window on active space - */ - - if (window->initial_workspace_set) - { - gboolean on_all_workspaces = window->on_all_workspaces; - MetaWorkspace *workspace = NULL; - - if (window->initial_workspace == (int) 0xFFFFFFFF) - { - meta_topic (META_DEBUG_PLACEMENT, - "Window %s is initially on all spaces", - window->desc); - - /* need to set on_all_workspaces first so that it will be - * added to all the MRU lists - */ - window->on_all_workspaces_requested = TRUE; - - on_all_workspaces = TRUE; - } - else if (!on_all_workspaces) - { - meta_topic (META_DEBUG_PLACEMENT, - "Window %s is initially on space %d", - window->desc, window->initial_workspace); - - workspace = meta_workspace_manager_get_workspace_by_index (workspace_manager, - window->initial_workspace); - } - - /* Ignore when a window requests to be placed on a non-existent workspace - */ - if (on_all_workspaces || workspace != NULL) - set_workspace_state (window, on_all_workspaces, workspace); - } - - /* override-redirect windows are subtly different from other windows - * with window->on_all_workspaces == TRUE. Other windows are part of - * some workspace (so they can return to that if the flag is turned off), - * but appear on other workspaces. override-redirect windows are part - * of no workspace. - */ - if (!window->override_redirect && window->workspace == NULL) - { - if (window->transient_for != NULL) - { - meta_topic (META_DEBUG_PLACEMENT, - "Putting window %s on same workspace as parent %s", - window->desc, window->transient_for->desc); - - g_warn_if_fail (!window->transient_for->override_redirect); - set_workspace_state (window, - window->transient_for->on_all_workspaces, - window->transient_for->workspace); - } - else if (window->on_all_workspaces) - { - meta_topic (META_DEBUG_PLACEMENT, - "Putting window %s on all workspaces", - window->desc); - - set_workspace_state (window, TRUE, NULL); - } - else - { - meta_topic (META_DEBUG_PLACEMENT, - "Putting window %s on active workspace", - window->desc); - - set_workspace_state (window, FALSE, workspace_manager->active_workspace); - } - - meta_window_update_struts (window); - } - - meta_window_main_monitor_changed (window, NULL); - - /* Must add window to stack before doing move/resize, since the - * window might have fullscreen size (i.e. should have been - * fullscreen'd; acrobat is one such braindead case; it withdraws - * and remaps its window whenever trying to become fullscreen...) - * and thus constraints may try to auto-fullscreen it which also - * means restacking it. - */ - if (meta_window_is_stackable (window)) - meta_stack_add (window->display->stack, - window); - else if (window->override_redirect) - window->layer = META_LAYER_OVERRIDE_REDIRECT; /* otherwise set by MetaStack */ - - if (!window->override_redirect) - { - /* FIXME we have a tendency to set this then immediately - * change it again. - */ - set_wm_state (window); - set_net_wm_state (window); - } - - meta_compositor_add_window (window->display->compositor, window); - window->known_to_compositor = TRUE; - - /* Sync stack changes */ - meta_stack_thaw (window->display->stack); - - /* Usually the we'll have queued a stack sync anyways, because we've - * added a new frame window or restacked. But if an undecorated - * window is mapped, already stacked in the right place, then we - * might need to do this explicitly. - */ - meta_stack_tracker_queue_sync_stack (window->display->stack_tracker); - - /* disable show desktop mode unless we're a desktop component */ - maybe_leave_show_desktop_mode (window); - - meta_window_queue (window, META_QUEUE_CALC_SHOWING); - /* See bug 303284; a transient of the given window can already exist, in which - * case we think it should probably be shown. - */ - meta_window_foreach_transient (window, - queue_calc_showing_func, - NULL); - /* See bug 334899; the window may have minimized ancestors - * which need to be shown. - * - * However, we shouldn't unminimize windows here when opening - * a new display because that breaks passing _NET_WM_STATE_HIDDEN - * between window managers when replacing them; see bug 358042. - * - * And we shouldn't unminimize windows if they were initially - * iconic. - */ - if (!window->override_redirect && - !display->display_opening && - !window->initially_iconic) - unminimize_window_and_all_transient_parents (window); - - window->constructing = FALSE; - - meta_display_notify_window_created (display, window); - - if (window->wm_state_demands_attention) - g_signal_emit_by_name (window->display, "window-demands-attention", window); - - return window; -} - -static gboolean -detach_foreach_func (MetaWindow *window, - void *data) -{ - GList **children = data; - MetaWindow *parent; - - if (window->attached) - { - /* Only return the immediate children of the window being unmanaged */ - parent = meta_window_get_transient_for (window); - if (parent->unmanaging) - *children = g_list_prepend (*children, window); - } - - return TRUE; -} - -void -meta_window_unmanage (MetaWindow *window, - guint32 timestamp) -{ - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - GList *tmp; - - meta_verbose ("Unmanaging %s", window->desc); - window->unmanaging = TRUE; - - g_clear_handle_id (&window->unmanage_idle_id, g_source_remove); - - g_signal_emit (window, window_signals[UNMANAGING], 0); - - meta_window_free_delete_dialog (window); - - if (window->visible_to_compositor) - { - window->visible_to_compositor = FALSE; - meta_compositor_hide_window (window->display->compositor, window, - META_COMP_EFFECT_DESTROY); - } - - meta_compositor_remove_window (window->display->compositor, window); - window->known_to_compositor = FALSE; - - if (destroying_windows_disallowed > 0) - meta_bug ("Tried to destroy window %s while destruction was not allowed", - window->desc); - - meta_display_unregister_stamp (window->display, window->stamp); - - if (meta_prefs_get_attach_modal_dialogs ()) - { - GList *attached_children = NULL, *iter; - - /* Detach any attached dialogs by unmapping and letting them - * be remapped after @window is destroyed. - */ - meta_window_foreach_transient (window, - detach_foreach_func, - &attached_children); - for (iter = attached_children; iter; iter = iter->next) - meta_window_unmanage (iter->data, timestamp); - g_list_free (attached_children); - } - - /* Make sure to only show window on all workspaces if requested, to - * not confuse other window managers that may take over - */ - if (meta_prefs_get_workspaces_only_on_primary ()) - meta_window_on_all_workspaces_changed (window); - - if (window->fullscreen) - { - MetaGroup *group; - - /* If the window is fullscreen, it may be forcing - * other windows in its group to a higher layer - */ - - meta_stack_freeze (window->display->stack); - group = meta_window_get_group (window); - if (group) - meta_group_update_layers (group); - meta_stack_thaw (window->display->stack); - } - - meta_display_remove_pending_pings_for_window (window->display, window); - - /* safe to do this early as group.c won't re-add to the - * group if window->unmanaging */ - meta_window_shutdown_group (window); - - /* If we have the focus, focus some other window. - * This is done first, so that if the unmap causes - * an EnterNotify the EnterNotify will have final say - * on what gets focused, maintaining sloppy focus - * invariants. - */ - if (meta_window_appears_focused (window)) - meta_window_propagate_focus_appearance (window, FALSE); - if (window->has_focus) - { - meta_topic (META_DEBUG_FOCUS, - "Focusing default window since we're unmanaging %s", - window->desc); - meta_workspace_focus_default_window (workspace_manager->active_workspace, - window, - timestamp); - } - else - { - meta_topic (META_DEBUG_FOCUS, - "Unmanaging window %s which doesn't currently have focus", - window->desc); - } - - g_assert (window->display->focus_window != window); - - if (window->struts) - { - g_slist_free_full (window->struts, g_free); - window->struts = NULL; - - meta_topic (META_DEBUG_WORKAREA, - "Unmanaging window %s which has struts, so invalidating work areas", - window->desc); - invalidate_work_areas (window); - } - - g_clear_handle_id (&window->sync_request_timeout_id, g_source_remove); - - if (window->display->grab_window == window) - meta_display_end_grab_op (window->display, timestamp); - - g_assert (window->display->grab_window != window); - - if (window->maximized_horizontally || window->maximized_vertically) - unmaximize_window_before_freeing (window); - - meta_window_unqueue (window, META_QUEUE_CALC_SHOWING | - META_QUEUE_MOVE_RESIZE | - META_QUEUE_UPDATE_ICON); - - set_workspace_state (window, FALSE, NULL); - - g_assert (window->workspace == NULL); - -#ifndef G_DISABLE_CHECKS - tmp = workspace_manager->workspaces; - while (tmp != NULL) - { - MetaWorkspace *workspace = tmp->data; - - g_assert (g_list_find (workspace->windows, window) == NULL); - g_assert (g_list_find (workspace->mru_list, window) == NULL); - - tmp = tmp->next; - } -#endif - - if (window->monitor) - { - const MetaLogicalMonitor *old = window->monitor; - - window->monitor = NULL; - meta_window_main_monitor_changed (window, old); - } - - if (meta_window_is_in_stack (window)) - meta_stack_remove (window->display->stack, window); - - /* If an undecorated window is being withdrawn, that will change the - * stack as presented to the compositing manager, without actually - * changing the stacking order of X windows. - */ - meta_stack_tracker_queue_sync_stack (window->display->stack_tracker); - - if (window->display->autoraise_window == window) - meta_display_remove_autoraise_callback (window->display); - - META_WINDOW_GET_CLASS (window)->unmanage (window); - - meta_prefs_remove_listener (prefs_changed_callback, window); - meta_display_queue_check_fullscreen (window->display); - - g_signal_emit (window, window_signals[UNMANAGED], 0); - - g_object_unref (window); -} - -static void -set_wm_state (MetaWindow *window) -{ - if (window->client_type == META_WINDOW_CLIENT_TYPE_X11) - meta_window_x11_set_wm_state (window); -} - -static void -set_net_wm_state (MetaWindow *window) -{ - if (window->client_type == META_WINDOW_CLIENT_TYPE_X11) - meta_window_x11_set_net_wm_state (window); -} - -static void -set_allowed_actions_hint (MetaWindow *window) -{ - if (window->client_type == META_WINDOW_CLIENT_TYPE_X11) - meta_window_x11_set_allowed_actions_hint (window); -} - -/** - * meta_window_located_on_workspace: - * @window: a #MetaWindow - * @workspace: a #MetaWorkspace - * - * Returns: whether @window is displayed on @workspace, or whether it - * will be displayed on all workspaces. - */ -gboolean -meta_window_located_on_workspace (MetaWindow *window, - MetaWorkspace *workspace) -{ - return (window->on_all_workspaces) || (window->workspace == workspace); -} - -static gboolean -is_minimized_foreach (MetaWindow *window, - void *data) -{ - gboolean *result = data; - - *result = window->minimized; - if (*result) - return FALSE; /* stop as soon as we find one */ - else - return TRUE; -} - -static gboolean -ancestor_is_minimized (MetaWindow *window) -{ - gboolean is_minimized; - - is_minimized = FALSE; - - meta_window_foreach_ancestor (window, is_minimized_foreach, &is_minimized); - - return is_minimized; -} - -/** - * meta_window_showing_on_its_workspace: - * @window: A #MetaWindow - * - * Returns: %TRUE if window would be visible, if its workspace was current - */ -gboolean -meta_window_showing_on_its_workspace (MetaWindow *window) -{ - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - gboolean showing; - gboolean is_desktop_or_dock; - MetaWorkspace* workspace_of_window; - - showing = TRUE; - - /* 1. See if we're minimized */ - if (window->minimized) - showing = FALSE; - - /* 2. See if we're in "show desktop" mode */ - is_desktop_or_dock = FALSE; - is_desktop_or_dock_foreach (window, - &is_desktop_or_dock); - - meta_window_foreach_ancestor (window, is_desktop_or_dock_foreach, - &is_desktop_or_dock); - - if (window->on_all_workspaces) - workspace_of_window = workspace_manager->active_workspace; - else if (window->workspace) - workspace_of_window = window->workspace; - else /* This only seems to be needed for startup */ - workspace_of_window = NULL; - - if (showing && - workspace_of_window && workspace_of_window->showing_desktop && - !is_desktop_or_dock) - { - meta_verbose ("We're showing the desktop on the workspace(s) that window %s is on", - window->desc); - showing = FALSE; - } - - /* 3. See if an ancestor is minimized (note that - * ancestor's "mapped" field may not be up to date - * since it's being computed in this same idle queue) - */ - - if (showing) - { - if (ancestor_is_minimized (window)) - showing = FALSE; - } - - return showing; -} - -gboolean -meta_window_should_be_showing (MetaWindow *window) -{ - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - -#ifdef HAVE_WAYLAND - if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND && - !meta_wayland_surface_get_buffer (window->surface)) - return FALSE; -#endif - - /* Windows should be showing if they're located on the - * active workspace and they're showing on their own workspace. */ - return (meta_window_located_on_workspace (window, workspace_manager->active_workspace) && - meta_window_showing_on_its_workspace (window)); -} - -static void -implement_showing (MetaWindow *window, - gboolean showing) -{ - /* Actually show/hide the window */ - meta_verbose ("Implement showing = %d for window %s", - showing, window->desc); - - /* Some windows are not stackable until being showed, so add those now. */ - if (meta_window_is_stackable (window) && !meta_window_is_in_stack (window)) - meta_stack_add (window->display->stack, window); - - if (!showing) - { - /* When we manage a new window, we normally delay placing it - * until it is is first shown, but if we're previewing hidden - * windows we might want to know where they are on the screen, - * so we should place the window even if we're hiding it rather - * than showing it. - * Force placing windows only when they should be already mapped, - * see #751887 - */ - if (!window->placed && client_window_should_be_mapped (window)) - meta_window_force_placement (window, FALSE); - - meta_window_hide (window); - } - else - meta_window_show (window); - - if (!window->override_redirect) - sync_client_window_mapped (window); -} - -static void -meta_window_calc_showing (MetaWindow *window) -{ - implement_showing (window, meta_window_should_be_showing (window)); -} - -static guint queue_later[NUMBER_OF_QUEUES] = {0, 0, 0}; -static GSList *queue_pending[NUMBER_OF_QUEUES] = {NULL, NULL, NULL}; - -static int -stackcmp (gconstpointer a, gconstpointer b) -{ - MetaWindow *aw = (gpointer) a; - MetaWindow *bw = (gpointer) b; - - return meta_stack_windows_cmp (aw->display->stack, - aw, bw); -} - -static gboolean -idle_calc_showing (gpointer data) -{ - MetaDisplay *display = meta_get_display (); - GSList *tmp; - GSList *copy; - GSList *should_show; - GSList *should_hide; - GSList *unplaced; - GSList *displays; - guint queue_index = GPOINTER_TO_INT (data); - - COGL_TRACE_BEGIN_SCOPED (MetaWindowCalcShowing, "Window: Calc showing"); - - g_return_val_if_fail (queue_pending[queue_index] != NULL, FALSE); - - meta_topic (META_DEBUG_WINDOW_STATE, - "Clearing the calc_showing queue"); - - /* Work with a copy, for reentrancy. The allowed reentrancy isn't - * complete; destroying a window while we're in here would result in - * badness. But it's OK to queue/unqueue calc_showings. - */ - copy = g_slist_copy (queue_pending[queue_index]); - g_slist_free (queue_pending[queue_index]); - queue_pending[queue_index] = NULL; - queue_later[queue_index] = 0; - - destroying_windows_disallowed += 1; - - /* We map windows from top to bottom and unmap from bottom to - * top, to avoid extra expose events. The exception is - * for unplaced windows, which have to be mapped from bottom to - * top so placement works. - */ - should_show = NULL; - should_hide = NULL; - unplaced = NULL; - displays = NULL; - - COGL_TRACE_BEGIN (MetaWindowCalcShowingCalc, "Window: Calc showing (calc)"); - - tmp = copy; - while (tmp != NULL) - { - MetaWindow *window; - - window = tmp->data; - - if (!window->placed) - unplaced = g_slist_prepend (unplaced, window); - else if (meta_window_should_be_showing (window)) - should_show = g_slist_prepend (should_show, window); - else - should_hide = g_slist_prepend (should_hide, window); - - tmp = tmp->next; - } - - /* bottom to top */ - unplaced = g_slist_sort (unplaced, stackcmp); - should_hide = g_slist_sort (should_hide, stackcmp); - /* top to bottom */ - should_show = g_slist_sort (should_show, stackcmp); - should_show = g_slist_reverse (should_show); - - COGL_TRACE_END (MetaWindowCalcShowingCalc); - - COGL_TRACE_BEGIN (MetaWindowCalcShowingUnplaced, - "Window: Calc showing (calc unplaced)"); - - tmp = unplaced; - while (tmp != NULL) - { - MetaWindow *window; - - window = tmp->data; - - meta_window_calc_showing (window); - - tmp = tmp->next; - } - - COGL_TRACE_END (MetaWindowCalcShowingUnplaced); - - meta_stack_freeze (display->stack); - - COGL_TRACE_BEGIN (MetaWindowCalcShowingShow, "Window: Calc showing (show)"); - tmp = should_show; - while (tmp != NULL) - { - MetaWindow *window; - - window = tmp->data; - - implement_showing (window, TRUE); - - tmp = tmp->next; - } - COGL_TRACE_END (MetaWindowCalcShowingShow); - - COGL_TRACE_BEGIN (MetaWindowCalcShowingHide, "Window: Calc showing (hide)"); - tmp = should_hide; - while (tmp != NULL) - { - MetaWindow *window; - - window = tmp->data; - - implement_showing (window, FALSE); - - tmp = tmp->next; - } - COGL_TRACE_END (MetaWindowCalcShowingHide); - - COGL_TRACE_BEGIN (MetaWindowCalcShowingSync, - "Window: Calc showing (sync stack)"); - meta_stack_thaw (display->stack); - COGL_TRACE_END (MetaWindowCalcShowingSync); - - tmp = copy; - while (tmp != NULL) - { - MetaWindow *window; - - window = tmp->data; - - /* important to set this here for reentrancy - - * if we queue a window again while it's in "copy", - * then queue_calc_showing will just return since - * we are still in the calc_showing queue - */ - window->is_in_queues &= ~META_QUEUE_CALC_SHOWING; - - tmp = tmp->next; - } - - if (meta_prefs_get_focus_mode () != G_DESKTOP_FOCUS_MODE_CLICK) - { - /* When display->mouse_mode is false, we want to ignore - * EnterNotify events unless they come from mouse motion. To do - * that, we set a sentinel property on the root window if we're - * not in mouse_mode. - */ - tmp = should_show; - while (tmp != NULL) - { - MetaWindow *window = tmp->data; - MetaDisplay *display = window->display; - - if (display->x11_display && !display->mouse_mode) - meta_x11_display_increment_focus_sentinel (display->x11_display); - - tmp = tmp->next; - } - } - - g_slist_free (copy); - - g_slist_free (unplaced); - g_slist_free (should_show); - g_slist_free (should_hide); - g_slist_free (displays); - - destroying_windows_disallowed -= 1; - - return FALSE; -} - -#ifdef WITH_VERBOSE_MODE -static const gchar* meta_window_queue_names[NUMBER_OF_QUEUES] = - {"calc_showing", "move_resize", "update_icon"}; -#endif - -static void -meta_window_unqueue (MetaWindow *window, guint queuebits) -{ - gint queuenum; - - for (queuenum=0; queuenumis_in_queues & 1<desc, - meta_window_queue_names[queuenum]); - - /* Note that window may not actually be in the queue - * because it may have been in "copy" inside the idle handler - */ - queue_pending[queuenum] = g_slist_remove (queue_pending[queuenum], window); - window->is_in_queues &= ~(1<is_in_queues & META_QUEUE_CALC_SHOWING) - { - meta_window_unqueue (window, META_QUEUE_CALC_SHOWING); - meta_window_calc_showing (window); - } -} - -void -meta_window_queue (MetaWindow *window, guint queuebits) -{ - guint queuenum; - - /* Easier to debug by checking here rather than in the idle */ - g_return_if_fail (!window->override_redirect || (queuebits & META_QUEUE_MOVE_RESIZE) == 0); - - for (queuenum=0; queuenumunmanaging) - break; - - /* If the window already claims to be in that queue, there's no - * point putting it in the queue. - */ - if (window->is_in_queues & 1<desc, - meta_window_queue_names[queuenum]); - - /* So, mark it as being in this queue. */ - window->is_in_queues |= 1<display->focus_window; - - meta_topic (META_DEBUG_STARTUP, - "COMPARISON:\n" - " net_wm_user_time_set : %d\n" - " net_wm_user_time : %u\n" - " initial_timestamp_set: %d\n" - " initial_timestamp : %u", - window->net_wm_user_time_set, - window->net_wm_user_time, - window->initial_timestamp_set, - window->initial_timestamp); - if (focus_window != NULL) - { - meta_topic (META_DEBUG_STARTUP, - "COMPARISON (continued):\n" - " focus_window : %s\n" - " fw->net_wm_user_time_set : %d\n" - " fw->net_wm_user_time : %u", - focus_window->desc, - focus_window->net_wm_user_time_set, - focus_window->net_wm_user_time); - } - - /* We expect the most common case for not focusing a new window - * to be when a hint to not focus it has been set. Since we can - * deal with that case rapidly, we use special case it--this is - * merely a preliminary optimization. :) - */ - if ( ((window->net_wm_user_time_set == TRUE) && - (window->net_wm_user_time == 0)) - || - ((window->initial_timestamp_set == TRUE) && - (window->initial_timestamp == 0))) - { - meta_topic (META_DEBUG_STARTUP, - "window %s explicitly requested no focus", - window->desc); - return TRUE; - } - - if (!(window->net_wm_user_time_set) && !(window->initial_timestamp_set)) - { - meta_topic (META_DEBUG_STARTUP, - "no information about window %s found", - window->desc); - return FALSE; - } - - if (focus_window != NULL && - !focus_window->net_wm_user_time_set) - { - meta_topic (META_DEBUG_STARTUP, - "focus window, %s, doesn't have a user time set yet!", - window->desc); - return FALSE; - } - - /* To determine the "launch" time of an application, - * startup-notification can set the TIMESTAMP and the - * application (usually via its toolkit such as gtk or qt) can - * set the _NET_WM_USER_TIME. If both are set, we need to be - * using the newer of the two values. - * - * See http://bugzilla.gnome.org/show_bug.cgi?id=573922 - */ - compare = 0; - if (window->net_wm_user_time_set && - window->initial_timestamp_set) - compare = - XSERVER_TIME_IS_BEFORE (window->net_wm_user_time, - window->initial_timestamp) ? - window->initial_timestamp : window->net_wm_user_time; - else if (window->net_wm_user_time_set) - compare = window->net_wm_user_time; - else if (window->initial_timestamp_set) - compare = window->initial_timestamp; - - if ((focus_window != NULL) && - XSERVER_TIME_IS_BEFORE (compare, focus_window->net_wm_user_time)) - { - meta_topic (META_DEBUG_STARTUP, - "window %s focus prevented by other activity; %u < %u", - window->desc, - compare, - focus_window->net_wm_user_time); - return TRUE; - } - else - { - meta_topic (META_DEBUG_STARTUP, - "new window %s with no intervening events", - window->desc); - return FALSE; - } -} - -/* This function is an ugly hack. It's experimental in nature and ought to be - * replaced by a real hint from the app to the WM if we decide the experimental - * behavior is worthwhile. The basic idea is to get more feedback about how - * usage scenarios of "strict" focus users and what they expect. See #326159. - */ -static gboolean -window_is_terminal (MetaWindow *window) -{ - if (window == NULL || window->res_class == NULL) - return FALSE; - - /* - * Compare res_class, which is not user-settable, and thus theoretically - * a more-reliable indication of term-ness. - */ - - /* gnome-terminal -- if you couldn't guess */ - if (strcmp (window->res_class, "Gnome-terminal") == 0) - return TRUE; - /* xterm, rxvt, aterm */ - else if (strcmp (window->res_class, "XTerm") == 0) - return TRUE; - /* konsole, KDE's terminal program */ - else if (strcmp (window->res_class, "Konsole") == 0) - return TRUE; - /* rxvt-unicode */ - else if (strcmp (window->res_class, "URxvt") == 0) - return TRUE; - /* eterm */ - else if (strcmp (window->res_class, "Eterm") == 0) - return TRUE; - /* KTerm -- some terminal not KDE based; so not like Konsole */ - else if (strcmp (window->res_class, "KTerm") == 0) - return TRUE; - /* Multi-gnome-terminal */ - else if (strcmp (window->res_class, "Multi-gnome-terminal") == 0) - return TRUE; - /* mlterm ("multi lingual terminal emulator on X") */ - else if (strcmp (window->res_class, "mlterm") == 0) - return TRUE; - /* Terminal -- XFCE Terminal */ - else if (strcmp (window->res_class, "Terminal") == 0) - return TRUE; - - return FALSE; -} - -/* This function determines what state the window should have assuming that it - * and the focus_window have no relation - */ -static void -window_state_on_map (MetaWindow *window, - gboolean *takes_focus, - gboolean *places_on_top) -{ - gboolean intervening_events; - - intervening_events = intervening_user_event_occurred (window); - - *takes_focus = !intervening_events; - *places_on_top = *takes_focus; - - /* don't initially focus windows that are intended to not accept - * focus - */ - if (!meta_window_is_focusable (window)) - { - *takes_focus = FALSE; - return; - } - - /* Terminal usage may be different; some users intend to launch - * many apps in quick succession or to just view things in the new - * window while still interacting with the terminal. In that case, - * apps launched from the terminal should not take focus. This - * isn't quite the same as not allowing focus to transfer from - * terminals due to new window map, but the latter is a much easier - * approximation to enforce so we do that. - */ - if (*takes_focus && - meta_prefs_get_focus_new_windows () == G_DESKTOP_FOCUS_NEW_WINDOWS_STRICT && - !window->display->allow_terminal_deactivation && - window_is_terminal (window->display->focus_window) && - !meta_window_is_ancestor_of_transient (window->display->focus_window, - window)) - { - meta_topic (META_DEBUG_FOCUS, - "focus_window is terminal; not focusing new window."); - *takes_focus = FALSE; - *places_on_top = FALSE; - } - - switch (window->type) - { - case META_WINDOW_UTILITY: - case META_WINDOW_TOOLBAR: - *takes_focus = FALSE; - *places_on_top = FALSE; - break; - case META_WINDOW_DOCK: - case META_WINDOW_DESKTOP: - case META_WINDOW_SPLASHSCREEN: - case META_WINDOW_MENU: - /* override redirect types: */ - case META_WINDOW_DROPDOWN_MENU: - case META_WINDOW_POPUP_MENU: - case META_WINDOW_TOOLTIP: - case META_WINDOW_NOTIFICATION: - case META_WINDOW_COMBO: - case META_WINDOW_DND: - case META_WINDOW_OVERRIDE_OTHER: - /* don't focus any of these; places_on_top may be irrelevant for some of - * these (e.g. dock)--but you never know--the focus window might also be - * of the same type in some weird situation... - */ - *takes_focus = FALSE; - break; - case META_WINDOW_NORMAL: - case META_WINDOW_DIALOG: - case META_WINDOW_MODAL_DIALOG: - /* The default is correct for these */ - break; - } -} - -static gboolean -windows_overlap (const MetaWindow *w1, const MetaWindow *w2) -{ - MetaRectangle w1rect, w2rect; - meta_window_get_frame_rect (w1, &w1rect); - meta_window_get_frame_rect (w2, &w2rect); - return meta_rectangle_overlap (&w1rect, &w2rect); -} - -/* Returns whether a new window would be covered by any - * existing window on the same workspace that is set - * to be "above" ("always on top"). A window that is not - * set "above" would be underneath the new window anyway. - * - * We take "covered" to mean even partially covered, but - * some people might prefer entirely covered. I think it - * is more useful to behave this way if any part of the - * window is covered, because a partial coverage could be - * (say) ninety per cent and almost indistinguishable from total. - */ -static gboolean -window_would_be_covered (const MetaWindow *newbie) -{ - MetaWorkspace *workspace = meta_window_get_workspace ((MetaWindow *)newbie); - GList *tmp, *windows; - - windows = meta_workspace_list_windows (workspace); - - tmp = windows; - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - - if (w->wm_state_above && w != newbie) - { - /* We have found a window that is "above". Perhaps it overlaps. */ - if (windows_overlap (w, newbie)) - { - g_list_free (windows); /* clean up... */ - return TRUE; /* yes, it does */ - } - } - - tmp = tmp->next; - } - - g_list_free (windows); - return FALSE; /* none found */ -} - -void -meta_window_force_placement (MetaWindow *window, - gboolean force_move) -{ - MetaMoveResizeFlags flags; - - if (window->placed) - return; - - /* We have to recalc the placement here since other windows may - * have been mapped/placed since we last did constrain_position - */ - - /* calc_placement is an efficiency hack to avoid - * multiple placement calculations before we finally - * show the window. - */ - window->calc_placement = TRUE; - - flags = META_MOVE_RESIZE_MOVE_ACTION | META_MOVE_RESIZE_RESIZE_ACTION; - if (force_move) - flags |= META_MOVE_RESIZE_FORCE_MOVE; - - meta_window_move_resize_internal (window, - flags, - META_GRAVITY_NORTH_WEST, - window->unconstrained_rect); - window->calc_placement = FALSE; - - /* don't ever do the initial position constraint thing again. - * This is toggled here so that initially-iconified windows - * still get placed when they are ultimately shown. - */ - window->placed = TRUE; - - /* Don't want to accidentally reuse the fact that we had been denied - * focus in any future constraints unless we're denied focus again. - */ - window->denied_focus_and_not_transient = FALSE; -} - -static void -meta_window_show (MetaWindow *window) -{ - gboolean did_show; - gboolean takes_focus_on_map; - gboolean place_on_top_on_map; - gboolean needs_stacking_adjustment; - MetaWindow *focus_window; - gboolean notify_demands_attention = FALSE; - MetaDisplay *display = window->display; - - meta_topic (META_DEBUG_WINDOW_STATE, - "Showing window %s, shaded: %d iconic: %d placed: %d", - window->desc, window->shaded, window->iconic, window->placed); - - focus_window = window->display->focus_window; /* May be NULL! */ - did_show = FALSE; - window_state_on_map (window, &takes_focus_on_map, &place_on_top_on_map); - needs_stacking_adjustment = FALSE; - - meta_topic (META_DEBUG_WINDOW_STATE, - "Window %s %s focus on map, and %s place on top on map.", - window->desc, - takes_focus_on_map ? "does" : "does not", - place_on_top_on_map ? "does" : "does not"); - - /* Now, in some rare cases we should *not* put a new window on top. - * These cases include certain types of windows showing for the first - * time, and any window which would be covered because of another window - * being set "above" ("always on top"). - * - * FIXME: Although "place_on_top_on_map" and "takes_focus_on_map" are - * generally based on the window type, there is a special case when the - * focus window is a terminal for them both to be false; this should - * probably rather be a term in the "if" condition below. - */ - - if ( focus_window != NULL && window->showing_for_first_time && - ( (!place_on_top_on_map && !takes_focus_on_map) || - window_would_be_covered (window) ) - ) { - if (!meta_window_is_ancestor_of_transient (focus_window, window)) - { - needs_stacking_adjustment = TRUE; - if (!window->placed) - window->denied_focus_and_not_transient = TRUE; - } - } - - if (!window->placed) - { - if (window->monitor && - meta_prefs_get_auto_maximize() && - window->showing_for_first_time && - window->has_maximize_func) - { - MetaRectangle work_area; - meta_window_get_work_area_for_monitor (window, window->monitor->number, &work_area); - /* Automaximize windows that map with a size > MAX_UNMAXIMIZED_WINDOW_AREA of the work area */ - if (window->rect.width * window->rect.height > work_area.width * work_area.height * MAX_UNMAXIMIZED_WINDOW_AREA) - { - window->maximize_horizontally_after_placement = TRUE; - window->maximize_vertically_after_placement = TRUE; - } - } - meta_window_force_placement (window, FALSE); - } - - if (needs_stacking_adjustment) - { - gboolean overlap; - - /* This window isn't getting focus on map. We may need to do some - * special handing with it in regards to - * - the stacking of the window - * - the MRU position of the window - * - the demands attention setting of the window - * - * Firstly, set the flag so we don't give the window focus anyway - * and confuse people. - */ - - takes_focus_on_map = FALSE; - - overlap = windows_overlap (window, focus_window); - - /* We want alt tab to go to the denied-focus window */ - ensure_mru_position_after (window, focus_window); - - /* We don't want the denied-focus window to obscure the focus - * window, and if we're in both click-to-focus mode and - * raise-on-click mode then we want to maintain the invariant - * that MRU order == stacking order. The need for this if - * comes from the fact that in sloppy/mouse focus the focus - * window may not overlap other windows and also can be - * considered "below" them; this combination means that - * placing the denied-focus window "below" the focus window - * in the stack when it doesn't overlap it confusingly places - * that new window below a lot of other windows. - */ - if (overlap || - (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK && - meta_prefs_get_raise_on_click ())) - meta_window_stack_just_below (window, focus_window); - - /* If the window will be obscured by the focus window, then the - * user might not notice the window appearing so set the - * demands attention hint. - * - * We set the hint ourselves rather than calling - * meta_window_set_demands_attention() because that would cause - * a recalculation of overlap, and a call to set_net_wm_state() - * which we are going to call ourselves here a few lines down. - */ - if (overlap) - { - if (!window->wm_state_demands_attention) - { - window->wm_state_demands_attention = TRUE; - notify_demands_attention = TRUE; - } - } - } - - if (window->hidden) - { - meta_stack_freeze (window->display->stack); - window->hidden = FALSE; - meta_stack_thaw (window->display->stack); - did_show = TRUE; - } - - if (window->iconic) - { - window->iconic = FALSE; - set_wm_state (window); - } - - if (!window->visible_to_compositor) - { - MetaCompEffect effect = META_COMP_EFFECT_NONE; - - window->visible_to_compositor = TRUE; - - switch (window->pending_compositor_effect) - { - case META_COMP_EFFECT_CREATE: - case META_COMP_EFFECT_UNMINIMIZE: - effect = window->pending_compositor_effect; - break; - case META_COMP_EFFECT_NONE: - case META_COMP_EFFECT_DESTROY: - case META_COMP_EFFECT_MINIMIZE: - break; - } - - meta_compositor_show_window (window->display->compositor, - window, effect); - window->pending_compositor_effect = META_COMP_EFFECT_NONE; - } - - /* We don't want to worry about all cases from inside - * implement_showing(); we only want to worry about focus if this - * window has not been shown before. - */ - if (window->showing_for_first_time) - { - window->showing_for_first_time = FALSE; - if (takes_focus_on_map) - { - guint32 timestamp; - - timestamp = meta_display_get_current_time_roundtrip (window->display); - - meta_window_focus (window, timestamp); - } - else if (display->x11_display) - { - /* Prevent EnterNotify events in sloppy/mouse focus from - * erroneously focusing the window that had been denied - * focus. FIXME: This introduces a race; I have a couple - * ideas for a better way to accomplish the same thing, but - * they're more involved so do it this way for now. - */ - meta_x11_display_increment_focus_sentinel (display->x11_display); - } - } - - set_net_wm_state (window); - - if (did_show && window->struts) - { - meta_topic (META_DEBUG_WORKAREA, - "Mapped window %s with struts, so invalidating work areas", - window->desc); - invalidate_work_areas (window); - } - - if (did_show) - meta_display_queue_check_fullscreen (window->display); - - /* - * Now that we have shown the window, we no longer want to consider the - * initial timestamp in any subsequent deliberations whether to focus this - * window or not, so clear the flag. - * - * See http://bugzilla.gnome.org/show_bug.cgi?id=573922 - */ - window->initial_timestamp_set = FALSE; - - if (notify_demands_attention) - { - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_DEMANDS_ATTENTION]); - g_signal_emit_by_name (window->display, "window-demands-attention", - window); - } - - if (did_show) - g_signal_emit (window, window_signals[SHOWN], 0); -} - -static void -meta_window_hide (MetaWindow *window) -{ - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - gboolean did_hide; - - meta_topic (META_DEBUG_WINDOW_STATE, - "Hiding window %s", window->desc); - - if (window->visible_to_compositor) - { - MetaCompEffect effect = META_COMP_EFFECT_NONE; - - window->visible_to_compositor = FALSE; - - switch (window->pending_compositor_effect) - { - case META_COMP_EFFECT_CREATE: - case META_COMP_EFFECT_UNMINIMIZE: - case META_COMP_EFFECT_NONE: - break; - case META_COMP_EFFECT_DESTROY: - case META_COMP_EFFECT_MINIMIZE: - effect = window->pending_compositor_effect; - break; - } - - meta_compositor_hide_window (window->display->compositor, window, effect); - window->pending_compositor_effect = META_COMP_EFFECT_NONE; - } - - did_hide = FALSE; - - if (!window->hidden) - { - meta_stack_freeze (window->display->stack); - window->hidden = TRUE; - meta_stack_thaw (window->display->stack); - - did_hide = TRUE; - } - - if (!window->iconic) - { - window->iconic = TRUE; - set_wm_state (window); - } - - set_net_wm_state (window); - - if (did_hide && window->struts) - { - meta_topic (META_DEBUG_WORKAREA, - "Unmapped window %s with struts, so invalidating work areas", - window->desc); - invalidate_work_areas (window); - } - - if (window->has_focus) - { - MetaWindow *not_this_one = NULL; - MetaWorkspace *my_workspace = meta_window_get_workspace (window); - guint32 timestamp = meta_display_get_current_time_roundtrip (window->display); - - /* - * If this window is modal, passing the not_this_one window to - * _focus_default_window() makes the focus to be given to this window's - * ancestor. This can only be the case if the window is on the currently - * active workspace; when it is not, we need to pass in NULL, so as to - * focus the default window for the active workspace (this scenario - * arises when we are switching workspaces). - * We also pass in NULL if we are in the process of hiding all non-desktop - * windows to avoid unexpected changes to the stacking order. - */ - if (my_workspace == workspace_manager->active_workspace && - !my_workspace->showing_desktop) - not_this_one = window; - - meta_workspace_focus_default_window (workspace_manager->active_workspace, - not_this_one, - timestamp); - } - - if (did_hide) - meta_display_queue_check_fullscreen (window->display); -} - -static gboolean -queue_calc_showing_func (MetaWindow *window, - void *data) -{ - meta_window_queue(window, META_QUEUE_CALC_SHOWING); - return TRUE; -} - -void -meta_window_minimize (MetaWindow *window) -{ - g_return_if_fail (!window->override_redirect); - - if (!window->minimized) - { - window->minimized = TRUE; - window->pending_compositor_effect = META_COMP_EFFECT_MINIMIZE; - meta_window_queue(window, META_QUEUE_CALC_SHOWING); - - meta_window_foreach_transient (window, - queue_calc_showing_func, - NULL); - - if (window->has_focus) - { - meta_topic (META_DEBUG_FOCUS, - "Focusing default window due to minimization of focus window %s", - window->desc); - } - else - { - meta_topic (META_DEBUG_FOCUS, - "Minimizing window %s which doesn't have the focus", - window->desc); - } - - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_MINIMIZED]); - } -} - -void -meta_window_unminimize (MetaWindow *window) -{ - g_return_if_fail (!window->override_redirect); - - if (window->minimized) - { - window->minimized = FALSE; - window->pending_compositor_effect = META_COMP_EFFECT_UNMINIMIZE; - meta_window_queue(window, META_QUEUE_CALC_SHOWING); - - meta_window_foreach_transient (window, - queue_calc_showing_func, - NULL); - - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_MINIMIZED]); - } -} - -static void -ensure_size_hints_satisfied (MetaRectangle *rect, - const XSizeHints *size_hints) -{ - int minw, minh, maxw, maxh; /* min/max width/height */ - int basew, baseh, winc, hinc; /* base width/height, width/height increment */ - int extra_width, extra_height; - - minw = size_hints->min_width; minh = size_hints->min_height; - maxw = size_hints->max_width; maxh = size_hints->max_height; - basew = size_hints->base_width; baseh = size_hints->base_height; - winc = size_hints->width_inc; hinc = size_hints->height_inc; - - /* First, enforce min/max size constraints */ - rect->width = CLAMP (rect->width, minw, maxw); - rect->height = CLAMP (rect->height, minh, maxh); - - /* Now, verify size increment constraints are satisfied, or make them be */ - extra_width = (rect->width - basew) % winc; - extra_height = (rect->height - baseh) % hinc; - - rect->width -= extra_width; - rect->height -= extra_height; - - /* Adjusting width/height down, as done above, may violate minimum size - * constraints, so one last fix. - */ - if (rect->width < minw) - rect->width += ((minw - rect->width)/winc + 1)*winc; - if (rect->height < minh) - rect->height += ((minh - rect->height)/hinc + 1)*hinc; -} - -static void -meta_window_save_rect (MetaWindow *window) -{ - if (!(META_WINDOW_MAXIMIZED (window) || META_WINDOW_TILED_SIDE_BY_SIDE (window) || window->fullscreen)) - { - /* save size/pos as appropriate args for move_resize */ - if (!window->maximized_horizontally) - { - window->saved_rect.x = window->rect.x; - window->saved_rect.width = window->rect.width; - } - if (!window->maximized_vertically) - { - window->saved_rect.y = window->rect.y; - window->saved_rect.height = window->rect.height; - } - } -} - -void -meta_window_maximize_internal (MetaWindow *window, - MetaMaximizeFlags directions, - MetaRectangle *saved_rect) -{ - /* At least one of the two directions ought to be set */ - gboolean maximize_horizontally, maximize_vertically; - maximize_horizontally = directions & META_MAXIMIZE_HORIZONTAL; - maximize_vertically = directions & META_MAXIMIZE_VERTICAL; - g_assert (maximize_horizontally || maximize_vertically); - - meta_topic (META_DEBUG_WINDOW_OPS, - "Maximizing %s%s", - window->desc, - maximize_horizontally && maximize_vertically ? "" : - maximize_horizontally ? " horizontally" : - maximize_vertically ? " vertically" : "BUGGGGG"); - - if (saved_rect != NULL) - window->saved_rect = *saved_rect; - else - meta_window_save_rect (window); - - if (maximize_horizontally && maximize_vertically) - window->saved_maximize = TRUE; - - window->maximized_horizontally = - window->maximized_horizontally || maximize_horizontally; - window->maximized_vertically = - window->maximized_vertically || maximize_vertically; - - /* Update the edge constraints */ - update_edge_constraints (window); - - meta_window_recalc_features (window); - set_net_wm_state (window); - - if (window->monitor && window->monitor->in_fullscreen) - meta_display_queue_check_fullscreen (window->display); - - g_object_freeze_notify (G_OBJECT (window)); - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_MAXIMIZED_HORIZONTALLY]); - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_MAXIMIZED_VERTICALLY]); - g_object_thaw_notify (G_OBJECT (window)); -} - -void -meta_window_maximize (MetaWindow *window, - MetaMaximizeFlags directions) -{ - MetaRectangle *saved_rect = NULL; - gboolean maximize_horizontally, maximize_vertically; - - g_return_if_fail (!window->override_redirect); - - /* At least one of the two directions ought to be set */ - maximize_horizontally = directions & META_MAXIMIZE_HORIZONTAL; - maximize_vertically = directions & META_MAXIMIZE_VERTICAL; - g_assert (maximize_horizontally || maximize_vertically); - - /* Only do something if the window isn't already maximized in the - * given direction(s). - */ - if ((maximize_horizontally && !window->maximized_horizontally) || - (maximize_vertically && !window->maximized_vertically)) - { - if (window->shaded && maximize_vertically) - { - /* Shading sucks anyway; I'm not adding a timestamp argument - * to this function just for this niche usage & corner case. - */ - guint32 timestamp = - meta_display_get_current_time_roundtrip (window->display); - meta_window_unshade (window, timestamp); - } - - /* if the window hasn't been placed yet, we'll maximize it then - */ - if (!window->placed) - { - window->maximize_horizontally_after_placement = - window->maximize_horizontally_after_placement || - maximize_horizontally; - window->maximize_vertically_after_placement = - window->maximize_vertically_after_placement || - maximize_vertically; - return; - } - - if (window->tile_mode != META_TILE_NONE) - { - saved_rect = &window->saved_rect; - - window->maximized_vertically = FALSE; - window->tile_mode = META_TILE_NONE; - } - - meta_window_maximize_internal (window, - directions, - saved_rect); - - MetaRectangle old_frame_rect, old_buffer_rect; - - meta_window_get_frame_rect (window, &old_frame_rect); - meta_window_get_buffer_rect (window, &old_buffer_rect); - - meta_compositor_size_change_window (window->display->compositor, window, - META_SIZE_CHANGE_MAXIMIZE, - &old_frame_rect, &old_buffer_rect); - - meta_window_move_resize_internal (window, - (META_MOVE_RESIZE_MOVE_ACTION | - META_MOVE_RESIZE_RESIZE_ACTION | - META_MOVE_RESIZE_STATE_CHANGED), - META_GRAVITY_NORTH_WEST, - window->unconstrained_rect); - } -} - -/** - * meta_window_get_maximized: - * @window: a #MetaWindow - * - * Gets the current maximization state of the window, as combination - * of the %META_MAXIMIZE_HORIZONTAL and %META_MAXIMIZE_VERTICAL flags; - * - * Return value: current maximization state - */ -MetaMaximizeFlags -meta_window_get_maximized (MetaWindow *window) -{ - return ((window->maximized_horizontally ? META_MAXIMIZE_HORIZONTAL : 0) | - (window->maximized_vertically ? META_MAXIMIZE_VERTICAL : 0)); -} - -/** - * meta_window_is_fullscreen: - * @window: a #MetaWindow - * - * Return value: %TRUE if the window is currently fullscreen - */ -gboolean -meta_window_is_fullscreen (MetaWindow *window) -{ - return window->fullscreen; -} - -/** - * meta_window_is_screen_sized: - * @window: A #MetaWindow - * - * Return value: %TRUE if the window is occupies the - * the whole screen (all monitors). - */ -gboolean -meta_window_is_screen_sized (MetaWindow *window) -{ - MetaRectangle window_rect; - int screen_width, screen_height; - - meta_display_get_size (window->display, &screen_width, &screen_height); - meta_window_get_frame_rect (window, &window_rect); - - if (window_rect.x == 0 && window_rect.y == 0 && - window_rect.width == screen_width && window_rect.height == screen_height) - return TRUE; - - return FALSE; -} - -/** - * meta_window_is_monitor_sized: - * @window: a #MetaWindow - * - * Return value: %TRUE if the window is occupies an entire monitor or - * the whole screen. - */ -gboolean -meta_window_is_monitor_sized (MetaWindow *window) -{ - if (!window->monitor) - return FALSE; - - if (window->fullscreen) - return TRUE; - - if (meta_window_is_screen_sized (window)) - return TRUE; - - if (window->override_redirect) - { - MetaRectangle window_rect, monitor_rect; - - meta_window_get_frame_rect (window, &window_rect); - meta_display_get_monitor_geometry (window->display, window->monitor->number, &monitor_rect); - - if (meta_rectangle_equal (&window_rect, &monitor_rect)) - return TRUE; - } - - return FALSE; -} - -/** - * meta_window_is_on_primary_monitor: - * @window: a #MetaWindow - * - * Return value: %TRUE if the window is on the primary monitor - */ -gboolean -meta_window_is_on_primary_monitor (MetaWindow *window) -{ - g_return_val_if_fail (window->monitor, FALSE); - - return window->monitor->is_primary; -} - -static void -meta_window_get_tile_fraction (MetaWindow *window, - MetaTileMode tile_mode, - double *fraction) -{ - MetaWindow *tile_match; - - /* Make sure the tile match is up-to-date and matches the - * passed in mode rather than the current state - */ - tile_match = meta_window_find_tile_match (window, tile_mode); - - if (tile_mode == META_TILE_NONE) - *fraction = -1.; - else if (tile_mode == META_TILE_MAXIMIZED) - *fraction = 1.; - else if (tile_match) - *fraction = 1. - tile_match->tile_hfraction; - else if (META_WINDOW_TILED_SIDE_BY_SIDE (window)) - { - if (window->tile_mode != tile_mode) - *fraction = 1. - window->tile_hfraction; - else - *fraction = window->tile_hfraction; - } - else - *fraction = .5; -} - -static void -meta_window_update_tile_fraction (MetaWindow *window, - int new_w, - int new_h) -{ - MetaWindow *tile_match = window->tile_match; - MetaRectangle work_area; - - if (!META_WINDOW_TILED_SIDE_BY_SIDE (window)) - return; - - meta_window_get_work_area_for_monitor (window, - window->tile_monitor_number, - &work_area); - window->tile_hfraction = (double)new_w / work_area.width; - - if (tile_match && window->display->grab_window == window) - meta_window_tile (tile_match, tile_match->tile_mode); -} - -static void -update_edge_constraints (MetaWindow *window) -{ - switch (window->tile_mode) - { - case META_TILE_NONE: - window->edge_constraints.top = META_EDGE_CONSTRAINT_NONE; - window->edge_constraints.right = META_EDGE_CONSTRAINT_NONE; - window->edge_constraints.bottom = META_EDGE_CONSTRAINT_NONE; - window->edge_constraints.left = META_EDGE_CONSTRAINT_NONE; - break; - - case META_TILE_MAXIMIZED: - window->edge_constraints.top = META_EDGE_CONSTRAINT_MONITOR; - window->edge_constraints.right = META_EDGE_CONSTRAINT_MONITOR; - window->edge_constraints.bottom = META_EDGE_CONSTRAINT_MONITOR; - window->edge_constraints.left = META_EDGE_CONSTRAINT_MONITOR; - break; - - case META_TILE_LEFT: - window->edge_constraints.top = META_EDGE_CONSTRAINT_MONITOR; - - if (window->tile_match) - window->edge_constraints.right = META_EDGE_CONSTRAINT_WINDOW; - else - window->edge_constraints.right = META_EDGE_CONSTRAINT_NONE; - - window->edge_constraints.bottom = META_EDGE_CONSTRAINT_MONITOR; - window->edge_constraints.left = META_EDGE_CONSTRAINT_MONITOR; - break; - - case META_TILE_RIGHT: - window->edge_constraints.top = META_EDGE_CONSTRAINT_MONITOR; - window->edge_constraints.right = META_EDGE_CONSTRAINT_MONITOR; - window->edge_constraints.bottom = META_EDGE_CONSTRAINT_MONITOR; - - if (window->tile_match) - window->edge_constraints.left = META_EDGE_CONSTRAINT_WINDOW; - else - window->edge_constraints.left = META_EDGE_CONSTRAINT_NONE; - break; - } - - /* h/vmaximize also modify the edge constraints */ - if (window->maximized_vertically) - { - window->edge_constraints.top = META_EDGE_CONSTRAINT_MONITOR; - window->edge_constraints.bottom = META_EDGE_CONSTRAINT_MONITOR; - } - - if (window->maximized_horizontally) - { - window->edge_constraints.right = META_EDGE_CONSTRAINT_MONITOR; - window->edge_constraints.left = META_EDGE_CONSTRAINT_MONITOR; - } -} - -void -meta_window_untile (MetaWindow *window) -{ - window->tile_monitor_number = - window->saved_maximize ? window->monitor->number - : -1; - window->tile_mode = - window->saved_maximize ? META_TILE_MAXIMIZED - : META_TILE_NONE; - - if (window->saved_maximize) - meta_window_maximize (window, META_MAXIMIZE_BOTH); - else - meta_window_unmaximize (window, META_MAXIMIZE_BOTH); -} - -void -meta_window_tile (MetaWindow *window, - MetaTileMode tile_mode) -{ - MetaMaximizeFlags directions; - MetaRectangle old_frame_rect, old_buffer_rect; - - meta_window_get_tile_fraction (window, tile_mode, &window->tile_hfraction); - window->tile_mode = tile_mode; - - /* Don't do anything if no tiling is requested */ - if (window->tile_mode == META_TILE_NONE) - { - window->tile_monitor_number = -1; - return; - } - else if (window->tile_monitor_number < 0) - { - window->tile_monitor_number = window->monitor->number; - } - - if (window->tile_mode == META_TILE_MAXIMIZED) - directions = META_MAXIMIZE_BOTH; - else - directions = META_MAXIMIZE_VERTICAL; - - meta_window_maximize_internal (window, directions, NULL); - meta_display_update_tile_preview (window->display, FALSE); - - /* Setup the edge constraints */ - update_edge_constraints (window); - - meta_window_get_frame_rect (window, &old_frame_rect); - meta_window_get_buffer_rect (window, &old_buffer_rect); - - meta_compositor_size_change_window (window->display->compositor, window, - META_SIZE_CHANGE_MAXIMIZE, - &old_frame_rect, &old_buffer_rect); - - meta_window_move_resize_internal (window, - (META_MOVE_RESIZE_MOVE_ACTION | - META_MOVE_RESIZE_RESIZE_ACTION | - META_MOVE_RESIZE_STATE_CHANGED), - META_GRAVITY_NORTH_WEST, - window->unconstrained_rect); - - if (window->frame) - meta_frame_queue_draw (window->frame); -} - -MetaTileMode -meta_window_get_tile_mode (MetaWindow *window) -{ - return window->tile_mode; -} - -void -meta_window_restore_tile (MetaWindow *window, - MetaTileMode mode, - int width, - int height) -{ - meta_window_update_tile_fraction (window, width, height); - meta_window_tile (window, mode); -} - -static gboolean -meta_window_can_tile_maximized (MetaWindow *window) -{ - return window->has_maximize_func; -} - -gboolean -meta_window_can_tile_side_by_side (MetaWindow *window) -{ - int monitor; - MetaRectangle tile_area; - MetaRectangle client_rect; - - if (!meta_window_can_tile_maximized (window)) - return FALSE; - - monitor = meta_display_get_current_monitor (window->display); - meta_window_get_work_area_for_monitor (window, monitor, &tile_area); - - /* Do not allow tiling in portrait orientation */ - if (tile_area.height > tile_area.width) - return FALSE; - - tile_area.width /= 2; - - meta_window_frame_rect_to_client_rect (window, &tile_area, &client_rect); - - return client_rect.width >= window->size_hints.min_width && - client_rect.height >= window->size_hints.min_height; -} - -static void -unmaximize_window_before_freeing (MetaWindow *window) -{ - meta_topic (META_DEBUG_WINDOW_OPS, - "Unmaximizing %s just before freeing", - window->desc); - - window->maximized_horizontally = FALSE; - window->maximized_vertically = FALSE; - - if (window->withdrawn) /* See bug #137185 */ - { - window->rect = window->saved_rect; - set_net_wm_state (window); - } -#ifdef HAVE_WAYLAND - else if (!meta_is_wayland_compositor ()) - { - /* Do NOT update net_wm_state: this screen is closing, - * it likely will be managed by another window manager - * that will need the current _NET_WM_STATE atoms. - * Moreover, it will need to know the unmaximized geometry, - * therefore move_resize the window to saved_rect here - * before closing it. */ - meta_window_move_resize_frame (window, - FALSE, - window->saved_rect.x, - window->saved_rect.y, - window->saved_rect.width, - window->saved_rect.height); - } -#endif -} - -static void -meta_window_maybe_apply_size_hints (MetaWindow *window, - MetaRectangle *target_rect) -{ - meta_window_frame_rect_to_client_rect (window, target_rect, target_rect); - ensure_size_hints_satisfied (target_rect, &window->size_hints); - meta_window_client_rect_to_frame_rect (window, target_rect, target_rect); -} - -void -meta_window_unmaximize (MetaWindow *window, - MetaMaximizeFlags directions) -{ - gboolean unmaximize_horizontally, unmaximize_vertically; - - g_return_if_fail (!window->override_redirect); - - /* At least one of the two directions ought to be set */ - unmaximize_horizontally = directions & META_MAXIMIZE_HORIZONTAL; - unmaximize_vertically = directions & META_MAXIMIZE_VERTICAL; - g_assert (unmaximize_horizontally || unmaximize_vertically); - - if (unmaximize_horizontally && unmaximize_vertically) - window->saved_maximize = FALSE; - - /* Only do something if the window isn't already maximized in the - * given direction(s). - */ - if ((unmaximize_horizontally && window->maximized_horizontally) || - (unmaximize_vertically && window->maximized_vertically)) - { - MetaRectangle *desired_rect; - MetaRectangle target_rect; - MetaRectangle work_area; - MetaRectangle old_frame_rect, old_buffer_rect; - gboolean has_target_size; - - meta_window_get_work_area_for_monitor (window, window->monitor->number, &work_area); - meta_window_get_frame_rect (window, &old_frame_rect); - meta_window_get_buffer_rect (window, &old_buffer_rect); - - if (unmaximize_vertically) - window->tile_mode = META_TILE_NONE; - - meta_topic (META_DEBUG_WINDOW_OPS, - "Unmaximizing %s%s", - window->desc, - unmaximize_horizontally && unmaximize_vertically ? "" : - unmaximize_horizontally ? " horizontally" : - unmaximize_vertically ? " vertically" : "BUGGGGG"); - - window->maximized_horizontally = - window->maximized_horizontally && !unmaximize_horizontally; - window->maximized_vertically = - window->maximized_vertically && !unmaximize_vertically; - - /* Update the edge constraints */ - update_edge_constraints (window); - - /* recalc_features() will eventually clear the cached frame - * extents, but we need the correct frame extents in the code below, - * so invalidate the old frame extents manually up front. - */ - meta_window_frame_size_changed (window); - - desired_rect = &window->saved_rect; - - /* Unmaximize to the saved_rect position in the direction(s) - * being unmaximized. - */ - target_rect = old_frame_rect; - - /* Avoid unmaximizing to "almost maximized" size when the previous size - * is greater then 80% of the work area use MAX_UNMAXIMIZED_WINDOW_AREA of the work area as upper limit - * while maintaining the aspect ratio. - */ - if (unmaximize_horizontally && unmaximize_vertically && - desired_rect->width * desired_rect->height > work_area.width * work_area.height * MAX_UNMAXIMIZED_WINDOW_AREA) - { - if (desired_rect->width > desired_rect->height) - { - float aspect = (float)desired_rect->height / (float)desired_rect->width; - desired_rect->width = MAX (work_area.width * sqrt (MAX_UNMAXIMIZED_WINDOW_AREA), window->size_hints.min_width); - desired_rect->height = MAX (desired_rect->width * aspect, window->size_hints.min_height); - } - else - { - float aspect = (float)desired_rect->width / (float)desired_rect->height; - desired_rect->height = MAX (work_area.height * sqrt (MAX_UNMAXIMIZED_WINDOW_AREA), window->size_hints.min_height); - desired_rect->width = MAX (desired_rect->height * aspect, window->size_hints.min_width); - } - } - - if (unmaximize_horizontally) - { - target_rect.x = desired_rect->x; - target_rect.width = desired_rect->width; - } - if (unmaximize_vertically) - { - target_rect.y = desired_rect->y; - target_rect.height = desired_rect->height; - } - - /* Window's size hints may have changed while maximized, making - * saved_rect invalid. #329152 - * Do not enforce limits, if no previous 'saved_rect' has been stored. - */ - has_target_size = (target_rect.width > 0 && target_rect.height > 0); - if (has_target_size) - meta_window_maybe_apply_size_hints (window, &target_rect); - - meta_compositor_size_change_window (window->display->compositor, window, - META_SIZE_CHANGE_UNMAXIMIZE, - &old_frame_rect, &old_buffer_rect); - - meta_window_move_resize_internal (window, - (META_MOVE_RESIZE_MOVE_ACTION | - META_MOVE_RESIZE_RESIZE_ACTION | - META_MOVE_RESIZE_STATE_CHANGED | - META_MOVE_RESIZE_UNMAXIMIZE), - META_GRAVITY_NORTH_WEST, - target_rect); - - /* When we unmaximize, if we're doing a mouse move also we could - * get the window suddenly jumping to the upper left corner of - * the workspace, since that's where it was when the grab op - * started. So we need to update the grab anchor position. - */ - if (meta_grab_op_is_moving (window->display->grab_op) && - window->display->grab_window == window) - { - window->display->grab_anchor_window_pos = target_rect; - } - - meta_window_recalc_features (window); - set_net_wm_state (window); - if (!window->monitor->in_fullscreen) - meta_display_queue_check_fullscreen (window->display); - } - - g_object_freeze_notify (G_OBJECT (window)); - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_MAXIMIZED_HORIZONTALLY]); - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_MAXIMIZED_VERTICALLY]); - g_object_thaw_notify (G_OBJECT (window)); -} - -void -meta_window_make_above (MetaWindow *window) -{ - g_return_if_fail (!window->override_redirect); - - meta_window_set_above (window, TRUE); - meta_window_raise (window); -} - -void -meta_window_unmake_above (MetaWindow *window) -{ - g_return_if_fail (!window->override_redirect); - - meta_window_set_above (window, FALSE); - meta_window_raise (window); -} - -static void -meta_window_set_above (MetaWindow *window, - gboolean new_value) -{ - new_value = new_value != FALSE; - if (new_value == window->wm_state_above) - return; - - window->wm_state_above = new_value; - meta_window_update_layer (window); - set_net_wm_state (window); - meta_window_frame_size_changed (window); - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_ABOVE]); -} - -void -meta_window_make_fullscreen_internal (MetaWindow *window) -{ - if (!window->fullscreen) - { - meta_topic (META_DEBUG_WINDOW_OPS, - "Fullscreening %s", window->desc); - - if (window->shaded) - { - /* Shading sucks anyway; I'm not adding a timestamp argument - * to this function just for this niche usage & corner case. - */ - guint32 timestamp = - meta_display_get_current_time_roundtrip (window->display); - meta_window_unshade (window, timestamp); - } - - window->saved_rect_fullscreen = window->rect; - - window->fullscreen = TRUE; - - meta_stack_freeze (window->display->stack); - - meta_window_raise (window); - meta_stack_thaw (window->display->stack); - - meta_window_recalc_features (window); - set_net_wm_state (window); - - /* For the auto-minimize feature, if we fail to get focus */ - meta_display_queue_check_fullscreen (window->display); - - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_FULLSCREEN]); - } -} - -void -meta_window_make_fullscreen (MetaWindow *window) -{ - g_return_if_fail (!window->override_redirect); - - if (!window->fullscreen) - { - MetaRectangle old_frame_rect, old_buffer_rect; - - meta_window_get_frame_rect (window, &old_frame_rect); - meta_window_get_buffer_rect (window, &old_buffer_rect); - - meta_compositor_size_change_window (window->display->compositor, - window, META_SIZE_CHANGE_FULLSCREEN, - &old_frame_rect, &old_buffer_rect); - - meta_window_make_fullscreen_internal (window); - meta_window_move_resize_internal (window, - (META_MOVE_RESIZE_MOVE_ACTION | - META_MOVE_RESIZE_RESIZE_ACTION | - META_MOVE_RESIZE_STATE_CHANGED), - META_GRAVITY_NORTH_WEST, - window->unconstrained_rect); - } -} - -void -meta_window_unmake_fullscreen (MetaWindow *window) -{ - g_return_if_fail (!window->override_redirect); - - if (window->fullscreen) - { - MetaRectangle old_frame_rect, old_buffer_rect, target_rect; - gboolean has_target_size; - - meta_topic (META_DEBUG_WINDOW_OPS, - "Unfullscreening %s", window->desc); - - window->fullscreen = FALSE; - target_rect = window->saved_rect_fullscreen; - - meta_window_frame_size_changed (window); - meta_window_get_frame_rect (window, &old_frame_rect); - meta_window_get_buffer_rect (window, &old_buffer_rect); - - /* Window's size hints may have changed while maximized, making - * saved_rect invalid. #329152 - * Do not enforce limits, if no previous 'saved_rect' has been stored. - */ - has_target_size = (target_rect.width > 0 && target_rect.height > 0); - if (has_target_size) - meta_window_maybe_apply_size_hints (window, &target_rect); - - /* Need to update window->has_resize_func before we move_resize() - */ - meta_window_recalc_features (window); - set_net_wm_state (window); - - meta_compositor_size_change_window (window->display->compositor, - window, META_SIZE_CHANGE_UNFULLSCREEN, - &old_frame_rect, &old_buffer_rect); - - meta_window_move_resize_internal (window, - (META_MOVE_RESIZE_MOVE_ACTION | - META_MOVE_RESIZE_RESIZE_ACTION | - META_MOVE_RESIZE_STATE_CHANGED | - META_MOVE_RESIZE_UNFULLSCREEN), - META_GRAVITY_NORTH_WEST, - target_rect); - - meta_display_queue_check_fullscreen (window->display); - - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_FULLSCREEN]); - } -} - -static void -meta_window_clear_fullscreen_monitors (MetaWindow *window) -{ - window->fullscreen_monitors.top = NULL; - window->fullscreen_monitors.bottom = NULL; - window->fullscreen_monitors.left = NULL; - window->fullscreen_monitors.right = NULL; -} - -void -meta_window_update_fullscreen_monitors (MetaWindow *window, - MetaLogicalMonitor *top, - MetaLogicalMonitor *bottom, - MetaLogicalMonitor *left, - MetaLogicalMonitor *right) -{ - if (top && bottom && left && right) - { - window->fullscreen_monitors.top = top; - window->fullscreen_monitors.bottom = bottom; - window->fullscreen_monitors.left = left; - window->fullscreen_monitors.right = right; - } - else - { - meta_window_clear_fullscreen_monitors (window); - } - - if (window->fullscreen) - { - meta_window_queue(window, META_QUEUE_MOVE_RESIZE); - } -} - -gboolean -meta_window_has_fullscreen_monitors (MetaWindow *window) -{ - return window->fullscreen_monitors.top != NULL; -} - -void -meta_window_adjust_fullscreen_monitor_rect (MetaWindow *window, - MetaRectangle *monitor_rect) -{ - MetaWindowClass *window_class = META_WINDOW_GET_CLASS (window); - - if (window_class->adjust_fullscreen_monitor_rect) - window_class->adjust_fullscreen_monitor_rect (window, monitor_rect); -} - -void -meta_window_shade (MetaWindow *window, - guint32 timestamp) -{ - g_return_if_fail (!window->override_redirect); - - meta_topic (META_DEBUG_WINDOW_OPS, - "Shading %s", window->desc); - if (!window->shaded) - { - window->shaded = TRUE; - - meta_window_queue(window, META_QUEUE_MOVE_RESIZE | META_QUEUE_CALC_SHOWING); - meta_window_frame_size_changed (window); - - /* After queuing the calc showing, since _focus flushes it, - * and we need to focus the frame - */ - meta_topic (META_DEBUG_FOCUS, - "Re-focusing window %s after shading it", - window->desc); - meta_window_focus (window, timestamp); - - set_net_wm_state (window); - } -} - -void -meta_window_unshade (MetaWindow *window, - guint32 timestamp) -{ - g_return_if_fail (!window->override_redirect); - - meta_topic (META_DEBUG_WINDOW_OPS, - "Unshading %s", window->desc); - if (window->shaded) - { - window->shaded = FALSE; - meta_window_queue(window, META_QUEUE_MOVE_RESIZE | META_QUEUE_CALC_SHOWING); - meta_window_frame_size_changed (window); - - /* focus the window */ - meta_topic (META_DEBUG_FOCUS, - "Focusing window %s after unshading it", - window->desc); - meta_window_focus (window, timestamp); - - set_net_wm_state (window); - } -} - -static gboolean -unminimize_func (MetaWindow *window, - void *data) -{ - meta_window_unminimize (window); - return TRUE; -} - -static void -unminimize_window_and_all_transient_parents (MetaWindow *window) -{ - meta_window_unminimize (window); - meta_window_foreach_ancestor (window, unminimize_func, NULL); -} - -void -meta_window_activate_full (MetaWindow *window, - guint32 timestamp, - MetaClientType source_indication, - MetaWorkspace *workspace) -{ - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - gboolean allow_workspace_switch; - - if (window->unmanaging) - { - g_warning ("Trying to activate unmanaged window '%s'", window->desc); - return; - } - - meta_topic (META_DEBUG_FOCUS, - "_NET_ACTIVE_WINDOW message sent for %s at time %u " - "by client type %u.", - window->desc, timestamp, source_indication); - - allow_workspace_switch = (timestamp != 0); - if (timestamp != 0 && - XSERVER_TIME_IS_BEFORE (timestamp, window->display->last_user_time)) - { - meta_topic (META_DEBUG_FOCUS, - "last_user_time (%u) is more recent; ignoring " - " _NET_ACTIVE_WINDOW message.", - window->display->last_user_time); - meta_window_set_demands_attention(window); - return; - } - - if (timestamp == 0) - timestamp = meta_display_get_current_time_roundtrip (window->display); - - meta_window_set_user_time (window, timestamp); - - /* disable show desktop mode unless we're a desktop component */ - maybe_leave_show_desktop_mode (window); - - /* Get window on current or given workspace */ - if (workspace == NULL) - workspace = workspace_manager->active_workspace; - - /* For non-transient windows, we just set up a pulsing indicator, - rather than move windows or workspaces. - See http://bugzilla.gnome.org/show_bug.cgi?id=482354 */ - if (window->transient_for == NULL && - !allow_workspace_switch && - !meta_window_located_on_workspace (window, workspace)) - { - meta_window_set_demands_attention (window); - /* We've marked it as demanding, don't need to do anything else. */ - return; - } - else if (window->transient_for != NULL) - { - /* Move transients to current workspace - preference dialogs should appear over - the source window. */ - meta_window_change_workspace (window, workspace); - } - - if (window->shaded) - meta_window_unshade (window, timestamp); - - unminimize_window_and_all_transient_parents (window); - - if (meta_prefs_get_raise_on_click () || - source_indication == META_CLIENT_TYPE_PAGER) - meta_window_raise (window); - - meta_topic (META_DEBUG_FOCUS, - "Focusing window %s due to activation", - window->desc); - - if (meta_window_located_on_workspace (window, workspace)) - meta_window_focus (window, timestamp); - else - meta_workspace_activate_with_focus (window->workspace, window, timestamp); - - meta_window_check_alive (window, timestamp); -} - -/* This function exists since most of the functionality in window_activate - * is useful for Mutter, but Mutter shouldn't need to specify a client - * type for itself. ;-) - */ -void -meta_window_activate (MetaWindow *window, - guint32 timestamp) -{ - g_return_if_fail (!window->override_redirect); - - /* We're not really a pager, but the behavior we want is the same as if - * we were such. If we change the pager behavior later, we could revisit - * this and just add extra flags to window_activate. - */ - meta_window_activate_full (window, timestamp, META_CLIENT_TYPE_PAGER, NULL); -} - -void -meta_window_activate_with_workspace (MetaWindow *window, - guint32 timestamp, - MetaWorkspace *workspace) -{ - g_return_if_fail (!window->override_redirect); - - meta_window_activate_full (window, timestamp, META_CLIENT_TYPE_APPLICATION, workspace); -} - -/** - * meta_window_updates_are_frozen: - * @window: a #MetaWindow - * - * Gets whether the compositor should be updating the window contents; - * window content updates may be frozen at client request by setting - * an odd value in the extended _NET_WM_SYNC_REQUEST_COUNTER counter - * by the window manager during a resize operation while waiting for - * the client to redraw. - * - * Return value: %TRUE if updates are currently frozen - */ -gboolean -meta_window_updates_are_frozen (MetaWindow *window) -{ - return META_WINDOW_GET_CLASS (window)->are_updates_frozen (window); -} - -static void -meta_window_reposition (MetaWindow *window) -{ - meta_window_move_resize_internal (window, - (META_MOVE_RESIZE_MOVE_ACTION | - META_MOVE_RESIZE_RESIZE_ACTION), - META_GRAVITY_NORTH_WEST, - window->rect); -} - -static gboolean -maybe_move_attached_window (MetaWindow *window, - void *data) -{ - if (window->hidden) - return G_SOURCE_CONTINUE; - - if (meta_window_is_attached_dialog (window) || - meta_window_get_placement_rule (window)) - meta_window_reposition (window); - - return G_SOURCE_CONTINUE; -} - -/** - * meta_window_get_monitor: - * @window: a #MetaWindow - * - * Gets index of the monitor that this window is on. - * - * Return Value: The index of the monitor in the screens monitor list, or -1 - * if the window has been recently unmanaged and does not have a monitor. - */ -int -meta_window_get_monitor (MetaWindow *window) -{ - if (!window->monitor) - return -1; - - return window->monitor->number; -} - -MetaLogicalMonitor * -meta_window_get_main_logical_monitor (MetaWindow *window) -{ - return window->monitor; -} - -static MetaLogicalMonitor * -find_monitor_by_winsys_id (MetaWindow *window, - uint64_t winsys_id) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - GList *logical_monitors, *l; - - logical_monitors = - meta_monitor_manager_get_logical_monitors (monitor_manager); - - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - - if (logical_monitor->winsys_id == winsys_id) - return logical_monitor; - } - - return NULL; -} - -/* This is called when the monitor setup has changed. The window->monitor - * reference is still "valid", but refer to the previous monitor setup */ -void -meta_window_update_for_monitors_changed (MetaWindow *window) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - const MetaLogicalMonitor *old, *new; - - if (meta_window_has_fullscreen_monitors (window)) - meta_window_clear_fullscreen_monitors (window); - - if (window->override_redirect || window->type == META_WINDOW_DESKTOP) - { - meta_window_update_monitor (window, - META_WINDOW_UPDATE_MONITOR_FLAGS_FORCE); - goto out; - } - - old = window->monitor; - - /* Try the preferred output first */ - new = find_monitor_by_winsys_id (window, window->preferred_output_winsys_id); - - /* Otherwise, try to find the old output on a new monitor */ - if (old && !new) - new = find_monitor_by_winsys_id (window, old->winsys_id); - - /* Fall back to primary if everything else failed */ - if (!new) - new = meta_monitor_manager_get_primary_logical_monitor (monitor_manager); - - if (window->tile_mode != META_TILE_NONE) - { - if (new) - window->tile_monitor_number = new->number; - else - window->tile_monitor_number = -1; - } - - if (new && old) - { - /* This will eventually reach meta_window_update_monitor that - * will send leave/enter-monitor events. The old != new monitor - * check will always fail (due to the new logical_monitors set) so - * we will always send the events, even if the new and old monitor - * index is the same. That is right, since the enumeration of the - * monitors changed and the same index could be refereing - * to a different monitor. */ - meta_window_move_between_rects (window, - META_MOVE_RESIZE_FORCE_UPDATE_MONITOR, - &old->rect, - &new->rect); - } - else - { - meta_window_update_monitor (window, - META_WINDOW_UPDATE_MONITOR_FLAGS_FORCE); - } - -out: - g_assert (!window->monitor || - g_list_find (meta_monitor_manager_get_logical_monitors (monitor_manager), - window->monitor)); -} - -void -meta_window_update_monitor (MetaWindow *window, - MetaWindowUpdateMonitorFlags flags) -{ - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - const MetaLogicalMonitor *old; - - old = window->monitor; - META_WINDOW_GET_CLASS (window)->update_main_monitor (window, flags); - if (old != window->monitor) - { - meta_window_on_all_workspaces_changed (window); - - /* If workspaces only on primary and we moved back to primary due to a user action, - * ensure that the window is now in that workspace. We do this because while - * the window is on a non-primary monitor it is always visible, so it would be - * very jarring if it disappeared when it crossed the monitor border. - * The one time we want it to both change to the primary monitor and a non-active - * workspace is when dropping the window on some other workspace thumbnail directly. - * That should be handled by explicitly moving the window before changing the - * workspace. - */ - if (meta_prefs_get_workspaces_only_on_primary () && - flags & META_WINDOW_UPDATE_MONITOR_FLAGS_USER_OP && - meta_window_is_on_primary_monitor (window) && - workspace_manager->active_workspace != window->workspace) - meta_window_change_workspace (window, workspace_manager->active_workspace); - - meta_window_main_monitor_changed (window, old); - - /* If we're changing monitors, we need to update the has_maximize_func flag, - * as the working area has changed. */ - meta_window_recalc_features (window); - } -} - -void -meta_window_move_resize_internal (MetaWindow *window, - MetaMoveResizeFlags flags, - MetaGravity gravity, - MetaRectangle frame_rect) -{ - /* The rectangle here that's passed in *always* in "frame rect" - * coordinates. That means the position of the frame's visible bounds, - * with x and y being absolute (root window) coordinates. - * - * For an X11 framed window, the client window's server rectangle is - * inset from this rectangle by the frame's visible borders, and the - * frame window's server rectangle is outset by the invisible borders. - * - * For an X11 unframed window, the rectangle here directly matches - * the server's rectangle, since the visible and invisible borders - * are both 0. - * - * For an X11 CSD window, the client window's server rectangle is - * outset from this rectagle by the client-specified frame extents. - * - * For a Wayland window, this rectangle can simply be sent directly - * to the client. - */ - - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - gboolean did_placement; - MetaRectangle unconstrained_rect; - MetaRectangle constrained_rect; - MetaRectangle temporary_rect; - int rel_x = 0; - int rel_y = 0; - MetaMoveResizeResultFlags result = 0; - gboolean moved_or_resized = FALSE; - MetaWindowUpdateMonitorFlags update_monitor_flags; - - g_return_if_fail (!window->override_redirect); - - /* The action has to be a move, a resize or the wayland client - * acking our choice of size. - */ - g_assert (flags & (META_MOVE_RESIZE_MOVE_ACTION | - META_MOVE_RESIZE_RESIZE_ACTION | - META_MOVE_RESIZE_WAYLAND_FINISH_MOVE_RESIZE)); - - did_placement = !window->placed && window->calc_placement; - - /* We don't need it in the idle queue anymore. */ - meta_window_unqueue (window, META_QUEUE_MOVE_RESIZE); - - if ((flags & META_MOVE_RESIZE_RESIZE_ACTION) && (flags & META_MOVE_RESIZE_MOVE_ACTION)) - { - /* We're both moving and resizing. Just use the passed in rect. */ - unconstrained_rect = frame_rect; - } - else if ((flags & META_MOVE_RESIZE_RESIZE_ACTION)) - { - /* If this is only a resize, then ignore the position given in - * the parameters and instead calculate the new position from - * resizing the old rectangle with the given gravity. */ - meta_rectangle_resize_with_gravity (&window->rect, - &unconstrained_rect, - gravity, - frame_rect.width, - frame_rect.height); - } - else if ((flags & META_MOVE_RESIZE_MOVE_ACTION)) - { - /* If this is only a move, then ignore the passed in size and - * just use the existing size of the window. */ - unconstrained_rect.x = frame_rect.x; - unconstrained_rect.y = frame_rect.y; - unconstrained_rect.width = window->rect.width; - unconstrained_rect.height = window->rect.height; - } - else if ((flags & META_MOVE_RESIZE_WAYLAND_FINISH_MOVE_RESIZE)) - { - /* This is a Wayland buffer acking our size. The new rect is - * just the existing one we have. Ignore the passed-in rect - * completely. */ - unconstrained_rect = window->rect; - } - else - g_assert_not_reached (); - - constrained_rect = unconstrained_rect; - temporary_rect = window->rect; - if (flags & (META_MOVE_RESIZE_MOVE_ACTION | META_MOVE_RESIZE_RESIZE_ACTION) && - !(flags & META_MOVE_RESIZE_WAYLAND_FINISH_MOVE_RESIZE) && - !(flags & (META_MOVE_RESIZE_UNMAXIMIZE | META_MOVE_RESIZE_UNFULLSCREEN)) && - window->monitor) - { - MetaRectangle old_rect; - meta_window_get_frame_rect (window, &old_rect); - - meta_window_constrain (window, - flags, - gravity, - &old_rect, - &constrained_rect, - &temporary_rect, - &rel_x, - &rel_y); - } - else if (window->placement.rule) - { - rel_x = window->placement.pending.rel_x; - rel_y = window->placement.pending.rel_y; - } - - /* If we did placement, then we need to save the position that the window - * was placed at to make sure that meta_window_move_resize_now places the - * window correctly. - */ - if (did_placement) - { - unconstrained_rect.x = constrained_rect.x; - unconstrained_rect.y = constrained_rect.y; - } - - /* Do the protocol-specific move/resize logic */ - META_WINDOW_GET_CLASS (window)->move_resize_internal (window, - gravity, - unconstrained_rect, - constrained_rect, - temporary_rect, - rel_x, - rel_y, - flags, &result); - - if (result & META_MOVE_RESIZE_RESULT_MOVED) - { - moved_or_resized = TRUE; - g_signal_emit (window, window_signals[POSITION_CHANGED], 0); - } - - if (result & META_MOVE_RESIZE_RESULT_RESIZED) - { - moved_or_resized = TRUE; - g_signal_emit (window, window_signals[SIZE_CHANGED], 0); - } - - if (moved_or_resized || did_placement) - window->unconstrained_rect = unconstrained_rect; - - if ((moved_or_resized || - did_placement || - (result & META_MOVE_RESIZE_RESULT_STATE_CHANGED) != 0) && - window->known_to_compositor) - { - meta_compositor_sync_window_geometry (window->display->compositor, - window, - did_placement); - } - - update_monitor_flags = META_WINDOW_UPDATE_MONITOR_FLAGS_NONE; - if (flags & META_MOVE_RESIZE_USER_ACTION) - update_monitor_flags |= META_WINDOW_UPDATE_MONITOR_FLAGS_USER_OP; - if (flags & META_MOVE_RESIZE_FORCE_UPDATE_MONITOR) - update_monitor_flags |= META_WINDOW_UPDATE_MONITOR_FLAGS_FORCE; - - if (window->monitor) - { - uint64_t old_output_winsys_id; - - old_output_winsys_id = window->monitor->winsys_id; - - meta_window_update_monitor (window, update_monitor_flags); - - if (old_output_winsys_id != window->monitor->winsys_id && - flags & META_MOVE_RESIZE_MOVE_ACTION && flags & META_MOVE_RESIZE_USER_ACTION) - window->preferred_output_winsys_id = window->monitor->winsys_id; - } - else - { - meta_window_update_monitor (window, update_monitor_flags); - } - - if ((result & META_MOVE_RESIZE_RESULT_FRAME_SHAPE_CHANGED) && window->frame_bounds) - { - cairo_region_destroy (window->frame_bounds); - window->frame_bounds = NULL; - } - - meta_window_foreach_transient (window, maybe_move_attached_window, NULL); - - meta_stack_update_window_tile_matches (window->display->stack, - workspace_manager->active_workspace); -} - -/** - * meta_window_move_frame: - * @window: a #MetaWindow - * @user_op: bool to indicate whether or not this is a user operation - * @root_x_nw: desired x pos - * @root_y_nw: desired y pos - * - * Moves the window to the desired location on window's assigned - * workspace, using the northwest edge of the frame as the reference, - * instead of the actual window's origin, but only if a frame is present. - * Otherwise, acts identically to meta_window_move(). - */ -void -meta_window_move_frame (MetaWindow *window, - gboolean user_op, - int root_x_nw, - int root_y_nw) -{ - MetaMoveResizeFlags flags; - MetaRectangle rect = { root_x_nw, root_y_nw, 0, 0 }; - - g_return_if_fail (!window->override_redirect); - - flags = (user_op ? META_MOVE_RESIZE_USER_ACTION : 0) | META_MOVE_RESIZE_MOVE_ACTION; - meta_window_move_resize_internal (window, flags, META_GRAVITY_NORTH_WEST, rect); -} - -static void -meta_window_move_between_rects (MetaWindow *window, - MetaMoveResizeFlags move_resize_flags, - const MetaRectangle *old_area, - const MetaRectangle *new_area) -{ - int rel_x, rel_y; - double scale_x, scale_y; - - if (old_area) - { - rel_x = window->unconstrained_rect.x - old_area->x; - rel_y = window->unconstrained_rect.y - old_area->y; - scale_x = (double)new_area->width / old_area->width; - scale_y = (double)new_area->height / old_area->height; - } - else - { - rel_x = rel_y = scale_x = scale_y = 0; - } - - window->unconstrained_rect.x = new_area->x + rel_x * scale_x; - window->unconstrained_rect.y = new_area->y + rel_y * scale_y; - window->saved_rect.x = window->unconstrained_rect.x; - window->saved_rect.y = window->unconstrained_rect.y; - - meta_window_move_resize_internal (window, - move_resize_flags | - META_MOVE_RESIZE_MOVE_ACTION | - META_MOVE_RESIZE_RESIZE_ACTION, - META_GRAVITY_NORTH_WEST, - window->unconstrained_rect); -} - -/** - * meta_window_move_resize_frame: - * @window: a #MetaWindow - * @user_op: bool to indicate whether or not this is a user operation - * @root_x_nw: new x - * @root_y_nw: new y - * @w: desired width - * @h: desired height - * - * Resizes the window so that its outer bounds (including frame) - * fit within the given rect - */ -void -meta_window_move_resize_frame (MetaWindow *window, - gboolean user_op, - int root_x_nw, - int root_y_nw, - int w, - int h) -{ - MetaMoveResizeFlags flags; - MetaRectangle rect = { root_x_nw, root_y_nw, w, h }; - - g_return_if_fail (!window->override_redirect); - - flags = (user_op ? META_MOVE_RESIZE_USER_ACTION : 0) | META_MOVE_RESIZE_MOVE_ACTION | META_MOVE_RESIZE_RESIZE_ACTION; - - meta_window_move_resize_internal (window, flags, META_GRAVITY_NORTH_WEST, rect); -} - -/** - * meta_window_move_to_monitor: - * @window: a #MetaWindow - * @monitor: desired monitor index - * - * Moves the window to the monitor with index @monitor, keeping - * the relative position of the window's top left corner. - */ -void -meta_window_move_to_monitor (MetaWindow *window, - int monitor) -{ - MetaRectangle old_area, new_area; - - if (window->tile_mode != META_TILE_NONE) - window->tile_monitor_number = monitor; - - meta_window_get_work_area_for_monitor (window, - window->monitor->number, - &old_area); - meta_window_get_work_area_for_monitor (window, - monitor, - &new_area); - - if (window->unconstrained_rect.width == 0 || - window->unconstrained_rect.height == 0 || - !meta_rectangle_overlap (&window->unconstrained_rect, &old_area)) - { - meta_window_move_between_rects (window, 0, NULL, &new_area); - } - else - { - if (monitor == window->monitor->number) - return; - - meta_window_move_between_rects (window, 0, &old_area, &new_area); - } - - window->preferred_output_winsys_id = window->monitor->winsys_id; - - if (window->fullscreen || window->override_redirect) - meta_display_queue_check_fullscreen (window->display); -} - -static void -adjust_size_for_tile_match (MetaWindow *window, - int *new_w, - int *new_h) -{ - MetaRectangle work_area, rect; - MetaWindow *tile_match = window->tile_match; - - if (!META_WINDOW_TILED_SIDE_BY_SIDE (window) || !tile_match) - return; - - meta_window_get_work_area_for_monitor (window, window->tile_monitor_number, &work_area); - - /* Make sure the resize does not break minimum sizes */ - rect = work_area; - rect.width = *new_w; - - meta_window_frame_rect_to_client_rect (window, &rect, &rect); - *new_w += MAX(0, window->size_hints.min_width - rect.width); - - /* Make sure we're not resizing the tile match below its min width */ - rect = work_area; - rect.width = work_area.width - *new_w; - - meta_window_frame_rect_to_client_rect (tile_match, &rect, &rect); - *new_w -= MAX(0, tile_match->size_hints.min_width - rect.width); -} - -void -meta_window_resize_frame_with_gravity (MetaWindow *window, - gboolean user_op, - int w, - int h, - MetaGravity gravity) -{ - MetaMoveResizeFlags flags; - MetaRectangle rect; - - rect.width = w; - rect.height = h; - - if (user_op) - { - /* When resizing in-tandem with a tile match, we need to respect - * its minimum width - */ - if (window->display->grab_window == window) - adjust_size_for_tile_match (window, &w, &h); - meta_window_update_tile_fraction (window, w, h); - } - - flags = (user_op ? META_MOVE_RESIZE_USER_ACTION : 0) | META_MOVE_RESIZE_RESIZE_ACTION; - meta_window_move_resize_internal (window, flags, gravity, rect); -} - -static void -meta_window_move_resize_now (MetaWindow *window) -{ - meta_window_move_resize_frame (window, FALSE, - window->unconstrained_rect.x, - window->unconstrained_rect.y, - window->unconstrained_rect.width, - window->unconstrained_rect.height); -} - -static gboolean -idle_move_resize (gpointer data) -{ - GSList *tmp; - GSList *copy; - guint queue_index = GPOINTER_TO_INT (data); - - meta_topic (META_DEBUG_GEOMETRY, "Clearing the move_resize queue"); - - /* Work with a copy, for reentrancy. The allowed reentrancy isn't - * complete; destroying a window while we're in here would result in - * badness. But it's OK to queue/unqueue move_resizes. - */ - copy = g_slist_copy (queue_pending[queue_index]); - g_slist_free (queue_pending[queue_index]); - queue_pending[queue_index] = NULL; - queue_later[queue_index] = 0; - - destroying_windows_disallowed += 1; - - tmp = copy; - while (tmp != NULL) - { - MetaWindow *window; - - window = tmp->data; - - /* As a side effect, sets window->move_resize_queued = FALSE */ - meta_window_move_resize_now (window); - - tmp = tmp->next; - } - - g_slist_free (copy); - - destroying_windows_disallowed -= 1; - - return FALSE; -} - -void -meta_window_get_gravity_position (MetaWindow *window, - MetaGravity gravity, - int *root_x, - int *root_y) -{ - MetaRectangle frame_extents; - int w, h; - int x, y; - - w = window->rect.width; - h = window->rect.height; - - if (gravity == META_GRAVITY_STATIC) - { - frame_extents = window->rect; - if (window->frame) - { - frame_extents.x = window->frame->rect.x + window->frame->child_x; - frame_extents.y = window->frame->rect.y + window->frame->child_y; - } - } - else - { - if (window->frame == NULL) - frame_extents = window->rect; - else - frame_extents = window->frame->rect; - } - - x = frame_extents.x; - y = frame_extents.y; - - switch (gravity) - { - case META_GRAVITY_NORTH: - case META_GRAVITY_CENTER: - case META_GRAVITY_SOUTH: - /* Find center of frame. */ - x += frame_extents.width / 2; - /* Center client window on that point. */ - x -= w / 2; - break; - - case META_GRAVITY_SOUTH_EAST: - case META_GRAVITY_EAST: - case META_GRAVITY_NORTH_EAST: - /* Find right edge of frame */ - x += frame_extents.width; - /* Align left edge of client at that point. */ - x -= w; - break; - default: - break; - } - - switch (gravity) - { - case META_GRAVITY_WEST: - case META_GRAVITY_CENTER: - case META_GRAVITY_EAST: - /* Find center of frame. */ - y += frame_extents.height / 2; - /* Center client window there. */ - y -= h / 2; - break; - case META_GRAVITY_SOUTH_WEST: - case META_GRAVITY_SOUTH: - case META_GRAVITY_SOUTH_EAST: - /* Find south edge of frame */ - y += frame_extents.height; - /* Place bottom edge of client there */ - y -= h; - break; - default: - break; - } - - if (root_x) - *root_x = x; - if (root_y) - *root_y = y; -} - -void -meta_window_get_session_geometry (MetaWindow *window, - int *x, - int *y, - int *width, - int *height) -{ - meta_window_get_gravity_position (window, - window->size_hints.win_gravity, - x, y); - - *width = (window->rect.width - window->size_hints.base_width) / - window->size_hints.width_inc; - *height = (window->rect.height - window->size_hints.base_height) / - window->size_hints.height_inc; -} - -/** - * meta_window_get_buffer_rect: - * @window: a #MetaWindow - * @rect: (out): pointer to an allocated #MetaRectangle - * - * Gets the rectangle that the pixmap or buffer of @window occupies. - * - * For X11 windows, this is the server-side geometry of the toplevel - * window. - * - * For Wayland windows, this is the bounding rectangle of the attached - * buffer. - */ -void -meta_window_get_buffer_rect (const MetaWindow *window, - MetaRectangle *rect) -{ - *rect = window->buffer_rect; -} - -/** - * meta_window_client_rect_to_frame_rect: - * @window: a #MetaWindow - * @client_rect: client rectangle in root coordinates - * @frame_rect: (out): location to store the computed corresponding frame bounds. - * - * Converts a desired bounds of the client window into the corresponding bounds - * of the window frame (excluding invisible borders and client side shadows.) - */ -void -meta_window_client_rect_to_frame_rect (MetaWindow *window, - MetaRectangle *client_rect, - MetaRectangle *frame_rect) -{ - if (!frame_rect) - return; - - *frame_rect = *client_rect; - - /* The support for G_MAXINT here to mean infinity is a convenience for - * constraints.c:get_size_limits() and not something that we provide - * in other locations or document. - */ - if (window->frame) - { - MetaFrameBorders borders; - meta_frame_calc_borders (window->frame, &borders); - - frame_rect->x -= borders.visible.left; - frame_rect->y -= borders.visible.top; - if (frame_rect->width != G_MAXINT) - frame_rect->width += borders.visible.left + borders.visible.right; - if (frame_rect->height != G_MAXINT) - frame_rect->height += borders.visible.top + borders.visible.bottom; - } - else - { - const GtkBorder *extents = &window->custom_frame_extents; - frame_rect->x += extents->left; - frame_rect->y += extents->top; - if (frame_rect->width != G_MAXINT) - frame_rect->width -= extents->left + extents->right; - if (frame_rect->height != G_MAXINT) - frame_rect->height -= extents->top + extents->bottom; - } -} - -/** - * meta_window_frame_rect_to_client_rect: - * @window: a #MetaWindow - * @frame_rect: desired frame bounds for the window - * @client_rect: (out): location to store the computed corresponding client rectangle. - * - * Converts a desired frame bounds for a window into the bounds of the client - * window. - */ -void -meta_window_frame_rect_to_client_rect (MetaWindow *window, - MetaRectangle *frame_rect, - MetaRectangle *client_rect) -{ - if (!client_rect) - return; - - *client_rect = *frame_rect; - - if (window->frame) - { - MetaFrameBorders borders; - meta_frame_calc_borders (window->frame, &borders); - - client_rect->x += borders.visible.left; - client_rect->y += borders.visible.top; - client_rect->width -= borders.visible.left + borders.visible.right; - client_rect->height -= borders.visible.top + borders.visible.bottom; - } - else - { - const GtkBorder *extents = &window->custom_frame_extents; - client_rect->x -= extents->left; - client_rect->y -= extents->top; - client_rect->width += extents->left + extents->right; - client_rect->height += extents->top + extents->bottom; - } -} - -/** - * meta_window_get_frame_rect: - * @window: a #MetaWindow - * @rect: (out): pointer to an allocated #MetaRectangle - * - * Gets the rectangle that bounds @window that is what the user thinks of - * as the edge of the window. This doesn't include any extra reactive - * area that we or the client adds to the window, or any area that the - * client adds to draw a client-side shadow. - */ -void -meta_window_get_frame_rect (const MetaWindow *window, - MetaRectangle *rect) -{ - *rect = window->rect; -} - -/** - * meta_window_get_client_area_rect: - * @window: a #MetaWindow - * @rect: (out): pointer to a cairo rectangle - * - * Gets the rectangle for the boundaries of the client area, relative - * to the buffer rect. If the window is shaded, the height of the - * rectangle is 0. - */ -void -meta_window_get_client_area_rect (const MetaWindow *window, - cairo_rectangle_int_t *rect) -{ - MetaFrameBorders borders; - - meta_frame_calc_borders (window->frame, &borders); - - rect->x = borders.total.left; - rect->y = borders.total.top; - - rect->width = window->buffer_rect.width - borders.total.left - borders.total.right; - if (window->shaded) - rect->height = 0; - else - rect->height = window->buffer_rect.height - borders.total.top - borders.total.bottom; -} - -void -meta_window_get_titlebar_rect (MetaWindow *window, - MetaRectangle *rect) -{ - meta_window_get_frame_rect (window, rect); - - /* The returned rectangle is relative to the frame rect. */ - rect->x = 0; - rect->y = 0; - - if (window->frame) - { - rect->height = window->frame->child_y; - } - else - { - /* Pick an arbitrary height for a titlebar. We might want to - * eventually have CSD windows expose their borders to us. */ - rect->height = 50; - } -} - -const char* -meta_window_get_startup_id (MetaWindow *window) -{ - if (window->startup_id == NULL) - { - MetaGroup *group; - - group = meta_window_get_group (window); - - if (group != NULL) - return meta_group_get_startup_id (group); - } - - return window->startup_id; -} - -static MetaWindow* -get_modal_transient (MetaWindow *window) -{ - GSList *windows; - GSList *tmp; - MetaWindow *modal_transient; - - /* A window can't be the transient of itself, but this is just for - * convenience in the loop below; we manually fix things up at the - * end if no real modal transient was found. - */ - modal_transient = window; - - windows = meta_display_list_windows (window->display, META_LIST_DEFAULT); - tmp = windows; - while (tmp != NULL) - { - MetaWindow *transient = tmp->data; - - if (transient->transient_for == modal_transient && - transient->type == META_WINDOW_MODAL_DIALOG) - { - modal_transient = transient; - tmp = windows; - continue; - } - - tmp = tmp->next; - } - - g_slist_free (windows); - - if (window == modal_transient) - modal_transient = NULL; - - return modal_transient; -} - -static gboolean -meta_window_transient_can_focus (MetaWindow *window) -{ -#ifdef HAVE_WAYLAND - if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND) - return meta_wayland_surface_get_buffer (window->surface) != NULL; -#endif - - return TRUE; -} - -/* XXX META_EFFECT_FOCUS */ -void -meta_window_focus (MetaWindow *window, - guint32 timestamp) -{ - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - MetaWindow *modal_transient; - - g_return_if_fail (!window->override_redirect); - - /* This is a oneshot flag */ - window->restore_focus_on_map = FALSE; - - meta_topic (META_DEBUG_FOCUS, - "Setting input focus to window %s, input: %d focusable: %d", - window->desc, window->input, meta_window_is_focusable (window)); - - if (window->display->grab_window && - window->display->grab_window != window && - window->display->grab_window->all_keys_grabbed && - !window->display->grab_window->unmanaging) - { - meta_topic (META_DEBUG_FOCUS, - "Current focus window %s has global keygrab, not focusing window %s after all", - window->display->grab_window->desc, window->desc); - return; - } - - modal_transient = get_modal_transient (window); - if (modal_transient != NULL && - !modal_transient->unmanaging && - meta_window_transient_can_focus (modal_transient)) - { - meta_topic (META_DEBUG_FOCUS, - "%s has %s as a modal transient, so focusing it instead.", - window->desc, modal_transient->desc); - if (!meta_window_located_on_workspace (modal_transient, workspace_manager->active_workspace)) - meta_window_change_workspace (modal_transient, workspace_manager->active_workspace); - window = modal_transient; - } - - meta_window_flush_calc_showing (window); - - if ((!window->mapped || window->hidden) && !window->shaded) - { - meta_topic (META_DEBUG_FOCUS, - "Window %s is not showing, not focusing after all", - window->desc); - return; - } - - META_WINDOW_GET_CLASS (window)->focus (window, timestamp); - - if (window->display->event_route == META_EVENT_ROUTE_NORMAL) - { - MetaBackend *backend = meta_get_backend (); - ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend)); - clutter_stage_set_key_focus (stage, NULL); - } - - if (window->close_dialog && - meta_close_dialog_is_visible (window->close_dialog)) - meta_close_dialog_focus (window->close_dialog); - - if (window->wm_state_demands_attention) - meta_window_unset_demands_attention(window); - -/* meta_effect_run_focus(window, NULL, NULL); */ -} - -/* Workspace management. Invariants: - * - * - window->workspace describes the workspace the window is on. - * - * - workspace->windows is a list of windows that is located on - * that workspace. - * - * - If the window is on_all_workspaces, then - * window->workspace == NULL, but workspace->windows contains - * the window. - */ - -static void -set_workspace_state (MetaWindow *window, - gboolean on_all_workspaces, - MetaWorkspace *workspace) -{ - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - - /* If we're on all workspaces, then our new workspace must be NULL, - * otherwise it must be set, unless we're unmanaging. */ - if (on_all_workspaces) - g_assert_null (workspace); - else - g_assert_true (window->unmanaging || workspace != NULL); - - /* If this is an override-redirect window, ensure that the only - * times we're setting the workspace state is either during construction - * to mark as on_all_workspaces, or when unmanaging to remove all the - * workspaces. */ - if (window->override_redirect) - g_return_if_fail ((window->constructing && on_all_workspaces) || window->unmanaging); - - if (on_all_workspaces == window->on_all_workspaces && - workspace == window->workspace && - !window->constructing) - return; - - if (window->workspace) - meta_workspace_remove_window (window->workspace, window); - else if (window->on_all_workspaces) - { - GList *l; - for (l = workspace_manager->workspaces; l != NULL; l = l->next) - { - MetaWorkspace *ws = l->data; - meta_workspace_remove_window (ws, window); - } - } - - window->on_all_workspaces = on_all_workspaces; - window->workspace = workspace; - - if (window->workspace) - meta_workspace_add_window (window->workspace, window); - else if (window->on_all_workspaces) - { - GList *l; - for (l = workspace_manager->workspaces; l != NULL; l = l->next) - { - MetaWorkspace *ws = l->data; - meta_workspace_add_window (ws, window); - } - } - - /* queue a move_resize since changing workspaces may change - * the relevant struts - */ - if (!window->override_redirect) - meta_window_queue (window, META_QUEUE_MOVE_RESIZE); - meta_window_queue (window, META_QUEUE_CALC_SHOWING); - meta_window_current_workspace_changed (window); - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_ON_ALL_WORKSPACES]); - g_signal_emit (window, window_signals[WORKSPACE_CHANGED], 0); -} - -static gboolean -should_be_on_all_workspaces (MetaWindow *window) -{ - if (window->always_sticky) - return TRUE; - - if (window->on_all_workspaces_requested) - return TRUE; - - if (window->override_redirect) - return TRUE; - - if (meta_prefs_get_workspaces_only_on_primary () && - !window->unmanaging && - window->monitor && - !meta_window_is_on_primary_monitor (window)) - return TRUE; - - return FALSE; -} - -void -meta_window_on_all_workspaces_changed (MetaWindow *window) -{ - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - gboolean on_all_workspaces = should_be_on_all_workspaces (window); - - if (window->on_all_workspaces == on_all_workspaces) - return; - - MetaWorkspace *workspace; - - if (on_all_workspaces) - { - workspace = NULL; - } - else - { - /* We're coming out of the sticky state. Put the window on - * the currently active workspace. */ - workspace = workspace_manager->active_workspace; - } - - set_workspace_state (window, on_all_workspaces, workspace); -} - -static void -meta_window_change_workspace_without_transients (MetaWindow *window, - MetaWorkspace *workspace) -{ - /* Try to unstick the window if it's stuck. This doesn't - * have any guarantee that we'll actually unstick the - * window, since it could be stuck for other reasons. */ - if (window->on_all_workspaces_requested) - meta_window_unstick (window); - - /* We failed to unstick the window. */ - if (window->on_all_workspaces) - return; - - if (window->workspace == workspace) - return; - - set_workspace_state (window, FALSE, workspace); -} - -static gboolean -change_workspace_foreach (MetaWindow *window, - void *data) -{ - meta_window_change_workspace_without_transients (window, data); - return TRUE; -} - -void -meta_window_change_workspace (MetaWindow *window, - MetaWorkspace *workspace) -{ - g_return_if_fail (!window->override_redirect); - - meta_window_change_workspace_without_transients (window, workspace); - - meta_window_foreach_transient (window, change_workspace_foreach, - workspace); - meta_window_foreach_ancestor (window, change_workspace_foreach, - workspace); -} - -static void -window_stick_impl (MetaWindow *window) -{ - meta_verbose ("Sticking window %s current on_all_workspaces = %d", - window->desc, window->on_all_workspaces); - - if (window->on_all_workspaces_requested) - return; - - /* We don't change window->workspaces, because we revert - * to that original workspace list if on_all_workspaces is - * toggled back off. - */ - window->on_all_workspaces_requested = TRUE; - meta_window_on_all_workspaces_changed (window); -} - -static void -window_unstick_impl (MetaWindow *window) -{ - if (!window->on_all_workspaces_requested) - return; - - /* Revert to window->workspaces */ - - window->on_all_workspaces_requested = FALSE; - meta_window_on_all_workspaces_changed (window); -} - -static gboolean -stick_foreach_func (MetaWindow *window, - void *data) -{ - gboolean stick; - - stick = *(gboolean*)data; - if (stick) - window_stick_impl (window); - else - window_unstick_impl (window); - return TRUE; -} - -void -meta_window_stick (MetaWindow *window) -{ - gboolean stick = TRUE; - - g_return_if_fail (!window->override_redirect); - - window_stick_impl (window); - meta_window_foreach_transient (window, - stick_foreach_func, - &stick); -} - -void -meta_window_unstick (MetaWindow *window) -{ - gboolean stick = FALSE; - - g_return_if_fail (!window->override_redirect); - - window_unstick_impl (window); - meta_window_foreach_transient (window, - stick_foreach_func, - &stick); -} - -void -meta_window_current_workspace_changed (MetaWindow *window) -{ - META_WINDOW_GET_CLASS (window)->current_workspace_changed (window); -} - -static gboolean -find_root_ancestor (MetaWindow *window, - void *data) -{ - MetaWindow **ancestor = data; - - /* Overwrite the previously "most-root" ancestor with the new one found */ - *ancestor = window; - - /* We want this to continue until meta_window_foreach_ancestor quits because - * there are no more valid ancestors. - */ - return TRUE; -} - -/** - * meta_window_find_root_ancestor: - * @window: a #MetaWindow - * - * Follow the chain of parents of @window, skipping transient windows, - * and return the "root" window which has no non-transient parent. - * - * Returns: (transfer none): The root ancestor window - */ -MetaWindow * -meta_window_find_root_ancestor (MetaWindow *window) -{ - MetaWindow *ancestor; - ancestor = window; - meta_window_foreach_ancestor (window, find_root_ancestor, &ancestor); - return ancestor; -} - -void -meta_window_raise (MetaWindow *window) -{ - MetaWindow *ancestor; - - g_return_if_fail (!window->override_redirect); - - ancestor = meta_window_find_root_ancestor (window); - - meta_topic (META_DEBUG_WINDOW_OPS, - "Raising window %s, ancestor of %s", - ancestor->desc, window->desc); - - /* Raise the ancestor of the window (if the window has no ancestor, - * then ancestor will be set to the window itself); do this because - * it's weird to see windows from other apps stacked between a child - * and parent window of the currently active app. The stacking - * constraints in stack.c then magically take care of raising all - * the child windows appropriately. - */ - if (window->display->stack == ancestor->display->stack) - { - meta_stack_raise (window->display->stack, ancestor); - } - else - { - meta_warning ( - "Either stacks aren't per screen or some window has a weird " - "transient_for hint; window->display->stack != " - "ancestor->screen->stack. window = %s, ancestor = %s.", - window->desc, ancestor->desc); - /* We could raise the window here, but don't want to do that twice and - * so we let the case below handle that. - */ - } - - /* Okay, so stacking constraints misses one case: If a window has - * two children and we want to raise one of those children, then - * raising the ancestor isn't enough; we need to also raise the - * correct child. See bug 307875. - */ - if (window != ancestor) - meta_stack_raise (window->display->stack, window); - - g_signal_emit (window, window_signals[RAISED], 0); -} - -void -meta_window_lower (MetaWindow *window) -{ - g_return_if_fail (!window->override_redirect); - - meta_topic (META_DEBUG_WINDOW_OPS, - "Lowering window %s", window->desc); - - meta_stack_lower (window->display->stack, window); -} - -/* - * Move window to the requested workspace; append controls whether new WS - * should be created if one does not exist. - */ -void -meta_window_change_workspace_by_index (MetaWindow *window, - gint space_index, - gboolean append) -{ - MetaWorkspaceManager *workspace_manager; - MetaWorkspace *workspace; - MetaDisplay *display; - - g_return_if_fail (!window->override_redirect); - - if (space_index == -1) - { - meta_window_stick (window); - return; - } - - display = window->display; - workspace_manager = display->workspace_manager; - - workspace = - meta_workspace_manager_get_workspace_by_index (workspace_manager, space_index); - - if (!workspace && append) - workspace = meta_workspace_manager_append_new_workspace (workspace_manager, FALSE, META_CURRENT_TIME); - - if (workspace) - meta_window_change_workspace (window, workspace); -} - -static void -meta_window_appears_focused_changed (MetaWindow *window) -{ - set_net_wm_state (window); - meta_window_frame_size_changed (window); - - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_APPEARS_FOCUSED]); - - if (window->frame) - meta_frame_queue_draw (window->frame); -} - -static gboolean -should_propagate_focus_appearance (MetaWindow *window) -{ - /* Parents of attached modal dialogs should appear focused. */ - if (meta_window_is_attached_dialog (window)) - return TRUE; - - /* Parents of these sorts of override-redirect windows should - * appear focused. */ - switch (window->type) - { - case META_WINDOW_DROPDOWN_MENU: - case META_WINDOW_POPUP_MENU: - case META_WINDOW_COMBO: - case META_WINDOW_TOOLTIP: - case META_WINDOW_NOTIFICATION: - case META_WINDOW_DND: - case META_WINDOW_OVERRIDE_OTHER: - return TRUE; - default: - break; - } - - return FALSE; -} - -/** - * meta_window_propagate_focus_appearance: - * @window: the window to start propagating from - * @focused: %TRUE if @window's ancestors should appear focused, - * %FALSE if they should not. - * - * Adjusts the value of #MetaWindow:appears-focused on @window's - * ancestors (but not @window itself). If @focused is %TRUE, each of - * @window's ancestors will have its %attached_focus_window field set - * to the current %focus_window. If @focused if %FALSE, each of - * @window's ancestors will have its %attached_focus_window field - * cleared if it is currently %focus_window. - */ -static void -meta_window_propagate_focus_appearance (MetaWindow *window, - gboolean focused) -{ - MetaWindow *child, *parent, *focus_window; - - focus_window = window->display->focus_window; - - child = window; - parent = meta_window_get_transient_for (child); - while (parent && (!focused || should_propagate_focus_appearance (child))) - { - gboolean child_focus_state_changed; - - if (focused) - { - if (parent->attached_focus_window == focus_window) - break; - child_focus_state_changed = (parent->attached_focus_window == NULL); - parent->attached_focus_window = focus_window; - } - else - { - if (parent->attached_focus_window != focus_window) - break; - child_focus_state_changed = (parent->attached_focus_window != NULL); - parent->attached_focus_window = NULL; - } - - if (child_focus_state_changed && !parent->has_focus) - { - meta_window_appears_focused_changed (parent); - } - - child = parent; - parent = meta_window_get_transient_for (child); - } -} - -void -meta_window_set_focused_internal (MetaWindow *window, - gboolean focused) -{ - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - - if (focused) - { - window->has_focus = TRUE; - if (window->override_redirect) - return; - - /* Move to the front of the focusing workspace's MRU list. - * We should only be "removing" it from the MRU list if it's - * not already there. Note that it's possible that we might - * be processing this FocusIn after we've changed to a - * different workspace; we should therefore update the MRU - * list only if the window is actually on the active - * workspace. - */ - if (workspace_manager->active_workspace && - meta_window_located_on_workspace (window, - workspace_manager->active_workspace)) - { - GList* link; - link = g_list_find (workspace_manager->active_workspace->mru_list, - window); - g_assert (link); - - workspace_manager->active_workspace->mru_list = - g_list_remove_link (workspace_manager->active_workspace->mru_list, - link); - g_list_free (link); - - workspace_manager->active_workspace->mru_list = - g_list_prepend (workspace_manager->active_workspace->mru_list, - window); - } - - if (window->frame) - meta_frame_queue_draw (window->frame); - - /* Ungrab click to focus button since the sync grab can interfere - * with some things you might do inside the focused window, by - * causing the client to get funky enter/leave events. - * - * The reason we usually have a passive grab on the window is - * so that we can intercept clicks and raise the window in - * response. For click-to-focus we don't need that since the - * focused window is already raised. When raise_on_click is - * FALSE we also don't need that since we don't do anything - * when the window is clicked. - * - * There is dicussion in bugs 102209, 115072, and 461577 - */ - if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK || - !meta_prefs_get_raise_on_click()) - { - meta_display_ungrab_focus_window_button (window->display, window); - /* Since we ungrab with XIAnyModifier above, all button - grabs go way so we need to re-grab the window buttons. */ - meta_display_grab_window_buttons (window->display, window->xwindow); - } - - g_signal_emit (window, window_signals[FOCUS], 0); - - if (!window->attached_focus_window) - meta_window_appears_focused_changed (window); - - meta_window_propagate_focus_appearance (window, TRUE); - } - else - { - window->has_focus = FALSE; - if (window->override_redirect) - return; - - meta_window_propagate_focus_appearance (window, FALSE); - - if (!window->attached_focus_window) - meta_window_appears_focused_changed (window); - - /* Re-grab for click to focus and raise-on-click, if necessary */ - if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK || - !meta_prefs_get_raise_on_click ()) - meta_display_grab_focus_window_button (window->display, window); - } -} - -/** - * meta_window_get_icon_geometry: - * @window: a #MetaWindow - * @rect: (out): rectangle into which to store the returned geometry. - * - * Gets the location of the icon corresponding to the window. The location - * will be provided set by the task bar or other user interface element - * displaying the icon, and is relative to the root window. - * - * Return value: %TRUE if the icon geometry was successfully retrieved. - */ -gboolean -meta_window_get_icon_geometry (MetaWindow *window, - MetaRectangle *rect) -{ - g_return_val_if_fail (!window->override_redirect, FALSE); - - if (window->icon_geometry_set) - { - if (rect) - *rect = window->icon_geometry; - - return TRUE; - } - - return FALSE; -} - -/** - * meta_window_set_icon_geometry: - * @window: a #MetaWindow - * @rect: (nullable): rectangle with the desired geometry or %NULL. - * - * Sets or unsets the location of the icon corresponding to the window. If - * set, the location should correspond to a dock, task bar or other user - * interface element displaying the icon, and is relative to the root window. - */ -void -meta_window_set_icon_geometry (MetaWindow *window, - MetaRectangle *rect) -{ - if (rect) - { - window->icon_geometry = *rect; - window->icon_geometry_set = TRUE; - } - else - { - window->icon_geometry_set = FALSE; - } -} - -static void -redraw_icon (MetaWindow *window) -{ - /* We could probably be smart and just redraw the icon here, - * instead of the whole frame. - */ - if (window->frame) - meta_frame_queue_draw (window->frame); -} - -static void -meta_window_update_icon_now (MetaWindow *window, - gboolean force) -{ - gboolean changed; - cairo_surface_t *icon = NULL; - cairo_surface_t *mini_icon; - - g_return_if_fail (!window->override_redirect); - - changed = META_WINDOW_GET_CLASS (window)->update_icon (window, &icon, &mini_icon); - - if (changed || force) - { - if (window->icon) - cairo_surface_destroy (window->icon); - window->icon = icon; - - if (window->mini_icon) - cairo_surface_destroy (window->mini_icon); - window->mini_icon = mini_icon; - - g_object_freeze_notify (G_OBJECT (window)); - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_ICON]); - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_MINI_ICON]); - g_object_thaw_notify (G_OBJECT (window)); - - redraw_icon (window); - } -} - -static gboolean -idle_update_icon (gpointer data) -{ - GSList *tmp; - GSList *copy; - guint queue_index = GPOINTER_TO_INT (data); - - meta_topic (META_DEBUG_GEOMETRY, "Clearing the update_icon queue"); - - /* Work with a copy, for reentrancy. The allowed reentrancy isn't - * complete; destroying a window while we're in here would result in - * badness. But it's OK to queue/unqueue update_icons. - */ - copy = g_slist_copy (queue_pending[queue_index]); - g_slist_free (queue_pending[queue_index]); - queue_pending[queue_index] = NULL; - queue_later[queue_index] = 0; - - destroying_windows_disallowed += 1; - - tmp = copy; - while (tmp != NULL) - { - MetaWindow *window; - - window = tmp->data; - - meta_window_update_icon_now (window, FALSE); - window->is_in_queues &= ~META_QUEUE_UPDATE_ICON; - - tmp = tmp->next; - } - - g_slist_free (copy); - - destroying_windows_disallowed -= 1; - - return FALSE; -} - -GList* -meta_window_get_workspaces (MetaWindow *window) -{ - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - - if (window->on_all_workspaces) - return workspace_manager->workspaces; - else if (window->workspace != NULL) - return window->workspace->list_containing_self; - else if (window->constructing) - return NULL; - else - g_assert_not_reached (); - return NULL; -} - -static void -invalidate_work_areas (MetaWindow *window) -{ - GList *tmp; - - tmp = meta_window_get_workspaces (window); - - while (tmp != NULL) - { - meta_workspace_invalidate_work_area (tmp->data); - tmp = tmp->next; - } -} - -void -meta_window_update_struts (MetaWindow *window) -{ - if (META_WINDOW_GET_CLASS (window)->update_struts (window)) - invalidate_work_areas (window); -} - -static void -meta_window_type_changed (MetaWindow *window) -{ - gboolean old_decorated = window->decorated; - GObject *object = G_OBJECT (window); - - window->attached = meta_window_should_attach_to_parent (window); - meta_window_recalc_features (window); - - if (!window->override_redirect) - set_net_wm_state (window); - - /* Update frame */ - if (window->decorated) - meta_window_ensure_frame (window); - else - meta_window_destroy_frame (window); - - /* update stacking constraints */ - meta_window_update_layer (window); - - meta_window_grab_keys (window); - - g_object_freeze_notify (object); - - if (old_decorated != window->decorated) - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_DECORATED]); - - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_WINDOW_TYPE]); - - g_object_thaw_notify (object); -} - -void -meta_window_set_type (MetaWindow *window, - MetaWindowType type) -{ - if (window->type == type) - return; - - window->type = type; - meta_window_type_changed (window); -} - -void -meta_window_frame_size_changed (MetaWindow *window) -{ - if (window->frame) - meta_frame_clear_cached_borders (window->frame); -} - -static void -meta_window_get_default_skip_hints (MetaWindow *window, - gboolean *skip_taskbar_out, - gboolean *skip_pager_out) -{ - META_WINDOW_GET_CLASS (window)->get_default_skip_hints (window, skip_taskbar_out, skip_pager_out); -} - -static void -meta_window_recalc_skip_features (MetaWindow *window) -{ - switch (window->type) - { - /* Force skip taskbar/pager on these window types */ - case META_WINDOW_DESKTOP: - case META_WINDOW_DOCK: - case META_WINDOW_TOOLBAR: - case META_WINDOW_MENU: - case META_WINDOW_UTILITY: - case META_WINDOW_SPLASHSCREEN: - case META_WINDOW_DROPDOWN_MENU: - case META_WINDOW_POPUP_MENU: - case META_WINDOW_TOOLTIP: - case META_WINDOW_NOTIFICATION: - case META_WINDOW_COMBO: - case META_WINDOW_DND: - case META_WINDOW_OVERRIDE_OTHER: - window->skip_taskbar = TRUE; - window->skip_pager = TRUE; - break; - - case META_WINDOW_DIALOG: - case META_WINDOW_MODAL_DIALOG: - /* only skip taskbar if we have a real transient parent - (and ignore the application hints) */ - if (window->transient_for != NULL) - window->skip_taskbar = TRUE; - else - window->skip_taskbar = window->skip_from_window_list; - break; - - case META_WINDOW_NORMAL: - { - gboolean skip_taskbar_hint, skip_pager_hint; - meta_window_get_default_skip_hints (window, &skip_taskbar_hint, &skip_pager_hint); - window->skip_taskbar = skip_taskbar_hint | window->skip_from_window_list; - window->skip_pager = skip_pager_hint | window->skip_from_window_list; - } - break; - } -} - -void -meta_window_recalc_features (MetaWindow *window) -{ - gboolean old_has_close_func; - gboolean old_has_minimize_func; - gboolean old_has_move_func; - gboolean old_has_resize_func; - gboolean old_has_shade_func; - gboolean old_always_sticky; - gboolean old_skip_taskbar; - - old_has_close_func = window->has_close_func; - old_has_minimize_func = window->has_minimize_func; - old_has_move_func = window->has_move_func; - old_has_resize_func = window->has_resize_func; - old_has_shade_func = window->has_shade_func; - old_always_sticky = window->always_sticky; - old_skip_taskbar = window->skip_taskbar; - - /* Use MWM hints initially */ - if (window->client_type == META_WINDOW_CLIENT_TYPE_X11) - window->decorated = window->mwm_decorated; - else - window->decorated = FALSE; - window->border_only = window->mwm_border_only; - window->has_close_func = window->mwm_has_close_func; - window->has_minimize_func = window->mwm_has_minimize_func; - window->has_maximize_func = window->mwm_has_maximize_func; - window->has_move_func = window->mwm_has_move_func; - - window->has_resize_func = TRUE; - - /* If min_size == max_size, then don't allow resize */ - if (window->size_hints.min_width == window->size_hints.max_width && - window->size_hints.min_height == window->size_hints.max_height) - window->has_resize_func = FALSE; - else if (!window->mwm_has_resize_func) - { - /* We ignore mwm_has_resize_func because WM_NORMAL_HINTS is the - * authoritative source for that info. Some apps such as mplayer or - * xine disable resize via MWM but not WM_NORMAL_HINTS, but that - * leads to e.g. us not fullscreening their windows. Apps that set - * MWM but not WM_NORMAL_HINTS are basically broken. We complain - * about these apps but make them work. - */ - - meta_warning ("Window %s sets an MWM hint indicating it isn't resizable, but sets min size %d x %d and max size %d x %d; this doesn't make much sense.", - window->desc, - window->size_hints.min_width, - window->size_hints.min_height, - window->size_hints.max_width, - window->size_hints.max_height); - } - - window->has_shade_func = TRUE; - window->has_fullscreen_func = TRUE; - - window->always_sticky = FALSE; - - /* Semantic category overrides the MWM hints */ - if (window->type == META_WINDOW_TOOLBAR) - window->decorated = FALSE; - - if (window->type == META_WINDOW_DESKTOP || - window->type == META_WINDOW_DOCK || - window->override_redirect) - window->always_sticky = TRUE; - - if (window->override_redirect || - meta_window_get_frame_type (window) == META_FRAME_TYPE_LAST) - { - window->decorated = FALSE; - window->has_close_func = FALSE; - window->has_shade_func = FALSE; - - /* FIXME this keeps panels and things from using - * NET_WM_MOVERESIZE; the problem is that some - * panels (edge panels) have fixed possible locations, - * and others ("floating panels") do not. - * - * Perhaps we should require edge panels to explicitly - * disable movement? - */ - window->has_move_func = FALSE; - window->has_resize_func = FALSE; - } - - if (window->type != META_WINDOW_NORMAL) - { - window->has_minimize_func = FALSE; - window->has_maximize_func = FALSE; - window->has_fullscreen_func = FALSE; - } - - if (!window->has_resize_func) - { - window->has_maximize_func = FALSE; - MetaRectangle display_rect = { 0 }; - - meta_display_get_size (window->display, &display_rect.width, - &display_rect.height); - - /* don't allow fullscreen if we can't resize, unless the size - * is entire screen size (kind of broken, because we - * actually fullscreen to monitor size not screen size) - */ - if (window->size_hints.min_width == display_rect.width && - window->size_hints.min_height == display_rect.height) - ; /* leave fullscreen available */ - else - window->has_fullscreen_func = FALSE; - } - - /* We leave fullscreen windows decorated, just push the frame outside - * the screen. This avoids flickering to unparent them. - * - * Note that setting has_resize_func = FALSE here must come after the - * above code that may disable fullscreen, because if the window - * is not resizable purely due to fullscreen, we don't want to - * disable fullscreen mode. - */ - if (window->fullscreen) - { - window->has_shade_func = FALSE; - window->has_move_func = FALSE; - window->has_resize_func = FALSE; - window->has_maximize_func = FALSE; - } - - if (window->has_maximize_func && window->monitor) - { - MetaRectangle work_area, client_rect; - - meta_window_get_work_area_current_monitor (window, &work_area); - meta_window_frame_rect_to_client_rect (window, &work_area, &client_rect); - - if (window->size_hints.min_width >= client_rect.width || - window->size_hints.min_height >= client_rect.height) - window->has_maximize_func = FALSE; - } - - meta_topic (META_DEBUG_WINDOW_OPS, - "Window %s fullscreen = %d not resizable, maximizable = %d fullscreenable = %d min size %dx%d max size %dx%d", - window->desc, - window->fullscreen, - window->has_maximize_func, window->has_fullscreen_func, - window->size_hints.min_width, - window->size_hints.min_height, - window->size_hints.max_width, - window->size_hints.max_height); - - /* no shading if not decorated */ - if (!window->decorated || window->border_only) - window->has_shade_func = FALSE; - - meta_window_recalc_skip_features (window); - - /* To prevent users from losing windows, let's prevent users from - * minimizing skip-taskbar windows through the window decorations. */ - if (window->skip_taskbar) - window->has_minimize_func = FALSE; - - meta_topic (META_DEBUG_WINDOW_OPS, - "Window %s decorated = %d border_only = %d has_close = %d has_minimize = %d has_maximize = %d has_move = %d has_shade = %d skip_taskbar = %d skip_pager = %d", - window->desc, - window->decorated, - window->border_only, - window->has_close_func, - window->has_minimize_func, - window->has_maximize_func, - window->has_move_func, - window->has_shade_func, - window->skip_taskbar, - window->skip_pager); - - if (old_skip_taskbar != window->skip_taskbar) - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_SKIP_TASKBAR]); - - /* FIXME: - * Lame workaround for recalc_features being used overzealously. - * The fix is to only recalc_features when something has - * actually changed. - */ - if (window->constructing || - old_has_close_func != window->has_close_func || - old_has_minimize_func != window->has_minimize_func || - old_has_move_func != window->has_move_func || - old_has_resize_func != window->has_resize_func || - old_has_shade_func != window->has_shade_func || - old_always_sticky != window->always_sticky) - set_allowed_actions_hint (window); - - if (window->has_resize_func != old_has_resize_func) - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_RESIZEABLE]); - - meta_window_frame_size_changed (window); - - /* FIXME perhaps should ensure if we don't have a shade func, - * we aren't shaded, etc. - */ -} - -void -meta_window_show_menu (MetaWindow *window, - MetaWindowMenuType menu, - int x, - int y) -{ - g_return_if_fail (!window->override_redirect); - meta_compositor_show_window_menu (window->display->compositor, window, menu, x, y); -} - -void -meta_window_show_menu_for_rect (MetaWindow *window, - MetaWindowMenuType menu, - MetaRectangle *rect) -{ - g_return_if_fail (!window->override_redirect); - meta_compositor_show_window_menu_for_rect (window->display->compositor, window, menu, rect); -} - -void -meta_window_shove_titlebar_onscreen (MetaWindow *window) -{ - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - MetaRectangle frame_rect; - GList *onscreen_region; - int horiz_amount, vert_amount; - - g_return_if_fail (!window->override_redirect); - - /* If there's no titlebar, don't bother */ - if (!window->frame) - return; - - /* Get the basic info we need */ - meta_window_get_frame_rect (window, &frame_rect); - onscreen_region = workspace_manager->active_workspace->screen_region; - - /* Extend the region (just in case the window is too big to fit on the - * screen), then shove the window on screen, then return the region to - * normal. - */ - horiz_amount = frame_rect.width; - vert_amount = frame_rect.height; - meta_rectangle_expand_region (onscreen_region, - horiz_amount, - horiz_amount, - 0, - vert_amount); - meta_rectangle_shove_into_region(onscreen_region, - FIXED_DIRECTION_X, - &frame_rect); - meta_rectangle_expand_region (onscreen_region, - -horiz_amount, - -horiz_amount, - 0, - -vert_amount); - - meta_window_move_frame (window, FALSE, frame_rect.x, frame_rect.y); -} - -gboolean -meta_window_titlebar_is_onscreen (MetaWindow *window) -{ - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - MetaRectangle titlebar_rect, frame_rect; - GList *onscreen_region; - gboolean is_onscreen; - - const int min_height_needed = 8; - const float min_width_percent = 0.5; - const int min_width_absolute = 50; - - /* Titlebar can't be offscreen if there is no titlebar... */ - if (!window->frame) - return TRUE; - - /* Get the rectangle corresponding to the titlebar */ - meta_window_get_titlebar_rect (window, &titlebar_rect); - - /* Translate into screen coordinates */ - meta_window_get_frame_rect (window, &frame_rect); - titlebar_rect.x = frame_rect.x; - titlebar_rect.y = frame_rect.y; - - /* Run through the spanning rectangles for the screen and see if one of - * them overlaps with the titlebar sufficiently to consider it onscreen. - */ - is_onscreen = FALSE; - onscreen_region = workspace_manager->active_workspace->screen_region; - while (onscreen_region) - { - MetaRectangle *spanning_rect = onscreen_region->data; - MetaRectangle overlap; - - meta_rectangle_intersect (&titlebar_rect, spanning_rect, &overlap); - if (overlap.height > MIN (titlebar_rect.height, min_height_needed) && - overlap.width > MIN (titlebar_rect.width * min_width_percent, - min_width_absolute)) - { - is_onscreen = TRUE; - break; - } - - onscreen_region = onscreen_region->next; - } - - return is_onscreen; -} - -static gboolean -check_moveresize_frequency (MetaWindow *window, - gdouble *remaining) -{ - int64_t current_time; - const double max_resizes_per_second = 25.0; - const double ms_between_resizes = 1000.0 / max_resizes_per_second; - double elapsed; - - current_time = g_get_real_time (); - - /* If we are throttling via _NET_WM_SYNC_REQUEST, we don't need - * an artificial timeout-based throttled */ - if (!window->disable_sync && - window->sync_request_alarm != None) - return TRUE; - - elapsed = (current_time - window->display->grab_last_moveresize_time) / 1000; - - if (elapsed >= 0.0 && elapsed < ms_between_resizes) - { - meta_topic (META_DEBUG_RESIZING, - "Delaying move/resize as only %g of %g ms elapsed", - elapsed, ms_between_resizes); - - if (remaining) - *remaining = (ms_between_resizes - elapsed); - - return FALSE; - } - - meta_topic (META_DEBUG_RESIZING, - " Checked moveresize freq, allowing move/resize now (%g of %g seconds elapsed)", - elapsed / 1000.0, 1.0 / max_resizes_per_second); - - return TRUE; -} - -static gboolean -update_move_timeout (gpointer data) -{ - MetaWindow *window = data; - - update_move (window, - window->display->grab_last_edge_resistance_flags, - window->display->grab_latest_motion_x, - window->display->grab_latest_motion_y); - - return FALSE; -} - -static void -update_move_maybe_tile (MetaWindow *window, - int shake_threshold, - int x, - int y) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaLogicalMonitor *logical_monitor; - MetaDisplay *display = window->display; - MetaRectangle work_area; - - /* For side-by-side tiling we are interested in the inside vertical - * edges of the work area of the monitor where the pointer is located, - * and in the outside top edge for maximized tiling. - * - * For maximized tiling we use the outside edge instead of the - * inside edge, because we don't want to force users to maximize - * windows they are placing near the top of their screens. - * - * The "current" idea of meta_window_get_work_area_current_monitor() and - * meta_screen_get_current_monitor() is slightly different: the former - * refers to the monitor which contains the largest part of the window, - * the latter to the one where the pointer is located. - */ - logical_monitor = - meta_monitor_manager_get_logical_monitor_at (monitor_manager, x, y); - if (!logical_monitor) - return; - - meta_window_get_work_area_for_monitor (window, - logical_monitor->number, - &work_area); - - /* Check if the cursor is in a position which triggers tiling - * and set tile_mode accordingly. - */ - if (meta_window_can_tile_side_by_side (window) && - x >= logical_monitor->rect.x && x < (work_area.x + shake_threshold)) - display->preview_tile_mode = META_TILE_LEFT; - else if (meta_window_can_tile_side_by_side (window) && - x >= work_area.x + work_area.width - shake_threshold && - x < (logical_monitor->rect.x + logical_monitor->rect.width)) - display->preview_tile_mode = META_TILE_RIGHT; - else if (meta_window_can_tile_maximized (window) && - y >= logical_monitor->rect.y && y <= work_area.y) - display->preview_tile_mode = META_TILE_MAXIMIZED; - else - display->preview_tile_mode = META_TILE_NONE; - - if (display->preview_tile_mode != META_TILE_NONE) - window->tile_monitor_number = logical_monitor->number; -} - -static void -update_move (MetaWindow *window, - MetaEdgeResistanceFlags flags, - int x, - int y) -{ - int dx, dy; - int new_x, new_y; - MetaRectangle old; - int shake_threshold; - MetaDisplay *display = window->display; - - display->grab_latest_motion_x = x; - display->grab_latest_motion_y = y; - - dx = x - display->grab_anchor_root_x; - dy = y - display->grab_anchor_root_y; - - new_x = display->grab_anchor_window_pos.x + dx; - new_y = display->grab_anchor_window_pos.y + dy; - - meta_verbose ("x,y = %d,%d anchor ptr %d,%d anchor pos %d,%d dx,dy %d,%d", - x, y, - display->grab_anchor_root_x, - display->grab_anchor_root_y, - display->grab_anchor_window_pos.x, - display->grab_anchor_window_pos.y, - dx, dy); - - /* Don't bother doing anything if no move has been specified. (This - * happens often, even in keyboard moving, due to the warping of the - * pointer. - */ - if (dx == 0 && dy == 0) - return; - - /* Originally for detaching maximized windows, but we use this - * for the zones at the sides of the monitor where trigger tiling - * because it's about the right size - */ -#define DRAG_THRESHOLD_TO_SHAKE_THRESHOLD_FACTOR 6 - shake_threshold = meta_prefs_get_drag_threshold () * - DRAG_THRESHOLD_TO_SHAKE_THRESHOLD_FACTOR; - - if (flags & META_EDGE_RESISTANCE_SNAP) - { - /* We don't want to tile while snapping. Also, clear any previous tile - request. */ - display->preview_tile_mode = META_TILE_NONE; - window->tile_monitor_number = -1; - } - else if (meta_prefs_get_edge_tiling () && - !META_WINDOW_MAXIMIZED (window) && - !META_WINDOW_TILED_SIDE_BY_SIDE (window)) - { - update_move_maybe_tile (window, shake_threshold, x, y); - } - - /* shake loose (unmaximize) maximized or tiled window if dragged beyond - * the threshold in the Y direction. Tiled windows can also be pulled - * loose via X motion. - */ - - if ((META_WINDOW_MAXIMIZED (window) && ABS (dy) >= shake_threshold) || - (META_WINDOW_TILED_SIDE_BY_SIDE (window) && (MAX (ABS (dx), ABS (dy)) >= shake_threshold))) - { - double prop; - - /* Shake loose, so that the window snaps back to maximized - * when dragged near the top; do not snap back if tiling - * is enabled, as top edge tiling can be used in that case - */ - window->shaken_loose = !meta_prefs_get_edge_tiling (); - window->tile_mode = META_TILE_NONE; - - /* move the unmaximized window to the cursor */ - prop = - ((double)(x - display->grab_initial_window_pos.x)) / - ((double)display->grab_initial_window_pos.width); - - display->grab_initial_window_pos.x = x - window->saved_rect.width * prop; - - /* If we started dragging the window from above the top of the window, - * pretend like we started dragging from the middle of the titlebar - * instead, as the "correct" anchoring looks wrong. */ - if (display->grab_anchor_root_y < display->grab_initial_window_pos.y) - { - MetaRectangle titlebar_rect; - meta_window_get_titlebar_rect (window, &titlebar_rect); - display->grab_anchor_root_y = display->grab_initial_window_pos.y + titlebar_rect.height / 2; - } - - window->saved_rect.x = display->grab_initial_window_pos.x; - window->saved_rect.y = display->grab_initial_window_pos.y; - - meta_window_unmaximize (window, META_MAXIMIZE_BOTH); - return; - } - - /* remaximize window on another monitor if window has been shaken - * loose or it is still maximized (then move straight) - */ - else if ((window->shaken_loose || META_WINDOW_MAXIMIZED (window)) && - window->tile_mode != META_TILE_LEFT && window->tile_mode != META_TILE_RIGHT) - { - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - int n_logical_monitors; - const MetaLogicalMonitor *wmonitor; - MetaRectangle work_area; - int monitor; - - window->tile_mode = META_TILE_NONE; - wmonitor = window->monitor; - n_logical_monitors = - meta_monitor_manager_get_num_logical_monitors (monitor_manager); - - for (monitor = 0; monitor < n_logical_monitors; monitor++) - { - meta_window_get_work_area_for_monitor (window, monitor, &work_area); - - /* check if cursor is near the top of a monitor work area */ - if (x >= work_area.x && - x < (work_area.x + work_area.width) && - y >= work_area.y && - y < (work_area.y + shake_threshold)) - { - /* move the saved rect if window will become maximized on an - * other monitor so user isn't surprised on a later unmaximize - */ - if (wmonitor->number != monitor) - { - window->saved_rect.x = work_area.x; - window->saved_rect.y = work_area.y; - - if (window->frame) - { - window->saved_rect.x += window->frame->child_x; - window->saved_rect.y += window->frame->child_y; - } - - window->unconstrained_rect.x = window->saved_rect.x; - window->unconstrained_rect.y = window->saved_rect.y; - - meta_window_unmaximize (window, META_MAXIMIZE_BOTH); - - display->grab_initial_window_pos = work_area; - display->grab_anchor_root_x = x; - display->grab_anchor_root_y = y; - window->shaken_loose = FALSE; - - meta_window_maximize (window, META_MAXIMIZE_BOTH); - } - - return; - } - } - } - - /* Delay showing the tile preview slightly to make it more unlikely to - * trigger it unwittingly, e.g. when shaking loose the window or moving - * it to another monitor. - */ - meta_display_update_tile_preview (window->display, - window->tile_mode != META_TILE_NONE); - - meta_window_get_frame_rect (window, &old); - - /* Don't allow movement in the maximized directions or while tiled */ - if (window->maximized_horizontally || META_WINDOW_TILED_SIDE_BY_SIDE (window)) - new_x = old.x; - if (window->maximized_vertically) - new_y = old.y; - - /* Do any edge resistance/snapping */ - meta_window_edge_resistance_for_move (window, - &new_x, - &new_y, - update_move_timeout, - flags); - - meta_window_move_frame (window, TRUE, new_x, new_y); -} - -static gboolean -update_resize_timeout (gpointer data) -{ - MetaWindow *window = data; - - update_resize (window, - window->display->grab_last_edge_resistance_flags, - window->display->grab_latest_motion_x, - window->display->grab_latest_motion_y, - TRUE); - return FALSE; -} - -static void -update_resize (MetaWindow *window, - MetaEdgeResistanceFlags flags, - int x, - int y, - gboolean force) -{ - int dx, dy; - MetaGravity gravity; - MetaRectangle new_rect; - MetaRectangle old_rect; - double remaining = 0; - - window->display->grab_latest_motion_x = x; - window->display->grab_latest_motion_y = y; - - dx = x - window->display->grab_anchor_root_x; - dy = y - window->display->grab_anchor_root_y; - - /* Attached modal dialogs are special in that size - * changes apply to both sides, so that the dialog - * remains centered to the parent. - */ - if (meta_window_is_attached_dialog (window)) - { - dx *= 2; - dy *= 2; - } - - new_rect.width = window->display->grab_anchor_window_pos.width; - new_rect.height = window->display->grab_anchor_window_pos.height; - - /* Don't bother doing anything if no move has been specified. (This - * happens often, even in keyboard resizing, due to the warping of the - * pointer. - */ - if (dx == 0 && dy == 0) - return; - - if (window->display->grab_op == META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN) - { - MetaGrabOp op = META_GRAB_OP_WINDOW_BASE | META_GRAB_OP_WINDOW_FLAG_KEYBOARD; - - if (dx > 0) - op |= META_GRAB_OP_WINDOW_DIR_EAST; - else if (dx < 0) - op |= META_GRAB_OP_WINDOW_DIR_WEST; - - if (dy > 0) - op |= META_GRAB_OP_WINDOW_DIR_SOUTH; - else if (dy < 0) - op |= META_GRAB_OP_WINDOW_DIR_NORTH; - - window->display->grab_op = op; - - meta_window_update_keyboard_resize (window, TRUE); - } - - if (window->display->grab_op & META_GRAB_OP_WINDOW_DIR_EAST) - new_rect.width += dx; - else if (window->display->grab_op & META_GRAB_OP_WINDOW_DIR_WEST) - new_rect.width -= dx; - - if (window->display->grab_op & META_GRAB_OP_WINDOW_DIR_SOUTH) - new_rect.height += dy; - else if (window->display->grab_op & META_GRAB_OP_WINDOW_DIR_NORTH) - new_rect.height -= dy; - - meta_window_maybe_apply_size_hints (window, &new_rect); - - /* If we're waiting for a request for _NET_WM_SYNC_REQUEST, we'll - * resize the window when the window responds, or when we time - * the response out. - */ - if (window->sync_request_timeout_id != 0) - return; - - if (!check_moveresize_frequency (window, &remaining) && !force) - { - /* we are ignoring an event here, so we schedule a - * compensation event when we would otherwise not ignore - * an event. Otherwise we can become stuck if the user never - * generates another event. - */ - if (!window->display->grab_resize_timeout_id) - { - window->display->grab_resize_timeout_id = - g_timeout_add ((int)remaining, update_resize_timeout, window); - g_source_set_name_by_id (window->display->grab_resize_timeout_id, - "[mutter] update_resize_timeout"); - } - - return; - } - - /* Remove any scheduled compensation events */ - g_clear_handle_id (&window->display->grab_resize_timeout_id, g_source_remove); - - meta_window_get_frame_rect (window, &old_rect); - - /* One sided resizing ought to actually be one-sided, despite the fact that - * aspect ratio windows don't interact nicely with the above stuff. So, - * to avoid some nasty flicker, we enforce that. - */ - - if ((window->display->grab_op & (META_GRAB_OP_WINDOW_DIR_WEST | META_GRAB_OP_WINDOW_DIR_EAST)) == 0) - new_rect.width = old_rect.width; - - if ((window->display->grab_op & (META_GRAB_OP_WINDOW_DIR_NORTH | META_GRAB_OP_WINDOW_DIR_SOUTH)) == 0) - new_rect.height = old_rect.height; - - /* compute gravity of client during operation */ - gravity = meta_resize_gravity_from_grab_op (window->display->grab_op); - g_assert (gravity >= 0); - - /* Do any edge resistance/snapping */ - meta_window_edge_resistance_for_resize (window, - &new_rect.width, - &new_rect.height, - gravity, - update_resize_timeout, - flags); - - meta_window_resize_frame_with_gravity (window, TRUE, - new_rect.width, new_rect.height, - gravity); - - /* Store the latest resize time, if we actually resized. */ - if (window->rect.width != old_rect.width || - window->rect.height != old_rect.height) - window->display->grab_last_moveresize_time = g_get_real_time (); -} - -static void -maybe_maximize_tiled_window (MetaWindow *window) -{ - MetaRectangle work_area; - gint shake_threshold; - - if (!META_WINDOW_TILED_SIDE_BY_SIDE (window)) - return; - - shake_threshold = meta_prefs_get_drag_threshold (); - - meta_window_get_work_area_for_monitor (window, - window->tile_monitor_number, - &work_area); - if (window->rect.width >= work_area.width - shake_threshold) - meta_window_maximize (window, META_MAXIMIZE_BOTH); -} - -void -meta_window_update_resize (MetaWindow *window, - MetaEdgeResistanceFlags flags, - int x, int y, - gboolean force) -{ - update_resize (window, flags, x, y, force); -} - -static void -end_grab_op (MetaWindow *window, - const ClutterEvent *event) -{ - ClutterModifierType modifiers; - MetaEdgeResistanceFlags last_flags; - gfloat x, y; - - clutter_event_get_coords (event, &x, &y); - modifiers = clutter_event_get_state (event); - meta_display_check_threshold_reached (window->display, x, y); - - /* If the user was snap moving then ignore the button - * release because they may have let go of shift before - * releasing the mouse button and they almost certainly do - * not want a non-snapped movement to occur from the button - * release. - */ - last_flags = window->display->grab_last_edge_resistance_flags; - if ((last_flags & META_EDGE_RESISTANCE_SNAP) == 0) - { - MetaEdgeResistanceFlags flags = META_EDGE_RESISTANCE_DEFAULT; - - if (modifiers & CLUTTER_SHIFT_MASK) - flags |= META_EDGE_RESISTANCE_SNAP; - - if (modifiers & CLUTTER_CONTROL_MASK) - flags |= META_EDGE_RESISTANCE_WINDOWS; - - if (meta_grab_op_is_moving (window->display->grab_op)) - { - if (window->display->preview_tile_mode != META_TILE_NONE) - meta_window_tile (window, window->display->preview_tile_mode); - else - update_move (window, flags, x, y); - } - else if (meta_grab_op_is_resizing (window->display->grab_op)) - { - if (window->tile_match != NULL) - flags |= (META_EDGE_RESISTANCE_SNAP | META_EDGE_RESISTANCE_WINDOWS); - - update_resize (window, flags, x, y, TRUE); - maybe_maximize_tiled_window (window); - } - } - window->display->preview_tile_mode = META_TILE_NONE; - meta_display_end_grab_op (window->display, clutter_event_get_time (event)); -} - -gboolean -meta_window_handle_mouse_grab_op_event (MetaWindow *window, - const ClutterEvent *event) -{ - ClutterEventSequence *sequence = clutter_event_get_event_sequence (event); - ClutterModifierType modifier_state; - MetaEdgeResistanceFlags flags; - gfloat x, y; - - switch (event->type) - { - case CLUTTER_TOUCH_BEGIN: - if (!meta_display_is_pointer_emulating_sequence (window->display, sequence)) - return FALSE; - - return TRUE; - - case CLUTTER_BUTTON_PRESS: - { - ClutterModifierType grab_mods = meta_display_get_compositor_modifiers (window->display); - - /* This is the keybinding or menu case where we've - * been dragging around the window without the button - * pressed. */ - - if ((meta_grab_op_is_mouse (window->display->grab_op) && - (event->button.modifier_state & grab_mods) == grab_mods && - window->display->grab_button != (int) event->button.button) || - meta_grab_op_is_keyboard (window->display->grab_op)) - { - end_grab_op (window, event); - return FALSE; - } - return TRUE; - } - - case CLUTTER_TOUCH_END: - if (!meta_display_is_pointer_emulating_sequence (window->display, sequence)) - return FALSE; - - end_grab_op (window, event); - return TRUE; - - case CLUTTER_BUTTON_RELEASE: - if (event->button.button == 1 || - event->button.button == (unsigned int) meta_prefs_get_mouse_button_resize ()) - end_grab_op (window, event); - - return TRUE; - - case CLUTTER_TOUCH_UPDATE: - if (!meta_display_is_pointer_emulating_sequence (window->display, sequence)) - return FALSE; - - /* Fall through */ - case CLUTTER_MOTION: - modifier_state = clutter_event_get_state (event); - clutter_event_get_coords (event, &x, &y); - flags = META_EDGE_RESISTANCE_DEFAULT; - - if (modifier_state & CLUTTER_SHIFT_MASK) - flags |= META_EDGE_RESISTANCE_SNAP; - - if (modifier_state & CLUTTER_CONTROL_MASK) - flags |= META_EDGE_RESISTANCE_WINDOWS; - - meta_display_check_threshold_reached (window->display, x, y); - if (meta_grab_op_is_moving (window->display->grab_op)) - { - update_move (window, flags, x, y); - } - else if (meta_grab_op_is_resizing (window->display->grab_op)) - { - if (window->tile_match != NULL) - flags |= (META_EDGE_RESISTANCE_SNAP | META_EDGE_RESISTANCE_WINDOWS); - - update_resize (window, flags, x, y, FALSE); - } - return TRUE; - - case CLUTTER_TOUCH_CANCEL: - end_grab_op (window, event); - return FALSE; - - default: - return FALSE; - } -} - -void -meta_window_get_work_area_for_logical_monitor (MetaWindow *window, - MetaLogicalMonitor *logical_monitor, - MetaRectangle *area) -{ - GList *tmp; - - g_assert (logical_monitor); - - /* Initialize to the whole monitor */ - *area = logical_monitor->rect; - - tmp = meta_window_get_workspaces (window); - while (tmp != NULL) - { - MetaRectangle workspace_work_area; - meta_workspace_get_work_area_for_logical_monitor (tmp->data, - logical_monitor, - &workspace_work_area); - meta_rectangle_intersect (area, - &workspace_work_area, - area); - tmp = tmp->next; - } - - meta_topic (META_DEBUG_WORKAREA, - "Window %s monitor %d has work area %d,%d %d x %d", - window->desc, logical_monitor->number, - area->x, area->y, area->width, area->height); -} - -/** - * meta_window_get_work_area_current_monitor: - * @window: a #MetaWindow - * @area: (out): a location to store the work area - * - * Get the work area for the monitor @window is currently on. - */ -void -meta_window_get_work_area_current_monitor (MetaWindow *window, - MetaRectangle *area) -{ - meta_window_get_work_area_for_monitor (window, - window->monitor->number, - area); -} - -/** - * meta_window_get_work_area_for_monitor: - * @window: a #MetaWindow - * @which_monitor: a moniotr to get the work area for - * @area: (out): a location to store the work area - * - * Get the work area for @window, given the monitor index - * @which_monitor. - */ -void -meta_window_get_work_area_for_monitor (MetaWindow *window, - int which_monitor, - MetaRectangle *area) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = meta_backend_get_monitor_manager (backend); - MetaLogicalMonitor *logical_monitor; - - g_return_if_fail (which_monitor >= 0); - - logical_monitor = - meta_monitor_manager_get_logical_monitor_from_number (monitor_manager, - which_monitor); - - meta_window_get_work_area_for_logical_monitor (window, logical_monitor, area); -} - -/** - * meta_window_get_work_area_all_monitors: - * @window: a #MetaWindow - * @area: (out): a location to store the work area - * - * Get the work area for all monitors for @window. - */ -void -meta_window_get_work_area_all_monitors (MetaWindow *window, - MetaRectangle *area) -{ - GList *tmp; - MetaRectangle display_rect = { 0 }; - - meta_display_get_size (window->display, - &display_rect.width, - &display_rect.height); - - /* Initialize to the whole display */ - *area = display_rect; - - tmp = meta_window_get_workspaces (window); - while (tmp != NULL) - { - MetaRectangle workspace_work_area; - meta_workspace_get_work_area_all_monitors (tmp->data, - &workspace_work_area); - meta_rectangle_intersect (area, - &workspace_work_area, - area); - tmp = tmp->next; - } - - meta_topic (META_DEBUG_WORKAREA, - "Window %s has whole-screen work area %d,%d %d x %d", - window->desc, area->x, area->y, area->width, area->height); -} - -int -meta_window_get_current_tile_monitor_number (MetaWindow *window) -{ - int tile_monitor_number = window->tile_monitor_number; - - if (tile_monitor_number < 0) - { - meta_warning ("%s called with an invalid monitor number; using 0 instead", G_STRFUNC); - tile_monitor_number = 0; - } - - return tile_monitor_number; -} - -void -meta_window_get_tile_area (MetaWindow *window, - MetaTileMode tile_mode, - MetaRectangle *tile_area) -{ - MetaRectangle work_area; - int tile_monitor_number; - double fraction; - - g_return_if_fail (tile_mode != META_TILE_NONE); - - tile_monitor_number = meta_window_get_current_tile_monitor_number (window); - - meta_window_get_work_area_for_monitor (window, tile_monitor_number, &work_area); - meta_window_get_tile_fraction (window, tile_mode, &fraction); - - *tile_area = work_area; - tile_area->width = round (tile_area->width * fraction); - - if (tile_mode == META_TILE_RIGHT) - tile_area->x += work_area.width - tile_area->width; -} - -gboolean -meta_window_same_application (MetaWindow *window, - MetaWindow *other_window) -{ - MetaGroup *group = meta_window_get_group (window); - MetaGroup *other_group = meta_window_get_group (other_window); - - return - group!=NULL && - other_group!=NULL && - group==other_group; -} - -/** - * meta_window_is_client_decorated: - * - * Check if if the window has decorations drawn by the client. - * (window->decorated refers only to whether we should add decorations) - */ -gboolean -meta_window_is_client_decorated (MetaWindow *window) -{ - if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND) - { - /* Assume all Wayland clients draw decorations - not strictly - * true but good enough for current purposes. - */ - return TRUE; - } - else - { - /* Currently the implementation here is hackish - - * has_custom_frame_extents() is set if _GTK_FRAME_EXTENTS is set - * to any value even 0. GTK+ always sets _GTK_FRAME_EXTENTS for - * client-side-decorated window, even if the value is 0 because - * the window is maxized and has no invisible borders or shadows. - */ - return window->has_custom_frame_extents; - } -} - -/** - * meta_window_foreach_transient: - * @window: a #MetaWindow - * @func: (scope call) (closure user_data): Called for each window which is a transient of @window (transitively) - * @user_data: User data - * - * Call @func for every window which is either transient for @window, or is - * a transient of a window which is in turn transient for @window. - * The order of window enumeration is not defined. - * - * Iteration will stop if @func at any point returns %FALSE. - */ -void -meta_window_foreach_transient (MetaWindow *window, - MetaWindowForeachFunc func, - void *user_data) -{ - GSList *windows; - GSList *tmp; - - windows = meta_display_list_windows (window->display, META_LIST_DEFAULT); - - tmp = windows; - while (tmp != NULL) - { - MetaWindow *transient = tmp->data; - - if (meta_window_is_ancestor_of_transient (window, transient)) - { - if (!(* func) (transient, user_data)) - break; - } - - tmp = tmp->next; - } - - g_slist_free (windows); -} - -/** - * meta_window_foreach_ancestor: - * @window: a #MetaWindow - * @func: (scope call) (closure user_data): Called for each window which is a transient parent of @window - * @user_data: User data - * - * If @window is transient, call @func with the window for which it's transient, - * repeatedly until either we find a non-transient window, or @func returns %FALSE. - */ -void -meta_window_foreach_ancestor (MetaWindow *window, - MetaWindowForeachFunc func, - void *user_data) -{ - MetaWindow *w; - - w = window; - do - { - if (w->transient_for == NULL) - break; - - w = w->transient_for; - } - while (w && (* func) (w, user_data)); -} - -typedef struct -{ - MetaWindow *ancestor; - gboolean found; -} FindAncestorData; - -static gboolean -find_ancestor_func (MetaWindow *window, - void *data) -{ - FindAncestorData *d = data; - - if (window == d->ancestor) - { - d->found = TRUE; - return FALSE; - } - - return TRUE; -} - -/** - * meta_window_is_ancestor_of_transient: - * @window: a #MetaWindow - * @transient: a #MetaWindow - * - * The function determines whether @window is an ancestor of @transient; it does - * so by traversing the @transient's ancestors until it either locates @window - * or reaches an ancestor that is not transient. - * - * Return Value: %TRUE if window is an ancestor of transient. - */ -gboolean -meta_window_is_ancestor_of_transient (MetaWindow *window, - MetaWindow *transient) -{ - FindAncestorData d; - - d.ancestor = window; - d.found = FALSE; - - meta_window_foreach_ancestor (transient, find_ancestor_func, &d); - - return d.found; -} - -/* Warp pointer to location appropriate for grab, - * return root coordinates where pointer ended up. - */ -static gboolean -warp_grab_pointer (MetaWindow *window, - MetaGrabOp grab_op, - int *x, - int *y) -{ - MetaRectangle rect; - MetaRectangle display_rect = { 0 }; - MetaDisplay *display; - ClutterSeat *seat; - - display = window->display; - meta_display_get_size (display, - &display_rect.width, - &display_rect.height); - - /* We may not have done begin_grab_op yet, i.e. may not be in a grab - */ - - meta_window_get_frame_rect (window, &rect); - - if (grab_op & META_GRAB_OP_WINDOW_DIR_WEST) - *x = 0; - else if (grab_op & META_GRAB_OP_WINDOW_DIR_EAST) - *x = rect.width - 1; - else - *x = rect.width / 2; - - if (grab_op & META_GRAB_OP_WINDOW_DIR_NORTH) - *y = 0; - else if (grab_op & META_GRAB_OP_WINDOW_DIR_SOUTH) - *y = rect.height - 1; - else - *y = rect.height / 2; - - *x += rect.x; - *y += rect.y; - - /* Avoid weird bouncing at the screen edge; see bug 154706 */ - *x = CLAMP (*x, 0, display_rect.width - 1); - *y = CLAMP (*y, 0, display_rect.height - 1); - - meta_topic (META_DEBUG_WINDOW_OPS, - "Warping pointer to %d,%d with window at %d,%d", - *x, *y, rect.x, rect.y); - - /* Need to update the grab positions so that the MotionNotify and other - * events generated by the XWarpPointer() call below don't cause complete - * funkiness. See bug 124582 and bug 122670. - */ - display->grab_anchor_root_x = *x; - display->grab_anchor_root_y = *y; - display->grab_latest_motion_x = *x; - display->grab_latest_motion_y = *y; - meta_window_get_frame_rect (window, - &display->grab_anchor_window_pos); - - seat = clutter_backend_get_default_seat (clutter_get_default_backend ()); - clutter_seat_warp_pointer (seat, *x, *y); - - return TRUE; -} - -void -meta_window_begin_grab_op (MetaWindow *window, - MetaGrabOp op, - gboolean frame_action, - guint32 timestamp) -{ - int x, y; - - warp_grab_pointer (window, - op, &x, &y); - - meta_display_begin_grab_op (window->display, - window, - op, - FALSE, - frame_action, - 0 /* button */, - 0, - timestamp, - x, y); -} - -void -meta_window_update_keyboard_resize (MetaWindow *window, - gboolean update_cursor) -{ - int x, y; - - warp_grab_pointer (window, - window->display->grab_op, - &x, &y); - - if (update_cursor) - meta_display_update_cursor (window->display); -} - -void -meta_window_update_keyboard_move (MetaWindow *window) -{ - int x, y; - - warp_grab_pointer (window, - window->display->grab_op, - &x, &y); -} - -MetaStackLayer -meta_window_get_default_layer (MetaWindow *window) -{ - if (window->wm_state_below) - return META_LAYER_BOTTOM; - else if (window->wm_state_above && !META_WINDOW_MAXIMIZED (window)) - return META_LAYER_TOP; - else - return META_LAYER_NORMAL; -} - -void -meta_window_update_layer (MetaWindow *window) -{ - MetaGroup *group; - - meta_stack_freeze (window->display->stack); - group = meta_window_get_group (window); - if (group) - meta_group_update_layers (group); - else - meta_stack_update_layer (window->display->stack, window); - meta_stack_thaw (window->display->stack); -} - -/* ensure_mru_position_after ensures that window appears after - * below_this_one in the active_workspace's mru_list (i.e. it treats - * window as having been less recently used than below_this_one) - */ -static void -ensure_mru_position_after (MetaWindow *window, - MetaWindow *after_this_one) -{ - /* This is sort of slow since it runs through the entire list more - * than once (especially considering the fact that we expect the - * windows of interest to be the first two elements in the list), - * but it doesn't matter while we're only using it on new window - * map. - */ - - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - GList* active_mru_list; - GList* window_position; - GList* after_this_one_position; - - active_mru_list = workspace_manager->active_workspace->mru_list; - window_position = g_list_find (active_mru_list, window); - after_this_one_position = g_list_find (active_mru_list, after_this_one); - - /* after_this_one_position is NULL when we switch workspaces, but in - * that case we don't need to do any MRU shuffling so we can simply - * return. - */ - if (after_this_one_position == NULL) - return; - - if (g_list_length (window_position) > g_list_length (after_this_one_position)) - { - workspace_manager->active_workspace->mru_list = - g_list_delete_link (workspace_manager->active_workspace->mru_list, - window_position); - - workspace_manager->active_workspace->mru_list = - g_list_insert_before (workspace_manager->active_workspace->mru_list, - after_this_one_position->next, - window); - } -} - -gboolean -meta_window_is_in_stack (MetaWindow *window) -{ - return window->stack_position >= 0; -} - -void -meta_window_stack_just_below (MetaWindow *window, - MetaWindow *below_this_one) -{ - g_return_if_fail (window != NULL); - g_return_if_fail (below_this_one != NULL); - - if (window->stack_position > below_this_one->stack_position) - { - meta_topic (META_DEBUG_STACK, - "Setting stack position of window %s to %d (making it below window %s).", - window->desc, - below_this_one->stack_position, - below_this_one->desc); - meta_window_set_stack_position (window, below_this_one->stack_position); - } - else - { - meta_topic (META_DEBUG_STACK, - "Window %s was already below window %s.", - window->desc, below_this_one->desc); - } -} - -void -meta_window_stack_just_above (MetaWindow *window, - MetaWindow *above_this_one) -{ - g_return_if_fail (window != NULL); - g_return_if_fail (above_this_one != NULL); - - if (window->stack_position < above_this_one->stack_position) - { - meta_topic (META_DEBUG_STACK, - "Setting stack position of window %s to %d (making it above window %s).", - window->desc, - above_this_one->stack_position, - above_this_one->desc); - meta_window_set_stack_position (window, above_this_one->stack_position); - } - else - { - meta_topic (META_DEBUG_STACK, - "Window %s was already above window %s.", - window->desc, above_this_one->desc); - } -} - -/** - * meta_window_get_user_time: - * @window: a #MetaWindow - * - * The user time represents a timestamp for the last time the user - * interacted with this window. Note this property is only available - * for non-override-redirect windows. - * - * The property is set by Mutter initially upon window creation, - * and updated thereafter on input events (key and button presses) seen by Mutter, - * client updates to the _NET_WM_USER_TIME property (if later than the current time) - * and when focusing the window. - * - * Returns: The last time the user interacted with this window. - */ -guint32 -meta_window_get_user_time (MetaWindow *window) -{ - return window->net_wm_user_time; -} - -void -meta_window_set_user_time (MetaWindow *window, - guint32 timestamp) -{ - /* FIXME: If Soeren's suggestion in bug 151984 is implemented, it will allow - * us to sanity check the timestamp here and ensure it doesn't correspond to - * a future time. - */ - - g_return_if_fail (!window->override_redirect); - - /* Only update the time if this timestamp is newer... */ - if (window->net_wm_user_time_set && - XSERVER_TIME_IS_BEFORE (timestamp, window->net_wm_user_time)) - { - meta_topic (META_DEBUG_STARTUP, - "Window %s _NET_WM_USER_TIME not updated to %u, because it " - "is less than %u", - window->desc, timestamp, window->net_wm_user_time); - } - else - { - meta_topic (META_DEBUG_STARTUP, - "Window %s has _NET_WM_USER_TIME of %u", - window->desc, timestamp); - window->net_wm_user_time_set = TRUE; - window->net_wm_user_time = timestamp; - if (XSERVER_TIME_IS_BEFORE (window->display->last_user_time, timestamp)) - window->display->last_user_time = timestamp; - - /* If this is a terminal, user interaction with it means the user likely - * doesn't want to have focus transferred for now due to new windows. - */ - if (meta_prefs_get_focus_new_windows () == G_DESKTOP_FOCUS_NEW_WINDOWS_STRICT && - window_is_terminal (window)) - window->display->allow_terminal_deactivation = FALSE; - - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_USER_TIME]); - } -} - -/** - * meta_window_get_stable_sequence: - * @window: A #MetaWindow - * - * The stable sequence number is a monotonicially increasing - * unique integer assigned to each #MetaWindow upon creation. - * - * This number can be useful for sorting windows in a stable - * fashion. - * - * Returns: Internal sequence number for this window - */ -guint32 -meta_window_get_stable_sequence (MetaWindow *window) -{ - g_return_val_if_fail (META_IS_WINDOW (window), 0); - - return window->stable_sequence; -} - -/* Sets the demands_attention hint on a window, but only - * if it's at least partially obscured (see #305882). - */ -void -meta_window_set_demands_attention (MetaWindow *window) -{ - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - MetaRectangle candidate_rect, other_rect; - GList *stack = window->display->stack->sorted; - MetaWindow *other_window; - gboolean obscured = FALSE; - - MetaWorkspace *workspace = workspace_manager->active_workspace; - - if (window->wm_state_demands_attention) - return; - - if (!meta_window_located_on_workspace (window, workspace)) - { - /* windows on other workspaces are necessarily obscured */ - obscured = TRUE; - } - else if (window->minimized) - { - obscured = TRUE; - } - else - { - meta_window_get_frame_rect (window, &candidate_rect); - - /* The stack is sorted with the top windows first. */ - - while (stack != NULL && stack->data != window) - { - other_window = stack->data; - stack = stack->next; - - if (meta_window_located_on_workspace (other_window, workspace)) - { - meta_window_get_frame_rect (other_window, &other_rect); - - if (meta_rectangle_overlap (&candidate_rect, &other_rect)) - { - obscured = TRUE; - break; - } - } - } - } - - if (obscured) - { - meta_topic (META_DEBUG_WINDOW_OPS, - "Marking %s as needing attention", - window->desc); - - window->wm_state_demands_attention = TRUE; - set_net_wm_state (window); - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_DEMANDS_ATTENTION]); - g_signal_emit_by_name (window->display, "window-demands-attention", - window); - } - else - { - /* If the window's in full view, there's no point setting the flag. */ - - meta_topic (META_DEBUG_WINDOW_OPS, - "Not marking %s as needing attention because " - "it's in full view", - window->desc); - } -} - -void -meta_window_unset_demands_attention (MetaWindow *window) -{ - meta_topic (META_DEBUG_WINDOW_OPS, - "Marking %s as not needing attention", window->desc); - - if (window->wm_state_demands_attention) - { - window->wm_state_demands_attention = FALSE; - set_net_wm_state (window); - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_DEMANDS_ATTENTION]); - } -} - -/** - * meta_window_get_frame: (skip) - * @window: a #MetaWindow - * - */ -MetaFrame * -meta_window_get_frame (MetaWindow *window) -{ - return window->frame; -} - -/** - * meta_window_appears_focused: - * @window: a #MetaWindow - * - * Determines if the window should be drawn with a focused appearance. This is - * true for focused windows but also true for windows with a focused modal - * dialog attached. - * - * Return value: %TRUE if the window should be drawn with a focused frame - */ -gboolean -meta_window_appears_focused (MetaWindow *window) -{ - return window->has_focus || (window->attached_focus_window != NULL); -} - -gboolean -meta_window_has_focus (MetaWindow *window) -{ - return window->has_focus; -} - -gboolean -meta_window_is_shaded (MetaWindow *window) -{ - return window->shaded; -} - -/** - * meta_window_is_override_redirect: - * @window: A #MetaWindow - * - * Returns: %TRUE if this window isn't managed by mutter; it will - * control its own positioning and mutter won't draw decorations - * among other things. In X terminology this is "override redirect". - */ -gboolean -meta_window_is_override_redirect (MetaWindow *window) -{ - return window->override_redirect; -} - -/** - * meta_window_is_skip_taskbar: - * @window: A #MetaWindow - * - * Gets whether this window should be ignored by task lists. - * - * Return value: %TRUE if the skip bar hint is set. - */ -gboolean -meta_window_is_skip_taskbar (MetaWindow *window) -{ - g_return_val_if_fail (META_IS_WINDOW (window), FALSE); - - return window->skip_taskbar; -} - -/** - * meta_window_get_display: - * @window: A #MetaWindow - * - * Returns: (transfer none): The display for @window - */ -MetaDisplay * -meta_window_get_display (MetaWindow *window) -{ - return window->display; -} - -/** - * meta_window_get_xwindow: (skip) - * @window: a #MetaWindow - * - */ -Window -meta_window_get_xwindow (MetaWindow *window) -{ - return window->xwindow; -} - -MetaWindowType -meta_window_get_window_type (MetaWindow *window) -{ - return window->type; -} - -/** - * meta_window_get_workspace: - * @window: a #MetaWindow - * - * Gets the #MetaWorkspace that the window is currently displayed on. - * If the window is on all workspaces, returns the currently active - * workspace. - * - * Return value: (transfer none): the #MetaWorkspace for the window - */ -MetaWorkspace * -meta_window_get_workspace (MetaWindow *window) -{ - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - - if (window->on_all_workspaces) - return workspace_manager->active_workspace; - else - return window->workspace; -} - -gboolean -meta_window_is_on_all_workspaces (MetaWindow *window) -{ - return window->on_all_workspaces; -} - -gboolean -meta_window_is_hidden (MetaWindow *window) -{ - return window->hidden; -} - -const char * -meta_window_get_description (MetaWindow *window) -{ - if (!window) - return NULL; - - return window->desc; -} - -/** - * meta_window_get_wm_class: - * @window: a #MetaWindow - * - * Return the current value of the name part of WM_CLASS X property. - */ -const char * -meta_window_get_wm_class (MetaWindow *window) -{ - if (!window) - return NULL; - - return window->res_class; -} - -/** - * meta_window_get_wm_class_instance: - * @window: a #MetaWindow - * - * Return the current value of the instance part of WM_CLASS X property. - */ -const char * -meta_window_get_wm_class_instance (MetaWindow *window) -{ - if (!window) - return NULL; - - return window->res_name; -} - -/** - * meta_window_get_sandboxed_app_id: - * @window: a #MetaWindow - * - * Gets an unique id for a sandboxed app (currently flatpaks and snaps are - * supported). - * - * Return value: (transfer none): the sandboxed application ID or %NULL - **/ -const char * -meta_window_get_sandboxed_app_id (MetaWindow *window) -{ - /* We're abusing this API here not to break the gnome shell assumptions - * or adding a new function, to be renamed to generic names in new versions */ - return window->sandboxed_app_id; -} - -/** - * meta_window_get_gtk_theme_variant: - * @window: a #MetaWindow - * - * Return value: (transfer none): the theme variant or %NULL - **/ -const char * -meta_window_get_gtk_theme_variant (MetaWindow *window) -{ - return window->gtk_theme_variant; -} - -/** - * meta_window_get_gtk_application_id: - * @window: a #MetaWindow - * - * Return value: (transfer none): the application ID - **/ -const char * -meta_window_get_gtk_application_id (MetaWindow *window) -{ - return window->gtk_application_id; -} - -/** - * meta_window_get_gtk_unique_bus_name: - * @window: a #MetaWindow - * - * Return value: (transfer none): the unique name - **/ -const char * -meta_window_get_gtk_unique_bus_name (MetaWindow *window) -{ - return window->gtk_unique_bus_name; -} - -/** - * meta_window_get_gtk_application_object_path: - * @window: a #MetaWindow - * - * Return value: (transfer none): the object path - **/ -const char * -meta_window_get_gtk_application_object_path (MetaWindow *window) -{ - return window->gtk_application_object_path; -} - -/** - * meta_window_get_gtk_window_object_path: - * @window: a #MetaWindow - * - * Return value: (transfer none): the object path - **/ -const char * -meta_window_get_gtk_window_object_path (MetaWindow *window) -{ - return window->gtk_window_object_path; -} - -/** - * meta_window_get_gtk_app_menu_object_path: - * @window: a #MetaWindow - * - * Return value: (transfer none): the object path - **/ -const char * -meta_window_get_gtk_app_menu_object_path (MetaWindow *window) -{ - return window->gtk_app_menu_object_path; -} - -/** - * meta_window_get_gtk_menubar_object_path: - * @window: a #MetaWindow - * - * Return value: (transfer none): the object path - **/ -const char * -meta_window_get_gtk_menubar_object_path (MetaWindow *window) -{ - return window->gtk_menubar_object_path; -} - -/** - * meta_window_get_compositor_private: - * @window: a #MetaWindow - * - * Gets the compositor's wrapper object for @window. - * - * Return value: (transfer none): the wrapper object. - **/ -GObject * -meta_window_get_compositor_private (MetaWindow *window) -{ - if (!window) - return NULL; - return window->compositor_private; -} - -void -meta_window_set_compositor_private (MetaWindow *window, GObject *priv) -{ - if (!window) - return; - window->compositor_private = priv; -} - -const char * -meta_window_get_role (MetaWindow *window) -{ - if (!window) - return NULL; - - return window->role; -} - -/** - * meta_window_get_title: - * @window: a #MetaWindow - * - * Returns: the current title of the window. - */ -const char * -meta_window_get_title (MetaWindow *window) -{ - g_return_val_if_fail (META_IS_WINDOW (window), NULL); - - return window->title; -} - -MetaStackLayer -meta_window_get_layer (MetaWindow *window) -{ - return window->layer; -} - -/** - * meta_window_get_transient_for: - * @window: a #MetaWindow - * - * Returns the #MetaWindow for the window that is pointed to by the - * WM_TRANSIENT_FOR hint on this window (see XGetTransientForHint() - * or XSetTransientForHint()). Metacity keeps transient windows above their - * parents. A typical usage of this hint is for a dialog that wants to stay - * above its associated window. - * - * Return value: (transfer none): the window this window is transient for, or - * %NULL if the WM_TRANSIENT_FOR hint is unset or does not point to a toplevel - * window that Metacity knows about. - */ -MetaWindow * -meta_window_get_transient_for (MetaWindow *window) -{ - g_return_val_if_fail (META_IS_WINDOW (window), NULL); - - if (window->transient_for) - return window->transient_for; - else if (window->xtransient_for) - return meta_x11_display_lookup_x_window (window->display->x11_display, - window->xtransient_for); - else - return NULL; -} - -/** - * meta_window_get_pid: - * @window: a #MetaWindow - * - * Returns the pid of the process that created this window, if available - * to the windowing system. - * - * Note that the value returned by this is vulnerable to spoofing attacks - * by the client. - * - * Return value: the pid, or 0 if not known. - */ -pid_t -meta_window_get_pid (MetaWindow *window) -{ - g_return_val_if_fail (META_IS_WINDOW (window), 0); - - if (window->client_pid == 0) - window->client_pid = META_WINDOW_GET_CLASS (window)->get_client_pid (window); - - return window->client_pid; -} - -/** - * meta_window_get_client_machine: - * @window: a #MetaWindow - * - * Returns name of the client machine from which this windows was created, - * if known (obtained from the WM_CLIENT_MACHINE property). - * - * Return value: (transfer none): the machine name, or NULL; the string is - * owned by the window manager and should not be freed or modified by the - * caller. - */ -const char * -meta_window_get_client_machine (MetaWindow *window) -{ - g_return_val_if_fail (META_IS_WINDOW (window), NULL); - - return window->wm_client_machine; -} - -/** - * meta_window_is_remote: - * @window: a #MetaWindow - * - * Returns: %TRUE if this window originates from a host - * different from the one running mutter. - */ -gboolean -meta_window_is_remote (MetaWindow *window) -{ - return window->is_remote; -} - -/** - * meta_window_get_mutter_hints: - * @window: a #MetaWindow - * - * Gets the current value of the _MUTTER_HINTS property. - * - * The purpose of the hints is to allow fine-tuning of the Window Manager and - * Compositor behaviour on per-window basis, and is intended primarily for - * hints that are plugin-specific. - * - * The property is a list of colon-separated key=value pairs. The key names for - * any plugin-specific hints must be suitably namespaced to allow for shared - * use; 'mutter-' key prefix is reserved for internal use, and must not be used - * by plugins. - * - * Return value: (transfer none): the _MUTTER_HINTS string, or %NULL if no hints - * are set. - */ -const char * -meta_window_get_mutter_hints (MetaWindow *window) -{ - g_return_val_if_fail (META_IS_WINDOW (window), NULL); - - return window->mutter_hints; -} - -/** - * meta_window_get_frame_type: - * @window: a #MetaWindow - * - * Gets the type of window decorations that should be used for this window. - * - * Return value: the frame type - */ -MetaFrameType -meta_window_get_frame_type (MetaWindow *window) -{ - MetaFrameType base_type = META_FRAME_TYPE_LAST; - - switch (window->type) - { - case META_WINDOW_NORMAL: - base_type = META_FRAME_TYPE_NORMAL; - break; - - case META_WINDOW_DIALOG: - base_type = META_FRAME_TYPE_DIALOG; - break; - - case META_WINDOW_MODAL_DIALOG: - if (meta_window_is_attached_dialog (window)) - base_type = META_FRAME_TYPE_ATTACHED; - else - base_type = META_FRAME_TYPE_MODAL_DIALOG; - break; - - case META_WINDOW_MENU: - base_type = META_FRAME_TYPE_MENU; - break; - - case META_WINDOW_UTILITY: - base_type = META_FRAME_TYPE_UTILITY; - break; - - case META_WINDOW_DESKTOP: - case META_WINDOW_DOCK: - case META_WINDOW_TOOLBAR: - case META_WINDOW_SPLASHSCREEN: - case META_WINDOW_DROPDOWN_MENU: - case META_WINDOW_POPUP_MENU: - case META_WINDOW_TOOLTIP: - case META_WINDOW_NOTIFICATION: - case META_WINDOW_COMBO: - case META_WINDOW_DND: - case META_WINDOW_OVERRIDE_OTHER: - /* No frame */ - base_type = META_FRAME_TYPE_LAST; - break; - } - - if (base_type == META_FRAME_TYPE_LAST) - { - /* can't add border if undecorated */ - return META_FRAME_TYPE_LAST; - } - else if (window->border_only) - { - /* override base frame type */ - return META_FRAME_TYPE_BORDER; - } - else - { - return base_type; - } -} - -/** - * meta_window_get_frame_bounds: - * @window: a #MetaWindow - * - * Gets a region representing the outer bounds of the window's frame. - * - * Return value: (transfer none) (nullable): a #cairo_region_t - * holding the outer bounds of the window, or %NULL if the window - * doesn't have a frame. - */ -cairo_region_t * -meta_window_get_frame_bounds (MetaWindow *window) -{ - if (!window->frame_bounds) - { - if (window->frame) - window->frame_bounds = meta_frame_get_frame_bounds (window->frame); - } - - return window->frame_bounds; -} - -/** - * meta_window_is_attached_dialog: - * @window: a #MetaWindow - * - * Tests if @window is should be attached to its parent window. - * (If the "attach_modal_dialogs" option is not enabled, this will - * always return %FALSE.) - * - * Return value: whether @window should be attached to its parent - */ -gboolean -meta_window_is_attached_dialog (MetaWindow *window) -{ - return window->attached; -} - -/** - * meta_window_get_tile_match: - * @window: a #MetaWindow - * - * Returns the matching tiled window on the same monitor as @window. This is - * the topmost tiled window in a complementary tile mode that is: - * - * - on the same monitor; - * - on the same workspace; - * - spanning the remaining monitor width; - * - there is no 3rd window stacked between both tiled windows that's - * partially visible in the common edge. - * - * Return value: (transfer none) (nullable): the matching tiled window or - * %NULL if it doesn't exist. - */ -MetaWindow * -meta_window_get_tile_match (MetaWindow *window) -{ - return window->tile_match; -} - -void -meta_window_compute_tile_match (MetaWindow *window) -{ - window->tile_match = meta_window_find_tile_match (window, window->tile_mode); -} - -static MetaWindow * -meta_window_find_tile_match (MetaWindow *window, - MetaTileMode current_mode) -{ - MetaWindow *match; - MetaStack *stack; - MetaTileMode match_tile_mode = META_TILE_NONE; - - if (window->shaded || window->minimized) - return NULL; - - if (current_mode == META_TILE_LEFT) - match_tile_mode = META_TILE_RIGHT; - else if (current_mode == META_TILE_RIGHT) - match_tile_mode = META_TILE_LEFT; - else - return NULL; - - stack = window->display->stack; - - for (match = meta_stack_get_top (stack); - match; - match = meta_stack_get_below (stack, match, FALSE)) - { - if (!match->shaded && - !match->minimized && - match->tile_mode == match_tile_mode && - match->tile_monitor_number == window->tile_monitor_number && - meta_window_get_workspace (match) == meta_window_get_workspace (window)) - break; - } - - if (match) - { - MetaWindow *above, *bottommost, *topmost; - MetaRectangle above_rect, bottommost_rect, topmost_rect; - - if (meta_stack_windows_cmp (window->display->stack, match, window) > 0) - { - topmost = match; - bottommost = window; - } - else - { - topmost = window; - bottommost = match; - } - - meta_window_get_frame_rect (bottommost, &bottommost_rect); - meta_window_get_frame_rect (topmost, &topmost_rect); - - /* - * If we are looking for a tile match while actually being tiled, - * rather than a match for a potential tile mode, then discard - * windows with too much gap or overlap - */ - if (window->tile_mode == current_mode && - !(meta_grab_op_is_resizing (window->display->grab_op) && - window->display->grab_window == window && - window->tile_match != NULL)) - { - int threshold = meta_prefs_get_drag_threshold (); - if (ABS (topmost_rect.x - bottommost_rect.x - bottommost_rect.width) > threshold && - ABS (bottommost_rect.x - topmost_rect.x - topmost_rect.width) > threshold) - return NULL; - } - - /* - * If there's a window stacked in between which is partially visible - * behind the topmost tile we don't consider the tiles to match. - */ - for (above = meta_stack_get_above (stack, bottommost, FALSE); - above && above != topmost; - above = meta_stack_get_above (stack, above, FALSE)) - { - if (above->minimized || - above->monitor != window->monitor || - meta_window_get_workspace (above) != meta_window_get_workspace (window)) - continue; - - meta_window_get_frame_rect (above, &above_rect); - - if (meta_rectangle_overlap (&above_rect, &bottommost_rect) && - meta_rectangle_overlap (&above_rect, &topmost_rect)) - return NULL; - } - } - - return match; -} - -void -meta_window_set_title (MetaWindow *window, - const char *title) -{ - g_free (window->title); - window->title = g_strdup (title); - - if (window->frame) - meta_frame_update_title (window->frame); - - meta_window_update_desc (window); - - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_TITLE]); -} - -void -meta_window_set_wm_class (MetaWindow *window, - const char *wm_class, - const char *wm_instance) -{ - g_free (window->res_class); - g_free (window->res_name); - - window->res_name = g_strdup (wm_instance); - window->res_class = g_strdup (wm_class); - - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_WM_CLASS]); -} - -void -meta_window_set_gtk_dbus_properties (MetaWindow *window, - const char *application_id, - const char *unique_bus_name, - const char *appmenu_path, - const char *menubar_path, - const char *application_object_path, - const char *window_object_path) -{ - g_object_freeze_notify (G_OBJECT (window)); - - g_free (window->gtk_application_id); - window->gtk_application_id = g_strdup (application_id); - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_GTK_APPLICATION_ID]); - - g_free (window->gtk_unique_bus_name); - window->gtk_unique_bus_name = g_strdup (unique_bus_name); - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_GTK_UNIQUE_BUS_NAME]); - - g_free (window->gtk_app_menu_object_path); - window->gtk_app_menu_object_path = g_strdup (appmenu_path); - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_GTK_APP_MENU_OBJECT_PATH]); - - g_free (window->gtk_menubar_object_path); - window->gtk_menubar_object_path = g_strdup (menubar_path); - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_GTK_MENUBAR_OBJECT_PATH]); - - g_free (window->gtk_application_object_path); - window->gtk_application_object_path = g_strdup (application_object_path); - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_GTK_APPLICATION_OBJECT_PATH]); - - g_free (window->gtk_window_object_path); - window->gtk_window_object_path = g_strdup (window_object_path); - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_GTK_WINDOW_OBJECT_PATH]); - - g_object_thaw_notify (G_OBJECT (window)); -} - -static gboolean -check_transient_for_loop (MetaWindow *window, - MetaWindow *parent) -{ - while (parent) - { - if (parent == window) - return TRUE; - parent = parent->transient_for; - } - - return FALSE; -} - -gboolean -meta_window_has_transient_type (MetaWindow *window) -{ - return (window->type == META_WINDOW_DIALOG || - window->type == META_WINDOW_MODAL_DIALOG || - window->type == META_WINDOW_TOOLBAR || - window->type == META_WINDOW_MENU || - window->type == META_WINDOW_UTILITY); -} - -void -meta_window_set_transient_for (MetaWindow *window, - MetaWindow *parent) -{ - if (check_transient_for_loop (window, parent)) - { - meta_warning ("Setting %s transient for %s would create a loop.", - window->desc, parent->desc); - return; - } - - if (meta_window_appears_focused (window) && window->transient_for != NULL) - meta_window_propagate_focus_appearance (window, FALSE); - - /* may now be a dialog */ - if (window->client_type == META_WINDOW_CLIENT_TYPE_X11) - { - meta_window_x11_recalc_window_type (window); - - if (!window->constructing) - { - /* If the window attaches, detaches, or changes attached - * parents, we need to destroy the MetaWindow and let a new one - * be created (which happens as a side effect of - * meta_window_unmanage()). The condition below is correct - * because we know window->transient_for has changed. - */ - if (window->attached || meta_window_should_attach_to_parent (window)) - { - guint32 timestamp; - - timestamp = - meta_display_get_current_time_roundtrip (window->display); - meta_window_unmanage (window, timestamp); - return; - } - } - } - else if (window->attached && parent == NULL) - { - guint32 timestamp; - - timestamp = - meta_display_get_current_time_roundtrip (window->display); - meta_window_unmanage (window, timestamp); - return; - } - /* We know this won't create a reference cycle because we check for loops */ - g_clear_object (&window->transient_for); - window->transient_for = parent ? g_object_ref (parent) : NULL; - - /* update stacking constraints */ - if (!window->override_redirect) - meta_stack_update_transient (window->display->stack, window); - - /* possibly change its group. We treat being a window's transient as - * equivalent to making it your group leader, to work around shortcomings - * in programs such as xmms-- see #328211. - */ - if (window->xtransient_for != None && - window->xgroup_leader != None && - window->xtransient_for != window->xgroup_leader) - meta_window_group_leader_changed (window); - - if (!window->constructing && !window->override_redirect) - meta_window_queue (window, META_QUEUE_MOVE_RESIZE | META_QUEUE_CALC_SHOWING); - - if (meta_window_appears_focused (window) && window->transient_for != NULL) - meta_window_propagate_focus_appearance (window, TRUE); -} - -void -meta_window_set_opacity (MetaWindow *window, - guint8 opacity) -{ - window->opacity = opacity; - - meta_compositor_window_opacity_changed (window->display->compositor, window); -} - -static void -reset_ignored_crossing_serials (MetaDisplay *display) -{ - int i; - - i = 0; - while (i < N_IGNORED_CROSSING_SERIALS) - { - display->ignored_crossing_serials[i] = 0; - ++i; - } -} - -typedef struct -{ - MetaWindow *window; - int pointer_x; - int pointer_y; -} MetaFocusData; - -static void -mouse_mode_focus (MetaWindow *window, - guint32 timestamp) -{ - MetaDisplay *display = window->display; - - if (window->override_redirect) - return; - - if (window->type != META_WINDOW_DESKTOP) - { - meta_topic (META_DEBUG_FOCUS, - "Focusing %s at time %u.", window->desc, timestamp); - - meta_window_focus (window, timestamp); - - if (meta_prefs_get_auto_raise ()) - meta_display_queue_autoraise_callback (display, window); - else - meta_topic (META_DEBUG_FOCUS, "Auto raise is disabled"); - } - else - { - /* In mouse focus mode, we defocus when the mouse *enters* - * the DESKTOP window, instead of defocusing on LeaveNotify. - * This is because having the mouse enter override-redirect - * child windows unfortunately causes LeaveNotify events that - * we can't distinguish from the mouse actually leaving the - * toplevel window as we expect. But, since we filter out - * EnterNotify events on override-redirect windows, this - * alternative mechanism works great. - */ - if (meta_prefs_get_focus_mode() == G_DESKTOP_FOCUS_MODE_MOUSE && - display->focus_window != NULL) - { - meta_topic (META_DEBUG_FOCUS, - "Unsetting focus from %s due to mouse entering " - "the DESKTOP window", - display->focus_window->desc); - meta_display_unset_input_focus (display, timestamp); - } - } -} - -static gboolean -window_has_pointer_wayland (MetaWindow *window) -{ - ClutterSeat *seat; - ClutterInputDevice *dev; - ClutterStage *stage; - ClutterActor *pointer_actor, *window_actor; - - seat = clutter_backend_get_default_seat (clutter_get_default_backend ()); - dev = clutter_seat_get_pointer (seat); - stage = CLUTTER_STAGE (meta_backend_get_stage (meta_get_backend ())); - pointer_actor = clutter_stage_get_device_actor (stage, dev, NULL); - window_actor = CLUTTER_ACTOR (meta_window_get_compositor_private (window)); - - return pointer_actor && clutter_actor_contains (window_actor, pointer_actor); -} - -static gboolean -window_has_pointer_x11 (MetaWindow *window) -{ - MetaX11Display *x11_display = window->display->x11_display; - Window root, child; - double root_x, root_y, x, y; - XIButtonState buttons; - XIModifierState mods; - XIGroupState group; - - meta_x11_error_trap_push (x11_display); - XIQueryPointer (x11_display->xdisplay, - META_VIRTUAL_CORE_POINTER_ID, - x11_display->xroot, - &root, &child, - &root_x, &root_y, &x, &y, - &buttons, &mods, &group); - meta_x11_error_trap_pop (x11_display); - free (buttons.mask); - - return meta_x11_display_lookup_x_window (x11_display, child) == window; -} - -gboolean -meta_window_has_pointer (MetaWindow *window) -{ - if (meta_is_wayland_compositor ()) - return window_has_pointer_wayland (window); - else - return window_has_pointer_x11 (window); -} - -static gboolean -window_focus_on_pointer_rest_callback (gpointer data) -{ - MetaFocusData *focus_data = data; - MetaWindow *window = focus_data->window; - MetaDisplay *display = window->display; - MetaBackend *backend = meta_get_backend (); - MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); - graphene_point_t point; - guint32 timestamp; - - if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK) - goto out; - - meta_cursor_tracker_get_pointer (cursor_tracker, &point, NULL); - - if ((int) point.x != focus_data->pointer_x || - (int) point.y != focus_data->pointer_y) - { - focus_data->pointer_x = point.x; - focus_data->pointer_y = point.y; - return G_SOURCE_CONTINUE; - } - - if (!meta_window_has_pointer (window)) - goto out; - - timestamp = meta_display_get_current_time_roundtrip (display); - mouse_mode_focus (window, timestamp); - - out: - display->focus_timeout_id = 0; - return G_SOURCE_REMOVE; -} - -/* The interval, in milliseconds, we use in focus-follows-mouse - * mode to check whether the pointer has stopped moving after a - * crossing event. - */ -#define FOCUS_TIMEOUT_DELAY 25 - -static void -queue_focus_callback (MetaDisplay *display, - MetaWindow *window, - int pointer_x, - int pointer_y) -{ - MetaFocusData *focus_data; - - focus_data = g_new (MetaFocusData, 1); - focus_data->window = window; - focus_data->pointer_x = pointer_x; - focus_data->pointer_y = pointer_y; - - g_clear_handle_id (&display->focus_timeout_id, g_source_remove); - - display->focus_timeout_id = - g_timeout_add_full (G_PRIORITY_DEFAULT, - FOCUS_TIMEOUT_DELAY, - window_focus_on_pointer_rest_callback, - focus_data, - g_free); - g_source_set_name_by_id (display->focus_timeout_id, - "[mutter] window_focus_on_pointer_rest_callback"); -} - -void -meta_window_handle_enter (MetaWindow *window, - guint32 timestamp, - guint root_x, - guint root_y) -{ - MetaDisplay *display = window->display; - - switch (meta_prefs_get_focus_mode ()) - { - case G_DESKTOP_FOCUS_MODE_SLOPPY: - case G_DESKTOP_FOCUS_MODE_MOUSE: - display->mouse_mode = TRUE; - if (window->type != META_WINDOW_DOCK) - { - if (meta_prefs_get_focus_change_on_pointer_rest()) - queue_focus_callback (display, window, root_x, root_y); - else - mouse_mode_focus (window, timestamp); - - /* stop ignoring stuff */ - reset_ignored_crossing_serials (display); - } - break; - case G_DESKTOP_FOCUS_MODE_CLICK: - break; - } - - if (window->type == META_WINDOW_DOCK) - meta_window_raise (window); -} - -void -meta_window_handle_leave (MetaWindow *window) -{ - if (window->type == META_WINDOW_DOCK && !window->has_focus) - meta_window_lower (window); -} - -gboolean -meta_window_handle_ui_frame_event (MetaWindow *window, - const ClutterEvent *event) -{ - if (!window->frame) - return FALSE; - - return meta_ui_frame_handle_event (window->frame->ui_frame, event); -} - -void -meta_window_handle_ungrabbed_event (MetaWindow *window, - const ClutterEvent *event) -{ - MetaDisplay *display = window->display; - gboolean unmodified; - gboolean is_window_grab; - gboolean is_window_button_grab_allowed; - ClutterModifierType grab_mods, event_mods; - ClutterInputDevice *source; - gfloat x, y; - guint button; - - if (window->unmanaging) - return; - - if (event->type != CLUTTER_BUTTON_PRESS && - event->type != CLUTTER_TOUCH_BEGIN) - return; - - if (event->type == CLUTTER_TOUCH_BEGIN) - { - ClutterEventSequence *sequence; - - button = 1; - sequence = clutter_event_get_event_sequence (event); - if (!meta_display_is_pointer_emulating_sequence (window->display, sequence)) - return; - } - else - button = clutter_event_get_button (event); - - if (display->grab_op != META_GRAB_OP_NONE) - return; - - /* Some windows might not ask for input, in which case we might be here - * because we selected for ButtonPress on the root window. In that case, - * we have to take special care not to act for an override-redirect window. - */ - if (window->override_redirect) - return; - - /* Don't focus panels--they must explicitly request focus. - * See bug 160470 - */ - if (window->type != META_WINDOW_DOCK) - { - meta_topic (META_DEBUG_FOCUS, - "Focusing %s due to button %u press (display.c)", - window->desc, button); - meta_window_focus (window, event->any.time); - meta_window_check_alive (window, event->any.time); - } - else - /* However, do allow terminals to lose focus due to new - * window mappings after the user clicks on a panel. - */ - display->allow_terminal_deactivation = TRUE; - - /* We have three passive button grabs: - * - on any button, without modifiers => focuses and maybe raises the window - * - on resize button, with modifiers => start an interactive resizing - * (normally middle) - * - on move button, with modifiers => start an interactive move - * (normally left) - * - on menu button, with modifiers => show the window menu - * (normally right) - * - * We may get here because we actually have a button - * grab on the window, or because we're a wayland - * compositor and thus we see all the events, so we - * need to check if the event is interesting. - * We want an event that is not modified for a window. - * - * We may have other events on the window, for example - * a click on a frame button, but that's not for us to - * care about. Just let the event through. - */ - - grab_mods = meta_display_get_compositor_modifiers (display); - event_mods = clutter_event_get_state (event); - unmodified = (event_mods & grab_mods) == 0; - source = clutter_event_get_source_device (event); - is_window_button_grab_allowed = !display->focus_window || - !meta_window_shortcuts_inhibited (display->focus_window, source); - is_window_grab = (is_window_button_grab_allowed && - ((event_mods & grab_mods) == grab_mods)); - - clutter_event_get_coords (event, &x, &y); - - if (unmodified) - { - if (meta_prefs_get_raise_on_click ()) - meta_window_raise (window); - else - meta_topic (META_DEBUG_FOCUS, - "Not raising window on click due to don't-raise-on-click option"); - } - else if (is_window_grab && (int) button == meta_prefs_get_mouse_button_resize ()) - { - if (window->has_resize_func) - { - gboolean north, south; - gboolean west, east; - MetaRectangle frame_rect; - MetaGrabOp op = META_GRAB_OP_WINDOW_BASE; - - meta_window_get_frame_rect (window, &frame_rect); - - west = x < (frame_rect.x + 1 * frame_rect.width / 3); - east = x > (frame_rect.x + 2 * frame_rect.width / 3); - north = y < (frame_rect.y + 1 * frame_rect.height / 3); - south = y > (frame_rect.y + 2 * frame_rect.height / 3); - - if (west) - op |= META_GRAB_OP_WINDOW_DIR_WEST; - if (east) - op |= META_GRAB_OP_WINDOW_DIR_EAST; - if (north) - op |= META_GRAB_OP_WINDOW_DIR_NORTH; - if (south) - op |= META_GRAB_OP_WINDOW_DIR_SOUTH; - - if (op != META_GRAB_OP_WINDOW_BASE) - meta_display_begin_grab_op (display, - window, - op, - TRUE, - FALSE, - button, - 0, - event->any.time, - x, y); - } - } - else if (is_window_grab && (int) button == meta_prefs_get_mouse_button_menu ()) - { - if (meta_prefs_get_raise_on_click ()) - meta_window_raise (window); - meta_window_show_menu (window, - META_WINDOW_MENU_WM, - x, y); - } - else if (is_window_grab && (int) button == 1) - { - if (window->has_move_func) - { - meta_display_begin_grab_op (display, - window, - META_GRAB_OP_MOVING, - TRUE, - FALSE, - button, - 0, - event->any.time, - x, y); - } - } -} - -gboolean -meta_window_can_maximize (MetaWindow *window) -{ - return window->has_maximize_func; -} - -gboolean -meta_window_can_minimize (MetaWindow *window) -{ - return window->has_minimize_func; -} - -gboolean -meta_window_can_shade (MetaWindow *window) -{ - return window->has_shade_func; -} - -gboolean -meta_window_can_close (MetaWindow *window) -{ - return window->has_close_func; -} - -gboolean -meta_window_is_always_on_all_workspaces (MetaWindow *window) -{ - return window->always_sticky; -} - -gboolean -meta_window_is_above (MetaWindow *window) -{ - return window->wm_state_above; -} - -gboolean -meta_window_allows_move (MetaWindow *window) -{ - return META_WINDOW_ALLOWS_MOVE (window); -} - -gboolean -meta_window_allows_resize (MetaWindow *window) -{ - return META_WINDOW_ALLOWS_RESIZE (window); -} - -void -meta_window_set_urgent (MetaWindow *window, - gboolean urgent) -{ - if (window->urgent == urgent) - return; - - window->urgent = urgent; - g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_URGENT]); - - if (urgent) - g_signal_emit_by_name (window->display, "window-marked-urgent", window); -} - -void -meta_window_grab_op_began (MetaWindow *window, - MetaGrabOp op) -{ - META_WINDOW_GET_CLASS (window)->grab_op_began (window, op); -} - -void -meta_window_grab_op_ended (MetaWindow *window, - MetaGrabOp op) -{ - META_WINDOW_GET_CLASS (window)->grab_op_ended (window, op); -} - -void -meta_window_emit_size_changed (MetaWindow *window) -{ - g_signal_emit (window, window_signals[SIZE_CHANGED], 0); -} - -MetaPlacementRule * -meta_window_get_placement_rule (MetaWindow *window) -{ - return window->placement.rule; -} - -void -meta_window_force_restore_shortcuts (MetaWindow *window, - ClutterInputDevice *source) -{ - META_WINDOW_GET_CLASS (window)->force_restore_shortcuts (window, source); -} - -gboolean -meta_window_shortcuts_inhibited (MetaWindow *window, - ClutterInputDevice *source) -{ - return META_WINDOW_GET_CLASS (window)->shortcuts_inhibited (window, source); -} - -gboolean -meta_window_is_focusable (MetaWindow *window) -{ - g_return_val_if_fail (!window->unmanaging, FALSE); - - return META_WINDOW_GET_CLASS (window)->is_focusable (window); -} - -gboolean -meta_window_can_ping (MetaWindow *window) -{ - g_return_val_if_fail (!window->unmanaging, FALSE); - - return META_WINDOW_GET_CLASS (window)->can_ping (window); -} - -gboolean -meta_window_is_stackable (MetaWindow *window) -{ - return META_WINDOW_GET_CLASS (window)->is_stackable (window); -} - -gboolean -meta_window_is_focus_async (MetaWindow *window) -{ - return META_WINDOW_GET_CLASS (window)->is_focus_async (window); -} - -MetaStackLayer -meta_window_calculate_layer (MetaWindow *window) -{ - return META_WINDOW_GET_CLASS (window)->calculate_layer (window); -} - -/** - * meta_window_get_id: - * @window: a #MetaWindow - * - * Returns the window id associated with window. - * - * Returns: The window id - */ -uint64_t -meta_window_get_id (MetaWindow *window) -{ - return window->id; -} - -/** - * meta_window_get_client_type: - * @window: a #MetaWindow - * - * Returns the #MetaWindowClientType of the window. - * - * Returns: The root ancestor window - */ -MetaWindowClientType -meta_window_get_client_type (MetaWindow *window) -{ - return window->client_type; -} diff --git a/src/core/workspace-private.h b/src/core/workspace-private.h deleted file mode 100644 index a58b2347d..000000000 --- a/src/core/workspace-private.h +++ /dev/null @@ -1,103 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/** - * \file workspace.h Workspaces - * - * A workspace is a set of windows which all live on the same - * screen. (You may also see the name "desktop" around the place, - * which is the EWMH's name for the same thing.) Only one workspace - * of a screen may be active at once; all windows on all other workspaces - * are unmapped. - */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2004, 2005 Elijah Newren - * - * 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 . - */ - -#ifndef META_WORKSPACE_PRIVATE_H -#define META_WORKSPACE_PRIVATE_H - -#include "core/window-private.h" -#include "meta/workspace.h" - -struct _MetaWorkspace -{ - GObject parent_instance; - MetaDisplay *display; - MetaWorkspaceManager *manager; - - GList *windows; - - /* The "MRU list", or "most recently used" list, is a list of - * MetaWindows ordered based on the time the the user interacted - * with the window most recently. - * - * For historical reasons, we keep an MRU list per workspace. - * It used to be used to calculate the default focused window, - * but isn't anymore, as the window next in the stacking order - * can sometimes be not the window the user interacted with last, - */ - GList *mru_list; - - GList *list_containing_self; - - GHashTable *logical_monitor_data; - - MetaRectangle work_area_screen; - GList *screen_region; - GList *screen_edges; - GList *monitor_edges; - GSList *builtin_struts; - GSList *all_struts; - guint work_areas_invalid : 1; - - guint showing_desktop : 1; -}; - -struct _MetaWorkspaceClass -{ - GObjectClass parent_class; -}; - -MetaWorkspace* meta_workspace_new (MetaWorkspaceManager *workspace_manager); -void meta_workspace_remove (MetaWorkspace *workspace); -void meta_workspace_add_window (MetaWorkspace *workspace, - MetaWindow *window); -void meta_workspace_remove_window (MetaWorkspace *workspace, - MetaWindow *window); -void meta_workspace_relocate_windows (MetaWorkspace *workspace, - MetaWorkspace *new_home); - -void meta_workspace_get_work_area_for_logical_monitor (MetaWorkspace *workspace, - MetaLogicalMonitor *logical_monitor, - MetaRectangle *area); - -void meta_workspace_invalidate_work_area (MetaWorkspace *workspace); - -GList* meta_workspace_get_onscreen_region (MetaWorkspace *workspace); -GList * meta_workspace_get_onmonitor_region (MetaWorkspace *workspace, - MetaLogicalMonitor *logical_monitor); - -void meta_workspace_focus_default_window (MetaWorkspace *workspace, - MetaWindow *not_this_one, - guint32 timestamp); - -const char* meta_workspace_get_name (MetaWorkspace *workspace); - -void meta_workspace_index_changed (MetaWorkspace *workspace); - -#endif diff --git a/src/core/workspace.c b/src/core/workspace.c deleted file mode 100644 index 321d3efb0..000000000 --- a/src/core/workspace.c +++ /dev/null @@ -1,1477 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004, 2005 Elijah Newren - * - * 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 . - */ - -/** - * SECTION:workspace - * @title:MetaWorkspace - * @short_description:Workspaces - * - * A workspace is a set of windows which all live on the same - * screen. (You may also see the name "desktop" around the place, - * which is the EWMH's name for the same thing.) Only one workspace - * of a screen may be active at once; all windows on all other workspaces - * are unmapped. - */ - -#include "config.h" - -#include "meta/workspace.h" - -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-logical-monitor.h" -#include "cogl/cogl.h" -#include "core/boxes-private.h" -#include "core/meta-workspace-manager-private.h" -#include "core/workspace-private.h" -#include "meta/compositor.h" -#include "meta/meta-x11-errors.h" -#include "meta/prefs.h" -#include "x11/meta-x11-display-private.h" - -void meta_workspace_queue_calc_showing (MetaWorkspace *workspace); -static void focus_ancestor_or_top_window (MetaWorkspace *workspace, - MetaWindow *not_this_one, - guint32 timestamp); - -G_DEFINE_TYPE (MetaWorkspace, meta_workspace, G_TYPE_OBJECT); - -enum -{ - PROP_0, - - PROP_N_WINDOWS, - PROP_WORKSPACE_INDEX, - PROP_ACTIVE, - - PROP_LAST, -}; - -static GParamSpec *obj_props[PROP_LAST]; - -enum -{ - WINDOW_ADDED, - WINDOW_REMOVED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -typedef struct _MetaWorkspaceLogicalMonitorData -{ - GList *logical_monitor_region; - MetaRectangle logical_monitor_work_area; -} MetaWorkspaceLogicalMonitorData; - -typedef struct _MetaWorkspaceFocusableAncestorData -{ - MetaWorkspace *workspace; - MetaWindow *out_window; -} MetaWorkspaceFocusableAncestorData; - -static MetaWorkspaceLogicalMonitorData * -meta_workspace_get_logical_monitor_data (MetaWorkspace *workspace, - MetaLogicalMonitor *logical_monitor) -{ - if (!workspace->logical_monitor_data) - return NULL; - return g_hash_table_lookup (workspace->logical_monitor_data, logical_monitor); -} - -static void -workspace_logical_monitor_data_free (MetaWorkspaceLogicalMonitorData *data) -{ - g_clear_pointer (&data->logical_monitor_region, - meta_rectangle_free_list_and_elements); - g_free (data); -} - -static MetaWorkspaceLogicalMonitorData * -meta_workspace_ensure_logical_monitor_data (MetaWorkspace *workspace, - MetaLogicalMonitor *logical_monitor) -{ - MetaWorkspaceLogicalMonitorData *data; - - data = meta_workspace_get_logical_monitor_data (workspace, logical_monitor); - if (data) - return data; - - if (!workspace->logical_monitor_data) - { - workspace->logical_monitor_data = - g_hash_table_new_full (g_direct_hash, - g_direct_equal, - NULL, - (GDestroyNotify) workspace_logical_monitor_data_free); - } - - data = g_new0 (MetaWorkspaceLogicalMonitorData, 1); - g_hash_table_insert (workspace->logical_monitor_data, logical_monitor, data); - - return data; -} - -static void -meta_workspace_clear_logical_monitor_data (MetaWorkspace *workspace) -{ - g_clear_pointer (&workspace->logical_monitor_data, g_hash_table_destroy); -} - -static void -meta_workspace_finalize (GObject *object) -{ - /* Actual freeing done in meta_workspace_remove() for now */ - G_OBJECT_CLASS (meta_workspace_parent_class)->finalize (object); -} - -static void -meta_workspace_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (prop_id) - { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_workspace_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaWorkspace *ws = META_WORKSPACE (object); - - switch (prop_id) - { - case PROP_N_WINDOWS: - /* - * This is reliable, but not very efficient; should we store - * the list length ? - */ - g_value_set_uint (value, g_list_length (ws->windows)); - break; - case PROP_WORKSPACE_INDEX: - g_value_set_uint (value, meta_workspace_index (ws)); - break; - case PROP_ACTIVE: - g_value_set_boolean (value, ws->manager->active_workspace == ws); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_workspace_class_init (MetaWorkspaceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - object_class->finalize = meta_workspace_finalize; - object_class->get_property = meta_workspace_get_property; - object_class->set_property = meta_workspace_set_property; - - signals[WINDOW_ADDED] = g_signal_new ("window-added", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 1, - META_TYPE_WINDOW); - signals[WINDOW_REMOVED] = g_signal_new ("window-removed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 1, - META_TYPE_WINDOW); - - obj_props[PROP_N_WINDOWS] = g_param_spec_uint ("n-windows", - "N Windows", - "Number of windows", - 0, G_MAXUINT, 0, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_props[PROP_WORKSPACE_INDEX] = g_param_spec_uint ("workspace-index", - "Workspace index", - "The workspace's index", - 0, G_MAXUINT, 0, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - obj_props[PROP_ACTIVE] = g_param_spec_boolean ("active", - "Active", - "Whether the workspace is currently active", - FALSE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties (object_class, PROP_LAST, obj_props); -} - -static void -meta_workspace_init (MetaWorkspace *workspace) -{ -} - -MetaWorkspace * -meta_workspace_new (MetaWorkspaceManager *workspace_manager) -{ - MetaDisplay *display = workspace_manager->display; - MetaWorkspace *workspace; - GSList *windows, *l; - - workspace = g_object_new (META_TYPE_WORKSPACE, NULL); - - workspace->display = display; - workspace->manager = workspace_manager; - - workspace_manager->workspaces = - g_list_append (workspace_manager->workspaces, workspace); - workspace->windows = NULL; - workspace->mru_list = NULL; - - workspace->work_areas_invalid = TRUE; - workspace->work_area_screen.x = 0; - workspace->work_area_screen.y = 0; - workspace->work_area_screen.width = 0; - workspace->work_area_screen.height = 0; - - workspace->screen_region = NULL; - workspace->screen_edges = NULL; - workspace->monitor_edges = NULL; - workspace->list_containing_self = g_list_prepend (NULL, workspace); - - workspace->builtin_struts = NULL; - workspace->all_struts = NULL; - - workspace->showing_desktop = FALSE; - - /* make sure sticky windows are in our mru_list */ - windows = meta_display_list_windows (display, META_LIST_SORTED); - for (l = windows; l; l = l->next) - if (meta_window_located_on_workspace (l->data, workspace)) - meta_workspace_add_window (workspace, l->data); - g_slist_free (windows); - - return workspace; -} - -/** - * workspace_free_all_struts: - * @workspace: The workspace. - * - * Frees the combined struts list of a workspace. - */ -static void -workspace_free_all_struts (MetaWorkspace *workspace) -{ - if (workspace->all_struts == NULL) - return; - - g_slist_free_full (workspace->all_struts, g_free); - workspace->all_struts = NULL; -} - -/** - * workspace_free_builtin_struts: - * @workspace: The workspace. - * - * Frees the struts list set with meta_workspace_set_builtin_struts - */ -static void -workspace_free_builtin_struts (MetaWorkspace *workspace) -{ - if (workspace->builtin_struts == NULL) - return; - - g_slist_free_full (workspace->builtin_struts, g_free); - workspace->builtin_struts = NULL; -} - -/* Ensure that the workspace is empty by making sure that - * all of our windows are on-all-workspaces. */ -static void -assert_workspace_empty (MetaWorkspace *workspace) -{ - GList *l; - for (l = workspace->windows; l != NULL; l = l->next) - { - MetaWindow *window = l->data; - g_assert (window->on_all_workspaces); - } -} - -void -meta_workspace_remove (MetaWorkspace *workspace) -{ - MetaWorkspaceManager *manager = workspace->display->workspace_manager; - - g_return_if_fail (workspace != manager->active_workspace); - - assert_workspace_empty (workspace); - - manager->workspaces = - g_list_remove (manager->workspaces, workspace); - - meta_workspace_clear_logical_monitor_data (workspace); - - g_list_free (workspace->mru_list); - g_list_free (workspace->list_containing_self); - - workspace_free_builtin_struts (workspace); - - /* screen.c:update_num_workspaces(), which calls us, removes windows from - * workspaces first, which can cause the workareas on the workspace to be - * invalidated (and hence for struts/regions/edges to be freed). - * So, no point trying to double free it; that causes a crash - * anyway. #361804. - */ - - if (!workspace->work_areas_invalid) - { - workspace_free_all_struts (workspace); - meta_rectangle_free_list_and_elements (workspace->screen_region); - meta_rectangle_free_list_and_elements (workspace->screen_edges); - meta_rectangle_free_list_and_elements (workspace->monitor_edges); - } - - g_object_unref (workspace); - - /* don't bother to reset names, pagers can just ignore - * extra ones - */ -} - -void -meta_workspace_add_window (MetaWorkspace *workspace, - MetaWindow *window) -{ - g_return_if_fail (g_list_find (workspace->mru_list, window) == NULL); - - COGL_TRACE_BEGIN_SCOPED (MetaWorkspaceAddWindow, - "Workspace (add window)"); - - workspace->mru_list = g_list_prepend (workspace->mru_list, window); - - workspace->windows = g_list_prepend (workspace->windows, window); - - if (window->struts) - { - meta_topic (META_DEBUG_WORKAREA, - "Invalidating work area of workspace %d since we're adding window %s to it", - meta_workspace_index (workspace), window->desc); - meta_workspace_invalidate_work_area (workspace); - } - - g_signal_emit (workspace, signals[WINDOW_ADDED], 0, window); - g_object_notify_by_pspec (G_OBJECT (workspace), obj_props[PROP_N_WINDOWS]); -} - -void -meta_workspace_remove_window (MetaWorkspace *workspace, - MetaWindow *window) -{ - COGL_TRACE_BEGIN_SCOPED (MetaWorkspaceRemoveWindow, - "Workspace (remove window)"); - - workspace->windows = g_list_remove (workspace->windows, window); - - workspace->mru_list = g_list_remove (workspace->mru_list, window); - g_assert (g_list_find (workspace->mru_list, window) == NULL); - - if (window->struts) - { - meta_topic (META_DEBUG_WORKAREA, - "Invalidating work area of workspace %d since we're removing window %s from it", - meta_workspace_index (workspace), window->desc); - meta_workspace_invalidate_work_area (workspace); - } - - g_signal_emit (workspace, signals[WINDOW_REMOVED], 0, window); - g_object_notify (G_OBJECT (workspace), "n-windows"); -} - -void -meta_workspace_relocate_windows (MetaWorkspace *workspace, - MetaWorkspace *new_home) -{ - GList *copy, *l; - - g_return_if_fail (workspace != new_home); - - /* can't modify list we're iterating over */ - copy = g_list_copy (workspace->windows); - - for (l = copy; l != NULL; l = l->next) - { - MetaWindow *window = l->data; - - if (!window->on_all_workspaces) - meta_window_change_workspace (window, new_home); - } - - g_list_free (copy); - - assert_workspace_empty (workspace); -} - -void -meta_workspace_queue_calc_showing (MetaWorkspace *workspace) -{ - GList *l; - - for (l = workspace->windows; l != NULL; l = l->next) - meta_window_queue (l->data, META_QUEUE_CALC_SHOWING); -} - -static void -workspace_switch_sound(MetaWorkspace *from, - MetaWorkspace *to) -{ - MetaSoundPlayer *player; - MetaWorkspaceLayout layout; - int i, nw, x, y, fi, ti; - const char *e; - - nw = meta_workspace_manager_get_n_workspaces (from->manager); - fi = meta_workspace_index(from); - ti = meta_workspace_index(to); - - meta_workspace_manager_calc_workspace_layout (from->manager, - nw, - fi, - &layout); - - for (i = 0; i < nw; i++) - if (layout.grid[i] == ti) - break; - - if (i >= nw) - { - meta_bug("Failed to find destination workspace in layout"); - goto finish; - } - - y = i / layout.cols; - x = i % layout.cols; - - /* We priorize horizontal over vertical movements here. The - rationale for this is that horizontal movements are probably more - interesting for sound effects because speakers are usually - positioned on a horizontal and not a vertical axis. i.e. your - spatial "Woosh!" effects will easily be able to encode horizontal - movement but not such much vertical movement. */ - - if (x < layout.current_col) - e = "desktop-switch-left"; - else if (x > layout.current_col) - e = "desktop-switch-right"; - else if (y < layout.current_row) - e = "desktop-switch-up"; - else if (y > layout.current_row) - e = "desktop-switch-down"; - else - { - meta_bug("Uh, origin and destination workspace at same logic position!"); - goto finish; - } - - player = meta_display_get_sound_player (from->display); - meta_sound_player_play_from_theme (player, e, "Desktop switched", NULL); - - finish: - meta_workspace_manager_free_workspace_layout (&layout); -} - -/** - * meta_workspace_activate_with_focus: - * @workspace: a #MetaWorkspace - * @focus_this: the #MetaWindow to be focused, or %NULL - * @timestamp: timestamp for @focus_this - * - * Switches to @workspace and possibly activates the window @focus_this. - * - * The window @focus_this is activated by calling meta_window_activate() - * which will unminimize it and transient parents, raise it and give it - * the focus. - * - * If a window is currently being moved by the user, it will be - * moved to @workspace. - * - * The advantage of calling this function instead of meta_workspace_activate() - * followed by meta_window_activate() is that it happens as a unit, so - * no other window gets focused first before @focus_this. - */ -void -meta_workspace_activate_with_focus (MetaWorkspace *workspace, - MetaWindow *focus_this, - guint32 timestamp) -{ - MetaWorkspace *old; - MetaWindow *move_window; - MetaCompositor *comp; - MetaWorkspaceLayout layout1, layout2; - gint num_workspaces, current_space, new_space; - MetaMotionDirection direction; - - meta_verbose ("Activating workspace %d", - meta_workspace_index (workspace)); - - if (workspace->manager->active_workspace == workspace) - { - if (focus_this) - meta_window_activate (focus_this, timestamp); - return; - } - - /* Free any cached pointers to the workspaces's edges from - * a current resize or move operation */ - meta_display_cleanup_edges (workspace->display); - - if (workspace->manager->active_workspace) - workspace_switch_sound (workspace->manager->active_workspace, workspace); - - /* Note that old can be NULL; e.g. when starting up */ - old = workspace->manager->active_workspace; - - workspace->manager->active_workspace = workspace; - - g_signal_emit_by_name (workspace->manager, "active-workspace-changed"); - - g_object_notify_by_pspec (G_OBJECT (workspace), obj_props[PROP_ACTIVE]); - - if (old == NULL) - return; - - g_object_notify_by_pspec (G_OBJECT (old), obj_props[PROP_ACTIVE]); - - /* If the "show desktop" mode is active for either the old workspace - * or the new one *but not both*, then update the - * _net_showing_desktop hint - */ - if (old->showing_desktop != workspace->showing_desktop) - g_signal_emit_by_name (workspace->manager, "showing-desktop-changed"); - - move_window = NULL; - if (meta_grab_op_is_moving (workspace->display->grab_op)) - move_window = workspace->display->grab_window; - - if (move_window != NULL) - { - /* We put the window on the new workspace, flip spaces, - * then remove from old workspace, so the window - * never gets unmapped and we maintain the button grab - * on it. - * - * \bug This comment appears to be the reverse of what happens - */ - if (!meta_window_located_on_workspace (move_window, workspace)) - meta_window_change_workspace (move_window, workspace); - } - - meta_workspace_queue_calc_showing (old); - meta_workspace_queue_calc_showing (workspace); - - /* - * Notify the compositor that the active workspace is changing. - */ - comp = meta_display_get_compositor (workspace->display); - direction = 0; - - current_space = meta_workspace_index (old); - new_space = meta_workspace_index (workspace); - num_workspaces = meta_workspace_manager_get_n_workspaces (workspace->manager); - meta_workspace_manager_calc_workspace_layout (workspace->manager, num_workspaces, - current_space, &layout1); - - meta_workspace_manager_calc_workspace_layout (workspace->manager, num_workspaces, - new_space, &layout2); - - if (meta_get_locale_direction () == META_LOCALE_DIRECTION_RTL) - { - if (layout1.current_col > layout2.current_col) - direction = META_MOTION_RIGHT; - else if (layout1.current_col < layout2.current_col) - direction = META_MOTION_LEFT; - } - else - { - if (layout1.current_col < layout2.current_col) - direction = META_MOTION_RIGHT; - else if (layout1.current_col > layout2.current_col) - direction = META_MOTION_LEFT; - } - - if (layout1.current_row < layout2.current_row) - { - if (!direction) - direction = META_MOTION_DOWN; - else if (direction == META_MOTION_RIGHT) - direction = META_MOTION_DOWN_RIGHT; - else - direction = META_MOTION_DOWN_LEFT; - } - - if (layout1.current_row > layout2.current_row) - { - if (!direction) - direction = META_MOTION_UP; - else if (direction == META_MOTION_RIGHT) - direction = META_MOTION_UP_RIGHT; - else - direction = META_MOTION_UP_LEFT; - } - - meta_workspace_manager_free_workspace_layout (&layout1); - meta_workspace_manager_free_workspace_layout (&layout2); - - meta_compositor_switch_workspace (comp, old, workspace, direction); - - /* This needs to be done after telling the compositor we are switching - * workspaces since focusing a window will cause it to be immediately - * shown and that would confuse the compositor if it didn't know we - * were in a workspace switch. - */ - if (focus_this) - { - meta_window_activate (focus_this, timestamp); - } - else if (move_window) - { - meta_window_raise (move_window); - } - else - { - meta_topic (META_DEBUG_FOCUS, "Focusing default window on new workspace"); - meta_workspace_focus_default_window (workspace, NULL, timestamp); - } - - meta_workspace_manager_workspace_switched (workspace->manager, current_space, - new_space, direction); -} - -void -meta_workspace_activate (MetaWorkspace *workspace, - guint32 timestamp) -{ - meta_workspace_activate_with_focus (workspace, NULL, timestamp); -} - -int -meta_workspace_index (MetaWorkspace *workspace) -{ - int ret; - - ret = g_list_index (workspace->manager->workspaces, workspace); - - if (ret < 0) - meta_bug ("Workspace does not exist to index!"); - - return ret; -} - -void -meta_workspace_index_changed (MetaWorkspace *workspace) -{ - GList *l; - for (l = workspace->windows; l != NULL; l = l->next) - { - MetaWindow *win = l->data; - meta_window_current_workspace_changed (win); - } - - g_object_notify_by_pspec (G_OBJECT (workspace), obj_props[PROP_WORKSPACE_INDEX]); -} - -/** - * meta_workspace_list_windows: - * @workspace: a #MetaWorkspace - * - * Gets windows contained on the workspace, including workspace->windows - * and also sticky windows. Override-redirect windows are not included. - * - * Return value: (transfer container) (element-type MetaWindow): the list of windows. - */ -GList* -meta_workspace_list_windows (MetaWorkspace *workspace) -{ - GSList *display_windows, *l; - GList *workspace_windows; - - display_windows = meta_display_list_windows (workspace->display, - META_LIST_DEFAULT); - - workspace_windows = NULL; - for (l = display_windows; l != NULL; l = l->next) - { - MetaWindow *window = l->data; - - if (meta_window_located_on_workspace (window, workspace)) - workspace_windows = g_list_prepend (workspace_windows, - window); - } - - g_slist_free (display_windows); - - return workspace_windows; -} - -void -meta_workspace_invalidate_work_area (MetaWorkspace *workspace) -{ - GList *windows, *l; - - if (workspace->work_areas_invalid) - { - meta_topic (META_DEBUG_WORKAREA, - "Work area for workspace %d is already invalid", - meta_workspace_index (workspace)); - return; - } - - meta_topic (META_DEBUG_WORKAREA, - "Invalidating work area for workspace %d", - meta_workspace_index (workspace)); - - /* If we are in the middle of a resize or move operation, we - * might have cached pointers to the workspace's edges */ - if (workspace == workspace->manager->active_workspace) - meta_display_cleanup_edges (workspace->display); - - meta_workspace_clear_logical_monitor_data (workspace); - - workspace_free_all_struts (workspace); - - meta_rectangle_free_list_and_elements (workspace->screen_region); - meta_rectangle_free_list_and_elements (workspace->screen_edges); - meta_rectangle_free_list_and_elements (workspace->monitor_edges); - workspace->screen_region = NULL; - workspace->screen_edges = NULL; - workspace->monitor_edges = NULL; - - workspace->work_areas_invalid = TRUE; - - /* redo the size/position constraints on all windows */ - windows = meta_workspace_list_windows (workspace); - - for (l = windows; l != NULL; l = l->next) - { - MetaWindow *w = l->data; - meta_window_queue (w, META_QUEUE_MOVE_RESIZE); - } - - g_list_free (windows); - - meta_display_queue_workarea_recalc (workspace->display); -} - -static MetaStrut * -copy_strut(MetaStrut *original) -{ - return g_memdup2 (original, sizeof (MetaStrut)); -} - -static GSList * -copy_strut_list(GSList *original) -{ - GSList *result = NULL; - - for (; original != NULL; original = original->next) - result = g_slist_prepend (result, copy_strut (original->data)); - - return g_slist_reverse (result); -} - -static void -ensure_work_areas_validated (MetaWorkspace *workspace) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - GList *windows; - GList *tmp; - GList *logical_monitors, *l; - MetaRectangle display_rect = { 0 }; - MetaRectangle work_area; - - if (!workspace->work_areas_invalid) - return; - - g_assert (workspace->all_struts == NULL); - g_assert (workspace->screen_region == NULL); - g_assert (workspace->screen_edges == NULL); - g_assert (workspace->monitor_edges == NULL); - - meta_display_get_size (workspace->display, - &display_rect.width, - &display_rect.height); - - /* STEP 1: Get the list of struts */ - - workspace->all_struts = copy_strut_list (workspace->builtin_struts); - - windows = meta_workspace_list_windows (workspace); - for (tmp = windows; tmp != NULL; tmp = tmp->next) - { - MetaWindow *win = tmp->data; - GSList *s_iter; - - for (s_iter = win->struts; s_iter != NULL; s_iter = s_iter->next) { - workspace->all_struts = g_slist_prepend (workspace->all_struts, - copy_strut(s_iter->data)); - } - } - g_list_free (windows); - - /* STEP 2: Get the maximal/spanning rects for the onscreen and - * on-single-monitor regions - */ - g_assert (workspace->screen_region == NULL); - - logical_monitors = - meta_monitor_manager_get_logical_monitors (monitor_manager); - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - MetaWorkspaceLogicalMonitorData *data; - - g_assert (!meta_workspace_get_logical_monitor_data (workspace, - logical_monitor)); - - data = meta_workspace_ensure_logical_monitor_data (workspace, - logical_monitor); - data->logical_monitor_region = - meta_rectangle_get_minimal_spanning_set_for_region ( - &logical_monitor->rect, - workspace->all_struts); - } - - workspace->screen_region = - meta_rectangle_get_minimal_spanning_set_for_region ( - &display_rect, - workspace->all_struts); - - /* STEP 3: Get the work areas (region-to-maximize-to) for the screen and - * monitors. - */ - work_area = display_rect; /* start with the screen */ - if (workspace->screen_region == NULL) - work_area = meta_rect (0, 0, -1, -1); - else - meta_rectangle_clip_to_region (workspace->screen_region, - FIXED_DIRECTION_NONE, - &work_area); - - /* Lots of paranoia checks, forcing work_area_screen to be sane */ -#define MIN_SANE_AREA 100 - if (work_area.width < MIN_SANE_AREA && - work_area.width != display_rect.width) - { - meta_warning ("struts occupy an unusually large percentage of the screen; " - "available remaining width = %d < %d", - work_area.width, MIN_SANE_AREA); - if (work_area.width < 1) - { - work_area.x = (display_rect.width - MIN_SANE_AREA)/2; - work_area.width = MIN_SANE_AREA; - } - else - { - int amount = (MIN_SANE_AREA - work_area.width)/2; - work_area.x -= amount; - work_area.width += 2*amount; - } - } - if (work_area.height < MIN_SANE_AREA && - work_area.height != display_rect.height) - { - meta_warning ("struts occupy an unusually large percentage of the screen; " - "available remaining height = %d < %d", - work_area.height, MIN_SANE_AREA); - if (work_area.height < 1) - { - work_area.y = (display_rect.height - MIN_SANE_AREA)/2; - work_area.height = MIN_SANE_AREA; - } - else - { - int amount = (MIN_SANE_AREA - work_area.height)/2; - work_area.y -= amount; - work_area.height += 2*amount; - } - } - workspace->work_area_screen = work_area; - meta_topic (META_DEBUG_WORKAREA, - "Computed work area for workspace %d: %d,%d %d x %d", - meta_workspace_index (workspace), - workspace->work_area_screen.x, - workspace->work_area_screen.y, - workspace->work_area_screen.width, - workspace->work_area_screen.height); - - /* Now find the work areas for each monitor */ - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - MetaWorkspaceLogicalMonitorData *data; - - data = meta_workspace_get_logical_monitor_data (workspace, - logical_monitor); - work_area = logical_monitor->rect; - - if (!data->logical_monitor_region) - /* FIXME: constraints.c untested with this, but it might be nice for - * a screen reader or magnifier. - */ - work_area = meta_rect (work_area.x, work_area.y, -1, -1); - else - meta_rectangle_clip_to_region (data->logical_monitor_region, - FIXED_DIRECTION_NONE, - &work_area); - - data->logical_monitor_work_area = work_area; - - meta_topic (META_DEBUG_WORKAREA, - "Computed work area for workspace %d " - "monitor %d: %d,%d %d x %d", - meta_workspace_index (workspace), - logical_monitor->number, - data->logical_monitor_work_area.x, - data->logical_monitor_work_area.y, - data->logical_monitor_work_area.width, - data->logical_monitor_work_area.height); - } - - /* STEP 4: Make sure the screen_region is nonempty (separate from step 2 - * since it relies on step 3). - */ - if (workspace->screen_region == NULL) - { - MetaRectangle *nonempty_region; - nonempty_region = g_new (MetaRectangle, 1); - *nonempty_region = workspace->work_area_screen; - workspace->screen_region = g_list_prepend (NULL, nonempty_region); - } - - /* STEP 5: Cache screen and monitor edges for edge resistance and snapping */ - g_assert (workspace->screen_edges == NULL); - g_assert (workspace->monitor_edges == NULL); - workspace->screen_edges = - meta_rectangle_find_onscreen_edges (&display_rect, - workspace->all_struts); - tmp = NULL; - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - - tmp = g_list_prepend (tmp, &logical_monitor->rect); - } - workspace->monitor_edges = - meta_rectangle_find_nonintersected_monitor_edges (tmp, - workspace->all_struts); - g_list_free (tmp); - - /* We're all done, YAAY! Record that everything has been validated. */ - workspace->work_areas_invalid = FALSE; -} - -static gboolean -strut_lists_equal (GSList *l, - GSList *m) -{ - for (; l && m; l = l->next, m = m->next) - { - MetaStrut *a = l->data; - MetaStrut *b = m->data; - - if (a->side != b->side || - !meta_rectangle_equal (&a->rect, &b->rect)) - return FALSE; - } - - return l == NULL && m == NULL; -} - -/** - * meta_workspace_set_builtin_struts: - * @workspace: a #MetaWorkspace - * @struts: (element-type Meta.Strut) (transfer none): list of #MetaStrut - * - * Sets a list of struts that will be used in addition to the struts - * of the windows in the workspace when computing the work area of - * the workspace. - */ -void -meta_workspace_set_builtin_struts (MetaWorkspace *workspace, - GSList *struts) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaDisplay *display = workspace->display; - MetaRectangle display_rect = { 0 }; - GSList *l; - - meta_display_get_size (display, &display_rect.width, &display_rect.height); - - for (l = struts; l; l = l->next) - { - MetaStrut *strut = l->data; - MetaLogicalMonitor *logical_monitor; - - logical_monitor = - meta_monitor_manager_get_logical_monitor_from_rect (monitor_manager, - &strut->rect); - - switch (strut->side) - { - case META_SIDE_TOP: - if (meta_monitor_manager_get_logical_monitor_neighbor (monitor_manager, - logical_monitor, - META_DISPLAY_UP)) - continue; - - strut->rect.height += strut->rect.y; - strut->rect.y = 0; - break; - case META_SIDE_BOTTOM: - if (meta_monitor_manager_get_logical_monitor_neighbor (monitor_manager, - logical_monitor, - META_DISPLAY_DOWN)) - continue; - - strut->rect.height = display_rect.height - strut->rect.y; - break; - case META_SIDE_LEFT: - if (meta_monitor_manager_get_logical_monitor_neighbor (monitor_manager, - logical_monitor, - META_DISPLAY_LEFT)) - continue; - - strut->rect.width += strut->rect.x; - strut->rect.x = 0; - break; - case META_SIDE_RIGHT: - if (meta_monitor_manager_get_logical_monitor_neighbor (monitor_manager, - logical_monitor, - META_DISPLAY_RIGHT)) - continue; - - strut->rect.width = display_rect.width - strut->rect.x; - break; - } - } - - /* Reordering doesn't actually matter, so we don't catch all - * no-impact changes, but this is just a (possibly unnecessary - * anyways) optimization */ - if (strut_lists_equal (struts, workspace->builtin_struts)) - return; - - workspace_free_builtin_struts (workspace); - workspace->builtin_struts = copy_strut_list (struts); - - meta_workspace_invalidate_work_area (workspace); -} - -void -meta_workspace_get_work_area_for_logical_monitor (MetaWorkspace *workspace, - MetaLogicalMonitor *logical_monitor, - MetaRectangle *area) -{ - meta_workspace_get_work_area_for_monitor (workspace, - logical_monitor->number, - area); -} - -/** - * meta_workspace_get_work_area_for_monitor: - * @workspace: a #MetaWorkspace - * @which_monitor: a monitor index - * @area: (out): location to store the work area - * - * Stores the work area for @which_monitor on @workspace - * in @area. - */ -void -meta_workspace_get_work_area_for_monitor (MetaWorkspace *workspace, - int which_monitor, - MetaRectangle *area) -{ - MetaBackend *backend = meta_get_backend(); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaLogicalMonitor *logical_monitor; - MetaWorkspaceLogicalMonitorData *data; - - logical_monitor = - meta_monitor_manager_get_logical_monitor_from_number (monitor_manager, - which_monitor); - g_return_if_fail (logical_monitor != NULL); - - ensure_work_areas_validated (workspace); - data = meta_workspace_get_logical_monitor_data (workspace, logical_monitor); - - g_return_if_fail (data != NULL); - - *area = data->logical_monitor_work_area; -} - -/** - * meta_workspace_get_work_area_all_monitors: - * @workspace: a #MetaWorkspace - * @area: (out): location to store the work area - * - * Stores the work area in @area. - */ -void -meta_workspace_get_work_area_all_monitors (MetaWorkspace *workspace, - MetaRectangle *area) -{ - ensure_work_areas_validated (workspace); - - *area = workspace->work_area_screen; -} - -GList* -meta_workspace_get_onscreen_region (MetaWorkspace *workspace) -{ - ensure_work_areas_validated (workspace); - - return workspace->screen_region; -} - -GList * -meta_workspace_get_onmonitor_region (MetaWorkspace *workspace, - MetaLogicalMonitor *logical_monitor) -{ - MetaWorkspaceLogicalMonitorData *data; - - ensure_work_areas_validated (workspace); - - data = meta_workspace_get_logical_monitor_data (workspace, logical_monitor); - - return data->logical_monitor_region; -} - -#ifdef WITH_VERBOSE_MODE -static const char * -meta_motion_direction_to_string (MetaMotionDirection direction) -{ - switch (direction) - { - case META_MOTION_UP: - return "Up"; - case META_MOTION_DOWN: - return "Down"; - case META_MOTION_LEFT: - return "Left"; - case META_MOTION_RIGHT: - return "Right"; - case META_MOTION_UP_RIGHT: - return "Up-Right"; - case META_MOTION_DOWN_RIGHT: - return "Down-Right"; - case META_MOTION_UP_LEFT: - return "Up-Left"; - case META_MOTION_DOWN_LEFT: - return "Down-Left"; - } - - return "Unknown"; -} -#endif /* WITH_VERBOSE_MODE */ - -/** - * meta_workspace_get_neighbor: - * @workspace: a #MetaWorkspace - * @direction: a #MetaMotionDirection, relative to @workspace - * - * Calculate and retrieve the workspace that is next to @workspace, - * according to @direction and the current workspace layout, as set - * by meta_screen_override_workspace_layout(). - * - * Returns: (transfer none): the workspace next to @workspace, or - * @workspace itself if the neighbor would be outside the layout - */ -MetaWorkspace* -meta_workspace_get_neighbor (MetaWorkspace *workspace, - MetaMotionDirection direction) -{ - MetaWorkspaceLayout layout; - int i, current_space, num_workspaces; - gboolean ltr; - - current_space = meta_workspace_index (workspace); - num_workspaces = meta_workspace_manager_get_n_workspaces (workspace->manager); - meta_workspace_manager_calc_workspace_layout (workspace->manager, num_workspaces, - current_space, &layout); - - meta_verbose ("Getting neighbor of %d in direction %s", - current_space, meta_motion_direction_to_string (direction)); - - ltr = (meta_get_locale_direction () == META_LOCALE_DIRECTION_LTR); - - switch (direction) - { - case META_MOTION_LEFT: - layout.current_col -= ltr ? 1 : -1; - break; - case META_MOTION_RIGHT: - layout.current_col += ltr ? 1 : -1; - break; - case META_MOTION_UP: - layout.current_row -= 1; - break; - case META_MOTION_DOWN: - layout.current_row += 1; - break; - default:; - } - - if (layout.current_col < 0) - layout.current_col = 0; - if (layout.current_col >= layout.cols) - layout.current_col = layout.cols - 1; - if (layout.current_row < 0) - layout.current_row = 0; - if (layout.current_row >= layout.rows) - layout.current_row = layout.rows - 1; - - i = layout.grid[layout.current_row * layout.cols + layout.current_col]; - - if (i < 0) - i = current_space; - - if (i >= num_workspaces) - meta_bug ("calc_workspace_layout left an invalid (too-high) workspace number %d in the grid", - i); - - meta_verbose ("Neighbor workspace is %d at row %d col %d", - i, layout.current_row, layout.current_col); - - meta_workspace_manager_free_workspace_layout (&layout); - - return meta_workspace_manager_get_workspace_by_index (workspace->manager, i); -} - -const char* -meta_workspace_get_name (MetaWorkspace *workspace) -{ - return meta_prefs_get_workspace_name (meta_workspace_index (workspace)); -} - -void -meta_workspace_focus_default_window (MetaWorkspace *workspace, - MetaWindow *not_this_one, - guint32 timestamp) -{ - if (timestamp == META_CURRENT_TIME) - meta_warning ("META_CURRENT_TIME used to choose focus window; " - "focus window may not be correct."); - - if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK || - !workspace->display->mouse_mode) - focus_ancestor_or_top_window (workspace, not_this_one, timestamp); - else - { - MetaWindow * window; - window = meta_display_get_pointer_window (workspace->display, not_this_one); - if (window && - window->type != META_WINDOW_DOCK && - window->type != META_WINDOW_DESKTOP) - { - if (timestamp == META_CURRENT_TIME) - { - - /* We would like for this to never happen. However, if - * it does happen then we kludge since using META_CURRENT_TIME - * can mean ugly race conditions--and we can avoid these - * by allowing EnterNotify events (which come with - * timestamps) to handle focus. - */ - - meta_topic (META_DEBUG_FOCUS, - "Not focusing mouse window %s because EnterNotify events should handle that", - window->desc); - } - else - { - meta_topic (META_DEBUG_FOCUS, - "Focusing mouse window %s", window->desc); - meta_window_focus (window, timestamp); - } - - if (workspace->display->autoraise_window != window && - meta_prefs_get_auto_raise ()) - { - meta_display_queue_autoraise_callback (workspace->display, window); - } - } - else if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_SLOPPY) - focus_ancestor_or_top_window (workspace, not_this_one, timestamp); - else if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_MOUSE) - { - meta_topic (META_DEBUG_FOCUS, - "Setting focus to no_focus_window, since no valid " - "window to focus found."); - meta_display_unset_input_focus (workspace->display, timestamp); - } - } -} - -static gboolean -find_focusable_ancestor (MetaWindow *window, - gpointer user_data) -{ - MetaWorkspaceFocusableAncestorData *data = user_data; - - if (!window->unmanaging && - window->mapped && - !window->hidden && - meta_window_is_focusable (window) && - meta_window_located_on_workspace (window, data->workspace) && - meta_window_showing_on_its_workspace (window)) - { - data->out_window = window; - return FALSE; - } - - return TRUE; -} - -static gboolean -try_to_set_focus_and_check (MetaWindow *window, - MetaWindow *not_this_one, - uint32_t timestamp) -{ - meta_window_focus (window, timestamp); - - /* meta_focus_window() will not change focus for clients using the - * "globally active input" model of input handling, hence defeating - * the assumption that focus should be changed for such windows. - * See https://tronche.com/gui/x/icccm/sec-4.html#s-4.1.7 - */ - if (meta_window_is_focus_async (window)) - return TRUE; - - /* meta_window_focus() does not guarantee that focus will end up - * where we expect, it can fail for various reasons, better check - * it did not actually changed or even left focus to the window we - * explicitly want to avoid. - */ - if (not_this_one && - meta_display_get_focus_window (window->display) == not_this_one) - { - meta_warning ("Failed to focus window %s while avoiding %s", - window->desc, not_this_one->desc); - - return FALSE; - } - - return TRUE; -} - -/* Focus ancestor of not_this_one if there is one */ -static void -focus_ancestor_or_top_window (MetaWorkspace *workspace, - MetaWindow *not_this_one, - guint32 timestamp) -{ - MetaWindow *window = NULL; - - if (not_this_one) - meta_topic (META_DEBUG_FOCUS, - "Focusing MRU window excluding %s", not_this_one->desc); - else - meta_topic (META_DEBUG_FOCUS, - "Focusing MRU window"); - - /* First, check to see if we need to focus an ancestor of a window */ - if (not_this_one) - { - MetaWindow *ancestor; - MetaWorkspaceFocusableAncestorData data; - - data = (MetaWorkspaceFocusableAncestorData) { - .workspace = workspace, - }; - meta_window_foreach_ancestor (not_this_one, find_focusable_ancestor, &data); - ancestor = data.out_window; - - if (ancestor) - { - meta_topic (META_DEBUG_FOCUS, - "Focusing %s, ancestor of %s", - ancestor->desc, not_this_one->desc); - - if (try_to_set_focus_and_check (ancestor, not_this_one, timestamp)) - { - /* Also raise the window if in click-to-focus */ - if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK) - meta_window_raise (ancestor); - - return; - } - } - } - - window = meta_stack_get_default_focus_window (workspace->display->stack, - workspace, - not_this_one); - - if (window) - { - meta_topic (META_DEBUG_FOCUS, - "Focusing workspace MRU window %s", window->desc); - if (try_to_set_focus_and_check (window, not_this_one, timestamp)) - { - /* Also raise the window if in click-to-focus */ - if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK) - meta_window_raise (window); - - return; - } - } - - meta_topic (META_DEBUG_FOCUS, - "No MRU window to focus found; focusing no_focus_window."); - meta_display_unset_input_focus (workspace->display, timestamp); -} - -/** - * meta_workspace_get_display: - * @workspace: a #MetaWorkspace - * - * Gets the #MetaDisplay that the workspace is part of. - * - * Return value: (transfer none): the #MetaDisplay for the workspace - */ -MetaDisplay * -meta_workspace_get_display (MetaWorkspace *workspace) -{ - return workspace->display; -} diff --git a/src/libmutter.pc.in b/src/libmutter.pc.in deleted file mode 100644 index 8ad9bdb5c..000000000 --- a/src/libmutter.pc.in +++ /dev/null @@ -1,14 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ -apiversion=@LIBMUTTER_API_VERSION@ -girdir=@libdir@/mutter-${apiversion} -typelibdir=@libdir@/mutter-${apiversion} - -Name: libmutter -Description: Mutter window manager library -Requires: gsettings-desktop-schemas gtk+-3.0 mutter-clutter-${apiversion} x11 -Version: @VERSION@ -Libs: -L${libdir} -lmutter-${apiversion} -Cflags: -I${includedir}/mutter-${apiversion} diff --git a/src/meson.build b/src/meson.build deleted file mode 100644 index 8ea2df0fa..000000000 --- a/src/meson.build +++ /dev/null @@ -1,1102 +0,0 @@ -mutter_includesubdir = join_paths(pkgname, 'meta') -mutter_includedir = join_paths(includedir, mutter_includesubdir) - -mutter_includes = [ - include_directories('.'), - top_includepath, - clutter_includepath, - cogl_includepath, -] - -mutter_lib_deps = [ - m_dep, -] - -mutter_pkg_deps = [ - cairo_dep, - gio_unix_dep, - glib_dep, - gsettings_desktop_schemas_dep, - gtk3_dep, - pango_dep, -] - -mutter_pkg_private_deps = [ - gmodule_no_export_dep, - gnome_desktop_dep, - gnome_settings_daemon_dep, - json_glib_dep, - libcanberra_dep, - xkbcommon_dep, -] - -if have_gl - mutter_pkg_deps += [ - gl_dep, - ] -endif - -if have_gles2 - mutter_pkg_private_deps += [ - gles2_dep, - ] -endif - -if have_egl - mutter_pkg_deps += [ - egl_dep, - ] -endif - -if have_libgudev - mutter_pkg_private_deps += [ - gudev_dep, - libudev_dep, - ] -endif - -if have_startup_notification - mutter_pkg_private_deps += [ - libstartup_notification_dep, - ] -endif - -if have_libwacom - mutter_pkg_private_deps += [ - libwacom_dep, - ] -endif - -if have_remote_desktop - mutter_pkg_private_deps += [ - libpipewire_dep, - ] -endif - -if have_introspection - mutter_pkg_private_deps += [ - gobject_introspection_dep, - ] -endif - -if have_x11 - mutter_pkg_deps += [ - xfixes_dep, - xi_dep, - x11_dep, - ] - - mutter_pkg_private_deps += [ - xrandr_dep, - xinerama_dep, - xext_dep, - ice_dep, - xcomposite_dep, - xcursor_dep, - xdamage_dep, - xkbfile_dep, - xkeyboard_config_dep, - xkbcommon_x11_dep, - xrender_dep, - x11_xcb_dep, - xcb_randr_dep, - xcb_res_dep, - xau_dep, - xtst_dep, - ] - - if have_sm - mutter_pkg_private_deps += [ - sm_dep, - ] - endif -endif - -if have_wayland - mutter_pkg_deps += [ - wayland_server_dep, - ] -endif - -if have_native_backend - mutter_pkg_private_deps += [ - libdrm_dep, - libinput_dep, - gudev_dep, - libgbm_dep, - logind_provider_dep, - libudev_dep, - xkbcommon_dep, - ] -endif - -if have_wayland_eglstream - mutter_lib_deps += [ - dl_dep, - ] - mutter_pkg_private_deps += [ - wayland_eglstream_protocols_dep, - ] -endif - -mutter_deps = [ - mutter_pkg_deps, - mutter_pkg_private_deps, - mutter_lib_deps, -] - -mutter_c_args = [ - '-DCLUTTER_ENABLE_COMPOSITOR_API', - '-DCOGL_ENABLE_EXPERIMENTAL_API', - '-DCOGL_ENABLE_EXPERIMENTAL_2_0_API', - '-DCOGL_ENABLE_MUTTER_API', - '-DCLUTTER_DISABLE_DEPRECATION_WARNINGS', - '-DCOGL_DISABLE_DEPRECATION_WARNINGS', - '-DG_LOG_DOMAIN="mutter"', - '-DSN_API_NOT_YET_FROZEN=1', - '-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name()), -] - -if get_option('verbose') - mutter_c_args += [ - '-DWITH_VERBOSE_MODE' - ] -endif - -mutter_sources = [ - 'backends/edid.h', - 'backends/edid-parse.c', - 'backends/gsm-inhibitor-flag.h', - 'backends/meta-backend.c', - 'backends/meta-backend-private.h', - 'backends/meta-barrier.c', - 'backends/meta-barrier-private.h', - 'backends/meta-crtc-mode.c', - 'backends/meta-crtc-mode.h', - 'backends/meta-crtc.c', - 'backends/meta-crtc.h', - 'backends/meta-cursor.c', - 'backends/meta-cursor.h', - 'backends/meta-cursor-renderer.c', - 'backends/meta-cursor-renderer.h', - 'backends/meta-cursor-sprite-xcursor.c', - 'backends/meta-cursor-sprite-xcursor.h', - 'backends/meta-cursor-tracker.c', - 'backends/meta-cursor-tracker-private.h', - 'backends/meta-display-config-shared.h', - 'backends/meta-dnd-private.h', - 'backends/meta-gpu.c', - 'backends/meta-gpu.h', - 'backends/meta-idle-monitor.c', - 'backends/meta-idle-manager.c', - 'backends/meta-idle-manager.h', - 'backends/meta-idle-monitor-private.h', - 'backends/meta-input-device.c', - 'backends/meta-input-mapper.c', - 'backends/meta-input-mapper-private.h', - 'backends/meta-input-settings.c', - 'backends/meta-input-settings-private.h', - 'backends/meta-input-settings-dummy.c', - 'backends/meta-input-settings-dummy.h', - 'backends/meta-keymap-utils.c', - 'backends/meta-keymap-utils.h', - 'backends/meta-logical-monitor.c', - 'backends/meta-logical-monitor.h', - 'backends/meta-monitor.c', - 'backends/meta-monitor-config-manager.c', - 'backends/meta-monitor-config-manager.h', - 'backends/meta-monitor-config-migration.c', - 'backends/meta-monitor-config-migration.h', - 'backends/meta-monitor-config-store.c', - 'backends/meta-monitor-config-store.h', - 'backends/meta-monitor.h', - 'backends/meta-monitor-manager.c', - 'backends/meta-monitor-manager-dummy.c', - 'backends/meta-monitor-manager-dummy.h', - 'backends/meta-monitor-manager-private.h', - 'backends/meta-monitor-transform.c', - 'backends/meta-monitor-transform.h', - 'backends/meta-orientation-manager.c', - 'backends/meta-orientation-manager.h', - 'backends/meta-output.c', - 'backends/meta-output.h', - 'backends/meta-pointer-constraint.c', - 'backends/meta-pointer-constraint.h', - 'backends/meta-remote-access-controller-private.h', - 'backends/meta-remote-access-controller.c', - 'backends/meta-renderer.c', - 'backends/meta-renderer.h', - 'backends/meta-renderer-view.c', - 'backends/meta-renderer-view.h', - 'backends/meta-screen-cast-window.c', - 'backends/meta-screen-cast-window.h', - 'backends/meta-settings.c', - 'backends/meta-settings-private.h', - 'backends/meta-stage.c', - 'backends/meta-stage-impl.c', - 'backends/meta-stage-impl-private.h', - 'backends/meta-stage-private.h', - 'backends/meta-stage-view.c', - 'backends/meta-stage-view-private.h', - 'backends/meta-viewport-info.c', - 'backends/meta-viewport-info.h', - 'backends/meta-virtual-monitor.c', - 'backends/meta-virtual-monitor.h', - 'backends/x11/cm/meta-backend-x11-cm.c', - 'backends/x11/cm/meta-backend-x11-cm.h', - 'backends/x11/cm/meta-cursor-sprite-xfixes.c', - 'backends/x11/cm/meta-cursor-sprite-xfixes.h', - 'backends/x11/cm/meta-renderer-x11-cm.c', - 'backends/x11/cm/meta-renderer-x11-cm.h', - 'backends/x11/meta-backend-x11.c', - 'backends/x11/meta-backend-x11.h', - 'backends/x11/meta-barrier-x11.c', - 'backends/x11/meta-barrier-x11.h', - 'backends/x11/meta-clutter-backend-x11.c', - 'backends/x11/meta-clutter-backend-x11.h', - 'backends/x11/meta-crtc-xrandr.c', - 'backends/x11/meta-crtc-xrandr.h', - 'backends/x11/meta-cursor-renderer-x11.c', - 'backends/x11/meta-cursor-renderer-x11.h', - 'backends/x11/meta-cursor-tracker-x11.c', - 'backends/x11/meta-cursor-tracker-x11.h', - 'backends/x11/meta-event-x11.c', - 'backends/x11/meta-event-x11.h', - 'backends/x11/meta-gpu-xrandr.c', - 'backends/x11/meta-gpu-xrandr.h', - 'backends/x11/meta-input-device-x11.c', - 'backends/x11/meta-input-device-x11.h', - 'backends/x11/meta-input-device-tool-x11.c', - 'backends/x11/meta-input-device-tool-x11.h', - 'backends/x11/meta-input-settings-x11.c', - 'backends/x11/meta-input-settings-x11.h', - 'backends/x11/meta-seat-x11.c', - 'backends/x11/meta-seat-x11.h', - 'backends/x11/meta-keymap-x11.c', - 'backends/x11/meta-keymap-x11.h', - 'backends/x11/meta-monitor-manager-xrandr.c', - 'backends/x11/meta-monitor-manager-xrandr.h', - 'backends/x11/meta-output-xrandr.c', - 'backends/x11/meta-output-xrandr.h', - 'backends/x11/meta-renderer-x11.c', - 'backends/x11/meta-renderer-x11.h', - 'backends/x11/meta-stage-x11.c', - 'backends/x11/meta-stage-x11.h', - 'backends/x11/meta-virtual-input-device-x11.c', - 'backends/x11/meta-virtual-input-device-x11.h', - 'backends/x11/meta-xkb-a11y-x11.c', - 'backends/x11/meta-xkb-a11y-x11.h', - 'backends/x11/nested/meta-backend-x11-nested.c', - 'backends/x11/nested/meta-backend-x11-nested.h', - 'backends/x11/nested/meta-cursor-renderer-x11-nested.c', - 'backends/x11/nested/meta-cursor-renderer-x11-nested.h', - 'backends/x11/nested/meta-stage-x11-nested.c', - 'backends/x11/nested/meta-stage-x11-nested.h', - 'backends/x11/nested/meta-renderer-x11-nested.c', - 'backends/x11/nested/meta-renderer-x11-nested.h', - 'compositor/clutter-utils.c', - 'compositor/clutter-utils.h', - 'compositor/cogl-utils.c', - 'compositor/cogl-utils.h', - 'compositor/compositor.c', - 'compositor/compositor-private.h', - 'compositor/meta-background-actor.c', - 'compositor/meta-background-actor-private.h', - 'compositor/meta-background-content.c', - 'compositor/meta-background-content-private.h', - 'compositor/meta-background.c', - 'compositor/meta-background-group.c', - 'compositor/meta-background-image.c', - 'compositor/meta-background-private.h', - 'compositor/meta-compositor-server.c', - 'compositor/meta-compositor-server.h', - 'compositor/meta-compositor-x11.c', - 'compositor/meta-compositor-x11.h', - 'compositor/meta-cullable.c', - 'compositor/meta-cullable.h', - 'compositor/meta-dnd-actor.c', - 'compositor/meta-dnd-actor-private.h', - 'compositor/meta-dnd.c', - 'compositor/meta-feedback-actor.c', - 'compositor/meta-feedback-actor-private.h', - 'compositor/meta-later.c', - 'compositor/meta-module.c', - 'compositor/meta-module.h', - 'compositor/meta-plugin.c', - 'compositor/meta-plugin-manager.c', - 'compositor/meta-plugin-manager.h', - 'compositor/meta-shadow-factory.c', - 'compositor/meta-shaped-texture.c', - 'compositor/meta-shaped-texture-private.h', - 'compositor/meta-surface-actor.c', - 'compositor/meta-surface-actor.h', - 'compositor/meta-surface-actor-x11.c', - 'compositor/meta-surface-actor-x11.h', - 'compositor/meta-sync-ring.c', - 'compositor/meta-sync-ring.h', - 'compositor/meta-texture-tower.c', - 'compositor/meta-texture-tower.h', - 'compositor/meta-window-actor.c', - 'compositor/meta-window-actor-private.h', - 'compositor/meta-window-actor-x11.c', - 'compositor/meta-window-actor-x11.h', - 'compositor/meta-window-group.c', - 'compositor/meta-window-group-private.h', - 'compositor/meta-window-shape.c', - 'compositor/region-utils.c', - 'compositor/region-utils.h', - 'core/bell.c', - 'core/bell.h', - 'core/boxes.c', - 'core/boxes-private.h', - 'core/constraints.c', - 'core/constraints.h', - 'core/delete.c', - 'core/display.c', - 'core/display-private.h', - 'core/edge-resistance.c', - 'core/edge-resistance.h', - 'core/events.c', - 'core/events.h', - 'core/frame.c', - 'core/frame.h', - 'core/keybindings.c', - 'core/keybindings-private.h', - 'core/meta-accel-parse.c', - 'core/meta-accel-parse.h', - 'core/meta-anonymous-file.c', - 'core/meta-anonymous-file.h', - 'core/meta-border.c', - 'core/meta-border.h', - 'core/meta-clipboard-manager.c', - 'core/meta-clipboard-manager.h', - 'core/meta-close-dialog.c', - 'core/meta-close-dialog-default.c', - 'core/meta-close-dialog-default-private.h', - 'core/meta-context-main.c', - 'core/meta-context-main.h', - 'core/meta-context-private.h', - 'core/meta-context.c', - 'core/meta-fraction.c', - 'core/meta-fraction.h', - 'core/meta-gesture-tracker.c', - 'core/meta-gesture-tracker-private.h', - 'core/meta-inhibit-shortcuts-dialog.c', - 'core/meta-inhibit-shortcuts-dialog-default.c', - 'core/meta-inhibit-shortcuts-dialog-default-private.h', - 'core/meta-launch-context.c', - 'core/meta-pad-action-mapper.c', - 'core/meta-private-enums.h', - 'core/meta-selection.c', - 'core/meta-selection-source.c', - 'core/meta-selection-source-memory.c', - 'core/meta-sound-player.c', - 'core/meta-workspace-manager.c', - 'core/meta-workspace-manager-private.h', - 'core/place.c', - 'core/place.h', - 'core/prefs-private.h', - 'core/prefs.c', - 'core/restart.c', - 'core/stack.c', - 'core/stack.h', - 'core/stack-tracker.c', - 'core/stack-tracker.h', - 'core/startup-notification.c', - 'core/startup-notification-private.h', - 'core/util.c', - 'core/util-private.h', - 'core/window.c', - 'core/window-private.h', - 'core/workspace.c', - 'core/workspace-private.h', - 'ui/frames.c', - 'ui/frames.h', - 'ui/theme.c', - 'ui/theme-private.h', - 'ui/ui.c', - 'ui/ui.h', - 'x11/atomnames.h', - 'x11/events.c', - 'x11/events.h', - 'x11/group.c', - 'x11/group-private.h', - 'x11/group-props.c', - 'x11/group-props.h', - 'x11/iconcache.c', - 'x11/iconcache.h', - 'x11/meta-selection-source-x11.c', - 'x11/meta-selection-source-x11-private.h', - 'x11/meta-startup-notification-x11.c', - 'x11/meta-startup-notification-x11.h', - 'x11/meta-x11-display.c', - 'x11/meta-x11-display-private.h', - 'x11/meta-x11-errors.c', - 'x11/meta-x11-selection.c', - 'x11/meta-x11-selection-private.h', - 'x11/meta-x11-selection-input-stream.c', - 'x11/meta-x11-selection-input-stream-private.h', - 'x11/meta-x11-selection-output-stream.c', - 'x11/meta-x11-selection-output-stream-private.h', - 'x11/meta-x11-stack.c', - 'x11/meta-x11-stack-private.h', - 'x11/meta-x11-window-control.c', - 'x11/meta-x11-window-control.h', - 'x11/mutter-Xatomtype.h', - 'x11/session.c', - 'x11/session.h', - 'x11/window-props.c', - 'x11/window-props.h', - 'x11/window-x11.c', - 'x11/window-x11.h', - 'x11/window-x11-private.h', - 'x11/xprops.c', - 'x11/xprops.h', -] - -if have_egl - mutter_sources += [ - 'backends/meta-egl.c', - 'backends/meta-egl-ext.h', - 'backends/meta-egl.h', - ] -endif - -if have_gles2 - mutter_sources += [ - 'backends/meta-gles3.c', - 'backends/meta-gles3.h', - 'backends/meta-gles3-table.h', - ] -endif - -if have_remote_desktop - mutter_sources += [ - 'backends/meta-dbus-session-watcher.c', - 'backends/meta-dbus-session-watcher.h', - 'backends/meta-remote-desktop.c', - 'backends/meta-remote-desktop.h', - 'backends/meta-remote-desktop-session.c', - 'backends/meta-remote-desktop-session.h', - 'backends/meta-screen-cast.c', - 'backends/meta-screen-cast.h', - 'backends/meta-screen-cast-area-stream.c', - 'backends/meta-screen-cast-area-stream.h', - 'backends/meta-screen-cast-area-stream-src.c', - 'backends/meta-screen-cast-area-stream-src.h', - 'backends/meta-screen-cast-monitor-stream.c', - 'backends/meta-screen-cast-monitor-stream.h', - 'backends/meta-screen-cast-monitor-stream-src.c', - 'backends/meta-screen-cast-monitor-stream-src.h', - 'backends/meta-screen-cast-virtual-stream-src.c', - 'backends/meta-screen-cast-virtual-stream-src.h', - 'backends/meta-screen-cast-virtual-stream.c', - 'backends/meta-screen-cast-virtual-stream.h', - 'backends/meta-screen-cast-window-stream-src.c', - 'backends/meta-screen-cast-window-stream-src.h', - 'backends/meta-screen-cast-window-stream.c', - 'backends/meta-screen-cast-window-stream.h', - 'backends/meta-screen-cast-session.c', - 'backends/meta-screen-cast-session.h', - 'backends/meta-screen-cast-stream.c', - 'backends/meta-screen-cast-stream.h', - 'backends/meta-screen-cast-stream-src.c', - 'backends/meta-screen-cast-stream-src.h', - 'core/meta-selection-source-remote.c', - 'core/meta-selection-source-remote.h', - ] -endif - -if have_wayland - mutter_sources += [ - 'compositor/meta-surface-actor-wayland.c', - 'compositor/meta-surface-actor-wayland.h', - 'compositor/meta-window-actor-wayland.c', - 'compositor/meta-window-actor-wayland.h', - 'wayland/meta-cursor-sprite-wayland.c', - 'wayland/meta-cursor-sprite-wayland.h', - 'wayland/meta-pointer-confinement-wayland.c', - 'wayland/meta-pointer-confinement-wayland.h', - 'wayland/meta-pointer-lock-wayland.c', - 'wayland/meta-pointer-lock-wayland.h', - 'wayland/meta-selection-source-wayland.c', - 'wayland/meta-selection-source-wayland-private.h', - 'wayland/meta-wayland-activation.c', - 'wayland/meta-wayland-activation.h', - 'wayland/meta-wayland-actor-surface.c', - 'wayland/meta-wayland-actor-surface.h', - 'wayland/meta-wayland-buffer.c', - 'wayland/meta-wayland-buffer.h', - 'wayland/meta-wayland.c', - 'wayland/meta-wayland-client.c', - 'wayland/meta-wayland-cursor-surface.c', - 'wayland/meta-wayland-cursor-surface.h', - 'wayland/meta-wayland-data-device.c', - 'wayland/meta-wayland-data-device.h', - 'wayland/meta-wayland-data-device-primary.c', - 'wayland/meta-wayland-data-device-primary.h', - 'wayland/meta-wayland-data-device-primary-legacy.c', - 'wayland/meta-wayland-data-device-primary-legacy.h', - 'wayland/meta-wayland-data-offer.c', - 'wayland/meta-wayland-data-offer.h', - 'wayland/meta-wayland-data-offer-primary.c', - 'wayland/meta-wayland-data-offer-primary.h', - 'wayland/meta-wayland-data-offer-primary-legacy.c', - 'wayland/meta-wayland-data-offer-primary-legacy.h', - 'wayland/meta-wayland-data-source.c', - 'wayland/meta-wayland-data-source.h', - 'wayland/meta-wayland-data-source-primary.c', - 'wayland/meta-wayland-data-source-primary.h', - 'wayland/meta-wayland-data-source-primary-legacy.c', - 'wayland/meta-wayland-data-source-primary-legacy.h', - 'wayland/meta-wayland-dma-buf.c', - 'wayland/meta-wayland-dma-buf.h', - 'wayland/meta-wayland-dnd-surface.c', - 'wayland/meta-wayland-dnd-surface.h', - 'wayland/meta-wayland-gtk-shell.c', - 'wayland/meta-wayland-gtk-shell.h', - 'wayland/meta-wayland.h', - 'wayland/meta-wayland-inhibit-shortcuts.c', - 'wayland/meta-wayland-inhibit-shortcuts-dialog.c', - 'wayland/meta-wayland-inhibit-shortcuts-dialog.h', - 'wayland/meta-wayland-inhibit-shortcuts.h', - 'wayland/meta-wayland-input-device.c', - 'wayland/meta-wayland-input-device.h', - 'wayland/meta-wayland-keyboard.c', - 'wayland/meta-wayland-keyboard.h', - 'wayland/meta-wayland-legacy-xdg-shell.c', - 'wayland/meta-wayland-legacy-xdg-shell.h', - 'wayland/meta-wayland-outputs.c', - 'wayland/meta-wayland-outputs.h', - 'wayland/meta-wayland-pointer.c', - 'wayland/meta-wayland-pointer-constraints.c', - 'wayland/meta-wayland-pointer-constraints.h', - 'wayland/meta-wayland-pointer-gesture-pinch.c', - 'wayland/meta-wayland-pointer-gesture-pinch.h', - 'wayland/meta-wayland-pointer-gestures.c', - 'wayland/meta-wayland-pointer-gestures.h', - 'wayland/meta-wayland-pointer-gesture-swipe.c', - 'wayland/meta-wayland-pointer-gesture-swipe.h', - 'wayland/meta-wayland-pointer.h', - 'wayland/meta-wayland-popup.c', - 'wayland/meta-wayland-popup.h', - 'wayland/meta-wayland-presentation-time.c', - 'wayland/meta-wayland-presentation-time-private.h', - 'wayland/meta-wayland-private.h', - 'wayland/meta-wayland-region.c', - 'wayland/meta-wayland-region.h', - 'wayland/meta-wayland-seat.c', - 'wayland/meta-wayland-seat.h', - 'wayland/meta-wayland-shell-surface.c', - 'wayland/meta-wayland-shell-surface.h', - 'wayland/meta-wayland-subsurface.c', - 'wayland/meta-wayland-subsurface.h', - 'wayland/meta-wayland-surface.c', - 'wayland/meta-wayland-surface.h', - 'wayland/meta-wayland-tablet.c', - 'wayland/meta-wayland-tablet-cursor-surface.c', - 'wayland/meta-wayland-tablet-cursor-surface.h', - 'wayland/meta-wayland-tablet.h', - 'wayland/meta-wayland-tablet-manager.c', - 'wayland/meta-wayland-tablet-manager.h', - 'wayland/meta-wayland-tablet-pad.c', - 'wayland/meta-wayland-tablet-pad-group.c', - 'wayland/meta-wayland-tablet-pad-group.h', - 'wayland/meta-wayland-tablet-pad.h', - 'wayland/meta-wayland-tablet-pad-ring.c', - 'wayland/meta-wayland-tablet-pad-ring.h', - 'wayland/meta-wayland-tablet-pad-strip.c', - 'wayland/meta-wayland-tablet-pad-strip.h', - 'wayland/meta-wayland-tablet-seat.c', - 'wayland/meta-wayland-tablet-seat.h', - 'wayland/meta-wayland-tablet-tool.c', - 'wayland/meta-wayland-tablet-tool.h', - 'wayland/meta-wayland-text-input.c', - 'wayland/meta-wayland-text-input.h', - 'wayland/meta-wayland-text-input-legacy.c', - 'wayland/meta-wayland-text-input-legacy.h', - 'wayland/meta-wayland-touch.c', - 'wayland/meta-wayland-touch.h', - 'wayland/meta-wayland-types.h', - 'wayland/meta-wayland-versions.h', - 'wayland/meta-wayland-viewporter.c', - 'wayland/meta-wayland-viewporter.h', - 'wayland/meta-wayland-window-configuration.c', - 'wayland/meta-wayland-window-configuration.h', - 'wayland/meta-wayland-wl-shell.c', - 'wayland/meta-wayland-wl-shell.h', - 'wayland/meta-wayland-xdg-foreign.c', - 'wayland/meta-wayland-xdg-foreign.h', - 'wayland/meta-wayland-xdg-shell.c', - 'wayland/meta-wayland-xdg-shell.h', - 'wayland/meta-window-wayland.c', - 'wayland/meta-window-wayland.h', - 'wayland/meta-window-xwayland.c', - 'wayland/meta-window-xwayland.h', - 'wayland/meta-xwayland.c', - 'wayland/meta-xwayland-grab-keyboard.c', - 'wayland/meta-xwayland-grab-keyboard.h', - 'wayland/meta-xwayland.h', - 'wayland/meta-xwayland-private.h', - 'wayland/meta-xwayland-dnd.c', - 'wayland/meta-xwayland-dnd-private.h', - 'wayland/meta-xwayland-surface.c', - 'wayland/meta-xwayland-surface.h', - ] -endif - -if have_native_backend - mutter_sources += [ - 'backends/native/dbus-utils.c', - 'backends/native/dbus-utils.h', - 'backends/native/meta-backend-native.c', - 'backends/native/meta-backend-native.h', - 'backends/native/meta-backend-native-private.h', - 'backends/native/meta-backend-native-types.h', - 'backends/native/meta-barrier-native.c', - 'backends/native/meta-barrier-native.h', - 'backends/native/meta-clutter-backend-native.c', - 'backends/native/meta-clutter-backend-native.h', - 'backends/native/meta-cogl-utils.c', - 'backends/native/meta-cogl-utils.h', - 'backends/native/meta-crtc-kms.c', - 'backends/native/meta-crtc-kms.h', - 'backends/native/meta-crtc-native.c', - 'backends/native/meta-crtc-native.h', - 'backends/native/meta-crtc-mode-kms.c', - 'backends/native/meta-crtc-mode-kms.h', - 'backends/native/meta-crtc-mode-virtual.c', - 'backends/native/meta-crtc-mode-virtual.h', - 'backends/native/meta-crtc-virtual.c', - 'backends/native/meta-crtc-virtual.h', - 'backends/native/meta-cursor-renderer-native.c', - 'backends/native/meta-cursor-renderer-native.h', - 'backends/native/meta-device-pool-private.h', - 'backends/native/meta-device-pool.c', - 'backends/native/meta-device-pool.h', - 'backends/native/meta-drm-buffer-dumb.c', - 'backends/native/meta-drm-buffer-dumb.h', - 'backends/native/meta-drm-buffer-gbm.c', - 'backends/native/meta-drm-buffer-gbm.h', - 'backends/native/meta-drm-buffer-import.c', - 'backends/native/meta-drm-buffer-import.h', - 'backends/native/meta-drm-buffer-private.h', - 'backends/native/meta-drm-buffer.c', - 'backends/native/meta-drm-buffer.h', - 'backends/native/meta-gpu-kms.c', - 'backends/native/meta-gpu-kms.h', - 'backends/native/meta-input-device-native.c', - 'backends/native/meta-input-device-native.h', - 'backends/native/meta-input-device-tool-native.c', - 'backends/native/meta-input-device-tool-native.h', - 'backends/native/meta-input-settings-native.c', - 'backends/native/meta-input-settings-native.h', - 'backends/native/meta-keymap-native.c', - 'backends/native/meta-keymap-native.h', - 'backends/native/meta-launcher.c', - 'backends/native/meta-launcher.h', - 'backends/native/meta-monitor-manager-native.c', - 'backends/native/meta-monitor-manager-native.h', - 'backends/native/meta-output-kms.c', - 'backends/native/meta-output-kms.h', - 'backends/native/meta-output-native.c', - 'backends/native/meta-output-native.h', - 'backends/native/meta-output-virtual.c', - 'backends/native/meta-output-virtual.h', - 'backends/native/meta-kms-connector-private.h', - 'backends/native/meta-kms-connector.c', - 'backends/native/meta-kms-connector.h', - 'backends/native/meta-kms-crtc-private.h', - 'backends/native/meta-kms-crtc.c', - 'backends/native/meta-kms-crtc.h', - 'backends/native/meta-kms-device-private.h', - 'backends/native/meta-kms-device.c', - 'backends/native/meta-kms-device.h', - 'backends/native/meta-kms-impl-device-atomic.c', - 'backends/native/meta-kms-impl-device-atomic.h', - 'backends/native/meta-kms-impl-device-dummy.c', - 'backends/native/meta-kms-impl-device-dummy.h', - 'backends/native/meta-kms-impl-device-simple.c', - 'backends/native/meta-kms-impl-device-simple.h', - 'backends/native/meta-kms-impl-device.c', - 'backends/native/meta-kms-impl-device.h', - 'backends/native/meta-kms-impl.c', - 'backends/native/meta-kms-impl.h', - 'backends/native/meta-kms-mode.c', - 'backends/native/meta-kms-mode.h', - 'backends/native/meta-kms-page-flip.c', - 'backends/native/meta-kms-page-flip-private.h', - 'backends/native/meta-kms-plane.c', - 'backends/native/meta-kms-plane-private.h', - 'backends/native/meta-kms-plane.h', - 'backends/native/meta-kms-private.h', - 'backends/native/meta-kms-types.h', - 'backends/native/meta-kms-update-private.h', - 'backends/native/meta-kms-update.c', - 'backends/native/meta-kms-update.h', - 'backends/native/meta-kms-utils.c', - 'backends/native/meta-kms-utils.h', - 'backends/native/meta-kms.c', - 'backends/native/meta-kms.h', - 'backends/native/meta-onscreen-native.c', - 'backends/native/meta-onscreen-native.h', - 'backends/native/meta-pointer-constraint-native.c', - 'backends/native/meta-pointer-constraint-native.h', - 'backends/native/meta-renderer-native-gles3.c', - 'backends/native/meta-renderer-native-gles3.h', - 'backends/native/meta-renderer-native-private.h', - 'backends/native/meta-renderer-native.c', - 'backends/native/meta-renderer-native.h', - 'backends/native/meta-seat-impl.c', - 'backends/native/meta-seat-impl.h', - 'backends/native/meta-seat-native.c', - 'backends/native/meta-seat-native.h', - 'backends/native/meta-stage-native.c', - 'backends/native/meta-stage-native.h', - 'backends/native/meta-udev.c', - 'backends/native/meta-udev.h', - 'backends/native/meta-virtual-input-device-native.c', - 'backends/native/meta-virtual-input-device-native.h', - 'backends/native/meta-virtual-monitor-native.c', - 'backends/native/meta-virtual-monitor-native.h', - 'backends/native/meta-xkb-utils.c', - 'backends/native/meta-xkb-utils.h', - 'compositor/meta-compositor-native.c', - 'compositor/meta-compositor-native.h', - ] -endif - -if have_wayland_eglstream - mutter_sources += [ - 'wayland/meta-wayland-egl-stream.c', - 'wayland/meta-wayland-egl-stream.h', - ] -endif - -mutter_private_enum_sources = [] - -if have_remote_desktop - mutter_private_enum_sources += [ - 'backends/meta-screen-cast.h', - ] -endif - -if have_native_backend - mutter_private_enum_sources += [ - 'backends/native/meta-backend-native-types.h', - 'backends/native/meta-kms-types.h', - ] -endif - -mutter_built_sources = [] - -if mutter_private_enum_sources.length() > 0 - mutter_private_enum_types = gnome.mkenums('meta-private-enum-types', - sources: mutter_private_enum_sources, - c_template: 'meta-private-enum-types.c.in', - h_template: 'meta-private-enum-types.h.in', - ) - - mutter_built_sources += mutter_private_enum_types -endif - -dbus_display_config_built_sources = gnome.gdbus_codegen('meta-dbus-display-config', - 'org.gnome.Mutter.DisplayConfig.xml', - interface_prefix: 'org.gnome.Mutter.', - namespace: 'MetaDBus', - ) -mutter_built_sources += dbus_display_config_built_sources - -dbus_idle_monitor_built_sources = gnome.gdbus_codegen('meta-dbus-idle-monitor', - 'org.gnome.Mutter.IdleMonitor.xml', - interface_prefix: 'org.gnome.Mutter.', - namespace: 'MetaDBus', - object_manager: true, - ) -mutter_built_sources += dbus_idle_monitor_built_sources - -if have_profiler - mutter_sources += [ - 'backends/meta-profiler.c', - 'backends/meta-profiler.h', - ] - - if sysprof_dep.type_name() == 'pkgconfig' - sysprof_dbus_interfaces_dir = join_paths(sysprof_dep.get_pkgconfig_variable('datadir'), 'dbus-1', 'interfaces') - else - sysprof_dbus_interfaces_dir = join_paths(meson.source_root(), 'subprojects', 'sysprof', 'src') - endif - - sysprof3_dbus_file = join_paths(sysprof_dbus_interfaces_dir, 'org.gnome.Sysprof3.Profiler.xml') - dbus_sysprof3_profiler_built_sources = gnome.gdbus_codegen('meta-dbus-sysprof3-profiler', - sysprof3_dbus_file, - interface_prefix: 'org.gnome.', - namespace: 'MetaDBus', - ) - mutter_built_sources += dbus_sysprof3_profiler_built_sources -endif - -if have_native_backend - cvt = find_program('cvt') - - gen_default_modes = find_program('backends/native/gen-default-modes.py') - default_modes_h = custom_target('meta-default-modes', - output: 'meta-default-modes.h', - command: [gen_default_modes, '@OUTPUT@'] - ) - mutter_built_sources += default_modes_h - - dbus_login1_built_sources = gnome.gdbus_codegen('meta-dbus-login1', - 'org.freedesktop.login1.xml', - interface_prefix: 'org.freedesktop.login1.', - namespace: 'MetaDbusLogin1', - ) - mutter_built_sources += dbus_login1_built_sources -endif - -if have_remote_desktop - dbus_remote_desktop_built_sources = gnome.gdbus_codegen('meta-dbus-remote-desktop', - 'org.gnome.Mutter.RemoteDesktop.xml', - interface_prefix: 'org.gnome.Mutter.', - namespace: 'MetaDBus', - ) - mutter_built_sources += dbus_remote_desktop_built_sources - - dbus_screen_cast_built_sources = gnome.gdbus_codegen('meta-dbus-screen-cast', - 'org.gnome.Mutter.ScreenCast.xml', - interface_prefix: 'org.gnome.Mutter.', - namespace: 'MetaDBus', - ) - mutter_built_sources += dbus_screen_cast_built_sources -endif - -wayland_protocol_server_headers = [] -wayland_protocol_client_headers = [] -wayland_protocol_sources = [] - -if have_wayland - # Format: - # - protocol name - # - protocol stability ('private', 'stable' or 'unstable') - # - protocol version (if stability is 'unstable') - wayland_protocols = [ - ['gtk-primary-selection', 'private', ], - ['gtk-shell', 'private', ], - ['gtk-text-input', 'private', ], - ['keyboard-shortcuts-inhibit', 'unstable', 'v1', ], - ['linux-dmabuf', 'unstable', 'v1', ], - ['pointer-constraints', 'unstable', 'v1', ], - ['pointer-gestures', 'unstable', 'v1', ], - ['presentation-time', 'stable', ], - ['primary-selection', 'unstable', 'v1', ], - ['relative-pointer', 'unstable', 'v1', ], - ['tablet', 'unstable', 'v2', ], - ['text-input', 'unstable', 'v3', ], - ['viewporter', 'stable', ], - ['xdg-activation', 'staging', 'v1', ], - ['xdg-foreign', 'unstable', 'v1', ], - ['xdg-output', 'unstable', 'v1', ], - ['xdg-shell', 'unstable', 'v6', ], - ['xdg-shell', 'stable', ], - ['xwayland-keyboard-grab', 'unstable', 'v1', ], - ] - if have_wayland_eglstream - wayland_eglstream_protocols_dir = wayland_eglstream_protocols_dep.get_pkgconfig_variable('pkgdatadir') - wayland_protocols += [ - ['wayland-eglstream-controller', 'third-party', wayland_eglstream_protocols_dir], - ] - endif - - wayland_scanner = find_program('wayland-scanner') - protocols_dir = wayland_protocols_dep.get_pkgconfig_variable('pkgdatadir') - assert(protocols_dir != '', 'Could not get pkgdatadir from wayland-protocols.pc') - - foreach p: wayland_protocols - protocol_name = p.get(0) - protocol_type = p.get(1) - - if protocol_type == 'stable' - output_base = protocol_name - input = join_paths(protocols_dir, - '@0@/@1@/@2@.xml'.format(protocol_type, - protocol_name, - output_base)) - elif protocol_type == 'staging' - protocol_version = p.get(2) - output_base = '@0@-@1@'.format(protocol_name, protocol_version) - input = join_paths(protocols_dir, - '@0@/@1@/@2@.xml'.format(protocol_type, - protocol_name, - output_base)) - elif protocol_type == 'private' - output_base = protocol_name - input = 'wayland/protocol/@0@.xml'.format(protocol_name) - elif protocol_type == 'third-party' - output_base = protocol_name - protocol_dir = p.get(2) - input = join_paths(protocol_dir, '@0@.xml'.format(protocol_name)) - else - protocol_version = p.get(2) - output_base = '@0@-@1@-@2@'.format(protocol_name, - protocol_type, - protocol_version) - input = join_paths(protocols_dir, - '@0@/@1@/@2@.xml'.format(protocol_type, - protocol_name, - output_base)) - endif - - wayland_protocol_server_headers += custom_target('@0@ server header'.format(output_base), - input: input, - output: '@0@-server-protocol.h'.format(output_base), - command: [ - wayland_scanner, - 'server-header', - '@INPUT@', '@OUTPUT@', - ] - ) - - # used by tests - wayland_protocol_client_headers += custom_target('@0@ client header'.format(output_base), - input: input, - output: '@0@-client-protocol.h'.format(output_base), - command: [ - wayland_scanner, - 'client-header', - '@INPUT@', '@OUTPUT@', - ] - ) - - wayland_protocol_sources += custom_target('@0@ source'.format(output_base), - input: input, - output: '@0@-protocol.c'.format(output_base), - command: [ - wayland_scanner, - 'private-code', - '@INPUT@', '@OUTPUT@', - ] - ) - endforeach -endif - -mutter_built_sources += wayland_protocol_server_headers -mutter_built_sources += wayland_protocol_sources - -subdir('meta') - -mutter_built_sources += mutter_enum_types - -libmutter = shared_library(libmutter_name, - mutter_sources, - mutter_built_sources, - version: '0.0.0', - soversion: 0, - gnu_symbol_visibility: 'hidden', - include_directories: mutter_includes, - c_args: mutter_c_args, - dependencies: [ - libmutter_cogl_dep, - libmutter_clutter_dep, - mutter_deps, - ], - install_rpath: pkglibdir, - install_dir: libdir, - install: true, -) - -libmutter_dep = declare_dependency( - link_with: libmutter, - include_directories: mutter_includes, - dependencies: [ - libmutter_cogl_dep, - libmutter_clutter_dep, - mutter_deps, - ], -) - -executable('mutter', - sources: [ - files('core/mutter.c'), - ], - include_directories: mutter_includes, - c_args: mutter_c_args, - dependencies: [libmutter_dep], - install_dir: bindir, - install: true, -) - -executable('mutter-restart-helper', - sources: [ - files('core/restart-helper.c'), - ], - include_directories: [ - top_includepath, - ], - c_args: mutter_c_args, - dependencies: [ - x11_dep, - xcomposite_dep, - ], - install_dir: libexecdir, - install: true, -) - -if have_introspection - mutter_introspected_sources = [] - foreach source : mutter_sources - if source.endswith('.c') - mutter_introspected_sources += source - endif - endforeach - - libmutter_gir = gnome.generate_gir(libmutter, - sources: [ - mutter_enum_types[1], - mutter_introspected_sources, - mutter_public_header_files - ], - nsversion: libmutter_api_version, - namespace: 'Meta', - symbol_prefix: 'meta', - includes: [ - 'GObject-2.0', - 'GDesktopEnums-3.0', - 'Gdk-3.0', - 'Gtk-3.0', - 'xlib-2.0', - 'xfixes-4.0', - libmutter_cogl_gir[0], - libmutter_cogl_pango_gir[0], - libmutter_clutter_gir[0], - ], - dependencies: [ - mutter_deps, - libmutter_dep, - ], - extra_args: mutter_c_args + introspection_args, - install_dir_gir: pkglibdir, - install_dir_typelib: pkglibdir, - install: true - ) -endif - -pkg.generate(libmutter, - name: 'Meta', - filebase: 'libmutter-' + libmutter_api_version, - description: 'Mutter compositor and window manager library', - subdirs: pkgname, - requires: [mutter_pkg_deps, libmutter_clutter_name], - version: meson.project_version(), - variables: [ - 'apiversion=' + libmutter_api_version, - 'girdir=${libdir}/mutter-' + libmutter_api_version, - 'typelibdir=${libdir}/mutter-' + libmutter_api_version, - ], - install_dir: pcdir, -) - -subdir('compositor/plugins') - -if have_core_tests - subdir('tests') -endif diff --git a/src/meta-private-enum-types.c.in b/src/meta-private-enum-types.c.in deleted file mode 100644 index c2479a91a..000000000 --- a/src/meta-private-enum-types.c.in +++ /dev/null @@ -1,39 +0,0 @@ -/*** BEGIN file-header ***/ -#include "meta-private-enum-types.h" -/*** END file-header ***/ - -/*** BEGIN file-production ***/ - -/* enumerations from "@filename@" */ -#include "@filename@" - -/*** END file-production ***/ - -/*** BEGIN value-header ***/ -GType -@enum_name@_get_type (void) -{ - static size_t g_enum_type_id = 0; - - if (g_once_init_enter (&g_enum_type_id)) - { - static const G@Type@Value values[] = { -/*** END value-header ***/ - -/*** BEGIN value-production ***/ - { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, -/*** END value-production ***/ - -/*** BEGIN value-tail ***/ - { 0, NULL, NULL } - }; - GType id; - - id = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); - - g_once_init_leave (&g_enum_type_id, id); - } - - return g_enum_type_id; -} -/*** END value-tail ***/ diff --git a/src/meta-private-enum-types.h.in b/src/meta-private-enum-types.h.in deleted file mode 100644 index 2427a0c68..000000000 --- a/src/meta-private-enum-types.h.in +++ /dev/null @@ -1,25 +0,0 @@ -/*** BEGIN file-header ***/ -#ifndef META_PRIVATE_ENUM_TYPES_H -#define META_PRIVATE_ENUM_TYPES_H - -#include - -G_BEGIN_DECLS - -/*** END file-header ***/ - -/*** BEGIN file-production ***/ -/* enumerations from "@basename@" */ -/*** END file-production ***/ - -/*** BEGIN file-tail ***/ -G_END_DECLS - -#endif /* !__MUTTER_ENUM_TYPES_H__ */ -/*** END file-tail ***/ - -/*** BEGIN value-header ***/ -GType @enum_name@_get_type (void) G_GNUC_CONST; -#define META_TYPE_@ENUMSHORT@ (@enum_name@_get_type()) - -/*** END value-header ***/ diff --git a/src/meta/barrier.h b/src/meta/barrier.h deleted file mode 100644 index 72ed33cfc..000000000 --- a/src/meta/barrier.h +++ /dev/null @@ -1,124 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; c-basic-offset: 2; -*- */ - -#ifndef __META_BARRIER_H__ -#define __META_BARRIER_H__ - -#include - -#include - -G_BEGIN_DECLS - -#define META_TYPE_BARRIER (meta_barrier_get_type ()) -#define META_BARRIER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BARRIER, MetaBarrier)) -#define META_BARRIER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_BARRIER, MetaBarrierClass)) -#define META_IS_BARRIER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BARRIER)) -#define META_IS_BARRIER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_BARRIER)) -#define META_BARRIER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_BARRIER, MetaBarrierClass)) - -typedef struct _MetaBarrier MetaBarrier; -typedef struct _MetaBarrierClass MetaBarrierClass; -typedef struct _MetaBarrierPrivate MetaBarrierPrivate; - -typedef struct _MetaBarrierEvent MetaBarrierEvent; - -/** - * MetaBarrier: - * - * The MetaBarrier structure contains - * only private data and should be accessed using the provided API - * - **/ -struct _MetaBarrier -{ - GObject parent; - - MetaBarrierPrivate *priv; -}; - -/** - * MetaBarrierClass: - * - * The MetaBarrierClass structure contains only - * private data. - */ -struct _MetaBarrierClass -{ - /*< private >*/ - GObjectClass parent_class; -}; - -META_EXPORT -GType meta_barrier_get_type (void) G_GNUC_CONST; - -META_EXPORT -gboolean meta_barrier_is_active (MetaBarrier *barrier); - -META_EXPORT -void meta_barrier_destroy (MetaBarrier *barrier); - -META_EXPORT -void meta_barrier_release (MetaBarrier *barrier, - MetaBarrierEvent *event); - -/** - * MetaBarrierDirection: - * @META_BARRIER_DIRECTION_POSITIVE_X: Positive direction in the X axis - * @META_BARRIER_DIRECTION_POSITIVE_Y: Positive direction in the Y axis - * @META_BARRIER_DIRECTION_NEGATIVE_X: Negative direction in the X axis - * @META_BARRIER_DIRECTION_NEGATIVE_Y: Negative direction in the Y axis - */ - -/* Keep in sync with XFixes */ -typedef enum -{ - META_BARRIER_DIRECTION_POSITIVE_X = 1 << 0, - META_BARRIER_DIRECTION_POSITIVE_Y = 1 << 1, - META_BARRIER_DIRECTION_NEGATIVE_X = 1 << 2, - META_BARRIER_DIRECTION_NEGATIVE_Y = 1 << 3, -} MetaBarrierDirection; - -/** - * MetaBarrierEvent: - * @event_id: A unique integer ID identifying a - * consecutive series of motions at or along the barrier - * @time: Server time, in milliseconds - * @dt: Server time, in milliseconds, since the last event - * sent for this barrier - * @x: The cursor X position in screen coordinates - * @y: The cursor Y position in screen coordinates. - * @dx: If the cursor hadn't been constrained, the delta - * of X movement past the barrier, in screen coordinates - * @dy: If the cursor hadn't been constrained, the delta - * of X movement past the barrier, in screen coordinates - * @released: A boolean flag, %TRUE if this event generated - * by the pointer leaving the barrier as a result of a client - * calling meta_barrier_release() (will be set only for - * MetaBarrier::leave signals) - * @grabbed: A boolean flag, %TRUE if the pointer was grabbed - * at the time this event was sent - */ -struct _MetaBarrierEvent { - /* < private > */ - volatile guint ref_count; - - /* < public > */ - int event_id; - int dt; - guint32 time; - double x; - double y; - double dx; - double dy; - gboolean released; - gboolean grabbed; -}; - -#define META_TYPE_BARRIER_EVENT (meta_barrier_event_get_type ()) - -META_EXPORT -GType meta_barrier_event_get_type (void) G_GNUC_CONST; - -G_END_DECLS - -#endif /* __META_BARRIER_H__ */ diff --git a/src/meta/boxes.h b/src/meta/boxes.h deleted file mode 100644 index 7585e1312..000000000 --- a/src/meta/boxes.h +++ /dev/null @@ -1,159 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Simple box operations */ - -/* - * Copyright (C) 2005, 2006 Elijah Newren - * - * 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 . - */ - -#ifndef META_BOXES_H -#define META_BOXES_H - -#include -#include - -#define META_TYPE_RECTANGLE (meta_rectangle_get_type ()) - -/** - * MetaRectangle: - * @x: X coordinate of the top-left corner - * @y: Y coordinate of the top-left corner - * @width: Width of the rectangle - * @height: Height of the rectangle - */ -#ifdef __GI_SCANNER__ -/* The introspection scanner is currently unable to lookup how - * cairo_rectangle_int_t is actually defined. This prevents - * introspection data for the GdkRectangle type to include fields - * descriptions. To workaround this issue, we define it with the same - * content as cairo_rectangle_int_t, but only under the introspection - * define. - */ -struct _MetaRectangle -{ - int x; - int y; - int width; - int height; -}; -typedef struct _MetaRectangle MetaRectangle; -#else -typedef cairo_rectangle_int_t MetaRectangle; -#endif - -/** - * MetaStrut: - * @rect: #MetaRectangle the #MetaStrut is on - * @side: #MetaSide the #MetaStrut is on - */ -typedef struct _MetaStrut MetaStrut; -struct _MetaStrut -{ - MetaRectangle rect; - MetaSide side; -}; - -/** - * MetaEdgeType: - * @META_EDGE_WINDOW: Whether the edge belongs to a window - * @META_EDGE_MONITOR: Whether the edge belongs to a monitor - * @META_EDGE_SCREEN: Whether the edge belongs to a screen - */ -typedef enum -{ - META_EDGE_WINDOW, - META_EDGE_MONITOR, - META_EDGE_SCREEN -} MetaEdgeType; - -/** - * MetaEdge: - * @rect: #MetaRectangle with the bounds of the edge - * @side_type: Side - * @edge_type: To what belongs the edge - */ -typedef struct _MetaEdge MetaEdge; -struct _MetaEdge -{ - MetaRectangle rect; /* width or height should be 1 */ - MetaSide side_type; - MetaEdgeType edge_type; -}; - -META_EXPORT -GType meta_rectangle_get_type (void); - -META_EXPORT -MetaRectangle *meta_rectangle_copy (const MetaRectangle *rect); - -META_EXPORT -void meta_rectangle_free (MetaRectangle *rect); - -/* Function to make initializing a rect with a single line of code easy */ -META_EXPORT -MetaRectangle meta_rect (int x, int y, int width, int height); - -/* Basic comparison functions */ -META_EXPORT -int meta_rectangle_area (const MetaRectangle *rect); - -META_EXPORT -gboolean meta_rectangle_intersect (const MetaRectangle *src1, - const MetaRectangle *src2, - MetaRectangle *dest); - -META_EXPORT -gboolean meta_rectangle_equal (const MetaRectangle *src1, - const MetaRectangle *src2); - -/* Find the bounding box of the union of two rectangles */ -META_EXPORT -void meta_rectangle_union (const MetaRectangle *rect1, - const MetaRectangle *rect2, - MetaRectangle *dest); - -/* overlap is similar to intersect but doesn't provide location of - * intersection information. - */ -META_EXPORT -gboolean meta_rectangle_overlap (const MetaRectangle *rect1, - const MetaRectangle *rect2); - -/* vert_overlap means ignore the horizontal location and ask if the - * vertical parts overlap. An alternate way to think of it is "Does there - * exist a way to shift either rect horizontally so that the two rects - * overlap?" horiz_overlap is similar. - */ -META_EXPORT -gboolean meta_rectangle_vert_overlap (const MetaRectangle *rect1, - const MetaRectangle *rect2); - -META_EXPORT -gboolean meta_rectangle_horiz_overlap (const MetaRectangle *rect1, - const MetaRectangle *rect2); - -/* could_fit_rect determines whether "outer_rect" is big enough to contain - * inner_rect. contains_rect checks whether it actually contains it. - */ -META_EXPORT -gboolean meta_rectangle_could_fit_rect (const MetaRectangle *outer_rect, - const MetaRectangle *inner_rect); - -META_EXPORT -gboolean meta_rectangle_contains_rect (const MetaRectangle *outer_rect, - const MetaRectangle *inner_rect); - -#endif /* META_BOXES_H */ diff --git a/src/meta/common.h b/src/meta/common.h deleted file mode 100644 index ab9308049..000000000 --- a/src/meta/common.h +++ /dev/null @@ -1,553 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * PLEASE KEEP IN SYNC WITH GSETTINGS SCHEMAS! - */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2005 Elijah Newren - * - * 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 . - */ - -#ifndef META_COMMON_H -#define META_COMMON_H - -#include -#include -#include -#include -#include - -#include "clutter/clutter.h" - -/** - * SECTION:common - * @Title: Common - * @Short_Description: Mutter common types - */ - -/* This is set in stone and also hard-coded in GDK. */ -#define META_VIRTUAL_CORE_POINTER_ID 2 -#define META_VIRTUAL_CORE_KEYBOARD_ID 3 - -/* Replacement for X11 CurrentTime */ -#define META_CURRENT_TIME 0L - -#define META_EXPORT __attribute__((visibility("default"))) extern - -/** - * MetaFrameFlags: - * @META_FRAME_ALLOWS_DELETE: frame allows delete - * @META_FRAME_ALLOWS_MENU: frame allows menu - * @META_FRAME_ALLOWS_MINIMIZE: frame allows minimize - * @META_FRAME_ALLOWS_MAXIMIZE: frame allows maximize - * @META_FRAME_ALLOWS_VERTICAL_RESIZE: frame allows vertical resize - * @META_FRAME_ALLOWS_HORIZONTAL_RESIZE: frame allows horizontal resize - * @META_FRAME_HAS_FOCUS: frame has focus - * @META_FRAME_SHADED: frame is shaded - * @META_FRAME_STUCK: frame is stuck - * @META_FRAME_MAXIMIZED: frame is maximized - * @META_FRAME_ALLOWS_SHADE: frame allows shade - * @META_FRAME_ALLOWS_MOVE: frame allows move - * @META_FRAME_FULLSCREEN: frame allows fullscreen - * @META_FRAME_ABOVE: frame is above - * @META_FRAME_TILED_LEFT: frame is tiled to the left - * @META_FRAME_TILED_RIGHT: frame is tiled to the right - */ -typedef enum -{ - META_FRAME_ALLOWS_DELETE = 1 << 0, - META_FRAME_ALLOWS_MENU = 1 << 1, - META_FRAME_ALLOWS_MINIMIZE = 1 << 2, - META_FRAME_ALLOWS_MAXIMIZE = 1 << 3, - META_FRAME_ALLOWS_VERTICAL_RESIZE = 1 << 4, - META_FRAME_ALLOWS_HORIZONTAL_RESIZE = 1 << 5, - META_FRAME_HAS_FOCUS = 1 << 6, - META_FRAME_SHADED = 1 << 7, - META_FRAME_STUCK = 1 << 8, - META_FRAME_MAXIMIZED = 1 << 9, - META_FRAME_ALLOWS_SHADE = 1 << 10, - META_FRAME_ALLOWS_MOVE = 1 << 11, - META_FRAME_FULLSCREEN = 1 << 12, - META_FRAME_ABOVE = 1 << 13, - META_FRAME_TILED_LEFT = 1 << 14, - META_FRAME_TILED_RIGHT = 1 << 15 -} MetaFrameFlags; - -/** - * MetaGrabOp: - * @META_GRAB_OP_NONE: None - * @META_GRAB_OP_MOVING: Moving with pointer - * @META_GRAB_OP_RESIZING_SE: Resizing SE with pointer - * @META_GRAB_OP_RESIZING_S: Resizing S with pointer - * @META_GRAB_OP_RESIZING_SW: Resizing SW with pointer - * @META_GRAB_OP_RESIZING_N: Resizing N with pointer - * @META_GRAB_OP_RESIZING_NE: Resizing NE with pointer - * @META_GRAB_OP_RESIZING_NW: Resizing NW with pointer - * @META_GRAB_OP_RESIZING_W: Resizing W with pointer - * @META_GRAB_OP_RESIZING_E: Resizing E with pointer - * @META_GRAB_OP_KEYBOARD_MOVING: Moving with keyboard - * @META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN: Resizing with keyboard - * @META_GRAB_OP_KEYBOARD_RESIZING_S: Resizing S with keyboard - * @META_GRAB_OP_KEYBOARD_RESIZING_N: Resizing N with keyboard - * @META_GRAB_OP_KEYBOARD_RESIZING_W: Resizing W with keyboard - * @META_GRAB_OP_KEYBOARD_RESIZING_E: Resizing E with keyboard - * @META_GRAB_OP_KEYBOARD_RESIZING_SE: Resizing SE with keyboard - * @META_GRAB_OP_KEYBOARD_RESIZING_NE: Resizing NE with keyboard - * @META_GRAB_OP_KEYBOARD_RESIZING_SW: Resizing SW with keyboard - * @META_GRAB_OP_KEYBOARD_RESIZING_NW: Resizing NS with keyboard - * @META_GRAB_OP_COMPOSITOR: Compositor asked for grab - */ - -/* The lower 16 bits of the grab operation is its type. - * - * Window grab operations have the following layout: - * - * 0000 0000 | 0000 0011 - * NSEW flags | type - * - * Flags contains whether the operation is a keyboard operation, - * and whether the keyboard operation is "unknown". - * - * The rest of the flags tell you which direction the resize is - * going in. - * - * If the directions field is 0000, then the operation is a move, - * not a resize. - */ -enum -{ - META_GRAB_OP_WINDOW_FLAG_KEYBOARD = 0x0100, - META_GRAB_OP_WINDOW_FLAG_UNKNOWN = 0x0200, - META_GRAB_OP_WINDOW_DIR_WEST = 0x1000, - META_GRAB_OP_WINDOW_DIR_EAST = 0x2000, - META_GRAB_OP_WINDOW_DIR_SOUTH = 0x4000, - META_GRAB_OP_WINDOW_DIR_NORTH = 0x8000, - META_GRAB_OP_WINDOW_DIR_MASK = 0xF000, - - /* WGO = "window grab op". shorthand for below */ - _WGO_K = META_GRAB_OP_WINDOW_FLAG_KEYBOARD, - _WGO_U = META_GRAB_OP_WINDOW_FLAG_UNKNOWN, - _WGO_W = META_GRAB_OP_WINDOW_DIR_WEST, - _WGO_E = META_GRAB_OP_WINDOW_DIR_EAST, - _WGO_S = META_GRAB_OP_WINDOW_DIR_SOUTH, - _WGO_N = META_GRAB_OP_WINDOW_DIR_NORTH, -}; - -typedef enum -{ - META_GRAB_OP_NONE, - - /* Window grab ops. */ - META_GRAB_OP_WINDOW_BASE, - - /* Special grab op when the compositor asked for a grab */ - META_GRAB_OP_COMPOSITOR, - - /* For when a Wayland client takes a popup grab. */ - META_GRAB_OP_WAYLAND_POPUP, - - /* For when the user clicks on a frame button. */ - META_GRAB_OP_FRAME_BUTTON, - - META_GRAB_OP_MOVING = META_GRAB_OP_WINDOW_BASE, - META_GRAB_OP_RESIZING_NW = META_GRAB_OP_WINDOW_BASE | _WGO_N | _WGO_W, - META_GRAB_OP_RESIZING_N = META_GRAB_OP_WINDOW_BASE | _WGO_N, - META_GRAB_OP_RESIZING_NE = META_GRAB_OP_WINDOW_BASE | _WGO_N | _WGO_E, - META_GRAB_OP_RESIZING_E = META_GRAB_OP_WINDOW_BASE | _WGO_E, - META_GRAB_OP_RESIZING_SW = META_GRAB_OP_WINDOW_BASE | _WGO_S | _WGO_W, - META_GRAB_OP_RESIZING_S = META_GRAB_OP_WINDOW_BASE | _WGO_S, - META_GRAB_OP_RESIZING_SE = META_GRAB_OP_WINDOW_BASE | _WGO_S | _WGO_E, - META_GRAB_OP_RESIZING_W = META_GRAB_OP_WINDOW_BASE | _WGO_W, - META_GRAB_OP_KEYBOARD_MOVING = META_GRAB_OP_WINDOW_BASE | _WGO_K, - META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN = META_GRAB_OP_WINDOW_BASE | _WGO_K | _WGO_U, - META_GRAB_OP_KEYBOARD_RESIZING_NW = META_GRAB_OP_WINDOW_BASE | _WGO_N | _WGO_W | _WGO_K, - META_GRAB_OP_KEYBOARD_RESIZING_N = META_GRAB_OP_WINDOW_BASE | _WGO_N | _WGO_K, - META_GRAB_OP_KEYBOARD_RESIZING_NE = META_GRAB_OP_WINDOW_BASE | _WGO_N | _WGO_E | _WGO_K, - META_GRAB_OP_KEYBOARD_RESIZING_E = META_GRAB_OP_WINDOW_BASE | _WGO_E | _WGO_K, - META_GRAB_OP_KEYBOARD_RESIZING_SW = META_GRAB_OP_WINDOW_BASE | _WGO_S | _WGO_W | _WGO_K, - META_GRAB_OP_KEYBOARD_RESIZING_S = META_GRAB_OP_WINDOW_BASE | _WGO_S | _WGO_K, - META_GRAB_OP_KEYBOARD_RESIZING_SE = META_GRAB_OP_WINDOW_BASE | _WGO_S | _WGO_E | _WGO_K, - META_GRAB_OP_KEYBOARD_RESIZING_W = META_GRAB_OP_WINDOW_BASE | _WGO_W | _WGO_K, -} MetaGrabOp; - -/** - * MetaCursor: - * @META_CURSOR_DEFAULT: Default cursor - * @META_CURSOR_NORTH_RESIZE: Resize northern edge cursor - * @META_CURSOR_SOUTH_RESIZE: Resize southern edge cursor - * @META_CURSOR_WEST_RESIZE: Resize western edge cursor - * @META_CURSOR_EAST_RESIZE: Resize eastern edge cursor - * @META_CURSOR_SE_RESIZE: Resize south-eastern corner cursor - * @META_CURSOR_SW_RESIZE: Resize south-western corner cursor - * @META_CURSOR_NE_RESIZE: Resize north-eastern corner cursor - * @META_CURSOR_NW_RESIZE: Resize north-western corner cursor - * @META_CURSOR_MOVE_OR_RESIZE_WINDOW: Move or resize cursor - * @META_CURSOR_BUSY: Busy cursor - * @META_CURSOR_DND_IN_DRAG: DND in drag cursor - * @META_CURSOR_DND_MOVE: DND move cursor - * @META_CURSOR_DND_COPY: DND copy cursor - * @META_CURSOR_DND_UNSUPPORTED_TARGET: DND unsupported target - * @META_CURSOR_POINTING_HAND: pointing hand - * @META_CURSOR_CROSSHAIR: crosshair (action forbidden) - * @META_CURSOR_IBEAM: I-beam (text input) - * @META_CURSOR_BLANK: Invisible cursor - */ -typedef enum -{ - META_CURSOR_NONE = 0, - META_CURSOR_DEFAULT, - META_CURSOR_NORTH_RESIZE, - META_CURSOR_SOUTH_RESIZE, - META_CURSOR_WEST_RESIZE, - META_CURSOR_EAST_RESIZE, - META_CURSOR_SE_RESIZE, - META_CURSOR_SW_RESIZE, - META_CURSOR_NE_RESIZE, - META_CURSOR_NW_RESIZE, - META_CURSOR_MOVE_OR_RESIZE_WINDOW, - META_CURSOR_BUSY, - META_CURSOR_DND_IN_DRAG, - META_CURSOR_DND_MOVE, - META_CURSOR_DND_COPY, - META_CURSOR_DND_UNSUPPORTED_TARGET, - META_CURSOR_POINTING_HAND, - META_CURSOR_CROSSHAIR, - META_CURSOR_IBEAM, - META_CURSOR_BLANK, - META_CURSOR_LAST -} MetaCursor; - -/** - * MetaFrameType: - * @META_FRAME_TYPE_NORMAL: Normal frame - * @META_FRAME_TYPE_DIALOG: Dialog frame - * @META_FRAME_TYPE_MODAL_DIALOG: Modal dialog frame - * @META_FRAME_TYPE_UTILITY: Utility frame - * @META_FRAME_TYPE_MENU: Menu frame - * @META_FRAME_TYPE_BORDER: Border frame - * @META_FRAME_TYPE_ATTACHED: Attached frame - * @META_FRAME_TYPE_LAST: Marks the end of the #MetaFrameType enumeration - */ -typedef enum -{ - META_FRAME_TYPE_NORMAL, - META_FRAME_TYPE_DIALOG, - META_FRAME_TYPE_MODAL_DIALOG, - META_FRAME_TYPE_UTILITY, - META_FRAME_TYPE_MENU, - META_FRAME_TYPE_BORDER, - META_FRAME_TYPE_ATTACHED, - META_FRAME_TYPE_LAST -} MetaFrameType; - -/** - * MetaVirtualModifier: - * @META_VIRTUAL_SHIFT_MASK: Shift mask - * @META_VIRTUAL_CONTROL_MASK: Control mask - * @META_VIRTUAL_ALT_MASK: Alt mask - * @META_VIRTUAL_META_MASK: Meta mask - * @META_VIRTUAL_SUPER_MASK: Super mask - * @META_VIRTUAL_HYPER_MASK: Hyper mask - * @META_VIRTUAL_MOD2_MASK: Mod2 mask - * @META_VIRTUAL_MOD3_MASK: Mod3 mask - * @META_VIRTUAL_MOD4_MASK: Mod4 mask - * @META_VIRTUAL_MOD5_MASK: Mod5 mask - */ -typedef enum -{ - /* Create gratuitous divergence from regular - * X mod bits, to be sure we find bugs - */ - META_VIRTUAL_SHIFT_MASK = 1 << 5, - META_VIRTUAL_CONTROL_MASK = 1 << 6, - META_VIRTUAL_ALT_MASK = 1 << 7, - META_VIRTUAL_META_MASK = 1 << 8, - META_VIRTUAL_SUPER_MASK = 1 << 9, - META_VIRTUAL_HYPER_MASK = 1 << 10, - META_VIRTUAL_MOD2_MASK = 1 << 11, - META_VIRTUAL_MOD3_MASK = 1 << 12, - META_VIRTUAL_MOD4_MASK = 1 << 13, - META_VIRTUAL_MOD5_MASK = 1 << 14 -} MetaVirtualModifier; - -/** - * MetaDirection: - * @META_DIRECTION_LEFT: Left - * @META_DIRECTION_RIGHT: Right - * @META_DIRECTION_TOP: Top - * @META_DIRECTION_BOTTOM: Bottom - * @META_DIRECTION_UP: Up - * @META_DIRECTION_DOWN: Down - * @META_DIRECTION_HORIZONTAL: Horizontal - * @META_DIRECTION_VERTICAL: Vertical - */ - -/* Relative directions or sides seem to come up all over the place... */ -/* FIXME: Replace - * display.[ch]:MetaDisplayDirection, - * workspace.[ch]:MetaMotionDirection, - * with the use of MetaDirection. - */ -typedef enum -{ - META_DIRECTION_LEFT = 1 << 0, - META_DIRECTION_RIGHT = 1 << 1, - META_DIRECTION_TOP = 1 << 2, - META_DIRECTION_BOTTOM = 1 << 3, - - /* Some aliases for making code more readable for various circumstances. */ - META_DIRECTION_UP = META_DIRECTION_TOP, - META_DIRECTION_DOWN = META_DIRECTION_BOTTOM, - - /* A few more definitions using aliases */ - META_DIRECTION_HORIZONTAL = META_DIRECTION_LEFT | META_DIRECTION_RIGHT, - META_DIRECTION_VERTICAL = META_DIRECTION_UP | META_DIRECTION_DOWN, -} MetaDirection; - -/** - * MetaMotionDirection: - * @META_MOTION_UP: Upwards motion - * @META_MOTION_DOWN: Downwards motion - * @META_MOTION_LEFT: Motion to the left - * @META_MOTION_RIGHT: Motion to the right - * @META_MOTION_UP_LEFT: Motion up and to the left - * @META_MOTION_UP_RIGHT: Motion up and to the right - * @META_MOTION_DOWN_LEFT: Motion down and to the left - * @META_MOTION_DOWN_RIGHT: Motion down and to the right - */ - -/* Negative to avoid conflicting with real workspace - * numbers - */ -typedef enum -{ - META_MOTION_UP = -1, - META_MOTION_DOWN = -2, - META_MOTION_LEFT = -3, - META_MOTION_RIGHT = -4, - /* These are only used for effects */ - META_MOTION_UP_LEFT = -5, - META_MOTION_UP_RIGHT = -6, - META_MOTION_DOWN_LEFT = -7, - META_MOTION_DOWN_RIGHT = -8 -} MetaMotionDirection; - -/** - * MetaSide: - * @META_SIDE_LEFT: Left side - * @META_SIDE_RIGHT: Right side - * @META_SIDE_TOP: Top side - * @META_SIDE_BOTTOM: Bottom side - */ - -/* Sometimes we want to talk about sides instead of directions; note - * that the values must be as follows or meta_window_update_struts() - * won't work. Using these values also is a safety blanket since - * MetaDirection used to be used as a side. - */ -typedef enum -{ - META_SIDE_LEFT = META_DIRECTION_LEFT, - META_SIDE_RIGHT = META_DIRECTION_RIGHT, - META_SIDE_TOP = META_DIRECTION_TOP, - META_SIDE_BOTTOM = META_DIRECTION_BOTTOM -} MetaSide; - -/** - * MetaButtonFunction: - * @META_BUTTON_FUNCTION_MENU: Menu - * @META_BUTTON_FUNCTION_MINIMIZE: Minimize - * @META_BUTTON_FUNCTION_MAXIMIZE: Maximize - * @META_BUTTON_FUNCTION_CLOSE: Close - * @META_BUTTON_FUNCTION_LAST: Marks the end of the #MetaButtonFunction enumeration - * - * Function a window button can have. Note, you can't add stuff here - * without extending the theme format to draw a new function and - * breaking all existing themes. - */ -typedef enum -{ - META_BUTTON_FUNCTION_MENU, - META_BUTTON_FUNCTION_MINIMIZE, - META_BUTTON_FUNCTION_MAXIMIZE, - META_BUTTON_FUNCTION_CLOSE, - META_BUTTON_FUNCTION_LAST -} MetaButtonFunction; - -#define MAX_BUTTONS_PER_CORNER META_BUTTON_FUNCTION_LAST - -/* Keep array size in sync with MAX_BUTTONS_PER_CORNER */ -/** - * MetaButtonLayout: - * @left_buttons: (array fixed-size=4): - * @right_buttons: (array fixed-size=4): - * @left_buttons_has_spacer: (array fixed-size=4): - * @right_buttons_has_spacer: (array fixed-size=4): - */ -typedef struct _MetaButtonLayout MetaButtonLayout; -struct _MetaButtonLayout -{ - /* buttons in the group on the left side */ - MetaButtonFunction left_buttons[MAX_BUTTONS_PER_CORNER]; - gboolean left_buttons_has_spacer[MAX_BUTTONS_PER_CORNER]; - - /* buttons in the group on the right side */ - MetaButtonFunction right_buttons[MAX_BUTTONS_PER_CORNER]; - gboolean right_buttons_has_spacer[MAX_BUTTONS_PER_CORNER]; -}; - -/** - * MetaWindowMenuType: - * @META_WINDOW_MENU_WM: the window manager menu - * @META_WINDOW_MENU_APP: the (fallback) app menu - * - * Menu the compositor should display for a given window - */ -typedef enum -{ - META_WINDOW_MENU_WM, - META_WINDOW_MENU_APP -} MetaWindowMenuType; - -/** - * MetaFrameBorders: - * @visible: inner visible portion of frame border - * @invisible: outer invisible portion of frame border - * @total: sum of the two borders above - */ -typedef struct _MetaFrameBorders MetaFrameBorders; -struct _MetaFrameBorders -{ - /* The frame border is made up of two pieces - an inner visible portion - * and an outer portion that is invisible but responds to events. - */ - GtkBorder visible; - GtkBorder invisible; - - /* For convenience, we have a "total" border which is equal to the sum - * of the two borders above. */ - GtkBorder total; -}; - -/* sets all dimensions to zero */ -META_EXPORT -void meta_frame_borders_clear (MetaFrameBorders *self); - -/* should investigate changing these to whatever most apps use */ -#define META_ICON_WIDTH 96 -#define META_ICON_HEIGHT 96 -#define META_MINI_ICON_WIDTH 16 -#define META_MINI_ICON_HEIGHT 16 - -#define META_DEFAULT_ICON_NAME "window" - -/* Main loop priorities determine when activity in the GLib - * will take precedence over the others. Priorities are sometimes - * used to enforce ordering: give A a higher priority than B if - * A must occur before B. But that poses a problem since then - * if A occurs frequently enough, B will never occur. - * - * Anything we want to occur more or less immediately should - * have a priority of G_PRIORITY_DEFAULT. When we want to - * coalesce multiple things together, the appropriate place to - * do it is usually META_PRIORITY_BEFORE_REDRAW. - * - * Note that its usually better to use meta_later_add() rather - * than calling g_idle_add() directly; this will make sure things - * get run when added from a clutter event handler without - * waiting for another repaint cycle. - * - * If something has a priority lower than the redraw priority - * (such as a default priority idle), then it may be arbitrarily - * delayed. This happens if the screen is updating rapidly: we - * are spending all our time either redrawing or waiting for a - * vblank-synced buffer swap. (When X is improved to allow - * clutter to do the buffer-swap asynchronously, this will get - * better.) - */ - -/* G_PRIORITY_DEFAULT: - * events - * many timeouts - */ - -/* GTK_PRIORITY_RESIZE: (G_PRIORITY_HIGH_IDLE + 10) */ -#define META_PRIORITY_RESIZE (G_PRIORITY_HIGH_IDLE + 15) -/* GTK_PRIORITY_REDRAW: (G_PRIORITY_HIGH_IDLE + 20) */ - -#define META_PRIORITY_BEFORE_REDRAW (G_PRIORITY_HIGH_IDLE + 40) -/* calc-showing idle - * update-icon idle - */ - -/* CLUTTER_PRIORITY_REDRAW: (G_PRIORITY_HIGH_IDLE + 50) */ -#define META_PRIORITY_REDRAW (G_PRIORITY_HIGH_IDLE + 50) - -/* ==== Anything below here can be starved arbitrarily ==== */ - -/* G_PRIORITY_DEFAULT_IDLE: - * Mutter plugin unloading - */ - -#define META_PRIORITY_PREFS_NOTIFY (G_PRIORITY_DEFAULT_IDLE + 10) - -/************************************************************/ - -/** - * MetaStackLayer: - * @META_LAYER_DESKTOP: Desktop layer - * @META_LAYER_BOTTOM: Bottom layer - * @META_LAYER_NORMAL: Normal layer - * @META_LAYER_TOP: Top layer - * @META_LAYER_DOCK: Dock layer - * @META_LAYER_OVERRIDE_REDIRECT: Override-redirect layer - * @META_LAYER_LAST: Marks the end of the #MetaStackLayer enumeration - * - * Layers a window can be in. - * These MUST be in the order of stacking. - */ -typedef enum -{ - META_LAYER_DESKTOP = 0, - META_LAYER_BOTTOM = 1, - META_LAYER_NORMAL = 2, - META_LAYER_TOP = 4, /* Same as DOCK; see EWMH and bug 330717 */ - META_LAYER_DOCK = 4, - META_LAYER_OVERRIDE_REDIRECT = 7, - META_LAYER_LAST = 8 -} MetaStackLayer; - -/* MetaGravity: (skip) - * - * Identical to the corresponding gravity value macros from libX11. - */ -typedef enum _MetaGravity -{ - META_GRAVITY_NONE = 0, - META_GRAVITY_NORTH_WEST = 1, - META_GRAVITY_NORTH = 2, - META_GRAVITY_NORTH_EAST = 3, - META_GRAVITY_WEST = 4, - META_GRAVITY_CENTER = 5, - META_GRAVITY_EAST = 6, - META_GRAVITY_SOUTH_WEST = 7, - META_GRAVITY_SOUTH = 8, - META_GRAVITY_SOUTH_EAST = 9, - META_GRAVITY_STATIC = 10, -} MetaGravity; - -#endif diff --git a/src/meta/compositor-mutter.h b/src/meta/compositor-mutter.h deleted file mode 100644 index 0c420882f..000000000 --- a/src/meta/compositor-mutter.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2008 Matthew Allum - * Copyright (C) 2007 Iain Holmes - * Based on xcompmgr - (c) 2003 Keith Packard - * xfwm4 - (c) 2005-2007 Olivier Fourdan - * - * 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 . - */ - -#ifndef MUTTER_H_ -#define MUTTER_H_ - -#include "clutter/clutter.h" -#include "meta/compositor.h" -#include "meta/meta-window-actor.h" -#include "meta/types.h" - -/* Public compositor API */ -META_EXPORT -ClutterActor *meta_get_stage_for_display (MetaDisplay *display); - -META_EXPORT -GList *meta_get_window_actors (MetaDisplay *display); - -META_EXPORT -ClutterActor *meta_get_window_group_for_display (MetaDisplay *display); - -META_EXPORT -ClutterActor *meta_get_top_window_group_for_display (MetaDisplay *display); - -META_EXPORT -ClutterActor *meta_get_feedback_group_for_display (MetaDisplay *display); - -META_EXPORT -void meta_disable_unredirect_for_display (MetaDisplay *display); - -META_EXPORT -void meta_enable_unredirect_for_display (MetaDisplay *display); - -META_EXPORT -void meta_focus_stage_window (MetaDisplay *display, - guint32 timestamp); - -META_EXPORT -gboolean meta_stage_is_focused (MetaDisplay *display); - -#endif diff --git a/src/meta/compositor.h b/src/meta/compositor.h deleted file mode 100644 index 1ccae70d7..000000000 --- a/src/meta/compositor.h +++ /dev/null @@ -1,165 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2008 Iain Holmes - * - * 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 . - */ - -#ifndef META_COMPOSITOR_H -#define META_COMPOSITOR_H - -#include - -#include -#include -#include -#include - -#define META_TYPE_COMPOSITOR (meta_compositor_get_type ()) -META_EXPORT -G_DECLARE_DERIVABLE_TYPE (MetaCompositor, meta_compositor, - META, COMPOSITOR, GObject) - -/** - * MetaCompEffect: - * @META_COMP_EFFECT_CREATE: The window is newly created - * (also used for a window that was previously on a different - * workspace and is changed to become visible on the active - * workspace.) - * @META_COMP_EFFECT_UNMINIMIZE: The window should be shown - * as unminimizing from its icon geometry. - * @META_COMP_EFFECT_DESTROY: The window is being destroyed - * @META_COMP_EFFECT_MINIMIZE: The window should be shown - * as minimizing to its icon geometry. - * @META_COMP_EFFECT_NONE: No effect, the window should be - * shown or hidden immediately. - * - * Indicates the appropriate effect to show the user for - * meta_compositor_show_window() and meta_compositor_hide_window() - */ -typedef enum -{ - META_COMP_EFFECT_CREATE, - META_COMP_EFFECT_UNMINIMIZE, - META_COMP_EFFECT_DESTROY, - META_COMP_EFFECT_MINIMIZE, - META_COMP_EFFECT_NONE -} MetaCompEffect; - -typedef enum -{ - META_SIZE_CHANGE_MAXIMIZE, - META_SIZE_CHANGE_UNMAXIMIZE, - META_SIZE_CHANGE_FULLSCREEN, - META_SIZE_CHANGE_UNFULLSCREEN, -} MetaSizeChange; - -META_EXPORT -void meta_compositor_destroy (MetaCompositor *compositor); - -META_EXPORT -void meta_compositor_manage (MetaCompositor *compositor); - -META_EXPORT -void meta_compositor_unmanage (MetaCompositor *compositor); - -META_EXPORT -void meta_compositor_window_shape_changed (MetaCompositor *compositor, - MetaWindow *window); - -META_EXPORT -void meta_compositor_window_opacity_changed (MetaCompositor *compositor, - MetaWindow *window); - -META_EXPORT -gboolean meta_compositor_filter_keybinding (MetaCompositor *compositor, - MetaKeyBinding *binding); - -META_EXPORT -void meta_compositor_add_window (MetaCompositor *compositor, - MetaWindow *window); - -META_EXPORT -void meta_compositor_remove_window (MetaCompositor *compositor, - MetaWindow *window); - -META_EXPORT -void meta_compositor_show_window (MetaCompositor *compositor, - MetaWindow *window, - MetaCompEffect effect); - -META_EXPORT -void meta_compositor_hide_window (MetaCompositor *compositor, - MetaWindow *window, - MetaCompEffect effect); - -META_EXPORT -void meta_compositor_switch_workspace (MetaCompositor *compositor, - MetaWorkspace *from, - MetaWorkspace *to, - MetaMotionDirection direction); - -META_EXPORT -void meta_compositor_size_change_window (MetaCompositor *compositor, - MetaWindow *window, - MetaSizeChange which_change, - MetaRectangle *old_frame_rect, - MetaRectangle *old_buffer_rect); - -META_EXPORT -void meta_compositor_sync_window_geometry (MetaCompositor *compositor, - MetaWindow *window, - gboolean did_placement); - -META_EXPORT -void meta_compositor_sync_updates_frozen (MetaCompositor *compositor, - MetaWindow *window); - -META_EXPORT -void meta_compositor_queue_frame_drawn (MetaCompositor *compositor, - MetaWindow *window, - gboolean no_delay_frame); - -META_EXPORT -void meta_compositor_sync_stack (MetaCompositor *compositor, - GList *stack); - -META_EXPORT -void meta_compositor_flash_display (MetaCompositor *compositor, - MetaDisplay *display); - -META_EXPORT -void meta_compositor_show_tile_preview (MetaCompositor *compositor, - MetaWindow *window, - MetaRectangle *tile_rect, - int tile_monitor_number); - -META_EXPORT -void meta_compositor_hide_tile_preview (MetaCompositor *compositor); - -META_EXPORT -void meta_compositor_show_window_menu (MetaCompositor *compositor, - MetaWindow *window, - MetaWindowMenuType menu, - int x, - int y); - -META_EXPORT -void meta_compositor_show_window_menu_for_rect (MetaCompositor *compositor, - MetaWindow *window, - MetaWindowMenuType menu, - MetaRectangle *rect); - -#endif /* META_COMPOSITOR_H */ diff --git a/src/meta/display.h b/src/meta/display.h deleted file mode 100644 index 23bcbd0f5..000000000 --- a/src/meta/display.h +++ /dev/null @@ -1,315 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2008 Iain Holmes - * - * 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 . - */ - -#ifndef META_DISPLAY_H -#define META_DISPLAY_H - -#include -#include - -#include -#include -#include -#include -#include -#include - -/** - * MetaTabList: - * @META_TAB_LIST_NORMAL: Normal windows - * @META_TAB_LIST_DOCKS: Dock windows - * @META_TAB_LIST_GROUP: Groups - * @META_TAB_LIST_NORMAL_ALL: All windows - */ -typedef enum -{ - META_TAB_LIST_NORMAL, - META_TAB_LIST_DOCKS, - META_TAB_LIST_GROUP, - META_TAB_LIST_NORMAL_ALL -} MetaTabList; - -/** - * MetaTabShowType: - * @META_TAB_SHOW_ICON: Show icon (Alt-Tab mode) - * @META_TAB_SHOW_INSTANTLY: Show instantly (Alt-Esc mode) - */ -typedef enum -{ - META_TAB_SHOW_ICON, /* Alt-Tab mode */ - META_TAB_SHOW_INSTANTLY /* Alt-Esc mode */ -} MetaTabShowType; - -typedef enum -{ - META_PAD_ACTION_BUTTON, /* Action is a button */ - META_PAD_ACTION_RING, /* Action is a ring */ - META_PAD_ACTION_STRIP, /* Action is a strip */ -} MetaPadActionType; - -typedef struct _MetaDisplayClass MetaDisplayClass; - -#define META_TYPE_DISPLAY (meta_display_get_type ()) -#define META_DISPLAY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), META_TYPE_DISPLAY, MetaDisplay)) -#define META_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DISPLAY, MetaDisplayClass)) -#define META_IS_DISPLAY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), META_TYPE_DISPLAY)) -#define META_IS_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DISPLAY)) -#define META_DISPLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DISPLAY, MetaDisplayClass)) - -META_EXPORT -GType meta_display_get_type (void) G_GNUC_CONST; - -#define meta_XFree(p) do { if ((p)) XFree ((p)); } while (0) - -META_EXPORT -gboolean meta_display_supports_extended_barriers (MetaDisplay *display); - -META_EXPORT -void meta_display_close (MetaDisplay *display, - guint32 timestamp); - -META_EXPORT -MetaContext * meta_display_get_context (MetaDisplay *display); - -META_EXPORT -MetaCompositor *meta_display_get_compositor (MetaDisplay *display); - -META_EXPORT -MetaX11Display *meta_display_get_x11_display (MetaDisplay *display); - -META_EXPORT -MetaWindow *meta_display_get_focus_window (MetaDisplay *display); - -META_EXPORT -gboolean meta_display_xserver_time_is_before (MetaDisplay *display, - guint32 time1, - guint32 time2); - -META_EXPORT -guint32 meta_display_get_last_user_time (MetaDisplay *display); - -META_EXPORT -guint32 meta_display_get_current_time (MetaDisplay *display); - -META_EXPORT -guint32 meta_display_get_current_time_roundtrip (MetaDisplay *display); - -META_EXPORT -GList* meta_display_get_tab_list (MetaDisplay *display, - MetaTabList type, - MetaWorkspace *workspace); - -META_EXPORT -MetaWindow* meta_display_get_tab_next (MetaDisplay *display, - MetaTabList type, - MetaWorkspace *workspace, - MetaWindow *window, - gboolean backward); - -META_EXPORT -MetaWindow* meta_display_get_tab_current (MetaDisplay *display, - MetaTabList type, - MetaWorkspace *workspace); - -META_EXPORT -gboolean meta_display_begin_grab_op (MetaDisplay *display, - MetaWindow *window, - MetaGrabOp op, - gboolean pointer_already_grabbed, - gboolean frame_action, - int button, - gulong modmask, - guint32 timestamp, - int root_x, - int root_y); - -META_EXPORT -void meta_display_end_grab_op (MetaDisplay *display, - guint32 timestamp); - -META_EXPORT -MetaGrabOp meta_display_get_grab_op (MetaDisplay *display); - -META_EXPORT -guint meta_display_add_keybinding (MetaDisplay *display, - const char *name, - GSettings *settings, - MetaKeyBindingFlags flags, - MetaKeyHandlerFunc handler, - gpointer user_data, - GDestroyNotify free_data); - -META_EXPORT -gboolean meta_display_remove_keybinding (MetaDisplay *display, - const char *name); - -META_EXPORT -guint meta_display_grab_accelerator (MetaDisplay *display, - const char *accelerator, - MetaKeyBindingFlags flags); - -META_EXPORT -gboolean meta_display_ungrab_accelerator (MetaDisplay *display, - guint action_id); - -META_EXPORT -guint meta_display_get_keybinding_action (MetaDisplay *display, - unsigned int keycode, - unsigned long mask); - -META_EXPORT -ClutterModifierType meta_display_get_compositor_modifiers (MetaDisplay *display); - -META_EXPORT -GSList *meta_display_sort_windows_by_stacking (MetaDisplay *display, - GSList *windows); - -META_EXPORT -void meta_display_add_ignored_crossing_serial (MetaDisplay *display, - unsigned long serial); - -META_EXPORT -void meta_display_clear_mouse_mode (MetaDisplay *display); - -META_EXPORT -void meta_display_freeze_keyboard (MetaDisplay *display, - guint32 timestamp); - -META_EXPORT -void meta_display_ungrab_keyboard (MetaDisplay *display, - guint32 timestamp); - -META_EXPORT -void meta_display_unfreeze_keyboard (MetaDisplay *display, - guint32 timestamp); - -META_EXPORT -gboolean meta_display_is_pointer_emulating_sequence (MetaDisplay *display, - ClutterEventSequence *sequence); - -META_EXPORT -void meta_display_request_pad_osd (MetaDisplay *display, - ClutterInputDevice *pad, - gboolean edition_mode); - -META_EXPORT -gchar * meta_display_get_pad_action_label (MetaDisplay *display, - ClutterInputDevice *pad, - MetaPadActionType action_type, - guint action_number); - -META_EXPORT -void meta_display_get_size (MetaDisplay *display, - int *width, - int *height); - -META_EXPORT -void meta_display_set_cursor (MetaDisplay *display, - MetaCursor cursor); - -/** - * MetaDisplayDirection: - * @META_DISPLAY_UP: up - * @META_DISPLAY_DOWN: down - * @META_DISPLAY_LEFT: left - * @META_DISPLAY_RIGHT: right - */ -typedef enum -{ - META_DISPLAY_UP, - META_DISPLAY_DOWN, - META_DISPLAY_LEFT, - META_DISPLAY_RIGHT -} MetaDisplayDirection; - -META_EXPORT -int meta_display_get_n_monitors (MetaDisplay *display); - -META_EXPORT -int meta_display_get_primary_monitor (MetaDisplay *display); - -META_EXPORT -int meta_display_get_current_monitor (MetaDisplay *display); - -META_EXPORT -void meta_display_get_monitor_geometry (MetaDisplay *display, - int monitor, - MetaRectangle *geometry); - -META_EXPORT -float meta_display_get_monitor_scale (MetaDisplay *display, - int monitor); - -META_EXPORT -gboolean meta_display_get_monitor_in_fullscreen (MetaDisplay *display, - int monitor); - -META_EXPORT -int meta_display_get_monitor_index_for_rect (MetaDisplay *display, - MetaRectangle *rect); - -META_EXPORT -int meta_display_get_monitor_neighbor_index (MetaDisplay *display, - int which_monitor, - MetaDisplayDirection dir); - -META_EXPORT -void meta_display_focus_default_window (MetaDisplay *display, - guint32 timestamp); - -/** - * MetaDisplayCorner: - * @META_DISPLAY_TOPLEFT: top-left corner - * @META_DISPLAY_TOPRIGHT: top-right corner - * @META_DISPLAY_BOTTOMLEFT: bottom-left corner - * @META_DISPLAY_BOTTOMRIGHT: bottom-right corner - */ -typedef enum -{ - META_DISPLAY_TOPLEFT, - META_DISPLAY_TOPRIGHT, - META_DISPLAY_BOTTOMLEFT, - META_DISPLAY_BOTTOMRIGHT -} MetaDisplayCorner; - -META_EXPORT -MetaWorkspaceManager *meta_display_get_workspace_manager (MetaDisplay *display); - -/** - * meta_display_get_startup_notification: (skip) - */ -META_EXPORT -MetaStartupNotification * meta_display_get_startup_notification (MetaDisplay *display); - -META_EXPORT -MetaSoundPlayer * meta_display_get_sound_player (MetaDisplay *display); - -META_EXPORT -MetaSelection * meta_display_get_selection (MetaDisplay *display); - -META_EXPORT -void meta_display_set_input_focus (MetaDisplay *display, - MetaWindow *window, - gboolean focus_frame, - guint32 timestamp); -META_EXPORT -void meta_display_unset_input_focus (MetaDisplay *display, - guint32 timestamp); - -#endif diff --git a/src/meta/group.h b/src/meta/group.h deleted file mode 100644 index 5567cf466..000000000 --- a/src/meta/group.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter window groups */ - -/* - * Copyright (C) 2002 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 . - */ - -#ifndef META_GROUP_H -#define META_GROUP_H - -#include -#include - -#include -#include - -/* note, can return NULL */ -META_EXPORT -MetaGroup* meta_window_get_group (MetaWindow *window); - -META_EXPORT -void meta_window_compute_group (MetaWindow* window); - -META_EXPORT -void meta_window_shutdown_group (MetaWindow *window); - -META_EXPORT -void meta_window_group_leader_changed (MetaWindow *window); - -/* note, can return NULL */ -META_EXPORT -MetaGroup *meta_x11_display_lookup_group (MetaX11Display *x11_display, - Window group_leader); - -META_EXPORT -GSList* meta_group_list_windows (MetaGroup *group); - -META_EXPORT -void meta_group_update_layers (MetaGroup *group); - -META_EXPORT -const char* meta_group_get_startup_id (MetaGroup *group); - -META_EXPORT -int meta_group_get_size (MetaGroup *group); - -META_EXPORT -gboolean meta_group_property_notify (MetaGroup *group, - XEvent *event); - -#endif diff --git a/src/meta/keybindings.h b/src/meta/keybindings.h deleted file mode 100644 index ac1cee5b3..000000000 --- a/src/meta/keybindings.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2009 Intel Corporation. - * - * 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 . - */ - -#ifndef META_KEYBINDINGS_H -#define META_KEYBINDINGS_H - -#include -#include - -#define META_TYPE_KEY_BINDING (meta_key_binding_get_type ()) - -META_EXPORT -const char *meta_key_binding_get_name (MetaKeyBinding *binding); - -META_EXPORT -MetaVirtualModifier meta_key_binding_get_modifiers (MetaKeyBinding *binding); - -META_EXPORT -guint meta_key_binding_get_mask (MetaKeyBinding *binding); - -META_EXPORT -gboolean meta_key_binding_is_builtin (MetaKeyBinding *binding); - -META_EXPORT -gboolean meta_key_binding_is_reversed (MetaKeyBinding *binding); - -META_EXPORT -gboolean meta_keybindings_set_custom_handler (const gchar *name, - MetaKeyHandlerFunc handler, - gpointer user_data, - GDestroyNotify free_data); -#endif diff --git a/src/meta/main.h b/src/meta/main.h deleted file mode 100644 index 3e5db424a..000000000 --- a/src/meta/main.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter main */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * 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 . - */ - -#ifndef META_MAIN_H -#define META_MAIN_H - -#include - -#include - -META_EXPORT -void meta_restart (const char *message); - -META_EXPORT -gboolean meta_is_restart (void); - -/** - * MetaExitCode: - * @META_EXIT_SUCCESS: Success - * @META_EXIT_ERROR: Error - */ -typedef enum -{ - META_EXIT_SUCCESS, - META_EXIT_ERROR -} MetaExitCode; - -/* exit immediately */ -META_EXPORT -void meta_exit (MetaExitCode code) G_GNUC_NORETURN; - -#endif diff --git a/src/meta/meson.build b/src/meta/meson.build deleted file mode 100644 index 3076f7532..000000000 --- a/src/meta/meson.build +++ /dev/null @@ -1,75 +0,0 @@ -mutter_public_headers = [ - 'barrier.h', - 'boxes.h', - 'common.h', - 'compositor.h', - 'compositor-mutter.h', - 'display.h', - 'group.h', - 'keybindings.h', - 'main.h', - 'meta-backend.h', - 'meta-background.h', - 'meta-background-actor.h', - 'meta-background-content.h', - 'meta-background-group.h', - 'meta-background-image.h', - 'meta-close-dialog.h', - 'meta-cursor-tracker.h', - 'meta-context.h', - 'meta-dnd.h', - 'meta-enums.h', - 'meta-idle-monitor.h', - 'meta-inhibit-shortcuts-dialog.h', - 'meta-launch-context.h', - 'meta-later.h', - 'meta-monitor-manager.h', - 'meta-plugin.h', - 'meta-remote-access-controller.h', - 'meta-selection.h', - 'meta-selection-source.h', - 'meta-selection-source-memory.h', - 'meta-settings.h', - 'meta-shadow-factory.h', - 'meta-shaped-texture.h', - 'meta-sound-player.h', - 'meta-stage.h', - 'meta-startup-notification.h', - 'meta-window-actor.h', - 'meta-window-group.h', - 'meta-window-shape.h', - 'meta-workspace-manager.h', - 'prefs.h', - 'theme.h', - 'types.h', - 'util.h', - 'window.h', - 'workspace.h', -] - -if have_wayland - mutter_public_headers += [ - 'meta-wayland-client.h', - ] -endif - -if have_x11 - mutter_public_headers += [ - 'meta-x11-display.h', - 'meta-x11-errors.h', - ] -endif - -install_headers(mutter_public_headers, - subdir: mutter_includesubdir -) - -mutter_public_header_files = files(mutter_public_headers) - -mutter_enum_types = gnome.mkenums('meta-enum-types', - sources: [mutter_public_headers], - c_template: 'meta-enum-types.c.in', - h_template: 'meta-enum-types.h.in', - install_dir: mutter_includedir, - install_header: true, -) diff --git a/src/meta/meta-backend.h b/src/meta/meta-backend.h deleted file mode 100644 index 63a679a1a..000000000 --- a/src/meta/meta-backend.h +++ /dev/null @@ -1,76 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -#ifndef META_BACKEND_H -#define META_BACKEND_H - -#include - -#include "clutter/clutter.h" -#include "meta/meta-dnd.h" -#include "meta/meta-idle-monitor.h" -#include "meta/meta-remote-access-controller.h" - -#define META_TYPE_BACKEND (meta_backend_get_type ()) -META_EXPORT -G_DECLARE_DERIVABLE_TYPE (MetaBackend, meta_backend, META, BACKEND, GObject) - -META_EXPORT -MetaBackend * meta_get_backend (void); - -META_EXPORT -void meta_backend_set_keymap (MetaBackend *backend, - const char *layouts, - const char *variants, - const char *options); - -META_EXPORT -void meta_backend_lock_layout_group (MetaBackend *backend, - guint idx); - -META_EXPORT -MetaContext * meta_backend_get_context (MetaBackend *backend); - -META_EXPORT -ClutterActor *meta_backend_get_stage (MetaBackend *backend); - -META_EXPORT -MetaDnd *meta_backend_get_dnd (MetaBackend *backend); - -META_EXPORT -MetaSettings *meta_backend_get_settings (MetaBackend *backend); - -META_EXPORT -MetaIdleMonitor * meta_backend_get_core_idle_monitor (MetaBackend *backend); - -META_EXPORT -MetaRemoteAccessController * meta_backend_get_remote_access_controller (MetaBackend *backend); - -META_EXPORT -gboolean meta_backend_is_rendering_hardware_accelerated (MetaBackend *backend); - -META_EXPORT -void meta_clutter_init (void); - -#endif /* META_BACKEND_H */ diff --git a/src/meta/meta-background-actor.h b/src/meta/meta-background-actor.h deleted file mode 100644 index 3008edcfd..000000000 --- a/src/meta/meta-background-actor.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * meta-background-actor.h: Actor for painting the root window background - * - * Copyright 2010 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 . - */ - -#ifndef META_BACKGROUND_ACTOR_H -#define META_BACKGROUND_ACTOR_H - -#include - -#include "clutter/clutter.h" -#include "meta/meta-background.h" - -/** - * MetaBackgroundActor: - * - * This class handles tracking and painting the root window background. - * By integrating with #MetaWindowGroup we can avoid painting parts of - * the background that are obscured by other windows. - */ - -#define META_TYPE_BACKGROUND_ACTOR (meta_background_actor_get_type ()) - -META_EXPORT -G_DECLARE_FINAL_TYPE (MetaBackgroundActor, - meta_background_actor, - META, BACKGROUND_ACTOR, - ClutterActor) - - -META_EXPORT -ClutterActor *meta_background_actor_new (MetaDisplay *display, - int monitor); - -#endif /* META_BACKGROUND_ACTOR_H */ diff --git a/src/meta/meta-background-content.h b/src/meta/meta-background-content.h deleted file mode 100644 index a24ad809e..000000000 --- a/src/meta/meta-background-content.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * meta-background-content.h: ClutterContent for painting the wallpaper - * - * Copyright 2010 Red Hat, Inc. - * Copyright 2020 Endless Foundation - * - * 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 . - */ - -#ifndef META_BACKGROUND_CONTENT_H -#define META_BACKGROUND_CONTENT_H - -#include - -#include "clutter/clutter.h" -#include "meta/meta-background.h" - -/** - * MetaBackgroundContent: - * - * This class handles tracking and painting the root window background. - * By integrating with #MetaWindowGroup we can avoid painting parts of - * the background that are obscured by other windows. - */ - -#define META_TYPE_BACKGROUND_CONTENT (meta_background_content_get_type ()) - -META_EXPORT -G_DECLARE_FINAL_TYPE (MetaBackgroundContent, - meta_background_content, - META, BACKGROUND_CONTENT, - GObject) - - -META_EXPORT -ClutterContent *meta_background_content_new (MetaDisplay *display, - int monitor); - -META_EXPORT -void meta_background_content_set_background (MetaBackgroundContent *self, - MetaBackground *background); - -META_EXPORT -void meta_background_content_set_gradient (MetaBackgroundContent *self, - gboolean enabled, - int height, - double tone_start); - -META_EXPORT -void meta_background_content_set_vignette (MetaBackgroundContent *self, - gboolean enabled, - double brightness, - double sharpness); - -META_EXPORT -void meta_background_content_set_rounded_clip_radius (MetaBackgroundContent *self, - float radius); - -META_EXPORT -void meta_background_content_set_rounded_clip_bounds (MetaBackgroundContent *self, - const graphene_rect_t *bounds); - -#endif /* META_BACKGROUND_CONTENT_H */ diff --git a/src/meta/meta-background-group.h b/src/meta/meta-background-group.h deleted file mode 100644 index b43fcb94a..000000000 --- a/src/meta/meta-background-group.h +++ /dev/null @@ -1,26 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -#ifndef META_BACKGROUND_GROUP_H -#define META_BACKGROUND_GROUP_H - -#include "clutter/clutter.h" - -#include - -#define META_TYPE_BACKGROUND_GROUP (meta_background_group_get_type ()) - -META_EXPORT -G_DECLARE_DERIVABLE_TYPE (MetaBackgroundGroup, - meta_background_group, - META, BACKGROUND_GROUP, - ClutterActor) - -struct _MetaBackgroundGroupClass -{ - ClutterActorClass parent_class; -}; - -META_EXPORT -ClutterActor *meta_background_group_new (void); - -#endif /* META_BACKGROUND_GROUP_H */ diff --git a/src/meta/meta-background-image.h b/src/meta/meta-background-image.h deleted file mode 100644 index 137a6ff8e..000000000 --- a/src/meta/meta-background-image.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * MetaBackgroundImageCache: - * - * Simple cache for background textures loaded from files - * - * Copyright 2014 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 . - */ - -#ifndef __META_BACKGROUND_IMAGE_H__ -#define __META_BACKGROUND_IMAGE_H__ - -#include -#include - -#include "cogl/cogl.h" -#include "meta/display.h" - -#define META_TYPE_BACKGROUND_IMAGE (meta_background_image_get_type ()) - -META_EXPORT -G_DECLARE_FINAL_TYPE (MetaBackgroundImage, - meta_background_image, - META, BACKGROUND_IMAGE, - GObject) - -META_EXPORT -gboolean meta_background_image_is_loaded (MetaBackgroundImage *image); - -META_EXPORT -gboolean meta_background_image_get_success (MetaBackgroundImage *image); - -META_EXPORT -CoglTexture *meta_background_image_get_texture (MetaBackgroundImage *image); - - -#define META_TYPE_BACKGROUND_IMAGE_CACHE (meta_background_image_cache_get_type ()) - -META_EXPORT -G_DECLARE_FINAL_TYPE (MetaBackgroundImageCache, - meta_background_image_cache, - META, BACKGROUND_IMAGE_CACHE, - GObject) - -META_EXPORT -MetaBackgroundImageCache *meta_background_image_cache_get_default (void); - -META_EXPORT -MetaBackgroundImage *meta_background_image_cache_load (MetaBackgroundImageCache *cache, - GFile *file); - -META_EXPORT -void meta_background_image_cache_purge (MetaBackgroundImageCache *cache, - GFile *file); - -#endif /* __META_BACKGROUND_IMAGE_H__ */ diff --git a/src/meta/meta-background.h b/src/meta/meta-background.h deleted file mode 100644 index 550b1d986..000000000 --- a/src/meta/meta-background.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * meta-background-actor.h: for painting the root window background - * - * Copyright 2010 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 . - */ - -#ifndef META_BACKGROUND_H -#define META_BACKGROUND_H - -#include - -#include "clutter/clutter.h" -#include "meta/display.h" - -/** - * MetaBackground: - * - * This class handles tracking and painting the root window background. - * By integrating with #MetaWindowGroup we can avoid painting parts of - * the background that are obscured by other windows. - */ - -#define META_TYPE_BACKGROUND (meta_background_get_type ()) - -META_EXPORT -G_DECLARE_FINAL_TYPE (MetaBackground, - meta_background, - META, BACKGROUND, - GObject) - - -META_EXPORT -void meta_background_refresh_all (void); - -META_EXPORT -MetaBackground *meta_background_new (MetaDisplay *display); - -META_EXPORT -void meta_background_set_color (MetaBackground *self, - ClutterColor *color); - -META_EXPORT -void meta_background_set_gradient (MetaBackground *self, - GDesktopBackgroundShading shading_direction, - ClutterColor *color, - ClutterColor *second_color); - -META_EXPORT -void meta_background_set_file (MetaBackground *self, - GFile *file, - GDesktopBackgroundStyle style); - -META_EXPORT -void meta_background_set_blend (MetaBackground *self, - GFile *file1, - GFile *file2, - double blend_factor, - GDesktopBackgroundStyle style); - -#endif /* META_BACKGROUND_H */ diff --git a/src/meta/meta-close-dialog.h b/src/meta/meta-close-dialog.h deleted file mode 100644 index 281b0ee24..000000000 --- a/src/meta/meta-close-dialog.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 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, see . - * - * Author: Carlos Garnacho - */ - -#ifndef META_CLOSE_DIALOG_H -#define META_CLOSE_DIALOG_H - -#include -#include - -#define META_TYPE_CLOSE_DIALOG (meta_close_dialog_get_type ()) - -META_EXPORT -G_DECLARE_INTERFACE (MetaCloseDialog, meta_close_dialog, - META, CLOSE_DIALOG, GObject) - -typedef enum -{ - META_CLOSE_DIALOG_RESPONSE_WAIT, - META_CLOSE_DIALOG_RESPONSE_FORCE_CLOSE, -} MetaCloseDialogResponse; - -struct _MetaCloseDialogInterface -{ - GTypeInterface parent_iface; - - void (* show) (MetaCloseDialog *dialog); - void (* hide) (MetaCloseDialog *dialog); - void (* focus) (MetaCloseDialog *dialog); -}; - -META_EXPORT -void meta_close_dialog_show (MetaCloseDialog *dialog); - -META_EXPORT -void meta_close_dialog_hide (MetaCloseDialog *dialog); - -META_EXPORT -void meta_close_dialog_focus (MetaCloseDialog *dialog); - -META_EXPORT -gboolean meta_close_dialog_is_visible (MetaCloseDialog *dialog); - -META_EXPORT -void meta_close_dialog_response (MetaCloseDialog *dialog, - MetaCloseDialogResponse response); - -#endif /* META_CLOSE_DIALOG_H */ diff --git a/src/meta/meta-context.h b/src/meta/meta-context.h deleted file mode 100644 index 50b4bd5f9..000000000 --- a/src/meta/meta-context.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2019 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_CONTEXT_H -#define META_CONTEXT_H - -#include - -#include "meta/common.h" -#include "meta/meta-enums.h" -#include "meta/types.h" - -#define META_TYPE_CONTEXT (meta_context_get_type ()) -META_EXPORT -G_DECLARE_DERIVABLE_TYPE (MetaContext, meta_context, META, CONTEXT, GObject) - -META_EXPORT -MetaContext * meta_create_context (const char *name); - -META_EXPORT -void meta_context_destroy (MetaContext *context); - -META_EXPORT -void meta_context_add_option_entries (MetaContext *context, - const GOptionEntry *entries, - const char *translation_domain); - -META_EXPORT -void meta_context_add_option_group (MetaContext *context, - GOptionGroup *group); - -META_EXPORT -void meta_context_set_plugin_gtype (MetaContext *context, - GType plugin_gtype); - -META_EXPORT -void meta_context_set_plugin_name (MetaContext *context, - const char *plugin_name); - -META_EXPORT -void meta_context_set_gnome_wm_keybindings (MetaContext *context, - const char *wm_keybindings); - -META_EXPORT -gboolean meta_context_configure (MetaContext *context, - int *argc, - char ***argv, - GError **error); - -META_EXPORT -gboolean meta_context_setup (MetaContext *context, - GError **error); - -META_EXPORT -gboolean meta_context_start (MetaContext *context, - GError **error); - -META_EXPORT -gboolean meta_context_run_main_loop (MetaContext *context, - GError **error); - -META_EXPORT -void meta_context_notify_ready (MetaContext *context); - -META_EXPORT -void meta_context_terminate (MetaContext *context); - -META_EXPORT -void meta_context_terminate_with_error (MetaContext *context, - GError *error); - -META_EXPORT -MetaCompositorType meta_context_get_compositor_type (MetaContext *context); - -META_EXPORT -gboolean meta_context_is_replacing (MetaContext *context); - -META_EXPORT -MetaBackend * meta_context_get_backend (MetaContext *context); - -META_EXPORT -MetaDisplay * meta_context_get_display (MetaContext *context); - -#endif /* META_CONTEXT_H */ diff --git a/src/meta/meta-cursor-tracker.h b/src/meta/meta-cursor-tracker.h deleted file mode 100644 index a3b71c4f6..000000000 --- a/src/meta/meta-cursor-tracker.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2013 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - * - * Author: Giovanni Campagna - */ - -#ifndef META_CURSOR_TRACKER_H -#define META_CURSOR_TRACKER_H - -#include - -#include "clutter/clutter.h" -#include "cogl/cogl.h" -#include "meta/types.h" -#include "meta/workspace.h" - -#define META_TYPE_CURSOR_TRACKER (meta_cursor_tracker_get_type ()) - -META_EXPORT -G_DECLARE_DERIVABLE_TYPE (MetaCursorTracker, - meta_cursor_tracker, - META, CURSOR_TRACKER, - GObject) - -META_EXPORT -MetaCursorTracker *meta_cursor_tracker_get_for_display (MetaDisplay *display); - -META_EXPORT -void meta_cursor_tracker_get_hot (MetaCursorTracker *tracker, - int *x, - int *y); - -META_EXPORT -CoglTexture *meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker); - -META_EXPORT -void meta_cursor_tracker_get_pointer (MetaCursorTracker *tracker, - graphene_point_t *coords, - ClutterModifierType *mods); - -META_EXPORT -gboolean meta_cursor_tracker_get_pointer_visible (MetaCursorTracker *tracker); - -META_EXPORT -void meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker, - gboolean visible); - -#endif diff --git a/src/meta/meta-dnd.h b/src/meta/meta-dnd.h deleted file mode 100644 index 2b2be1029..000000000 --- a/src/meta/meta-dnd.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 Hyungwon Hwang - * - * 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 . - */ - -#ifndef META_DND_H -#define META_DND_H - -#include -#include - -#include -#include - -#define META_TYPE_DND (meta_dnd_get_type ()) - -META_EXPORT -G_DECLARE_FINAL_TYPE (MetaDnd, meta_dnd, META, DND, GObject) - -#endif /* META_DND_H */ diff --git a/src/meta/meta-enum-types.c.in b/src/meta/meta-enum-types.c.in deleted file mode 100644 index a5d839141..000000000 --- a/src/meta/meta-enum-types.c.in +++ /dev/null @@ -1,39 +0,0 @@ -/*** BEGIN file-header ***/ -#include -/*** END file-header ***/ - -/*** BEGIN file-production ***/ - -/* enumerations from "@filename@" */ -#include "@filename@" - -/*** END file-production ***/ - -/*** BEGIN value-header ***/ -GType -@enum_name@_get_type (void) -{ - static size_t g_enum_type_id = 0; - - if (g_once_init_enter (&g_enum_type_id)) - { - static const G@Type@Value values[] = { -/*** END value-header ***/ - -/*** BEGIN value-production ***/ - { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, -/*** END value-production ***/ - -/*** BEGIN value-tail ***/ - { 0, NULL, NULL } - }; - GType id; - - id = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); - - g_once_init_leave (&g_enum_type_id, id); - } - - return g_enum_type_id; -} -/*** END value-tail ***/ diff --git a/src/meta/meta-enum-types.h.in b/src/meta/meta-enum-types.h.in deleted file mode 100644 index bee0196de..000000000 --- a/src/meta/meta-enum-types.h.in +++ /dev/null @@ -1,27 +0,0 @@ -/*** BEGIN file-header ***/ -#ifndef __META_ENUM_TYPES_H__ -#define __META_ENUM_TYPES_H__ - -#include -#include - -G_BEGIN_DECLS - -/*** END file-header ***/ - -/*** BEGIN file-production ***/ -/* enumerations from "@basename@" */ -/*** END file-production ***/ - -/*** BEGIN file-tail ***/ -G_END_DECLS - -#endif /* !__MUTTER_ENUM_TYPES_H__ */ -/*** END file-tail ***/ - -/*** BEGIN value-header ***/ -META_EXPORT GType @enum_name@_get_type (void) G_GNUC_CONST; -#define META_TYPE_@ENUMSHORT@ (@enum_name@_get_type()) - -/*** END value-header ***/ - diff --git a/src/meta/meta-enums.h b/src/meta/meta-enums.h deleted file mode 100644 index 373d14451..000000000 --- a/src/meta/meta-enums.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2016-2021 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_ENUMS_H -#define META_ENUMS_H - -typedef enum _MetaCompositorType -{ - META_COMPOSITOR_TYPE_WAYLAND, - META_COMPOSITOR_TYPE_X11, -} MetaCompositorType; - -#endif /* META_ENUMS_H */ diff --git a/src/meta/meta-idle-monitor.h b/src/meta/meta-idle-monitor.h deleted file mode 100644 index 8cc9bf2bf..000000000 --- a/src/meta/meta-idle-monitor.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright 2013 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#ifndef META_IDLE_MONITOR_H -#define META_IDLE_MONITOR_H - -#include -#include - -#define META_TYPE_IDLE_MONITOR (meta_idle_monitor_get_type ()) -META_EXPORT -G_DECLARE_FINAL_TYPE (MetaIdleMonitor, meta_idle_monitor, - META, IDLE_MONITOR, - GObject) - -typedef void (*MetaIdleMonitorWatchFunc) (MetaIdleMonitor *monitor, - guint watch_id, - gpointer user_data); - -META_EXPORT -guint meta_idle_monitor_add_idle_watch (MetaIdleMonitor *monitor, - guint64 interval_msec, - MetaIdleMonitorWatchFunc callback, - gpointer user_data, - GDestroyNotify notify); - -META_EXPORT -guint meta_idle_monitor_add_user_active_watch (MetaIdleMonitor *monitor, - MetaIdleMonitorWatchFunc callback, - gpointer user_data, - GDestroyNotify notify); - -META_EXPORT -void meta_idle_monitor_remove_watch (MetaIdleMonitor *monitor, - guint id); - -META_EXPORT -gint64 meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor); - -#endif diff --git a/src/meta/meta-inhibit-shortcuts-dialog.h b/src/meta/meta-inhibit-shortcuts-dialog.h deleted file mode 100644 index 4e34f1701..000000000 --- a/src/meta/meta-inhibit-shortcuts-dialog.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2017 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, see . - * - */ - -#ifndef META_INHIBIT_SHORTCUTS_DIALOG_H -#define META_INHIBIT_SHORTCUTS_DIALOG_H - -#include -#include - -#define META_TYPE_INHIBIT_SHORTCUTS_DIALOG (meta_inhibit_shortcuts_dialog_get_type ()) - -META_EXPORT -G_DECLARE_INTERFACE (MetaInhibitShortcutsDialog, meta_inhibit_shortcuts_dialog, - META, INHIBIT_SHORTCUTS_DIALOG, GObject) - -typedef enum -{ - META_INHIBIT_SHORTCUTS_DIALOG_RESPONSE_ALLOW, - META_INHIBIT_SHORTCUTS_DIALOG_RESPONSE_DENY, -} MetaInhibitShortcutsDialogResponse; - -struct _MetaInhibitShortcutsDialogInterface -{ - GTypeInterface parent_iface; - - void (* show) (MetaInhibitShortcutsDialog *dialog); - void (* hide) (MetaInhibitShortcutsDialog *dialog); -}; - -META_EXPORT -void meta_inhibit_shortcuts_dialog_show (MetaInhibitShortcutsDialog *dialog); - -META_EXPORT -void meta_inhibit_shortcuts_dialog_hide (MetaInhibitShortcutsDialog *dialog); - -META_EXPORT -void meta_inhibit_shortcuts_dialog_response (MetaInhibitShortcutsDialog *dialog, - MetaInhibitShortcutsDialogResponse response); - -#endif /* META_INHIBIT_SHORTCUTS_DIALOG_H */ diff --git a/src/meta/meta-later.h b/src/meta/meta-later.h deleted file mode 100644 index 4464fc3bd..000000000 --- a/src/meta/meta-later.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2005 Elijah Newren - * Copyright (C) 2020 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 . - */ - -#ifndef META_LATER_H -#define META_LATER_H - -/** - * MetaLaterType: - * @META_LATER_RESIZE: call in a resize processing phase that is done - * before GTK+ repainting (including window borders) is done. - * @META_LATER_CALC_SHOWING: used by Mutter to compute which windows should be mapped - * @META_LATER_CHECK_FULLSCREEN: used by Mutter to see if there's a fullscreen window - * @META_LATER_SYNC_STACK: used by Mutter to send it's idea of the stacking order to the server - * @META_LATER_BEFORE_REDRAW: call before the stage is redrawn - * @META_LATER_IDLE: call at a very low priority (can be blocked - * by running animations or redrawing applications) - **/ -typedef enum -{ - META_LATER_RESIZE, - META_LATER_CALC_SHOWING, - META_LATER_CHECK_FULLSCREEN, - META_LATER_SYNC_STACK, - META_LATER_BEFORE_REDRAW, - META_LATER_IDLE -} MetaLaterType; - -META_EXPORT -guint meta_later_add (MetaLaterType when, - GSourceFunc func, - gpointer data, - GDestroyNotify notify); - -META_EXPORT -void meta_later_remove (guint later_id); - -#endif /* META_LATER_H */ diff --git a/src/meta/meta-launch-context.h b/src/meta/meta-launch-context.h deleted file mode 100644 index b719f0e07..000000000 --- a/src/meta/meta-launch-context.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2018 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: Carlos Garnacho - */ -#ifndef META_LAUNCH_CONTEXT_H -#define META_LAUNCH_CONTEXT_H - -#include - -META_EXPORT -G_DECLARE_FINAL_TYPE (MetaLaunchContext, meta_launch_context, META, LAUNCH_CONTEXT, GAppLaunchContext) - -#define META_TYPE_LAUNCH_CONTEXT (meta_launch_context_get_type ()) - -META_EXPORT -void meta_launch_context_set_timestamp (MetaLaunchContext *context, - uint32_t timestamp); - -META_EXPORT -void meta_launch_context_set_workspace (MetaLaunchContext *context, - MetaWorkspace *workspace); - -#endif /* META_LAUNCH_CONTEXT_H */ diff --git a/src/meta/meta-monitor-manager.h b/src/meta/meta-monitor-manager.h deleted file mode 100644 index ce57156be..000000000 --- a/src/meta/meta-monitor-manager.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015 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_MONITOR_MANAGER_H -#define META_MONITOR_MANAGER_H - -#include - -typedef enum -{ - META_MONITOR_SWITCH_CONFIG_ALL_MIRROR, - META_MONITOR_SWITCH_CONFIG_ALL_LINEAR, - META_MONITOR_SWITCH_CONFIG_EXTERNAL, - META_MONITOR_SWITCH_CONFIG_BUILTIN, - META_MONITOR_SWITCH_CONFIG_UNKNOWN, -} MetaMonitorSwitchConfigType; - -typedef struct _MetaMonitorManagerClass MetaMonitorManagerClass; -typedef struct _MetaMonitorManager MetaMonitorManager; - -META_EXPORT -GType meta_monitor_manager_get_type (void); - -META_EXPORT -MetaMonitorManager *meta_monitor_manager_get (void); - -META_EXPORT -gint meta_monitor_manager_get_monitor_for_connector (MetaMonitorManager *manager, - const char *connector); - -META_EXPORT -gboolean meta_monitor_manager_get_is_builtin_display_on (MetaMonitorManager *manager); - -META_EXPORT -void meta_monitor_manager_switch_config (MetaMonitorManager *manager, - MetaMonitorSwitchConfigType config_type); - -META_EXPORT -gboolean meta_monitor_manager_can_switch_config (MetaMonitorManager *manager); - -META_EXPORT -MetaMonitorSwitchConfigType meta_monitor_manager_get_switch_config (MetaMonitorManager *manager); - -META_EXPORT -gint meta_monitor_manager_get_display_configuration_timeout (void); - -META_EXPORT -gboolean meta_monitor_manager_get_panel_orientation_managed (MetaMonitorManager *manager); - -#endif /* META_MONITOR_MANAGER_H */ diff --git a/src/meta/meta-plugin.h b/src/meta/meta-plugin.h deleted file mode 100644 index 1bc19a5f0..000000000 --- a/src/meta/meta-plugin.h +++ /dev/null @@ -1,370 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (c) 2008 Intel Corp. - * - * Author: Tomas Frydrych - * - * 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 . - */ - -#ifndef META_PLUGIN_H_ -#define META_PLUGIN_H_ - -#include -#include - -#include "clutter/clutter.h" -#include "meta/compositor-mutter.h" -#include "meta/compositor.h" -#include "meta/meta-close-dialog.h" -#include "meta/meta-inhibit-shortcuts-dialog.h" -#include "meta/types.h" - -#define META_TYPE_PLUGIN (meta_plugin_get_type ()) - -META_EXPORT -G_DECLARE_DERIVABLE_TYPE (MetaPlugin, meta_plugin, META, PLUGIN, GObject) - -typedef struct _MetaPluginInfo MetaPluginInfo; - -/** - * MetaPluginClass: - * @start: virtual function called when the compositor starts managing a screen - * @minimize: virtual function called when a window is minimized - * @size_change: virtual function called when a window changes size to/from constraints - * @map: virtual function called when a window is mapped - * @destroy: virtual function called when a window is destroyed - * @switch_workspace: virtual function called when the user switches to another - * workspace - * @kill_window_effects: virtual function called when the effects on a window - * need to be killed prematurely; the plugin must call the completed() callback - * as if the effect terminated naturally - * @kill_switch_workspace: virtual function called when the workspace-switching - * effect needs to be killed prematurely - * @xevent_filter: virtual function called when handling each event - * @keybinding_filter: virtual function called when handling each keybinding - * @plugin_info: virtual function that returns information about the - * #MetaPlugin - */ -struct _MetaPluginClass -{ - /*< private >*/ - GObjectClass parent_class; - - /*< public >*/ - - /** - * MetaPluginClass::start: - * - * Virtual function called when the compositor starts managing a screen - */ - void (*start) (MetaPlugin *plugin); - - /** - * MetaPluginClass::minimize: - * @actor: a #MetaWindowActor - * - * Virtual function called when the window represented by @actor is minimized. - */ - void (*minimize) (MetaPlugin *plugin, - MetaWindowActor *actor); - - /** - * MetaPluginClass::unminimize: - * @actor: a #MetaWindowActor - * - * Virtual function called when the window represented by @actor is unminimized. - */ - void (*unminimize) (MetaPlugin *plugin, - MetaWindowActor *actor); - - void (*size_changed) (MetaPlugin *plugin, - MetaWindowActor *actor); - - void (*size_change) (MetaPlugin *plugin, - MetaWindowActor *actor, - MetaSizeChange which_change, - MetaRectangle *old_frame_rect, - MetaRectangle *old_buffer_rect); - - /** - * MetaPluginClass::map: - * @actor: a #MetaWindowActor - * - * Virtual function called when the window represented by @actor is mapped. - */ - void (*map) (MetaPlugin *plugin, - MetaWindowActor *actor); - - /** - * MetaPluginClass::destroy: - * @actor: a #MetaWindowActor - * - * Virtual function called when the window represented by @actor is destroyed. - */ - void (*destroy) (MetaPlugin *plugin, - MetaWindowActor *actor); - - /** - * MetaPluginClass::switch_workspace: - * @from: origin workspace - * @to: destination workspace - * @direction: a #MetaMotionDirection - * - * Virtual function called when the window represented by @actor is destroyed. - */ - void (*switch_workspace) (MetaPlugin *plugin, - gint from, - gint to, - MetaMotionDirection direction); - - void (*show_tile_preview) (MetaPlugin *plugin, - MetaWindow *window, - MetaRectangle *tile_rect, - int tile_monitor_number); - void (*hide_tile_preview) (MetaPlugin *plugin); - - void (*show_window_menu) (MetaPlugin *plugin, - MetaWindow *window, - MetaWindowMenuType menu, - int x, - int y); - - void (*show_window_menu_for_rect) (MetaPlugin *plugin, - MetaWindow *window, - MetaWindowMenuType menu, - MetaRectangle *rect); - - /** - * MetaPluginClass::kill_window_effects: - * @actor: a #MetaWindowActor - * - * Virtual function called when the effects on @actor need to be killed - * prematurely; the plugin must call the completed() callback as if the effect - * terminated naturally. - */ - void (*kill_window_effects) (MetaPlugin *plugin, - MetaWindowActor *actor); - - /** - * MetaPluginClass::kill_switch_workspace: - * - * Virtual function called when the workspace-switching effect needs to be - * killed prematurely. - */ - void (*kill_switch_workspace) (MetaPlugin *plugin); - - /** - * MetaPluginClass::xevent_filter: - * @event: (type xlib.XEvent): - * - * Virtual function called when handling each event. - * - * Returns: %TRUE if the plugin handled the event type (i.e., if the return - * value is %FALSE, there will be no subsequent call to the manager - * completed() callback, and the compositor must ensure that any appropriate - * post-effect cleanup is carried out. - */ - gboolean (*xevent_filter) (MetaPlugin *plugin, - XEvent *event); - - /** - * MetaPluginClass::keybinding_filter: - * @binding: a #MetaKeyBinding - * - * Virtual function called when handling each keybinding. - * - * Returns: %TRUE if the plugin handled the keybinding. - */ - gboolean (*keybinding_filter) (MetaPlugin *plugin, - MetaKeyBinding *binding); - - /** - * MetaPluginClass::confirm_display_config: - * @plugin: a #MetaPlugin - * - * Virtual function called when the display configuration changes. - * The common way to implement this function is to show some form - * of modal dialog that should ask the user if everything was ok. - * - * When confirmed by the user, the plugin must call meta_plugin_complete_display_change() - * to make the configuration permanent. If that function is not - * called within the timeout, the previous configuration will be - * reapplied. - */ - void (*confirm_display_change) (MetaPlugin *plugin); - - /** - * MetaPluginClass::plugin_info: - * @plugin: a #MetaPlugin - * - * Virtual function that returns information about the #MetaPlugin. - * - * Returns: a #MetaPluginInfo. - */ - const MetaPluginInfo * (*plugin_info) (MetaPlugin *plugin); - - /** - * MetaPluginClass::create_close_dialog: - * @plugin: a #MetaPlugin - * @window: a #MetaWindow - * - * Virtual function called to create a "force quit" dialog - * on non-responsive clients. - */ - MetaCloseDialog * (* create_close_dialog) (MetaPlugin *plugin, - MetaWindow *window); - - /** - * MetaPluginClass::create_inhibit_shortcuts_dialog: - * @plugin: a #MetaPlugin - * @window: a #MetaWindow - * - * Virtual function called to create a "inhibit shortcuts" dialog - * when a client requests compositor shortcuts to be inhibited. - */ - MetaInhibitShortcutsDialog * (* create_inhibit_shortcuts_dialog) (MetaPlugin *plugin, - MetaWindow *window); - - /** - * MetaPluginClass::locate_pointer: - * - * Virtual function called when the user triggered the "locate-pointer" - * mechanism. - * The common way to implement this function is to show some animation - * on screen to draw user attention on the pointer location. - */ - void (*locate_pointer) (MetaPlugin *plugin); -}; - -/** - * MetaPluginInfo: - * @name: name of the plugin - * @version: version of the plugin - * @author: author of the plugin - * @license: license of the plugin - * @description: description of the plugin - */ -struct _MetaPluginInfo -{ - const gchar *name; - const gchar *version; - const gchar *author; - const gchar *license; - const gchar *description; -}; - -META_EXPORT -const MetaPluginInfo * meta_plugin_get_info (MetaPlugin *plugin); - -/* - * Convenience macro to set up the plugin type. Based on GEdit. - */ -#define META_PLUGIN_DECLARE_WITH_CODE(ObjectName, object_name, CODE) \ - /* Prototypes */ \ - G_MODULE_EXPORT GType \ - object_name##_get_type (void); \ - \ - G_MODULE_EXPORT GType \ - meta_plugin_register_type (GTypeModule *type_module); \ - \ - \ - G_DEFINE_DYNAMIC_TYPE_EXTENDED(ObjectName, object_name, \ - META_TYPE_PLUGIN, 0, CODE) \ - \ - /* Unused, but required by G_DEFINE_DYNAMIC_TYPE */ \ - static void \ - object_name##_class_finalize (ObjectName##Class *klass) {} \ - \ - G_MODULE_EXPORT GType \ - meta_plugin_register_type (GTypeModule *type_module) \ - { \ - object_name##_register_type (type_module); \ - return object_name##_get_type (); \ - } \ - -#define META_PLUGIN_DECLARE(ObjectName, object_name) \ - META_PLUGIN_DECLARE_WITH_CODE(ObjectName, object_name, {}) - -META_EXPORT -void -meta_plugin_switch_workspace_completed (MetaPlugin *plugin); - -META_EXPORT -void -meta_plugin_minimize_completed (MetaPlugin *plugin, - MetaWindowActor *actor); - -META_EXPORT -void -meta_plugin_unminimize_completed (MetaPlugin *plugin, - MetaWindowActor *actor); - -META_EXPORT -void -meta_plugin_size_change_completed (MetaPlugin *plugin, - MetaWindowActor *actor); - -META_EXPORT -void -meta_plugin_map_completed (MetaPlugin *plugin, - MetaWindowActor *actor); - -META_EXPORT -void -meta_plugin_destroy_completed (MetaPlugin *plugin, - MetaWindowActor *actor); - -META_EXPORT -void -meta_plugin_complete_display_change (MetaPlugin *plugin, - gboolean ok); - -/** - * MetaModalOptions: - * @META_MODAL_POINTER_ALREADY_GRABBED: if set the pointer is already - * grabbed by the plugin and should not be grabbed again. - * @META_MODAL_KEYBOARD_ALREADY_GRABBED: if set the keyboard is already - * grabbed by the plugin and should not be grabbed again. - * - * Options that can be provided when calling meta_plugin_begin_modal(). - */ -typedef enum -{ - META_MODAL_POINTER_ALREADY_GRABBED = 1 << 0, - META_MODAL_KEYBOARD_ALREADY_GRABBED = 1 << 1 -} MetaModalOptions; - -META_EXPORT -gboolean -meta_plugin_begin_modal (MetaPlugin *plugin, - MetaModalOptions options, - guint32 timestamp); - -META_EXPORT -void -meta_plugin_end_modal (MetaPlugin *plugin, - guint32 timestamp); - -META_EXPORT -MetaDisplay *meta_plugin_get_display (MetaPlugin *plugin); - -void _meta_plugin_set_compositor (MetaPlugin *plugin, MetaCompositor *compositor); - -/* XXX: Putting this in here so it's in the public header. */ -META_EXPORT -void meta_plugin_manager_set_plugin_type (GType gtype); - -#endif /* META_PLUGIN_H_ */ diff --git a/src/meta/meta-remote-access-controller.h b/src/meta/meta-remote-access-controller.h deleted file mode 100644 index 81b717eac..000000000 --- a/src/meta/meta-remote-access-controller.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 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, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_REMOTE_ACCESS_CONTROLLER_H -#define META_REMOTE_ACCESS_CONTROLLER_H - -#include - -#include - -#define META_TYPE_REMOTE_ACCESS_HANDLE meta_remote_access_handle_get_type () - -META_EXPORT -G_DECLARE_DERIVABLE_TYPE (MetaRemoteAccessHandle, - meta_remote_access_handle, - META, REMOTE_ACCESS_HANDLE, - GObject) - -struct _MetaRemoteAccessHandleClass -{ - GObjectClass parent_class; - - void (*stop) (MetaRemoteAccessHandle *handle); -}; - -META_EXPORT -void meta_remote_access_handle_stop (MetaRemoteAccessHandle *handle); - -META_EXPORT -gboolean meta_remote_access_handle_get_disable_animations (MetaRemoteAccessHandle *handle); - -#define META_TYPE_REMOTE_ACCESS_CONTROLLER meta_remote_access_controller_get_type () - -META_EXPORT -G_DECLARE_FINAL_TYPE (MetaRemoteAccessController, - meta_remote_access_controller, - META, REMOTE_ACCESS_CONTROLLER, - GObject) - -META_EXPORT -void meta_remote_access_controller_inhibit_remote_access (MetaRemoteAccessController *controller); - -META_EXPORT -void meta_remote_access_controller_uninhibit_remote_access (MetaRemoteAccessController *controller); - -#endif /* META_REMOTE_ACCESS_CONTROLLER_H */ diff --git a/src/meta/meta-selection-source-memory.h b/src/meta/meta-selection-source-memory.h deleted file mode 100644 index b72e12762..000000000 --- a/src/meta/meta-selection-source-memory.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2018 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: Carlos Garnacho - */ - -#ifndef META_MEMORY_SELECTION_SOURCE_H -#define META_MEMORY_SELECTION_SOURCE_H - -#include "meta/meta-selection-source.h" - -#define META_TYPE_SELECTION_SOURCE_MEMORY (meta_selection_source_memory_get_type ()) - -META_EXPORT -G_DECLARE_FINAL_TYPE (MetaSelectionSourceMemory, - meta_selection_source_memory, - META, SELECTION_SOURCE_MEMORY, - MetaSelectionSource) - -META_EXPORT -MetaSelectionSource * meta_selection_source_memory_new (const char *mimetype, - GBytes *content); - -#endif /* META_SELECTION_SOURCE_MEMORY_H */ diff --git a/src/meta/meta-selection-source.h b/src/meta/meta-selection-source.h deleted file mode 100644 index a341bede1..000000000 --- a/src/meta/meta-selection-source.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2018 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: Carlos Garnacho - */ - -#ifndef META_SELECTION_SOURCE_H -#define META_SELECTION_SOURCE_H - -#include - -#include - -typedef enum -{ - META_SELECTION_PRIMARY, - META_SELECTION_CLIPBOARD, - META_SELECTION_DND, - META_N_SELECTION_TYPES, -} MetaSelectionType; - -typedef struct _MetaSelectionSourceClass MetaSelectionSourceClass; -typedef struct _MetaSelectionSource MetaSelectionSource; - -#define META_TYPE_SELECTION_SOURCE (meta_selection_source_get_type ()) - -META_EXPORT -G_DECLARE_DERIVABLE_TYPE (MetaSelectionSource, - meta_selection_source, - META, SELECTION_SOURCE, - GObject) - -struct _MetaSelectionSourceClass -{ - GObjectClass parent_class; - - void (* activated) (MetaSelectionSource *source); - void (* deactivated) (MetaSelectionSource *source); - - GList * (* get_mimetypes) (MetaSelectionSource *source); - - void (* read_async) (MetaSelectionSource *source, - const gchar *mimetype, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - GInputStream * (* read_finish) (MetaSelectionSource *source, - GAsyncResult *result, - GError **error); -}; - -META_EXPORT -void meta_selection_source_read_async (MetaSelectionSource *source, - const gchar *mimetype, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -META_EXPORT -GInputStream * meta_selection_source_read_finish (MetaSelectionSource *source, - GAsyncResult *result, - GError **error); - -META_EXPORT -GList * meta_selection_source_get_mimetypes (MetaSelectionSource *source); - -META_EXPORT -gboolean meta_selection_source_is_active (MetaSelectionSource *source); - -#endif /* META_SELECTION_SOURCE_H */ diff --git a/src/meta/meta-selection.h b/src/meta/meta-selection.h deleted file mode 100644 index ef86dce1d..000000000 --- a/src/meta/meta-selection.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2018 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: Carlos Garnacho - */ - -#ifndef META_SELECTION_H -#define META_SELECTION_H - -#include - -#include -#include -#include - -#define META_TYPE_SELECTION (meta_selection_get_type ()) - -META_EXPORT -G_DECLARE_FINAL_TYPE (MetaSelection, - meta_selection, - META, SELECTION, - GObject) - -META_EXPORT -MetaSelection * - meta_selection_new (MetaDisplay *display); - -META_EXPORT -void meta_selection_set_owner (MetaSelection *selection, - MetaSelectionType selection_type, - MetaSelectionSource *owner); -META_EXPORT -void meta_selection_unset_owner (MetaSelection *selection, - MetaSelectionType selection_type, - MetaSelectionSource *owner); - -META_EXPORT -GList * meta_selection_get_mimetypes (MetaSelection *selection, - MetaSelectionType selection_type); - -META_EXPORT -void meta_selection_transfer_async (MetaSelection *selection, - MetaSelectionType selection_type, - const gchar *mimetype, - gssize size, - GOutputStream *output, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -META_EXPORT -gboolean meta_selection_transfer_finish (MetaSelection *selection, - GAsyncResult *result, - GError **error); - -#endif /* META_SELECTION_H */ diff --git a/src/meta/meta-settings.h b/src/meta/meta-settings.h deleted file mode 100644 index 5683d7c1d..000000000 --- a/src/meta/meta-settings.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 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_SETTINGS_H -#define META_SETTINGS_H - -#include -#include - -META_EXPORT -int meta_settings_get_ui_scaling_factor (MetaSettings *settings); - -META_EXPORT -int meta_settings_get_font_dpi (MetaSettings *settings); - -#endif /* META_SETTINGS_H */ diff --git a/src/meta/meta-shadow-factory.h b/src/meta/meta-shadow-factory.h deleted file mode 100644 index a3aa0847c..000000000 --- a/src/meta/meta-shadow-factory.h +++ /dev/null @@ -1,135 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * MetaShadowFactory: - * - * Create and cache shadow textures for arbitrary window shapes - * - * Copyright (C) 2010 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 . - */ - -#ifndef __META_SHADOW_FACTORY_H__ -#define __META_SHADOW_FACTORY_H__ - -#include - -#include "clutter/clutter.h" -#include "cogl/cogl.h" -#include "meta/meta-window-shape.h" - -META_EXPORT -GType meta_shadow_get_type (void) G_GNUC_CONST; - -/** - * MetaShadowParams: - * @radius: the radius (gaussian standard deviation) of the shadow - * @top_fade: if >= 0, the shadow doesn't extend above the top - * of the shape, and fades out over the given number of pixels - * @x_offset: horizontal offset of the shadow with respect to the - * shape being shadowed, in pixels - * @y_offset: vertical offset of the shadow with respect to the - * shape being shadowed, in pixels - * @opacity: opacity of the shadow, from 0 to 255 - * - * The #MetaShadowParams structure holds information about how to draw - * a particular style of shadow. - */ - -typedef struct _MetaShadowParams MetaShadowParams; - -struct _MetaShadowParams -{ - int radius; - int top_fade; - int x_offset; - int y_offset; - guint8 opacity; -}; - -#define META_TYPE_SHADOW_FACTORY (meta_shadow_factory_get_type ()) - -META_EXPORT -G_DECLARE_FINAL_TYPE (MetaShadowFactory, - meta_shadow_factory, - META, SHADOW_FACTORY, - GObject) - -/** - * MetaShadowFactory: - * - * #MetaShadowFactory is used to create window shadows. It caches shadows internally - * so that multiple shadows created for the same shape with the same radius will - * share the same MetaShadow. - */ -META_EXPORT -MetaShadowFactory *meta_shadow_factory_get_default (void); - -META_EXPORT -void meta_shadow_factory_set_params (MetaShadowFactory *factory, - const char *class_name, - gboolean focused, - MetaShadowParams *params); - -META_EXPORT -void meta_shadow_factory_get_params (MetaShadowFactory *factory, - const char *class_name, - gboolean focused, - MetaShadowParams *params); - -/** - * MetaShadow: - * #MetaShadow holds a shadow texture along with information about how to - * apply that texture to draw a window texture. (E.g., it knows how big the - * unscaled borders are on each side of the shadow texture.) - */ -typedef struct _MetaShadow MetaShadow; - -META_EXPORT -MetaShadow *meta_shadow_ref (MetaShadow *shadow); - -META_EXPORT -void meta_shadow_unref (MetaShadow *shadow); - -META_EXPORT -void meta_shadow_paint (MetaShadow *shadow, - CoglFramebuffer *framebuffer, - int window_x, - int window_y, - int window_width, - int window_height, - guint8 opacity, - cairo_region_t *clip, - gboolean clip_strictly); - -META_EXPORT -void meta_shadow_get_bounds (MetaShadow *shadow, - int window_x, - int window_y, - int window_width, - int window_height, - cairo_rectangle_int_t *bounds); - -META_EXPORT -MetaShadowFactory *meta_shadow_factory_new (void); - -META_EXPORT -MetaShadow *meta_shadow_factory_get_shadow (MetaShadowFactory *factory, - MetaWindowShape *shape, - int width, - int height, - const char *class_name, - gboolean focused); - -#endif /* __META_SHADOW_FACTORY_H__ */ diff --git a/src/meta/meta-shaped-texture.h b/src/meta/meta-shaped-texture.h deleted file mode 100644 index 2ca0e6e61..000000000 --- a/src/meta/meta-shaped-texture.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * shaped texture - * - * An actor to draw a texture clipped to a list of rectangles - * - * Authored By Neil Roberts - * - * Copyright (C) 2008 Intel Corporation - * - * 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 . - */ - -#ifndef __META_SHAPED_TEXTURE_H__ -#define __META_SHAPED_TEXTURE_H__ - -#include - -#include "clutter/clutter.h" -#include - -G_BEGIN_DECLS - -#define META_TYPE_SHAPED_TEXTURE (meta_shaped_texture_get_type ()) - -META_EXPORT -G_DECLARE_FINAL_TYPE (MetaShapedTexture, - meta_shaped_texture, - META, SHAPED_TEXTURE, - GObject) - - -META_EXPORT -void meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex, - gboolean create_mipmaps); - -META_EXPORT -CoglTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex); - -META_EXPORT -void meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex, - CoglTexture *mask_texture); - -META_EXPORT -cairo_surface_t * meta_shaped_texture_get_image (MetaShapedTexture *stex, - cairo_rectangle_int_t *clip); - -G_END_DECLS - -#endif /* __META_SHAPED_TEXTURE_H__ */ diff --git a/src/meta/meta-sound-player.h b/src/meta/meta-sound-player.h deleted file mode 100644 index 4183689cd..000000000 --- a/src/meta/meta-sound-player.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2018 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: Carlos Garnacho - */ -#ifndef META_SOUND_PLAYER_H -#define META_SOUND_PLAYER_H - -#include - -#include - -#define META_TYPE_SOUND_PLAYER (meta_sound_player_get_type ()) - -META_EXPORT -G_DECLARE_FINAL_TYPE (MetaSoundPlayer, meta_sound_player, - META, SOUND_PLAYER, GObject) - -META_EXPORT -void meta_sound_player_play_from_theme (MetaSoundPlayer *player, - const char *name, - const char *description, - GCancellable *cancellable); - -META_EXPORT -void meta_sound_player_play_from_file (MetaSoundPlayer *player, - GFile *file, - const char *description, - GCancellable *cancellable); - -#endif /* META_SOUND_PLAYER_H */ diff --git a/src/meta/meta-stage.h b/src/meta/meta-stage.h deleted file mode 100644 index afab102e5..000000000 --- a/src/meta/meta-stage.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2012 Intel Corporation - * - * 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_STAGE_H -#define META_STAGE_H - -#include "clutter/clutter.h" - -G_BEGIN_DECLS - -#define META_TYPE_STAGE (meta_stage_get_type ()) - -META_EXPORT -G_DECLARE_FINAL_TYPE (MetaStage, meta_stage, META, STAGE, ClutterStage) - -G_END_DECLS - -#endif /* META_STAGE_H */ diff --git a/src/meta/meta-startup-notification.h b/src/meta/meta-startup-notification.h deleted file mode 100644 index 11afb3e05..000000000 --- a/src/meta/meta-startup-notification.h +++ /dev/null @@ -1,76 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * Copyright (C) 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 . - */ - -#ifndef META_STARTUP_NOTIFICATION_H -#define META_STARTUP_NOTIFICATION_H - -#include - -#define META_TYPE_STARTUP_SEQUENCE (meta_startup_sequence_get_type ()) -#define META_TYPE_STARTUP_NOTIFICATION (meta_startup_notification_get_type ()) - -META_EXPORT -G_DECLARE_FINAL_TYPE (MetaStartupNotification, - meta_startup_notification, - META, STARTUP_NOTIFICATION, - GObject) - -META_EXPORT -G_DECLARE_DERIVABLE_TYPE (MetaStartupSequence, - meta_startup_sequence, - META, STARTUP_SEQUENCE, - GObject) - -/** - * meta_startup_notification_get_sequences: (skip) - */ -META_EXPORT -GSList * meta_startup_notification_get_sequences (MetaStartupNotification *sn); - -META_EXPORT -MetaLaunchContext * - meta_startup_notification_create_launcher (MetaStartupNotification *sn); - -META_EXPORT -const char * meta_startup_sequence_get_id (MetaStartupSequence *sequence); - -META_EXPORT -gboolean meta_startup_sequence_get_completed (MetaStartupSequence *sequence); - -META_EXPORT -const char * meta_startup_sequence_get_name (MetaStartupSequence *sequence); - -META_EXPORT -int meta_startup_sequence_get_workspace (MetaStartupSequence *sequence); - -META_EXPORT -uint64_t meta_startup_sequence_get_timestamp (MetaStartupSequence *sequence); - -META_EXPORT -const char * meta_startup_sequence_get_icon_name (MetaStartupSequence *sequence); - -META_EXPORT -const char * meta_startup_sequence_get_application_id (MetaStartupSequence *sequence); - -META_EXPORT -const char * meta_startup_sequence_get_wmclass (MetaStartupSequence *sequence); - -META_EXPORT -void meta_startup_sequence_complete (MetaStartupSequence *sequence); - -#endif /* META_STARTUP_NOTIFICATION_H */ diff --git a/src/meta/meta-wayland-client.h b/src/meta/meta-wayland-client.h deleted file mode 100644 index 911048b3e..000000000 --- a/src/meta/meta-wayland-client.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright 2019 Sergio Costas (rastersoft@gmail.com) - * - * 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_WAYLAND_CLIENT_H -#define META_WAYLAND_CLIENT_H - -#include -#include - -#include "meta/display.h" - -G_BEGIN_DECLS - -#define META_TYPE_WAYLAND_CLIENT (meta_wayland_client_get_type ()) -META_EXPORT -G_DECLARE_FINAL_TYPE (MetaWaylandClient, meta_wayland_client, META, WAYLAND_CLIENT, GObject) - -META_EXPORT -MetaWaylandClient *meta_wayland_client_new (GSubprocessLauncher *launcher, - GError **error); - -META_EXPORT -GSubprocess *meta_wayland_client_spawn (MetaWaylandClient *client, - MetaDisplay *display, - GError **error, - const char *argv0, - ...) G_GNUC_NULL_TERMINATED; - -META_EXPORT -GSubprocess *meta_wayland_client_spawnv (MetaWaylandClient *client, - MetaDisplay *display, - const char * const *argv, - GError **error); - -META_EXPORT -gboolean meta_wayland_client_owns_window (MetaWaylandClient *client, - MetaWindow *window); - -META_EXPORT -void meta_wayland_client_hide_from_window_list (MetaWaylandClient *client, - MetaWindow *window); - -META_EXPORT -void meta_wayland_client_show_in_window_list (MetaWaylandClient *client, - MetaWindow *window); - -G_END_DECLS - -#endif /* META_WAYLAND_CLIENT_H */ diff --git a/src/meta/meta-window-actor.h b/src/meta/meta-window-actor.h deleted file mode 100644 index 6e18683a2..000000000 --- a/src/meta/meta-window-actor.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2008 Matthew Allum - * Copyright (C) 2007 Iain Holmes - * Based on xcompmgr - (c) 2003 Keith Packard - * xfwm4 - (c) 2005-2007 Olivier Fourdan - * - * 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 . - */ - -#ifndef META_WINDOW_ACTOR_H_ -#define META_WINDOW_ACTOR_H_ - -#include "clutter/clutter.h" -#include "meta/compositor.h" -#include "meta/meta-shaped-texture.h" - -#define META_TYPE_WINDOW_ACTOR (meta_window_actor_get_type ()) - -META_EXPORT -G_DECLARE_DERIVABLE_TYPE (MetaWindowActor, - meta_window_actor, - META, WINDOW_ACTOR, - ClutterActor) - -META_EXPORT -MetaWindow * meta_window_actor_get_meta_window (MetaWindowActor *self); - -META_EXPORT -MetaShapedTexture *meta_window_actor_get_texture (MetaWindowActor *self); - -META_EXPORT -void meta_window_actor_sync_visibility (MetaWindowActor *self); - -META_EXPORT -gboolean meta_window_actor_is_destroyed (MetaWindowActor *self); - -META_EXPORT -cairo_surface_t * meta_window_actor_get_image (MetaWindowActor *self, - cairo_rectangle_int_t *clip); - -META_EXPORT -void meta_window_actor_freeze (MetaWindowActor *self); - -META_EXPORT -void meta_window_actor_thaw (MetaWindowActor *self); - -typedef enum -{ - META_SHADOW_MODE_AUTO, - META_SHADOW_MODE_FORCED_OFF, - META_SHADOW_MODE_FORCED_ON, -} MetaShadowMode; - -#endif /* META_WINDOW_ACTOR_H */ diff --git a/src/meta/meta-window-group.h b/src/meta/meta-window-group.h deleted file mode 100644 index cfc487e7c..000000000 --- a/src/meta/meta-window-group.h +++ /dev/null @@ -1,16 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -#ifndef META_WINDOW_GROUP_H -#define META_WINDOW_GROUP_H - -#include "clutter/clutter.h" - -#define META_TYPE_WINDOW_GROUP (meta_window_group_get_type()) - -META_EXPORT -G_DECLARE_FINAL_TYPE (MetaWindowGroup, - meta_window_group, - META, WINDOW_GROUP, - ClutterActor) - -#endif /* META_WINDOW_GROUP_H */ diff --git a/src/meta/meta-window-shape.h b/src/meta/meta-window-shape.h deleted file mode 100644 index ec9fa7da1..000000000 --- a/src/meta/meta-window-shape.h +++ /dev/null @@ -1,76 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * MetaWindowShape - * - * Extracted invariant window shape - * - * Copyright (C) 2010 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 . - */ - -#ifndef __META_WINDOW_SHAPE_H__ -#define __META_WINDOW_SHAPE_H__ - -#include -#include - -#include - -META_EXPORT -GType meta_window_shape_get_type (void) G_GNUC_CONST; - -/** - * MetaWindowShape: - * #MetaWindowShape represents a 9-sliced region with borders on all sides that - * are unscaled, and a constant central region that is scaled. For example, - * the regions representing two windows that are rounded rectangles, - * with the same corner radius but different sizes, have the - * same MetaWindowShape. - * - * #MetaWindowShape is designed to be used as part of a hash table key, so has - * efficient hash and equal functions. - */ -typedef struct _MetaWindowShape MetaWindowShape; - -META_EXPORT -MetaWindowShape * meta_window_shape_new (cairo_region_t *region); - -META_EXPORT -MetaWindowShape * meta_window_shape_ref (MetaWindowShape *shape); - -META_EXPORT -void meta_window_shape_unref (MetaWindowShape *shape); - -META_EXPORT -guint meta_window_shape_hash (MetaWindowShape *shape); - -META_EXPORT -gboolean meta_window_shape_equal (MetaWindowShape *shape_a, - MetaWindowShape *shape_b); - -META_EXPORT -void meta_window_shape_get_borders (MetaWindowShape *shape, - int *border_top, - int *border_right, - int *border_bottom, - int *border_left); - -META_EXPORT -cairo_region_t *meta_window_shape_to_region (MetaWindowShape *shape, - int center_width, - int center_height); - -#endif /* __META_WINDOW_SHAPE_H __*/ - diff --git a/src/meta/meta-workspace-manager.h b/src/meta/meta-workspace-manager.h deleted file mode 100644 index 92cd68191..000000000 --- a/src/meta/meta-workspace-manager.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002, 2003, 2004 Red Hat, Inc. - * Copyright (C) 2003, 2004 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * 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 . - */ - -#ifndef META_WORKSPACE_MANAGER_H -#define META_WORKSPACE_MANAGER_H - -#include - -#include -#include -#include -#include - -#define META_TYPE_WORKSPACE_MANAGER (meta_workspace_manager_get_type ()) - -META_EXPORT -G_DECLARE_FINAL_TYPE (MetaWorkspaceManager, - meta_workspace_manager, - META, WORKSPACE_MANAGER, - GObject) - -META_EXPORT -GList *meta_workspace_manager_get_workspaces (MetaWorkspaceManager *workspace_manager); - -META_EXPORT -int meta_workspace_manager_get_n_workspaces (MetaWorkspaceManager *workspace_manager); - -META_EXPORT -MetaWorkspace* meta_workspace_manager_get_workspace_by_index (MetaWorkspaceManager *workspace_manager, - int index); - -META_EXPORT -void meta_workspace_manager_remove_workspace (MetaWorkspaceManager *workspace_manager, - MetaWorkspace *workspace, - guint32 timestamp); - -META_EXPORT -MetaWorkspace *meta_workspace_manager_append_new_workspace (MetaWorkspaceManager *workspace_manager, - gboolean activate, - guint32 timestamp); - -META_EXPORT -void meta_workspace_manager_reorder_workspace (MetaWorkspaceManager *workspace_manager, - MetaWorkspace *workspace, - int new_index); - -META_EXPORT -int meta_workspace_manager_get_active_workspace_index (MetaWorkspaceManager *workspace_manager); - -META_EXPORT -MetaWorkspace *meta_workspace_manager_get_active_workspace (MetaWorkspaceManager *workspace_manager); - -META_EXPORT -void meta_workspace_manager_override_workspace_layout (MetaWorkspaceManager *workspace_manager, - MetaDisplayCorner starting_corner, - gboolean vertical_layout, - int n_rows, - int n_columns); -#endif /* META_WORKSPACE_MANAGER_H */ diff --git a/src/meta/meta-x11-display.h b/src/meta/meta-x11-display.h deleted file mode 100644 index eb84c2b20..000000000 --- a/src/meta/meta-x11-display.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2008 Iain Holmes - * - * 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 . - */ - -#ifndef META_X11_DISPLAY_H -#define META_X11_DISPLAY_H - -#include -#include - -#include -#include -#include - -#define META_TYPE_X11_DISPLAY (meta_x11_display_get_type ()) - -META_EXPORT -G_DECLARE_FINAL_TYPE (MetaX11Display, meta_x11_display, META, X11_DISPLAY, GObject) - -META_EXPORT -gboolean meta_x11_init_gdk_display (GError **error); - -META_EXPORT -int meta_x11_display_get_screen_number (MetaX11Display *x11_display); - -META_EXPORT -Display *meta_x11_display_get_xdisplay (MetaX11Display *x11_display); - -META_EXPORT -Window meta_x11_display_get_xroot (MetaX11Display *x11_display); - -META_EXPORT -int meta_x11_display_get_xinput_opcode (MetaX11Display *x11_display); - -META_EXPORT -int meta_x11_display_get_damage_event_base (MetaX11Display *x11_display); - -META_EXPORT -int meta_x11_display_get_shape_event_base (MetaX11Display *x11_display); - -META_EXPORT -gboolean meta_x11_display_has_shape (MetaX11Display *x11_display); - -META_EXPORT -void meta_x11_display_set_cm_selection (MetaX11Display *x11_display); - -META_EXPORT -gboolean meta_x11_display_xwindow_is_a_no_focus_window (MetaX11Display *x11_display, - Window xwindow); - -META_EXPORT -void meta_x11_display_set_stage_input_region (MetaX11Display *x11_display, - XserverRegion region); - -META_EXPORT -void meta_x11_display_clear_stage_input_region (MetaX11Display *x11_display); - -#endif /* META_X11_DISPLAY_H */ diff --git a/src/meta/meta-x11-errors.h b/src/meta/meta-x11-errors.h deleted file mode 100644 index ec9fa5c71..000000000 --- a/src/meta/meta-x11-errors.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter X error handling */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * 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 . - */ - -#ifndef META_ERRORS_H -#define META_ERRORS_H - -#include - -#include -#include - -META_EXPORT -void meta_x11_error_trap_push (MetaX11Display *x11_display); - -META_EXPORT -void meta_x11_error_trap_pop (MetaX11Display *x11_display); - -/* returns X error code, or 0 for no error */ -META_EXPORT -int meta_x11_error_trap_pop_with_return (MetaX11Display *x11_display); - - -#endif diff --git a/src/meta/prefs.h b/src/meta/prefs.h deleted file mode 100644 index 7a8bfab96..000000000 --- a/src/meta/prefs.h +++ /dev/null @@ -1,485 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter preferences */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2006 Elijah Newren - * - * 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 . - */ - -#ifndef META_PREFS_H -#define META_PREFS_H - -/* This header is a "common" one between the UI and core side */ -#include -#include -#include -#include -#include - -/** - * MetaPreference: - * @META_PREF_MOUSE_BUTTON_MODS: mouse button modifiers - * @META_PREF_FOCUS_MODE: focus mode - * @META_PREF_FOCUS_NEW_WINDOWS: focus new windows - * @META_PREF_ATTACH_MODAL_DIALOGS: attach modal dialogs - * @META_PREF_RAISE_ON_CLICK: raise on click - * @META_PREF_ACTION_DOUBLE_CLICK_TITLEBAR: action double click titlebar - * @META_PREF_ACTION_MIDDLE_CLICK_TITLEBAR: action middle click titlebar - * @META_PREF_ACTION_RIGHT_CLICK_TITLEBAR: action right click titlebar - * @META_PREF_AUTO_RAISE: auto-raise - * @META_PREF_AUTO_RAISE_DELAY: auto-raise delay - * @META_PREF_FOCUS_CHANGE_ON_POINTER_REST: focus change on pointer rest - * @META_PREF_TITLEBAR_FONT: title-bar font - * @META_PREF_NUM_WORKSPACES: number of workspaces - * @META_PREF_DYNAMIC_WORKSPACES: dynamic workspaces - * @META_PREF_KEYBINDINGS: keybindings - * @META_PREF_DISABLE_WORKAROUNDS: disable workarounds - * @META_PREF_BUTTON_LAYOUT: button layout - * @META_PREF_WORKSPACE_NAMES: workspace names - * @META_PREF_VISUAL_BELL: visual bell - * @META_PREF_AUDIBLE_BELL: audible bell - * @META_PREF_VISUAL_BELL_TYPE: visual bell type - * @META_PREF_GNOME_ACCESSIBILITY: GNOME accessibility - * @META_PREF_GNOME_ANIMATIONS: GNOME animations - * @META_PREF_CURSOR_THEME: cursor theme - * @META_PREF_CURSOR_SIZE: cursor size - * @META_PREF_RESIZE_WITH_RIGHT_BUTTON: resize with right button - * @META_PREF_EDGE_TILING: edge tiling - * @META_PREF_FORCE_FULLSCREEN: force fullscreen - * @META_PREF_WORKSPACES_ONLY_ON_PRIMARY: workspaces only on primary - * @META_PREF_DRAGGABLE_BORDER_WIDTH: draggable border width - * @META_PREF_AUTO_MAXIMIZE: auto-maximize - * @META_PREF_CENTER_NEW_WINDOWS: center new windows - * @META_PREF_DRAG_THRESHOLD: drag threshold - * @META_PREF_LOCATE_POINTER: show pointer location - */ - -/* Keep in sync with GSettings schemas! */ -typedef enum -{ - META_PREF_MOUSE_BUTTON_MODS, - META_PREF_FOCUS_MODE, - META_PREF_FOCUS_NEW_WINDOWS, - META_PREF_ATTACH_MODAL_DIALOGS, - META_PREF_RAISE_ON_CLICK, - META_PREF_ACTION_DOUBLE_CLICK_TITLEBAR, - META_PREF_ACTION_MIDDLE_CLICK_TITLEBAR, - META_PREF_ACTION_RIGHT_CLICK_TITLEBAR, - META_PREF_AUTO_RAISE, - META_PREF_AUTO_RAISE_DELAY, - META_PREF_FOCUS_CHANGE_ON_POINTER_REST, - META_PREF_TITLEBAR_FONT, - META_PREF_NUM_WORKSPACES, - META_PREF_DYNAMIC_WORKSPACES, - META_PREF_KEYBINDINGS, - META_PREF_DISABLE_WORKAROUNDS, - META_PREF_BUTTON_LAYOUT, - META_PREF_WORKSPACE_NAMES, - META_PREF_VISUAL_BELL, - META_PREF_AUDIBLE_BELL, - META_PREF_VISUAL_BELL_TYPE, - META_PREF_GNOME_ACCESSIBILITY, - META_PREF_GNOME_ANIMATIONS, - META_PREF_CURSOR_THEME, - META_PREF_CURSOR_SIZE, - META_PREF_RESIZE_WITH_RIGHT_BUTTON, - META_PREF_EDGE_TILING, - META_PREF_FORCE_FULLSCREEN, - META_PREF_WORKSPACES_ONLY_ON_PRIMARY, - META_PREF_DRAGGABLE_BORDER_WIDTH, - META_PREF_AUTO_MAXIMIZE, - META_PREF_CENTER_NEW_WINDOWS, - META_PREF_DRAG_THRESHOLD, - META_PREF_LOCATE_POINTER, - META_PREF_CHECK_ALIVE_TIMEOUT, -} MetaPreference; - -typedef void (* MetaPrefsChangedFunc) (MetaPreference pref, - gpointer user_data); - -META_EXPORT -void meta_prefs_add_listener (MetaPrefsChangedFunc func, - gpointer user_data); - -META_EXPORT -void meta_prefs_remove_listener (MetaPrefsChangedFunc func, - gpointer user_data); - -META_EXPORT -const char* meta_preference_to_string (MetaPreference pref); - -META_EXPORT -MetaVirtualModifier meta_prefs_get_mouse_button_mods (void); - -META_EXPORT -gint meta_prefs_get_mouse_button_resize (void); - -META_EXPORT -gint meta_prefs_get_mouse_button_menu (void); - -META_EXPORT -GDesktopFocusMode meta_prefs_get_focus_mode (void); - -META_EXPORT -GDesktopFocusNewWindows meta_prefs_get_focus_new_windows (void); - -META_EXPORT -gboolean meta_prefs_get_attach_modal_dialogs (void); - -META_EXPORT -gboolean meta_prefs_get_raise_on_click (void); - -/* returns NULL if GTK default should be used */ -META_EXPORT -const PangoFontDescription* meta_prefs_get_titlebar_font (void); - -META_EXPORT -int meta_prefs_get_num_workspaces (void); - -META_EXPORT -gboolean meta_prefs_get_dynamic_workspaces (void); - -META_EXPORT -gboolean meta_prefs_get_disable_workarounds (void); - -META_EXPORT -gboolean meta_prefs_get_auto_raise (void); - -META_EXPORT -int meta_prefs_get_auto_raise_delay (void); - -META_EXPORT -gboolean meta_prefs_get_focus_change_on_pointer_rest (void); - -META_EXPORT -gboolean meta_prefs_get_gnome_accessibility (void); - -META_EXPORT -gboolean meta_prefs_get_gnome_animations (void); - -META_EXPORT -gboolean meta_prefs_get_edge_tiling (void); - -META_EXPORT -gboolean meta_prefs_get_auto_maximize (void); - -META_EXPORT -gboolean meta_prefs_get_center_new_windows (void); - -META_EXPORT -gboolean meta_prefs_get_show_fallback_app_menu (void); - -META_EXPORT -void meta_prefs_set_show_fallback_app_menu (gboolean whether); - -META_EXPORT -void meta_prefs_get_button_layout (MetaButtonLayout *button_layout); - -/* Double, right, middle click can be configured to any titlebar meta-action */ -META_EXPORT -GDesktopTitlebarAction meta_prefs_get_action_double_click_titlebar (void); - -META_EXPORT -GDesktopTitlebarAction meta_prefs_get_action_middle_click_titlebar (void); - -META_EXPORT -GDesktopTitlebarAction meta_prefs_get_action_right_click_titlebar (void); - -META_EXPORT -void meta_prefs_set_num_workspaces (int n_workspaces); - -META_EXPORT -const char* meta_prefs_get_workspace_name (int i); - -META_EXPORT -void meta_prefs_change_workspace_name (int i, - const char *name); - -META_EXPORT -const char* meta_prefs_get_cursor_theme (void); - -META_EXPORT -int meta_prefs_get_cursor_size (void); - -META_EXPORT -gboolean meta_prefs_get_compositing_manager (void); - -META_EXPORT -gboolean meta_prefs_get_force_fullscreen (void); - -META_EXPORT -void meta_prefs_set_force_fullscreen (gboolean whether); - -META_EXPORT -gboolean meta_prefs_get_workspaces_only_on_primary (void); - -META_EXPORT -int meta_prefs_get_draggable_border_width (void); - -META_EXPORT -int meta_prefs_get_drag_threshold (void); - -/** - * MetaKeyBindingAction: - * @META_KEYBINDING_ACTION_NONE: FILLME - * @META_KEYBINDING_ACTION_WORKSPACE_1: FILLME - * @META_KEYBINDING_ACTION_WORKSPACE_2: FILLME - * @META_KEYBINDING_ACTION_WORKSPACE_3: FILLME - * @META_KEYBINDING_ACTION_WORKSPACE_4: FILLME - * @META_KEYBINDING_ACTION_WORKSPACE_5: FILLME - * @META_KEYBINDING_ACTION_WORKSPACE_6: FILLME - * @META_KEYBINDING_ACTION_WORKSPACE_7: FILLME - * @META_KEYBINDING_ACTION_WORKSPACE_8: FILLME - * @META_KEYBINDING_ACTION_WORKSPACE_9: FILLME - * @META_KEYBINDING_ACTION_WORKSPACE_10: FILLME - * @META_KEYBINDING_ACTION_WORKSPACE_11: FILLME - * @META_KEYBINDING_ACTION_WORKSPACE_12: FILLME - * @META_KEYBINDING_ACTION_WORKSPACE_LEFT: FILLME - * @META_KEYBINDING_ACTION_WORKSPACE_RIGHT: FILLME - * @META_KEYBINDING_ACTION_WORKSPACE_UP: FILLME - * @META_KEYBINDING_ACTION_WORKSPACE_DOWN: FILLME - * @META_KEYBINDING_ACTION_WORKSPACE_LAST: FILLME - * @META_KEYBINDING_ACTION_SWITCH_APPLICATIONS: FILLME - * @META_KEYBINDING_ACTION_SWITCH_APPLICATIONS_BACKWARD: FILLME - * @META_KEYBINDING_ACTION_SWITCH_GROUP: FILLME - * @META_KEYBINDING_ACTION_SWITCH_GROUP_BACKWARD: FILLME - * @META_KEYBINDING_ACTION_SWITCH_WINDOWS: FILLME - * @META_KEYBINDING_ACTION_SWITCH_WINDOWS_BACKWARD: FILLME - * @META_KEYBINDING_ACTION_SWITCH_PANELS: FILLME - * @META_KEYBINDING_ACTION_SWITCH_PANELS_BACKWARD: FILLME - * @META_KEYBINDING_ACTION_CYCLE_GROUP: FILLME - * @META_KEYBINDING_ACTION_CYCLE_GROUP_BACKWARD: FILLME - * @META_KEYBINDING_ACTION_CYCLE_WINDOWS: FILLME - * @META_KEYBINDING_ACTION_CYCLE_WINDOWS_BACKWARD: FILLME - * @META_KEYBINDING_ACTION_CYCLE_PANELS: FILLME - * @META_KEYBINDING_ACTION_CYCLE_PANELS_BACKWARD: FILLME - * @META_KEYBINDING_ACTION_SHOW_DESKTOP: FILLME - * @META_KEYBINDING_ACTION_PANEL_MAIN_MENU: FILLME - * @META_KEYBINDING_ACTION_PANEL_RUN_DIALOG: FILLME - * @META_KEYBINDING_ACTION_TOGGLE_RECORDING: FILLME - * @META_KEYBINDING_ACTION_SET_SPEW_MARK: FILLME - * @META_KEYBINDING_ACTION_ACTIVATE_WINDOW_MENU: FILLME - * @META_KEYBINDING_ACTION_TOGGLE_FULLSCREEN: FILLME - * @META_KEYBINDING_ACTION_TOGGLE_MAXIMIZED: FILLME - * @META_KEYBINDING_ACTION_TOGGLE_TILED_LEFT: FILLME - * @META_KEYBINDING_ACTION_TOGGLE_TILED_RIGHT: FILLME - * @META_KEYBINDING_ACTION_TOGGLE_ABOVE: FILLME - * @META_KEYBINDING_ACTION_MAXIMIZE: FILLME - * @META_KEYBINDING_ACTION_UNMAXIMIZE: FILLME - * @META_KEYBINDING_ACTION_TOGGLE_SHADED: FILLME - * @META_KEYBINDING_ACTION_MINIMIZE: FILLME - * @META_KEYBINDING_ACTION_CLOSE: FILLME - * @META_KEYBINDING_ACTION_BEGIN_MOVE: FILLME - * @META_KEYBINDING_ACTION_BEGIN_RESIZE: FILLME - * @META_KEYBINDING_ACTION_TOGGLE_ON_ALL_WORKSPACES: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_1: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_2: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_3: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_4: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_5: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_6: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_7: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_8: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_9: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_10: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_11: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_12: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_LEFT: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_RIGHT: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_UP: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_DOWN: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_LAST: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_MONITOR_LEFT: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_MONITOR_RIGHT: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_MONITOR_UP: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_MONITOR_DOWN: FILLME - * @META_KEYBINDING_ACTION_RAISE_OR_LOWER: FILLME - * @META_KEYBINDING_ACTION_RAISE: FILLME - * @META_KEYBINDING_ACTION_LOWER: FILLME - * @META_KEYBINDING_ACTION_MAXIMIZE_VERTICALLY: FILLME - * @META_KEYBINDING_ACTION_MAXIMIZE_HORIZONTALLY: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_CORNER_NW: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_CORNER_NE: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_CORNER_SW: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_CORNER_SE: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_SIDE_N: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_SIDE_S: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_SIDE_E: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_SIDE_W: FILLME - * @META_KEYBINDING_ACTION_MOVE_TO_CENTER: FILLME - * @META_KEYBINDING_ACTION_OVERLAY_KEY: FILLME - * @META_KEYBINDING_ACTION_LOCATE_POINTER_KEY: FILLME - * @META_KEYBINDING_ACTION_ALWAYS_ON_TOP: FILLME - * @META_KEYBINDING_ACTION_LAST: FILLME - */ -/* XXX FIXME This should be x-macroed, but isn't yet because it would be - * difficult (or perhaps impossible) to add the suffixes using the current - * system. It needs some more thought, perhaps after the current system - * evolves a little. - */ -typedef enum _MetaKeyBindingAction -{ - META_KEYBINDING_ACTION_NONE, - META_KEYBINDING_ACTION_WORKSPACE_1, - META_KEYBINDING_ACTION_WORKSPACE_2, - META_KEYBINDING_ACTION_WORKSPACE_3, - META_KEYBINDING_ACTION_WORKSPACE_4, - META_KEYBINDING_ACTION_WORKSPACE_5, - META_KEYBINDING_ACTION_WORKSPACE_6, - META_KEYBINDING_ACTION_WORKSPACE_7, - META_KEYBINDING_ACTION_WORKSPACE_8, - META_KEYBINDING_ACTION_WORKSPACE_9, - META_KEYBINDING_ACTION_WORKSPACE_10, - META_KEYBINDING_ACTION_WORKSPACE_11, - META_KEYBINDING_ACTION_WORKSPACE_12, - META_KEYBINDING_ACTION_WORKSPACE_LEFT, - META_KEYBINDING_ACTION_WORKSPACE_RIGHT, - META_KEYBINDING_ACTION_WORKSPACE_UP, - META_KEYBINDING_ACTION_WORKSPACE_DOWN, - META_KEYBINDING_ACTION_WORKSPACE_LAST, - META_KEYBINDING_ACTION_SWITCH_APPLICATIONS, - META_KEYBINDING_ACTION_SWITCH_APPLICATIONS_BACKWARD, - META_KEYBINDING_ACTION_SWITCH_GROUP, - META_KEYBINDING_ACTION_SWITCH_GROUP_BACKWARD, - META_KEYBINDING_ACTION_SWITCH_WINDOWS, - META_KEYBINDING_ACTION_SWITCH_WINDOWS_BACKWARD, - META_KEYBINDING_ACTION_SWITCH_PANELS, - META_KEYBINDING_ACTION_SWITCH_PANELS_BACKWARD, - META_KEYBINDING_ACTION_CYCLE_GROUP, - META_KEYBINDING_ACTION_CYCLE_GROUP_BACKWARD, - META_KEYBINDING_ACTION_CYCLE_WINDOWS, - META_KEYBINDING_ACTION_CYCLE_WINDOWS_BACKWARD, - META_KEYBINDING_ACTION_CYCLE_PANELS, - META_KEYBINDING_ACTION_CYCLE_PANELS_BACKWARD, - META_KEYBINDING_ACTION_SHOW_DESKTOP, - META_KEYBINDING_ACTION_PANEL_MAIN_MENU, - META_KEYBINDING_ACTION_PANEL_RUN_DIALOG, - META_KEYBINDING_ACTION_TOGGLE_RECORDING, - META_KEYBINDING_ACTION_SET_SPEW_MARK, - META_KEYBINDING_ACTION_ACTIVATE_WINDOW_MENU, - META_KEYBINDING_ACTION_TOGGLE_FULLSCREEN, - META_KEYBINDING_ACTION_TOGGLE_MAXIMIZED, - META_KEYBINDING_ACTION_TOGGLE_TILED_LEFT, - META_KEYBINDING_ACTION_TOGGLE_TILED_RIGHT, - META_KEYBINDING_ACTION_TOGGLE_ABOVE, - META_KEYBINDING_ACTION_MAXIMIZE, - META_KEYBINDING_ACTION_UNMAXIMIZE, - META_KEYBINDING_ACTION_TOGGLE_SHADED, - META_KEYBINDING_ACTION_MINIMIZE, - META_KEYBINDING_ACTION_CLOSE, - META_KEYBINDING_ACTION_BEGIN_MOVE, - META_KEYBINDING_ACTION_BEGIN_RESIZE, - META_KEYBINDING_ACTION_TOGGLE_ON_ALL_WORKSPACES, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_1, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_2, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_3, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_4, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_5, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_6, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_7, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_8, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_9, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_10, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_11, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_12, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_LEFT, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_RIGHT, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_UP, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_DOWN, - META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_LAST, - META_KEYBINDING_ACTION_MOVE_TO_MONITOR_LEFT, - META_KEYBINDING_ACTION_MOVE_TO_MONITOR_RIGHT, - META_KEYBINDING_ACTION_MOVE_TO_MONITOR_UP, - META_KEYBINDING_ACTION_MOVE_TO_MONITOR_DOWN, - META_KEYBINDING_ACTION_RAISE_OR_LOWER, - META_KEYBINDING_ACTION_RAISE, - META_KEYBINDING_ACTION_LOWER, - META_KEYBINDING_ACTION_MAXIMIZE_VERTICALLY, - META_KEYBINDING_ACTION_MAXIMIZE_HORIZONTALLY, - META_KEYBINDING_ACTION_MOVE_TO_CORNER_NW, - META_KEYBINDING_ACTION_MOVE_TO_CORNER_NE, - META_KEYBINDING_ACTION_MOVE_TO_CORNER_SW, - META_KEYBINDING_ACTION_MOVE_TO_CORNER_SE, - META_KEYBINDING_ACTION_MOVE_TO_SIDE_N, - META_KEYBINDING_ACTION_MOVE_TO_SIDE_S, - META_KEYBINDING_ACTION_MOVE_TO_SIDE_E, - META_KEYBINDING_ACTION_MOVE_TO_SIDE_W, - META_KEYBINDING_ACTION_MOVE_TO_CENTER, - META_KEYBINDING_ACTION_OVERLAY_KEY, - META_KEYBINDING_ACTION_LOCATE_POINTER_KEY, - META_KEYBINDING_ACTION_ISO_NEXT_GROUP, - META_KEYBINDING_ACTION_ALWAYS_ON_TOP, - META_KEYBINDING_ACTION_SWITCH_MONITOR, - META_KEYBINDING_ACTION_ROTATE_MONITOR, - - META_KEYBINDING_ACTION_LAST -} MetaKeyBindingAction; - -/** - * MetaKeyBindingFlags: - * @META_KEY_BINDING_NONE: none - * @META_KEY_BINDING_PER_WINDOW: per-window - * @META_KEY_BINDING_BUILTIN: built-in - * @META_KEY_BINDING_IS_REVERSED: is reversed - * @META_KEY_BINDING_NON_MASKABLE: always active - * @META_KEY_BINDING_NO_AUTO_GRAB: not grabbed automatically - */ -typedef enum -{ - META_KEY_BINDING_NONE, - META_KEY_BINDING_PER_WINDOW = 1 << 0, - META_KEY_BINDING_BUILTIN = 1 << 1, - META_KEY_BINDING_IS_REVERSED = 1 << 2, - META_KEY_BINDING_NON_MASKABLE = 1 << 3, - META_KEY_BINDING_IGNORE_AUTOREPEAT = 1 << 4, - META_KEY_BINDING_NO_AUTO_GRAB = 1 << 5, -} MetaKeyBindingFlags; - -/** - * MetaKeyHandlerFunc: - * @display: a #MetaDisplay - * @window: a #MetaWindow - * @event: (type gpointer): a #ClutterKeyEvent - * @binding: a #MetaKeyBinding - * @user_data: data passed to the function - * - */ -typedef void (* MetaKeyHandlerFunc) (MetaDisplay *display, - MetaWindow *window, - ClutterKeyEvent *event, - MetaKeyBinding *binding, - gpointer user_data); - -META_EXPORT -GType meta_key_binding_get_type (void); - -META_EXPORT -MetaKeyBindingAction meta_prefs_get_keybinding_action (const char *name); - -META_EXPORT -gboolean meta_prefs_get_visual_bell (void); - -META_EXPORT -gboolean meta_prefs_bell_is_audible (void); - -META_EXPORT -GDesktopVisualBellType meta_prefs_get_visual_bell_type (void); - -META_EXPORT -unsigned int meta_prefs_get_check_alive_timeout (void); - -#endif diff --git a/src/meta/theme.h b/src/meta/theme.h deleted file mode 100644 index 0fbd1e5af..000000000 --- a/src/meta/theme.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity Theme Rendering */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * 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 . - */ - -#ifndef META_THEME_H -#define META_THEME_H - -#include - -/** - * MetaTheme: - * - */ -typedef struct _MetaTheme MetaTheme; - -META_EXPORT -MetaTheme* meta_theme_get_default (void); - -META_EXPORT -MetaTheme* meta_theme_new (void); - -META_EXPORT -void meta_theme_free (MetaTheme *theme); -#endif diff --git a/src/meta/types.h b/src/meta/types.h deleted file mode 100644 index 403e62b16..000000000 --- a/src/meta/types.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2008 Iain Holmes - * - * 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 . - */ - -#ifndef META_TYPES_H -#define META_TYPES_H - -/** - * MetaCompositor: (skip) - * - */ -typedef struct _MetaBackend MetaBackend; -typedef struct _MetaContext MetaContext; -typedef struct _MetaCompositor MetaCompositor; -typedef struct _MetaDisplay MetaDisplay; -typedef struct _MetaX11Display MetaX11Display; -typedef struct _MetaFrame MetaFrame; -typedef struct _MetaWindow MetaWindow; -typedef struct _MetaWorkspace MetaWorkspace; -/** - * MetaGroup: (skip) - * - */ -typedef struct _MetaGroup MetaGroup; -typedef struct _MetaKeyBinding MetaKeyBinding; -typedef struct _MetaCursorTracker MetaCursorTracker; - -typedef struct _MetaDnd MetaDnd; -typedef struct _MetaSettings MetaSettings; - -typedef struct _MetaWorkspaceManager MetaWorkspaceManager; -typedef struct _MetaSelection MetaSelection; - -#endif diff --git a/src/meta/util.h b/src/meta/util.h deleted file mode 100644 index 834e61d49..000000000 --- a/src/meta/util.h +++ /dev/null @@ -1,236 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter utilities */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2005 Elijah Newren - * - * 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 . - */ - -#ifndef META_UTIL_H -#define META_UTIL_H - -#include -#include - -#include -#include - -META_EXPORT -gboolean meta_is_verbose (void); - -META_EXPORT -gboolean meta_is_syncing (void); - -META_EXPORT -gboolean meta_is_wayland_compositor (void); - -META_EXPORT -void meta_verbose_real (const char *format, - ...) G_GNUC_PRINTF (1, 2); - -META_EXPORT -void meta_bug (const char *format, - ...) G_GNUC_PRINTF (1, 2); - -META_EXPORT -void meta_warning (const char *format, - ...) G_GNUC_PRINTF (1, 2); - -META_EXPORT -void meta_fatal (const char *format, - ...) G_GNUC_PRINTF (1, 2) G_GNUC_NORETURN G_ANALYZER_NORETURN; - -/** - * MetaDebugTopic: - * @META_DEBUG_VERBOSE: verbose logging - * @META_DEBUG_FOCUS: focus - * @META_DEBUG_WORKAREA: workarea - * @META_DEBUG_STACK: stack - * @META_DEBUG_SM: session management - * @META_DEBUG_EVENTS: events - * @META_DEBUG_WINDOW_STATE: window state - * @META_DEBUG_WINDOW_OPS: window operations - * @META_DEBUG_GEOMETRY: geometry - * @META_DEBUG_PLACEMENT: window placement - * @META_DEBUG_PING: ping - * @META_DEBUG_KEYBINDINGS: keybindings - * @META_DEBUG_SYNC: sync - * @META_DEBUG_STARTUP: startup - * @META_DEBUG_PREFS: preferences - * @META_DEBUG_GROUPS: groups - * @META_DEBUG_RESIZING: resizing - * @META_DEBUG_SHAPES: shapes - * @META_DEBUG_EDGE_RESISTANCE: edge resistance - * @META_DEBUG_WAYLAND: Wayland - * @META_DEBUG_KMS: kernel mode setting - * @META_DEBUG_SCREEN_CAST: screencasting - * @META_DEBUG_REMOTE_DESKTOP: remote desktop - * @META_DEBUG_BACKEND: backend - */ -typedef enum -{ - META_DEBUG_VERBOSE = -1, - META_DEBUG_FOCUS = 1 << 0, - META_DEBUG_WORKAREA = 1 << 1, - META_DEBUG_STACK = 1 << 2, - META_DEBUG_SM = 1 << 3, - META_DEBUG_EVENTS = 1 << 4, - META_DEBUG_WINDOW_STATE = 1 << 5, - META_DEBUG_WINDOW_OPS = 1 << 6, - META_DEBUG_GEOMETRY = 1 << 7, - META_DEBUG_PLACEMENT = 1 << 8, - META_DEBUG_PING = 1 << 9, - META_DEBUG_KEYBINDINGS = 1 << 10, - META_DEBUG_SYNC = 1 << 11, - META_DEBUG_STARTUP = 1 << 12, - META_DEBUG_PREFS = 1 << 13, - META_DEBUG_GROUPS = 1 << 14, - META_DEBUG_RESIZING = 1 << 15, - META_DEBUG_SHAPES = 1 << 16, - META_DEBUG_EDGE_RESISTANCE = 1 << 17, - META_DEBUG_DBUS = 1 << 18, - META_DEBUG_INPUT = 1 << 19, - META_DEBUG_WAYLAND = 1 << 20, - META_DEBUG_KMS = 1 << 21, - META_DEBUG_SCREEN_CAST = 1 << 22, - META_DEBUG_REMOTE_DESKTOP = 1 << 23, - META_DEBUG_BACKEND = 1 << 24, -} MetaDebugTopic; - -/** - * MetaDebugPaintFlag: - * @META_DEBUG_PAINT_NONE: default - * @META_DEBUG_PAINT_OPAQUE_REGION: paint opaque regions - */ -typedef enum -{ - META_DEBUG_PAINT_NONE = 0, - META_DEBUG_PAINT_OPAQUE_REGION = 1 << 0, -} MetaDebugPaintFlag; - -META_EXPORT -gboolean meta_is_topic_enabled (MetaDebugTopic topic); - -META_EXPORT -void meta_topic_real (MetaDebugTopic topic, - const char *format, - ...) G_GNUC_PRINTF (2, 3); - -META_EXPORT -void meta_add_verbose_topic (MetaDebugTopic topic); - -META_EXPORT -void meta_remove_verbose_topic (MetaDebugTopic topic); - -META_EXPORT -void meta_push_no_msg_prefix (void); - -META_EXPORT -void meta_pop_no_msg_prefix (void); - -META_EXPORT -gint meta_unsigned_long_equal (gconstpointer v1, - gconstpointer v2); - -META_EXPORT -guint meta_unsigned_long_hash (gconstpointer v); - -META_EXPORT -const char* meta_frame_type_to_string (MetaFrameType type); -META_EXPORT -const char* meta_gravity_to_string (MetaGravity gravity); - -META_EXPORT -char* meta_external_binding_name_for_action (guint keybinding_action); - -META_EXPORT -char* meta_g_utf8_strndup (const gchar *src, gsize n); - -META_EXPORT -GPid meta_show_dialog (const char *type, - const char *message, - const char *timeout, - const char *display, - const char *ok_text, - const char *cancel_text, - const char *icon_name, - const int transient_for, - GSList *columns, - GSList *entries); - -/* To disable verbose mode, we make these functions into no-ops */ -#ifdef WITH_VERBOSE_MODE - -#define meta_verbose(...) \ - G_STMT_START \ - { \ - if (meta_is_topic_enabled (META_DEBUG_VERBOSE)) \ - meta_verbose_real (__VA_ARGS__); \ - } \ - G_STMT_END - -#define meta_topic(debug_topic,...) \ - G_STMT_START \ - { \ - if (meta_is_topic_enabled (debug_topic)) \ - meta_topic_real (debug_topic, __VA_ARGS__); \ - } \ - G_STMT_END - -#else - -# ifdef G_HAVE_ISO_VARARGS -# define meta_verbose(...) -# define meta_topic(...) -# elif defined(G_HAVE_GNUC_VARARGS) -# define meta_verbose(format...) -# define meta_topic(format...) -# else -# error "This compiler does not support varargs macros and thus verbose mode can't be disabled meaningfully" -# endif - -#endif /* !WITH_VERBOSE_MODE */ - -typedef enum -{ - META_LOCALE_DIRECTION_LTR, - META_LOCALE_DIRECTION_RTL, -} MetaLocaleDirection; - -META_EXPORT -MetaLocaleDirection meta_get_locale_direction (void); - -META_EXPORT -void meta_add_clutter_debug_flags (ClutterDebugFlag debug_flags, - ClutterDrawDebugFlag draw_flags, - ClutterPickDebugFlag pick_flags); - -META_EXPORT -void meta_remove_clutter_debug_flags (ClutterDebugFlag debug_flags, - ClutterDrawDebugFlag draw_flags, - ClutterPickDebugFlag pick_flags); - -META_EXPORT -void meta_add_debug_paint_flag (MetaDebugPaintFlag flag); - -META_EXPORT -void meta_remove_debug_paint_flag (MetaDebugPaintFlag flag); - -META_EXPORT -MetaDebugPaintFlag meta_get_debug_paint_flags (void); - -#endif /* META_UTIL_H */ diff --git a/src/meta/window.h b/src/meta/window.h deleted file mode 100644 index 3157d44ee..000000000 --- a/src/meta/window.h +++ /dev/null @@ -1,449 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2008 Iain Holmes - * - * 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 . - */ - -#ifndef META_WINDOW_H -#define META_WINDOW_H - -#include -#include -#include - -#include -#include - -/** - * MetaWindowType: - * @META_WINDOW_NORMAL: Normal - * @META_WINDOW_DESKTOP: Desktop - * @META_WINDOW_DOCK: Dock - * @META_WINDOW_DIALOG: Dialog - * @META_WINDOW_MODAL_DIALOG: Modal dialog - * @META_WINDOW_TOOLBAR: Toolbar - * @META_WINDOW_MENU: Menu - * @META_WINDOW_UTILITY: Utility - * @META_WINDOW_SPLASHSCREEN: Splashcreen - * @META_WINDOW_DROPDOWN_MENU: Dropdown menu - * @META_WINDOW_POPUP_MENU: Popup menu - * @META_WINDOW_TOOLTIP: Tooltip - * @META_WINDOW_NOTIFICATION: Notification - * @META_WINDOW_COMBO: Combobox - * @META_WINDOW_DND: Drag and drop - * @META_WINDOW_OVERRIDE_OTHER: Other override-redirect window type - */ -typedef enum -{ - META_WINDOW_NORMAL, - META_WINDOW_DESKTOP, - META_WINDOW_DOCK, - META_WINDOW_DIALOG, - META_WINDOW_MODAL_DIALOG, - META_WINDOW_TOOLBAR, - META_WINDOW_MENU, - META_WINDOW_UTILITY, - META_WINDOW_SPLASHSCREEN, - - /* override redirect window types: */ - META_WINDOW_DROPDOWN_MENU, - META_WINDOW_POPUP_MENU, - META_WINDOW_TOOLTIP, - META_WINDOW_NOTIFICATION, - META_WINDOW_COMBO, - META_WINDOW_DND, - META_WINDOW_OVERRIDE_OTHER -} MetaWindowType; - -/** - * MetaMaximizeFlags: - * @META_MAXIMIZE_HORIZONTAL: Horizontal - * @META_MAXIMIZE_VERTICAL: Vertical - * @META_MAXIMIZE_BOTH: Both - */ -typedef enum -{ - META_MAXIMIZE_HORIZONTAL = 1 << 0, - META_MAXIMIZE_VERTICAL = 1 << 1, - META_MAXIMIZE_BOTH = (1 << 0 | 1 << 1), -} MetaMaximizeFlags; - -/** - * MetaWindowClientType: - * @META_WINDOW_CLIENT_TYPE_WAYLAND: A Wayland based window - * @META_WINDOW_CLIENT_TYPE_X11: An X11 based window - */ -typedef enum -{ - META_WINDOW_CLIENT_TYPE_WAYLAND, - META_WINDOW_CLIENT_TYPE_X11 -} MetaWindowClientType; - -#define META_TYPE_WINDOW (meta_window_get_type ()) -#define META_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_WINDOW, MetaWindow)) -#define META_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_WINDOW, MetaWindowClass)) -#define META_IS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_WINDOW)) -#define META_IS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_WINDOW)) -#define META_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_WINDOW, MetaWindowClass)) - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaWindow, g_object_unref) - -typedef struct _MetaWindowClass MetaWindowClass; - -META_EXPORT -GType meta_window_get_type (void); - -META_EXPORT -MetaFrame *meta_window_get_frame (MetaWindow *window); - -META_EXPORT -gboolean meta_window_has_focus (MetaWindow *window); - -META_EXPORT -gboolean meta_window_appears_focused (MetaWindow *window); - -META_EXPORT -gboolean meta_window_is_shaded (MetaWindow *window); - -META_EXPORT -gboolean meta_window_is_override_redirect (MetaWindow *window); - -META_EXPORT -gboolean meta_window_is_skip_taskbar (MetaWindow *window); - -META_EXPORT -void meta_window_get_buffer_rect (const MetaWindow *window, MetaRectangle *rect); - -META_EXPORT -void meta_window_get_frame_rect (const MetaWindow *window, MetaRectangle *rect); - -META_EXPORT -void meta_window_client_rect_to_frame_rect (MetaWindow *window, - MetaRectangle *client_rect, - MetaRectangle *frame_rect); - -META_EXPORT -void meta_window_frame_rect_to_client_rect (MetaWindow *window, - MetaRectangle *frame_rect, - MetaRectangle *client_rect); - -META_EXPORT -MetaDisplay *meta_window_get_display (MetaWindow *window); - -META_EXPORT -Window meta_window_get_xwindow (MetaWindow *window); - -META_EXPORT -MetaWindowType meta_window_get_window_type (MetaWindow *window); - -META_EXPORT -MetaWorkspace *meta_window_get_workspace (MetaWindow *window); - -META_EXPORT -int meta_window_get_monitor (MetaWindow *window); - -META_EXPORT -gboolean meta_window_is_on_all_workspaces (MetaWindow *window); - -META_EXPORT -gboolean meta_window_located_on_workspace (MetaWindow *window, - MetaWorkspace *workspace); - -META_EXPORT -gboolean meta_window_is_hidden (MetaWindow *window); - -META_EXPORT -void meta_window_activate (MetaWindow *window,guint32 current_time); - -META_EXPORT -void meta_window_activate_with_workspace (MetaWindow *window, - guint32 current_time, - MetaWorkspace *workspace); - -META_EXPORT -const char * meta_window_get_description (MetaWindow *window); - -META_EXPORT -const char * meta_window_get_wm_class (MetaWindow *window); - -META_EXPORT -const char * meta_window_get_wm_class_instance (MetaWindow *window); - -META_EXPORT -gboolean meta_window_showing_on_its_workspace (MetaWindow *window); - -META_EXPORT -const char * meta_window_get_sandboxed_app_id (MetaWindow *window); - -META_EXPORT -const char * meta_window_get_gtk_theme_variant (MetaWindow *window); - -META_EXPORT -const char * meta_window_get_gtk_application_id (MetaWindow *window); - -META_EXPORT -const char * meta_window_get_gtk_unique_bus_name (MetaWindow *window); - -META_EXPORT -const char * meta_window_get_gtk_application_object_path (MetaWindow *window); - -META_EXPORT -const char * meta_window_get_gtk_window_object_path (MetaWindow *window); - -META_EXPORT -const char * meta_window_get_gtk_app_menu_object_path (MetaWindow *window); - -META_EXPORT -const char * meta_window_get_gtk_menubar_object_path (MetaWindow *window); - -META_EXPORT -void meta_window_move_frame(MetaWindow *window, gboolean user_op, int root_x_nw, int root_y_nw); - -META_EXPORT -void meta_window_move_resize_frame (MetaWindow *window, gboolean user_op, int root_x_nw, int root_y_nw, int w, int h); - -META_EXPORT -void meta_window_move_to_monitor (MetaWindow *window, int monitor); - -META_EXPORT -void meta_window_set_demands_attention (MetaWindow *window); - -META_EXPORT -void meta_window_unset_demands_attention (MetaWindow *window); - -META_EXPORT -const char* meta_window_get_startup_id (MetaWindow *window); - -META_EXPORT -void meta_window_change_workspace_by_index (MetaWindow *window, - gint space_index, - gboolean append); - -META_EXPORT -void meta_window_change_workspace (MetaWindow *window, - MetaWorkspace *workspace); - -META_EXPORT -GObject *meta_window_get_compositor_private (MetaWindow *window); - -META_EXPORT -void meta_window_set_compositor_private (MetaWindow *window, GObject *priv); - -META_EXPORT -const char *meta_window_get_role (MetaWindow *window); - -META_EXPORT -MetaStackLayer meta_window_get_layer (MetaWindow *window); - -META_EXPORT -MetaWindow* meta_window_find_root_ancestor (MetaWindow *window); - -META_EXPORT -gboolean meta_window_is_ancestor_of_transient (MetaWindow *window, - MetaWindow *transient); - -typedef gboolean (*MetaWindowForeachFunc) (MetaWindow *window, - void *user_data); - -META_EXPORT -void meta_window_foreach_transient (MetaWindow *window, - MetaWindowForeachFunc func, - void *user_data); - -META_EXPORT -void meta_window_foreach_ancestor (MetaWindow *window, - MetaWindowForeachFunc func, - void *user_data); - -META_EXPORT -MetaMaximizeFlags meta_window_get_maximized (MetaWindow *window); - -META_EXPORT -gboolean meta_window_is_fullscreen (MetaWindow *window); - -META_EXPORT -gboolean meta_window_is_screen_sized (MetaWindow *window); - -META_EXPORT -gboolean meta_window_is_monitor_sized (MetaWindow *window); - -META_EXPORT -gboolean meta_window_is_on_primary_monitor (MetaWindow *window); - -META_EXPORT -gboolean meta_window_get_icon_geometry (MetaWindow *window, - MetaRectangle *rect); - -META_EXPORT -void meta_window_set_icon_geometry (MetaWindow *window, - MetaRectangle *rect); - -META_EXPORT -void meta_window_maximize (MetaWindow *window, - MetaMaximizeFlags directions); - -META_EXPORT -void meta_window_unmaximize (MetaWindow *window, - MetaMaximizeFlags directions); - -META_EXPORT -void meta_window_minimize (MetaWindow *window); - -META_EXPORT -void meta_window_unminimize (MetaWindow *window); - -META_EXPORT -void meta_window_raise (MetaWindow *window); - -META_EXPORT -void meta_window_lower (MetaWindow *window); - -META_EXPORT -const char *meta_window_get_title (MetaWindow *window); - -META_EXPORT -MetaWindow *meta_window_get_transient_for (MetaWindow *window); - -META_EXPORT -void meta_window_delete (MetaWindow *window, - guint32 timestamp); - -META_EXPORT -guint meta_window_get_stable_sequence (MetaWindow *window); - -META_EXPORT -guint32 meta_window_get_user_time (MetaWindow *window); - -META_EXPORT -pid_t meta_window_get_pid (MetaWindow *window); - -META_EXPORT -const char *meta_window_get_client_machine (MetaWindow *window); - -META_EXPORT -gboolean meta_window_is_remote (MetaWindow *window); - -META_EXPORT -gboolean meta_window_is_attached_dialog (MetaWindow *window); - -META_EXPORT -const char *meta_window_get_mutter_hints (MetaWindow *window); - -META_EXPORT -MetaFrameType meta_window_get_frame_type (MetaWindow *window); - -META_EXPORT -cairo_region_t *meta_window_get_frame_bounds (MetaWindow *window); - -META_EXPORT -MetaWindow *meta_window_get_tile_match (MetaWindow *window); - -META_EXPORT -void meta_window_make_fullscreen (MetaWindow *window); - -META_EXPORT -void meta_window_unmake_fullscreen (MetaWindow *window); - -META_EXPORT -void meta_window_make_above (MetaWindow *window); - -META_EXPORT -void meta_window_unmake_above (MetaWindow *window); - -META_EXPORT -void meta_window_shade (MetaWindow *window, - guint32 timestamp); - -META_EXPORT -void meta_window_unshade (MetaWindow *window, - guint32 timestamp); - -META_EXPORT -void meta_window_stick (MetaWindow *window); - -META_EXPORT -void meta_window_unstick (MetaWindow *window); - -META_EXPORT -void meta_window_kill (MetaWindow *window); - -META_EXPORT -void meta_window_focus (MetaWindow *window, - guint32 timestamp); - -META_EXPORT -void meta_window_check_alive (MetaWindow *window, - guint32 timestamp); - -META_EXPORT -void meta_window_get_work_area_current_monitor (MetaWindow *window, - MetaRectangle *area); - -META_EXPORT -void meta_window_get_work_area_for_monitor (MetaWindow *window, - int which_monitor, - MetaRectangle *area); - -META_EXPORT -void meta_window_get_work_area_all_monitors (MetaWindow *window, - MetaRectangle *area); - -META_EXPORT -void meta_window_begin_grab_op (MetaWindow *window, - MetaGrabOp op, - gboolean frame_action, - guint32 timestamp); - -META_EXPORT -gboolean meta_window_can_maximize (MetaWindow *window); - -META_EXPORT -gboolean meta_window_can_minimize (MetaWindow *window); - -META_EXPORT -gboolean meta_window_can_shade (MetaWindow *window); - -META_EXPORT -gboolean meta_window_can_close (MetaWindow *window); - -META_EXPORT -gboolean meta_window_is_always_on_all_workspaces (MetaWindow *window); - -META_EXPORT -gboolean meta_window_is_above (MetaWindow *window); - -META_EXPORT -gboolean meta_window_allows_move (MetaWindow *window); - -META_EXPORT -gboolean meta_window_allows_resize (MetaWindow *window); - -META_EXPORT -gboolean meta_window_is_client_decorated (MetaWindow *window); - -META_EXPORT -gboolean meta_window_titlebar_is_onscreen (MetaWindow *window); - -META_EXPORT -void meta_window_shove_titlebar_onscreen (MetaWindow *window); - -META_EXPORT -uint64_t meta_window_get_id (MetaWindow *window); - -META_EXPORT -MetaWindowClientType meta_window_get_client_type (MetaWindow *window); - -#endif diff --git a/src/meta/workspace.h b/src/meta/workspace.h deleted file mode 100644 index 99aebee5d..000000000 --- a/src/meta/workspace.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2004, 2005 Elijah Newren - * - * 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 . - */ - -#ifndef META_WORKSPACE_H -#define META_WORKSPACE_H - -#include -#include - -#define META_TYPE_WORKSPACE (meta_workspace_get_type ()) -#define META_WORKSPACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_WORKSPACE, MetaWorkspace)) -#define META_WORKSPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_WORKSPACE, MetaWorkspaceClass)) -#define META_IS_WORKSPACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_WORKSPACE)) -#define META_IS_WORKSPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_WORKSPACE)) -#define META_WORKSPACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_WORKSPACE, MetaWorkspaceClass)) - -typedef struct _MetaWorkspaceClass MetaWorkspaceClass; - -META_EXPORT -GType meta_workspace_get_type (void); - -META_EXPORT -int meta_workspace_index (MetaWorkspace *workspace); - -META_EXPORT -MetaDisplay *meta_workspace_get_display (MetaWorkspace *workspace); - -META_EXPORT -GList* meta_workspace_list_windows (MetaWorkspace *workspace); - -META_EXPORT -void meta_workspace_get_work_area_for_monitor (MetaWorkspace *workspace, - int which_monitor, - MetaRectangle *area); - -META_EXPORT -void meta_workspace_get_work_area_all_monitors (MetaWorkspace *workspace, - MetaRectangle *area); - -META_EXPORT -void meta_workspace_activate (MetaWorkspace *workspace, guint32 timestamp); - -META_EXPORT -void meta_workspace_activate_with_focus (MetaWorkspace *workspace, - MetaWindow *focus_this, - guint32 timestamp); - -META_EXPORT -void meta_workspace_set_builtin_struts (MetaWorkspace *workspace, - GSList *struts); - -META_EXPORT -MetaWorkspace* meta_workspace_get_neighbor (MetaWorkspace *workspace, - MetaMotionDirection direction); - -#endif diff --git a/src/org.freedesktop.login1.xml b/src/org.freedesktop.login1.xml deleted file mode 100644 index 765475132..000000000 --- a/src/org.freedesktop.login1.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/org.gnome.Mutter.DisplayConfig.xml b/src/org.gnome.Mutter.DisplayConfig.xml deleted file mode 100644 index 7522652dc..000000000 --- a/src/org.gnome.Mutter.DisplayConfig.xml +++ /dev/null @@ -1,473 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/org.gnome.Mutter.IdleMonitor.xml b/src/org.gnome.Mutter.IdleMonitor.xml deleted file mode 100644 index 374af4dc4..000000000 --- a/src/org.gnome.Mutter.IdleMonitor.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/org.gnome.Mutter.RemoteDesktop.xml b/src/org.gnome.Mutter.RemoteDesktop.xml deleted file mode 100644 index 7bae10e43..000000000 --- a/src/org.gnome.Mutter.RemoteDesktop.xml +++ /dev/null @@ -1,351 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/org.gnome.Mutter.ScreenCast.xml b/src/org.gnome.Mutter.ScreenCast.xml deleted file mode 100644 index d9f1f4435..000000000 --- a/src/org.gnome.Mutter.ScreenCast.xml +++ /dev/null @@ -1,220 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/tests/README b/src/tests/README deleted file mode 100644 index 9c620c328..000000000 --- a/src/tests/README +++ /dev/null @@ -1,93 +0,0 @@ -This directory implements a framework for automated tests of Mutter. The basic -idea is that mutter-test-runner acts as the window manager and compositor, and -forks off instances of mutter-test-client to act as clients. - -There's a simple scripting language for tests. A very small test would look like: - ---- -# Start up a new X11 client with the client id 1 (doesn't have to be an integer) -# Windows for this client will be referred to as 1/ -new_client 1 x11 - -# Create and show two windows - again the IDs don't have to be integers -create 1/1 -show 1/1 -create 1/2 -show 1/2 - -# Wait for the commands we've executed in the clients to reach Mutter -wait - -# Check that the windows are in the order we expect -assert_stacking 1/1 1/2 ---- - -Running -======= - -The tests are installed according to: - -https://wiki.gnome.org/Initiatives/GnomeGoals/InstalledTests - -if -Dtests=true is passed to `meson configure`. You can run them uninstalled with: - - ninja test - -Command reference -================= - -The following commands are supported. Quoting and comments follow shell rules. - -new_client [wayland|x11] - Starts a client, connecting by either Wayland or X11. The client - will subsequently be known with the given client-id (an arbitrary - string) - -quit_client - Destroys all windows for the client, waits for that to be processed, - then instructs the client to exit. - -create / [override|csd] - Creates a new window. For the X11 backend, the keyword 'override' - can be given to create an override-redirect and the keyword 'csd' - can be given to create a client-side decorated window. - -show / -hide / - Ask the client to show (map) or hide (unmap) the given window - -activate / - Ask the client to raise and focus the given window. This is currently a no-op - for Wayland, where this capability is not supported in the protocol. - -local_activate - - The same as 'activate', but the operation is done directly inside Mutter - and works for both backends - -raise / -lower / - Ask the client to raise or lower the given window ID. This is a no-op - for Wayland clients. (It's also considered discouraged, but supported, for - non-override-redirect X11 clients.) - -minimize / -unminimize / - Ask the client to minimize or unminimize the given window ID. This older - term for this operation is "iconify". - -destroy / - Destroy the given window - -wait - Wait until all requests sent by Mutter to clients have been received by Mutter, - and then wait until all requests by Mutter have been processed by the X server. - -assert_stacking / / ... - Assert that the list of client windows known to Mutter is as given and in - the given order, bottom to top. The character '|' can be present in the - list of windows to indicate the guard window that separates hidden and - visible windows. If '|' isn't present, the guard window is asserted to - be below all client windows. - - This function also queries the X server stack and verifies that Mutter's - expectation of the X server stack matches reality. diff --git a/src/tests/anonymous-file.c b/src/tests/anonymous-file.c deleted file mode 100644 index 29f5ceac8..000000000 --- a/src/tests/anonymous-file.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright (C) 2020 Jonas Dreßler. - * - * 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 . - */ - -#include "config.h" - -#include -#include -#include -#include -#include - -#include - -#if defined(HAVE_MEMFD_CREATE) -#define READONLY_SEALS (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE) -#endif - -static const char *teststring = "test string 1234567890"; - -static gboolean -test_read_fd_mmap (int fd, - const char *expected_string) -{ - void *mem; - int string_size; - - string_size = strlen (expected_string) + 1; - - mem = mmap (NULL, string_size, PROT_READ, MAP_PRIVATE, fd, 0); - g_assert (mem != MAP_FAILED); - - if (strcmp (expected_string, mem) != 0) - { - munmap (mem, string_size); - return FALSE; - } - - munmap (mem, string_size); - return TRUE; -} - -static gboolean -test_write_fd (int fd, - const char *string) -{ - int written_size, string_size; - - string_size = strlen (string) + 1; - written_size = write (fd, string, string_size); - if (written_size != string_size) - return FALSE; - - return TRUE; -} - -#if defined(HAVE_MEMFD_CREATE) -static gboolean -test_readonly_seals (int fd) -{ - unsigned int seals; - - seals = fcntl (fd, F_GET_SEALS); - if (seals == -1) - return FALSE; - - if (seals != READONLY_SEALS) - return FALSE; - - return TRUE; -} -#endif - -static gboolean -test_write_read (int fd) -{ - g_autofree char *new_string = g_uuid_string_random (); - - if (!test_write_fd (fd, new_string)) - return FALSE; - - if (!test_read_fd_mmap (fd, new_string)) - return FALSE; - - return TRUE; -} - -#if defined(HAVE_MEMFD_CREATE) -static gboolean -test_open_write_read (const char *path) -{ - int fd; - - fd = open (path, O_RDWR); - g_assert (fd != -1); - - if (!test_write_read (fd)) - { - close (fd); - return FALSE; - } - - close (fd); - return TRUE; -} -#endif - -int -main (int argc, - char **argv) -{ - MetaAnonymousFile *file; - int fd = -1, other_fd = -1; - g_autofree char *fd_path = NULL; - - file = meta_anonymous_file_new (strlen (teststring) + 1, - (const uint8_t *) teststring); - if (!file) - { - g_critical ("%s: Creating file failed", __func__); - return EXIT_FAILURE; - } - -#if defined(HAVE_MEMFD_CREATE) - fd = meta_anonymous_file_open_fd (file, META_ANONYMOUS_FILE_MAPMODE_PRIVATE); - g_assert (fd != -1); - other_fd = meta_anonymous_file_open_fd (file, META_ANONYMOUS_FILE_MAPMODE_PRIVATE); - g_assert (other_fd != -1); - - /* When MAPMODE_PRIVATE was used, meta_anonymous_file_open_fd() should always - * return the same fd. */ - if (other_fd != fd) - goto fail; - - /* If memfd_create was used and we request a MAPMODE_PRIVATE file, all the - * readonly seals should be set. */ - if (!test_readonly_seals (fd)) - goto fail; - - if (!test_read_fd_mmap (fd, teststring)) - goto fail; - - /* Writing and reading the written data should fail */ - if (test_write_read (fd)) - goto fail; - - /* Instead we should still be reading the teststring */ - if (!test_read_fd_mmap (fd, teststring)) - goto fail; - - /* Opening the fd manually in RW mode and writing to it should fail */ - fd_path = g_strdup_printf ("/proc/%d/fd/%d", getpid (), fd); - if (test_open_write_read (fd_path)) - goto fail; - - /* Instead we should still be reading the teststring */ - if (!test_read_fd_mmap (fd, teststring)) - goto fail; - - /* Just to be sure test the other fd, too */ - if (!test_read_fd_mmap (other_fd, teststring)) - goto fail; - - meta_anonymous_file_close_fd (fd); - meta_anonymous_file_close_fd (fd); - - - fd = meta_anonymous_file_open_fd (file, META_ANONYMOUS_FILE_MAPMODE_SHARED); - g_assert (fd != -1); - other_fd = meta_anonymous_file_open_fd (file, META_ANONYMOUS_FILE_MAPMODE_SHARED); - g_assert (other_fd != -1); - - /* The MAPMODE_SHARED fd should not have readonly seals applied */ - if (test_readonly_seals (fd)) - goto fail; - - if (!test_read_fd_mmap (fd, teststring)) - goto fail; - - if (!test_read_fd_mmap (other_fd, teststring)) - goto fail; - - /* Writing and reading the written data should succeed */ - if (!test_write_read (fd)) - goto fail; - - /* The other fd should still read the teststring though */ - if (!test_read_fd_mmap (other_fd, teststring)) - goto fail; - - meta_anonymous_file_close_fd (fd); - meta_anonymous_file_close_fd (other_fd); - - - /* Test an artificial out-of-space situation by setting the maximum file - * size this process may create to 2 bytes, if memfd_create with - * MAPMODE_PRIVATE is used, everything should still work (the existing FD - * should be used). */ - - if (!getenv ("CI_JOB_ID")) - { - struct rlimit rlimit = { - .rlim_cur = 2, - .rlim_max = 2, - }; - - if (setrlimit (RLIMIT_FSIZE, &rlimit) == -1) - goto fail; - - fd = meta_anonymous_file_open_fd (file, META_ANONYMOUS_FILE_MAPMODE_PRIVATE); - g_assert (fd != -1); - - if (!test_read_fd_mmap (fd, teststring)) - goto fail; - - meta_anonymous_file_close_fd (fd); - } -#else - fd = meta_anonymous_file_open_fd (file, META_ANONYMOUS_FILE_MAPMODE_PRIVATE); - g_assert (fd != -1); - other_fd = meta_anonymous_file_open_fd (file, META_ANONYMOUS_FILE_MAPMODE_PRIVATE); - g_assert (other_fd != -1); - - /* Writing and reading the written data should succeed */ - if (!test_write_read (fd)) - goto fail; - - /* The other fd should still read the teststring though */ - if (!test_read_fd_mmap (other_fd, teststring)) - goto fail; - - meta_anonymous_file_close_fd (fd); - meta_anonymous_file_close_fd (other_fd); - - - fd = meta_anonymous_file_open_fd (file, META_ANONYMOUS_FILE_MAPMODE_SHARED); - g_assert (fd != -1); - other_fd = meta_anonymous_file_open_fd (file, META_ANONYMOUS_FILE_MAPMODE_SHARED); - g_assert (other_fd != -1); - - if (!test_read_fd_mmap (fd, teststring)) - goto fail; - - if (!test_read_fd_mmap (other_fd, teststring)) - goto fail; - - /* Writing and reading the written data should succeed */ - if (!test_write_read (fd)) - goto fail; - - /* The other fd should still read the teststring though */ - if (!test_read_fd_mmap (other_fd, teststring)) - goto fail; - - meta_anonymous_file_close_fd (fd); - meta_anonymous_file_close_fd (other_fd); -#endif - - meta_anonymous_file_free (file); - return EXIT_SUCCESS; - - fail: - if (fd > 0) - meta_anonymous_file_close_fd (fd); - if (other_fd > 0) - meta_anonymous_file_close_fd (other_fd); - meta_anonymous_file_free (file); - return EXIT_FAILURE; -} diff --git a/src/tests/boxes-tests.c b/src/tests/boxes-tests.c deleted file mode 100644 index 0c27ea77e..000000000 --- a/src/tests/boxes-tests.c +++ /dev/null @@ -1,1389 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter box operation testing program */ - -/* - * Copyright (C) 2005 Elijah Newren - * - * 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 . - */ - -#include "config.h" - -#include "tests/boxes-tests.h" - -#include -#include -#include -#include -#include -#include - -#include "core/boxes-private.h" - -#define NUM_RANDOM_RUNS 10000 - -static void -init_random_ness (void) -{ - srand (time (NULL)); -} - -static void -get_random_rect (MetaRectangle *rect) -{ - rect->x = rand () % 1600; - rect->y = rand () % 1200; - rect->width = rand () % 1600 + 1; - rect->height = rand () % 1200 + 1; -} - -static MetaRectangle* -new_meta_rect (int x, int y, int width, int height) -{ - MetaRectangle* temporary; - temporary = g_new (MetaRectangle, 1); - temporary->x = x; - temporary->y = y; - temporary->width = width; - temporary->height = height; - - return temporary; -} - -static MetaStrut* -new_meta_strut (int x, int y, int width, int height, int side) -{ - MetaStrut* temporary; - temporary = g_new (MetaStrut, 1); - temporary->rect = meta_rect(x, y, width, height); - temporary->side = side; - - return temporary; -} - -static MetaEdge* -new_screen_edge (int x, int y, int width, int height, int side_type) -{ - MetaEdge* temporary; - temporary = g_new (MetaEdge, 1); - temporary->rect.x = x; - temporary->rect.y = y; - temporary->rect.width = width; - temporary->rect.height = height; - temporary->side_type = side_type; - temporary->edge_type = META_EDGE_SCREEN; - - return temporary; -} - -static MetaEdge* -new_monitor_edge (int x, int y, int width, int height, int side_type) -{ - MetaEdge* temporary; - temporary = g_new (MetaEdge, 1); - temporary->rect.x = x; - temporary->rect.y = y; - temporary->rect.width = width; - temporary->rect.height = height; - temporary->side_type = side_type; - temporary->edge_type = META_EDGE_MONITOR; - - return temporary; -} - -static void -test_area (void) -{ - MetaRectangle temp; - int i; - for (i = 0; i < NUM_RANDOM_RUNS; i++) - { - get_random_rect (&temp); - g_assert (meta_rectangle_area (&temp) == temp.width * temp.height); - } - - temp = meta_rect (0, 0, 5, 7); - g_assert (meta_rectangle_area (&temp) == 35); -} - -static void -test_intersect (void) -{ - MetaRectangle a = {100, 200, 50, 40}; - MetaRectangle b = { 0, 50, 110, 152}; - MetaRectangle c = { 0, 0, 10, 10}; - MetaRectangle d = {100, 100, 50, 50}; - MetaRectangle b_intersect_d = {100, 100, 10, 50}; - MetaRectangle temp; - MetaRectangle temp2; - - meta_rectangle_intersect (&a, &b, &temp); - temp2 = meta_rect (100, 200, 10, 2); - g_assert (meta_rectangle_equal (&temp, &temp2)); - g_assert (meta_rectangle_area (&temp) == 20); - - meta_rectangle_intersect (&a, &c, &temp); - g_assert (meta_rectangle_area (&temp) == 0); - - meta_rectangle_intersect (&a, &d, &temp); - g_assert (meta_rectangle_area (&temp) == 0); - - meta_rectangle_intersect (&b, &d, &b); - g_assert (meta_rectangle_equal (&b, &b_intersect_d)); -} - -static void -test_equal (void) -{ - MetaRectangle a = {10, 12, 4, 18}; - MetaRectangle b = a; - MetaRectangle c = {10, 12, 4, 19}; - MetaRectangle d = {10, 12, 7, 18}; - MetaRectangle e = {10, 62, 4, 18}; - MetaRectangle f = {27, 12, 4, 18}; - - g_assert ( meta_rectangle_equal (&a, &b)); - g_assert (!meta_rectangle_equal (&a, &c)); - g_assert (!meta_rectangle_equal (&a, &d)); - g_assert (!meta_rectangle_equal (&a, &e)); - g_assert (!meta_rectangle_equal (&a, &f)); -} - -static void -test_overlap_funcs (void) -{ - MetaRectangle temp1, temp2; - int i; - for (i = 0; i < NUM_RANDOM_RUNS; i++) - { - get_random_rect (&temp1); - get_random_rect (&temp2); - g_assert (meta_rectangle_overlap (&temp1, &temp2) == - (meta_rectangle_horiz_overlap (&temp1, &temp2) && - meta_rectangle_vert_overlap (&temp1, &temp2))); - } - - temp1 = meta_rect ( 0, 0, 10, 10); - temp2 = meta_rect (20, 0, 10, 5); - g_assert (!meta_rectangle_overlap (&temp1, &temp2)); - g_assert (!meta_rectangle_horiz_overlap (&temp1, &temp2)); - g_assert ( meta_rectangle_vert_overlap (&temp1, &temp2)); -} - -static void -test_basic_fitting (void) -{ - MetaRectangle temp1, temp2, temp3; - int i; - /* Four cases: - * case temp1 fits temp2 temp1 could fit temp2 - * 1 Y Y - * 2 N Y - * 3 Y N - * 4 N N - * Of the four cases, case 3 is impossible. An alternate way of looking - * at this table is that either the middle column must be no, or the last - * column must be yes. So we test that. Also, we can repeat the test - * reversing temp1 and temp2. - */ - for (i = 0; i < NUM_RANDOM_RUNS; i++) - { - get_random_rect (&temp1); - get_random_rect (&temp2); - g_assert (meta_rectangle_contains_rect (&temp1, &temp2) == FALSE || - meta_rectangle_could_fit_rect (&temp1, &temp2) == TRUE); - g_assert (meta_rectangle_contains_rect (&temp2, &temp1) == FALSE || - meta_rectangle_could_fit_rect (&temp2, &temp1) == TRUE); - } - - temp1 = meta_rect ( 0, 0, 10, 10); - temp2 = meta_rect ( 5, 5, 5, 5); - temp3 = meta_rect ( 8, 2, 3, 7); - g_assert ( meta_rectangle_contains_rect (&temp1, &temp2)); - g_assert (!meta_rectangle_contains_rect (&temp2, &temp1)); - g_assert (!meta_rectangle_contains_rect (&temp1, &temp3)); - g_assert ( meta_rectangle_could_fit_rect (&temp1, &temp3)); - g_assert (!meta_rectangle_could_fit_rect (&temp3, &temp2)); -} - -static void -free_strut_list (GSList *struts) -{ - g_slist_free_full (struts, g_free); -} - -static GSList* -get_strut_list (int which) -{ - GSList *ans; - MetaSide wc = 0; /* wc == who cares? ;-) */ - - ans = NULL; - - g_assert (which >=0 && which <= 6); - switch (which) - { - case 0: - break; - case 1: - ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, META_SIDE_TOP)); - ans = g_slist_prepend (ans, new_meta_strut ( 400, 1160, 1600, 40, META_SIDE_BOTTOM)); - break; - case 2: - ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, META_SIDE_TOP)); - ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100, 400, 100, META_SIDE_BOTTOM)); - ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150, 150, 50, META_SIDE_BOTTOM)); - break; - case 3: - ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, META_SIDE_TOP)); - ans = g_slist_prepend (ans, new_meta_strut ( 800, 1100, 400, 100, META_SIDE_LEFT)); - ans = g_slist_prepend (ans, new_meta_strut ( 300, 1150, 80, 50, META_SIDE_BOTTOM)); - ans = g_slist_prepend (ans, new_meta_strut ( 700, 525, 200, 150, wc)); - break; - case 4: - ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 800, 1200, META_SIDE_LEFT)); - ans = g_slist_prepend (ans, new_meta_strut ( 800, 0, 1600, 20, META_SIDE_TOP)); - break; - case 5: - ans = g_slist_prepend (ans, new_meta_strut ( 800, 0, 1600, 20, META_SIDE_TOP)); - ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 800, 1200, META_SIDE_LEFT)); - ans = g_slist_prepend (ans, new_meta_strut ( 800, 10, 800, 1200, META_SIDE_RIGHT)); - break; - case 6: - ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 40, META_SIDE_TOP)); - ans = g_slist_prepend (ans, new_meta_strut ( 0, 0, 1600, 20, META_SIDE_TOP)); - break; - } - - return ans; -} - -static GList* -get_screen_region (int which) -{ - GList *ret; - GSList *struts; - MetaRectangle basic_rect; - - basic_rect = meta_rect (0, 0, 1600, 1200); - ret = NULL; - - struts = get_strut_list (which); - ret = meta_rectangle_get_minimal_spanning_set_for_region (&basic_rect, struts); - free_strut_list (struts); - - return ret; -} - -static GList* -get_screen_edges (int which) -{ - GList *ret; - GSList *struts; - MetaRectangle basic_rect; - - basic_rect = meta_rect (0, 0, 1600, 1200); - ret = NULL; - - struts = get_strut_list (which); - ret = meta_rectangle_find_onscreen_edges (&basic_rect, struts); - free_strut_list (struts); - - return ret; -} - -static GList* -get_monitor_edges (int which_monitor_set, int which_strut_set) -{ - GList *ret; - GSList *struts; - GList *xins; - - xins = NULL; - g_assert (which_monitor_set >=0 && which_monitor_set <= 3); - switch (which_monitor_set) - { - case 0: - xins = g_list_prepend (xins, new_meta_rect ( 0, 0, 1600, 1200)); - break; - case 1: - xins = g_list_prepend (xins, new_meta_rect ( 0, 0, 800, 1200)); - xins = g_list_prepend (xins, new_meta_rect (800, 0, 800, 1200)); - break; - case 2: - xins = g_list_prepend (xins, new_meta_rect ( 0, 0, 1600, 600)); - xins = g_list_prepend (xins, new_meta_rect ( 0, 600, 1600, 600)); - break; - case 3: - xins = g_list_prepend (xins, new_meta_rect ( 0, 0, 1600, 600)); - xins = g_list_prepend (xins, new_meta_rect ( 0, 600, 800, 600)); - xins = g_list_prepend (xins, new_meta_rect (800, 600, 800, 600)); - break; - } - - ret = NULL; - - struts = get_strut_list (which_strut_set); - ret = meta_rectangle_find_nonintersected_monitor_edges (xins, struts); - - free_strut_list (struts); - meta_rectangle_free_list_and_elements (xins); - - return ret; -} - -#if 0 -static void -test_merge_regions (void) -{ - /* logarithmically distributed random number of struts (range?) - * logarithmically distributed random size of struts (up to screen size???) - * uniformly distributed location of center of struts (within screen) - * merge all regions that are possible - * print stats on problem setup - * number of (non-completely-occluded?) struts - * percentage of screen covered - * length of resulting non-minimal spanning set - * length of resulting minimal spanning set - * print stats on merged regions: - * number boxes merged - * number of those merges that were of the form A contains B - * number of those merges that were of the form A partially contains B - * number of those merges that were of the form A is adjacent to B - */ - - GList* region; - GList* compare; - int num_contains, num_merged, num_part_contains, num_adjacent; - - num_contains = num_merged = num_part_contains = num_adjacent = 0; - compare = region = get_screen_region (2); - g_assert (region); - - printf ("Merging stats:\n"); - printf (" Length of initial list: %d\n", g_list_length (region)); -#ifdef PRINT_DEBUG - char rect1[RECT_LENGTH], rect2[RECT_LENGTH]; - char region_list[(RECT_LENGTH + 2) * g_list_length (region)]; - meta_rectangle_region_to_string (region, ", ", region_list); - printf (" Initial rectangles: %s\n", region_list); -#endif - - while (compare && compare->next) - { - MetaRectangle *a = compare->data; - GList *other = compare->next; - - g_assert (a->width > 0 && a->height > 0); - - while (other) - { - MetaRectangle *b = other->data; - GList *delete_me = NULL; - - g_assert (b->width > 0 && b->height > 0); - -#ifdef PRINT_DEBUG - printf (" -- Comparing %s to %s --\n", - meta_rectangle_to_string (a, rect1), - meta_rectangle_to_string (b, rect2)); -#endif - - /* If a contains b, just remove b */ - if (meta_rectangle_contains_rect (a, b)) - { - delete_me = other; - num_contains++; - num_merged++; - } - /* If b contains a, just remove a */ - else if (meta_rectangle_contains_rect (a, b)) - { - delete_me = compare; - num_contains++; - num_merged++; - } - /* If a and b might be mergeable horizontally */ - else if (a->y == b->y && a->height == b->height) - { - /* If a and b overlap */ - if (meta_rectangle_overlap (a, b)) - { - int new_x = MIN (a->x, b->x); - a->width = MAX (a->x + a->width, b->x + b->width) - new_x; - a->x = new_x; - delete_me = other; - num_part_contains++; - num_merged++; - } - /* If a and b are adjacent */ - else if (a->x + a->width == b->x || a->x == b->x + b->width) - { - int new_x = MIN (a->x, b->x); - a->width = MAX (a->x + a->width, b->x + b->width) - new_x; - a->x = new_x; - delete_me = other; - num_adjacent++; - num_merged++; - } - } - /* If a and b might be mergeable vertically */ - else if (a->x == b->x && a->width == b->width) - { - /* If a and b overlap */ - if (meta_rectangle_overlap (a, b)) - { - int new_y = MIN (a->y, b->y); - a->height = MAX (a->y + a->height, b->y + b->height) - new_y; - a->y = new_y; - delete_me = other; - num_part_contains++; - num_merged++; - } - /* If a and b are adjacent */ - else if (a->y + a->height == b->y || a->y == b->y + b->height) - { - int new_y = MIN (a->y, b->y); - a->height = MAX (a->y + a->height, b->y + b->height) - new_y; - a->y = new_y; - delete_me = other; - num_adjacent++; - num_merged++; - } - } - - other = other->next; - - /* Delete any rectangle in the list that is no longer wanted */ - if (delete_me != NULL) - { -#ifdef PRINT_DEBUG - MetaRectangle *bla = delete_me->data; - printf (" Deleting rect %s\n", - meta_rectangle_to_string (bla, rect1)); -#endif - - /* Deleting the rect we're compare others to is a little tricker */ - if (compare == delete_me) - { - compare = compare->next; - other = compare->next; - a = compare->data; - } - - /* Okay, we can free it now */ - g_free (delete_me->data); - region = g_list_delete_link (region, delete_me); - } - -#ifdef PRINT_DEBUG - char region_list[(RECT_LENGTH + 2) * g_list_length (region)]; - meta_rectangle_region_to_string (region, ", ", region_list); - printf (" After comparison, new list is: %s\n", region_list); -#endif - } - - compare = compare->next; - } - - printf (" Num rectangles contained in others : %d\n", - num_contains); - printf (" Num rectangles partially contained in others: %d\n", - num_part_contains); - printf (" Num rectangles adjacent to others : %d\n", - num_adjacent); - printf (" Num rectangles merged with others : %d\n", - num_merged); -#ifdef PRINT_DEBUG - char region_list2[(RECT_LENGTH + 2) * g_list_length (region)]; - meta_rectangle_region_to_string (region, ", ", region_list2); - printf (" Final rectangles: %s\n", region_list2); -#endif - - meta_rectangle_free_spanning_set (region); - region = NULL; - - printf ("%s passed.\n", G_STRFUNC); -} -#endif - -static void -verify_lists_are_equal (GList *code, GList *answer) -{ - int which = 0; - - while (code && answer) - { - MetaRectangle *a = code->data; - MetaRectangle *b = answer->data; - - if (a->x != b->x || - a->y != b->y || - a->width != b->width || - a->height != b->height) - { - g_error ("%dth item in code answer answer lists do not match; " - "code rect: %d,%d + %d,%d; answer rect: %d,%d + %d,%d\n", - which, - a->x, a->y, a->width, a->height, - b->x, b->y, b->width, b->height); - } - - code = code->next; - answer = answer->next; - - which++; - } - - /* Ought to be at the end of both lists; check if we aren't */ - if (code) - { - MetaRectangle *tmp = code->data; - g_error ("code list longer than answer list by %d items; " - "first extra item: %d,%d +%d,%d\n", - g_list_length (code), - tmp->x, tmp->y, tmp->width, tmp->height); - } - - if (answer) - { - MetaRectangle *tmp = answer->data; - g_error ("answer list longer than code list by %d items; " - "first extra item: %d,%d +%d,%d\n", - g_list_length (answer), - tmp->x, tmp->y, tmp->width, tmp->height); - } -} - -static void -test_regions_okay (void) -{ - GList* region; - GList* tmp; - - /*************************************************************/ - /* Make sure test region 0 has the right spanning rectangles */ - /*************************************************************/ - region = get_screen_region (0); - tmp = NULL; - tmp = g_list_prepend (tmp, new_meta_rect (0, 0, 1600, 1200)); - verify_lists_are_equal (region, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (region); - - /*************************************************************/ - /* Make sure test region 1 has the right spanning rectangles */ - /*************************************************************/ - region = get_screen_region (1); - tmp = NULL; - tmp = g_list_prepend (tmp, new_meta_rect (0, 20, 400, 1180)); - tmp = g_list_prepend (tmp, new_meta_rect (0, 20, 1600, 1140)); - verify_lists_are_equal (region, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (region); - - /*************************************************************/ - /* Make sure test region 2 has the right spanning rectangles */ - /*************************************************************/ - region = get_screen_region (2); - tmp = NULL; - tmp = g_list_prepend (tmp, new_meta_rect ( 0, 20, 300, 1180)); - tmp = g_list_prepend (tmp, new_meta_rect ( 450, 20, 350, 1180)); - tmp = g_list_prepend (tmp, new_meta_rect (1200, 20, 400, 1180)); - tmp = g_list_prepend (tmp, new_meta_rect ( 0, 20, 800, 1130)); - tmp = g_list_prepend (tmp, new_meta_rect ( 0, 20, 1600, 1080)); - verify_lists_are_equal (region, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (region); - - /*************************************************************/ - /* Make sure test region 3 has the right spanning rectangles */ - /*************************************************************/ - region = get_screen_region (3); - tmp = NULL; - tmp = g_list_prepend (tmp, new_meta_rect ( 0, 20, 300, 1180)); /* 354000 */ - tmp = g_list_prepend (tmp, new_meta_rect ( 380, 20, 1220, 1180)); /* 377600 */ - tmp = g_list_prepend (tmp, new_meta_rect ( 0, 20, 1600, 1130)); /* 791000 */ -#if 0 - printf ("Got to here...\n"); - char region_list[(RECT_LENGTH+2) * g_list_length (region)]; - char tmp_list[ (RECT_LENGTH+2) * g_list_length (tmp)]; - meta_rectangle_region_to_string (region, ", ", region_list); - meta_rectangle_region_to_string (region, ", ", tmp_list); - printf ("%s vs. %s\n", region_list, tmp_list); -#endif - verify_lists_are_equal (region, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (region); - - /*************************************************************/ - /* Make sure test region 4 has the right spanning rectangles */ - /*************************************************************/ - region = get_screen_region (4); - tmp = NULL; - tmp = g_list_prepend (tmp, new_meta_rect ( 800, 20, 800, 1180)); - verify_lists_are_equal (region, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (region); - - /*************************************************************/ - /* Make sure test region 5 has the right spanning rectangles */ - /*************************************************************/ - g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, - "Region to merge was empty!*"); - region = get_screen_region (5); - g_test_assert_expected_messages (); - - verify_lists_are_equal (region, NULL); - - /* FIXME: Still to do: - * - Create random struts and check the regions somehow - */ -} - -static void -test_region_fitting (void) -{ - GList* region; - MetaRectangle rect; - - /* See test_basic_fitting() for how/why these automated random tests work */ - int i; - region = get_screen_region (3); - for (i = 0; i < NUM_RANDOM_RUNS; i++) - { - get_random_rect (&rect); - g_assert (meta_rectangle_contained_in_region (region, &rect) == FALSE || - meta_rectangle_could_fit_in_region (region, &rect) == TRUE); - } - meta_rectangle_free_list_and_elements (region); - - /* Do some manual tests too */ - region = get_screen_region (1); - - rect = meta_rect (50, 50, 400, 400); - g_assert (meta_rectangle_could_fit_in_region (region, &rect)); - g_assert (meta_rectangle_contained_in_region (region, &rect)); - - rect = meta_rect (250, 0, 500, 1150); - g_assert (!meta_rectangle_could_fit_in_region (region, &rect)); - g_assert (!meta_rectangle_contained_in_region (region, &rect)); - - rect = meta_rect (250, 0, 400, 400); - g_assert (meta_rectangle_could_fit_in_region (region, &rect)); - g_assert (!meta_rectangle_contained_in_region (region, &rect)); - - meta_rectangle_free_list_and_elements (region); - - region = get_screen_region (2); - rect = meta_rect (1000, 50, 600, 1100); - g_assert (meta_rectangle_could_fit_in_region (region, &rect)); - g_assert (!meta_rectangle_contained_in_region (region, &rect)); - - meta_rectangle_free_list_and_elements (region); -} - -static void -test_clamping_to_region (void) -{ - GList* region; - MetaRectangle rect; - MetaRectangle min_size; - FixedDirections fixed_directions; - int i; - - min_size.height = min_size.width = 1; - fixed_directions = 0; - - region = get_screen_region (3); - for (i = 0; i < NUM_RANDOM_RUNS; i++) - { - MetaRectangle temp; - get_random_rect (&rect); - temp = rect; - meta_rectangle_clamp_to_fit_into_region (region, - fixed_directions, - &rect, - &min_size); - g_assert (meta_rectangle_could_fit_in_region (region, &rect) == TRUE); - g_assert (rect.x == temp.x && rect.y == temp.y); - } - meta_rectangle_free_list_and_elements (region); - - /* Do some manual tests too */ - region = get_screen_region (1); - - rect = meta_rect (50, 50, 10000, 10000); - meta_rectangle_clamp_to_fit_into_region (region, - fixed_directions, - &rect, - &min_size); - g_assert (rect.width == 1600 && rect.height == 1140); - - rect = meta_rect (275, -50, 410, 10000); - meta_rectangle_clamp_to_fit_into_region (region, - fixed_directions, - &rect, - &min_size); - g_assert (rect.width == 400 && rect.height == 1180); - - rect = meta_rect (50, 50, 10000, 10000); - min_size.height = 1170; - meta_rectangle_clamp_to_fit_into_region (region, - fixed_directions, - &rect, - &min_size); - g_assert (rect.width == 400 && rect.height == 1180); - - rect = meta_rect (50, 50, 10000, 10000); - min_size.width = 600; min_size.height = 1170; - - g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, - "No rect whose size to clamp to found*"); - meta_rectangle_clamp_to_fit_into_region (region, - fixed_directions, - &rect, - &min_size); - g_test_assert_expected_messages (); - - g_assert (rect.width == 600 && rect.height == 1170); - - rect = meta_rect (350, 50, 100, 1100); - min_size.width = 1; min_size.height = 1; - fixed_directions = FIXED_DIRECTION_X; - meta_rectangle_clamp_to_fit_into_region (region, - fixed_directions, - &rect, - &min_size); - g_assert (rect.width == 100 && rect.height == 1100); - - rect = meta_rect (300, 70, 500, 1100); - min_size.width = 1; min_size.height = 1; - fixed_directions = FIXED_DIRECTION_Y; - meta_rectangle_clamp_to_fit_into_region (region, - fixed_directions, - &rect, - &min_size); - g_assert (rect.width == 400 && rect.height == 1100); - - rect = meta_rect (300, 70, 999999, 999999); - min_size.width = 100; min_size.height = 200; - fixed_directions = FIXED_DIRECTION_Y; - - g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, - "No rect whose size to clamp to found*"); - meta_rectangle_clamp_to_fit_into_region (region, - fixed_directions, - &rect, - &min_size); - g_test_assert_expected_messages (); - - g_assert (rect.width == 100 && rect.height == 999999); - - meta_rectangle_free_list_and_elements (region); -} - -static gboolean -rect_overlaps_region (const GList *spanning_rects, - const MetaRectangle *rect) -{ - /* FIXME: Should I move this to boxes.[ch]? */ - const GList *temp; - gboolean overlaps; - - temp = spanning_rects; - overlaps = FALSE; - while (!overlaps && temp != NULL) - { - overlaps = overlaps || meta_rectangle_overlap (temp->data, rect); - temp = temp->next; - } - - return overlaps; -} - -gboolean time_to_print = FALSE; - -static void -test_clipping_to_region (void) -{ - GList* region; - MetaRectangle rect, temp; - FixedDirections fixed_directions = 0; - int i; - - region = get_screen_region (3); - for (i = 0; i < NUM_RANDOM_RUNS; i++) - { - get_random_rect (&rect); - if (rect_overlaps_region (region, &rect)) - { - meta_rectangle_clip_to_region (region, 0, &rect); - g_assert (meta_rectangle_contained_in_region (region, &rect) == TRUE); - } - } - meta_rectangle_free_list_and_elements (region); - - /* Do some manual tests too */ - region = get_screen_region (2); - - rect = meta_rect (-50, -10, 10000, 10000); - meta_rectangle_clip_to_region (region, - fixed_directions, - &rect); - g_assert (meta_rectangle_equal (region->data, &rect)); - - rect = meta_rect (300, 1000, 400, 200); - temp = meta_rect (300, 1000, 400, 150); - meta_rectangle_clip_to_region (region, - fixed_directions, - &rect); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect (400, 1000, 300, 200); - temp = meta_rect (450, 1000, 250, 200); - meta_rectangle_clip_to_region (region, - fixed_directions, - &rect); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect (400, 1000, 300, 200); - temp = meta_rect (400, 1000, 300, 150); - meta_rectangle_clip_to_region (region, - FIXED_DIRECTION_X, - &rect); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect (400, 1000, 300, 200); - temp = meta_rect (400, 1000, 300, 150); - meta_rectangle_clip_to_region (region, - FIXED_DIRECTION_X, - &rect); - g_assert (meta_rectangle_equal (&rect, &temp)); - - meta_rectangle_free_list_and_elements (region); -} - -static void -test_shoving_into_region (void) -{ - GList* region; - MetaRectangle rect, temp; - FixedDirections fixed_directions = 0; - int i; - - region = get_screen_region (3); - for (i = 0; i < NUM_RANDOM_RUNS; i++) - { - get_random_rect (&rect); - if (meta_rectangle_could_fit_in_region (region, &rect)) - { - meta_rectangle_shove_into_region (region, 0, &rect); - g_assert (meta_rectangle_contained_in_region (region, &rect)); - } - } - meta_rectangle_free_list_and_elements (region); - - /* Do some manual tests too */ - region = get_screen_region (2); - - rect = meta_rect (300, 1000, 400, 200); - temp = meta_rect (300, 950, 400, 200); - meta_rectangle_shove_into_region (region, - fixed_directions, - &rect); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect (425, 1000, 300, 200); - temp = meta_rect (450, 1000, 300, 200); - meta_rectangle_shove_into_region (region, - fixed_directions, - &rect); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect (425, 1000, 300, 200); - temp = meta_rect (425, 950, 300, 200); - meta_rectangle_shove_into_region (region, - FIXED_DIRECTION_X, - &rect); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect ( 300, 1000, 400, 200); - temp = meta_rect (1200, 1000, 400, 200); - meta_rectangle_shove_into_region (region, - FIXED_DIRECTION_Y, - &rect); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect ( 800, 1150, 400, 50); /* Completely "offscreen" :) */ - temp = meta_rect ( 800, 1050, 400, 50); - meta_rectangle_shove_into_region (region, - 0, - &rect); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect (-1000, 0, 400, 150); /* Offscreen in 2 directions */ - temp = meta_rect ( 0, 20, 400, 150); - meta_rectangle_shove_into_region (region, - 0, - &rect); - g_assert (meta_rectangle_equal (&rect, &temp)); - - meta_rectangle_free_list_and_elements (region); -} - -static void -verify_edge_lists_are_equal (GList *code, GList *answer) -{ - int which = 0; - - while (code && answer) - { - MetaEdge *a = code->data; - MetaEdge *b = answer->data; - - if (!meta_rectangle_equal (&a->rect, &b->rect) || - a->side_type != b->side_type || - a->edge_type != b->edge_type) - { - g_error ("%dth item in code answer answer lists do not match; " - "code rect: %d,%d + %d,%d; answer rect: %d,%d + %d,%d\n", - which, - a->rect.x, a->rect.y, a->rect.width, a->rect.height, - b->rect.x, b->rect.y, b->rect.width, b->rect.height); - } - - code = code->next; - answer = answer->next; - - which++; - } - - /* Ought to be at the end of both lists; check if we aren't */ - if (code) - { - MetaEdge *tmp = code->data; - g_error ("code list longer than answer list by %d items; " - "first extra item rect: %d,%d +%d,%d\n", - g_list_length (code), - tmp->rect.x, tmp->rect.y, tmp->rect.width, tmp->rect.height); - } - - if (answer) - { - MetaEdge *tmp = answer->data; - g_error ("answer list longer than code list by %d items; " - "first extra item rect: %d,%d +%d,%d\n", - g_list_length (answer), - tmp->rect.x, tmp->rect.y, tmp->rect.width, tmp->rect.height); - } -} - -static void -test_find_onscreen_edges (void) -{ - GList* edges; - GList* tmp; - - int left = META_DIRECTION_LEFT; - int right = META_DIRECTION_RIGHT; - int top = META_DIRECTION_TOP; - int bottom = META_DIRECTION_BOTTOM; - - /*************************************************/ - /* Make sure test region 0 has the correct edges */ - /*************************************************/ - edges = get_screen_edges (0); - tmp = NULL; - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 1200, 1600, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 0, 1600, 0, top)); - tmp = g_list_prepend (tmp, new_screen_edge (1600, 0, 0, 1200, right)); - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 0, 0, 1200, left)); - verify_edge_lists_are_equal (edges, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (edges); - - /*************************************************/ - /* Make sure test region 1 has the correct edges */ - /*************************************************/ - edges = get_screen_edges (1); - tmp = NULL; - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 1200, 400, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 400, 1160, 1200, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 20, 1600, 0, top)); - tmp = g_list_prepend (tmp, new_screen_edge (1600, 20, 0, 1140, right)); - tmp = g_list_prepend (tmp, new_screen_edge ( 400, 1160, 0, 40, right)); - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 20, 0, 1180, left)); - verify_edge_lists_are_equal (edges, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (edges); - - /*************************************************/ - /* Make sure test region 2 has the correct edges */ - /*************************************************/ - edges = get_screen_edges (2); - tmp = NULL; - tmp = g_list_prepend (tmp, new_screen_edge (1200, 1200, 400, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 450, 1200, 350, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 1200, 300, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 300, 1150, 150, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 800, 1100, 400, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 20, 1600, 0, top)); - tmp = g_list_prepend (tmp, new_screen_edge (1600, 20, 0, 1180, right)); - tmp = g_list_prepend (tmp, new_screen_edge ( 800, 1100, 0, 100, right)); - tmp = g_list_prepend (tmp, new_screen_edge ( 300, 1150, 0, 50, right)); - tmp = g_list_prepend (tmp, new_screen_edge (1200, 1100, 0, 100, left)); - tmp = g_list_prepend (tmp, new_screen_edge ( 450, 1150, 0, 50, left)); - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 20, 0, 1180, left)); - verify_edge_lists_are_equal (edges, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (edges); - - /*************************************************/ - /* Make sure test region 3 has the correct edges */ - /*************************************************/ - edges = get_screen_edges (3); - tmp = NULL; - tmp = g_list_prepend (tmp, new_screen_edge (1200, 1200, 400, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 380, 1200, 420, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 1200, 300, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 300, 1150, 80, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 800, 1100, 400, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 700, 525, 200, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 700, 675, 200, 0, top)); - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 20, 1600, 0, top)); - tmp = g_list_prepend (tmp, new_screen_edge (1600, 20, 0, 1180, right)); - tmp = g_list_prepend (tmp, new_screen_edge ( 800, 1100, 0, 100, right)); - tmp = g_list_prepend (tmp, new_screen_edge ( 700, 525, 0, 150, right)); - tmp = g_list_prepend (tmp, new_screen_edge ( 300, 1150, 0, 50, right)); - tmp = g_list_prepend (tmp, new_screen_edge (1200, 1100, 0, 100, left)); - tmp = g_list_prepend (tmp, new_screen_edge ( 900, 525, 0, 150, left)); - tmp = g_list_prepend (tmp, new_screen_edge ( 380, 1150, 0, 50, left)); - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 20, 0, 1180, left)); - -#if 0 - #define FUDGE 50 /* number of edges */ - char big_buffer1[(EDGE_LENGTH+2)*FUDGE], big_buffer2[(EDGE_LENGTH+2)*FUDGE]; - meta_rectangle_edge_list_to_string (edges, "\n ", big_buffer1); - meta_rectangle_edge_list_to_string (tmp, "\n ", big_buffer2); - printf("Generated edge list:\n %s\nComparison edges list:\n %s\n", - big_buffer1, big_buffer2); -#endif - - verify_edge_lists_are_equal (edges, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (edges); - - /*************************************************/ - /* Make sure test region 4 has the correct edges */ - /*************************************************/ - edges = get_screen_edges (4); - tmp = NULL; - tmp = g_list_prepend (tmp, new_screen_edge ( 800, 1200, 800, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 800, 20, 800, 0, top)); - tmp = g_list_prepend (tmp, new_screen_edge (1600, 20, 0, 1180, right)); - tmp = g_list_prepend (tmp, new_screen_edge ( 800, 20, 0, 1180, left)); - verify_edge_lists_are_equal (edges, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (edges); - - /*************************************************/ - /* Make sure test region 5 has the correct edges */ - /*************************************************/ - edges = get_screen_edges (5); - tmp = NULL; - verify_edge_lists_are_equal (edges, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (edges); - - /*************************************************/ - /* Make sure test region 6 has the correct edges */ - /*************************************************/ - edges = get_screen_edges (6); - tmp = NULL; - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 1200, 1600, 0, bottom)); - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 40, 1600, 0, top)); - tmp = g_list_prepend (tmp, new_screen_edge (1600, 40, 0, 1160, right)); - tmp = g_list_prepend (tmp, new_screen_edge ( 0, 40, 0, 1160, left)); - verify_edge_lists_are_equal (edges, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (edges); -} - -static void -test_find_nonintersected_monitor_edges (void) -{ - GList* edges; - GList* tmp; - - int left = META_DIRECTION_LEFT; - int right = META_DIRECTION_RIGHT; - int top = META_DIRECTION_TOP; - int bottom = META_DIRECTION_BOTTOM; - - /*************************************************************************/ - /* Make sure test monitor set 0 for with region 0 has the correct edges */ - /*************************************************************************/ - edges = get_monitor_edges (0, 0); - tmp = NULL; - verify_edge_lists_are_equal (edges, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (edges); - - /*************************************************************************/ - /* Make sure test monitor set 2 for with region 1 has the correct edges */ - /*************************************************************************/ - edges = get_monitor_edges (2, 1); - tmp = NULL; - tmp = g_list_prepend (tmp, new_monitor_edge ( 0, 600, 1600, 0, bottom)); - tmp = g_list_prepend (tmp, new_monitor_edge ( 0, 600, 1600, 0, top)); - verify_edge_lists_are_equal (edges, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (edges); - - /*************************************************************************/ - /* Make sure test monitor set 1 for with region 2 has the correct edges */ - /*************************************************************************/ - edges = get_monitor_edges (1, 2); - tmp = NULL; - tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 20, 0, 1080, right)); - tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 20, 0, 1180, left)); -#if 0 - #define FUDGE 50 - char big_buffer1[(EDGE_LENGTH+2)*FUDGE], big_buffer2[(EDGE_LENGTH+2)*FUDGE]; - meta_rectangle_edge_list_to_string (edges, "\n ", big_buffer1); - meta_rectangle_edge_list_to_string (tmp, "\n ", big_buffer2); - printf("Generated edge list:\n %s\nComparison edges list:\n %s\n", - big_buffer1, big_buffer2); -#endif - verify_edge_lists_are_equal (edges, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (edges); - - /*************************************************************************/ - /* Make sure test monitor set 3 for with region 3 has the correct edges */ - /*************************************************************************/ - edges = get_monitor_edges (3, 3); - tmp = NULL; - tmp = g_list_prepend (tmp, new_monitor_edge ( 900, 600, 700, 0, bottom)); - tmp = g_list_prepend (tmp, new_monitor_edge ( 0, 600, 700, 0, bottom)); - tmp = g_list_prepend (tmp, new_monitor_edge ( 900, 600, 700, 0, top)); - tmp = g_list_prepend (tmp, new_monitor_edge ( 0, 600, 700, 0, top)); - tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 675, 0, 425, right)); - tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 675, 0, 525, left)); - verify_edge_lists_are_equal (edges, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (edges); - - /*************************************************************************/ - /* Make sure test monitor set 3 for with region 4 has the correct edges */ - /*************************************************************************/ - edges = get_monitor_edges (3, 4); - tmp = NULL; - tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 600, 800, 0, bottom)); - tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 600, 800, 0, top)); - tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 600, 0, 600, right)); - verify_edge_lists_are_equal (edges, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (edges); - - /*************************************************************************/ - /* Make sure test monitor set 3 for with region 5has the correct edges */ - /*************************************************************************/ - edges = get_monitor_edges (3, 5); - tmp = NULL; - verify_edge_lists_are_equal (edges, tmp); - meta_rectangle_free_list_and_elements (tmp); - meta_rectangle_free_list_and_elements (edges); -} - -static void -test_gravity_resize (void) -{ - MetaRectangle oldrect, rect, temp; - - rect.x = -500; /* Some random amount not equal to oldrect.x to ensure that - * the resize is done with respect to oldrect instead of rect - */ - oldrect = meta_rect ( 50, 300, 250, 400); - temp = meta_rect ( 50, 300, 20, 5); - meta_rectangle_resize_with_gravity (&oldrect, - &rect, - META_GRAVITY_NORTH_WEST, - 20, - 5); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect ( 50, 300, 250, 400); - temp = meta_rect (165, 300, 20, 5); - meta_rectangle_resize_with_gravity (&rect, - &rect, - META_GRAVITY_NORTH, - 20, - 5); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect ( 50, 300, 250, 400); - temp = meta_rect (280, 300, 20, 5); - meta_rectangle_resize_with_gravity (&rect, - &rect, - META_GRAVITY_NORTH_EAST, - 20, - 5); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect ( 50, 300, 250, 400); - temp = meta_rect ( 50, 695, 50, 5); - meta_rectangle_resize_with_gravity (&rect, - &rect, - META_GRAVITY_SOUTH_WEST, - 50, - 5); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect ( 50, 300, 250, 400); - temp = meta_rect (150, 695, 50, 5); - meta_rectangle_resize_with_gravity (&rect, - &rect, - META_GRAVITY_SOUTH, - 50, - 5); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect ( 50, 300, 250, 400); - temp = meta_rect (250, 695, 50, 5); - meta_rectangle_resize_with_gravity (&rect, - &rect, - META_GRAVITY_SOUTH_EAST, - 50, - 5); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect (167, 738, 237, 843); - temp = meta_rect (167, 1113, 832, 93); - meta_rectangle_resize_with_gravity (&rect, - &rect, - META_GRAVITY_WEST, - 832, - 93); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect ( 167, 738, 237, 843); - temp = meta_rect (-131, 1113, 833, 93); - meta_rectangle_resize_with_gravity (&rect, - &rect, - META_GRAVITY_CENTER, - 832, - 93); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect (300, 1000, 400, 200); - temp = meta_rect (270, 994, 430, 212); - meta_rectangle_resize_with_gravity (&rect, - &rect, - META_GRAVITY_EAST, - 430, - 211); - g_assert (meta_rectangle_equal (&rect, &temp)); - - rect = meta_rect (300, 1000, 400, 200); - temp = meta_rect (300, 1000, 430, 211); - meta_rectangle_resize_with_gravity (&rect, - &rect, - META_GRAVITY_STATIC, - 430, - 211); - g_assert (meta_rectangle_equal (&rect, &temp)); -} - -#define EPSILON 0.000000001 -static void -test_find_closest_point_to_line (void) -{ - double x1, y1, x2, y2, px, py, rx, ry; - double answer_x, answer_y; - - x1 = 3.0; y1 = 49.0; - x2 = 2.0; y2 = - 1.0; - px = -2.6; py = 19.1; - answer_x = 2.4; answer_y = 19; - meta_rectangle_find_linepoint_closest_to_point (x1, y1, - x2, y2, - px, py, - &rx, &ry); - g_assert (fabs (rx - answer_x) < EPSILON && fabs (ry - answer_y) < EPSILON); - - /* Special test for x1 == x2, so that slop of line is infinite */ - x1 = 3.0; y1 = 49.0; - x2 = 3.0; y2 = - 1.0; - px = -2.6; py = 19.1; - answer_x = 3.0; answer_y = 19.1; - meta_rectangle_find_linepoint_closest_to_point (x1, y1, - x2, y2, - px, py, - &rx, &ry); - g_assert (fabs (rx - answer_x) < EPSILON && fabs (ry - answer_y) < EPSILON); - - /* Special test for y1 == y2, so perp line has slope of infinity */ - x1 = 3.14; y1 = 7.0; - x2 = 2.718; y2 = 7.0; - px = -2.6; py = 19.1; - answer_x = -2.6; answer_y = 7; - meta_rectangle_find_linepoint_closest_to_point (x1, y1, - x2, y2, - px, py, - &rx, &ry); - g_assert (fabs (rx - answer_x) < EPSILON && fabs (ry - answer_y) < EPSILON); - - /* Test when we the point we want to be closest to is actually on the line */ - x1 = 3.0; y1 = 49.0; - x2 = 2.0; y2 = - 1.0; - px = 2.4; py = 19.0; - answer_x = 2.4; answer_y = 19; - meta_rectangle_find_linepoint_closest_to_point (x1, y1, - x2, y2, - px, py, - &rx, &ry); - g_assert (fabs (rx - answer_x) < EPSILON && fabs (ry - answer_y) < EPSILON); -} - -void -init_boxes_tests (void) -{ - init_random_ness (); - - g_test_add_func ("/util/boxes/area", test_area); - g_test_add_func ("/util/boxes/intersect", test_intersect); - g_test_add_func ("/util/boxes/equal", test_equal); - g_test_add_func ("/util/boxes/overlap", test_overlap_funcs); - g_test_add_func ("/util/boxes/basic-fitting", test_basic_fitting); - - g_test_add_func ("/util/boxes/regions-ok", test_regions_okay); - g_test_add_func ("/util/boxes/regions-fitting", test_region_fitting); - - g_test_add_func ("/util/boxes/clamp-to-region", test_clamping_to_region); - g_test_add_func ("/util/boxes/clip-to-region", test_clipping_to_region); - g_test_add_func ("/util/boxes/shove-into-region", test_shoving_into_region); - - /* And now the functions dealing with edges more than boxes */ - g_test_add_func ("/util/boxes/onscreen-edges", test_find_onscreen_edges); - g_test_add_func ("/util/boxes/nonintersected-monitor-edges", - test_find_nonintersected_monitor_edges); - - /* And now the misfit functions that don't quite fit in anywhere else... */ - g_test_add_func ("/util/boxes/gravity-resize", test_gravity_resize); - g_test_add_func ("/util/boxes/closest-point-to-line", - test_find_closest_point_to_line); -} diff --git a/src/tests/boxes-tests.h b/src/tests/boxes-tests.h deleted file mode 100644 index 9f3b778b7..000000000 --- a/src/tests/boxes-tests.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 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 . - */ - -#ifndef BOXES_TESTS_H -#define BOXES_TESTS_H - -void init_boxes_tests (void); - -#endif /* BOXES_TESTS_H */ diff --git a/src/tests/clutter-test-utils.c b/src/tests/clutter-test-utils.c deleted file mode 100644 index de4b94e23..000000000 --- a/src/tests/clutter-test-utils.c +++ /dev/null @@ -1,473 +0,0 @@ -#include "clutter-test-utils.h" - -#include -#include -#include - -#include "compositor/meta-plugin-manager.h" -#include "core/meta-context-private.h" - -typedef struct { - gpointer dummy_field; -} ClutterTestEnvironment; - -static ClutterTestEnvironment *test_environ = NULL; - -static GMainLoop *clutter_test_main_loop = NULL; - -#define DBUS_NAME_WARNING "Lost or failed to acquire name" - -static gboolean -log_func (const gchar *log_domain, - GLogLevelFlags log_level, - const gchar *message, - gpointer user_data) -{ - if ((log_level & G_LOG_LEVEL_WARNING) && - g_strcmp0 (log_domain, "mutter") == 0 && - g_str_has_prefix (message, DBUS_NAME_WARNING)) - return FALSE; - - return TRUE; -} - -/* - * clutter_test_init: - * @argc: (inout): number of arguments in @argv - * @argv: (inout) (array length=argc) (nullable): array of arguments - * - * Initializes the Clutter test environment. - * - * Since: 1.18 - */ -void -clutter_test_init (int *argc, - char ***argv) -{ - MetaContext *context; - - context = meta_create_test_context (META_CONTEXT_TEST_TYPE_NESTED, - META_CONTEXT_TEST_FLAG_NO_X11); - g_assert (meta_context_configure (context, argc, argv, NULL)); - g_assert (meta_context_setup (context, NULL)); - - test_environ = g_new0 (ClutterTestEnvironment, 1); - - g_assert (meta_context_start (context, NULL)); - - clutter_test_main_loop = g_main_loop_new (NULL, FALSE); -} - -/** - * clutter_test_get_stage: - * - * Retrieves the #ClutterStage used for testing. - * - * Return value: (transfer none): the stage used for testing - * - * Since: 1.18 - */ -ClutterActor * -clutter_test_get_stage (void) -{ - MetaBackend *backend = meta_get_backend (); - - return meta_backend_get_stage (backend); -} - -typedef struct { - gpointer test_func; - gpointer test_data; - GDestroyNotify test_notify; -} ClutterTestData; - -static gboolean -list_equal_unsorted (GList *list_a, - GList *list_b) -{ - GList *l_a; - GList *l_b; - - for (l_a = list_a, l_b = list_b; - l_a && l_b; - l_a = l_a->next, l_b = l_b->next) - { - if (l_a->data != l_b->data) - return FALSE; - } - - return !l_a && !l_b; -} - -static void -clutter_test_func_wrapper (gconstpointer data_) -{ - const ClutterTestData *data = data_; - ClutterActor *stage; - GList *pre_stage_children; - GList *post_stage_children; - - g_test_log_set_fatal_handler (log_func, NULL); - - /* ensure that the previous test state has been cleaned up */ - stage = clutter_test_get_stage (); - clutter_actor_hide (stage); - - pre_stage_children = clutter_actor_get_children (stage); - - if (data->test_data != NULL) - { - GTestDataFunc test_func = data->test_func; - - test_func (data->test_data); - } - else - { - GTestFunc test_func = data->test_func; - - test_func (); - } - - if (data->test_notify != NULL) - data->test_notify (data->test_data); - - post_stage_children = clutter_actor_get_children (stage); - - g_assert_true (list_equal_unsorted (pre_stage_children, post_stage_children)); - - g_list_free (pre_stage_children); - g_list_free (post_stage_children); - - clutter_actor_hide (stage); -} - -/** - * clutter_test_add: (skip) - * @test_path: unique path for identifying the test - * @test_func: function containing the test - * - * Adds a test unit to the Clutter test environment. - * - * See also: g_test_add() - * - * Since: 1.18 - */ -void -clutter_test_add (const char *test_path, - GTestFunc test_func) -{ - clutter_test_add_data_full (test_path, (GTestDataFunc) test_func, NULL, NULL); -} - -/** - * clutter_test_add_data: (skip) - * @test_path: unique path for identifying the test - * @test_func: function containing the test - * @test_data: data to pass to the test function - * - * Adds a test unit to the Clutter test environment. - * - * See also: g_test_add_data_func() - * - * Since: 1.18 - */ -void -clutter_test_add_data (const char *test_path, - GTestDataFunc test_func, - gpointer test_data) -{ - clutter_test_add_data_full (test_path, test_func, test_data, NULL); -} - -/** - * clutter_test_add_data_full: - * @test_path: unique path for identifying the test - * @test_func: (scope notified): function containing the test - * @test_data: (closure): data to pass to the test function - * @test_notify: function called when the test function ends - * - * Adds a test unit to the Clutter test environment. - * - * See also: g_test_add_data_func_full() - * - * Since: 1.18 - */ -void -clutter_test_add_data_full (const char *test_path, - GTestDataFunc test_func, - gpointer test_data, - GDestroyNotify test_notify) -{ - ClutterTestData *data; - - g_return_if_fail (test_path != NULL); - g_return_if_fail (test_func != NULL); - - g_assert (test_environ != NULL); - - data = g_new (ClutterTestData, 1); - data->test_func = test_func; - data->test_data = test_data; - data->test_notify = test_notify; - - g_test_add_data_func_full (test_path, data, - clutter_test_func_wrapper, - g_free); -} - -/** - * clutter_test_run: - * - * Runs the test suite using the units added by calling - * clutter_test_add(). - * - * The typical test suite is composed of a list of functions - * called by clutter_test_run(), for instance: - * - * |[ - * static void unit_foo (void) { ... } - * - * static void unit_bar (void) { ... } - * - * static void unit_baz (void) { ... } - * - * int - * main (int argc, char *argv[]) - * { - * clutter_test_init (&argc, &argv); - * - * clutter_test_add ("/unit/foo", unit_foo); - * clutter_test_add ("/unit/bar", unit_bar); - * clutter_test_add ("/unit/baz", unit_baz); - * - * return clutter_test_run (); - * } - * ]| - * - * Return value: the exit code for the test suite - * - * Since: 1.18 - */ -int -clutter_test_run (void) -{ - int res; - - g_assert (test_environ != NULL); - - res = g_test_run (); - - g_free (test_environ); - - return res; -} - -void -clutter_test_main (void) -{ - g_assert_nonnull (clutter_test_main_loop); - - g_main_loop_run (clutter_test_main_loop); -} - -void -clutter_test_quit (void) -{ - g_assert_nonnull (clutter_test_main_loop); - - g_main_loop_quit (clutter_test_main_loop); -} - -typedef struct { - ClutterActor *stage; - - graphene_point_t point; - - gpointer result; - - guint check_actor : 1; - guint check_color : 1; - - guint was_painted : 1; -} ValidateData; - -static gboolean -validate_stage (gpointer data_) -{ - ValidateData *data = data_; - - if (data->check_actor) - { - data->result = - clutter_stage_get_actor_at_pos (CLUTTER_STAGE (data->stage), - CLUTTER_PICK_ALL, - data->point.x, - data->point.y); - } - - if (data->check_color) - { - data->result = - clutter_stage_read_pixels (CLUTTER_STAGE (data->stage), - data->point.x, - data->point.y, - 1, 1); - } - - if (!g_test_verbose ()) - { - clutter_actor_hide (data->stage); - data->was_painted = TRUE; - } - - return G_SOURCE_REMOVE; -} - -static gboolean -on_key_press_event (ClutterActor *stage, - ClutterEvent *event, - gpointer data_) -{ - ValidateData *data = data_; - - if (data->stage == stage && - clutter_event_get_key_symbol (event) == CLUTTER_KEY_Escape) - { - clutter_actor_hide (stage); - - data->was_painted = TRUE; - } - - return CLUTTER_EVENT_PROPAGATE; -} - -/** - * clutter_test_check_actor_at_point: - * @stage: a #ClutterStage - * @point: coordinates to check - * @actor: the expected actor at the given coordinates - * @result: (out) (nullable): actor at the coordinates - * - * Checks the given coordinates of the @stage and compares the - * actor found there with the given @actor. - * - * Returns: %TRUE if the actor at the given coordinates matches - * - * Since: 1.18 - */ -gboolean -clutter_test_check_actor_at_point (ClutterActor *stage, - const graphene_point_t *point, - ClutterActor *actor, - ClutterActor **result) -{ - ValidateData *data; - gulong press_id = 0; - - g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); - g_return_val_if_fail (point != NULL, FALSE); - g_return_val_if_fail (CLUTTER_IS_ACTOR (stage), FALSE); - g_return_val_if_fail (result != NULL, FALSE); - - data = g_new0 (ValidateData, 1); - data->stage = stage; - data->point = *point; - data->check_actor = TRUE; - - if (g_test_verbose ()) - { - g_printerr ("Press ESC to close the stage and resume the test\n"); - press_id = g_signal_connect (stage, "key-press-event", - G_CALLBACK (on_key_press_event), - data); - } - - clutter_actor_show (stage); - - clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT, - validate_stage, - data, - NULL); - - while (!data->was_painted) - g_main_context_iteration (NULL, TRUE); - - *result = data->result; - - g_clear_signal_handler (&press_id, stage); - - g_free (data); - - return *result == actor; -} - -/** - * clutter_test_check_color_at_point: - * @stage: a #ClutterStage - * @point: coordinates to check - * @color: expected color - * @result: (out caller-allocates): color at the given coordinates - * - * Checks the color at the given coordinates on @stage, and matches - * it with the red, green, and blue channels of @color. The alpha - * component of @color and @result is ignored. - * - * Returns: %TRUE if the colors match - * - * Since: 1.18 - */ -gboolean -clutter_test_check_color_at_point (ClutterActor *stage, - const graphene_point_t *point, - const ClutterColor *color, - ClutterColor *result) -{ - ValidateData *data; - gboolean retval; - guint8 *buffer; - gulong press_id = 0; - - g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE); - g_return_val_if_fail (point != NULL, FALSE); - g_return_val_if_fail (color != NULL, FALSE); - g_return_val_if_fail (result != NULL, FALSE); - - data = g_new0 (ValidateData, 1); - data->stage = stage; - data->point = *point; - data->check_color = TRUE; - - if (g_test_verbose ()) - { - g_printerr ("Press ESC to close the stage and resume the test\n"); - press_id = g_signal_connect (stage, "key-press-event", - G_CALLBACK (on_key_press_event), - data); - } - - clutter_actor_show (stage); - - clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT, - validate_stage, - data, - NULL); - - while (!data->was_painted) - g_main_context_iteration (NULL, TRUE); - - g_clear_signal_handler (&press_id, stage); - - buffer = data->result; - - clutter_color_init (result, buffer[0], buffer[1], buffer[2], 255); - - /* we only check the color channels, so we can't use clutter_color_equal() */ - retval = buffer[0] == color->red && - buffer[1] == color->green && - buffer[2] == color->blue; - - g_free (data->result); - g_free (data); - - return retval; -} diff --git a/src/tests/clutter-test-utils.h b/src/tests/clutter-test-utils.h deleted file mode 100644 index 95f54ceed..000000000 --- a/src/tests/clutter-test-utils.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Clutter. - * - * An OpenGL based 'interactive canvas' library. - * - * Copyright (C) 2013 Emmanuele Bassi - * - * 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 . - */ - -#include "config.h" - -#ifndef __CLUTTER_TEST_UTILS_H__ -#define __CLUTTER_TEST_UTILS_H__ - -#define __CLUTTER_H_INSIDE__ - -#include "clutter/clutter-types.h" -#include "clutter/clutter-actor.h" -#include "clutter/clutter-color.h" -#include "clutter/clutter-private.h" -#include "meta/common.h" -#include "meta-test/meta-context-test.h" - -G_BEGIN_DECLS - -/** - * CLUTTER_TEST_UNIT: - * @path: the GTest path for the test function - * @func: the GTestFunc function - * - * Adds @func at the given @path in the test suite. - * - * Since: 1.18 - */ -#define CLUTTER_TEST_UNIT(path,func) \ - clutter_test_add (path, func); - -/** - * CLUTTER_TEST_SUITE: - * @units: a list of %CLUTTER_TEST_UNIT definitions - * - * Defines the entry point and initializes a Clutter test unit, e.g.: - * - * |[ - * CLUTTER_TEST_SUITE ( - * CLUTTER_TEST_UNIT ("/foobarize", foobarize) - * CLUTTER_TEST_UNIT ("/bar-enabled", bar_enabled) - * ) - * ]| - * - * Expands to: - * - * |[ - * int - * main (int argc, - * char *argv[]) - * { - * clutter_test_init (&argc, &argv); - * - * clutter_test_add ("/foobarize", foobarize); - * clutter_test_add ("/bar-enabled", bar_enabled); - * - * return clutter_test_run (); - * } - * ]| - * - * Since: 1.18 - */ -#define CLUTTER_TEST_SUITE(units) \ -int \ -main (int argc, char *argv[]) \ -{ \ - clutter_test_init (&argc, &argv); \ -\ - { \ - units \ - } \ -\ - return clutter_test_run (); \ -} - -CLUTTER_EXPORT -void clutter_test_init (int *argc, - char ***argv); - -CLUTTER_EXPORT -int clutter_test_run (void); - -CLUTTER_EXPORT -void clutter_test_main (void); - -CLUTTER_EXPORT -void clutter_test_quit (void); - -CLUTTER_EXPORT -void clutter_test_add (const char *test_path, - GTestFunc test_func); -CLUTTER_EXPORT -void clutter_test_add_data (const char *test_path, - GTestDataFunc test_func, - gpointer test_data); -CLUTTER_EXPORT -void clutter_test_add_data_full (const char *test_path, - GTestDataFunc test_func, - gpointer test_data, - GDestroyNotify test_notify); - -CLUTTER_EXPORT -ClutterActor * clutter_test_get_stage (void); - -#define clutter_test_assert_actor_at_point(stage,point,actor) \ -G_STMT_START { \ - const graphene_point_t *__p = (point); \ - ClutterActor *__actor = (actor); \ - ClutterActor *__stage = (stage); \ - ClutterActor *__res; \ - if (clutter_test_check_actor_at_point (__stage, __p, actor, &__res)) ; else { \ - const char *__str1 = clutter_actor_get_name (__actor) != NULL \ - ? clutter_actor_get_name (__actor) \ - : G_OBJECT_TYPE_NAME (__actor); \ - const char *__str2 = clutter_actor_get_name (__res) != NULL \ - ? clutter_actor_get_name (__res) \ - : G_OBJECT_TYPE_NAME (__res); \ - char *__msg = g_strdup_printf ("assertion failed (actor %s at %.2f,%.2f): found actor %s", \ - __str1, __p->x, __p->y, __str2); \ - g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, __msg); \ - g_free (__msg); \ - } \ -} G_STMT_END - -#define clutter_test_assert_color_at_point(stage,point,color) \ -G_STMT_START { \ - const graphene_point_t *__p = (point); \ - const ClutterColor *__c = (color); \ - ClutterActor *__stage = (stage); \ - ClutterColor __res; \ - if (clutter_test_check_color_at_point (__stage, __p, __c, &__res)) ; else { \ - char *__str1 = clutter_color_to_string (__c); \ - char *__str2 = clutter_color_to_string (&__res); \ - char *__msg = g_strdup_printf ("assertion failed (color %s at %.2f,%.2f): found color %s", \ - __str1, __p->x, __p->y, __str2); \ - g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, __msg); \ - g_free (__msg); \ - g_free (__str1); \ - g_free (__str2); \ - } \ -} G_STMT_END - -CLUTTER_EXPORT -gboolean clutter_test_check_actor_at_point (ClutterActor *stage, - const graphene_point_t *point, - ClutterActor *actor, - ClutterActor **result); -CLUTTER_EXPORT -gboolean clutter_test_check_color_at_point (ClutterActor *stage, - const graphene_point_t *point, - const ClutterColor *color, - ClutterColor *result); - -G_END_DECLS - -#endif /* __CLUTTER_TEST_UTILS_H__ */ diff --git a/src/tests/clutter/README b/src/tests/clutter/README deleted file mode 100644 index b5665e6ab..000000000 --- a/src/tests/clutter/README +++ /dev/null @@ -1,38 +0,0 @@ -Outline of test categories: - -The conform/ tests should be non-interactive unit-tests that verify a single -feature is behaving as documented. Use the GLib and Clutter test API and macros -to write the test units. The conformance test suites are meant to be used with -continuous integration builds. - -The performance/ tests are performance tests, both focused tests testing single -metrics and larger tests. These tests are used to report one or more -performance markers for the build of Clutter. Each performance marker is picked -up from the standard output of running the tests from strings having the form -"\n@ marker-name: 42.23" where 'marker-name' and '42.23' are the key/value pairs -of a single metric. Each test can provide multiple key/value pairs. Note that -if framerate is the feedback metric the test should forcibly enable FPS -debugging itself. The file test-common.h contains utility function helping to -do fps reporting. - -The interactive/ tests are any tests whose status can not be determined without -a user looking at some visual output, or providing some manual input etc. This -covers most of the original Clutter tests. Ideally some of these tests will be -migrated into the conform/ directory. - -The accessibility/ tests are tests created to test the accessibility support of -clutter, testing some of the atk interfaces. - -Other notes: - -• All tests should ideally include a detailed description in the source -explaining exactly what the test is for, how the test was designed to work, -and possibly a rationale for the approach taken for testing. Tests for specific -bugs should reference the bug report URL or number. - -• When running tests under Valgrind, you should follow the instructions -available here: - - https://wiki.gnome.org/Valgrind - -and also use the suppression file available in the Git repository. diff --git a/src/tests/clutter/accessibility/cally-atkcomponent-example.c b/src/tests/clutter/accessibility/cally-atkcomponent-example.c deleted file mode 100644 index 4e7024597..000000000 --- a/src/tests/clutter/accessibility/cally-atkcomponent-example.c +++ /dev/null @@ -1,95 +0,0 @@ -/* CALLY - The Clutter Accessibility Implementation Library - * - * Copyright (C) 2009 Igalia, S.L. - * - * Author: Alejandro Piñeiro Iglesias - * - * 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, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include - -#include "cally-examples-util.h" - -#define WIDTH 300 -#define HEIGHT 300 -#define SIZE 50 -#define DEPTH -100 - -int -main (int argc, char *argv[]) -{ - ClutterActor *stage = NULL; - ClutterActor *button1 = NULL; - ClutterActor *button2 = NULL; - ClutterActor *button3 = NULL; - ClutterActor *button4 = NULL; - ClutterActor *group[4]; - int i = 0; - - cally_util_a11y_init (&argc, &argv); - - stage = clutter_test_get_stage (); - - clutter_stage_set_title (CLUTTER_STAGE (stage), "Cally - AtkComponent Test"); - clutter_actor_set_background_color (CLUTTER_ACTOR (stage), CLUTTER_COLOR_White); - clutter_actor_set_size (stage, WIDTH, HEIGHT); - - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - - button1 = clutter_actor_new (); - clutter_actor_set_background_color (button1, CLUTTER_COLOR_Yellow); - clutter_actor_set_size (button1, SIZE, SIZE); - - button2 = clutter_actor_new (); - clutter_actor_set_background_color (button2, CLUTTER_COLOR_Green); - clutter_actor_set_position (button2, 2 * SIZE, 0); - clutter_actor_set_size (button2, SIZE, SIZE); - - button3 = clutter_actor_new (); - clutter_actor_set_background_color (button3, CLUTTER_COLOR_Blue); - clutter_actor_set_position (button3, 0, 2 * SIZE); - clutter_actor_set_size (button3, SIZE, SIZE); - clutter_actor_set_z_position (button3, DEPTH); - - /* a nested hierarchy, to check that the relative positions are - computed properly */ - button4 = clutter_actor_new (); - clutter_actor_set_background_color (button4, CLUTTER_COLOR_Magenta); - clutter_actor_set_position (button4, SIZE / 2, SIZE / 2); - clutter_actor_set_size (button4, SIZE, SIZE); - - for (i = 0; i < 4; i++) { - group[i] = clutter_actor_new (); - clutter_actor_set_position (group[i], SIZE / 2, SIZE / 2); - clutter_actor_set_size (group[i], SIZE, SIZE); - - if (i > 0) - clutter_container_add_actor (CLUTTER_CONTAINER (group[i]), group [i - 1]); - } - - clutter_container_add_actor (CLUTTER_CONTAINER (stage), button1); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), button2); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), button3); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), group[3]); - clutter_container_add_actor (CLUTTER_CONTAINER (group[0]), button4); - - clutter_actor_show (stage); - - clutter_test_main (); - - return 0; -} diff --git a/src/tests/clutter/accessibility/cally-atkeditabletext-example.c b/src/tests/clutter/accessibility/cally-atkeditabletext-example.c deleted file mode 100644 index 0c28ee90b..000000000 --- a/src/tests/clutter/accessibility/cally-atkeditabletext-example.c +++ /dev/null @@ -1,266 +0,0 @@ -/* CALLY - The Clutter Accessibility Implementation Library - * - * Copyright (C) 2009 Igalia, S.L. - * - * Author: Alejandro Piñeiro Iglesias - * - * 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, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include -#include - -#include "cally-examples-util.h" - -#define WIDTH 800 -#define HEIGHT 600 - -static ClutterActor *text_actor = NULL; -static ClutterActor *text_editable_actor = NULL; - -/* - * Test AtkText interface - */ -static void -test_atk_text (ClutterActor *actor) -{ - AtkObject *object = NULL; - AtkEditableText *cally_editable_text = NULL; - gint pos = 0; - - object = atk_gobject_accessible_for_object (G_OBJECT (actor)); - cally_editable_text = ATK_EDITABLE_TEXT (object); - - if (cally_editable_text != NULL) { - atk_editable_text_set_text_contents (cally_editable_text, "New text"); - atk_editable_text_delete_text (cally_editable_text, 0, 3); - pos = 3; - atk_editable_text_insert_text (cally_editable_text, "New", 0, &pos); - - /* Not implemented in cally, just checking that we can call this - functions */ - atk_editable_text_copy_text (cally_editable_text, 0, -1); - atk_editable_text_paste_text (cally_editable_text, 5); - atk_editable_text_cut_text (cally_editable_text, 0, -1); - } -} - -static gboolean -insert_text_press_cb (ClutterActor *actor, - ClutterButtonEvent *event, - gpointer data) -{ - AtkObject *object = NULL; - AtkEditableText *cally_editable_text = NULL; - gint pos = 0; - - object = atk_gobject_accessible_for_object (G_OBJECT (text_editable_actor)); - cally_editable_text = ATK_EDITABLE_TEXT (object); - - pos = 3; - atk_editable_text_insert_text (cally_editable_text, "New", 0, &pos); - - return TRUE; -} - -static gboolean -delete_text_press_cb (ClutterActor *actor, - ClutterButtonEvent *event, - gpointer data) -{ - AtkObject *object = NULL; - AtkEditableText *cally_editable_text = NULL; - - object = atk_gobject_accessible_for_object (G_OBJECT (text_editable_actor)); - cally_editable_text = ATK_EDITABLE_TEXT (object); - - atk_editable_text_delete_text (cally_editable_text, 0, 3); - - return TRUE; -} - -static gboolean -set_text_press_cb (ClutterActor *actor, - ClutterButtonEvent *event, - gpointer data) -{ - AtkObject *object = NULL; - AtkEditableText *cally_editable_text = NULL; - - object = atk_gobject_accessible_for_object (G_OBJECT (text_editable_actor)); - cally_editable_text = ATK_EDITABLE_TEXT (object); - - atk_editable_text_set_text_contents (cally_editable_text, "New text"); - - return TRUE; -} - -static gboolean -activate_deactivate_press_cb (ClutterActor *actor, - ClutterButtonEvent *event, - gpointer data) -{ - gboolean active = FALSE; - - active = clutter_text_get_activatable (CLUTTER_TEXT (text_editable_actor)); - clutter_text_set_activatable (CLUTTER_TEXT (text_editable_actor), !active); - - return TRUE; -} - -static gboolean -print_cursor_position_press_cb (ClutterActor *actor, - ClutterButtonEvent *event, - gpointer data) -{ - gint pos = 0; - - pos = clutter_text_get_cursor_position (CLUTTER_TEXT (text_editable_actor)); - - g_print ("current cursor position %i\n", pos); - - return TRUE; -} - -static void -activate_cb (ClutterActor *actor, - gpointer data) -{ - g_print ("Actor activated\n"); -} - -static ClutterActor* -_create_button (const gchar *text) -{ - ClutterActor *button = NULL; - ClutterActor *rectangle = NULL; - ClutterActor *label = NULL; - - button = clutter_actor_new (); - rectangle = clutter_actor_new (); - clutter_actor_set_background_color (rectangle, CLUTTER_COLOR_Magenta); - clutter_actor_set_size (rectangle, 375, 35); - - label = clutter_text_new_full ("Sans Bold 32px", - text, - CLUTTER_COLOR_Black); - clutter_container_add_actor (CLUTTER_CONTAINER (button), rectangle); - clutter_container_add_actor (CLUTTER_CONTAINER (button), label); - clutter_actor_set_reactive (button, TRUE); - - return button; -} - -static void -make_ui (ClutterActor *stage) -{ - ClutterActor *button = NULL; - - clutter_stage_set_title (CLUTTER_STAGE (stage), "Cally - AtkEditable Test"); - clutter_actor_set_background_color (CLUTTER_ACTOR (stage), CLUTTER_COLOR_White); - clutter_actor_set_size (stage, WIDTH, HEIGHT); - - /* text */ - text_actor = clutter_text_new_full ("Sans Bold 32px", - "Lorem ipsum dolor sit amet", - CLUTTER_COLOR_Red); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), text_actor); - - /* text_editable */ - text_editable_actor = clutter_text_new_full ("Sans Bold 32px", - "consectetur adipisicing elit", - CLUTTER_COLOR_Red); - clutter_actor_set_position (text_editable_actor, 0, 100); - clutter_text_set_editable (CLUTTER_TEXT (text_editable_actor), TRUE); - clutter_text_set_selectable (CLUTTER_TEXT (text_editable_actor), TRUE); - clutter_text_set_selection_color (CLUTTER_TEXT (text_editable_actor), - CLUTTER_COLOR_Green); - clutter_text_set_activatable (CLUTTER_TEXT (text_editable_actor), - TRUE); - clutter_text_set_line_wrap (CLUTTER_TEXT (text_editable_actor), TRUE); - clutter_actor_grab_key_focus (text_editable_actor); - clutter_actor_set_reactive (text_editable_actor, TRUE); - - clutter_container_add_actor (CLUTTER_CONTAINER (stage), text_editable_actor); - g_signal_connect (text_editable_actor, "activate", - G_CALLBACK (activate_cb), NULL); - - /* test buttons */ - button = _create_button ("Set"); - clutter_actor_set_position (button, 100, 200); - - g_signal_connect_after (button, "button-press-event", - G_CALLBACK (set_text_press_cb), NULL); - - clutter_container_add_actor (CLUTTER_CONTAINER (stage), button); - - button = _create_button ("Delete"); - clutter_actor_set_position (button, 100, 250); - - g_signal_connect_after (button, "button-press-event", - G_CALLBACK (delete_text_press_cb), NULL); - - clutter_container_add_actor (CLUTTER_CONTAINER (stage), button); - - button = _create_button ("Insert"); - clutter_actor_set_position (button, 100, 300); - - g_signal_connect_after (button, "button-press-event", - G_CALLBACK (insert_text_press_cb), NULL); - - clutter_container_add_actor (CLUTTER_CONTAINER (stage), button); - - button = _create_button ("Activate/Deactivate"); - clutter_actor_set_position (button, 100, 350); - - g_signal_connect_after (button, "button-press-event", - G_CALLBACK (activate_deactivate_press_cb), NULL); - - clutter_container_add_actor (CLUTTER_CONTAINER (stage), button); - - button = _create_button ("Cursor position"); - clutter_actor_set_position (button, 100, 450); - - g_signal_connect_after (button, "button-press-event", - G_CALLBACK (print_cursor_position_press_cb), NULL); - - clutter_container_add_actor (CLUTTER_CONTAINER (stage), button); - -} - -int -main (int argc, char *argv[]) -{ - ClutterActor *stage = NULL; - - g_set_application_name ("AtkEditableText"); - - cally_util_a11y_init (&argc, &argv); - - stage = clutter_test_get_stage (); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - - make_ui (stage); - - clutter_actor_show (stage); - - test_atk_text (text_actor); - test_atk_text (text_editable_actor); - - clutter_test_main (); - - return 0; -} diff --git a/src/tests/clutter/accessibility/cally-atkevents-example.c b/src/tests/clutter/accessibility/cally-atkevents-example.c deleted file mode 100644 index a94b7880a..000000000 --- a/src/tests/clutter/accessibility/cally-atkevents-example.c +++ /dev/null @@ -1,194 +0,0 @@ -/* CALLY - The Clutter Accessibility Implementation Library - * - * Copyright (C) 2009 Igalia, S.L. - * - * Author: Alejandro Piñeiro Iglesias - * - * 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, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* - * The purpose of this example is test key event and global event - * implementation, specifically: - * - * atk_add_global_event_listener - * atk_remove_global_event_listener - * atk_add_key_event_listener - * atk_remove_key_event_listener - */ -#include -#include -#include - -#include "cally-examples-util.h" - -#define WIDTH 800 -#define HEIGHT 600 -#define HEIGHT_STEP 100 -#define NUM_ENTRIES 3 - -struct _Data{ - gint value; -}; -typedef struct _Data Data; - -static gboolean -atk_key_listener (AtkKeyEventStruct *event, gpointer data) -{ - Data *my_data = (Data*) data; - - g_print ("atk_listener: 0x%x ", event->keyval); - - if (my_data != NULL) { - g_print ("\t Data value: %i\n", my_data->value); - } else { - g_print ("\tNo data!!\n"); - } - - return FALSE; -} - -static gboolean -window_event_listener (GSignalInvocationHint * signal_hint, - guint n_param_values, - const GValue * param_values, gpointer data) -{ - AtkObject *accessible; - GSignalQuery signal_query; - const gchar *name, *s; - - g_signal_query (signal_hint->signal_id, &signal_query); - name = signal_query.signal_name; - - accessible = ATK_OBJECT (g_value_get_object (¶m_values[0])); - s = atk_object_get_name (accessible); - - g_print ("Detected window event \"%s\" from object \"%p\" named \"%s\"\n", - name, accessible, s); - - return TRUE; -} -static void -make_ui (ClutterActor *stage) -{ - gint i = 0; - ClutterActor *editable = NULL; - ClutterActor *rectangle = NULL; - ClutterActor *label = NULL; - ClutterColor color_sel = { 0x00, 0xff, 0x00, 0x55 }; - ClutterColor color_label = { 0x00, 0xff, 0x55, 0xff }; - ClutterColor color_rect = { 0x00, 0xff, 0xff, 0x55 }; - float label_geom_y, editable_geom_y; - - clutter_actor_set_background_color (CLUTTER_ACTOR (stage), CLUTTER_COLOR_White); - clutter_actor_set_size (stage, WIDTH, HEIGHT); - - label_geom_y = 50; - editable_geom_y = 50; - - for (i = 0; i < NUM_ENTRIES; i++) - { - /* label */ - label = clutter_text_new_full ("Sans Bold 32px", - "Entry", - &color_label); - clutter_actor_set_position (label, 0, label_geom_y); - - /* editable */ - editable = clutter_text_new_full ("Sans Bold 32px", - "ddd", - CLUTTER_COLOR_Red); - clutter_actor_set_position (editable, 150, editable_geom_y); - clutter_actor_set_size (editable, 500, 75); - clutter_text_set_editable (CLUTTER_TEXT (editable), TRUE); - clutter_text_set_selectable (CLUTTER_TEXT (editable), TRUE); - clutter_text_set_selection_color (CLUTTER_TEXT (editable), - &color_sel); - clutter_actor_grab_key_focus (editable); - clutter_actor_set_reactive (editable, TRUE); - - /* rectangle: to create a entry "feeling" */ - rectangle = clutter_actor_new (); - clutter_actor_set_background_color (rectangle, &color_rect); - clutter_actor_set_position (rectangle, 150, editable_geom_y); - clutter_actor_set_size (rectangle, 500, 75); - - clutter_container_add_actor (CLUTTER_CONTAINER (stage), label); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), editable); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), rectangle); - - label_geom_y += HEIGHT_STEP; - editable_geom_y += HEIGHT_STEP; - } -} - -int -main (int argc, char *argv[]) -{ - ClutterActor *stage, *stage_main; - Data data1, data2, data3; - guint id_1 = 0, id_2 = 0, id_3 = 0; - - g_set_application_name ("AtkText"); - - if (cally_util_a11y_init (&argc, &argv) == FALSE) - { - g_error ("This example requires the accessibility support, " - "specifically AtkUtil implementation loaded, " - "as it tries to register and remove event listeners"); - } - - data1.value = 10; - data2.value = 20; - data3.value = 30; - - /* key event listeners */ - id_1 = atk_add_key_event_listener ((AtkKeySnoopFunc)atk_key_listener, &data1); - atk_remove_key_event_listener (id_1); - id_2 = atk_add_key_event_listener ((AtkKeySnoopFunc)atk_key_listener, &data2); - id_3 = atk_add_key_event_listener ((AtkKeySnoopFunc)atk_key_listener, &data3); - - atk_remove_key_event_listener (id_2); - - g_print ("key event listener ids registered: (%i, %i, %i)\n", id_1, id_2, id_3); - - /* event listeners */ - atk_add_global_event_listener (window_event_listener, "Atk:AtkWindow:create"); - atk_add_global_event_listener (window_event_listener, "Atk:AtkWindow:destroy"); - atk_add_global_event_listener (window_event_listener, "Atk:AtkWindow:activate"); - atk_add_global_event_listener (window_event_listener, "Atk:AtkWindow:deactivate"); - - stage_main = clutter_test_get_stage (); - clutter_stage_set_title (CLUTTER_STAGE (stage_main), "Cally - AtkEvents/1"); - g_signal_connect (stage_main, "destroy", G_CALLBACK (clutter_test_quit), NULL); - make_ui (stage_main); - - clutter_actor_show (stage_main); - - if (clutter_feature_available (CLUTTER_FEATURE_STAGE_MULTIPLE)) - { - stage = clutter_test_get_stage (); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Cally - AtkEvents/2"); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - - make_ui (stage); - clutter_actor_show (stage); - } - - clutter_test_main (); - - return 0; -} diff --git a/src/tests/clutter/accessibility/cally-atktext-example.c b/src/tests/clutter/accessibility/cally-atktext-example.c deleted file mode 100644 index 64a920da5..000000000 --- a/src/tests/clutter/accessibility/cally-atktext-example.c +++ /dev/null @@ -1,253 +0,0 @@ -/* CALLY - The Clutter Accessibility Implementation Library - * - * Copyright (C) 2009 Igalia, S.L. - * - * Author: Alejandro Piñeiro Iglesias - * - * 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, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include -#include - -#include "cally-examples-util.h" - -#define WIDTH 800 -#define HEIGHT 600 - -static ClutterActor *text_actor = NULL; -static ClutterActor *text_editable_actor = NULL; - -/* - * Test AtkText interface - */ -static void -test_atk_text (ClutterActor *actor) -{ - gchar *text = NULL; - AtkObject *object = NULL; - AtkText *cally_text = NULL; - gboolean boolean = FALSE; - gunichar unichar; - gint count = -1; - gint start = -1; - gint end = -1; - gint pos = -1; - AtkAttributeSet *at_set = NULL; - GSList *attrs; - gchar *buf; - gint x, y, width, height; - - object = atk_gobject_accessible_for_object (G_OBJECT (actor)); - cally_text = ATK_TEXT (object); - - if (!cally_text) - return; - - text = atk_text_get_text (cally_text, 0, -1); - g_print ("atk_text_get_text output: %s\n", text); - - unichar = atk_text_get_character_at_offset (cally_text, 5); - buf = g_ucs4_to_utf8 (&unichar, 1, NULL, NULL, NULL); - g_print ("atk_text_get_character_at_offset(5): '%s' vs '%c'\n", buf, text[5]); - g_free (text); text = NULL; - g_free (buf); buf = NULL; - - text = atk_text_get_string_at_offset (cally_text, - 5, - ATK_TEXT_GRANULARITY_WORD, - &start, &end); - g_print ("atk_text_get_string_at_offset: %s, %i, %i\n", - text, start, end); - g_free (text); text = NULL; - - pos = atk_text_get_caret_offset (cally_text); - g_print ("atk_text_get_caret_offset: %i\n", pos); - - atk_text_set_caret_offset (cally_text, 5); - - count = atk_text_get_character_count (cally_text); - g_print ("atk_text_get_character_count: %i\n", count); - - count = atk_text_get_n_selections (cally_text); - g_print ("atk_text_get_n_selections: %i\n", count); - - text = atk_text_get_selection (cally_text, 0, &start, &end); - g_print ("atk_text_get_selection: %s, %i, %i\n", text, start, end); - g_free(text); text = NULL; - - boolean = atk_text_remove_selection (cally_text, 0); - g_print ("atk_text_remove_selection (0): %i\n", boolean); - - boolean = atk_text_remove_selection (cally_text, 1); - g_print ("atk_text_remove_selection (1): %i\n", boolean); - - boolean = atk_text_add_selection (cally_text, 5, 10); - g_print ("atk_text_add_selection: %i\n", boolean); - - boolean = atk_text_set_selection (cally_text, 0, 6, 10); - g_print ("atk_text_set_selection: %i\n", boolean); - - at_set = atk_text_get_run_attributes (cally_text, 0, - &start, &end); - g_print ("atk_text_get_run_attributes: %i, %i\n", start, end); - attrs = (GSList*) at_set; - while (attrs) - { - AtkAttribute *at = (AtkAttribute *) attrs->data; - g_print ("text run %s = %s\n", at->name, at->value); - attrs = g_slist_next (attrs); - } - - atk_text_get_character_extents (cally_text, 0, &x, &y, &width, &height, - ATK_XY_WINDOW); - g_print ("atk_text_get_character_extents (0, window): x=%i y=%i width=%i height=%i\n", - x, y, width, height); - - atk_text_get_character_extents (cally_text, 0, &x, &y, &width, &height, - ATK_XY_SCREEN); - g_print ("atk_text_get_character_extents (0, screen): x=%i y=%i width=%i height=%i\n", - x, y, width, height); - - pos = atk_text_get_offset_at_point (cally_text, 200, 10, ATK_XY_WINDOW); - g_print ("atk_text_get_offset_at_point (200, 10, window): %i\n", pos); - - pos = atk_text_get_offset_at_point (cally_text, 200, 100, ATK_XY_SCREEN); - g_print ("atk_text_get_offset_at_point (200, 100, screen): %i\n", pos); - -} - -static void -dump_actor_default_atk_attributes (ClutterActor *actor) -{ - AtkObject *object = NULL; - AtkText *cally_text = NULL; - AtkAttributeSet *at_set = NULL; - GSList *attrs; - const gchar *text_value = NULL; - - object = atk_gobject_accessible_for_object (G_OBJECT (actor)); - cally_text = ATK_TEXT (object); - - if (!cally_text) - return; - - text_value = clutter_text_get_text (CLUTTER_TEXT (actor)); - g_print ("text value = %s\n", text_value); - - at_set = atk_text_get_default_attributes (cally_text); - attrs = (GSList*) at_set; - while (attrs) { - AtkAttribute *at = (AtkAttribute *) attrs->data; - g_print ("text default %s = %s\n", at->name, at->value); - attrs = g_slist_next (attrs); - } -} - -static gboolean -button_press_cb (ClutterActor *actor, - ClutterButtonEvent *event, - gpointer data) -{ - test_atk_text (text_actor); - test_atk_text (text_editable_actor); - - return TRUE; -} - -static void -make_ui (ClutterActor *stage) -{ - ClutterColor color_stage = { 0x00, 0x00, 0x00, 0xff }; - ClutterColor color_text = { 0xff, 0x00, 0x00, 0xff }; - ClutterColor color_sel = { 0x00, 0xff, 0x00, 0x55 }; - ClutterColor color_rect = { 0x00, 0xff, 0xff, 0xff }; - ClutterColor color_label = { 0x00, 0x00, 0x00, 0xff }; - ClutterActor *button = NULL; - ClutterActor *rectangle = NULL; - ClutterActor *label = NULL; - - clutter_actor_set_background_color (CLUTTER_ACTOR (stage), &color_stage); - clutter_actor_set_size (stage, WIDTH, HEIGHT); - - /* text */ - text_actor = clutter_text_new_full ("Sans Bold 32px", - "", - &color_text); - clutter_text_set_markup (CLUTTER_TEXT(text_actor), - "Lorem ipsum dolor sit amet"); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), text_actor); - dump_actor_default_atk_attributes (text_actor); - - /* text_editable */ - text_editable_actor = clutter_text_new_full ("Sans Bold 32px", - "consectetur adipisicing elit", - &color_text); - clutter_actor_set_position (text_editable_actor, 20, 100); - clutter_text_set_editable (CLUTTER_TEXT (text_editable_actor), TRUE); - clutter_text_set_selectable (CLUTTER_TEXT (text_editable_actor), TRUE); - clutter_text_set_selection_color (CLUTTER_TEXT (text_editable_actor), - &color_sel); - clutter_text_set_line_wrap (CLUTTER_TEXT (text_editable_actor), TRUE); - clutter_actor_grab_key_focus (text_editable_actor); - clutter_actor_set_reactive (text_editable_actor, TRUE); - dump_actor_default_atk_attributes (text_editable_actor); - - clutter_container_add_actor (CLUTTER_CONTAINER (stage), text_editable_actor); - - /* test button */ - button = clutter_actor_new (); - rectangle = clutter_actor_new (); - clutter_actor_set_background_color (rectangle, &color_rect); - clutter_actor_set_size (rectangle, 75, 35); - - label = clutter_text_new_full ("Sans Bold 32px", - "Test", &color_label); - clutter_actor_set_position (button, 100, 200); - clutter_container_add_actor (CLUTTER_CONTAINER (button), rectangle); - clutter_container_add_actor (CLUTTER_CONTAINER (button), label); - clutter_actor_set_reactive (button, TRUE); - - g_signal_connect_after (button, "button-press-event", - G_CALLBACK (button_press_cb), NULL); - - clutter_container_add_actor (CLUTTER_CONTAINER (stage), button); -} - -int -main (int argc, char *argv[]) -{ - ClutterActor *stage; - - g_set_application_name ("AtkText"); - - cally_util_a11y_init (&argc, &argv); - - stage = clutter_test_get_stage (); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Cally - AtkText Test"); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - - make_ui (stage); - - clutter_actor_show (stage); - - test_atk_text (text_actor); - test_atk_text (text_editable_actor); - - clutter_test_main (); - - return 0; -} diff --git a/src/tests/clutter/accessibility/cally-clone-example.c b/src/tests/clutter/accessibility/cally-clone-example.c deleted file mode 100644 index 0078a9855..000000000 --- a/src/tests/clutter/accessibility/cally-clone-example.c +++ /dev/null @@ -1,112 +0,0 @@ -/* CALLY - The Clutter Accessibility Implementation Library - * - * Copyright (C) 2009 Igalia, S.L. - * - * Author: Alejandro Piñeiro Iglesias - * - * 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, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include -#include - -#include "cally-examples-util.h" - -#define WIDTH 800 -#define HEIGHT 600 -#define HEIGHT_STEP 100 -#define NUM_ENTRIES 3 - -static void -make_ui (ClutterActor *stage) -{ - ClutterActor *editable = NULL; - ClutterActor *rectangle = NULL; - ClutterActor *label = NULL; - ClutterColor color_stage = { 0x00, 0x00, 0x00, 0xff }; - ClutterColor color_text = { 0xff, 0x00, 0x00, 0xff }; - ClutterColor color_sel = { 0x00, 0xff, 0x00, 0x55 }; - ClutterColor color_label = { 0x00, 0xff, 0x55, 0xff }; - ClutterColor color_rect = { 0x00, 0xff, 0xff, 0x55 }; - ClutterActor *full_entry = NULL; - ClutterActor *cloned_entry = NULL; - - - clutter_actor_set_background_color (CLUTTER_ACTOR (stage), &color_stage); - clutter_actor_set_size (stage, WIDTH, HEIGHT); - - label = clutter_text_new_full ("Sans Bold 32px", - "Entry", - &color_label); - clutter_actor_set_position (label, 0, 50); - - /* editable */ - editable = clutter_text_new_full ("Sans Bold 32px", - "ddd", - &color_text); - clutter_actor_set_position (editable, 150, 50); - clutter_text_set_editable (CLUTTER_TEXT (editable), TRUE); - clutter_text_set_selectable (CLUTTER_TEXT (editable), TRUE); - clutter_text_set_selection_color (CLUTTER_TEXT (editable), - &color_sel); - clutter_actor_grab_key_focus (editable); - clutter_actor_set_reactive (editable, TRUE); - - /* rectangle: to create a entry "feeling" */ - rectangle = clutter_actor_new (); - clutter_actor_set_background_color (rectangle, &color_rect); - clutter_actor_set_position (rectangle, 150, 50); - clutter_actor_add_constraint (rectangle, clutter_bind_constraint_new (editable, CLUTTER_BIND_SIZE, 0)); - - full_entry = clutter_actor_new (); - clutter_actor_set_position (full_entry, 0, 50); - clutter_actor_set_size (full_entry, 100, 75); - clutter_container_add_actor (CLUTTER_CONTAINER (full_entry), label); - clutter_container_add_actor (CLUTTER_CONTAINER (full_entry), editable); - clutter_container_add_actor (CLUTTER_CONTAINER (full_entry), rectangle); - clutter_actor_set_scale (full_entry, 2, 1); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), full_entry); - - /* Cloning! */ - cloned_entry = clutter_clone_new (full_entry); - clutter_actor_set_position (cloned_entry, 50, 200); - clutter_actor_set_scale (cloned_entry, 1, 2); - clutter_actor_set_reactive (cloned_entry, TRUE); - - clutter_container_add_actor (CLUTTER_CONTAINER (stage), cloned_entry); -} - -int -main (int argc, char *argv[]) -{ - ClutterActor *stage; - - g_set_application_name ("Clone Example"); - - cally_util_a11y_init (&argc, &argv); - - stage = clutter_test_get_stage (); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Cally - Clone Test"); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - - make_ui (stage); - - clutter_actor_show (stage); - - clutter_test_main (); - - return 0; -} diff --git a/src/tests/clutter/accessibility/cally-examples-util.c b/src/tests/clutter/accessibility/cally-examples-util.c deleted file mode 100644 index cf8dd8742..000000000 --- a/src/tests/clutter/accessibility/cally-examples-util.c +++ /dev/null @@ -1,148 +0,0 @@ -/* CALLY - The Clutter Accessibility Implementation Library - * - * Copyright (C) 2009 Igalia, S.L. - * - * Author: Alejandro Piñeiro Iglesias - * - * 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, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#include -#include - -#include - -#include "cally-examples-util.h" - -/* Checking the at-spi sources, the module directory is - * $(libdir)/gtk-2.0/modules - * - * It is supposed cally would be installed on the same libdir. - * - * You could use the option atk-bridge-dir to use other directory. - */ -#define ATK_BRIDGE_DEFAULT_MODULE_DIRECTORY PREFIXDIR"/gtk-2.0/modules" - -static gchar * -_search_for_bridge_module (const gchar *module_name) -{ - /* We simplify the search for the atk bridge, see see the definition - * of the macro for more information*/ - return g_strdup (ATK_BRIDGE_DEFAULT_MODULE_DIRECTORY); -} - -static gchar* -_a11y_check_custom_bridge (int *argc, - char ***argv) -{ - GError *error = NULL; - GOptionContext *context; - static gchar *bridge_dir = NULL; - static GOptionEntry entries [] = - { - {"atk-bridge-dir", 'd', 0, G_OPTION_ARG_STRING, &bridge_dir, "atk-bridge module directory", NULL} - }; - - context = g_option_context_new ("- cally examples"); - g_option_context_add_main_entries (context, entries, NULL); - if (!g_option_context_parse (context, argc, argv, &error)) - { - g_print ("%s\n", error->message); - g_print ("Use --help for more information.\n"); - exit (0); - } - - return bridge_dir; -} - - -static gboolean -_a11y_invoke_module (const gchar *module_path, - gboolean init) -{ - GModule *handle; - void (*invoke_fn) (void); - const char *method; - - if (init) - method = "gnome_accessibility_module_init"; - else - method = "gnome_accessibility_module_shutdown"; - - if (!module_path) - return FALSE; - - if (!(handle = g_module_open (module_path, G_MODULE_BIND_LAZY))) - { - g_warning ("Accessibility: failed to load module '%s': '%s'", - module_path, g_module_error ()); - - return FALSE; - } - - if (!g_module_symbol (handle, method, (gpointer *)&invoke_fn)) - { - g_warning ("Accessibility: error library '%s' does not include " - "method '%s' required for accessibility support", - module_path, method); - g_module_close (handle); - - return FALSE; - } - - g_debug ("Module %s loaded successfully", module_path); - invoke_fn (); - - return TRUE; -} - -/** - * This method will initialize the accessibility support provided by cally. - * - * Basically it will load the cally module using gmodule functions. - * - * Returns if it was able to init the a11y support or not. - */ -gboolean -cally_util_a11y_init (int *argc, char ***argv) -{ - gchar *bridge_dir = NULL; - gchar *bridge_path = NULL; - gboolean result = FALSE; - - clutter_test_init (argc, argv); - - if (clutter_get_accessibility_enabled () == FALSE) - { - g_warning ("Accessibility: clutter has no accessibility enabled" - " skipping the atk-bridge load"); - return FALSE; - } - - bridge_dir = _a11y_check_custom_bridge (argc, argv); - if (bridge_dir == NULL) - bridge_dir = _search_for_bridge_module ("atk-bridge"); - - bridge_path = g_module_build_path (bridge_dir, "libatk-bridge"); - - result = _a11y_invoke_module (bridge_path, TRUE); - - g_free (bridge_dir); - g_free (bridge_path); - - return result; -} diff --git a/src/tests/clutter/accessibility/cally-examples-util.h b/src/tests/clutter/accessibility/cally-examples-util.h deleted file mode 100644 index ea7d2c0b2..000000000 --- a/src/tests/clutter/accessibility/cally-examples-util.h +++ /dev/null @@ -1,26 +0,0 @@ -/* CALLY - The Clutter Accessibility Implementation Library - * - * Copyright (C) 2009 Igalia, S.L. - * - * Author: Alejandro Piñeiro Iglesias - * - * 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, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "tests/clutter-test-utils.h" - -gboolean -cally_util_a11y_init (int *argc, char ***argv); diff --git a/src/tests/clutter/accessibility/meson.build b/src/tests/clutter/accessibility/meson.build deleted file mode 100644 index ce6361b59..000000000 --- a/src/tests/clutter/accessibility/meson.build +++ /dev/null @@ -1,39 +0,0 @@ -clutter_test_accessibility_common_sources = [ - 'cally-examples-util.c', - 'cally-examples-util.h', -] - -clutter_test_accessibility_c_args = [ - '-DPREFIXDIR="@0@"'.format(libdir), - '-DCLUTTER_DISABLE_DEPRECATION_WARNINGS', - '-DGLIB_DISABLE_DEPRECATION_WARNINGS', - '-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name()), -] - -clutter_test_accessibility_c_args += clutter_debug_c_args - -clutter_accessibility_tests_dependencies = [ - libmutter_test_dep, -] - -clutter_accessibility_tests = [ - 'cally-atkcomponent-example', - 'cally-atktext-example', - 'cally-atkevents-example', - 'cally-atkeditabletext-example', - 'cally-clone-example', -] - -foreach test : clutter_accessibility_tests - executable(test, - sources: [ - clutter_test_accessibility_common_sources, - test + '.c', - clutter_test_utils, - ], - include_directories: clutter_includes, - c_args: clutter_test_accessibility_c_args, - dependencies: [clutter_accessibility_tests_dependencies], - install: false, - ) -endforeach diff --git a/src/tests/clutter/clutter-1.0.suppressions b/src/tests/clutter/clutter-1.0.suppressions deleted file mode 100644 index b7f82ab30..000000000 --- a/src/tests/clutter/clutter-1.0.suppressions +++ /dev/null @@ -1,165 +0,0 @@ -{ - ioctl_1 - Memcheck:Param - ioctl(generic) - fun:ioctl - fun:driDrawableInitVBlank - fun:intelMakeCurrent - fun:glXMakeContextCurrent -} - -{ - ioctl_2 - Memcheck:Param - ioctl(generic) - fun:ioctl - fun:driDrawableGetMSC32 - fun:clutter_backend_glx_redraw -} - -{ - ioctl_3 - Memcheck:Param - ioctl(generic) - fun:ioctl - fun:driWaitForMSC32 - fun:clutter_backend_glx_redraw -} - -{ - mesa_init_context - Memcheck:Leak - fun:*alloc - ... - fun:glXCreateNewContext -} - -{ - type_register - Memcheck:Leak - fun:*alloc - ... - fun:g_type_register_* -} - -{ - type_ref - Memcheck:Leak - fun:*alloc - ... - fun:g_type_class_ref -} - -{ - type_interface_prereq - Memcheck:Leak - fun:*alloc - ... - fun:g_type_interface_add_prerequisite -} - -{ - get_charset - Memcheck:Leak - fun:*alloc - ... - fun:g_get_charset -} - -{ - glx_query_version - Memcheck:Leak - fun:*alloc - ... - fun:glXQueryVersion -} - -{ - glx_create_context - Memcheck:Leak - fun:*alloc - ... - fun:glXCreateNewContext -} - -{ - glx_make_current - Memcheck:Leak - fun:*alloc - ... - fun:glXMakeContextCurrent -} - -{ - gl_draw_arrays - Memcheck:Leak - fun:*malloc - ... - fun:glDrawArrays -} - -{ - cogl_clear - Memcheck:Leak - fun:*alloc - ... - fun:cogl_clear -} - -{ - default_font - Memcheck:Leak - fun:*alloc - ... - fun:clutter_backend_get_font_name -} - -{ - id_pool - Memcheck:Leak - fun:*alloc - ... - fun:clutter_id_pool_new -} - -{ - x_open_display - Memcheck:Leak - fun:*alloc - ... - fun:XOpenDisplay -} - -# ... and font descriptions from every "sans 12" type string -{ - pango_font_description_from_string - Memcheck:Leak - fun:*alloc - ... - fun:pango_font_description_from_string -} - -# other lib init -{ - fontconfig_init - Memcheck:Leak - fun:*alloc - ... - fun:FcConfigParseAndLoad -} - -{ - freetype_init - Memcheck:Leak - fun:*alloc - ... - fun:FT_Open_Face -} - -{ - x_init_ext - Memcheck:Leak - fun:*alloc - ... - fun:XInitExtension -} diff --git a/src/tests/clutter/conform/actor-clone.c b/src/tests/clutter/conform/actor-clone.c deleted file mode 100644 index 582ddbbf3..000000000 --- a/src/tests/clutter/conform/actor-clone.c +++ /dev/null @@ -1,68 +0,0 @@ -#include -#include - -#include - -#include "tests/clutter-test-utils.h" - -static void -on_presented (ClutterStage *stage, - ClutterStageView *view, - ClutterFrameInfo *frame_info, - gboolean *was_presented) -{ - *was_presented = TRUE; -} - -static void -actor_clone_unmapped (void) -{ - ClutterActor *container; - ClutterActor *actor; - ClutterActor *clone; - ClutterActor *stage; - gboolean was_presented; - - stage = clutter_test_get_stage (); - - container = clutter_actor_new (); - g_object_ref_sink (container); - g_object_add_weak_pointer (G_OBJECT (container), (gpointer *) &container); - - actor = clutter_actor_new (); - g_object_ref_sink (actor); - g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor); - - clone = clutter_clone_new (actor); - g_object_ref_sink (clone); - g_object_add_weak_pointer (G_OBJECT (clone), (gpointer *) &clone); - - clutter_actor_hide (container); - clutter_actor_hide (actor); - - clutter_actor_add_child (stage, container); - clutter_actor_add_child (container, actor); - clutter_actor_add_child (stage, clone); - - clutter_actor_set_offscreen_redirect (actor, CLUTTER_OFFSCREEN_REDIRECT_ALWAYS); - - g_signal_connect (stage, "presented", G_CALLBACK (on_presented), - &was_presented); - - clutter_actor_show (stage); - - was_presented = FALSE; - while (!was_presented) - g_main_context_iteration (NULL, FALSE); - - clutter_actor_destroy (clone); - clutter_actor_destroy (actor); - clutter_actor_destroy (container); - g_assert_null (clone); - g_assert_null (actor); - g_assert_null (container); -} - -CLUTTER_TEST_SUITE ( - CLUTTER_TEST_UNIT ("/actor/clone/unmapped", actor_clone_unmapped) -) diff --git a/src/tests/clutter/conform/actor-destroy.c b/src/tests/clutter/conform/actor-destroy.c deleted file mode 100644 index eebcacc47..000000000 --- a/src/tests/clutter/conform/actor-destroy.c +++ /dev/null @@ -1,200 +0,0 @@ -#define CLUTTER_DISABLE_DEPRECATION_WARNINGS -#include - -#include "tests/clutter-test-utils.h" - -#define TEST_TYPE_DESTROY (test_destroy_get_type ()) -#define TEST_DESTROY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_DESTROY, TestDestroy)) -#define TEST_IS_DESTROY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_DESTROY)) - -typedef struct _TestDestroy TestDestroy; -typedef struct _TestDestroyClass TestDestroyClass; - -struct _TestDestroy -{ - ClutterActor parent_instance; - - ClutterActor *bg; - ClutterActor *label; - - GList *children; -}; - -struct _TestDestroyClass -{ - ClutterActorClass parent_class; -}; - -static void clutter_container_init (ClutterContainerIface *iface); - -GType test_destroy_get_type (void); - -G_DEFINE_TYPE_WITH_CODE (TestDestroy, test_destroy, CLUTTER_TYPE_ACTOR, - G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER, - clutter_container_init)); - -static void -test_destroy_add (ClutterContainer *container, - ClutterActor *actor) -{ - TestDestroy *self = TEST_DESTROY (container); - - if (!g_test_quiet ()) - g_print ("Adding '%s' (type:%s)\n", - clutter_actor_get_name (actor), - G_OBJECT_TYPE_NAME (actor)); - - self->children = g_list_prepend (self->children, actor); - clutter_actor_add_child (CLUTTER_ACTOR (container), actor); -} - -static void -test_destroy_remove (ClutterContainer *container, - ClutterActor *actor) -{ - TestDestroy *self = TEST_DESTROY (container); - - if (!g_test_quiet ()) - g_print ("Removing '%s' (type:%s)\n", - clutter_actor_get_name (actor), - G_OBJECT_TYPE_NAME (actor)); - - g_assert_true (g_list_find (self->children, actor)); - self->children = g_list_remove (self->children, actor); - - clutter_actor_remove_child (CLUTTER_ACTOR (container), actor); -} - -static void -clutter_container_init (ClutterContainerIface *iface) -{ - iface->add = test_destroy_add; - iface->remove = test_destroy_remove; -} - -static void -test_destroy_destroy (ClutterActor *self) -{ - TestDestroy *test = TEST_DESTROY (self); - - g_assert_cmpuint (g_list_length (test->children), ==, 3); - - if (test->bg != NULL) - { - if (!g_test_quiet ()) - g_print ("Destroying '%s' (type:%s)\n", - clutter_actor_get_name (test->bg), - G_OBJECT_TYPE_NAME (test->bg)); - - clutter_actor_destroy (test->bg); - test->bg = NULL; - } - - if (test->label != NULL) - { - if (!g_test_quiet ()) - g_print ("Destroying '%s' (type:%s)\n", - clutter_actor_get_name (test->label), - G_OBJECT_TYPE_NAME (test->label)); - - clutter_actor_destroy (test->label); - test->label = NULL; - } - - g_assert_cmpuint (g_list_length (test->children), ==, 1); - - if (CLUTTER_ACTOR_CLASS (test_destroy_parent_class)->destroy) - CLUTTER_ACTOR_CLASS (test_destroy_parent_class)->destroy (self); - - g_assert_null (test->children); -} - -static void -test_destroy_class_init (TestDestroyClass *klass) -{ - ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); - - actor_class->destroy = test_destroy_destroy; -} - -static void -test_destroy_init (TestDestroy *self) -{ - self->bg = clutter_actor_new (); - clutter_container_add_actor (CLUTTER_CONTAINER (self), self->bg); - clutter_actor_set_name (self->bg, "Background"); - - self->label = clutter_text_new (); - clutter_container_add_actor (CLUTTER_CONTAINER (self), self->label); - clutter_actor_set_name (self->label, "Label"); -} - -static void -on_destroy (ClutterActor *actor, - gpointer data) -{ - gboolean *destroy_called = data; - - g_assert_true (CLUTTER_IS_ACTOR (clutter_actor_get_parent (actor))); - - *destroy_called = TRUE; -} - -static void -on_parent_set (ClutterActor *actor, - ClutterActor *old_parent, - gpointer data) -{ - gboolean *parent_set_called = data; - - *parent_set_called = TRUE; -} - -static void -on_notify (ClutterActor *actor, - ClutterActor *old_parent, - gpointer data) -{ - gboolean *property_changed = data; - - *property_changed = TRUE; -} - -static void -actor_destruction (void) -{ - ClutterActor *test = g_object_new (TEST_TYPE_DESTROY, NULL); - ClutterActor *child = clutter_actor_new (); - gboolean destroy_called = FALSE; - gboolean parent_set_called = FALSE; - gboolean property_changed = FALSE; - - g_object_ref_sink (test); - - g_object_add_weak_pointer (G_OBJECT (test), (gpointer *) &test); - g_object_add_weak_pointer (G_OBJECT (child), (gpointer *) &child); - - if (!g_test_quiet ()) - g_print ("Adding external child...\n"); - - clutter_actor_set_name (child, "Child"); - clutter_container_add_actor (CLUTTER_CONTAINER (test), child); - g_signal_connect (child, "parent-set", G_CALLBACK (on_parent_set), - &parent_set_called); - g_signal_connect (child, "notify", G_CALLBACK (on_notify), &property_changed); - g_signal_connect (child, "destroy", G_CALLBACK (on_destroy), &destroy_called); - - if (!g_test_quiet ()) - g_print ("Calling destroy()...\n"); - - clutter_actor_destroy (test); - g_assert (destroy_called); - g_assert_false (parent_set_called); - g_assert_false (property_changed); - g_assert_null (child); - g_assert_null (test); -} - -CLUTTER_TEST_SUITE ( - CLUTTER_TEST_UNIT ("/actor/destruction", actor_destruction) -) diff --git a/src/tests/clutter/conform/actor-graph.c b/src/tests/clutter/conform/actor-graph.c deleted file mode 100644 index 06255ebe8..000000000 --- a/src/tests/clutter/conform/actor-graph.c +++ /dev/null @@ -1,552 +0,0 @@ -#include - -#include "tests/clutter-test-utils.h" - -static void -actor_add_child (void) -{ - ClutterActor *actor = clutter_actor_new (); - ClutterActor *iter; - - g_object_ref_sink (actor); - g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor); - - clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, - "name", "foo", - NULL)); - clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, - "name", "bar", - NULL)); - clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, - "name", "baz", - NULL)); - - g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 3); - - iter = clutter_actor_get_first_child (actor); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo"); - - iter = clutter_actor_get_next_sibling (iter); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar"); - - iter = clutter_actor_get_next_sibling (iter); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "baz"); - g_assert (iter == clutter_actor_get_last_child (actor)); - g_assert (clutter_actor_get_next_sibling (iter) == NULL); - - iter = clutter_actor_get_last_child (actor); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "baz"); - - iter = clutter_actor_get_previous_sibling (iter); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar"); - - iter = clutter_actor_get_previous_sibling (iter); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo"); - g_assert (iter == clutter_actor_get_first_child (actor)); - g_assert (clutter_actor_get_previous_sibling (iter) == NULL); - - clutter_actor_destroy (actor); - g_assert (actor == NULL); -} - -static void -actor_insert_child (void) -{ - ClutterActor *actor = clutter_actor_new (); - ClutterActor *iter; - - g_object_ref_sink (actor); - g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor); - - clutter_actor_insert_child_at_index (actor, - g_object_new (CLUTTER_TYPE_ACTOR, - "name", "foo", - NULL), - 0); - - iter = clutter_actor_get_first_child (actor); - g_assert (iter != NULL); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo"); - g_assert (iter == clutter_actor_get_child_at_index (actor, 0)); - - clutter_actor_insert_child_below (actor, - g_object_new (CLUTTER_TYPE_ACTOR, - "name", "bar", - NULL), - iter); - - g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 2); - - iter = clutter_actor_get_first_child (actor); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar"); - iter = clutter_actor_get_next_sibling (iter); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo"); - g_assert (iter == clutter_actor_get_child_at_index (actor, 1)); - - iter = clutter_actor_get_first_child (actor); - clutter_actor_insert_child_above (actor, - g_object_new (CLUTTER_TYPE_ACTOR, - "name", "baz", - NULL), - iter); - - iter = clutter_actor_get_last_child (actor); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo"); - - iter = clutter_actor_get_previous_sibling (iter); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "baz"); - - iter = clutter_actor_get_previous_sibling (iter); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar"); - - clutter_actor_remove_all_children (actor); - - clutter_actor_insert_child_at_index (actor, - g_object_new (CLUTTER_TYPE_ACTOR, - "name", "1", - NULL), - 0); - iter = clutter_actor_get_child_at_index (actor, 0); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "1"); - g_assert (clutter_actor_get_first_child (actor) == iter); - g_assert (clutter_actor_get_last_child (actor) == iter); - - clutter_actor_insert_child_at_index (actor, - g_object_new (CLUTTER_TYPE_ACTOR, - "name", "2", - NULL), - 0); - iter = clutter_actor_get_child_at_index (actor, 0); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "2"); - g_assert (clutter_actor_get_first_child (actor) == iter); - iter = clutter_actor_get_child_at_index (actor, 1); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "1"); - g_assert (clutter_actor_get_last_child (actor) == iter); - - clutter_actor_insert_child_at_index (actor, - g_object_new (CLUTTER_TYPE_ACTOR, - "name", "3", - NULL), - -1); - iter = clutter_actor_get_child_at_index (actor, 2); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "3"); - g_assert (clutter_actor_get_last_child (actor) == iter); - - clutter_actor_destroy (actor); - g_assert (actor == NULL); -} - -static void -actor_remove_child (void) -{ - ClutterActor *actor = clutter_actor_new (); - ClutterActor *iter; - - g_object_ref_sink (actor); - g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor); - - clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, - "name", "foo", - NULL)); - clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, - "name", "bar", - NULL)); - - g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 2); - - g_assert (clutter_actor_get_first_child (actor) != clutter_actor_get_last_child (actor)); - - iter = clutter_actor_get_first_child (actor); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo"); - - iter = clutter_actor_get_last_child (actor); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar"); - - clutter_actor_remove_child (actor, clutter_actor_get_first_child (actor)); - - g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 1); - - iter = clutter_actor_get_first_child (actor); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar"); - g_assert (clutter_actor_get_first_child (actor) == clutter_actor_get_last_child (actor)); - - clutter_actor_remove_child (actor, clutter_actor_get_first_child (actor)); - - g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 0); - g_assert (clutter_actor_get_first_child (actor) == NULL); - g_assert (clutter_actor_get_last_child (actor) == NULL); - - clutter_actor_destroy (actor); - g_assert (actor == NULL); -} - -static void -actor_raise_child (void) -{ - ClutterActor *actor = clutter_actor_new (); - ClutterActor *iter; - gboolean show_on_set_parent; - - g_object_ref_sink (actor); - g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor); - - clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, - "name", "foo", - "visible", FALSE, - NULL)); - clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, - "name", "bar", - "visible", FALSE, - NULL)); - clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, - "name", "baz", - "visible", FALSE, - NULL)); - - g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 3); - - iter = clutter_actor_get_child_at_index (actor, 1); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar"); - - clutter_actor_set_child_above_sibling (actor, iter, - clutter_actor_get_child_at_index (actor, 2)); - - g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 0)), - ==, - "foo"); - g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 1)), - ==, - "baz"); - g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 2)), - ==, - "bar"); - g_assert (!clutter_actor_is_visible (iter)); - g_object_get (iter, "show-on-set-parent", &show_on_set_parent, NULL); - g_assert (!show_on_set_parent); - - iter = clutter_actor_get_child_at_index (actor, 0); - clutter_actor_set_child_above_sibling (actor, iter, NULL); - g_object_add_weak_pointer (G_OBJECT (iter), (gpointer *) &iter); - - g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 0)), - ==, - "baz"); - g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 1)), - ==, - "bar"); - g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 2)), - ==, - "foo"); - g_assert (!clutter_actor_is_visible (iter)); - g_object_get (iter, "show-on-set-parent", &show_on_set_parent, NULL); - g_assert (!show_on_set_parent); - - clutter_actor_destroy (actor); - g_assert (actor == NULL); - g_assert (iter == NULL); -} - -static void -actor_lower_child (void) -{ - ClutterActor *actor = clutter_actor_new (); - ClutterActor *iter; - gboolean show_on_set_parent; - - g_object_ref_sink (actor); - g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor); - - clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, - "name", "foo", - "visible", FALSE, - NULL)); - clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, - "name", "bar", - "visible", FALSE, - NULL)); - clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, - "name", "baz", - "visible", FALSE, - NULL)); - - g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 3); - - iter = clutter_actor_get_child_at_index (actor, 1); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar"); - - clutter_actor_set_child_below_sibling (actor, iter, - clutter_actor_get_child_at_index (actor, 0)); - - g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 0)), - ==, - "bar"); - g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 1)), - ==, - "foo"); - g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 2)), - ==, - "baz"); - g_assert (!clutter_actor_is_visible (iter)); - g_object_get (iter, "show-on-set-parent", &show_on_set_parent, NULL); - g_assert (!show_on_set_parent); - - iter = clutter_actor_get_child_at_index (actor, 2); - clutter_actor_set_child_below_sibling (actor, iter, NULL); - - g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 0)), - ==, - "baz"); - g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 1)), - ==, - "bar"); - g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 2)), - ==, - "foo"); - g_assert (!clutter_actor_is_visible (iter)); - g_object_get (iter, "show-on-set-parent", &show_on_set_parent, NULL); - g_assert (!show_on_set_parent); - - clutter_actor_destroy (actor); - g_assert (actor == NULL); -} - -static void -actor_replace_child (void) -{ - ClutterActor *actor = clutter_actor_new (); - ClutterActor *iter; - - g_object_ref_sink (actor); - g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor); - - clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, - "name", "foo", - NULL)); - clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, - "name", "bar", - NULL)); - - iter = clutter_actor_get_child_at_index (actor, 0); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo"); - - clutter_actor_replace_child (actor, iter, - g_object_new (CLUTTER_TYPE_ACTOR, - "name", "baz", - NULL)); - - iter = clutter_actor_get_child_at_index (actor, 0); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "baz"); - - iter = clutter_actor_get_child_at_index (actor, 1); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar"); - - clutter_actor_replace_child (actor, iter, - g_object_new (CLUTTER_TYPE_ACTOR, - "name", "qux", - NULL)); - - iter = clutter_actor_get_child_at_index (actor, 0); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "baz"); - - iter = clutter_actor_get_child_at_index (actor, 1); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "qux"); - - clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, - "name", "foo", - NULL)); - - clutter_actor_replace_child (actor, iter, - g_object_new (CLUTTER_TYPE_ACTOR, - "name", "bar", - NULL)); - - iter = clutter_actor_get_last_child (actor); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo"); - iter = clutter_actor_get_previous_sibling (iter); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar"); - iter = clutter_actor_get_previous_sibling (iter); - g_assert_cmpstr (clutter_actor_get_name (iter), ==, "baz"); - - clutter_actor_destroy (actor); - g_assert (actor == NULL); -} - -static void -actor_remove_all (void) -{ - ClutterActor *actor = clutter_actor_new (); - - g_object_ref_sink (actor); - g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor); - - clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, - "name", "foo", - NULL)); - clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, - "name", "bar", - NULL)); - clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, - "name", "baz", - NULL)); - - g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 3); - - clutter_actor_remove_all_children (actor); - - g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 0); - - clutter_actor_destroy (actor); - g_assert (actor == NULL); -} - -static void -actor_added (ClutterContainer *container, - ClutterActor *child, - gpointer data) -{ - ClutterActor *actor = CLUTTER_ACTOR (container); - int *counter = data; - ClutterActor *old_child; - - if (!g_test_quiet ()) - g_print ("Adding actor '%s'\n", clutter_actor_get_name (child)); - - old_child = clutter_actor_get_child_at_index (actor, 0); - if (old_child != child) - clutter_actor_remove_child (actor, old_child); - - *counter += 1; -} - -static void -actor_removed (ClutterContainer *container, - ClutterActor *child, - gpointer data) -{ - int *counter = data; - - if (!g_test_quiet ()) - g_print ("Removing actor '%s'\n", clutter_actor_get_name (child)); - - *counter += 1; -} - -static void -actor_container_signals (void) -{ - ClutterActor *actor = clutter_actor_new (); - int add_count, remove_count; - - g_object_ref_sink (actor); - g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor); - - add_count = remove_count = 0; - g_signal_connect (actor, - "actor-added", G_CALLBACK (actor_added), - &add_count); - g_signal_connect (actor, - "actor-removed", G_CALLBACK (actor_removed), - &remove_count); - - clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, - "name", "foo", - NULL)); - - g_assert_cmpint (add_count, ==, 1); - g_assert_cmpint (remove_count, ==, 0); - g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 1); - - clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR, - "name", "bar", - NULL)); - - g_assert_cmpint (add_count, ==, 2); - g_assert_cmpint (remove_count, ==, 1); - g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 1); - - g_signal_handlers_disconnect_by_func (actor, G_CALLBACK (actor_added), - &add_count); - g_signal_handlers_disconnect_by_func (actor, G_CALLBACK (actor_removed), - &remove_count); - - clutter_actor_destroy (actor); - g_assert (actor == NULL); -} - -static void -actor_contains (void) -{ - /* This build up the following tree: - * - * a - * ╱ │ ╲ - * ╱ │ ╲ - * b c d - * ╱ ╲ ╱ ╲ ╱ ╲ - * e f g h i j - */ - struct { - ClutterActor *actor_a, *actor_b, *actor_c, *actor_d, *actor_e; - ClutterActor *actor_f, *actor_g, *actor_h, *actor_i, *actor_j; - } d; - int x, y; - ClutterActor **actor_array = &d.actor_a; - - /* Matrix of expected results */ - static const gboolean expected_results[] = - { /* a, b, c, d, e, f, g, h, i, j */ - /* a */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - /* b */ 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, - /* c */ 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, - /* d */ 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, - /* e */ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - /* f */ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - /* g */ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - /* h */ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - /* i */ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - /* j */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 - }; - - d.actor_a = clutter_actor_new (); - d.actor_b = clutter_actor_new (); - d.actor_c = clutter_actor_new (); - d.actor_d = clutter_actor_new (); - d.actor_e = clutter_actor_new (); - d.actor_f = clutter_actor_new (); - d.actor_g = clutter_actor_new (); - d.actor_h = clutter_actor_new (); - d.actor_i = clutter_actor_new (); - d.actor_j = clutter_actor_new (); - - clutter_actor_add_child (d.actor_a, d.actor_b); - clutter_actor_add_child (d.actor_a, d.actor_c); - clutter_actor_add_child (d.actor_a, d.actor_d); - - clutter_actor_add_child (d.actor_b, d.actor_e); - clutter_actor_add_child (d.actor_b, d.actor_f); - - clutter_actor_add_child (d.actor_c, d.actor_g); - clutter_actor_add_child (d.actor_c, d.actor_h); - - clutter_actor_add_child (d.actor_d, d.actor_i); - clutter_actor_add_child (d.actor_d, d.actor_j); - - for (y = 0; y < 10; y++) - for (x = 0; x < 10; x++) - g_assert_cmpint (clutter_actor_contains (actor_array[x], - actor_array[y]), - ==, - expected_results[x * 10 + y]); -} - -CLUTTER_TEST_SUITE ( - CLUTTER_TEST_UNIT ("/actor/graph/add-child", actor_add_child) - CLUTTER_TEST_UNIT ("/actor/graph/insert-child", actor_insert_child) - CLUTTER_TEST_UNIT ("/actor/graph/remove-child", actor_remove_child) - CLUTTER_TEST_UNIT ("/actor/graph/raise-child", actor_raise_child) - CLUTTER_TEST_UNIT ("/actor/graph/lower-child", actor_lower_child) - CLUTTER_TEST_UNIT ("/actor/graph/replace-child", actor_replace_child) - CLUTTER_TEST_UNIT ("/actor/graph/remove-all", actor_remove_all) - CLUTTER_TEST_UNIT ("/actor/graph/container-signals", actor_container_signals) - CLUTTER_TEST_UNIT ("/actor/graph/contains", actor_contains) -) diff --git a/src/tests/clutter/conform/actor-invariants.c b/src/tests/clutter/conform/actor-invariants.c deleted file mode 100644 index 652bdcfa7..000000000 --- a/src/tests/clutter/conform/actor-invariants.c +++ /dev/null @@ -1,368 +0,0 @@ -#include -#include - -#define CLUTTER_DISABLE_DEPRECATION_WARNINGS -#include - -#include "tests/clutter-test-utils.h" - -static void -actor_initial_state (void) -{ - ClutterActor *actor; - - actor = clutter_actor_new (); - g_object_ref_sink (actor); - g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor); - - if (!g_test_quiet ()) - g_print ("initial state - visible: %s, realized: %s, mapped: %s\n", - CLUTTER_ACTOR_IS_VISIBLE (actor) ? "yes" : "no", - CLUTTER_ACTOR_IS_REALIZED (actor) ? "yes" : "no", - CLUTTER_ACTOR_IS_MAPPED (actor) ? "yes" : "no"); - - g_assert (!(CLUTTER_ACTOR_IS_REALIZED (actor))); - g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor))); - g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (actor))); - - clutter_actor_destroy (actor); - g_assert (actor == NULL); -} - -static void -actor_shown_not_parented (void) -{ - ClutterActor *actor; - - actor = clutter_actor_new (); - g_object_ref_sink (actor); - g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor); - - clutter_actor_show (actor); - - if (!g_test_quiet ()) - g_print ("show without a parent - visible: %s, realized: %s, mapped: %s\n", - CLUTTER_ACTOR_IS_VISIBLE (actor) ? "yes" : "no", - CLUTTER_ACTOR_IS_REALIZED (actor) ? "yes" : "no", - CLUTTER_ACTOR_IS_MAPPED (actor) ? "yes" : "no"); - - g_assert (!CLUTTER_ACTOR_IS_REALIZED (actor)); - g_assert (!CLUTTER_ACTOR_IS_MAPPED (actor)); - g_assert (CLUTTER_ACTOR_IS_VISIBLE (actor)); - - clutter_actor_destroy (actor); - g_assert (actor == NULL); -} - -static void -actor_realized (void) -{ - ClutterActor *actor; - ClutterActor *stage; - - stage = clutter_test_get_stage (); - - actor = clutter_actor_new (); - - g_assert (!(CLUTTER_ACTOR_IS_REALIZED (actor))); - - clutter_actor_hide (actor); /* don't show, so won't map */ - clutter_actor_add_child (stage, actor); - clutter_actor_realize (actor); - - g_assert (CLUTTER_ACTOR_IS_REALIZED (actor)); - - g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor))); - g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (actor))); - - clutter_actor_destroy (actor); -} - -static void -actor_mapped (void) -{ - ClutterActor *actor; - ClutterActor *stage; - - stage = clutter_test_get_stage (); - clutter_actor_show (stage); - - actor = clutter_actor_new (); - - g_assert (!(CLUTTER_ACTOR_IS_REALIZED (actor))); - g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor))); - - clutter_actor_add_child (stage, actor); - - if (!g_test_quiet ()) - g_print ("adding to a container should map - " - "visible: %s, realized: %s, mapped: %s\n", - CLUTTER_ACTOR_IS_VISIBLE (actor) ? "yes" : "no", - CLUTTER_ACTOR_IS_REALIZED (actor) ? "yes" : "no", - CLUTTER_ACTOR_IS_MAPPED (actor) ? "yes" : "no"); - - g_assert (CLUTTER_ACTOR_IS_REALIZED (actor)); - g_assert (CLUTTER_ACTOR_IS_MAPPED (actor)); - g_assert (CLUTTER_ACTOR_IS_VISIBLE (actor)); - - clutter_actor_hide (actor); - - if (!g_test_quiet ()) - g_print ("hiding should unmap - " - "visible: %s, realized: %s, mapped: %s\n", - CLUTTER_ACTOR_IS_VISIBLE (actor) ? "yes" : "no", - CLUTTER_ACTOR_IS_REALIZED (actor) ? "yes" : "no", - CLUTTER_ACTOR_IS_MAPPED (actor) ? "yes" : "no"); - - g_assert (CLUTTER_ACTOR_IS_REALIZED (actor)); - g_assert (!CLUTTER_ACTOR_IS_MAPPED (actor)); - g_assert (!CLUTTER_ACTOR_IS_VISIBLE (actor)); - - clutter_actor_destroy (actor); -} - -static void -actor_visibility_not_recursive (void) -{ - ClutterActor *actor, *group; - ClutterActor *stage; - - stage = clutter_test_get_stage (); - - group = clutter_actor_new (); - actor = clutter_actor_new (); - - clutter_actor_hide (group); /* don't show, so won't map */ - clutter_actor_hide (actor); /* don't show, so won't map */ - - g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (stage))); - g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (group))); - g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (actor))); - - clutter_actor_add_child (stage, group); - clutter_actor_add_child (group, actor); - - clutter_actor_show (actor); - g_assert (CLUTTER_ACTOR_IS_VISIBLE (actor)); - g_assert (!CLUTTER_ACTOR_IS_VISIBLE (group)); - g_assert (!CLUTTER_ACTOR_IS_VISIBLE (stage)); - - clutter_actor_show (stage); - g_assert (CLUTTER_ACTOR_IS_VISIBLE (actor)); - g_assert (!CLUTTER_ACTOR_IS_VISIBLE (group)); - g_assert (CLUTTER_ACTOR_IS_VISIBLE (stage)); - - clutter_actor_hide (actor); - clutter_actor_hide (group); - clutter_actor_hide (stage); - g_assert (!CLUTTER_ACTOR_IS_VISIBLE (actor)); - - clutter_actor_show (stage); - g_assert (!CLUTTER_ACTOR_IS_VISIBLE (actor)); - - clutter_actor_destroy (actor); - clutter_actor_destroy (group); -} - -static void -actor_realize_not_recursive (void) -{ - ClutterActor *actor, *group; - ClutterActor *stage; - - stage = clutter_test_get_stage (); - clutter_actor_show (stage); - - group = clutter_actor_new (); - - actor = clutter_actor_new (); - - clutter_actor_hide (group); /* don't show, so won't map */ - clutter_actor_hide (actor); /* don't show, so won't map */ - - g_assert (!(CLUTTER_ACTOR_IS_REALIZED (group))); - g_assert (!(CLUTTER_ACTOR_IS_REALIZED (actor))); - - clutter_actor_add_child (stage, group); - clutter_actor_add_child (group, actor); - - clutter_actor_realize (group); - - g_assert (CLUTTER_ACTOR_IS_REALIZED (group)); - - g_assert (!(CLUTTER_ACTOR_IS_MAPPED (group))); - g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (group))); - - /* realizing group did not realize the child */ - g_assert (!CLUTTER_ACTOR_IS_REALIZED (actor)); - g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor))); - g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (actor))); - - clutter_actor_destroy (actor); - clutter_actor_destroy (group); -} - -static void -actor_map_recursive (void) -{ - ClutterActor *actor, *group; - ClutterActor *stage; - - stage = clutter_test_get_stage (); - clutter_actor_show (stage); - - group = clutter_actor_new (); - - actor = clutter_actor_new (); - - clutter_actor_hide (group); /* hide at first */ - clutter_actor_show (actor); /* show at first */ - - g_assert (!(CLUTTER_ACTOR_IS_REALIZED (group))); - g_assert (!(CLUTTER_ACTOR_IS_REALIZED (actor))); - g_assert (!(CLUTTER_ACTOR_IS_MAPPED (group))); - g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor))); - g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (group))); - g_assert ((CLUTTER_ACTOR_IS_VISIBLE (actor))); - - clutter_actor_add_child (stage, group); - clutter_actor_add_child (group, actor); - - g_assert (!(CLUTTER_ACTOR_IS_REALIZED (group))); - g_assert (!(CLUTTER_ACTOR_IS_REALIZED (actor))); - g_assert (!(CLUTTER_ACTOR_IS_MAPPED (group))); - g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor))); - g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (group))); - g_assert ((CLUTTER_ACTOR_IS_VISIBLE (actor))); - - /* show group, which should map and realize both - * group and child. - */ - clutter_actor_show (group); - g_assert (CLUTTER_ACTOR_IS_REALIZED (group)); - g_assert (CLUTTER_ACTOR_IS_REALIZED (actor)); - g_assert (CLUTTER_ACTOR_IS_MAPPED (group)); - g_assert (CLUTTER_ACTOR_IS_MAPPED (actor)); - g_assert (CLUTTER_ACTOR_IS_VISIBLE (group)); - g_assert (CLUTTER_ACTOR_IS_VISIBLE (actor)); - - clutter_actor_destroy (actor); - clutter_actor_destroy (group); -} - -static void -actor_show_on_set_parent (void) -{ - ClutterActor *actor, *group; - gboolean show_on_set_parent; - ClutterActor *stage; - - stage = clutter_test_get_stage (); - - group = clutter_actor_new (); - - g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (group))); - - clutter_actor_add_child (stage, group); - - actor = clutter_actor_new (); - g_object_get (actor, - "show-on-set-parent", &show_on_set_parent, - NULL); - - g_assert (!(CLUTTER_ACTOR_IS_VISIBLE (actor))); - g_assert (show_on_set_parent); - - clutter_actor_add_child (group, actor); - g_object_get (actor, - "show-on-set-parent", &show_on_set_parent, - NULL); - - g_assert (CLUTTER_ACTOR_IS_VISIBLE (actor)); - g_assert (show_on_set_parent); - - g_object_ref (actor); - clutter_actor_remove_child (group, actor); - g_object_get (actor, - "show-on-set-parent", &show_on_set_parent, - NULL); - - g_assert (!CLUTTER_ACTOR_IS_REALIZED (actor)); - g_assert (!CLUTTER_ACTOR_IS_MAPPED (actor)); - g_assert (CLUTTER_ACTOR_IS_VISIBLE (actor)); - g_assert (show_on_set_parent); - - clutter_actor_destroy (actor); - clutter_actor_destroy (group); - - actor = clutter_actor_new (); - clutter_actor_add_child (stage, actor); - clutter_actor_hide (actor); - g_object_get (actor, - "show-on-set-parent", &show_on_set_parent, - NULL); - g_assert (!CLUTTER_ACTOR_IS_VISIBLE (actor)); - g_assert (!CLUTTER_ACTOR_IS_MAPPED (actor)); - g_assert (show_on_set_parent); - - clutter_actor_destroy (actor); - - actor = clutter_actor_new (); - clutter_actor_hide (actor); - clutter_actor_add_child (stage, actor); - g_object_get (actor, - "show-on-set-parent", &show_on_set_parent, - NULL); - g_assert (!CLUTTER_ACTOR_IS_VISIBLE (actor)); - g_assert (!CLUTTER_ACTOR_IS_MAPPED (actor)); - g_assert (!show_on_set_parent); - - clutter_actor_destroy (actor); -} - -static void -clone_no_map (void) -{ - ClutterActor *stage; - ClutterActor *group; - ClutterActor *actor; - ClutterActor *clone; - - stage = clutter_test_get_stage (); - clutter_actor_show (stage); - - group = clutter_actor_new (); - actor = clutter_actor_new (); - - clutter_actor_hide (group); - - clutter_actor_add_child (group, actor); - clutter_actor_add_child (stage, group); - - g_assert (!(CLUTTER_ACTOR_IS_MAPPED (group))); - g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor))); - - clone = clutter_clone_new (group); - - clutter_actor_add_child (stage, clone); - - g_assert (CLUTTER_ACTOR_IS_MAPPED (clone)); - g_assert (!(CLUTTER_ACTOR_IS_MAPPED (group))); - g_assert (!(CLUTTER_ACTOR_IS_MAPPED (actor))); - - clutter_actor_destroy (actor); - clutter_actor_destroy (CLUTTER_ACTOR (clone)); - clutter_actor_destroy (CLUTTER_ACTOR (group)); -} - -CLUTTER_TEST_SUITE ( - CLUTTER_TEST_UNIT ("/actor/invariants/initial-state", actor_initial_state) - CLUTTER_TEST_UNIT ("/actor/invariants/show-not-parented", actor_shown_not_parented) - CLUTTER_TEST_UNIT ("/actor/invariants/realized", actor_realized) - CLUTTER_TEST_UNIT ("/actor/invariants/mapped", actor_mapped) - CLUTTER_TEST_UNIT ("/actor/invariants/visibility-not-recursive", actor_visibility_not_recursive) - CLUTTER_TEST_UNIT ("/actor/invariants/realize-not-recursive", actor_realize_not_recursive) - CLUTTER_TEST_UNIT ("/actor/invariants/map-recursive", actor_map_recursive) - CLUTTER_TEST_UNIT ("/actor/invariants/show-on-set-parent", actor_show_on_set_parent) - CLUTTER_TEST_UNIT ("/actor/invariants/clone-no-map", clone_no_map) -) diff --git a/src/tests/clutter/conform/actor-iter.c b/src/tests/clutter/conform/actor-iter.c deleted file mode 100644 index 06a7812d9..000000000 --- a/src/tests/clutter/conform/actor-iter.c +++ /dev/null @@ -1,220 +0,0 @@ -#include -#include - -#include "tests/clutter-test-utils.h" - -static void -actor_iter_traverse_children (void) -{ - ClutterActorIter iter; - ClutterActor *actor; - ClutterActor *child; - int i, n_actors; - - actor = clutter_actor_new (); - clutter_actor_set_name (actor, "root"); - g_object_ref_sink (actor); - - n_actors = g_random_int_range (10, 50); - for (i = 0; i < n_actors; i++) - { - char *name; - - name = g_strdup_printf ("actor%d", i); - child = clutter_actor_new (); - clutter_actor_set_name (child, name); - - clutter_actor_add_child (actor, child); - - g_free (name); - } - - g_assert_cmpint (clutter_actor_get_n_children (actor), ==, n_actors); - - i = 0; - clutter_actor_iter_init (&iter, actor); - g_assert (clutter_actor_iter_is_valid (&iter)); - - while (clutter_actor_iter_next (&iter, &child)) - { - g_assert (CLUTTER_IS_ACTOR (child)); - g_assert (clutter_actor_get_parent (child) == actor); - - if (!g_test_quiet ()) - g_print ("actor %d = '%s'\n", i, clutter_actor_get_name (child)); - - if (i == 0) - g_assert (child == clutter_actor_get_first_child (actor)); - - if (i == (n_actors - 1)) - g_assert (child == clutter_actor_get_last_child (actor)); - - i += 1; - } - - g_assert_cmpint (i, ==, n_actors); - - i = 0; - clutter_actor_iter_init (&iter, actor); - g_assert (clutter_actor_iter_is_valid (&iter)); - - while (clutter_actor_iter_prev (&iter, &child)) - { - g_assert (CLUTTER_IS_ACTOR (child)); - g_assert (clutter_actor_get_parent (child) == actor); - - if (!g_test_quiet ()) - g_print ("actor %d = '%s'\n", i, clutter_actor_get_name (child)); - - if (i == 0) - g_assert (child == clutter_actor_get_last_child (actor)); - - if (i == (n_actors - 1)) - g_assert (child == clutter_actor_get_first_child (actor)); - - i += 1; - } - - g_object_unref (actor); -} - -static void -actor_iter_traverse_remove (void) -{ - ClutterActorIter iter; - ClutterActor *actor; - ClutterActor *child; - int i, n_actors; - - actor = clutter_actor_new (); - clutter_actor_set_name (actor, "root"); - g_object_ref_sink (actor); - - n_actors = g_random_int_range (10, 50); - for (i = 0; i < n_actors; i++) - { - char *name; - - name = g_strdup_printf ("actor%d", i); - child = clutter_actor_new (); - clutter_actor_set_name (child, name); - - clutter_actor_add_child (actor, child); - - g_free (name); - } - - g_assert_cmpint (clutter_actor_get_n_children (actor), ==, n_actors); - - i = 0; - clutter_actor_iter_init (&iter, actor); - g_assert (clutter_actor_iter_is_valid (&iter)); - - while (clutter_actor_iter_next (&iter, &child)) - { - g_assert (CLUTTER_IS_ACTOR (child)); - g_assert (clutter_actor_get_parent (child) == actor); - - if (!g_test_quiet ()) - g_print ("actor %d = '%s'\n", i, clutter_actor_get_name (child)); - - if (i == 0) - g_assert (child == clutter_actor_get_first_child (actor)); - - if (i == (n_actors - 1)) - g_assert (child == clutter_actor_get_last_child (actor)); - - clutter_actor_iter_remove (&iter); - g_assert (clutter_actor_iter_is_valid (&iter)); - - i += 1; - } - - g_assert_cmpint (i, ==, n_actors); - g_assert_cmpint (0, ==, clutter_actor_get_n_children (actor)); -} - -static void -actor_iter_assignment (void) -{ - ClutterActorIter iter_a, iter_b; - ClutterActor *actor; - ClutterActor *child; - int i, n_actors; - - actor = clutter_actor_new (); - clutter_actor_set_name (actor, "root"); - g_object_ref_sink (actor); - - n_actors = g_random_int_range (10, 50); - for (i = 0; i < n_actors; i++) - { - char *name; - - name = g_strdup_printf ("actor[%02d]", i); - child = clutter_actor_new (); - clutter_actor_set_name (child, name); - - clutter_actor_add_child (actor, child); - - g_free (name); - } - - g_assert_cmpint (clutter_actor_get_n_children (actor), ==, n_actors); - - i = 0; - - clutter_actor_iter_init (&iter_a, actor); - - iter_b = iter_a; - - g_assert (clutter_actor_iter_is_valid (&iter_a)); - g_assert (clutter_actor_iter_is_valid (&iter_b)); - - while (clutter_actor_iter_next (&iter_a, &child)) - { - g_assert (CLUTTER_IS_ACTOR (child)); - g_assert (clutter_actor_get_parent (child) == actor); - - if (!g_test_quiet ()) - g_print ("actor %2d = '%s'\n", i, clutter_actor_get_name (child)); - - if (i == 0) - g_assert (child == clutter_actor_get_first_child (actor)); - - if (i == (n_actors - 1)) - g_assert (child == clutter_actor_get_last_child (actor)); - - i += 1; - } - - g_assert_cmpint (i, ==, n_actors); - - i = n_actors - 1; - - while (clutter_actor_iter_prev (&iter_b, &child)) - { - g_assert (clutter_actor_get_parent (child) == actor); - - if (!g_test_quiet ()) - g_print ("actor %2d = '%s'\n", i, clutter_actor_get_name (child)); - - if (i == n_actors - 1) - g_assert (child == clutter_actor_get_last_child (actor)); - - if (i == 0) - g_assert (child == clutter_actor_get_first_child (actor)); - - i -= 1; - } - - g_assert_cmpint (i, ==, -1); - - g_object_unref (actor); -} - -CLUTTER_TEST_SUITE ( - CLUTTER_TEST_UNIT ("/actor/iter/traverse-children", actor_iter_traverse_children) - CLUTTER_TEST_UNIT ("/actor/iter/traverse-remove", actor_iter_traverse_remove) - CLUTTER_TEST_UNIT ("/actor/iter/assignment", actor_iter_assignment) -) diff --git a/src/tests/clutter/conform/actor-layout.c b/src/tests/clutter/conform/actor-layout.c deleted file mode 100644 index 9af90f55a..000000000 --- a/src/tests/clutter/conform/actor-layout.c +++ /dev/null @@ -1,98 +0,0 @@ -#include - -#include "tests/clutter-test-utils.h" - -static void -actor_basic_layout (void) -{ - ClutterActor *stage = clutter_test_get_stage (); - ClutterActor *vase; - ClutterActor *flower[3]; - graphene_point_t p; - - vase = clutter_actor_new (); - clutter_actor_set_name (vase, "Vase"); - clutter_actor_set_layout_manager (vase, clutter_flow_layout_new (CLUTTER_FLOW_HORIZONTAL)); - clutter_actor_add_child (stage, vase); - - flower[0] = clutter_actor_new (); - clutter_actor_set_background_color (flower[0], CLUTTER_COLOR_Red); - clutter_actor_set_size (flower[0], 100, 100); - clutter_actor_set_name (flower[0], "Red Flower"); - clutter_actor_add_child (vase, flower[0]); - - flower[1] = clutter_actor_new (); - clutter_actor_set_background_color (flower[1], CLUTTER_COLOR_Yellow); - clutter_actor_set_size (flower[1], 100, 100); - clutter_actor_set_name (flower[1], "Yellow Flower"); - clutter_actor_add_child (vase, flower[1]); - - flower[2] = clutter_actor_new (); - clutter_actor_set_background_color (flower[2], CLUTTER_COLOR_Green); - clutter_actor_set_size (flower[2], 100, 100); - clutter_actor_set_name (flower[2], "Green Flower"); - clutter_actor_add_child (vase, flower[2]); - - graphene_point_init (&p, 50, 50); - clutter_test_assert_actor_at_point (stage, &p, flower[0]); - - graphene_point_init (&p, 150, 50); - clutter_test_assert_actor_at_point (stage, &p, flower[1]); - - graphene_point_init (&p, 250, 50); - clutter_test_assert_actor_at_point (stage, &p, flower[2]); - - clutter_actor_destroy (vase); -} - -static void -actor_margin_layout (void) -{ - ClutterActor *stage = clutter_test_get_stage (); - ClutterActor *vase; - ClutterActor *flower[3]; - graphene_point_t p; - - vase = clutter_actor_new (); - clutter_actor_set_name (vase, "Vase"); - clutter_actor_set_layout_manager (vase, clutter_box_layout_new ()); - clutter_actor_add_child (stage, vase); - - flower[0] = clutter_actor_new (); - clutter_actor_set_background_color (flower[0], CLUTTER_COLOR_Red); - clutter_actor_set_size (flower[0], 100, 100); - clutter_actor_set_name (flower[0], "Red Flower"); - clutter_actor_add_child (vase, flower[0]); - - flower[1] = clutter_actor_new (); - clutter_actor_set_background_color (flower[1], CLUTTER_COLOR_Yellow); - clutter_actor_set_size (flower[1], 100, 100); - clutter_actor_set_name (flower[1], "Yellow Flower"); - clutter_actor_set_margin_right (flower[1], 6); - clutter_actor_set_margin_left (flower[1], 6); - clutter_actor_add_child (vase, flower[1]); - - flower[2] = clutter_actor_new (); - clutter_actor_set_background_color (flower[2], CLUTTER_COLOR_Green); - clutter_actor_set_size (flower[2], 100, 100); - clutter_actor_set_name (flower[2], "Green Flower"); - clutter_actor_set_margin_top (flower[2], 6); - clutter_actor_set_margin_bottom (flower[2], 6); - clutter_actor_add_child (vase, flower[2]); - - graphene_point_init (&p, 0, 7); - clutter_test_assert_actor_at_point (stage, &p, flower[0]); - - graphene_point_init (&p, 106, 50); - clutter_test_assert_actor_at_point (stage, &p, flower[1]); - - graphene_point_init (&p, 212, 7); - clutter_test_assert_actor_at_point (stage, &p, flower[2]); - - clutter_actor_destroy (vase); -} - -CLUTTER_TEST_SUITE ( - CLUTTER_TEST_UNIT ("/actor/layout/basic", actor_basic_layout) - CLUTTER_TEST_UNIT ("/actor/layout/margin", actor_margin_layout) -) diff --git a/src/tests/clutter/conform/actor-meta.c b/src/tests/clutter/conform/actor-meta.c deleted file mode 100644 index 0211f99ae..000000000 --- a/src/tests/clutter/conform/actor-meta.c +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include - -#include - -#include "tests/clutter-test-utils.h" - -static void -actor_meta_clear (void) -{ - ClutterActor *actor, *stage; - - stage = clutter_test_get_stage (); - - actor = clutter_actor_new (); - g_object_ref_sink (actor); - g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor); - - clutter_actor_add_action (actor, clutter_click_action_new ()); - clutter_actor_add_constraint (actor, clutter_bind_constraint_new (stage, CLUTTER_BIND_ALL, 0)); - clutter_actor_add_effect (actor, clutter_blur_effect_new ()); - - g_assert (clutter_actor_has_actions (actor)); - g_assert (clutter_actor_has_constraints (actor)); - g_assert (clutter_actor_has_effects (actor)); - - clutter_actor_clear_actions (actor); - g_assert (!clutter_actor_has_actions (actor)); - - clutter_actor_clear_constraints (actor); - g_assert (!clutter_actor_has_constraints (actor)); - - clutter_actor_clear_effects (actor); - g_assert (!clutter_actor_has_effects (actor)); - - clutter_actor_destroy (actor); - g_assert (actor == NULL); -} - -CLUTTER_TEST_SUITE ( - CLUTTER_TEST_UNIT ("/actor/meta/clear", actor_meta_clear) -) diff --git a/src/tests/clutter/conform/actor-offscreen-redirect.c b/src/tests/clutter/conform/actor-offscreen-redirect.c deleted file mode 100644 index d7088beda..000000000 --- a/src/tests/clutter/conform/actor-offscreen-redirect.c +++ /dev/null @@ -1,452 +0,0 @@ -#define CLUTTER_DISABLE_DEPRECATION_WARNINGS -#include - -#include "tests/clutter-test-utils.h" - -typedef struct _FooActor FooActor; -typedef struct _FooActorClass FooActorClass; - -struct _FooActorClass -{ - ClutterActorClass parent_class; -}; - -struct _FooActor -{ - ClutterActor parent; - - guint8 last_paint_opacity; - int paint_count; -}; - -typedef struct -{ - ClutterActor *stage; - FooActor *foo_actor; - ClutterActor *parent_container; - ClutterActor *container; - ClutterActor *child; - ClutterActor *unrelated_actor; - gboolean was_painted; -} Data; - -GType foo_actor_get_type (void) G_GNUC_CONST; - -G_DEFINE_TYPE (FooActor, foo_actor, CLUTTER_TYPE_ACTOR); - -static gboolean group_has_overlaps; - -static void -foo_actor_paint (ClutterActor *actor, - ClutterPaintContext *paint_context) -{ - CoglContext *ctx = - clutter_backend_get_cogl_context (clutter_get_default_backend ()); - FooActor *foo_actor = (FooActor *) actor; - ClutterActorBox allocation; - CoglPipeline *pipeline; - CoglFramebuffer *framebuffer; - - foo_actor->last_paint_opacity = clutter_actor_get_paint_opacity (actor); - foo_actor->paint_count++; - - clutter_actor_get_allocation_box (actor, &allocation); - - /* Paint a red rectangle with the right opacity */ - pipeline = cogl_pipeline_new (ctx); - cogl_pipeline_set_color4ub (pipeline, - 255, 0, 0, - foo_actor->last_paint_opacity); - - framebuffer = clutter_paint_context_get_framebuffer (paint_context); - cogl_framebuffer_draw_rectangle (framebuffer, - pipeline, - allocation.x1, - allocation.y1, - allocation.x2, - allocation.y2); - cogl_object_unref (pipeline); -} - -static gboolean -foo_actor_get_paint_volume (ClutterActor *actor, - ClutterPaintVolume *volume) -{ - return clutter_paint_volume_set_from_allocation (volume, actor); -} - -static gboolean -foo_actor_has_overlaps (ClutterActor *actor) -{ - return FALSE; -} - -static void -foo_actor_class_init (FooActorClass *klass) -{ - ClutterActorClass *actor_class = (ClutterActorClass *) klass; - - actor_class->paint = foo_actor_paint; - actor_class->get_paint_volume = foo_actor_get_paint_volume; - actor_class->has_overlaps = foo_actor_has_overlaps; -} - -static void -foo_actor_init (FooActor *self) -{ -} - -typedef struct _FooGroup FooGroup; -typedef struct _FooGroupClass FooGroupClass; - -struct _FooGroupClass -{ - ClutterActorClass parent_class; -}; - -struct _FooGroup -{ - ClutterActor parent; -}; - -GType foo_group_get_type (void); - -G_DEFINE_TYPE (FooGroup, foo_group, CLUTTER_TYPE_ACTOR) - -static gboolean -foo_group_has_overlaps (ClutterActor *actor) -{ - return group_has_overlaps; -} - -static void -foo_group_class_init (FooGroupClass *klass) -{ - ClutterActorClass *actor_class = (ClutterActorClass *) klass; - - actor_class->has_overlaps = foo_group_has_overlaps; -} - -static void -foo_group_init (FooGroup *self) -{ -} - -static void -verify_results (Data *data, - guint8 expected_color_red, - guint8 expected_color_green, - guint8 expected_color_blue, - int expected_paint_count, - int expected_paint_opacity) -{ - guchar *pixel; - - data->foo_actor->paint_count = 0; - - /* Read a pixel at the center of the to determine what color it - painted. This should cause a redraw */ - pixel = clutter_stage_read_pixels (CLUTTER_STAGE (data->stage), - 50, 50, /* x/y */ - 1, 1 /* width/height */); - - g_assert_cmpint (expected_paint_count, ==, data->foo_actor->paint_count); - g_assert_cmpint (expected_paint_opacity, - ==, - data->foo_actor->last_paint_opacity); - - g_assert_cmpint (ABS ((int) expected_color_red - (int) pixel[0]), <=, 2); - g_assert_cmpint (ABS ((int) expected_color_green - (int) pixel[1]), <=, 2); - g_assert_cmpint (ABS ((int) expected_color_blue - (int) pixel[2]), <=, 2); - - g_free (pixel); -} - -static void -verify_redraw (Data *data, int expected_paint_count) -{ - GMainLoop *main_loop = g_main_loop_new (NULL, TRUE); - gulong paint_handler; - - paint_handler = g_signal_connect_data (CLUTTER_STAGE (data->stage), - "after-paint", - G_CALLBACK (g_main_loop_quit), - main_loop, - NULL, - G_CONNECT_SWAPPED); - - /* Queue a redraw on the stage */ - clutter_actor_queue_redraw (data->stage); - - data->foo_actor->paint_count = 0; - - /* Wait for it to paint */ - g_main_loop_run (main_loop); - - g_clear_signal_handler (&paint_handler, data->stage); - - g_assert_cmpint (data->foo_actor->paint_count, ==, expected_paint_count); -} - -static gboolean -verify_redraws (gpointer user_data) -{ - Data *data = user_data; - - clutter_actor_set_offscreen_redirect (data->container, - CLUTTER_OFFSCREEN_REDIRECT_ALWAYS); - - /* Queueing a redraw on the actor should cause a redraw */ - clutter_actor_queue_redraw (data->container); - verify_redraw (data, 1); - - /* Queueing a redraw on a child should cause a redraw */ - clutter_actor_queue_redraw (data->child); - verify_redraw (data, 1); - - /* Modifying the transformation on the parent should not cause a redraw, - since the FBO stores pre-transformed rendering that can be reused with - any transformation. */ - clutter_actor_set_translation (data->parent_container, 0.f, -1.f, 0.f); - verify_redraw (data, 0); - - /* Redrawing an unrelated actor shouldn't cause a redraw */ - clutter_actor_set_position (data->unrelated_actor, 0, 1); - verify_redraw (data, 0); - - data->was_painted = TRUE; - - return G_SOURCE_REMOVE; -} - -static gboolean -run_verify (gpointer user_data) -{ - Data *data = user_data; - int i; - - group_has_overlaps = FALSE; - - /* By default the actor shouldn't be redirected so the redraw should - cause the actor to be painted */ - verify_results (data, - 255, 0, 0, - 1, - 255); - - /* Make the actor semi-transparent and verify the paint opacity */ - clutter_actor_set_opacity (data->container, 127); - verify_results (data, - 255, 127, 127, - 1, - 127); - - /* With automatic redirect for opacity it shouldn't redirect if - * has_overlaps returns FALSE; */ - clutter_actor_set_offscreen_redirect - (data->container, CLUTTER_OFFSCREEN_REDIRECT_AUTOMATIC_FOR_OPACITY); - verify_results (data, - 255, 127, 127, - 1, - 127); - - /* We do a double check here to verify that the actor wasn't cached - * during the last check. If it was cached then this check wouldn't - * result in any foo-actor re-paint. */ - verify_results (data, - 255, 127, 127, - 1, - 127); - - /* With automatic redirect for opacity it should redirect if - * has_overlaps returns TRUE. - * The first paint will still cause the actor to draw because - * it needs to fill the cache first. It should be painted with full - * opacity */ - group_has_overlaps = TRUE; - - verify_results (data, - 255, 127, 127, - 1, - 255); - - /* The second time the actor is painted it should be cached */ - verify_results (data, - 255, 127, 127, - 0, - 255); - - /* We should be able to change the opacity without causing the actor - to redraw */ - clutter_actor_set_opacity (data->container, 64); - verify_results (data, - 255, 191, 191, - 0, - 255); - - /* Changing it back to fully opaque should cause it not to go - through the FBO so it will draw */ - clutter_actor_set_opacity (data->container, 255); - verify_results (data, - 255, 0, 0, - 1, - 255); - - /* Tell it to always redirect through the FBO. This should cause a - paint of the actor because the last draw didn't go through the - FBO */ - clutter_actor_set_offscreen_redirect (data->container, - CLUTTER_OFFSCREEN_REDIRECT_ALWAYS); - verify_results (data, - 255, 0, 0, - 1, - 255); - - /* We should be able to change the opacity without causing the actor - to redraw */ - clutter_actor_set_opacity (data->container, 64); - verify_results (data, - 255, 191, 191, - 0, - 255); - - /* Even changing it back to fully opaque shouldn't cause a redraw */ - clutter_actor_set_opacity (data->container, 255); - verify_results (data, - 255, 0, 0, - 0, - 255); - - /* ON_IDLE: Defer redirection through the FBO until it is deemed to be the - * best performing option, which means when the actor's contents have - * stopped changing. - */ - clutter_actor_set_offscreen_redirect (data->container, - CLUTTER_OFFSCREEN_REDIRECT_ON_IDLE); - - /* Changing modes should not incur a redraw */ - verify_results (data, - 255, 0, 0, - 0, - 255); - - /* These will incur a redraw because the actor is dirty: */ - for (i = 0; i < 10; i++) - { - clutter_actor_queue_redraw (data->container); - verify_results (data, - 255, 0, 0, - 1, - 255); - } - - /* The actor is not dirty, but also not yet cached so a redraw is expected */ - verify_results (data, - 255, 0, 0, - 1, - 255); - - /* These will NOT incur a redraw because the actor is unchanged: */ - for (i = 0; i < 10; i++) - { - verify_results (data, - 255, 0, 0, - 0, - 255); - } - - /* The first opacity change should require no redaw */ - clutter_actor_set_opacity (data->container, 64); - verify_results (data, - 255, 191, 191, - 0, - 255); - - /* The second opacity change should require no redaw */ - clutter_actor_set_opacity (data->container, 127); - verify_results (data, - 255, 127, 127, - 0, - 255); - - /* The third opacity change should require no redaw */ - clutter_actor_set_opacity (data->container, 255); - verify_results (data, - 255, 0, 0, - 0, - 255); - - /* Now several frames without the actor changing AND the FBO is populated. - * Expect no internal repaints. - */ - for (i = 0; i < 10; i++) - { - verify_results (data, - 255, 0, 0, - 0, - 255); - } - - /* Another opacity change, no redraw expected */ - clutter_actor_set_opacity (data->container, 127); - verify_results (data, - 255, 127, 127, - 0, - 255); - - /* Finally the actor's content changes so a redraw is expected */ - clutter_actor_queue_redraw (data->container); - verify_results (data, - 255, 127, 127, - 1, - 127); - - /* Check redraws */ - g_idle_add (verify_redraws, data); - - return G_SOURCE_REMOVE; -} - -static void -actor_offscreen_redirect (void) -{ - Data data = { 0 }; - - data.stage = clutter_test_get_stage (); - data.parent_container = clutter_actor_new (); - clutter_actor_set_background_color (data.parent_container, - &(ClutterColor) { 255, 255, 255, 255 }); - - data.container = g_object_new (foo_group_get_type (), NULL); - data.foo_actor = g_object_new (foo_actor_get_type (), NULL); - clutter_actor_set_size (CLUTTER_ACTOR (data.foo_actor), 100, 100); - - clutter_actor_add_child (data.container, CLUTTER_ACTOR (data.foo_actor)); - clutter_actor_add_child (data.parent_container, data.container); - clutter_actor_add_child (data.stage, data.parent_container); - - data.child = clutter_actor_new (); - clutter_actor_set_size (data.child, 1, 1); - clutter_actor_add_child (data.container, data.child); - - data.unrelated_actor = clutter_actor_new (); - clutter_actor_set_size (data.child, 1, 1); - clutter_actor_add_child (data.stage, data.unrelated_actor); - - clutter_actor_show (data.stage); - - clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT, - run_verify, - &data, - NULL); - - while (!data.was_painted) - g_main_context_iteration (NULL, FALSE); - - clutter_actor_destroy (data.parent_container); - clutter_actor_destroy (data.unrelated_actor); -} - -CLUTTER_TEST_SUITE ( - CLUTTER_TEST_UNIT ("/actor/offscreen/redirect", actor_offscreen_redirect) -) diff --git a/src/tests/clutter/conform/actor-paint-opacity.c b/src/tests/clutter/conform/actor-paint-opacity.c deleted file mode 100644 index f73a8f0f7..000000000 --- a/src/tests/clutter/conform/actor-paint-opacity.c +++ /dev/null @@ -1,151 +0,0 @@ -#include -#include - -#include "tests/clutter-test-utils.h" - -static void -opacity_label (void) -{ - ClutterActor *stage; - ClutterActor *label; - ClutterColor label_color = { 255, 0, 0, 128 }; - ClutterColor color_check = { 0, }; - - stage = clutter_test_get_stage (); - - label = clutter_text_new_with_text ("Sans 18px", "Label, 50% opacity"); - clutter_text_set_color (CLUTTER_TEXT (label), &label_color); - - if (!g_test_quiet ()) - g_print ("label 50%%.get_color()/1\n"); - clutter_text_get_color (CLUTTER_TEXT (label), &color_check); - g_assert (color_check.alpha == label_color.alpha); - - clutter_actor_add_child (stage, label); - clutter_actor_set_position (label, 10, 10); - - if (!g_test_quiet ()) - g_print ("label 50%%.get_color()/2\n"); - clutter_text_get_color (CLUTTER_TEXT (label), &color_check); - g_assert (color_check.alpha == label_color.alpha); - - if (!g_test_quiet ()) - g_print ("label 50%%.get_paint_opacity()/1\n"); - g_assert (clutter_actor_get_paint_opacity (label) == 255); - - if (!g_test_quiet ()) - g_print ("label 50%%.get_paint_opacity()/2\n"); - clutter_actor_set_opacity (label, 128); - g_assert (clutter_actor_get_paint_opacity (label) == 128); - - clutter_actor_destroy (label); -} - -G_GNUC_BEGIN_IGNORE_DEPRECATIONS -static void -opacity_rectangle (void) -{ - ClutterActor *stage; - ClutterActor *rect; - ClutterColor rect_color = { 0, 0, 255, 255 }; - ClutterColor color_check = { 0, }; - - stage = clutter_test_get_stage (); - - rect = clutter_actor_new (); - clutter_actor_set_background_color (rect, &rect_color); - clutter_actor_set_size (rect, 128, 128); - clutter_actor_set_position (rect, 150, 90); - - if (!g_test_quiet ()) - g_print ("rect 100%%.get_color()/1\n"); - clutter_actor_get_background_color (rect, &color_check); - g_assert (color_check.alpha == rect_color.alpha); - - clutter_actor_add_child (stage, rect); - - if (!g_test_quiet ()) - g_print ("rect 100%%.get_color()/2\n"); - clutter_actor_set_background_color (rect, &color_check); - g_assert (color_check.alpha == rect_color.alpha); - - if (!g_test_quiet ()) - g_print ("rect 100%%.get_paint_opacity()\n"); - g_assert (clutter_actor_get_paint_opacity (rect) == 255); - - clutter_actor_destroy (rect); -} -G_GNUC_END_IGNORE_DEPRECATIONS - -G_GNUC_BEGIN_IGNORE_DEPRECATIONS -static void -opacity_paint (void) -{ - ClutterActor *stage, *group1, *group2; - ClutterActor *label, *rect; - ClutterColor label_color = { 255, 0, 0, 128 }; - ClutterColor rect_color = { 0, 0, 255, 255 }; - ClutterColor color_check = { 0, }; - - stage = clutter_test_get_stage (); - - group1 = clutter_actor_new (); - clutter_actor_set_opacity (group1, 128); - clutter_container_add (CLUTTER_CONTAINER (stage), group1, NULL); - clutter_actor_set_position (group1, 10, 30); - clutter_actor_show (group1); - - label = clutter_text_new_with_text ("Sans 18px", "Label+Group, 25% opacity"); - clutter_text_set_color (CLUTTER_TEXT (label), &label_color); - - if (!g_test_quiet ()) - g_print ("label 50%% + group 50%%.get_color()/1\n"); - clutter_text_get_color (CLUTTER_TEXT (label), &color_check); - g_assert (color_check.alpha == label_color.alpha); - - clutter_container_add (CLUTTER_CONTAINER (group1), label, NULL); - - if (!g_test_quiet ()) - g_print ("label 50%% + group 50%%.get_color()/2\n"); - clutter_text_get_color (CLUTTER_TEXT (label), &color_check); - g_assert (color_check.alpha == label_color.alpha); - - if (!g_test_quiet ()) - g_print ("label 50%% + group 50%%.get_paint_opacity() = 128\n"); - g_assert (clutter_actor_get_paint_opacity (label) == 128); - - clutter_actor_destroy (label); - - group2 = clutter_actor_new (); - clutter_container_add (CLUTTER_CONTAINER (group1), group2, NULL); - clutter_actor_set_position (group2, 10, 60); - - rect = clutter_actor_new (); - clutter_actor_set_background_color (rect, &rect_color); - clutter_actor_set_size (rect, 128, 128); - - if (!g_test_quiet ()) - g_print ("rect 100%% + group 100%% + group 50%%.get_color()/1\n"); - clutter_actor_get_background_color (rect, &color_check); - g_assert (color_check.alpha == rect_color.alpha); - - clutter_container_add (CLUTTER_CONTAINER (group2), rect, NULL); - - if (!g_test_quiet ()) - g_print ("rect 100%% + group 100%% + group 50%%.get_color()/2\n"); - clutter_actor_get_background_color (rect, &color_check); - g_assert (color_check.alpha == rect_color.alpha); - - if (!g_test_quiet ()) - g_print ("rect 100%%.get_paint_opacity()\n"); - g_assert (clutter_actor_get_paint_opacity (rect) == 128); - - clutter_actor_destroy (group1); -} -G_GNUC_END_IGNORE_DEPRECATIONS - -CLUTTER_TEST_SUITE ( - CLUTTER_TEST_UNIT ("/actor/opacity/text", opacity_label) - CLUTTER_TEST_UNIT ("/actor/opacity/rectangle", opacity_rectangle) - CLUTTER_TEST_UNIT ("/actor/opacity/paint", opacity_paint) -) diff --git a/src/tests/clutter/conform/actor-pick.c b/src/tests/clutter/conform/actor-pick.c deleted file mode 100644 index 011acec4a..000000000 --- a/src/tests/clutter/conform/actor-pick.c +++ /dev/null @@ -1,231 +0,0 @@ -#define CLUTTER_DISABLE_DEPRECATION_WARNINGS -#include - -#include "tests/clutter-test-utils.h" - -#define STAGE_WIDTH 640 -#define STAGE_HEIGHT 480 -#define ACTORS_X 12 -#define ACTORS_Y 16 - -typedef struct _State State; - -struct _State -{ - ClutterActor *stage; - int y, x; - ClutterActor *actors[ACTORS_X * ACTORS_Y]; - guint actor_width, actor_height; - guint failed_pass; - guint failed_idx; - gboolean pass; - GList *actor_list; -}; - -static const char *test_passes[] = { - "No covering actor", - "Invisible covering actor", - "Clipped covering actor", - "Blur effect", -}; - -static gboolean -on_timeout (gpointer data) -{ - State *state = data; - int test_num = 0; - int y, x; - ClutterActor *over_actor = NULL; - - /* This will cause an unclipped pick redraw that will get buffered. - We'll check below that this buffer is discarded because we also need - to pick non-reactive actors */ - clutter_stage_get_actor_at_pos (CLUTTER_STAGE (state->stage), - CLUTTER_PICK_REACTIVE, 10, 10); - - clutter_stage_get_actor_at_pos (CLUTTER_STAGE (state->stage), - CLUTTER_PICK_REACTIVE, 10, 10); - - for (test_num = 0; test_num < G_N_ELEMENTS (test_passes); test_num++) - { - if (test_num == 0) - { - if (!g_test_quiet ()) - g_print ("No covering actor:\n"); - } - if (test_num == 1) - { - static const ClutterColor red = { 0xff, 0x00, 0x00, 0xff }; - /* Create an actor that covers the whole stage but that - isn't visible so it shouldn't affect the picking */ - over_actor = clutter_actor_new (); - clutter_actor_set_background_color (over_actor, &red); - clutter_actor_set_size (over_actor, STAGE_WIDTH, STAGE_HEIGHT); - clutter_actor_add_child (state->stage, over_actor); - state->actor_list = g_list_prepend (state->actor_list, over_actor); - clutter_actor_hide (over_actor); - - if (!g_test_quiet ()) - g_print ("Invisible covering actor:\n"); - } - else if (test_num == 2) - { - ClutterActorBox over_actor_box = - CLUTTER_ACTOR_BOX_INIT (0, 0, STAGE_WIDTH, STAGE_HEIGHT); - - /* Make the actor visible but set a clip so that only some - of the actors are accessible */ - clutter_actor_show (over_actor); - clutter_actor_set_clip (over_actor, - state->actor_width * 2, - state->actor_height * 2, - state->actor_width * (ACTORS_X - 4), - state->actor_height * (ACTORS_Y - 4)); - - /* Only allocated actors can be picked, so force an allocation - * of the overlay actor here. - */ - clutter_actor_allocate (over_actor, &over_actor_box); - - if (!g_test_quiet ()) - g_print ("Clipped covering actor:\n"); - } - else if (test_num == 3) - { - if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) - continue; - - clutter_actor_hide (over_actor); - - clutter_actor_add_effect_with_name (CLUTTER_ACTOR (state->stage), - "blur", - clutter_blur_effect_new ()); - - if (!g_test_quiet ()) - g_print ("With blur effect:\n"); - } - - for (y = 0; y < ACTORS_Y; y++) - { - x = 0; - - for (; x < ACTORS_X; x++) - { - gboolean pass = FALSE; - gfloat pick_x; - ClutterActor *actor; - - pick_x = x * state->actor_width + state->actor_width / 2; - - actor = - clutter_stage_get_actor_at_pos (CLUTTER_STAGE (state->stage), - CLUTTER_PICK_ALL, - pick_x, - y * state->actor_height - + state->actor_height / 2); - - if (!g_test_quiet ()) - g_print ("% 3i,% 3i / %p -> ", - x, y, state->actors[y * ACTORS_X + x]); - - if (actor == NULL) - { - if (!g_test_quiet ()) - g_print ("NULL: FAIL\n"); - } - else if (actor == over_actor) - { - if (test_num == 2 - && x >= 2 && x < ACTORS_X - 2 - && y >= 2 && y < ACTORS_Y - 2) - pass = TRUE; - - if (!g_test_quiet ()) - g_print ("over_actor: %s\n", pass ? "pass" : "FAIL"); - } - else - { - if (actor == state->actors[y * ACTORS_X + x] - && (test_num != 2 - || x < 2 || x >= ACTORS_X - 2 - || y < 2 || y >= ACTORS_Y - 2)) - pass = TRUE; - - if (!g_test_quiet ()) - g_print ("%p: %s\n", actor, pass ? "pass" : "FAIL"); - } - - if (!pass) - { - state->failed_pass = test_num; - state->failed_idx = y * ACTORS_X + x; - state->pass = FALSE; - } - } - } - } - - clutter_test_quit (); - - return G_SOURCE_REMOVE; -} - -static void -actor_pick (void) -{ - int y, x; - State state = { 0 }; - - state.pass = TRUE; - - state.stage = clutter_test_get_stage (); - - state.actor_width = STAGE_WIDTH / ACTORS_X; - state.actor_height = STAGE_HEIGHT / ACTORS_Y; - - for (y = 0; y < ACTORS_Y; y++) - for (x = 0; x < ACTORS_X; x++) - { - ClutterColor color = { x * 255 / (ACTORS_X - 1), - y * 255 / (ACTORS_Y - 1), - 128, 255 }; - ClutterActor *rect = clutter_actor_new (); - state.actor_list = g_list_prepend (state.actor_list, rect); - - clutter_actor_set_background_color (rect, &color); - clutter_actor_set_position (rect, - x * state.actor_width, - y * state.actor_height); - clutter_actor_set_size (rect, - state.actor_width, - state.actor_height); - - clutter_actor_add_child (state.stage, rect); - - state.actors[y * ACTORS_X + x] = rect; - } - - clutter_actor_show (state.stage); - - clutter_threads_add_idle (on_timeout, &state); - - clutter_test_main (); - - if (!g_test_quiet ()) - { - if (!state.pass) - g_test_message ("Failed pass: %s[%d], actor index: %d [%p]\n", - test_passes[state.failed_pass], - state.failed_pass, - state.failed_idx, - state.actors[state.failed_idx]); - } - - g_assert (state.pass); - - g_list_free_full (state.actor_list, (GDestroyNotify) clutter_actor_destroy); -} - -CLUTTER_TEST_SUITE ( - CLUTTER_TEST_UNIT ("/actor/pick", actor_pick) -) diff --git a/src/tests/clutter/conform/actor-pivot-point.c b/src/tests/clutter/conform/actor-pivot-point.c deleted file mode 100644 index 6a5cdf22c..000000000 --- a/src/tests/clutter/conform/actor-pivot-point.c +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include - -#define CLUTTER_DISABLE_DEPRECATION_WARNINGS -#include - -#include "tests/clutter-test-utils.h" - -static void -actor_pivot (void) -{ - ClutterActor *stage, *actor_implicit, *actor_explicit; - graphene_matrix_t transform, result_implicit, result_explicit; - ClutterActorBox allocation = CLUTTER_ACTOR_BOX_INIT (0, 0, 90, 30); - gfloat angle = 30; - - stage = clutter_test_get_stage (); - - actor_implicit = clutter_actor_new (); - actor_explicit = clutter_actor_new (); - - clutter_actor_add_child (stage, actor_implicit); - clutter_actor_add_child (stage, actor_explicit); - - clutter_actor_show (stage); - - /* Fake allocation or pivot-point will not have any effect */ - clutter_actor_allocate (actor_implicit, &allocation); - clutter_actor_allocate (actor_explicit, &allocation); - - clutter_actor_set_pivot_point (actor_implicit, 0.5, 0.5); - clutter_actor_set_pivot_point (actor_explicit, 0.5, 0.5); - - /* Implicit transformation */ - clutter_actor_set_rotation_angle (actor_implicit, CLUTTER_Z_AXIS, angle); - - /* Explicit transformation */ - graphene_matrix_init_rotate (&transform, angle, graphene_vec3_z_axis ()); - clutter_actor_set_transform (actor_explicit, &transform); - - clutter_actor_get_transform (actor_implicit, &result_implicit); - clutter_actor_get_transform (actor_explicit, &result_explicit); - - g_assert (graphene_matrix_equal (&result_implicit, &result_explicit)); - - clutter_actor_destroy (actor_implicit); - clutter_actor_destroy (actor_explicit); -} - -CLUTTER_TEST_SUITE ( - CLUTTER_TEST_UNIT ("/actor/transforms/pivot-point", actor_pivot) -) diff --git a/src/tests/clutter/conform/actor-shader-effect.c b/src/tests/clutter/conform/actor-shader-effect.c deleted file mode 100644 index a22ae5f99..000000000 --- a/src/tests/clutter/conform/actor-shader-effect.c +++ /dev/null @@ -1,301 +0,0 @@ -#define CLUTTER_DISABLE_DEPRECATION_WARNINGS -#include - -#include "tests/clutter-test-utils.h" - -/**************************************************************** - Old style shader effect - This uses clutter_shader_effect_set_source - ****************************************************************/ - -static const gchar -old_shader_effect_source[] = - "uniform vec3 override_color;\n" - "\n" - "void\n" - "main ()\n" - "{\n" - " cogl_color_out = vec4 (override_color, 1.0);\n" - "}"; - -typedef struct _FooOldShaderEffectClass -{ - ClutterShaderEffectClass parent_class; -} FooOldShaderEffectClass; - -typedef struct _FooOldShaderEffect -{ - ClutterShaderEffect parent; -} FooOldShaderEffect; - -GType foo_old_shader_effect_get_type (void); - -G_DEFINE_TYPE (FooOldShaderEffect, - foo_old_shader_effect, - CLUTTER_TYPE_SHADER_EFFECT); - -static void -foo_old_shader_effect_paint_target (ClutterOffscreenEffect *effect, - ClutterPaintNode *node, - ClutterPaintContext *paint_context) -{ - clutter_shader_effect_set_shader_source (CLUTTER_SHADER_EFFECT (effect), - old_shader_effect_source); - clutter_shader_effect_set_uniform (CLUTTER_SHADER_EFFECT (effect), - "override_color", - G_TYPE_FLOAT, 3, - 1.0f, 0.0f, 0.0f); - - CLUTTER_OFFSCREEN_EFFECT_CLASS (foo_old_shader_effect_parent_class)-> - paint_target (effect, node, paint_context); -} - -static void -foo_old_shader_effect_class_init (FooOldShaderEffectClass *klass) -{ - ClutterOffscreenEffectClass *offscreen_effect_class = - CLUTTER_OFFSCREEN_EFFECT_CLASS (klass); - - offscreen_effect_class->paint_target = foo_old_shader_effect_paint_target; -} - -static void -foo_old_shader_effect_init (FooOldShaderEffect *self) -{ -} - -/**************************************************************** - New style shader effect - This overrides get_static_shader_source() - ****************************************************************/ - -static const gchar -new_shader_effect_source[] = - "uniform vec3 override_color;\n" - "\n" - "void\n" - "main ()\n" - "{\n" - " cogl_color_out = (vec4 (override_color, 1.0) +\n" - " vec4 (0.0, 0.0, 1.0, 0.0));\n" - "}"; - -typedef struct _FooNewShaderEffectClass -{ - ClutterShaderEffectClass parent_class; -} FooNewShaderEffectClass; - -typedef struct _FooNewShaderEffect -{ - ClutterShaderEffect parent; -} FooNewShaderEffect; - -GType foo_new_shader_effect_get_type (void); - -G_DEFINE_TYPE (FooNewShaderEffect, - foo_new_shader_effect, - CLUTTER_TYPE_SHADER_EFFECT); - -static gchar * -foo_new_shader_effect_get_static_source (ClutterShaderEffect *effect) -{ - static gboolean already_called = FALSE; - - /* This should only be called once even though we have two actors - using this effect */ - g_assert (!already_called); - - already_called = TRUE; - - return g_strdup (new_shader_effect_source); -} - -static void -foo_new_shader_effect_paint_target (ClutterOffscreenEffect *effect, - ClutterPaintNode *node, - ClutterPaintContext *paint_context) -{ - clutter_shader_effect_set_uniform (CLUTTER_SHADER_EFFECT (effect), - "override_color", - G_TYPE_FLOAT, 3, - 0.0f, 1.0f, 0.0f); - - CLUTTER_OFFSCREEN_EFFECT_CLASS (foo_new_shader_effect_parent_class)-> - paint_target (effect, node, paint_context); -} - -static void -foo_new_shader_effect_class_init (FooNewShaderEffectClass *klass) -{ - ClutterOffscreenEffectClass *offscreen_effect_class = - CLUTTER_OFFSCREEN_EFFECT_CLASS (klass); - ClutterShaderEffectClass *shader_effect_class = - CLUTTER_SHADER_EFFECT_CLASS (klass); - - offscreen_effect_class->paint_target = foo_new_shader_effect_paint_target; - - shader_effect_class->get_static_shader_source = - foo_new_shader_effect_get_static_source; -} - -static void -foo_new_shader_effect_init (FooNewShaderEffect *self) -{ -} - -/**************************************************************** - Another new style shader effect - This is the same but with a different shader. This is just - sanity check that each class gets its own copy of the private - data - ****************************************************************/ - -static const gchar -another_new_shader_effect_source[] = - "\n" - "void\n" - "main ()\n" - "{\n" - " cogl_color_out = vec4 (1.0, 0.0, 1.0, 1.0);\n" - "}"; - -typedef struct _FooAnotherNewShaderEffectClass -{ - ClutterShaderEffectClass parent_class; -} FooAnotherNewShaderEffectClass; - -typedef struct _FooAnotherNewShaderEffect -{ - ClutterShaderEffect parent; -} FooAnotherNewShaderEffect; - -GType foo_another_new_shader_effect_get_type (void); - -G_DEFINE_TYPE (FooAnotherNewShaderEffect, - foo_another_new_shader_effect, - CLUTTER_TYPE_SHADER_EFFECT); - -static gchar * -foo_another_new_shader_effect_get_static_source (ClutterShaderEffect *effect) -{ - return g_strdup (another_new_shader_effect_source); -} - -static void -foo_another_new_shader_effect_class_init (FooAnotherNewShaderEffectClass *klass) -{ - ClutterShaderEffectClass *shader_effect_class = - CLUTTER_SHADER_EFFECT_CLASS (klass); - - shader_effect_class->get_static_shader_source = - foo_another_new_shader_effect_get_static_source; -} - -static void -foo_another_new_shader_effect_init (FooAnotherNewShaderEffect *self) -{ -} - -/****************************************************************/ - -static ClutterActor * -make_actor (GType shader_type) -{ - ClutterActor *rect; - const ClutterColor white = { 0xff, 0xff, 0xff, 0xff }; - - rect = clutter_actor_new (); - clutter_actor_set_background_color (rect, &white); - clutter_actor_set_size (rect, 50, 50); - - clutter_actor_add_effect (rect, g_object_new (shader_type, NULL)); - - return rect; -} - -static guint32 -get_pixel (CoglFramebuffer *fb, - int x, - int y) -{ - guint8 data[4]; - - 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) | - data[2]); -} - -static void -view_painted_cb (ClutterStage *stage, - ClutterStageView *view, - cairo_region_t *redraw_clip, - gpointer data) -{ - CoglFramebuffer *fb = clutter_stage_view_get_framebuffer (view); - gboolean *was_painted = data; - - /* old shader effect */ - g_assert_cmpint (get_pixel (fb, 0, 25), ==, 0xff0000); - /* new shader effect */ - g_assert_cmpint (get_pixel (fb, 100, 25), ==, 0x00ffff); - /* another new shader effect */ - g_assert_cmpint (get_pixel (fb, 200, 25), ==, 0xff00ff); - /* new shader effect */ - g_assert_cmpint (get_pixel (fb, 300, 25), ==, 0x00ffff); - - *was_painted = TRUE; -} - -static void -actor_shader_effect (void) -{ - ClutterActor *stage; - ClutterActor *rect; - gboolean was_painted; - GList *actors = NULL; - - if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) - return; - - stage = clutter_test_get_stage (); - - rect = make_actor (foo_old_shader_effect_get_type ()); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); - actors = g_list_prepend (actors, rect); - - rect = make_actor (foo_new_shader_effect_get_type ()); - clutter_actor_set_x (rect, 100); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); - actors = g_list_prepend (actors, rect); - - rect = make_actor (foo_another_new_shader_effect_get_type ()); - clutter_actor_set_x (rect, 200); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); - actors = g_list_prepend (actors, rect); - - rect = make_actor (foo_new_shader_effect_get_type ()); - clutter_actor_set_x (rect, 300); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); - actors = g_list_prepend (actors, rect); - - clutter_actor_show (stage); - - was_painted = FALSE; - g_signal_connect_after (stage, "paint-view", - G_CALLBACK (view_painted_cb), - &was_painted); - - while (!was_painted) - g_main_context_iteration (NULL, FALSE); - - g_list_free_full (actors, (GDestroyNotify) clutter_actor_destroy); -} - -CLUTTER_TEST_SUITE ( - CLUTTER_TEST_UNIT ("/actor/shader-effect", actor_shader_effect) -) diff --git a/src/tests/clutter/conform/actor-size.c b/src/tests/clutter/conform/actor-size.c deleted file mode 100644 index e8b04af3b..000000000 --- a/src/tests/clutter/conform/actor-size.c +++ /dev/null @@ -1,218 +0,0 @@ -#include -#include - -#include - -#include "tests/clutter-test-utils.h" - -#define TEST_TYPE_ACTOR (test_actor_get_type ()) - -typedef struct _TestActor TestActor; -typedef struct _ClutterActorClass TestActorClass; - -struct _TestActor -{ - ClutterActor parent_instance; - - guint preferred_width_called : 1; - guint preferred_height_called : 1; -}; - -GType test_actor_get_type (void); - -G_DEFINE_TYPE (TestActor, test_actor, CLUTTER_TYPE_ACTOR); - -static void -test_actor_get_preferred_width (ClutterActor *self, - gfloat for_height, - gfloat *min_width_p, - gfloat *nat_width_p) -{ - TestActor *test = (TestActor *) self; - - test->preferred_width_called = TRUE; - - if (for_height == 10) - { - *min_width_p = 10; - *nat_width_p = 100; - } - else - { - *min_width_p = 100; - *nat_width_p = 100; - } -} - -static void -test_actor_get_preferred_height (ClutterActor *self, - gfloat for_width, - gfloat *min_height_p, - gfloat *nat_height_p) -{ - TestActor *test = (TestActor *) self; - - test->preferred_height_called = TRUE; - - if (for_width == 10) - { - *min_height_p = 50; - *nat_height_p = 100; - } - else - { - *min_height_p = 100; - *nat_height_p = 100; - } -} - -static void -test_actor_class_init (TestActorClass *klass) -{ - ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); - - actor_class->get_preferred_width = test_actor_get_preferred_width; - actor_class->get_preferred_height = test_actor_get_preferred_height; -} - -static void -test_actor_init (TestActor *self) -{ -} - -static void -actor_preferred_size (void) -{ - ClutterActor *test; - TestActor *self; - gfloat min_width, min_height; - gfloat nat_width, nat_height; - - test = g_object_new (TEST_TYPE_ACTOR, NULL); - self = (TestActor *) test; - - if (!g_test_quiet ()) - g_print ("Preferred size\n"); - - clutter_actor_get_preferred_size (test, - &min_width, &min_height, - &nat_width, &nat_height); - - g_assert (self->preferred_width_called); - g_assert (self->preferred_height_called); - g_assert_cmpfloat (min_width, ==, 100); - g_assert_cmpfloat (min_height, ==, 100); - g_assert_cmpfloat (nat_width, ==, min_width); - g_assert_cmpfloat (nat_height, ==, min_height); - - if (!g_test_quiet ()) - g_print ("Preferred width\n"); - self->preferred_width_called = FALSE; - clutter_actor_get_preferred_width (test, 10, &min_width, &nat_width); - g_assert (self->preferred_width_called); - g_assert_cmpfloat (min_width, ==, 10); - g_assert_cmpfloat (nat_width, ==, 100); - - if (!g_test_quiet ()) - g_print ("Preferred height\n"); - self->preferred_height_called = FALSE; - clutter_actor_get_preferred_height (test, 200, &min_height, &nat_height); - g_assert (self->preferred_height_called); - g_assert_cmpfloat (min_height, !=, 10); - g_assert_cmpfloat (nat_height, ==, 100); - - if (!g_test_quiet ()) - g_print ("Preferred width (cached)\n"); - self->preferred_width_called = FALSE; - clutter_actor_get_preferred_width (test, 10, &min_width, &nat_width); - g_assert (!self->preferred_width_called); - g_assert_cmpfloat (min_width, ==, 10); - g_assert_cmpfloat (nat_width, ==, 100); - - if (!g_test_quiet ()) - g_print ("Preferred height (cache eviction)\n"); - self->preferred_height_called = FALSE; - clutter_actor_get_preferred_height (test, 10, &min_height, &nat_height); - g_assert (self->preferred_height_called); - g_assert_cmpfloat (min_height, ==, 50); - g_assert_cmpfloat (nat_height, ==, 100); - - clutter_actor_destroy (test); -} - -static void -actor_fixed_size (void) -{ - ClutterActor *rect; - gboolean min_width_set, nat_width_set; - gboolean min_height_set, nat_height_set; - gfloat min_width, min_height; - gfloat nat_width, nat_height; - - rect = clutter_actor_new (); - g_object_ref_sink (rect); - - if (!g_test_quiet ()) - g_print ("Initial size is 0\n"); - - g_assert_cmpfloat (clutter_actor_get_width (rect), ==, 0); - g_assert_cmpfloat (clutter_actor_get_height (rect), ==, 0); - - clutter_actor_set_size (rect, 100, 100); - - if (!g_test_quiet ()) - g_print ("Explicit size set\n"); - - g_assert_cmpfloat (clutter_actor_get_width (rect), ==, 100); - g_assert_cmpfloat (clutter_actor_get_height (rect), ==, 100); - - g_object_get (G_OBJECT (rect), - "min-width-set", &min_width_set, - "min-height-set", &min_height_set, - "natural-width-set", &nat_width_set, - "natural-height-set", &nat_height_set, - NULL); - - if (!g_test_quiet ()) - g_print ("Notification properties\n"); - - g_assert (min_width_set && nat_width_set); - g_assert (min_height_set && nat_height_set); - - clutter_actor_get_preferred_size (rect, - &min_width, &min_height, - &nat_width, &nat_height); - - if (!g_test_quiet ()) - g_print ("Preferred size\n"); - - g_assert_cmpfloat (min_width, ==, 100); - g_assert_cmpfloat (min_height, ==, 100); - g_assert_cmpfloat (min_width, ==, nat_width); - g_assert_cmpfloat (min_height, ==, nat_height); - - clutter_actor_set_size (rect, -1, -1); - - if (!g_test_quiet ()) - g_print ("Explicit size unset\n"); - - g_object_get (G_OBJECT (rect), - "min-width-set", &min_width_set, - "min-height-set", &min_height_set, - "natural-width-set", &nat_width_set, - "natural-height-set", &nat_height_set, - NULL); - g_assert (!min_width_set && !nat_width_set); - g_assert (!min_height_set && !nat_height_set); - - g_assert_cmpfloat (clutter_actor_get_width (rect), ==, 0); - g_assert_cmpfloat (clutter_actor_get_height (rect), ==, 0); - - clutter_actor_destroy (rect); - g_object_unref (rect); -} - -CLUTTER_TEST_SUITE ( - CLUTTER_TEST_UNIT ("/actor/size/preferred", actor_preferred_size) - CLUTTER_TEST_UNIT ("/actor/size/fixed", actor_fixed_size) -) diff --git a/src/tests/clutter/conform/binding-pool.c b/src/tests/clutter/conform/binding-pool.c deleted file mode 100644 index a14ea573e..000000000 --- a/src/tests/clutter/conform/binding-pool.c +++ /dev/null @@ -1,311 +0,0 @@ -#include - -#include - -#include "tests/clutter-test-utils.h" - -#define TYPE_KEY_GROUP (key_group_get_type ()) -#define KEY_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_KEY_GROUP, KeyGroup)) -#define IS_KEY_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_KEY_GROUP)) -#define KEY_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_KEY_GROUP, KeyGroupClass)) -#define IS_KEY_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_KEY_GROUP)) - -typedef struct _KeyGroup KeyGroup; -typedef struct _KeyGroupClass KeyGroupClass; - -struct _KeyGroup -{ - ClutterActor parent_instance; - - gint selected_index; -}; - -struct _KeyGroupClass -{ - ClutterActorClass parent_class; - - void (* activate) (KeyGroup *group, - ClutterActor *child); -}; - -GType key_group_get_type (void); - -G_DEFINE_TYPE (KeyGroup, key_group, CLUTTER_TYPE_ACTOR) - -enum -{ - ACTIVATE, - - LAST_SIGNAL -}; - -static guint group_signals[LAST_SIGNAL] = { 0, }; - -static gboolean -key_group_action_move_left (KeyGroup *self, - const gchar *action_name, - guint key_val, - ClutterModifierType modifiers) -{ - gint n_children; - - g_assert_cmpstr (action_name, ==, "move-left"); - g_assert_cmpint (key_val, ==, CLUTTER_KEY_Left); - - n_children = clutter_actor_get_n_children (CLUTTER_ACTOR (self)); - - self->selected_index -= 1; - - if (self->selected_index < 0) - self->selected_index = n_children - 1; - - return TRUE; -} - -static gboolean -key_group_action_move_right (KeyGroup *self, - const gchar *action_name, - guint key_val, - ClutterModifierType modifiers) -{ - gint n_children; - - g_assert_cmpstr (action_name, ==, "move-right"); - g_assert_cmpint (key_val, ==, CLUTTER_KEY_Right); - - n_children = clutter_actor_get_n_children (CLUTTER_ACTOR (self)); - - self->selected_index += 1; - - if (self->selected_index >= n_children) - self->selected_index = 0; - - return TRUE; -} - -static gboolean -key_group_action_activate (KeyGroup *self, - const gchar *action_name, - guint key_val, - ClutterModifierType modifiers) -{ - ClutterActor *child = NULL; - - g_assert_cmpstr (action_name, ==, "activate"); - g_assert (key_val == CLUTTER_KEY_Return || - key_val == CLUTTER_KEY_KP_Enter || - key_val == CLUTTER_KEY_ISO_Enter); - - if (self->selected_index == -1) - return FALSE; - - child = clutter_actor_get_child_at_index (CLUTTER_ACTOR (self), self->selected_index); - if (child != NULL) - { - g_signal_emit (self, group_signals[ACTIVATE], 0, child); - return TRUE; - } - else - return FALSE; -} - -static gboolean -key_group_key_press (ClutterActor *actor, - ClutterKeyEvent *event) -{ - ClutterBindingPool *pool; - gboolean res; - - pool = clutter_binding_pool_find (G_OBJECT_TYPE_NAME (actor)); - g_assert (pool != NULL); - - res = clutter_binding_pool_activate (pool, - event->keyval, - event->modifier_state, - G_OBJECT (actor)); - - /* if we activate a key binding, redraw the actor */ - if (res) - clutter_actor_queue_redraw (actor); - - return res; -} - -static void -key_group_paint (ClutterActor *actor, - ClutterPaintContext *paint_context) -{ - KeyGroup *self = KEY_GROUP (actor); - CoglContext *ctx = - clutter_backend_get_cogl_context (clutter_get_default_backend ()); - ClutterActorIter iter; - ClutterActor *child; - CoglPipeline *pipeline; - CoglFramebuffer *framebuffer; - gint i = 0; - - pipeline = cogl_pipeline_new (ctx); - cogl_pipeline_set_color4ub (pipeline, 255, 255, 0, 224); - - framebuffer = clutter_paint_context_get_framebuffer (paint_context); - - clutter_actor_iter_init (&iter, actor); - while (clutter_actor_iter_next (&iter, &child)) - { - /* paint the selection rectangle */ - if (i == self->selected_index) - { - ClutterActorBox box = { 0, }; - - clutter_actor_get_allocation_box (child, &box); - - box.x1 -= 2; - box.y1 -= 2; - box.x2 += 2; - box.y2 += 2; - - cogl_framebuffer_draw_rectangle (framebuffer, pipeline, - box.x1, box.y1, box.x2, box.y2); - } - - clutter_actor_paint (child, paint_context); - } - - cogl_object_unref (pipeline); -} - -static void -key_group_class_init (KeyGroupClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); - ClutterBindingPool *binding_pool; - - actor_class->paint = key_group_paint; - actor_class->key_press_event = key_group_key_press; - - group_signals[ACTIVATE] = - g_signal_new (g_intern_static_string ("activate"), - G_OBJECT_CLASS_TYPE (gobject_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (KeyGroupClass, activate), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - CLUTTER_TYPE_ACTOR); - - binding_pool = clutter_binding_pool_get_for_class (klass); - - clutter_binding_pool_install_action (binding_pool, "move-right", - CLUTTER_KEY_Right, 0, - G_CALLBACK (key_group_action_move_right), - NULL, NULL); - clutter_binding_pool_install_action (binding_pool, "move-left", - CLUTTER_KEY_Left, 0, - G_CALLBACK (key_group_action_move_left), - NULL, NULL); - clutter_binding_pool_install_action (binding_pool, "activate", - CLUTTER_KEY_Return, 0, - G_CALLBACK (key_group_action_activate), - NULL, NULL); - clutter_binding_pool_install_action (binding_pool, "activate", - CLUTTER_KEY_KP_Enter, 0, - G_CALLBACK (key_group_action_activate), - NULL, NULL); - clutter_binding_pool_install_action (binding_pool, "activate", - CLUTTER_KEY_ISO_Enter, 0, - G_CALLBACK (key_group_action_activate), - NULL, NULL); -} - -static void -key_group_init (KeyGroup *self) -{ - self->selected_index = -1; -} - -static void -init_event (ClutterKeyEvent *event) -{ - event->type = CLUTTER_KEY_PRESS; - event->time = 0; /* not needed */ - event->flags = CLUTTER_EVENT_FLAG_SYNTHETIC; - event->stage = NULL; /* not needed */ - event->source = NULL; /* not needed */ - event->modifier_state = 0; - event->hardware_keycode = 0; /* not needed */ -} - -static void -send_keyval (KeyGroup *group, int keyval) -{ - ClutterKeyEvent event; - - init_event (&event); - event.keyval = keyval; - event.unicode_value = 0; /* should be ignored for cursor keys etc. */ - - clutter_actor_event (CLUTTER_ACTOR (group), (ClutterEvent *) &event, FALSE); -} - -static void -on_activate (KeyGroup *key_group, - ClutterActor *child, - gpointer data) -{ - gint _index = GPOINTER_TO_INT (data); - - g_assert_cmpint (key_group->selected_index, ==, _index); -} - -static void -binding_pool (void) -{ - KeyGroup *key_group = g_object_new (TYPE_KEY_GROUP, NULL); - g_object_ref_sink (key_group); - - clutter_actor_add_child (CLUTTER_ACTOR (key_group), - g_object_new (CLUTTER_TYPE_ACTOR, - "width", 50.0, - "height", 50.0, - "x", 0.0, "y", 0.0, - NULL)); - clutter_actor_add_child (CLUTTER_ACTOR (key_group), - g_object_new (CLUTTER_TYPE_ACTOR, - "width", 50.0, - "height", 50.0, - "x", 75.0, "y", 0.0, - NULL)); - clutter_actor_add_child (CLUTTER_ACTOR (key_group), - g_object_new (CLUTTER_TYPE_ACTOR, - "width", 50.0, - "height", 50.0, - "x", 150.0, "y", 0.0, - NULL)); - - g_assert_cmpint (key_group->selected_index, ==, -1); - - send_keyval (key_group, CLUTTER_KEY_Left); - g_assert_cmpint (key_group->selected_index, ==, 2); - - send_keyval (key_group, CLUTTER_KEY_Left); - g_assert_cmpint (key_group->selected_index, ==, 1); - - send_keyval (key_group, CLUTTER_KEY_Right); - g_assert_cmpint (key_group->selected_index, ==, 2); - - send_keyval (key_group, CLUTTER_KEY_Right); - g_assert_cmpint (key_group->selected_index, ==, 0); - - g_signal_connect (key_group, - "activate", G_CALLBACK (on_activate), - GINT_TO_POINTER (0)); - - send_keyval (key_group, CLUTTER_KEY_Return); - - clutter_actor_destroy (CLUTTER_ACTOR (key_group)); -} - -CLUTTER_TEST_SUITE ( - CLUTTER_TEST_UNIT ("/binding-pool", binding_pool) -) diff --git a/src/tests/clutter/conform/cally-text.c b/src/tests/clutter/conform/cally-text.c deleted file mode 100644 index 1644181f5..000000000 --- a/src/tests/clutter/conform/cally-text.c +++ /dev/null @@ -1,338 +0,0 @@ -#include -#include -#include - -#include "test-conform-common.h" - -#define TEST_FONT "Sans 10" - -typedef struct _CallbackData CallbackData; - -struct _CallbackData -{ - ClutterActor *stage; - ClutterActor *label; - gint offset; - gboolean test_failed; - - gint extents_x; - gint extents_y; - gint extents_width; - gint extents_height; - GSList *run_attributes; - GSList *default_attributes; - CallbackData *next; -}; - - -static gint -attribute_lookup_func (gconstpointer data, - gconstpointer user_data) -{ - AtkAttribute *lookup_attr = (AtkAttribute*) user_data; - AtkAttribute *at = (AtkAttribute *) data; - if (!data) - return -1; - if (!g_strcmp0 (at->name, lookup_attr->name)) - return g_strcmp0 (at->value, lookup_attr->value); - return -1; -} - -/* check l1 is a sub-set of l2 */ -static gboolean -compare_lists (GSList* l1, GSList* l2) -{ - gboolean fail = FALSE; - - if (l2 && !l1) - return TRUE; - - while (l1) - { - AtkAttribute *at = (AtkAttribute *) l1->data; - GSList* result = g_slist_find_custom ((GSList*) l2, - (gconstpointer) at, - attribute_lookup_func); - if (!result) - { - fail = TRUE; - break; - } - l1 = g_slist_next (l1); - } - - return fail; -} - -static void -dump_attribute_set (AtkAttributeSet *at_set) -{ - GSList *attrs = (GSList*) at_set; - - while (attrs) { - AtkAttribute *at = (AtkAttribute *) attrs->data; - g_print ("text attribute %s = %s\n", at->name, at->value); - attrs = g_slist_next (attrs); - } - -} - -static gboolean -check_result (CallbackData *data) -{ - gboolean fail = FALSE; - gchar *text = NULL; - const gchar *expected_text = NULL; - AtkObject *object = NULL; - AtkText *cally_text = NULL; - gunichar unichar; - gunichar expected_char; - gint x, y, width, height; - gint pos; - AtkAttributeSet *at_set = NULL; - GSList *attrs; - gint start = -1; - gint end = -1; - - object = atk_gobject_accessible_for_object (G_OBJECT (data->label)); - cally_text = ATK_TEXT (object); - - if (!cally_text) { - g_print("no text\n"); - return TRUE; - } - - text = atk_text_get_text (cally_text, 0, -1); - expected_text = clutter_text_get_text (CLUTTER_TEXT (data->label)); - - if (g_strcmp0 (expected_text, text) != 0) - { - if (!g_test_quiet ()) - g_print ("text value differs %s vs %s\n", expected_text, text); - fail = TRUE; - } - - unichar = atk_text_get_character_at_offset (cally_text, data->offset); - expected_char = g_utf8_get_char (g_utf8_offset_to_pointer (text, data->offset)); - if (expected_char != unichar) - { - if (!g_test_quiet ()) - g_print ("text af offset differs\n"); - fail = TRUE; - } - - atk_text_get_character_extents (cally_text, data->offset, &x, &y, &width, &height, - ATK_XY_WINDOW); - if (x != data->extents_x) - { - if (!g_test_quiet ()) - g_print ("extents x position at index 0 differs (current value=%d)\n", x); - fail = TRUE; - } - if (y != data->extents_y) - { - if (!g_test_quiet ()) - g_print ("extents y position at index 0 differs (current value=%d)\n", y); - fail = TRUE; - } - if (width != data->extents_width) - { - if (!g_test_quiet ()) - g_print ("extents width at index 0 differs (current value=%d)\n", width); - fail = TRUE; - } - if (height != data->extents_height) - { - if (!g_test_quiet ()) - g_print ("extents height at index 0 differs (current value=%d)\n", height); - fail = TRUE; - } - - pos = atk_text_get_offset_at_point (cally_text, x, y, ATK_XY_WINDOW); - if (pos != data->offset) - { - if (!g_test_quiet ()) - g_print ("offset at position (%d, %d) differs (current value=%d)\n", x, - y, pos); - fail = TRUE; - } - - at_set = atk_text_get_run_attributes (cally_text, 0, - &start, &end); - if (start != 0) - { - if (!g_test_quiet ()) - g_print ("run attributes start offset is not 0: %d\n", start); - fail = TRUE; - } - if (end != g_utf8_strlen (text, -1)) - { - if (!g_test_quiet ()) - g_print ("run attributes end offset is not text length: %d\n", end); - fail = TRUE; - } - - attrs = (GSList*) at_set; - fail = compare_lists (attrs, data->run_attributes); - if (fail && !g_test_quiet ()) - { - g_print ("run attributes mismatch\n"); - dump_attribute_set (attrs); - } - - at_set = atk_text_get_default_attributes (cally_text); - attrs = (GSList*) at_set; - fail = compare_lists (attrs, data->default_attributes); - if (fail && !g_test_quiet ()) - { - g_print ("default attributes mismatch\n"); - dump_attribute_set (attrs); - } - - g_free (text); - text = NULL; - - if (fail) - { - if (!g_test_quiet ()) - g_print ("FAIL\n"); - data->test_failed = TRUE; - } - else if (!g_test_quiet ()) - g_print ("pass\n"); - - return fail; -} - -static gboolean -do_tests (CallbackData *data) -{ - while (data) - { - gboolean result = check_result (data); - g_assert (result == FALSE); - data = data->next; - } - - clutter_test_quit (); - - return FALSE; -} - -static GSList* -build_attribute_set (const gchar* first_attribute, ...) -{ - AtkAttributeSet *return_set = g_slist_alloc (); - va_list args; - const gchar *name; - const gchar *value; - gint i = 0; - - value = first_attribute; - va_start (args, first_attribute); - - while (value) - { - if ((i> 0) && (i % 2 != 0)) - { - AtkAttribute *at = g_malloc (sizeof (AtkAttribute)); - at->name = g_strdup (name); - at->value = g_strdup (value); - return_set = g_slist_prepend (return_set, at); - } - i++; - name = g_strdup (value); - value = va_arg (args, gchar*); - } - va_end (args); - return return_set; -} - -void -cally_text (void) -{ - CallbackData data; - CallbackData data1; - GSList* default_attributes = build_attribute_set ("left-margin", "0", - "right-margin", "0", - "indent", "0", - "invisible", "false", - "editable", "false", - "pixels-above-lines", "0", - "pixels-below-lines", "0", - "pixels-inside-wrap", "0", - "bg-full-height", "0", - "bg-stipple", "false", - "fg-stipple", "false", - "fg-color", "0,0,0", - "wrap-mode", "word", - "justification", "left", - "size", "10", - "weight", "400", - "family-name", "Sans", - "stretch", "normal", - "variant", "normal", - "style", "normal", - "language", "en-us", - "direction", "ltr", - NULL); - - memset (&data, 0, sizeof (data)); - - data.stage = clutter_test_get_stage (); - - data.default_attributes = default_attributes; - data.run_attributes = build_attribute_set ("fg-color", "0,0,0", NULL); - - data.label = clutter_text_new_with_text (TEST_FONT, "Lorem ipsum dolor sit amet"); - - clutter_container_add (CLUTTER_CONTAINER (data.stage), data.label, NULL); - data.offset = 6; - data.extents_x = 64; - data.extents_y = 99; - data.extents_width = 3; - data.extents_height = 17; - clutter_actor_set_position (data.label, 20, 100); - - memset (&data1, 0, sizeof (data1)); - data1.stage = data.stage; - data1.default_attributes = default_attributes; - data1.run_attributes = build_attribute_set ("bg-color", "0,65535,0", - "fg-color", "65535,65535,0", - "strikethrough", "true", NULL); - - data1.label = clutter_text_new_with_text (TEST_FONT, ""); - clutter_text_set_markup (CLUTTER_TEXT(data1.label), "Lorem ipsum dolor sit amet"); - - clutter_container_add (CLUTTER_CONTAINER (data1.stage), data1.label, NULL); - data1.offset = 10; - data1.extents_x = 90; - data1.extents_y = 199; - data1.extents_width = 13; - data1.extents_height = 17; - clutter_actor_set_position (data1.label, 20, 200); - data.next = &data1; - - clutter_actor_show (data.stage); - clutter_threads_add_idle ((GSourceFunc) do_tests, &data); - clutter_test_main (); - - clutter_actor_destroy (data.stage); - - if (!g_test_quiet ()) - g_print ("\nOverall result: "); - - if (!g_test_quiet ()) - { - if (data.test_failed) - g_print ("FAIL\n"); - else - g_print ("pass\n"); - } - else - { - g_assert (data.test_failed != TRUE); - g_assert (data1.test_failed != TRUE); - } -} - diff --git a/src/tests/clutter/conform/color.c b/src/tests/clutter/conform/color.c deleted file mode 100644 index b66d5f63a..000000000 --- a/src/tests/clutter/conform/color.c +++ /dev/null @@ -1,321 +0,0 @@ -#include - -#include "tests/clutter-test-utils.h" - -static void -color_hls_roundtrip (void) -{ - ClutterColor color; - gfloat hue, luminance, saturation; - - /* test luminance only */ - clutter_color_from_string (&color, "#7f7f7f"); - g_assert_cmpuint (color.red, ==, 0x7f); - g_assert_cmpuint (color.green, ==, 0x7f); - g_assert_cmpuint (color.blue, ==, 0x7f); - - clutter_color_to_hls (&color, &hue, &luminance, &saturation); - g_assert_cmpfloat (hue, ==, 0.0); - g_assert (luminance >= 0.0 && luminance <= 1.0); - g_assert_cmpfloat (saturation, ==, 0.0); - if (!g_test_quiet ()) - { - g_print ("RGB = { %x, %x, %x }, HLS = { %.2f, %.2f, %.2f }\n", - color.red, - color.green, - color.blue, - hue, - luminance, - saturation); - } - - color.red = color.green = color.blue = 0; - clutter_color_from_hls (&color, hue, luminance, saturation); - - g_assert_cmpuint (color.red, ==, 0x7f); - g_assert_cmpuint (color.green, ==, 0x7f); - g_assert_cmpuint (color.blue, ==, 0x7f); - - /* full conversion */ - clutter_color_from_string (&color, "#7f8f7f"); - color.alpha = 255; - - g_assert_cmpuint (color.red, ==, 0x7f); - g_assert_cmpuint (color.green, ==, 0x8f); - g_assert_cmpuint (color.blue, ==, 0x7f); - - clutter_color_to_hls (&color, &hue, &luminance, &saturation); - g_assert (hue >= 0.0 && hue < 360.0); - g_assert (luminance >= 0.0 && luminance <= 1.0); - g_assert (saturation >= 0.0 && saturation <= 1.0); - if (!g_test_quiet ()) - { - g_print ("RGB = { %x, %x, %x }, HLS = { %.2f, %.2f, %.2f }\n", - color.red, - color.green, - color.blue, - hue, - luminance, - saturation); - } - - color.red = color.green = color.blue = 0; - clutter_color_from_hls (&color, hue, luminance, saturation); - - g_assert_cmpuint (color.red, ==, 0x7f); - g_assert_cmpuint (color.green, ==, 0x8f); - g_assert_cmpuint (color.blue, ==, 0x7f); - - /* the alpha channel should be untouched */ - g_assert_cmpuint (color.alpha, ==, 255); -} - -static void -color_from_string_invalid (void) -{ - ClutterColor color; - - g_assert (!clutter_color_from_string (&color, "ff0000ff")); - g_assert (!clutter_color_from_string (&color, "#decaffbad")); - g_assert (!clutter_color_from_string (&color, "ponies")); - g_assert (!clutter_color_from_string (&color, "rgb(255, 0, 0, 0)")); - g_assert (!clutter_color_from_string (&color, "rgba(1.0, 0, 0)")); - g_assert (!clutter_color_from_string (&color, "hsl(100, 0, 0)")); - g_assert (!clutter_color_from_string (&color, "hsla(10%, 0%, 50%)")); - g_assert (!clutter_color_from_string (&color, "hsla(100%, 0%, 50%, 20%)")); - g_assert (!clutter_color_from_string (&color, "hsla(0.5, 0.9, 0.2, 0.4)")); -} - -static void -color_from_string_valid (void) -{ - ClutterColor color; - - g_assert (clutter_color_from_string (&color, "#ff0000ff")); - if (!g_test_quiet ()) - { - g_print ("color = { %x, %x, %x, %x }, expected = { 0xff, 0, 0, 0xff }\n", - color.red, - color.green, - color.blue, - color.alpha); - } - g_assert_cmpuint (color.red, ==, 0xff); - g_assert_cmpuint (color.green, ==, 0); - g_assert_cmpuint (color.blue, ==, 0); - g_assert_cmpuint (color.alpha, ==, 0xff); - - g_assert (clutter_color_from_string (&color, "#0f0f")); - if (!g_test_quiet ()) - { - g_print ("color = { %x, %x, %x, %x }, expected = { 0, 0xff, 0, 0xff }\n", - color.red, - color.green, - color.blue, - color.alpha); - } - g_assert_cmpuint (color.red, ==, 0); - g_assert_cmpuint (color.green, ==, 0xff); - g_assert_cmpuint (color.blue, ==, 0); - g_assert_cmpuint (color.alpha, ==, 0xff); - - g_assert (clutter_color_from_string (&color, "#0000ff")); - if (!g_test_quiet ()) - { - g_print ("color = { %x, %x, %x, %x }, expected = { 0, 0, 0xff, 0xff }\n", - color.red, - color.green, - color.blue, - color.alpha); - } - g_assert_cmpuint (color.red, ==, 0); - g_assert_cmpuint (color.green, ==, 0); - g_assert_cmpuint (color.blue, ==, 0xff); - g_assert_cmpuint (color.alpha, ==, 0xff); - - g_assert (clutter_color_from_string (&color, "#abc")); - if (!g_test_quiet ()) - { - g_print ("color = { %x, %x, %x, %x }, expected = { 0xaa, 0xbb, 0xcc, 0xff }\n", - color.red, - color.green, - color.blue, - color.alpha); - } - g_assert_cmpuint (color.red, ==, 0xaa); - g_assert_cmpuint (color.green, ==, 0xbb); - g_assert_cmpuint (color.blue, ==, 0xcc); - g_assert_cmpuint (color.alpha, ==, 0xff); - - g_assert (clutter_color_from_string (&color, "#123abc")); - if (!g_test_quiet ()) - { - g_print ("color = { %x, %x, %x, %x }, expected = { 0x12, 0x3a, 0xbc, 0xff }\n", - color.red, - color.green, - color.blue, - color.alpha); - } - g_assert (color.red == 0x12); - g_assert (color.green == 0x3a); - g_assert (color.blue == 0xbc); - g_assert (color.alpha == 0xff); - - g_assert (clutter_color_from_string (&color, "rgb(255, 128, 64)")); - if (!g_test_quiet ()) - { - g_print ("color = { %x, %x, %x, %x }, expected = { 255, 128, 64, 255 }\n", - color.red, - color.green, - color.blue, - color.alpha); - } - g_assert_cmpuint (color.red, ==, 255); - g_assert_cmpuint (color.green, ==, 128); - g_assert_cmpuint (color.blue, ==, 64); - g_assert_cmpuint (color.alpha, ==, 255); - - g_assert (clutter_color_from_string (&color, "rgba ( 30%, 0, 25%, 0.5 ) ")); - if (!g_test_quiet ()) - { - g_print ("color = { %x, %x, %x, %x }, expected = { %.1f, 0, %.1f, 128 }\n", - color.red, - color.green, - color.blue, - color.alpha, - CLAMP (255.0 / 100.0 * 30.0, 0, 255), - CLAMP (255.0 / 100.0 * 25.0, 0, 255)); - } - g_assert_cmpuint (color.red, ==, (255.0 / 100.0 * 30.0)); - g_assert_cmpuint (color.green, ==, 0); - g_assert_cmpuint (color.blue, ==, (255.0 / 100.0 * 25.0)); - g_assert_cmpuint (color.alpha, ==, 127); - - g_assert (clutter_color_from_string (&color, "rgb( 50%, -50%, 150% )")); - if (!g_test_quiet ()) - { - g_print ("color = { %x, %x, %x, %x }, expected = { 127, 0, 255, 255 }\n", - color.red, - color.green, - color.blue, - color.alpha); - } - g_assert_cmpuint (color.red, ==, 127); - g_assert_cmpuint (color.green, ==, 0); - g_assert_cmpuint (color.blue, ==, 255); - g_assert_cmpuint (color.alpha, ==, 255); - - g_assert (clutter_color_from_string (&color, "hsl( 0, 100%, 50% )")); - if (!g_test_quiet ()) - { - g_print ("color = { %x, %x, %x, %x }, expected = { 255, 0, 0, 255 }\n", - color.red, - color.green, - color.blue, - color.alpha); - } - g_assert_cmpuint (color.red, ==, 255); - g_assert_cmpuint (color.green, ==, 0); - g_assert_cmpuint (color.blue, ==, 0); - g_assert_cmpuint (color.alpha, ==, 255); - - g_assert (clutter_color_from_string (&color, "hsl( 0, 100%, 50% )")); - - g_assert (clutter_color_from_string (&color, "hsla( 0, 100%, 50%, 0.5 )")); - if (!g_test_quiet ()) - { - g_print ("color = { %x, %x, %x, %x }, expected = { 255, 0, 0, 127 }\n", - color.red, - color.green, - color.blue, - color.alpha); - } - g_assert_cmpuint (color.red, ==, 255); - g_assert_cmpuint (color.green, ==, 0); - g_assert_cmpuint (color.blue, ==, 0); - g_assert_cmpuint (color.alpha, ==, 127); - - g_test_bug ("662818"); - g_assert (clutter_color_from_string (&color, "hsla(0,100%,50% , 0.5)")); -} - -static void -color_to_string (void) -{ - ClutterColor color; - gchar *str; - - color.red = 0xcc; - color.green = 0xcc; - color.blue = 0xcc; - color.alpha = 0x22; - - str = clutter_color_to_string (&color); - g_assert_cmpstr (str, ==, "#cccccc22"); - - g_free (str); -} - -static void -color_operators (void) -{ - ClutterColor op1, op2; - ClutterColor res; - - clutter_color_from_pixel (&op1, 0xff0000ff); - g_assert_cmpuint (op1.red, ==, 0xff); - g_assert_cmpuint (op1.green, ==, 0); - g_assert_cmpuint (op1.blue, ==, 0); - g_assert_cmpuint (op1.alpha, ==, 0xff); - - clutter_color_from_pixel (&op2, 0x00ff00ff); - g_assert_cmpuint (op2.red, ==, 0); - g_assert_cmpuint (op2.green, ==, 0xff); - g_assert_cmpuint (op2.blue, ==, 0); - g_assert_cmpuint (op2.alpha, ==, 0xff); - - if (!g_test_quiet ()) - g_print ("Adding %x, %x; expected result: %x\n", - clutter_color_to_pixel (&op1), - clutter_color_to_pixel (&op2), - 0xffff00ff); - - clutter_color_add (&op1, &op2, &res); - g_assert_cmpuint (clutter_color_to_pixel (&res), ==, 0xffff00ff); - - if (!g_test_quiet ()) - g_print ("Checking alpha channel on color add\n"); - - op1.alpha = 0xdd; - op2.alpha = 0xcc; - clutter_color_add (&op1, &op2, &res); - g_assert_cmpuint (clutter_color_to_pixel (&res), ==, 0xffff00dd); - - clutter_color_from_pixel (&op1, 0xffffffff); - clutter_color_from_pixel (&op2, 0xff00ffff); - - if (!g_test_quiet ()) - g_print ("Subtracting %x, %x; expected result: %x\n", - clutter_color_to_pixel (&op1), - clutter_color_to_pixel (&op2), - 0x00ff00ff); - - clutter_color_subtract (&op1, &op2, &res); - g_assert_cmpuint (clutter_color_to_pixel (&res), ==, 0x00ff00ff); - - if (!g_test_quiet ()) - g_print ("Checking alpha channel on color subtract\n"); - - op1.alpha = 0xdd; - op2.alpha = 0xcc; - clutter_color_subtract (&op1, &op2, &res); - g_assert_cmpuint (clutter_color_to_pixel (&res), ==, 0x00ff00cc); -} - -CLUTTER_TEST_SUITE ( - CLUTTER_TEST_UNIT ("/color/hls-roundtrip", color_hls_roundtrip) - CLUTTER_TEST_UNIT ("/color/from-string/invalid", color_from_string_invalid) - CLUTTER_TEST_UNIT ("/color/from-string/valid", color_from_string_valid) - CLUTTER_TEST_UNIT ("/color/to-string", color_to_string) - CLUTTER_TEST_UNIT ("/color/operators", color_operators) -) diff --git a/src/tests/clutter/conform/frame-clock-timeline.c b/src/tests/clutter/conform/frame-clock-timeline.c deleted file mode 100644 index 0f9f04d79..000000000 --- a/src/tests/clutter/conform/frame-clock-timeline.c +++ /dev/null @@ -1,209 +0,0 @@ -#include "clutter/clutter.h" -#include "tests/clutter-test-utils.h" - -static const float refresh_rate = 60.0; - -static ClutterFrameResult -timeline_frame_clock_frame (ClutterFrameClock *frame_clock, - int64_t frame_count, - int64_t time_us, - gpointer user_data) -{ - ClutterFrameInfo frame_info; - - frame_info = (ClutterFrameInfo) { - .presentation_time = g_get_monotonic_time (), - .refresh_rate = refresh_rate, - .flags = CLUTTER_FRAME_INFO_FLAG_NONE, - .sequence = 0, - }; - clutter_frame_clock_notify_presented (frame_clock, &frame_info); - clutter_frame_clock_schedule_update (frame_clock); - - return CLUTTER_FRAME_RESULT_PENDING_PRESENTED; -} - -static const ClutterFrameListenerIface timeline_frame_listener_iface = { - .frame = timeline_frame_clock_frame, -}; - -static void -on_marker_reached (ClutterTimeline *timeline, - const char *marker_name, - unsigned int frame_number, - gboolean *marker_reached) -{ - *marker_reached = TRUE; -} - -static void -on_timeline_new_frame (ClutterTimeline *timeline, - int time_ms, - int *frame_counter) -{ - (*frame_counter)++; -} - -static void -on_timeline_completed (ClutterTimeline *timeline, - GMainLoop *main_loop) -{ - g_main_loop_quit (main_loop); -} - -static void -frame_clock_timeline_basic (void) -{ - GMainLoop *main_loop; - ClutterFrameClock *frame_clock; - ClutterTimeline *timeline; - gboolean marker1_reached; - int frame_counter; - int64_t before_us; - int64_t after_us; - - main_loop = g_main_loop_new (NULL, FALSE); - frame_clock = clutter_frame_clock_new (refresh_rate, - 0, - &timeline_frame_listener_iface, - NULL); - g_object_add_weak_pointer (G_OBJECT (frame_clock), (gpointer *) &frame_clock); - - timeline = g_object_new (CLUTTER_TYPE_TIMELINE, - "duration", 1000, - "frame-clock", frame_clock, - NULL); - g_object_add_weak_pointer (G_OBJECT (timeline), (gpointer *) &timeline); - - clutter_timeline_add_marker_at_time (timeline, "marker1", 500); - - marker1_reached = FALSE; - frame_counter = 0; - - g_signal_connect (timeline, "marker-reached::marker1", - G_CALLBACK (on_marker_reached), - &marker1_reached); - g_signal_connect (timeline, "new-frame", - G_CALLBACK (on_timeline_new_frame), - &frame_counter); - g_signal_connect (timeline, "completed", - G_CALLBACK (on_timeline_completed), - main_loop); - - clutter_timeline_start (timeline); - - before_us = g_get_monotonic_time (); - - g_main_loop_run (main_loop); - - after_us = g_get_monotonic_time (); - - g_assert_cmpint (after_us - before_us, - >=, - ms2us (clutter_timeline_get_duration (timeline))); - - g_assert_true (marker1_reached); - - /* Just check that we got at least a few frames. Require too high and we'll be - * flaky. - */ - g_assert_cmpint (frame_counter, >, 20); - - g_main_loop_unref (main_loop); - g_object_unref (timeline); - g_assert_null (timeline); - clutter_frame_clock_destroy (frame_clock); - g_assert_null (frame_clock); -} - -static void -on_switch_reached (ClutterTimeline *timeline, - const char *marker_name, - unsigned int frame_number, - ClutterFrameClock *new_frame_clock) -{ - ClutterFrameClock *old_frame_clock; - - old_frame_clock = clutter_timeline_get_frame_clock (timeline); - clutter_frame_clock_inhibit (old_frame_clock); - - clutter_timeline_set_frame_clock (timeline, new_frame_clock); -} - -static void -frame_clock_timeline_switch (void) -{ - GMainLoop *main_loop; - ClutterFrameClock *frame_clock2; - ClutterFrameClock *frame_clock1; - ClutterTimeline *timeline; - int frame_counter; - int64_t before_us; - int64_t after_us; - - main_loop = g_main_loop_new (NULL, FALSE); - - frame_clock1 = clutter_frame_clock_new (refresh_rate, - 0, - &timeline_frame_listener_iface, - NULL); - g_object_add_weak_pointer (G_OBJECT (frame_clock1), (gpointer *) &frame_clock1); - frame_clock2 = clutter_frame_clock_new (refresh_rate, - 0, - &timeline_frame_listener_iface, - NULL); - g_object_add_weak_pointer (G_OBJECT (frame_clock2), (gpointer *) &frame_clock2); - - timeline = g_object_new (CLUTTER_TYPE_TIMELINE, - "duration", 1000, - "frame-clock", frame_clock1, - NULL); - g_object_add_weak_pointer (G_OBJECT (timeline), (gpointer *) &timeline); - - clutter_timeline_add_marker_at_time (timeline, "switch", 500); - - frame_counter = 0; - - g_signal_connect (timeline, "marker-reached::switch", - G_CALLBACK (on_switch_reached), - frame_clock2); - g_signal_connect (timeline, "new-frame", - G_CALLBACK (on_timeline_new_frame), - &frame_counter); - g_signal_connect (timeline, "completed", - G_CALLBACK (on_timeline_completed), - main_loop); - - clutter_timeline_start (timeline); - - before_us = g_get_monotonic_time (); - - g_main_loop_run (main_loop); - - after_us = g_get_monotonic_time (); - - g_assert_cmpint (after_us - before_us, - >=, - ms2us (clutter_timeline_get_duration (timeline))); - - g_assert (clutter_timeline_get_frame_clock (timeline) == frame_clock2); - - /* The duration is 1s, with a 60hz clock, and we switch after 0.5s. To verify - * we continued to get frames, check that we have a bit more than half of the - * frames accounted for. - */ - g_assert_cmpint (frame_counter, >, 35); - - g_main_loop_unref (main_loop); - g_object_unref (timeline); - g_assert_null (timeline); - clutter_frame_clock_destroy (frame_clock1); - g_assert_null (frame_clock1); - clutter_frame_clock_destroy (frame_clock2); - g_assert_null (frame_clock2); -} - -CLUTTER_TEST_SUITE ( - CLUTTER_TEST_UNIT ("/frame-clock/timeline/basic", frame_clock_timeline_basic) - CLUTTER_TEST_UNIT ("/frame-clock/timeline/switch", frame_clock_timeline_switch) -) diff --git a/src/tests/clutter/conform/frame-clock.c b/src/tests/clutter/conform/frame-clock.c deleted file mode 100644 index 810c39a02..000000000 --- a/src/tests/clutter/conform/frame-clock.c +++ /dev/null @@ -1,846 +0,0 @@ -#include "clutter/clutter.h" -#include "tests/clutter-test-utils.h" - -static const float refresh_rate = 60.0; -static const int64_t refresh_interval_us = (int64_t) (0.5 + G_USEC_PER_SEC / - refresh_rate); - -static int64_t test_frame_count; -static int64_t expected_frame_count; - -typedef struct _FakeHwClock -{ - GSource source; - - ClutterFrameClock *frame_clock; - - int64_t next_presentation_time_us; - gboolean has_pending_present; -} FakeHwClock; - -typedef struct _FrameClockTest -{ - FakeHwClock *fake_hw_clock; - - GMainLoop *main_loop; -} FrameClockTest; - -static void -init_frame_info (ClutterFrameInfo *frame_info, - int64_t presentation_time_us) -{ - *frame_info = (ClutterFrameInfo) { - .presentation_time = presentation_time_us, - .refresh_rate = refresh_rate, - .flags = CLUTTER_FRAME_INFO_FLAG_NONE, - .sequence = 0, - }; -} - -static gboolean -fake_hw_clock_source_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data) -{ - FakeHwClock *fake_hw_clock = (FakeHwClock *) source; - ClutterFrameClock *frame_clock = fake_hw_clock->frame_clock; - - if (fake_hw_clock->has_pending_present) - { - ClutterFrameInfo frame_info; - - fake_hw_clock->has_pending_present = FALSE; - init_frame_info (&frame_info, g_source_get_time (source)); - clutter_frame_clock_notify_presented (frame_clock, &frame_info); - if (callback) - callback (user_data); - } - - fake_hw_clock->next_presentation_time_us += refresh_interval_us; - g_source_set_ready_time (source, fake_hw_clock->next_presentation_time_us); - - return G_SOURCE_CONTINUE; -} - -static GSourceFuncs fake_hw_clock_source_funcs = { - NULL, - NULL, - fake_hw_clock_source_dispatch, - NULL -}; - -static FakeHwClock * -fake_hw_clock_new (ClutterFrameClock *frame_clock, - GSourceFunc callback, - gpointer user_data) -{ - GSource *source; - FakeHwClock *fake_hw_clock; - - source = g_source_new (&fake_hw_clock_source_funcs, sizeof (FakeHwClock)); - fake_hw_clock = (FakeHwClock *) source; - fake_hw_clock->frame_clock = frame_clock; - - fake_hw_clock->next_presentation_time_us = - g_get_monotonic_time () + refresh_interval_us; - g_source_set_ready_time (source, fake_hw_clock->next_presentation_time_us); - g_source_set_callback (source, callback, user_data, NULL); - - return fake_hw_clock; -} - -static ClutterFrameResult -frame_clock_frame (ClutterFrameClock *frame_clock, - int64_t frame_count, - int64_t time_us, - gpointer user_data) -{ - FrameClockTest *test = user_data; - GMainLoop *main_loop = test->main_loop; - - g_assert_cmpint (frame_count, ==, expected_frame_count); - - expected_frame_count++; - - if (test_frame_count == 0) - { - g_main_loop_quit (main_loop); - return CLUTTER_FRAME_RESULT_IDLE; - } - else - { - test->fake_hw_clock->has_pending_present = TRUE; - } - - test_frame_count--; - - return CLUTTER_FRAME_RESULT_PENDING_PRESENTED; -} - -static const ClutterFrameListenerIface frame_listener_iface = { - .frame = frame_clock_frame, -}; - -static gboolean -schedule_update_hw_callback (gpointer user_data) -{ - ClutterFrameClock *frame_clock = user_data; - - clutter_frame_clock_schedule_update (frame_clock); - - return G_SOURCE_CONTINUE; -} - -static void -frame_clock_schedule_update (void) -{ - FrameClockTest test; - ClutterFrameClock *frame_clock; - int64_t before_us; - int64_t after_us; - GSource *source; - FakeHwClock *fake_hw_clock; - - test_frame_count = 10; - expected_frame_count = 0; - - test.main_loop = g_main_loop_new (NULL, FALSE); - frame_clock = clutter_frame_clock_new (refresh_rate, - 0, - &frame_listener_iface, - &test); - - fake_hw_clock = fake_hw_clock_new (frame_clock, - schedule_update_hw_callback, - frame_clock); - source = &fake_hw_clock->source; - g_source_attach (source, NULL); - - test.fake_hw_clock = fake_hw_clock; - - before_us = g_get_monotonic_time (); - - clutter_frame_clock_schedule_update (frame_clock); - g_main_loop_run (test.main_loop); - - after_us = g_get_monotonic_time (); - - g_assert_cmpint (after_us - before_us, >, 10 * refresh_interval_us); - - g_main_loop_unref (test.main_loop); - - clutter_frame_clock_destroy (frame_clock); - g_source_destroy (source); - g_source_unref (source); -} - -static gboolean -schedule_update_idle (gpointer user_data) -{ - ClutterFrameClock *frame_clock = user_data; - - clutter_frame_clock_schedule_update (frame_clock); - - return G_SOURCE_REMOVE; -} - -static ClutterFrameResult -immediate_frame_clock_frame (ClutterFrameClock *frame_clock, - int64_t frame_count, - int64_t time_us, - gpointer user_data) -{ - GMainLoop *main_loop = user_data; - ClutterFrameInfo frame_info; - - g_assert_cmpint (frame_count, ==, expected_frame_count); - - expected_frame_count++; - - if (test_frame_count == 0) - { - g_main_loop_quit (main_loop); - return CLUTTER_FRAME_RESULT_IDLE; - } - - test_frame_count--; - - init_frame_info (&frame_info, g_get_monotonic_time ()); - clutter_frame_clock_notify_presented (frame_clock, &frame_info); - g_idle_add (schedule_update_idle, frame_clock); - - return CLUTTER_FRAME_RESULT_PENDING_PRESENTED; -} - -static const ClutterFrameListenerIface immediate_frame_listener_iface = { - .frame = immediate_frame_clock_frame, -}; - -static void -frame_clock_immediate_present (void) -{ - GMainLoop *main_loop; - ClutterFrameClock *frame_clock; - int64_t before_us; - int64_t after_us; - - test_frame_count = 10; - expected_frame_count = 0; - - main_loop = g_main_loop_new (NULL, FALSE); - frame_clock = clutter_frame_clock_new (refresh_rate, - 0, - &immediate_frame_listener_iface, - main_loop); - - before_us = g_get_monotonic_time (); - - clutter_frame_clock_schedule_update (frame_clock); - g_main_loop_run (main_loop); - - after_us = g_get_monotonic_time (); - - /* The initial frame will only be delayed by 2 ms, so we are checking one - * less. - */ - g_assert_cmpint (after_us - before_us, >, 9 * refresh_interval_us); - - g_main_loop_unref (main_loop); - clutter_frame_clock_destroy (frame_clock); -} - -static gboolean -schedule_update_timeout (gpointer user_data) -{ - ClutterFrameClock *frame_clock = user_data; - - clutter_frame_clock_schedule_update (frame_clock); - - return G_SOURCE_REMOVE; -} - -static ClutterFrameResult -delayed_damage_frame_clock_frame (ClutterFrameClock *frame_clock, - int64_t frame_count, - int64_t time_us, - gpointer user_data) -{ - FrameClockTest *test = user_data; - GMainLoop *main_loop = test->main_loop; - - g_assert_cmpint (frame_count, ==, expected_frame_count); - - expected_frame_count++; - - if (test_frame_count == 0) - { - g_main_loop_quit (main_loop); - return CLUTTER_FRAME_RESULT_IDLE; - } - else - { - test->fake_hw_clock->has_pending_present = TRUE; - } - - test_frame_count--; - - g_timeout_add (100, schedule_update_timeout, frame_clock); - - return CLUTTER_FRAME_RESULT_PENDING_PRESENTED; -} - -static const ClutterFrameListenerIface delayed_damage_frame_listener_iface = { - .frame = delayed_damage_frame_clock_frame, -}; - -static void -frame_clock_delayed_damage (void) -{ - FrameClockTest test; - ClutterFrameClock *frame_clock; - int64_t before_us; - int64_t after_us; - FakeHwClock *fake_hw_clock; - GSource *source; - - test_frame_count = 2; - expected_frame_count = 0; - - test.main_loop = g_main_loop_new (NULL, FALSE); - frame_clock = clutter_frame_clock_new (refresh_rate, - 0, - &delayed_damage_frame_listener_iface, - &test); - - fake_hw_clock = fake_hw_clock_new (frame_clock, NULL, NULL); - source = &fake_hw_clock->source; - g_source_attach (source, NULL); - - test.fake_hw_clock = fake_hw_clock; - - before_us = g_get_monotonic_time (); - - clutter_frame_clock_schedule_update (frame_clock); - g_main_loop_run (test.main_loop); - - after_us = g_get_monotonic_time (); - - g_assert_cmpint (after_us - before_us, >, 100000 + refresh_interval_us); - - g_main_loop_unref (test.main_loop); - clutter_frame_clock_destroy (frame_clock); - g_source_destroy (source); - g_source_unref (source); -} - -static ClutterFrameResult -no_damage_frame_clock_frame (ClutterFrameClock *frame_clock, - int64_t frame_count, - int64_t time_us, - gpointer user_data) -{ - g_assert_not_reached (); - - return CLUTTER_FRAME_RESULT_PENDING_PRESENTED; -} - -static const ClutterFrameListenerIface no_damage_frame_listener_iface = { - .frame = no_damage_frame_clock_frame, -}; - -static gboolean -quit_main_loop_idle (gpointer user_data) -{ - GMainLoop *main_loop = user_data; - - g_main_loop_quit (main_loop); - - return G_SOURCE_REMOVE; -} - -static void -frame_clock_no_damage (void) -{ - GMainLoop *main_loop; - ClutterFrameClock *frame_clock; - - test_frame_count = 10; - expected_frame_count = 0; - - main_loop = g_main_loop_new (NULL, FALSE); - frame_clock = clutter_frame_clock_new (refresh_rate, - 0, - &no_damage_frame_listener_iface, - NULL); - - g_timeout_add (100, quit_main_loop_idle, main_loop); - - g_main_loop_run (main_loop); - - g_main_loop_unref (main_loop); - clutter_frame_clock_destroy (frame_clock); -} - -typedef struct _UpdateNowFrameClockTest -{ - FrameClockTest base; - guint idle_source_id; -} UpdateNowFrameClockTest; - -static ClutterFrameResult -update_now_frame_clock_frame (ClutterFrameClock *frame_clock, - int64_t frame_count, - int64_t time_us, - gpointer user_data) -{ - UpdateNowFrameClockTest *test = user_data; - GMainLoop *main_loop = test->base.main_loop; - - g_assert_cmpint (frame_count, ==, expected_frame_count); - - expected_frame_count++; - - g_clear_handle_id (&test->idle_source_id, g_source_remove); - - if (test_frame_count == 0) - { - g_main_loop_quit (main_loop); - return CLUTTER_FRAME_RESULT_IDLE; - } - else - { - test->base.fake_hw_clock->has_pending_present = TRUE; - } - - test_frame_count--; - - return CLUTTER_FRAME_RESULT_PENDING_PRESENTED; -} - -static const ClutterFrameListenerIface update_now_frame_listener_iface = { - .frame = update_now_frame_clock_frame, -}; - -static gboolean -assert_not_reached_idle (gpointer user_data) -{ - g_assert_not_reached (); - return G_SOURCE_REMOVE; -} - -static gboolean -schedule_update_now_hw_callback (gpointer user_data) -{ - UpdateNowFrameClockTest *test = user_data; - ClutterFrameClock *frame_clock = test->base.fake_hw_clock->frame_clock; - - clutter_frame_clock_schedule_update_now (frame_clock); - g_assert (!test->idle_source_id); - test->idle_source_id = g_idle_add (assert_not_reached_idle, NULL); - - return G_SOURCE_CONTINUE; -} - -static void -frame_clock_schedule_update_now (void) -{ - UpdateNowFrameClockTest test = { 0 }; - ClutterFrameClock *frame_clock; - int64_t before_us; - int64_t after_us; - GSource *source; - FakeHwClock *fake_hw_clock; - - test_frame_count = 10; - expected_frame_count = 0; - - test.base.main_loop = g_main_loop_new (NULL, FALSE); - frame_clock = clutter_frame_clock_new (refresh_rate, - 0, - &update_now_frame_listener_iface, - &test); - - fake_hw_clock = fake_hw_clock_new (frame_clock, - schedule_update_now_hw_callback, - &test); - source = &fake_hw_clock->source; - g_source_attach (source, NULL); - - test.base.fake_hw_clock = fake_hw_clock; - - before_us = g_get_monotonic_time (); - - clutter_frame_clock_schedule_update (frame_clock); - g_main_loop_run (test.base.main_loop); - - after_us = g_get_monotonic_time (); - - g_assert_cmpint (after_us - before_us, >, 10 * refresh_interval_us); - - g_main_loop_unref (test.base.main_loop); - - clutter_frame_clock_destroy (frame_clock); - g_source_destroy (source); - g_source_unref (source); -} - -static void -before_frame_frame_clock_before_frame (ClutterFrameClock *frame_clock, - int64_t frame_count, - gpointer user_data) -{ - int64_t *expected_frame_count = user_data; - - g_assert_cmpint (*expected_frame_count, ==, frame_count); -} - -static ClutterFrameResult -before_frame_frame_clock_frame (ClutterFrameClock *frame_clock, - int64_t frame_count, - int64_t time_us, - gpointer user_data) -{ - int64_t *expected_frame_count = user_data; - ClutterFrameInfo frame_info; - - g_assert_cmpint (*expected_frame_count, ==, frame_count); - - (*expected_frame_count)++; - - init_frame_info (&frame_info, g_get_monotonic_time ()); - clutter_frame_clock_notify_presented (frame_clock, &frame_info); - clutter_frame_clock_schedule_update (frame_clock); - - return CLUTTER_FRAME_RESULT_PENDING_PRESENTED; -} - -static const ClutterFrameListenerIface before_frame_frame_listener_iface = { - .before_frame = before_frame_frame_clock_before_frame, - .frame = before_frame_frame_clock_frame, -}; - -static gboolean -quit_main_loop_timeout (gpointer user_data) -{ - GMainLoop *main_loop = user_data; - - g_main_loop_quit (main_loop); - - return G_SOURCE_REMOVE; -} - -static void -frame_clock_before_frame (void) -{ - GMainLoop *main_loop; - ClutterFrameClock *frame_clock; - - expected_frame_count = 0; - - main_loop = g_main_loop_new (NULL, FALSE); - frame_clock = clutter_frame_clock_new (refresh_rate, - 0, - &before_frame_frame_listener_iface, - &expected_frame_count); - - clutter_frame_clock_schedule_update (frame_clock); - g_timeout_add (100, quit_main_loop_timeout, main_loop); - g_main_loop_run (main_loop); - - /* We should have at least processed a couple of frames within 100 ms. */ - g_assert_cmpint (expected_frame_count, >, 2); - - g_main_loop_unref (main_loop); - clutter_frame_clock_destroy (frame_clock); -} - -typedef struct _InhibitTest -{ - GMainLoop *main_loop; - ClutterFrameClock *frame_clock; - - gboolean frame_count; - gboolean pending_inhibit; - gboolean pending_quit; -} InhibitTest; - -static ClutterFrameResult -inhibit_frame_clock_frame (ClutterFrameClock *frame_clock, - int64_t frame_count, - int64_t time_us, - gpointer user_data) -{ - InhibitTest *test = user_data; - ClutterFrameInfo frame_info; - - g_assert_cmpint (frame_count, ==, test->frame_count); - - test->frame_count++; - - init_frame_info (&frame_info, g_get_monotonic_time ()); - clutter_frame_clock_notify_presented (frame_clock, &frame_info); - clutter_frame_clock_schedule_update (frame_clock); - - if (test->pending_inhibit) - { - test->pending_inhibit = FALSE; - clutter_frame_clock_inhibit (frame_clock); - } - - clutter_frame_clock_schedule_update (frame_clock); - - if (test->pending_quit) - g_main_loop_quit (test->main_loop); - - return CLUTTER_FRAME_RESULT_PENDING_PRESENTED; -} - -static const ClutterFrameListenerIface inhibit_frame_listener_iface = { - .frame = inhibit_frame_clock_frame, -}; - -static gboolean -uninhibit_timeout (gpointer user_data) -{ - InhibitTest *test = user_data; - - g_assert_cmpint (test->frame_count, ==, 1); - - clutter_frame_clock_uninhibit (test->frame_clock); - test->pending_quit = TRUE; - - return G_SOURCE_REMOVE; -} - -static void -frame_clock_inhibit (void) -{ - InhibitTest test = { 0 }; - - expected_frame_count = 0; - - test.main_loop = g_main_loop_new (NULL, FALSE); - test.frame_clock = clutter_frame_clock_new (refresh_rate, - 0, - &inhibit_frame_listener_iface, - &test); - - test.pending_inhibit = TRUE; - - clutter_frame_clock_schedule_update (test.frame_clock); - g_timeout_add (100, uninhibit_timeout, &test); - g_main_loop_run (test.main_loop); - - g_assert_cmpint (test.frame_count, ==, 2); - - g_main_loop_unref (test.main_loop); - clutter_frame_clock_destroy (test.frame_clock); -} - -typedef struct _RescheduleOnIdleFrameClockTest -{ - FrameClockTest base; -} RescheduleOnIdleFrameClockTest; - -static ClutterFrameResult -reschedule_on_idle_clock_frame (ClutterFrameClock *frame_clock, - int64_t frame_count, - int64_t time_us, - gpointer user_data) -{ - RescheduleOnIdleFrameClockTest *test = user_data; - GMainLoop *main_loop = test->base.main_loop; - - g_assert_cmpint (frame_count, ==, expected_frame_count); - - expected_frame_count++; - - if (test_frame_count == 0) - { - g_main_loop_quit (main_loop); - return CLUTTER_FRAME_RESULT_IDLE; - } - - test_frame_count--; - - clutter_frame_clock_schedule_update (frame_clock); - - return CLUTTER_FRAME_RESULT_IDLE; -} - -static const ClutterFrameListenerIface reschedule_on_idle_listener_iface = { - .frame = reschedule_on_idle_clock_frame, -}; - -static void -frame_clock_reschedule_on_idle (void) -{ - RescheduleOnIdleFrameClockTest test; - ClutterFrameClock *frame_clock; - FakeHwClock *fake_hw_clock; - GSource *source; - - test_frame_count = 10; - expected_frame_count = 0; - - test.base.main_loop = g_main_loop_new (NULL, FALSE); - frame_clock = clutter_frame_clock_new (refresh_rate, - 0, - &reschedule_on_idle_listener_iface, - &test); - fake_hw_clock = fake_hw_clock_new (frame_clock, NULL, NULL); - source = &fake_hw_clock->source; - g_source_attach (source, NULL); - test.base.fake_hw_clock = fake_hw_clock; - - clutter_frame_clock_schedule_update (frame_clock); - g_main_loop_run (test.base.main_loop); - - g_main_loop_unref (test.base.main_loop); - clutter_frame_clock_destroy (frame_clock); -} - -static const ClutterFrameListenerIface dummy_frame_listener_iface = { - .frame = NULL, -}; - -static void -on_destroy (ClutterFrameClock *frame_clock, - gboolean *destroy_signalled) -{ - g_assert_false (*destroy_signalled); - *destroy_signalled = TRUE; -} - -static void -frame_clock_destroy_signal (void) -{ - ClutterFrameClock *frame_clock; - ClutterFrameClock *frame_clock_backup; - gboolean destroy_signalled; - - /* Test that the destroy signal is emitted when removing last reference. */ - - frame_clock = clutter_frame_clock_new (refresh_rate, - 0, - &dummy_frame_listener_iface, - NULL); - - destroy_signalled = FALSE; - g_signal_connect (frame_clock, "destroy", - G_CALLBACK (on_destroy), - &destroy_signalled); - g_object_add_weak_pointer (G_OBJECT (frame_clock), (gpointer *) &frame_clock); - - g_object_unref (frame_clock); - g_assert_true (destroy_signalled); - g_assert_null (frame_clock); - - /* Test that destroy signal is emitted when destroying with references still - * left. - */ - - frame_clock = clutter_frame_clock_new (refresh_rate, - 0, - &dummy_frame_listener_iface, - NULL); - frame_clock_backup = frame_clock; - - destroy_signalled = FALSE; - g_signal_connect (frame_clock, "destroy", - G_CALLBACK (on_destroy), - &destroy_signalled); - g_object_add_weak_pointer (G_OBJECT (frame_clock), (gpointer *) &frame_clock); - g_object_ref (frame_clock); - - clutter_frame_clock_destroy (frame_clock); - g_assert_true (destroy_signalled); - g_assert_null (frame_clock); - g_object_unref (frame_clock_backup); -} - -static gboolean -notify_ready_and_schedule_update_idle (gpointer user_data) -{ - ClutterFrameClock *frame_clock = user_data; - - clutter_frame_clock_notify_ready (frame_clock); - clutter_frame_clock_schedule_update (frame_clock); - - return G_SOURCE_REMOVE; -} - -static ClutterFrameResult -frame_clock_ready_frame (ClutterFrameClock *frame_clock, - int64_t frame_count, - int64_t time_us, - gpointer user_data) -{ - GMainLoop *main_loop = user_data; - - g_assert_cmpint (frame_count, ==, expected_frame_count); - - expected_frame_count++; - - if (test_frame_count == 0) - { - g_main_loop_quit (main_loop); - return CLUTTER_FRAME_RESULT_IDLE; - } - - test_frame_count--; - - g_idle_add (notify_ready_and_schedule_update_idle, frame_clock); - - return CLUTTER_FRAME_RESULT_PENDING_PRESENTED; -} - -static const ClutterFrameListenerIface frame_clock_ready_listener_iface = { - .frame = frame_clock_ready_frame, -}; - -static void -frame_clock_notify_ready (void) -{ - GMainLoop *main_loop; - ClutterFrameClock *frame_clock; - int64_t before_us; - int64_t after_us; - - test_frame_count = 10; - expected_frame_count = 0; - - main_loop = g_main_loop_new (NULL, FALSE); - frame_clock = clutter_frame_clock_new (refresh_rate, - 0, - &frame_clock_ready_listener_iface, - main_loop); - - before_us = g_get_monotonic_time (); - - clutter_frame_clock_schedule_update (frame_clock); - g_main_loop_run (main_loop); - - after_us = g_get_monotonic_time (); - - /* The initial frame will only be delayed by 2 ms, so we are checking one - * less. - */ - g_assert_cmpint (after_us - before_us, >, 8 * refresh_interval_us); - - g_main_loop_unref (main_loop); - clutter_frame_clock_destroy (frame_clock); -} - -CLUTTER_TEST_SUITE ( - CLUTTER_TEST_UNIT ("/frame-clock/schedule-update", frame_clock_schedule_update) - CLUTTER_TEST_UNIT ("/frame-clock/immediate-present", frame_clock_immediate_present) - CLUTTER_TEST_UNIT ("/frame-clock/delayed-damage", frame_clock_delayed_damage) - CLUTTER_TEST_UNIT ("/frame-clock/no-damage", frame_clock_no_damage) - CLUTTER_TEST_UNIT ("/frame-clock/schedule-update-now", frame_clock_schedule_update_now) - CLUTTER_TEST_UNIT ("/frame-clock/before-frame", frame_clock_before_frame) - CLUTTER_TEST_UNIT ("/frame-clock/inhibit", frame_clock_inhibit) - CLUTTER_TEST_UNIT ("/frame-clock/reschedule-on-idle", frame_clock_reschedule_on_idle) - CLUTTER_TEST_UNIT ("/frame-clock/destroy-signal", frame_clock_destroy_signal) - CLUTTER_TEST_UNIT ("/frame-clock/notify-ready", frame_clock_notify_ready) -) diff --git a/src/tests/clutter/conform/interval.c b/src/tests/clutter/conform/interval.c deleted file mode 100644 index 263a25b37..000000000 --- a/src/tests/clutter/conform/interval.c +++ /dev/null @@ -1,119 +0,0 @@ -#include - -#include "tests/clutter-test-utils.h" - -static void -interval_initial_state (void) -{ - ClutterInterval *interval; - int initial, final; - const GValue *value; - - interval = clutter_interval_new (G_TYPE_INT, 0, 100); - g_assert (CLUTTER_IS_INTERVAL (interval)); - g_assert (clutter_interval_get_value_type (interval) == G_TYPE_INT); - - clutter_interval_get_interval (interval, &initial, &final); - g_assert_cmpint (initial, ==, 0); - g_assert_cmpint (final, ==, 100); - - value = clutter_interval_compute (interval, 0); - g_assert (G_VALUE_HOLDS_INT (value)); - g_assert_cmpint (g_value_get_int (value), ==, 0); - - value = clutter_interval_compute (interval, 1); - g_assert (G_VALUE_HOLDS_INT (value)); - g_assert_cmpint (g_value_get_int (value), ==, 100); - - value = clutter_interval_compute (interval, 0.5); - g_assert (G_VALUE_HOLDS_INT (value)); - g_assert_cmpint (g_value_get_int (value), ==, 50); - - clutter_interval_set_final (interval, 200); - value = clutter_interval_peek_final_value (interval); - g_assert (G_VALUE_HOLDS_INT (value)); - g_assert_cmpint (g_value_get_int (value), ==, 200); - - g_object_unref (interval); -} - -static void -interval_transform (void) -{ - ClutterInterval *interval; - GValue value = G_VALUE_INIT; - const GValue *value_p = NULL; - - interval = clutter_interval_new_with_values (G_TYPE_FLOAT, NULL, NULL); - - g_value_init (&value, G_TYPE_DOUBLE); - - g_value_set_double (&value, 0.0); - clutter_interval_set_initial_value (interval, &value); - - g_value_set_double (&value, 100.0); - clutter_interval_set_final_value (interval, &value); - - g_value_unset (&value); - - value_p = clutter_interval_peek_initial_value (interval); - g_assert (G_VALUE_HOLDS_FLOAT (value_p)); - g_assert_cmpfloat (g_value_get_float (value_p), ==, 0.f); - - value_p = clutter_interval_peek_final_value (interval); - g_assert (G_VALUE_HOLDS_FLOAT (value_p)); - g_assert_cmpfloat (g_value_get_float (value_p), ==, 100.f); - - g_object_unref (interval); -} - -static void -interval_from_script (void) -{ - ClutterScript *script = clutter_script_new (); - ClutterInterval *interval; - gchar *test_file; - GError *error = NULL; - GValue *initial, *final; - - test_file = g_test_build_filename (G_TEST_DIST, - "scripts", - "test-script-interval.json", - NULL); - clutter_script_load_from_file (script, test_file, &error); - if (!g_test_quiet () && error) - g_printerr ("\tError: %s", error->message); - - g_assert_no_error (error); - - interval = CLUTTER_INTERVAL (clutter_script_get_object (script, "int-1")); - initial = clutter_interval_peek_initial_value (interval); - if (!g_test_quiet ()) - g_test_message ("\tinitial ['%s'] = '%.2f'", - g_type_name (G_VALUE_TYPE (initial)), - g_value_get_float (initial)); - g_assert (G_VALUE_HOLDS (initial, G_TYPE_FLOAT)); - g_assert_cmpfloat (g_value_get_float (initial), ==, 23.3f); - final = clutter_interval_peek_final_value (interval); - if (!g_test_quiet ()) - g_test_message ("\tfinal ['%s'] = '%.2f'", - g_type_name (G_VALUE_TYPE (final)), - g_value_get_float (final)); - g_assert (G_VALUE_HOLDS (final, G_TYPE_FLOAT)); - g_assert_cmpfloat (g_value_get_float (final), ==, 42.2f); - - interval = CLUTTER_INTERVAL (clutter_script_get_object (script, "int-2")); - initial = clutter_interval_peek_initial_value (interval); - g_assert (G_VALUE_HOLDS (initial, CLUTTER_TYPE_COLOR)); - final = clutter_interval_peek_final_value (interval); - g_assert (G_VALUE_HOLDS (final, CLUTTER_TYPE_COLOR)); - - g_object_unref (script); - g_free (test_file); -} - -CLUTTER_TEST_SUITE ( - CLUTTER_TEST_UNIT ("/interval/initial-state", interval_initial_state) - CLUTTER_TEST_UNIT ("/interval/transform", interval_transform) - CLUTTER_TEST_UNIT ("/interval/from-script", interval_from_script) -) diff --git a/src/tests/clutter/conform/meson.build b/src/tests/clutter/conform/meson.build deleted file mode 100644 index aec4a9148..000000000 --- a/src/tests/clutter/conform/meson.build +++ /dev/null @@ -1,79 +0,0 @@ -clutter_tests_conform_c_args = [ - '-DG_LOG_DOMAIN="Clutter-Conform"', - '-DCOGL_DISABLE_DEPRECATION_WARNINGS', - '-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name()), -] -clutter_tests_conform_c_args += clutter_debug_c_args - -clutter_tests_conform_link_args = [ - '-Wl,--export-dynamic', -] - -clutter_conform_tests_actor_tests = [ - 'actor-clone', - 'actor-destroy', - 'actor-graph', - 'actor-invariants', - 'actor-iter', - 'actor-layout', - 'actor-meta', - 'actor-offscreen-redirect', - 'actor-paint-opacity', - 'actor-pick', - 'actor-pivot-point', - 'actor-shader-effect', - 'actor-size', -] - -clutter_conform_tests_classes_tests = [ - 'text', -] - -clutter_conform_tests_general_tests = [ - 'binding-pool', - 'color', - 'frame-clock', - 'frame-clock-timeline', - 'interval', - 'script-parser', - 'timeline', - 'timeline-interpolate', - 'timeline-progress', - 'timeline-rewind', - 'units', -] - -clutter_conform_tests = [] -clutter_conform_tests += clutter_conform_tests_actor_tests -clutter_conform_tests += clutter_conform_tests_classes_tests -clutter_conform_tests += clutter_conform_tests_general_tests - -test_env = environment() -test_env.set('G_TEST_SRCDIR', meson.current_source_dir()) -test_env.set('G_TEST_BUILDDIR', meson.current_build_dir()) -test_env.set('G_ENABLE_DIAGNOSTIC', '0') -test_env.set('CLUTTER_ENABLE_DIAGNOSTIC', '0') -test_env.set('CLUTTER_SCALE', '1') -test_env.set('MUTTER_TEST_PLUGIN_PATH', '@0@'.format(default_plugin.full_path())) - -foreach test : clutter_conform_tests - test_executable = executable('@0@'.format(test), - sources: [ - '@0@.c'.format(test), - clutter_test_utils, - ], - include_directories: clutter_includes, - c_args: clutter_tests_conform_c_args, - link_args: clutter_tests_conform_link_args, - dependencies: [ - libmutter_test_dep, - ], - install: false, - ) - - test(test, test_executable, - suite: ['clutter', 'clutter/conform'], - env: test_env, - is_parallel: false, - ) -endforeach diff --git a/src/tests/clutter/conform/path.c b/src/tests/clutter/conform/path.c deleted file mode 100644 index 55620069a..000000000 --- a/src/tests/clutter/conform/path.c +++ /dev/null @@ -1,740 +0,0 @@ -#include -#include -#include -#include - -#include "test-conform-common.h" - -#define MAX_NODES 128 - -#define FLOAT_FUZZ_AMOUNT 5.0f - -typedef struct _CallbackData CallbackData; - -typedef gboolean (* PathTestFunc) (CallbackData *data); - -static void compare_node (const ClutterPathNode *node, gpointer data_p); - -struct _CallbackData -{ - ClutterPath *path; - - guint n_nodes; - ClutterPathNode nodes[MAX_NODES]; - - gboolean nodes_different; - guint nodes_found; -}; - -static const char path_desc[] = - "M 21 22 " - "L 25 26 " - "C 29 30 31 32 33 34 " - "m 23 24 " - "l 27 28 " - "c 35 36 37 38 39 40 " - "z"; -static const ClutterPathNode path_nodes[] = - { { CLUTTER_PATH_MOVE_TO, { { 21, 22 }, { 0, 0 }, { 0, 0 } } }, - { CLUTTER_PATH_LINE_TO, { { 25, 26 }, { 0, 0 }, { 0, 0 } } }, - { CLUTTER_PATH_CURVE_TO, { { 29, 30 }, { 31, 32 }, { 33, 34 } } }, - { CLUTTER_PATH_REL_MOVE_TO, { { 23, 24 }, { 0, 0 }, { 0, 0 } } }, - { CLUTTER_PATH_REL_LINE_TO, { { 27, 28 }, { 0, 0 }, { 0, 0 } } }, - { CLUTTER_PATH_REL_CURVE_TO, { { 35, 36 }, { 37, 38 }, { 39, 40 } } }, - { CLUTTER_PATH_CLOSE, { { 0, 0 }, { 0, 0 }, { 0, 0 } } } }; - -static gboolean -path_test_add_move_to (CallbackData *data) -{ - ClutterPathNode node = { 0, }; - - node.type = CLUTTER_PATH_MOVE_TO; - node.points[0].x = 1; - node.points[0].y = 2; - - clutter_path_add_move_to (data->path, node.points[0].x, node.points[0].y); - - data->nodes[data->n_nodes++] = node; - - return TRUE; -} - -static gboolean -path_test_add_line_to (CallbackData *data) -{ - ClutterPathNode node = { 0, }; - - node.type = CLUTTER_PATH_LINE_TO; - node.points[0].x = 3; - node.points[0].y = 4; - - clutter_path_add_line_to (data->path, node.points[0].x, node.points[0].y); - - data->nodes[data->n_nodes++] = node; - - return TRUE; -} - -static gboolean -path_test_add_curve_to (CallbackData *data) -{ - ClutterPathNode node = { 0, }; - - node.type = CLUTTER_PATH_CURVE_TO; - node.points[0].x = 5; - node.points[0].y = 6; - node.points[1].x = 7; - node.points[1].y = 8; - node.points[2].x = 9; - node.points[2].y = 10; - - clutter_path_add_curve_to (data->path, - node.points[0].x, node.points[0].y, - node.points[1].x, node.points[1].y, - node.points[2].x, node.points[2].y); - - data->nodes[data->n_nodes++] = node; - - return TRUE; -} - -static gboolean -path_test_add_close (CallbackData *data) -{ - ClutterPathNode node = { 0, }; - - node.type = CLUTTER_PATH_CLOSE; - - clutter_path_add_close (data->path); - - data->nodes[data->n_nodes++] = node; - - return TRUE; -} - -static gboolean -path_test_add_rel_move_to (CallbackData *data) -{ - ClutterPathNode node = { 0, }; - - node.type = CLUTTER_PATH_REL_MOVE_TO; - node.points[0].x = 11; - node.points[0].y = 12; - - clutter_path_add_rel_move_to (data->path, node.points[0].x, node.points[0].y); - - data->nodes[data->n_nodes++] = node; - - return TRUE; -} - -static gboolean -path_test_add_rel_line_to (CallbackData *data) -{ - ClutterPathNode node = { 0, }; - - node.type = CLUTTER_PATH_REL_LINE_TO; - node.points[0].x = 13; - node.points[0].y = 14; - - clutter_path_add_rel_line_to (data->path, node.points[0].x, node.points[0].y); - - data->nodes[data->n_nodes++] = node; - - return TRUE; -} - -static gboolean -path_test_add_rel_curve_to (CallbackData *data) -{ - ClutterPathNode node = { 0, }; - - node.type = CLUTTER_PATH_REL_CURVE_TO; - node.points[0].x = 15; - node.points[0].y = 16; - node.points[1].x = 17; - node.points[1].y = 18; - node.points[2].x = 19; - node.points[2].y = 20; - - clutter_path_add_rel_curve_to (data->path, - node.points[0].x, node.points[0].y, - node.points[1].x, node.points[1].y, - node.points[2].x, node.points[2].y); - - data->nodes[data->n_nodes++] = node; - - return TRUE; -} - -static gboolean -path_test_add_string (CallbackData *data) -{ - int i; - - for (i = 0; i < G_N_ELEMENTS (path_nodes); i++) - data->nodes[data->n_nodes++] = path_nodes[i]; - - clutter_path_add_string (data->path, path_desc); - - return TRUE; -} - -static gboolean -path_test_add_node_by_struct (CallbackData *data) -{ - int i; - - for (i = 0; i < G_N_ELEMENTS (path_nodes); i++) - { - data->nodes[data->n_nodes++] = path_nodes[i]; - clutter_path_add_node (data->path, path_nodes + i); - } - - return TRUE; -} - -static gboolean -path_test_get_n_nodes (CallbackData *data) -{ - return clutter_path_get_n_nodes (data->path) == data->n_nodes; -} - -static gboolean -path_test_get_node (CallbackData *data) -{ - int i; - - data->nodes_found = 0; - data->nodes_different = FALSE; - - for (i = 0; i < data->n_nodes; i++) - { - ClutterPathNode node; - - clutter_path_get_node (data->path, i, &node); - - compare_node (&node, data); - } - - return !data->nodes_different; -} - -static gboolean -path_test_get_nodes (CallbackData *data) -{ - GSList *list, *node; - - data->nodes_found = 0; - data->nodes_different = FALSE; - - list = clutter_path_get_nodes (data->path); - - for (node = list; node; node = node->next) - compare_node (node->data, data); - - g_slist_free (list); - - return !data->nodes_different && data->nodes_found == data->n_nodes; -} - -static gboolean -path_test_insert_beginning (CallbackData *data) -{ - ClutterPathNode node; - - node.type = CLUTTER_PATH_LINE_TO; - node.points[0].x = 41; - node.points[0].y = 42; - - memmove (data->nodes + 1, data->nodes, - data->n_nodes++ * sizeof (ClutterPathNode)); - data->nodes[0] = node; - - clutter_path_insert_node (data->path, 0, &node); - - return TRUE; -} - -static gboolean -path_test_insert_end (CallbackData *data) -{ - ClutterPathNode node; - - node.type = CLUTTER_PATH_LINE_TO; - node.points[0].x = 43; - node.points[0].y = 44; - - data->nodes[data->n_nodes++] = node; - - clutter_path_insert_node (data->path, -1, &node); - - return TRUE; -} - -static gboolean -path_test_insert_middle (CallbackData *data) -{ - ClutterPathNode node; - int pos = data->n_nodes / 2; - - node.type = CLUTTER_PATH_LINE_TO; - node.points[0].x = 45; - node.points[0].y = 46; - - memmove (data->nodes + pos + 1, data->nodes + pos, - (data->n_nodes - pos) * sizeof (ClutterPathNode)); - data->nodes[pos] = node; - data->n_nodes++; - - clutter_path_insert_node (data->path, pos, &node); - - return TRUE; -} - -static gboolean -path_test_clear (CallbackData *data) -{ - clutter_path_clear (data->path); - - data->n_nodes = 0; - - return TRUE; -} - -static gboolean -path_test_clear_insert (CallbackData *data) -{ - return path_test_clear (data) && path_test_insert_middle (data); -} - -static gboolean -path_test_remove_beginning (CallbackData *data) -{ - memmove (data->nodes, data->nodes + 1, - --data->n_nodes * sizeof (ClutterPathNode)); - - clutter_path_remove_node (data->path, 0); - - return TRUE; -} - -static gboolean -path_test_remove_end (CallbackData *data) -{ - clutter_path_remove_node (data->path, --data->n_nodes); - - return TRUE; -} - -static gboolean -path_test_remove_middle (CallbackData *data) -{ - int pos = data->n_nodes / 2; - - memmove (data->nodes + pos, data->nodes + pos + 1, - (--data->n_nodes - pos) * sizeof (ClutterPathNode)); - - clutter_path_remove_node (data->path, pos); - - return TRUE; -} - -static gboolean -path_test_remove_only (CallbackData *data) -{ - return path_test_clear (data) - && path_test_add_line_to (data) - && path_test_remove_beginning (data); -} - -static gboolean -path_test_replace (CallbackData *data) -{ - ClutterPathNode node; - int pos = data->n_nodes / 2; - - node.type = CLUTTER_PATH_LINE_TO; - node.points[0].x = 47; - node.points[0].y = 48; - - data->nodes[pos] = node; - - clutter_path_replace_node (data->path, pos, &node); - - return TRUE; -} - -static gboolean -path_test_set_description (CallbackData *data) -{ - data->n_nodes = G_N_ELEMENTS (path_nodes); - memcpy (data->nodes, path_nodes, sizeof (path_nodes)); - - return clutter_path_set_description (data->path, path_desc); -} - -static gboolean -path_test_get_description (CallbackData *data) -{ - char *desc1, *desc2; - gboolean ret = TRUE; - - desc1 = clutter_path_get_description (data->path); - clutter_path_clear (data->path); - if (!clutter_path_set_description (data->path, desc1)) - ret = FALSE; - desc2 = clutter_path_get_description (data->path); - - if (strcmp (desc1, desc2)) - ret = FALSE; - - g_free (desc1); - g_free (desc2); - - return ret; -} - -static gboolean -path_test_convert_to_cairo_path (CallbackData *data) -{ - cairo_surface_t *surface; - cairo_t *cr; - cairo_path_t *cpath; - guint i, j; - ClutterKnot path_start = { 0, 0 }, last_point = { 0, 0 }; - - /* Create a temporary image surface and context to hold the cairo - path */ - surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 10, 10); - cr = cairo_create (surface); - - /* Convert to a cairo path */ - clutter_path_to_cairo_path (data->path, cr); - - /* Get a copy of the cairo path data */ - cpath = cairo_copy_path (cr); - - /* Convert back to a clutter path */ - clutter_path_clear (data->path); - clutter_path_add_cairo_path (data->path, cpath); - - /* The relative nodes will have been converted to absolute so we - need to reflect this in the node array for comparison */ - for (i = 0; i < data->n_nodes; i++) - { - switch (data->nodes[i].type) - { - case CLUTTER_PATH_MOVE_TO: - path_start = last_point = data->nodes[i].points[0]; - break; - - case CLUTTER_PATH_LINE_TO: - last_point = data->nodes[i].points[0]; - break; - - case CLUTTER_PATH_CURVE_TO: - last_point = data->nodes[i].points[2]; - break; - - case CLUTTER_PATH_REL_MOVE_TO: - last_point.x += data->nodes[i].points[0].x; - last_point.y += data->nodes[i].points[0].y; - data->nodes[i].points[0] = last_point; - data->nodes[i].type = CLUTTER_PATH_MOVE_TO; - path_start = last_point; - break; - - case CLUTTER_PATH_REL_LINE_TO: - last_point.x += data->nodes[i].points[0].x; - last_point.y += data->nodes[i].points[0].y; - data->nodes[i].points[0] = last_point; - data->nodes[i].type = CLUTTER_PATH_LINE_TO; - break; - - case CLUTTER_PATH_REL_CURVE_TO: - for (j = 0; j < 3; j++) - { - data->nodes[i].points[j].x += last_point.x; - data->nodes[i].points[j].y += last_point.y; - } - last_point = data->nodes[i].points[2]; - data->nodes[i].type = CLUTTER_PATH_CURVE_TO; - break; - - case CLUTTER_PATH_CLOSE: - last_point = path_start; - - /* Cairo always adds a move to after every close so we need - to insert one here. Since Cairo commit 166453c1abf2 it - doesn't seem to do this anymore so will assume that if - Cairo's minor version is >= 11 then it includes that - commit */ - if (cairo_version () < CAIRO_VERSION_ENCODE (1, 11, 0)) - { - memmove (data->nodes + i + 2, data->nodes + i + 1, - (data->n_nodes - i - 1) * sizeof (ClutterPathNode)); - data->nodes[i + 1].type = CLUTTER_PATH_MOVE_TO; - data->nodes[i + 1].points[0] = last_point; - data->n_nodes++; - } - break; - } - } - - /* Free the cairo resources */ - cairo_path_destroy (cpath); - cairo_destroy (cr); - cairo_surface_destroy (surface); - - return TRUE; -} - -static gboolean -float_fuzzy_equals (float fa, float fb) -{ - return fabs (fa - fb) <= FLOAT_FUZZ_AMOUNT; -} - -static void -set_triangle_path (CallbackData *data) -{ - /* Triangular shaped path hitting (0,0), (64,64) and (128,0) in four - parts. The two curves are actually straight lines */ - static const ClutterPathNode nodes[] = - { { CLUTTER_PATH_MOVE_TO, { { 0, 0 } } }, - { CLUTTER_PATH_LINE_TO, { { 32, 32 } } }, - { CLUTTER_PATH_CURVE_TO, { { 40, 40 }, { 56, 56 }, { 64, 64 } } }, - { CLUTTER_PATH_REL_CURVE_TO, { { 8, -8 }, { 24, -24 }, { 32, -32 } } }, - { CLUTTER_PATH_REL_LINE_TO, { { 32, -32 } } } }; - gint i; - - clutter_path_clear (data->path); - - for (i = 0; i < G_N_ELEMENTS (nodes); i++) - clutter_path_add_node (data->path, nodes + i); - - memcpy (data->nodes, nodes, sizeof (nodes)); - data->n_nodes = G_N_ELEMENTS (nodes); -} - -static gboolean -path_test_get_position (CallbackData *data) -{ - static const float values[] = { 0.125f, 16.0f, 16.0f, - 0.375f, 48.0f, 48.0f, - 0.625f, 80.0f, 48.0f, - 0.875f, 112.0f, 16.0f }; - gint i; - - set_triangle_path (data); - - for (i = 0; i < G_N_ELEMENTS (values); i += 3) - { - ClutterKnot pos; - - clutter_path_get_position (data->path, - values[i], - &pos); - - if (!float_fuzzy_equals (values[i + 1], pos.x) - || !float_fuzzy_equals (values[i + 2], pos.y)) - return FALSE; - } - - return TRUE; -} - -static gboolean -path_test_get_length (CallbackData *data) -{ - const float actual_length /* sqrt(64**2 + 64**2) * 2 */ = 181.019336f; - guint approx_length; - - clutter_path_set_description (data->path, "M 0 0 L 46340 0"); - g_object_get (data->path, "length", &approx_length, NULL); - - if (!(fabs (approx_length - 46340.f) / 46340.f <= 0.15f)) - { - if (!g_test_quiet ()) - g_print ("M 0 0 L 46340 0 - Expected 46340, got %d instead.", approx_length); - - return FALSE; - } - - clutter_path_set_description (data->path, "M 0 0 L 46341 0"); - g_object_get (data->path, "length", &approx_length, NULL); - - if (!(fabs (approx_length - 46341.f) / 46341.f <= 0.15f)) - { - if (!g_test_quiet ()) - g_print ("M 0 0 L 46341 0 - Expected 46341, got %d instead.", approx_length); - - return FALSE; - } - - set_triangle_path (data); - - g_object_get (data->path, "length", &approx_length, NULL); - - /* Allow 15% margin of error */ - if (!(fabs (approx_length - actual_length) / (float) actual_length <= 0.15f)) - { - if (!g_test_quiet ()) - g_print ("Expected %g, got %d instead.\n", actual_length, approx_length); - - return FALSE; - } - - return TRUE; -} - -static gboolean -path_test_boxed_type (CallbackData *data) -{ - gboolean ret = TRUE; - GSList *nodes, *l; - GValue value; - - nodes = clutter_path_get_nodes (data->path); - - memset (&value, 0, sizeof (value)); - - for (l = nodes; l; l = l->next) - { - g_value_init (&value, CLUTTER_TYPE_PATH_NODE); - - g_value_set_boxed (&value, l->data); - - if (!clutter_path_node_equal (l->data, - g_value_get_boxed (&value))) - ret = FALSE; - - g_value_unset (&value); - } - - g_slist_free (nodes); - - return ret; -} - -static const struct -{ - const char *desc; - PathTestFunc func; -} -path_tests[] = - { - { "Add line to", path_test_add_line_to }, - { "Add move to", path_test_add_move_to }, - { "Add curve to", path_test_add_curve_to }, - { "Add close", path_test_add_close }, - { "Add relative line to", path_test_add_rel_line_to }, - { "Add relative move to", path_test_add_rel_move_to }, - { "Add relative curve to", path_test_add_rel_curve_to }, - { "Add string", path_test_add_string }, - { "Add node by struct", path_test_add_node_by_struct }, - { "Get number of nodes", path_test_get_n_nodes }, - { "Get a node", path_test_get_node }, - { "Get all nodes", path_test_get_nodes }, - { "Insert at beginning", path_test_insert_beginning }, - { "Insert at end", path_test_insert_end }, - { "Insert at middle", path_test_insert_middle }, - { "Add after insert", path_test_add_line_to }, - { "Clear then insert", path_test_clear_insert }, - { "Add string again", path_test_add_string }, - { "Remove from beginning", path_test_remove_beginning }, - { "Remove from end", path_test_remove_end }, - { "Remove from middle", path_test_remove_middle }, - { "Add after remove", path_test_add_line_to }, - { "Remove only node", path_test_remove_only }, - { "Add after remove again", path_test_add_line_to }, - { "Replace a node", path_test_replace }, - { "Set description", path_test_set_description }, - { "Get description", path_test_get_description }, - { "Convert to cairo path and back", path_test_convert_to_cairo_path }, - { "Clear", path_test_clear }, - { "Get position", path_test_get_position }, - { "Check node boxed type", path_test_boxed_type }, - { "Get length", path_test_get_length } - }; - -static void -compare_node (const ClutterPathNode *node, gpointer data_p) -{ - CallbackData *data = data_p; - - if (data->nodes_found >= data->n_nodes) - data->nodes_different = TRUE; - else - { - guint n_points = 0, i; - const ClutterPathNode *onode = data->nodes + data->nodes_found; - - if (node->type != onode->type) - data->nodes_different = TRUE; - - switch (node->type & ~CLUTTER_PATH_RELATIVE) - { - case CLUTTER_PATH_MOVE_TO: n_points = 1; break; - case CLUTTER_PATH_LINE_TO: n_points = 1; break; - case CLUTTER_PATH_CURVE_TO: n_points = 3; break; - case CLUTTER_PATH_CLOSE: n_points = 0; break; - - default: - data->nodes_different = TRUE; - break; - } - - for (i = 0; i < n_points; i++) - if (node->points[i].x != onode->points[i].x - || node->points[i].y != onode->points[i].y) - { - data->nodes_different = TRUE; - break; - } - } - - data->nodes_found++; -} - -static gboolean -compare_nodes (CallbackData *data) -{ - data->nodes_different = FALSE; - data->nodes_found = 0; - - clutter_path_foreach (data->path, compare_node, data); - - return !data->nodes_different && data->nodes_found == data->n_nodes; -} - -void -path_base (TestConformSimpleFixture *fixture, - gconstpointer _data) -{ - CallbackData data; - gint i; - - memset (&data, 0, sizeof (data)); - - data.path = clutter_path_new (); - - for (i = 0; i < G_N_ELEMENTS (path_tests); i++) - { - gboolean succeeded; - - if (!g_test_quiet ()) - g_print ("%s... ", path_tests[i].desc); - - succeeded = path_tests[i].func (&data) && compare_nodes (&data); - - if (!g_test_quiet ()) - g_print ("%s\n", succeeded ? "ok" : "FAIL"); - - g_assert (succeeded); - } - - g_object_unref (data.path); -} - diff --git a/src/tests/clutter/conform/script-parser.c b/src/tests/clutter/conform/script-parser.c deleted file mode 100644 index c51329e13..000000000 --- a/src/tests/clutter/conform/script-parser.c +++ /dev/null @@ -1,303 +0,0 @@ -#include -#include - -#define CLUTTER_DISABLE_DEPRECATION_WARNINGS -#include - -#include "tests/clutter-test-utils.h" - -#define TEST_TYPE_GROUP (test_group_get_type ()) -#define TEST_TYPE_GROUP_META (test_group_meta_get_type ()) - -#define TEST_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_GROUP, TestGroup)) -#define TEST_IS_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_GROUP)) - -#define TEST_GROUP_META(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_GROUP_META, TestGroupMeta)) -#define TEST_IS_GROUP_META(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_GROUP_META)) - -typedef struct _ClutterActor TestGroup; -typedef struct _ClutterActorClass TestGroupClass; - -typedef struct _TestGroupMeta { - ClutterChildMeta parent_instance; - - guint is_focus : 1; -} TestGroupMeta; - -typedef struct _ClutterChildMetaClass TestGroupMetaClass; - -GType test_group_meta_get_type (void); - -G_DEFINE_TYPE (TestGroupMeta, test_group_meta, CLUTTER_TYPE_CHILD_META) - -enum -{ - PROP_META_0, - - PROP_META_FOCUS -}; - -static void -test_group_meta_set_property (GObject *gobject, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - TestGroupMeta *self = TEST_GROUP_META (gobject); - - switch (prop_id) - { - case PROP_META_FOCUS: - self->is_focus = g_value_get_boolean (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); - break; - } -} - -static void -test_group_meta_get_property (GObject *gobject, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - TestGroupMeta *self = TEST_GROUP_META (gobject); - - switch (prop_id) - { - case PROP_META_FOCUS: - g_value_set_boolean (value, self->is_focus); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); - break; - } -} - -static void -test_group_meta_class_init (TestGroupMetaClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GParamSpec *pspec; - - gobject_class->set_property = test_group_meta_set_property; - gobject_class->get_property = test_group_meta_get_property; - - pspec = g_param_spec_boolean ("focus", "Focus", "Focus", - FALSE, - G_PARAM_READWRITE); - g_object_class_install_property (gobject_class, PROP_META_FOCUS, pspec); -} - -static void -test_group_meta_init (TestGroupMeta *meta) -{ - meta->is_focus = FALSE; -} - -static void -clutter_container_iface_init (ClutterContainerIface *iface) -{ - iface->child_meta_type = TEST_TYPE_GROUP_META; -} - -GType test_group_get_type (void); - -G_DEFINE_TYPE_WITH_CODE (TestGroup, test_group, CLUTTER_TYPE_ACTOR, - G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER, - clutter_container_iface_init)) - -static void -test_group_class_init (TestGroupClass *klass) -{ -} - -static void -test_group_init (TestGroup *self) -{ -} - -static void -script_child (void) -{ - ClutterScript *script = clutter_script_new (); - GObject *container, *actor; - GError *error = NULL; - gboolean focus_ret; - gchar *test_file; - - test_file = g_test_build_filename (G_TEST_DIST, "scripts", "test-script-child.json", NULL); - clutter_script_load_from_file (script, test_file, &error); - if (!g_test_quiet () && error) - g_print ("Error: %s", error->message); - - g_assert_no_error (error); - - container = actor = NULL; - clutter_script_get_objects (script, - "test-group", &container, - "test-rect-1", &actor, - NULL); - g_assert (TEST_IS_GROUP (container)); - g_assert (CLUTTER_IS_ACTOR (actor)); - - focus_ret = FALSE; - clutter_container_child_get (CLUTTER_CONTAINER (container), - CLUTTER_ACTOR (actor), - "focus", &focus_ret, - NULL); - g_assert (focus_ret); - - actor = clutter_script_get_object (script, "test-rect-2"); - g_assert (CLUTTER_IS_ACTOR (actor)); - - focus_ret = FALSE; - clutter_container_child_get (CLUTTER_CONTAINER (container), - CLUTTER_ACTOR (actor), - "focus", &focus_ret, - NULL); - g_assert (!focus_ret); - - g_object_unref (script); - g_free (test_file); -} - -static void -script_single (void) -{ - ClutterScript *script = clutter_script_new (); - ClutterColor color = { 0, }; - GObject *actor = NULL; - GError *error = NULL; - ClutterActor *rect; - gchar *test_file; - - test_file = g_test_build_filename (G_TEST_DIST, "scripts", "test-script-single.json", NULL); - clutter_script_load_from_file (script, test_file, &error); - if (!g_test_quiet () && error) - g_print ("Error: %s", error->message); - - g_assert_no_error (error); - - actor = clutter_script_get_object (script, "test"); - g_assert (CLUTTER_IS_ACTOR (actor)); - - rect = CLUTTER_ACTOR (actor); - g_assert_cmpfloat (clutter_actor_get_width (rect), ==, 50.0); - g_assert_cmpfloat (clutter_actor_get_y (rect), ==, 100.0); - - clutter_actor_get_background_color (rect, &color); - g_assert_cmpint (color.red, ==, 255); - g_assert_cmpint (color.green, ==, 0xcc); - g_assert_cmpint (color.alpha, ==, 0xff); - - g_object_unref (script); - g_free (test_file); -} - -static void -script_object_property (void) -{ - ClutterScript *script = clutter_script_new (); - ClutterLayoutManager *manager; - GObject *actor = NULL; - GError *error = NULL; - gchar *test_file; - - test_file = g_test_build_filename (G_TEST_DIST, "scripts", "test-script-object-property.json", NULL); - clutter_script_load_from_file (script, test_file, &error); - if (!g_test_quiet () && error) - g_print ("Error: %s", error->message); - - g_assert_no_error (error); - - actor = clutter_script_get_object (script, "test"); - g_assert (CLUTTER_IS_ACTOR (actor)); - - manager = clutter_actor_get_layout_manager (CLUTTER_ACTOR (actor)); - g_assert (CLUTTER_IS_BIN_LAYOUT (manager)); - - g_object_unref (script); - g_free (test_file); -} - -static void -script_named_object (void) -{ - ClutterScript *script = clutter_script_new (); - ClutterLayoutManager *manager; - GObject *actor = NULL; - GError *error = NULL; - gchar *test_file; - - test_file = g_test_build_filename (G_TEST_DIST, "scripts", "test-script-named-object.json", NULL); - clutter_script_load_from_file (script, test_file, &error); - if (!g_test_quiet () && error) - g_print ("Error: %s", error->message); - - g_assert_no_error (error); - - actor = clutter_script_get_object (script, "test"); - g_assert (CLUTTER_IS_ACTOR (actor)); - - manager = clutter_actor_get_layout_manager (CLUTTER_ACTOR (actor)); - g_assert (CLUTTER_IS_BOX_LAYOUT (manager)); - g_assert (clutter_box_layout_get_orientation (CLUTTER_BOX_LAYOUT (manager)) == CLUTTER_ORIENTATION_VERTICAL); - - g_object_unref (script); - g_free (test_file); -} - -static void -script_margin (void) -{ - ClutterScript *script = clutter_script_new (); - ClutterActor *actor; - gchar *test_file; - GError *error = NULL; - - test_file = g_test_build_filename (G_TEST_DIST, "scripts", "test-script-margin.json", NULL); - clutter_script_load_from_file (script, test_file, &error); - if (!g_test_quiet () && error) - g_print ("Error: %s", error->message); - - g_assert_no_error (error); - - actor = CLUTTER_ACTOR (clutter_script_get_object (script, "actor-1")); - g_assert_cmpfloat (clutter_actor_get_margin_top (actor), ==, 10.0f); - g_assert_cmpfloat (clutter_actor_get_margin_right (actor), ==, 10.0f); - g_assert_cmpfloat (clutter_actor_get_margin_bottom (actor), ==, 10.0f); - g_assert_cmpfloat (clutter_actor_get_margin_left (actor), ==, 10.0f); - - actor = CLUTTER_ACTOR (clutter_script_get_object (script, "actor-2")); - g_assert_cmpfloat (clutter_actor_get_margin_top (actor), ==, 10.0f); - g_assert_cmpfloat (clutter_actor_get_margin_right (actor), ==, 20.0f); - g_assert_cmpfloat (clutter_actor_get_margin_bottom (actor), ==, 10.0f); - g_assert_cmpfloat (clutter_actor_get_margin_left (actor), ==, 20.0f); - - actor = CLUTTER_ACTOR (clutter_script_get_object (script, "actor-3")); - g_assert_cmpfloat (clutter_actor_get_margin_top (actor), ==, 10.0f); - g_assert_cmpfloat (clutter_actor_get_margin_right (actor), ==, 20.0f); - g_assert_cmpfloat (clutter_actor_get_margin_bottom (actor), ==, 30.0f); - g_assert_cmpfloat (clutter_actor_get_margin_left (actor), ==, 20.0f); - - actor = CLUTTER_ACTOR (clutter_script_get_object (script, "actor-4")); - g_assert_cmpfloat (clutter_actor_get_margin_top (actor), ==, 10.0f); - g_assert_cmpfloat (clutter_actor_get_margin_right (actor), ==, 20.0f); - g_assert_cmpfloat (clutter_actor_get_margin_bottom (actor), ==, 30.0f); - g_assert_cmpfloat (clutter_actor_get_margin_left (actor), ==, 40.0f); - - g_object_unref (script); - g_free (test_file); -} - -CLUTTER_TEST_SUITE ( - CLUTTER_TEST_UNIT ("/script/single-object", script_single) - CLUTTER_TEST_UNIT ("/script/container-child", script_child) - CLUTTER_TEST_UNIT ("/script/named-object", script_named_object) - CLUTTER_TEST_UNIT ("/script/object-property", script_object_property) - CLUTTER_TEST_UNIT ("/script/actor-margin", script_margin) -) diff --git a/src/tests/clutter/conform/scripts/test-script-child.json b/src/tests/clutter/conform/scripts/test-script-child.json deleted file mode 100644 index f23208a79..000000000 --- a/src/tests/clutter/conform/scripts/test-script-child.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "type" : "TestGroup", - "id" : "test-group", - "children" : [ - { - "type" : "ClutterActor", - "id" : "test-rect-1", - "width" : 100.0, - "height" : 100.0, - "background-color" : [ 255, 0, 0, 255 ], - "child::focus" : true - }, - { - "type" : "ClutterActor", - "id" : "test-rect-2", - "width" : 100.0, - "height" : 100.0, - "background-color" : [ 0, 255, 0, 255 ] - } - ] -} diff --git a/src/tests/clutter/conform/scripts/test-script-interval.json b/src/tests/clutter/conform/scripts/test-script-interval.json deleted file mode 100644 index 35fe5c22c..000000000 --- a/src/tests/clutter/conform/scripts/test-script-interval.json +++ /dev/null @@ -1,16 +0,0 @@ -[ - { - "id" : "int-1", - "type" : "ClutterInterval", - "value-type" : "gfloat", - "initial" : 23.3, - "final" : 42.2 - }, - { - "id" : "int-2", - "type" : "ClutterInterval", - "value-type" : "ClutterColor", - "initial" : "red", - "final" : "blue" - } -] diff --git a/src/tests/clutter/conform/scripts/test-script-margin.json b/src/tests/clutter/conform/scripts/test-script-margin.json deleted file mode 100644 index 1f5289fa6..000000000 --- a/src/tests/clutter/conform/scripts/test-script-margin.json +++ /dev/null @@ -1,22 +0,0 @@ -[ - { - "id" : "actor-1", - "type" : "ClutterActor", - "margin" : [ 10 ] - }, - { - "id" : "actor-2", - "type" : "ClutterActor", - "margin" : [ 10, 20 ] - }, - { - "id" : "actor-3", - "type" : "ClutterActor", - "margin" : [ 10, 20, 30 ] - }, - { - "id" : "actor-4", - "type" : "ClutterActor", - "margin" : [ 10, 20, 30, 40] - } -] diff --git a/src/tests/clutter/conform/scripts/test-script-model.json b/src/tests/clutter/conform/scripts/test-script-model.json deleted file mode 100644 index dc4a62dc0..000000000 --- a/src/tests/clutter/conform/scripts/test-script-model.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "id" : "test-model", - "type" : "ClutterListModel", - "columns" : [ - [ "text-column", "gchararray" ], - [ "int-column", "gint" ], - [ "actor-column", "ClutterActor" ] - ], - "rows" : [ - [ "text-row-1", 1, null ], - [ "text-row-2", 2, { "type" : "ClutterActor", "background-color" : "blue" } ], - { - "int-column" : 3, - "actor-column" : { "type" : "ClutterActor", "name" : "actor-row-3" } - } - ] -} diff --git a/src/tests/clutter/conform/scripts/test-script-named-object.json b/src/tests/clutter/conform/scripts/test-script-named-object.json deleted file mode 100644 index 4ba5d2c92..000000000 --- a/src/tests/clutter/conform/scripts/test-script-named-object.json +++ /dev/null @@ -1,44 +0,0 @@ -[ - { - "id" : "layout", - "type" : "ClutterBoxLayout", - "orientation" : "vertical", - "spacing" : 12, - "pack-start" : false - }, - { - "type" : "ClutterStage", - "id" : "main-stage", - "children" : [ - { - "id" : "test", - "type" : "ClutterActor", - "layout-manager" : "layout", - "children" : [ - { - "id" : "child-1", - "type" : "ClutterActor", - "width" : "3 em", - "height" : "3 em" - } - ], - "constraints" : [ - { - "type" : "ClutterAlignConstraint", - "name" : "x-align", - "factor" : 0.5, - "align-axis" : "x-axis", - "source" : "main-stage" - }, - { - "type" : "ClutterAlignConstraint", - "name" : "y-align", - "factor" : 0.5, - "align-axis" : "y-axis", - "source" : "main-stage" - } - ] - } - ] - } -] diff --git a/src/tests/clutter/conform/scripts/test-script-object-property.json b/src/tests/clutter/conform/scripts/test-script-object-property.json deleted file mode 100644 index 58187bbb6..000000000 --- a/src/tests/clutter/conform/scripts/test-script-object-property.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "id" : "test", - "type" : "ClutterActor", - "layout-manager" : { "id" : "layout", "type" : "ClutterBinLayout" }, - "children" : [ - { - "id" : "child-1", - "type" : "ClutterActor", - "width" : "3 em", - "height" : "3 em" - } - ] -} diff --git a/src/tests/clutter/conform/scripts/test-script-single.json b/src/tests/clutter/conform/scripts/test-script-single.json deleted file mode 100644 index cb09d696a..000000000 --- a/src/tests/clutter/conform/scripts/test-script-single.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "type" : "ClutterActor", - "id" : "test", - "width" : 50.0, - "height" : 100.0, - "x" : 100.0, - "y" : 100.0, - "background-color" : "#ffccdd", - "name" : "Test Rectangle" -} diff --git a/src/tests/clutter/conform/scripts/test-script-timeline-markers.json b/src/tests/clutter/conform/scripts/test-script-timeline-markers.json deleted file mode 100644 index e26ba5f01..000000000 --- a/src/tests/clutter/conform/scripts/test-script-timeline-markers.json +++ /dev/null @@ -1,16 +0,0 @@ -[ - { "id" : "actor0", "type" : "ClutterActor" }, - { - "id" : "timeline0", - "type" : "ClutterTimeline", - "duration" : 1000, - "actor" : "actor0", - - "markers" : [ - { "name" : "marker0", "time" : 250 }, - { "name" : "marker1", "time" : 500 }, - { "name" : "marker2", "time" : 750 }, - { "name" : "marker3", "progress" : 0.5 } - ] - } -] diff --git a/src/tests/clutter/conform/text-cache.c b/src/tests/clutter/conform/text-cache.c deleted file mode 100644 index 63d38d07d..000000000 --- a/src/tests/clutter/conform/text-cache.c +++ /dev/null @@ -1,299 +0,0 @@ -#include -#include -#include - -#include "test-conform-common.h" - -#define TEST_FONT "Sans 10" - -static const char long_text[] = - "This is some REALLY " - "long text that contains markup for testing the use_markup " - "property and to test word-wrapping, justification and alignment."; - -typedef struct _CallbackData CallbackData; - -struct _CallbackData -{ - ClutterActor *stage; - ClutterActor *label; - - PangoLayout *old_layout; - gboolean layout_changed; - PangoRectangle label_extents; - - PangoLayout *test_layout; - - gboolean test_failed; -}; - -static void -on_paint (ClutterActor *stage, - ClutterPaintContext *paint_context, - CallbackData *data) -{ - PangoLayout *new_layout; - - /* Check whether the layout used for this paint is different from - the layout used for the last paint */ - new_layout = clutter_text_get_layout (CLUTTER_TEXT (data->label)); - data->layout_changed = data->old_layout != new_layout; - - if (data->old_layout) - g_object_unref (data->old_layout); - /* Keep a reference to the old layout so we can be sure it won't - just reallocate a new layout with the same address */ - data->old_layout = g_object_ref (new_layout); - - pango_layout_get_extents (new_layout, NULL, &data->label_extents); -} - -static void -force_redraw (CallbackData *data) -{ - /* XXX - this is fugly; we force a paint on the stage, which - * will then paint the Text actor. inside the Text actor we - * check for a Layout with the allocation size. if the allocation - * has changed it will cause a relayout in the middle of the - * paint, which is expensive and broken. this will ensure that - * the test passes, though - */ - clutter_actor_paint (clutter_actor_get_stage (data->label)); -} - -static gboolean -check_result (CallbackData *data, const char *note, - gboolean layout_should_change) -{ - PangoRectangle test_extents; - gboolean fail = FALSE; - - if (!g_test_quiet ()) - g_print ("%s: ", note); - - /* Force a redraw to get the on_paint handler to run */ - force_redraw (data); - - /* Compare the extents from the label with the extents from our test - layout */ - pango_layout_get_extents (data->test_layout, NULL, &test_extents); - if (memcmp (&test_extents, &data->label_extents, sizeof (PangoRectangle))) - { - if (!g_test_quiet ()) - g_print ("extents are different: expected: %d, %d, %d, %d " - "-> text: %d, %d, %d, %d\n", - test_extents.x / 1024, - test_extents.y / 1024, - test_extents.width / 1024, - test_extents.height / 1024, - data->label_extents.x / 1024, - data->label_extents.y / 1024, - data->label_extents.width / 1024, - data->label_extents.height / 1024); - - fail = TRUE; - } - else - { - if (!g_test_quiet ()) - g_print ("extents are the same, "); - } - - if (data->layout_changed) - { - if (!g_test_quiet ()) - g_print ("layout changed, "); - } - else - { - if (!g_test_quiet ()) - g_print ("layout did not change, "); - } - - if (data->layout_changed != layout_should_change) - fail = TRUE; - - if (fail) - { - if (!g_test_quiet ()) - g_print ("FAIL\n"); - - data->test_failed = TRUE; - } - else - { - if (!g_test_quiet ()) - g_print ("pass\n"); - } - - return fail; -} - -static gboolean -do_tests (CallbackData *data) -{ - PangoFontDescription *fd; - static const ClutterColor red = { 0xff, 0x00, 0x00, 0xff }; - PangoAttrList *attr_list, *attr_list_copy; - PangoAttribute *attr; - - /* TEST 1: change the text */ - clutter_text_set_text (CLUTTER_TEXT (data->label), "Counter 0"); - pango_layout_set_text (data->test_layout, "Counter 0", -1); - g_assert (check_result (data, "Change text", TRUE) == FALSE); - - /* TEST 2: change a single character */ - clutter_text_set_text (CLUTTER_TEXT (data->label), "Counter 1"); - pango_layout_set_text (data->test_layout, "Counter 1", -1); - g_assert (check_result (data, "Change a single character", TRUE) == FALSE); - - /* TEST 3: move the label */ - clutter_actor_set_position (data->label, 10, 0); - g_assert (check_result (data, "Move the label", FALSE) == FALSE); - - /* TEST 4: change the font */ - clutter_text_set_font_name (CLUTTER_TEXT (data->label), "Serif 15"); - fd = pango_font_description_from_string ("Serif 15"); - pango_layout_set_font_description (data->test_layout, fd); - pango_font_description_free (fd); - g_assert (check_result (data, "Change the font", TRUE) == FALSE); - - /* TEST 5: change the color */ - clutter_text_set_color (CLUTTER_TEXT (data->label), &red); - g_assert (check_result (data, "Change the color", FALSE) == FALSE); - - /* TEST 6: change the attributes */ - attr = pango_attr_weight_new (PANGO_WEIGHT_BOLD); - attr->start_index = 0; - attr->end_index = 2; - attr_list = pango_attr_list_new (); - pango_attr_list_insert (attr_list, attr); - attr_list_copy = pango_attr_list_copy (attr_list); - clutter_text_set_attributes (CLUTTER_TEXT (data->label), attr_list); - pango_layout_set_attributes (data->test_layout, attr_list_copy); - pango_attr_list_unref (attr_list_copy); - pango_attr_list_unref (attr_list); - g_assert (check_result (data, "Change the attributes", TRUE) == FALSE); - - /* TEST 7: change the text again */ - clutter_text_set_attributes (CLUTTER_TEXT (data->label), NULL); - clutter_text_set_text (CLUTTER_TEXT (data->label), long_text); - pango_layout_set_attributes (data->test_layout, NULL); - pango_layout_set_text (data->test_layout, long_text, -1); - g_assert (check_result (data, "Change the text again", TRUE) == FALSE); - - /* TEST 8: enable markup */ - clutter_text_set_use_markup (CLUTTER_TEXT (data->label), TRUE); - pango_layout_set_markup (data->test_layout, long_text, -1); - g_assert (check_result (data, "Enable markup", TRUE) == FALSE); - - /* This part can't be a test because Clutter won't restrict the - width if wrapping and ellipsizing is disabled so the extents will - be different, but we still want to do it for the later tests */ - clutter_actor_set_width (data->label, 200); - pango_layout_set_width (data->test_layout, 200 * PANGO_SCALE); - /* Force a redraw so that changing the width won't affect the - results */ - force_redraw (data); - - /* TEST 9: enable ellipsize */ - clutter_text_set_ellipsize (CLUTTER_TEXT (data->label), - PANGO_ELLIPSIZE_END); - pango_layout_set_ellipsize (data->test_layout, PANGO_ELLIPSIZE_END); - g_assert (check_result (data, "Enable ellipsize", TRUE) == FALSE); - clutter_text_set_ellipsize (CLUTTER_TEXT (data->label), - PANGO_ELLIPSIZE_NONE); - pango_layout_set_ellipsize (data->test_layout, PANGO_ELLIPSIZE_NONE); - force_redraw (data); - - /* TEST 10: enable line wrap */ - clutter_text_set_line_wrap (CLUTTER_TEXT (data->label), TRUE); - pango_layout_set_wrap (data->test_layout, PANGO_WRAP_WORD); - g_assert (check_result (data, "Enable line wrap", TRUE) == FALSE); - - /* TEST 11: change wrap mode - * FIXME - broken - */ - clutter_text_set_line_wrap_mode (CLUTTER_TEXT (data->label), - PANGO_WRAP_CHAR); - pango_layout_set_wrap (data->test_layout, PANGO_WRAP_CHAR); - g_assert (check_result (data, "Change wrap mode", TRUE) == FALSE); - - /* TEST 12: enable justify */ - clutter_text_set_justify (CLUTTER_TEXT (data->label), TRUE); - pango_layout_set_justify (data->test_layout, TRUE); - /* Pango appears to have a bug which means that you can't change the - justification after setting the text but this fixes it. - See http://bugzilla.gnome.org/show_bug.cgi?id=551865 */ - pango_layout_context_changed (data->test_layout); - g_assert (check_result (data, "Enable justify", TRUE) == FALSE); - - /* TEST 13: change alignment */ - clutter_text_set_line_alignment (CLUTTER_TEXT (data->label), - PANGO_ALIGN_RIGHT); - pango_layout_set_alignment (data->test_layout, PANGO_ALIGN_RIGHT); - g_assert (check_result (data, "Change alignment", TRUE) == FALSE); - - clutter_test_quit (); - - return FALSE; -} - -static PangoLayout * -make_layout_like_label (ClutterText *label) -{ - PangoLayout *label_layout, *new_layout; - PangoContext *context; - PangoFontDescription *fd; - - /* Make another layout using the same context as the layout from the - label */ - label_layout = clutter_text_get_layout (label); - context = pango_layout_get_context (label_layout); - new_layout = pango_layout_new (context); - fd = pango_font_description_from_string (TEST_FONT); - pango_layout_set_font_description (new_layout, fd); - pango_font_description_free (fd); - - return new_layout; -} - -void -text_cache (void) -{ - CallbackData data; - - memset (&data, 0, sizeof (data)); - - data.stage = clutter_test_get_stage (); - - data.label = clutter_text_new_with_text (TEST_FONT, ""); - - data.test_layout = make_layout_like_label (CLUTTER_TEXT (data.label)); - - g_signal_connect (data.stage, "paint", G_CALLBACK (on_paint), &data); - - clutter_container_add (CLUTTER_CONTAINER (data.stage), data.label, NULL); - - clutter_actor_show (data.stage); - - clutter_threads_add_idle ((GSourceFunc) do_tests, &data); - - clutter_test_main (); - - clutter_actor_destroy (data.stage); - - if (!g_test_quiet ()) - g_print ("\nOverall result: "); - - if (!g_test_quiet ()) - { - if (data.test_failed) - g_print ("FAIL\n"); - else - g_print ("pass\n"); - } - else - g_assert (data.test_failed != TRUE); -} - diff --git a/src/tests/clutter/conform/text.c b/src/tests/clutter/conform/text.c deleted file mode 100644 index 304fa1dd4..000000000 --- a/src/tests/clutter/conform/text.c +++ /dev/null @@ -1,564 +0,0 @@ -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -typedef struct { - gunichar unichar; - const char bytes[6]; - gint nbytes; -} TestData; - -static const TestData -test_text_data[] = { - { 0xe4, "\xc3\xa4", 2 }, /* LATIN SMALL LETTER A WITH DIAERESIS */ - { 0x2665, "\xe2\x99\xa5", 3 } /* BLACK HEART SUIT */ -}; - -static void -text_utf8_validation (void) -{ - int i; - - for (i = 0; i < G_N_ELEMENTS (test_text_data); i++) - { - const TestData *t = &test_text_data[i]; - gunichar unichar; - char bytes[6]; - int nbytes; - - g_assert (g_unichar_validate (t->unichar)); - - nbytes = g_unichar_to_utf8 (t->unichar, bytes); - bytes[nbytes] = '\0'; - g_assert_cmpint (nbytes, ==, t->nbytes); - g_assert (memcmp (t->bytes, bytes, nbytes) == 0); - - unichar = g_utf8_get_char_validated (bytes, nbytes); - g_assert_cmpint (unichar, ==, t->unichar); - } -} - -static int -get_nbytes (ClutterText *text) -{ - const char *s = clutter_text_get_text (text); - return strlen (s); -} - -static int -get_nchars (ClutterText *text) -{ - const char *s = clutter_text_get_text (text); - g_assert (g_utf8_validate (s, -1, NULL)); - return g_utf8_strlen (s, -1); -} - -#define DONT_MOVE_CURSOR (-2) - -static void -insert_unichar (ClutterText *text, gunichar unichar, int position) -{ - if (position > DONT_MOVE_CURSOR) - { - clutter_text_set_cursor_position (text, position); - g_assert_cmpint (clutter_text_get_cursor_position (text), ==, position); - } - - clutter_text_insert_unichar (text, unichar); -} - -static void -text_set_empty (void) -{ - ClutterText *text = CLUTTER_TEXT (clutter_text_new ()); - g_object_ref_sink (text); - - g_assert_cmpstr (clutter_text_get_text (text), ==, ""); - g_assert_cmpint (*clutter_text_get_text (text), ==, '\0'); - g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1); - - clutter_text_set_text (text, ""); - g_assert_cmpint (get_nchars (text), ==, 0); - g_assert_cmpint (get_nbytes (text), ==, 0); - g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1); - - clutter_actor_destroy (CLUTTER_ACTOR (text)); -} - -static void -text_set_text (void) -{ - ClutterText *text = CLUTTER_TEXT (clutter_text_new ()); - g_object_ref_sink (text); - - clutter_text_set_text (text, "abcdef"); - g_assert_cmpint (get_nchars (text), ==, 6); - g_assert_cmpint (get_nbytes (text), ==, 6); - g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1); - - clutter_text_set_cursor_position (text, 5); - g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 5); - - /* FIXME: cursor position should be -1? - clutter_text_set_text (text, ""); - g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1); - */ - - clutter_actor_destroy (CLUTTER_ACTOR (text)); -} - -static void -text_append_some (void) -{ - ClutterText *text = CLUTTER_TEXT (clutter_text_new ()); - int i; - - g_object_ref_sink (text); - - for (i = 0; i < G_N_ELEMENTS (test_text_data); i++) - { - const TestData *t = &test_text_data[i]; - int j; - - for (j = 1; j <= 4; j++) - { - insert_unichar (text, t->unichar, DONT_MOVE_CURSOR); - - g_assert_cmpint (get_nchars (text), ==, j); - g_assert_cmpint (get_nbytes (text), ==, j * t->nbytes); - g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1); - } - - clutter_text_set_text (text, ""); - } - - clutter_actor_destroy (CLUTTER_ACTOR (text)); -} - -static void -text_prepend_some (void) -{ - ClutterText *text = CLUTTER_TEXT (clutter_text_new ()); - int i; - - g_object_ref_sink (text); - - for (i = 0; i < G_N_ELEMENTS (test_text_data); i++) - { - const TestData *t = &test_text_data[i]; - int j; - - clutter_text_insert_unichar (text, t->unichar); - - g_assert_cmpint (get_nchars (text), ==, 1); - g_assert_cmpint (get_nbytes (text), ==, 1 * t->nbytes); - g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1); - - for (j = 2; j <= 4; j++) - { - insert_unichar (text, t->unichar, 0); - - g_assert_cmpint (get_nchars (text), ==, j); - g_assert_cmpint (get_nbytes (text), ==, j * t->nbytes); - g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 1); - } - - clutter_text_set_text (text, ""); - } - - clutter_actor_destroy (CLUTTER_ACTOR (text)); -} - -static void -text_insert (void) -{ - ClutterText *text = CLUTTER_TEXT (clutter_text_new ()); - int i; - - g_object_ref_sink (text); - - for (i = 0; i < G_N_ELEMENTS (test_text_data); i++) - { - const TestData *t = &test_text_data[i]; - - clutter_text_insert_unichar (text, t->unichar); - clutter_text_insert_unichar (text, t->unichar); - - insert_unichar (text, t->unichar, 1); - - g_assert_cmpint (get_nchars (text), ==, 3); - g_assert_cmpint (get_nbytes (text), ==, 3 * t->nbytes); - g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 2); - - clutter_text_set_text (text, ""); - } - - clutter_actor_destroy (CLUTTER_ACTOR (text)); -} - -static void -text_delete_chars (void) -{ - ClutterText *text = CLUTTER_TEXT (clutter_text_new ()); - int i; - - g_object_ref_sink (text); - - for (i = 0; i < G_N_ELEMENTS (test_text_data); i++) - { - const TestData *t = &test_text_data[i]; - int j; - - for (j = 0; j < 4; j++) - clutter_text_insert_unichar (text, t->unichar); - - if (!g_test_quiet ()) - g_print ("text: %s\n", clutter_text_get_text (text)); - - clutter_text_set_cursor_position (text, 2); - clutter_text_delete_chars (text, 1); - if (!g_test_quiet ()) - g_print ("text: %s (cursor at: %d)\n", - clutter_text_get_text (text), - clutter_text_get_cursor_position (text)); - g_assert_cmpint (get_nchars (text), ==, 3); - g_assert_cmpint (get_nbytes (text), ==, 3 * t->nbytes); - g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 1); - - clutter_text_set_cursor_position (text, 2); - clutter_text_delete_chars (text, 1); - if (!g_test_quiet ()) - g_print ("text: %s (cursor at: %d)\n", - clutter_text_get_text (text), - clutter_text_get_cursor_position (text)); - g_assert_cmpint (get_nchars (text), ==, 2); - g_assert_cmpint (get_nbytes (text), ==, 2 * t->nbytes); - g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 1); - - clutter_text_set_text (text, ""); - } - - clutter_actor_destroy (CLUTTER_ACTOR (text)); -} - -static void -text_get_chars (void) -{ - ClutterText *text = CLUTTER_TEXT (clutter_text_new ()); - gchar *chars; - - g_object_ref_sink (text); - - clutter_text_set_text (text, "00abcdef11"); - g_assert_cmpint (get_nchars (text), ==, 10); - g_assert_cmpint (get_nbytes (text), ==, 10); - g_assert_cmpstr (clutter_text_get_text (text), ==, "00abcdef11"); - - chars = clutter_text_get_chars (text, 2, -1); - g_assert_cmpstr (chars, ==, "abcdef11"); - g_free (chars); - - chars = clutter_text_get_chars (text, 0, 8); - g_assert_cmpstr (chars, ==, "00abcdef"); - g_free (chars); - - chars = clutter_text_get_chars (text, 2, 8); - g_assert_cmpstr (chars, ==, "abcdef"); - g_free (chars); - - chars = clutter_text_get_chars (text, 8, 12); - g_assert_cmpstr (chars, ==, "11"); - g_free (chars); - - clutter_actor_destroy (CLUTTER_ACTOR (text)); -} - -static void -text_delete_text (void) -{ - ClutterText *text = CLUTTER_TEXT (clutter_text_new ()); - int i; - - g_object_ref_sink (text); - - for (i = 0; i < G_N_ELEMENTS (test_text_data); i++) - { - const TestData *t = &test_text_data[i]; - int j; - - for (j = 0; j < 4; j++) - clutter_text_insert_unichar (text, t->unichar); - - clutter_text_set_cursor_position (text, 3); - clutter_text_delete_text (text, 2, 4); - - g_assert_cmpint (get_nchars (text), ==, 2); - g_assert_cmpint (get_nbytes (text), ==, 2 * t->nbytes); - - /* FIXME: cursor position should be -1? - g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1); - */ - - clutter_text_set_text (text, ""); - } - - clutter_actor_destroy (CLUTTER_ACTOR (text)); -} - -static void -text_password_char (void) -{ - ClutterText *text = CLUTTER_TEXT (clutter_text_new ()); - - g_object_ref_sink (text); - - g_assert_cmpint (clutter_text_get_password_char (text), ==, 0); - - clutter_text_set_text (text, "hello"); - g_assert_cmpstr (clutter_text_get_text (text), ==, "hello"); - - clutter_text_set_password_char (text, '*'); - g_assert_cmpint (clutter_text_get_password_char (text), ==, '*'); - - g_assert_cmpstr (clutter_text_get_text (text), ==, "hello"); - - clutter_actor_destroy (CLUTTER_ACTOR (text)); -} - -static ClutterEvent * -init_event (void) -{ - ClutterEvent *retval = clutter_event_new (CLUTTER_KEY_PRESS); - - clutter_event_set_time (retval, CLUTTER_CURRENT_TIME); - clutter_event_set_flags (retval, CLUTTER_EVENT_FLAG_SYNTHETIC); - - return retval; -} - -static void -send_keyval (ClutterText *text, int keyval) -{ - ClutterEvent *event = init_event (); - - /* Unicode should be ignored for cursor keys etc. */ - clutter_event_set_key_unicode (event, 0); - clutter_event_set_key_symbol (event, keyval); - - clutter_actor_event (CLUTTER_ACTOR (text), event, FALSE); - - clutter_event_free (event); -} - -static void -send_unichar (ClutterText *text, gunichar unichar) -{ - ClutterEvent *event = init_event (); - - /* Key symbol should be ignored for printable characters */ - clutter_event_set_key_symbol (event, 0); - clutter_event_set_key_unicode (event, unichar); - - clutter_actor_event (CLUTTER_ACTOR (text), event, FALSE); - - clutter_event_free (event); -} - -static void -text_cursor (void) -{ - ClutterText *text = CLUTTER_TEXT (clutter_text_new ()); - int i; - - g_object_ref_sink (text); - - /* only editable entries listen to events */ - clutter_text_set_editable (text, TRUE); - - for (i = 0; i < G_N_ELEMENTS (test_text_data); i++) - { - const TestData *t = &test_text_data[i]; - int j; - - for (j = 0; j < 4; ++j) - clutter_text_insert_unichar (text, t->unichar); - - clutter_text_set_cursor_position (text, 2); - - /* test cursor moves and is clamped */ - send_keyval (text, CLUTTER_KEY_Left); - g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 1); - - send_keyval (text, CLUTTER_KEY_Left); - g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 0); - - send_keyval (text, CLUTTER_KEY_Left); - g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 0); - - /* delete text containing the cursor */ - clutter_text_set_cursor_position (text, 3); - g_assert_cmpint (clutter_text_get_cursor_position (text), ==, 3); - - clutter_text_delete_text (text, 2, 4); - send_keyval (text, CLUTTER_KEY_Left); - - /* FIXME: cursor position should be -1? - g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1); - */ - - clutter_text_set_text (text, ""); - } - - clutter_actor_destroy (CLUTTER_ACTOR (text)); -} - -static void -text_event (void) -{ - ClutterText *text = CLUTTER_TEXT (clutter_text_new ()); - int i; - - g_object_ref_sink (text); - - /* only editable entries listen to events */ - clutter_text_set_editable (text, TRUE); - - for (i = 0; i < G_N_ELEMENTS (test_text_data); i++) - { - const TestData *t = &test_text_data[i]; - - send_unichar (text, t->unichar); - - g_assert_cmpint (get_nchars (text), ==, 1); - g_assert_cmpint (get_nbytes (text), ==, 1 * t->nbytes); - g_assert_cmpint (clutter_text_get_cursor_position (text), ==, -1); - - clutter_text_set_text (text, ""); - } - - clutter_actor_destroy (CLUTTER_ACTOR (text)); -} - -static inline void -validate_markup_attributes (ClutterText *text, - PangoAttrType attr_type, - int start_index, - int end_index) -{ - PangoLayout *layout; - PangoAttrList *attrs; - PangoAttrIterator *iter; - - layout = clutter_text_get_layout (text); - g_assert (layout != NULL); - - attrs = pango_layout_get_attributes (layout); - g_assert (attrs != NULL); - - iter = pango_attr_list_get_iterator (attrs); - while (pango_attr_iterator_next (iter)) - { - GSList *attributes = pango_attr_iterator_get_attrs (iter); - PangoAttribute *a; - - if (attributes == NULL) - break; - - g_assert (attributes->data != NULL); - - a = attributes->data; - - if (a->klass->type == PANGO_ATTR_SCALE) - { - PangoAttrFloat *scale = (PangoAttrFloat*) a; - float resource_scale; - - resource_scale = clutter_actor_get_resource_scale (CLUTTER_ACTOR (text)); - - g_assert_cmpfloat (scale->value, ==, resource_scale); - g_slist_free_full (attributes, (GDestroyNotify) pango_attribute_destroy); - continue; - } - - g_assert (a->klass->type == attr_type); - g_assert_cmpint (a->start_index, ==, start_index); - g_assert_cmpint (a->end_index, ==, end_index); - - g_slist_free_full (attributes, (GDestroyNotify) pango_attribute_destroy); - } - - pango_attr_iterator_destroy (iter); -} - -static void -text_idempotent_use_markup (void) -{ - ClutterText *text; - const char *contents = "foo bar"; - const char *display = "foo bar"; - int bar_start_index = strstr (display, "bar") - display; - int bar_end_index = bar_start_index + strlen ("bar"); - - /* case 1: text -> use_markup */ - if (!g_test_quiet ()) - g_print ("text: '%s' -> use-markup: TRUE\n", contents); - - text = g_object_new (CLUTTER_TYPE_TEXT, - "text", contents, "use-markup", TRUE, - NULL); - g_object_ref_sink (text); - - if (!g_test_quiet ()) - g_print ("Contents: '%s' (expected: '%s')\n", - clutter_text_get_text (text), - display); - - g_assert_cmpstr (clutter_text_get_text (text), ==, display); - - validate_markup_attributes (text, - PANGO_ATTR_WEIGHT, - bar_start_index, - bar_end_index); - - clutter_actor_destroy (CLUTTER_ACTOR (text)); - - /* case 2: use_markup -> text */ - if (!g_test_quiet ()) - g_print ("use-markup: TRUE -> text: '%s'\n", contents); - - text = g_object_new (CLUTTER_TYPE_TEXT, - "use-markup", TRUE, "text", contents, - NULL); - - if (!g_test_quiet ()) - g_print ("Contents: '%s' (expected: '%s')\n", - clutter_text_get_text (text), - display); - - g_assert_cmpstr (clutter_text_get_text (text), ==, display); - - validate_markup_attributes (text, - PANGO_ATTR_WEIGHT, - bar_start_index, - bar_end_index); - - clutter_actor_destroy (CLUTTER_ACTOR (text)); -} - -CLUTTER_TEST_SUITE ( - CLUTTER_TEST_UNIT ("/text/utf8-validation", text_utf8_validation) - CLUTTER_TEST_UNIT ("/text/set-empty", text_set_empty) - CLUTTER_TEST_UNIT ("/text/set-text", text_set_text) - CLUTTER_TEST_UNIT ("/text/append-some", text_append_some) - CLUTTER_TEST_UNIT ("/text/prepend-some", text_prepend_some) - CLUTTER_TEST_UNIT ("/text/insert", text_insert) - CLUTTER_TEST_UNIT ("/text/delete-chars", text_delete_chars) - CLUTTER_TEST_UNIT ("/text/get-chars", text_get_chars) - CLUTTER_TEST_UNIT ("/text/delete-text", text_delete_text) - CLUTTER_TEST_UNIT ("/text/password-char", text_password_char) - CLUTTER_TEST_UNIT ("/text/cursor", text_cursor) - CLUTTER_TEST_UNIT ("/text/event", text_event) - CLUTTER_TEST_UNIT ("/text/idempotent-use-markup", text_idempotent_use_markup) -) diff --git a/src/tests/clutter/conform/texture-fbo.c b/src/tests/clutter/conform/texture-fbo.c deleted file mode 100644 index f8f274cb2..000000000 --- a/src/tests/clutter/conform/texture-fbo.c +++ /dev/null @@ -1,227 +0,0 @@ -#include -#include - -#include "test-conform-common.h" - -#define SOURCE_SIZE 32 -#define SOURCE_DIVISIONS_X 2 -#define SOURCE_DIVISIONS_Y 2 -#define DIVISION_WIDTH (SOURCE_SIZE / SOURCE_DIVISIONS_X) -#define DIVISION_HEIGHT (SOURCE_SIZE / SOURCE_DIVISIONS_Y) - -static const ClutterColor -corner_colors[SOURCE_DIVISIONS_X * SOURCE_DIVISIONS_Y] = - { - { 0xff, 0x00, 0x00, 0xff }, /* red top left */ - { 0x00, 0xff, 0x00, 0xff }, /* green top right */ - { 0x00, 0x00, 0xff, 0xff }, /* blue bottom left */ - { 0xff, 0x00, 0xff, 0xff } /* purple bottom right */ - }; - -static const ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff }; - -typedef struct _TestState -{ - ClutterActor *stage; - guint frame; - gboolean was_painted; -} TestState; - -static ClutterActor * -create_source (void) -{ - int x, y; - ClutterActor *group = clutter_actor_new (); - - /* Create a group with a different coloured rectangle at each - corner */ - for (y = 0; y < SOURCE_DIVISIONS_Y; y++) - for (x = 0; x < SOURCE_DIVISIONS_X; x++) - { - ClutterActor *rect = clutter_actor_new (); - clutter_actor_set_background_color (rect, - corner_colors + - (y * SOURCE_DIVISIONS_X + x)); - clutter_actor_set_size (rect, DIVISION_WIDTH, DIVISION_HEIGHT); - clutter_actor_set_position (rect, - DIVISION_WIDTH * x, - DIVISION_HEIGHT * y); - clutter_container_add (CLUTTER_CONTAINER (group), rect, NULL); - } - - return group; -} - -static void -pre_paint_clip_cb (void) -{ - /* Generate a clip path that clips out the top left division */ - cogl_path_move_to (DIVISION_WIDTH, 0); - cogl_path_line_to (SOURCE_SIZE, 0); - cogl_path_line_to (SOURCE_SIZE, SOURCE_SIZE); - cogl_path_line_to (0, SOURCE_SIZE); - cogl_path_line_to (0, DIVISION_HEIGHT); - cogl_path_line_to (DIVISION_WIDTH, DIVISION_HEIGHT); - cogl_path_close (); - cogl_clip_push_from_path (); -} - -static void -post_paint_clip_cb (void) -{ - cogl_clip_pop (); -} - -static void -validate_part (TestState *state, - int xpos, int ypos, - int clip_flags) -{ - int x, y; - - /* Check whether the center of each division is the right color */ - for (y = 0; y < SOURCE_DIVISIONS_Y; y++) - for (x = 0; x < SOURCE_DIVISIONS_X; x++) - { - guchar *pixels; - const ClutterColor *correct_color; - - /* Read the center pixels of this division */ - pixels = clutter_stage_read_pixels (CLUTTER_STAGE (state->stage), - x * DIVISION_WIDTH + - DIVISION_WIDTH / 2 + xpos, - y * DIVISION_HEIGHT + - DIVISION_HEIGHT / 2 + ypos, - 1, 1); - - /* If this division is clipped then it should be the stage - color */ - if ((clip_flags & (1 << ((y * SOURCE_DIVISIONS_X) + x)))) - correct_color = &stage_color; - else - /* Otherwise it should be the color for this division */ - correct_color = corner_colors + (y * SOURCE_DIVISIONS_X) + x; - - g_assert (pixels != NULL); - g_assert_cmpint (pixels[0], ==, correct_color->red); - g_assert_cmpint (pixels[1], ==, correct_color->green); - g_assert_cmpint (pixels[2], ==, correct_color->blue); - - g_free (pixels); - } -} - -static void -validate_result (TestState *state) -{ - int ypos = 0; - - if (!g_test_quiet ()) - g_print ("Testing onscreen clone...\n"); - validate_part (state, SOURCE_SIZE, ypos * SOURCE_SIZE, 0); - ypos++; - -#if 0 /* this doesn't work */ - if (!g_test_quiet ()) - g_print ("Testing offscreen clone...\n"); - validate_part (state, SOURCE_SIZE, ypos * SOURCE_SIZE, 0); -#endif - ypos++; - - if (!g_test_quiet ()) - g_print ("Testing onscreen clone with rectangular clip...\n"); - validate_part (state, SOURCE_SIZE, ypos * SOURCE_SIZE, ~1); - ypos++; - - if (!g_test_quiet ()) - g_print ("Testing onscreen clone with path clip...\n"); - validate_part (state, SOURCE_SIZE, ypos * SOURCE_SIZE, 1); - ypos++; -} - -static gboolean -on_paint (gpointer data) -{ - TestState *state = data; - int frame_num; - - /* XXX: validate_result calls clutter_stage_read_pixels which will result in - * another paint run so to avoid infinite recursion we only aim to validate - * the first frame. */ - frame_num = state->frame++; - if (frame_num == 1) - validate_result (state); - - state->was_painted = TRUE; - - return G_SOURCE_REMOVE; -} - -void -texture_fbo (TestConformSimpleFixture *fixture, - gconstpointer data) -{ - TestState state; - ClutterActor *actor; - int ypos = 0; - - state.frame = 0; - - state.stage = clutter_test_get_stage (); - - clutter_actor_set_background_color (CLUTTER_ACTOR (state.stage), &stage_color); - - /* Onscreen source with clone next to it */ - actor = create_source (); - clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL); - clutter_actor_set_position (actor, 0, ypos * SOURCE_SIZE); - actor = clutter_texture_new_from_actor (actor); - clutter_actor_set_position (actor, SOURCE_SIZE, ypos * SOURCE_SIZE); - clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL); - ypos++; - - /* Offscreen source with clone */ -#if 0 /* this doesn't work */ - actor = create_source (); - actor = clutter_texture_new_from_actor (actor); - clutter_actor_set_position (actor, SOURCE_SIZE, ypos * SOURCE_SIZE); - clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL); -#endif - ypos++; - - /* Source clipped to the top left division */ - actor = create_source (); - clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL); - clutter_actor_set_position (actor, 0, ypos * SOURCE_SIZE); - clutter_actor_set_clip (actor, 0, 0, DIVISION_WIDTH, DIVISION_HEIGHT); - actor = clutter_texture_new_from_actor (actor); - clutter_actor_set_position (actor, SOURCE_SIZE, ypos * SOURCE_SIZE); - clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL); - ypos++; - - /* Source clipped to everything but top left division using a - path */ - actor = create_source (); - clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL); - clutter_actor_set_position (actor, 0, ypos * SOURCE_SIZE); - g_signal_connect (actor, "paint", - G_CALLBACK (pre_paint_clip_cb), NULL); - g_signal_connect_after (actor, "paint", - G_CALLBACK (post_paint_clip_cb), NULL); - actor = clutter_texture_new_from_actor (actor); - clutter_actor_set_position (actor, SOURCE_SIZE, ypos * SOURCE_SIZE); - clutter_container_add (CLUTTER_CONTAINER (state.stage), actor, NULL); - ypos++; - - clutter_actor_show (state.stage); - - clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT, - on_paint, - &state, - NULL); - - while (!state.was_painted) - g_main_context_iteration (NULL, FALSE); - - clutter_actor_destroy (state.stage); -} diff --git a/src/tests/clutter/conform/timeline-interpolate.c b/src/tests/clutter/conform/timeline-interpolate.c deleted file mode 100644 index b63461d93..000000000 --- a/src/tests/clutter/conform/timeline-interpolate.c +++ /dev/null @@ -1,211 +0,0 @@ -#define CLUTTER_DISABLE_DEPRECATION_WARNINGS -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -#define TEST_TIMELINE_DURATION 3000 - -/* - * Make the test tolarate being half a second off track in each direction, - * the thing we're testing for will still be tested for. - */ -#define TEST_ERROR_TOLERANCE 500 - -typedef struct _TestState -{ - ClutterTimeline *timeline; - int64_t start_time_us; - int new_frame_counter; - int expected_frame; - int completion_count; - int cycle_frame_counter; -} TestState; - - -static void -new_frame_cb (ClutterTimeline *timeline, - int frame_num, - TestState *state) -{ - int64_t current_time_us; - int current_frame_ms; - long msec_diff; - int loop_overflow = 0; - - current_time_us = g_get_monotonic_time (); - current_frame_ms = clutter_timeline_get_elapsed_time (state->timeline); - msec_diff = us2ms (current_time_us - state->start_time_us); - - /* If we expect to have interpolated past the end of the timeline - * we keep track of the overflow so we can determine when - * the next timeout will happen. We then clip expected_frames - * to TEST_TIMELINE_DURATION since clutter-timeline - * semantics guaranty this frame is always signaled before - * looping */ - if (state->expected_frame > TEST_TIMELINE_DURATION) - { - loop_overflow = state->expected_frame - TEST_TIMELINE_DURATION; - state->expected_frame = TEST_TIMELINE_DURATION; - } - - switch (state->cycle_frame_counter) - { - case 0: - case 1: - if (current_frame_ms >= (state->expected_frame - TEST_ERROR_TOLERANCE) && - current_frame_ms <= (state->expected_frame + TEST_ERROR_TOLERANCE)) - { - g_test_message ("elapsed milliseconds=%-5li " - "expected frame=%-4i actual frame=%-4i (OK)", - msec_diff, - state->expected_frame, - current_frame_ms); - } - else - { - g_test_message ("elapsed milliseconds=%-5li " - "expected frame=%-4i actual frame=%-4i (FAILED)", - msec_diff, - state->expected_frame, - current_frame_ms); - g_test_fail (); - } - break; - case 2: - g_assert_cmpint (current_frame_ms, ==, TEST_TIMELINE_DURATION); - break; - default: - g_assert_not_reached (); - } - - /* We already tested that we interpolated when looping, lets stop now. */ - if (state->completion_count == 1 && - state->cycle_frame_counter == 0) - { - clutter_timeline_stop (timeline); - return; - } - - switch (state->cycle_frame_counter) - { - case 0: - { - /* - * First frame, sleep so we're about in the middle of the cycle, - * before the end of the timeline cycle. - */ - int delay_ms = ms (1500); - - state->expected_frame = current_frame_ms + delay_ms; - g_test_message ("Sleeping for 1.5 seconds " - "so next frame should be (%d + %d) = %d", - current_frame_ms, - delay_ms, - state->expected_frame); - g_usleep (ms2us (delay_ms)); - break; - } - case 1: - { - /* - * Second frame, we're about in the middle of the cycle; sleep one cycle, - * and check that we end up in the middle again. - */ - int delay_ms = TEST_TIMELINE_DURATION; - - state->expected_frame = current_frame_ms + delay_ms; - g_test_message ("Sleeping for %d seconds " - "so next frame should be (%d + %d) = %d, " - "which is %d into the next cycle", - TEST_TIMELINE_DURATION / 1000, - current_frame_ms, - delay_ms, - state->expected_frame, - state->expected_frame - TEST_TIMELINE_DURATION); - g_usleep (ms2us (delay_ms)); - - g_assert_cmpint (state->expected_frame, >, TEST_TIMELINE_DURATION); - - state->expected_frame += loop_overflow; - state->expected_frame -= TEST_TIMELINE_DURATION; - g_test_message ("End of timeline reached: " - "Wrapping expected frame too %d", - state->expected_frame); - break; - } - case 2: - case 3: - { - break; - } - } - - state->new_frame_counter++; - state->cycle_frame_counter++; -} - -static void -completed_cb (ClutterTimeline *timeline, - TestState *state) -{ - state->completion_count++; - state->cycle_frame_counter = 0; - - if (state->completion_count >= 2) - g_assert_not_reached (); -} - -static void -stopped_cb (ClutterTimeline *timeline, - gboolean is_finished, - TestState *state) -{ - g_assert_cmpint (state->completion_count, ==, 1); - - clutter_test_quit (); -} - -static void -timeline_interpolation (void) -{ - ClutterActor *stage; - TestState state; - - stage = clutter_test_get_stage (); - - state.timeline = - clutter_timeline_new_for_actor (stage, TEST_TIMELINE_DURATION); - clutter_timeline_set_repeat_count (state.timeline, -1); - g_signal_connect (state.timeline, - "new-frame", - G_CALLBACK (new_frame_cb), - &state); - g_signal_connect (state.timeline, - "completed", - G_CALLBACK (completed_cb), - &state); - g_signal_connect (state.timeline, - "stopped", - G_CALLBACK (stopped_cb), - &state); - - state.completion_count = 0; - state.new_frame_counter = 0; - state.cycle_frame_counter = 0; - state.expected_frame = 0; - - clutter_actor_show (stage); - - state.start_time_us = g_get_monotonic_time (); - clutter_timeline_start (state.timeline); - - clutter_test_main (); - - g_object_unref (state.timeline); -} - -CLUTTER_TEST_SUITE ( - CLUTTER_TEST_UNIT ("/timeline/interpolate", timeline_interpolation) -) diff --git a/src/tests/clutter/conform/timeline-progress.c b/src/tests/clutter/conform/timeline-progress.c deleted file mode 100644 index fc4ce8421..000000000 --- a/src/tests/clutter/conform/timeline-progress.c +++ /dev/null @@ -1,117 +0,0 @@ -#define CLUTTER_DISABLE_DEPRECATION_WARNINGS -#include -#include - -#include "tests/clutter-test-utils.h" - -static void -timeline_progress_step (void) -{ - ClutterActor *stage = clutter_test_get_stage (); - ClutterTimeline *timeline; - - timeline = clutter_timeline_new_for_actor (stage, 1000); - - if (!g_test_quiet ()) - g_print ("mode: step(3, end)\n"); - - clutter_timeline_rewind (timeline); - clutter_timeline_set_step_progress (timeline, 3, CLUTTER_STEP_MODE_END); - g_assert_cmpint (clutter_timeline_get_progress (timeline), ==, 0); - - clutter_timeline_advance (timeline, 1000 / 3 - 1); - g_assert_cmpint (clutter_timeline_get_progress (timeline) * 1000, ==, 0); - - clutter_timeline_advance (timeline, 1000 / 3 + 1); - g_assert_cmpint (clutter_timeline_get_progress (timeline) * 1000, ==, 333); - - clutter_timeline_advance (timeline, 1000 / 3 * 2 - 1); - g_assert_cmpint (clutter_timeline_get_progress (timeline) * 1000, ==, 333); - - clutter_timeline_advance (timeline, 1000 / 3 * 2 + 1); - g_assert_cmpint (clutter_timeline_get_progress (timeline) * 1000, ==, 666); - - clutter_timeline_rewind (timeline); - clutter_timeline_set_progress_mode (timeline, CLUTTER_STEP_START); - g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 0.0); - - clutter_timeline_advance (timeline, 1); - g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 1.0); - - clutter_timeline_advance (timeline, 500); - g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 1.0); - - clutter_timeline_advance (timeline, 999); - g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 1.0); - - clutter_timeline_advance (timeline, 1000); - g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 1.0); - - if (!g_test_quiet ()) - g_print ("mode: step-start\n"); - - clutter_timeline_rewind (timeline); - clutter_timeline_set_progress_mode (timeline, CLUTTER_STEP_START); - g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 0.0); - - clutter_timeline_advance (timeline, 1); - g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 1.0); - - clutter_timeline_advance (timeline, 500); - g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 1.0); - - clutter_timeline_advance (timeline, 999); - g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 1.0); - - clutter_timeline_advance (timeline, 1000); - g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 1.0); - - if (!g_test_quiet ()) - g_print ("mode: step-end\n"); - - clutter_timeline_rewind (timeline); - clutter_timeline_set_progress_mode (timeline, CLUTTER_STEP_END); - g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 0.0); - - clutter_timeline_advance (timeline, 1); - g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 0.0); - - clutter_timeline_advance (timeline, 500); - g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 0.0); - - clutter_timeline_advance (timeline, 999); - g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 0.0); - - clutter_timeline_advance (timeline, 1000); - g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 1.0); - - g_object_unref (timeline); -} - -static void -timeline_progress_mode (void) -{ - ClutterActor *stage = clutter_test_get_stage (); - ClutterTimeline *timeline; - - timeline = clutter_timeline_new_for_actor (stage, 1000); - - g_assert (clutter_timeline_get_progress_mode (timeline) == CLUTTER_LINEAR); - g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 0.0); - - clutter_timeline_advance (timeline, 500); - g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 0.5); - - clutter_timeline_advance (timeline, 1000); - g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 1.0); - - clutter_timeline_rewind (timeline); - g_assert_cmpfloat (clutter_timeline_get_progress (timeline), ==, 0.0); - - g_object_unref (timeline); -} - -CLUTTER_TEST_SUITE ( - CLUTTER_TEST_UNIT ("/timeline/progress/step", timeline_progress_step); - CLUTTER_TEST_UNIT ("/timeline/progress/mode", timeline_progress_mode) -) diff --git a/src/tests/clutter/conform/timeline-rewind.c b/src/tests/clutter/conform/timeline-rewind.c deleted file mode 100644 index aadedc5d1..000000000 --- a/src/tests/clutter/conform/timeline-rewind.c +++ /dev/null @@ -1,102 +0,0 @@ -#define CLUTTER_DISABLE_DEPRECATION_WARNINGS -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -#define TEST_TIMELINE_DURATION 500 -#define TEST_WATCHDOG_KICK_IN_SECONDS 10 - -typedef struct _TestState -{ - ClutterTimeline *timeline; - gint rewind_count; -} TestState; - -static gboolean -watchdog_timeout (gpointer data) -{ - TestState *state = data; - - g_test_message ("Watchdog timer kicking in"); - g_test_message ("rewind_count=%i", state->rewind_count); - if (state->rewind_count <= 3) - { - /* The test has hung */ - g_test_message ("Failed (This test shouldn't have hung!)"); - exit (EXIT_FAILURE); - } - else - { - g_test_message ("Passed"); - clutter_test_quit (); - } - - return G_SOURCE_REMOVE; -} - -static void -new_frame_cb (ClutterTimeline *timeline, - gint elapsed_time, - TestState *state) -{ - if (elapsed_time == TEST_TIMELINE_DURATION) - { - g_test_message ("new-frame signal received (end of timeline)"); - g_test_message ("Rewinding timeline"); - clutter_timeline_rewind (timeline); - state->rewind_count++; - } - else - { - if (elapsed_time == 0) - { - g_test_message ("new-frame signal received (start of timeline)"); - } - else - { - g_test_message ("new-frame signal received (mid frame)"); - } - - if (state->rewind_count >= 2) - { - g_test_message ("Sleeping for 1 second"); - g_usleep (1000000); - } - } -} - -static void -timeline_rewind (void) -{ - ClutterActor *stage; - TestState state; - - stage = clutter_test_get_stage (); - - state.timeline = - clutter_timeline_new_for_actor (stage, TEST_TIMELINE_DURATION); - g_signal_connect (G_OBJECT(state.timeline), - "new-frame", - G_CALLBACK(new_frame_cb), - &state); - g_test_message ("Installing a watchdog timeout " - "to determine if this test hangs"); - clutter_threads_add_timeout (TEST_WATCHDOG_KICK_IN_SECONDS * 1000, - watchdog_timeout, - &state); - state.rewind_count = 0; - - clutter_actor_show (stage); - - clutter_timeline_start (state.timeline); - - clutter_test_main (); - - g_object_unref (state.timeline); -} - -CLUTTER_TEST_SUITE ( - CLUTTER_TEST_UNIT ("/timeline/rewind", timeline_rewind) -) diff --git a/src/tests/clutter/conform/timeline.c b/src/tests/clutter/conform/timeline.c deleted file mode 100644 index 6bd8f32bb..000000000 --- a/src/tests/clutter/conform/timeline.c +++ /dev/null @@ -1,365 +0,0 @@ -#define CLUTTER_DISABLE_DEPRECATION_WARNINGS -#include -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -/* This test runs three timelines at 6 fps with 10 frames. Some of - the timelines have markers. Once the timelines are run it then - checks that all of the frames were hit, all of the markers were hit - and that the completed signal was fired. The timelines are then run - again but this time with a timeout source that introduces a - delay. This should cause some frames to be skipped. The test is run - again but only the markers and the completed signal is checked - for. */ - -#define FRAME_COUNT 10 -#define FPS 6 - -typedef struct _TimelineData TimelineData; - -struct _TimelineData -{ - int timeline_num; - - guint frame_hit_count[FRAME_COUNT + 1]; - GSList *markers_hit; - guint completed_count; -}; - -static void -timeline_data_init (TimelineData *data, int timeline_num) -{ - memset (data, 0, sizeof (TimelineData)); - data->timeline_num = timeline_num; -} - -static void -timeline_data_destroy (TimelineData *data) -{ - g_slist_free_full (data->markers_hit, g_free); -} - -static void -timeline_complete_cb (ClutterTimeline *timeline, - TimelineData *data) -{ - g_printerr ("%i: Completed\n", data->timeline_num); - - data->completed_count++; -} - -static void -timeline_new_frame_cb (ClutterTimeline *timeline, - gint msec, - TimelineData *data) -{ - /* Calculate an approximate frame number from the duration with - rounding */ - int frame_no = ((msec * FRAME_COUNT + (FRAME_COUNT * 1000 / FPS) / 2) - / (FRAME_COUNT * 1000 / FPS)); - - g_printerr ("%i: Doing frame %d, delta = %i\n", - data->timeline_num, frame_no, - clutter_timeline_get_delta (timeline)); - - g_assert (frame_no >= 0 && frame_no <= FRAME_COUNT); - - data->frame_hit_count[frame_no]++; -} - -static void -timeline_marker_reached_cb (ClutterTimeline *timeline, - const gchar *marker_name, - guint frame_num, - TimelineData *data) -{ - g_printerr ("%i: Marker '%s' (%d) reached, delta = %i\n", - data->timeline_num, marker_name, frame_num, - clutter_timeline_get_delta (timeline)); - data->markers_hit = g_slist_prepend (data->markers_hit, - g_strdup (marker_name)); -} - -static gboolean -check_timeline (ClutterTimeline *timeline, - TimelineData *data, - gboolean check_missed_frames) -{ - gchar **markers; - gsize n_markers; - guint *marker_reached_count; - gboolean succeeded = TRUE; - GSList *node; - int i; - int missed_frame_count = 0; - int frame_offset; - - if (clutter_timeline_get_direction (timeline) == CLUTTER_TIMELINE_BACKWARD) - frame_offset = 0; - else - frame_offset = 1; - - markers = clutter_timeline_list_markers (timeline, -1, &n_markers); - marker_reached_count = g_new0 (guint, n_markers); - - for (node = data->markers_hit; node; node = node->next) - { - for (i = 0; i < n_markers; i++) - if (!strcmp (node->data, markers[i])) - break; - - if (i < n_markers) - marker_reached_count[i]++; - else - { - g_printerr ("FAIL: unknown marker '%s' hit for timeline %i\n", - (char *) node->data, data->timeline_num); - succeeded = FALSE; - } - } - - for (i = 0; i < n_markers; i++) - if (marker_reached_count[i] != 1) - { - g_printerr ("FAIL: marker '%s' hit %i times for timeline %i\n", - markers[i], marker_reached_count[i], data->timeline_num); - succeeded = FALSE; - } - - if (check_missed_frames) - { - for (i = 0; i < FRAME_COUNT; i++) - if (data->frame_hit_count[i + frame_offset] < 1) - missed_frame_count++; - - if (missed_frame_count) - { - g_printerr ("FAIL: missed %i frame%s for timeline %i\n", - missed_frame_count, missed_frame_count == 1 ? "" : "s", - data->timeline_num); - succeeded = FALSE; - } - } - - if (data->completed_count != 1) - { - g_printerr ("FAIL: timeline %i completed %i times\n", - data->timeline_num, data->completed_count); - succeeded = FALSE; - } - - g_strfreev (markers); - g_free (marker_reached_count); - - return succeeded; -} - -static gboolean -timeout_cb (gpointer data G_GNUC_UNUSED) -{ - clutter_test_quit (); - - return FALSE; -} - -static gboolean -delay_cb (gpointer data) -{ - /* Waste a bit of time so that it will skip frames */ - g_usleep (G_USEC_PER_SEC * 66 / 1000); - - return TRUE; -} - -static gboolean -add_timeout_idle (gpointer user_data) -{ - clutter_threads_add_timeout (2000, timeout_cb, NULL); - - return G_SOURCE_REMOVE; -} - -static void -timeline_base (void) -{ - ClutterActor *stage; - ClutterTimeline *timeline_1; - TimelineData data_1; - ClutterTimeline *timeline_2; - TimelineData data_2; - ClutterTimeline *timeline_3; - TimelineData data_3; - gchar **markers; - gsize n_markers; - guint delay_tag; - - stage = clutter_test_get_stage (); - - timeline_data_init (&data_1, 1); - timeline_1 = clutter_timeline_new_for_actor (stage, FRAME_COUNT * 1000 / FPS); - clutter_timeline_add_marker_at_time (timeline_1, "start-marker", - 0 * 1000 / FPS); - clutter_timeline_add_marker_at_time (timeline_1, "foo", 5 * 1000 / FPS); - clutter_timeline_add_marker_at_time (timeline_1, "bar", 5 * 1000 / FPS); - clutter_timeline_add_marker_at_time (timeline_1, "baz", 5 * 1000 / FPS); - clutter_timeline_add_marker_at_time (timeline_1, "near-end-marker", - 9 * 1000 / FPS); - clutter_timeline_add_marker_at_time (timeline_1, "end-marker", - 10 * 1000 / FPS); - markers = clutter_timeline_list_markers (timeline_1, 5 * 1000 / FPS, - &n_markers); - g_assert (markers != NULL); - g_assert (n_markers == 3); - g_strfreev (markers); - - timeline_data_init (&data_2, 2); - timeline_2 = clutter_timeline_new_for_actor (stage, FRAME_COUNT * 1000 / FPS); - clutter_timeline_add_marker_at_time (timeline_2, "bar", 2 * 1000 / FPS); - markers = clutter_timeline_list_markers (timeline_2, -1, &n_markers); - g_assert (markers != NULL); - g_assert (n_markers == 1); - g_assert (strcmp (markers[0], "bar") == 0); - g_strfreev (markers); - - timeline_data_init (&data_3, 3); - timeline_3 = clutter_timeline_new_for_actor (stage, FRAME_COUNT * 1000 / FPS); - clutter_timeline_set_direction (timeline_3, CLUTTER_TIMELINE_BACKWARD); - clutter_timeline_add_marker_at_time (timeline_3, "start-marker", - FRAME_COUNT * 1000 / FPS); - clutter_timeline_add_marker_at_time (timeline_3, "foo", 5 * 1000 / FPS); - clutter_timeline_add_marker_at_time (timeline_3, "baz", 8 * 1000 / FPS); - clutter_timeline_add_marker_at_time (timeline_3, "near-end-marker", - 1 * 1000 / FPS); - clutter_timeline_add_marker_at_time (timeline_3, "end-marker", - 0 * 1000 / FPS); - - g_signal_connect (timeline_1, - "marker-reached", G_CALLBACK (timeline_marker_reached_cb), - &data_1); - g_signal_connect (timeline_1, - "new-frame", G_CALLBACK (timeline_new_frame_cb), - &data_1); - g_signal_connect (timeline_1, - "completed", G_CALLBACK (timeline_complete_cb), - &data_1); - - g_signal_connect (timeline_2, - "marker-reached::bar", - G_CALLBACK (timeline_marker_reached_cb), - &data_2); - g_signal_connect (timeline_2, - "new-frame", G_CALLBACK (timeline_new_frame_cb), - &data_2); - g_signal_connect (timeline_2, - "completed", G_CALLBACK (timeline_complete_cb), - &data_2); - - g_signal_connect (timeline_3, - "marker-reached", G_CALLBACK (timeline_marker_reached_cb), - &data_3); - g_signal_connect (timeline_3, - "new-frame", G_CALLBACK (timeline_new_frame_cb), - &data_3); - g_signal_connect (timeline_3, - "completed", G_CALLBACK (timeline_complete_cb), - &data_3); - - clutter_actor_show (stage); - - g_printerr ("Without delay...\n"); - - clutter_timeline_start (timeline_1); - clutter_timeline_start (timeline_2); - clutter_timeline_start (timeline_3); - - g_idle_add (add_timeout_idle, NULL); - - clutter_test_main (); - - g_assert (check_timeline (timeline_1, &data_1, TRUE)); - g_assert (check_timeline (timeline_2, &data_2, TRUE)); - g_assert (check_timeline (timeline_3, &data_3, TRUE)); - - g_printerr ("With delay...\n"); - - timeline_data_destroy (&data_1); - timeline_data_init (&data_1, 1); - timeline_data_destroy (&data_2); - timeline_data_init (&data_2, 2); - timeline_data_destroy (&data_3); - timeline_data_init (&data_3, 3); - - clutter_timeline_start (timeline_1); - clutter_timeline_start (timeline_2); - clutter_timeline_start (timeline_3); - - clutter_threads_add_timeout (2000, timeout_cb, NULL); - delay_tag = clutter_threads_add_timeout (99, delay_cb, NULL); - - clutter_test_main (); - - g_assert (check_timeline (timeline_1, &data_1, FALSE)); - g_assert (check_timeline (timeline_2, &data_2, FALSE)); - g_assert (check_timeline (timeline_3, &data_3, FALSE)); - - g_object_unref (timeline_1); - g_object_unref (timeline_2); - g_object_unref (timeline_3); - - timeline_data_destroy (&data_1); - timeline_data_destroy (&data_2); - timeline_data_destroy (&data_3); - - g_clear_handle_id (&delay_tag, g_source_remove); -} - -static void -timeline_markers_from_script (void) -{ - ClutterScript *script = clutter_script_new (); - ClutterTimeline *timeline; - GError *error = NULL; - gchar *test_file; - gchar **markers; - gsize n_markers; - - test_file = g_test_build_filename (G_TEST_DIST, - "scripts", - "test-script-timeline-markers.json", - NULL); - if (!clutter_script_load_from_file (script, test_file, &error)) - g_printerr ("Error: %s", error->message); - - g_assert_no_error (error); - - timeline = CLUTTER_TIMELINE (clutter_script_get_object (script, "timeline0")); - - g_assert (clutter_timeline_has_marker (timeline, "marker0")); - g_assert (clutter_timeline_has_marker (timeline, "marker1")); - g_assert (!clutter_timeline_has_marker (timeline, "foo")); - g_assert (clutter_timeline_has_marker (timeline, "marker2")); - g_assert (clutter_timeline_has_marker (timeline, "marker3")); - - markers = clutter_timeline_list_markers (timeline, -1, &n_markers); - g_assert_cmpint (n_markers, ==, 4); - g_strfreev (markers); - - markers = clutter_timeline_list_markers (timeline, 500, &n_markers); - g_assert_cmpint (n_markers, ==, 2); - g_assert (markers != NULL); - g_assert (g_strv_contains ((const char * const *) markers, "marker1")); - g_assert (g_strv_contains ((const char * const *) markers, "marker3")); - g_strfreev (markers); - - g_object_unref (script); - - g_free (test_file); -} - -CLUTTER_TEST_SUITE ( - CLUTTER_TEST_UNIT ("/timeline/base", timeline_base); - CLUTTER_TEST_UNIT ("/timeline/markers-from-script", timeline_markers_from_script) -) diff --git a/src/tests/clutter/conform/units.c b/src/tests/clutter/conform/units.c deleted file mode 100644 index bcfb5890d..000000000 --- a/src/tests/clutter/conform/units.c +++ /dev/null @@ -1,133 +0,0 @@ -#include - -#include "tests/clutter-test-utils.h" - -static void -units_cache (void) -{ - ClutterUnits units; - ClutterSettings *settings; - gfloat pixels; - gint old_dpi; - - settings = clutter_settings_get_default (); - g_object_get (settings, "font-dpi", &old_dpi, NULL); - - g_object_set (settings, "font-dpi", 96 * 1024, NULL); - clutter_units_from_em (&units, 1.0); - pixels = clutter_units_to_pixels (&units); - - g_object_set (settings, "font-dpi", ((96 * 2) * 1024), NULL); - g_assert_cmpfloat (clutter_units_to_pixels (&units), !=, pixels); - - g_object_set (settings, "font-dpi", (96 * 1024), NULL); - g_assert_cmpfloat (clutter_units_to_pixels (&units), ==, pixels); - - g_object_set (settings, "font-dpi", old_dpi, NULL); -} - -static void -units_constructors (void) -{ - ClutterUnits units, units_cm; - - clutter_units_from_pixels (&units, 100); - g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_PIXEL); - g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 100.0); - g_assert_cmpfloat (clutter_units_to_pixels (&units), ==, 100.0); - - clutter_units_from_em (&units, 5.0); - g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_EM); - g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 5.0); - g_assert_cmpfloat (clutter_units_to_pixels (&units), !=, 5.0); - - clutter_units_from_cm (&units_cm, 5.0); - g_assert (clutter_units_get_unit_type (&units_cm) == CLUTTER_UNIT_CM); - g_assert_cmpfloat (clutter_units_get_unit_value (&units_cm), ==, 5.0); - g_assert_cmpfloat (clutter_units_to_pixels (&units_cm), !=, 5.0); - - clutter_units_from_mm (&units, 50.0); - g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_MM); - g_assert_cmpfloat (clutter_units_to_pixels (&units), - ==, - clutter_units_to_pixels (&units_cm)); -} - -static void -units_string (void) -{ - ClutterUnits units; - gchar *string; - - g_assert (clutter_units_from_string (&units, "") == FALSE); - - g_assert (clutter_units_from_string (&units, "10") == TRUE); - g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_PIXEL); - g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 10); - - g_assert (clutter_units_from_string (&units, "10 px") == TRUE); - g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_PIXEL); - - g_assert (clutter_units_from_string (&units, "10 mm") == TRUE); - g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_MM); - - g_assert (clutter_units_from_string (&units, "10 cm") == TRUE); - g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_CM); - - g_assert (clutter_units_from_string (&units, "10 ") == TRUE); - g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_PIXEL); - g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 10); - - g_assert (clutter_units_from_string (&units, "5 em") == TRUE); - g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_EM); - g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 5); - - g_assert (clutter_units_from_string (&units, "5 emeralds") == FALSE); - - g_assert (clutter_units_from_string (&units, " 16 mm") == TRUE); - g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_MM); - g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 16); - - g_assert (clutter_units_from_string (&units, " 24 pt ") == TRUE); - g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_POINT); - g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 24); - - g_assert (clutter_units_from_string (&units, " 32 em garbage") == FALSE); - - g_assert (clutter_units_from_string (&units, "5.1cm") == TRUE); - g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_CM); - g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 5.1f); - - g_assert (clutter_units_from_string (&units, "5,mm") == FALSE); - - g_assert (clutter_units_from_string (&units, ".5pt") == TRUE); - g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_POINT); - g_assert_cmpfloat (clutter_units_get_unit_value (&units), ==, 0.5f); - - g_assert (clutter_units_from_string (&units, "1 omg!!pony") == FALSE); - - clutter_units_from_pt (&units, 24.0); - string = clutter_units_to_string (&units); - g_assert_cmpstr (string, ==, "24.0 pt"); - g_free (string); - - clutter_units_from_em (&units, 3.0); - string = clutter_units_to_string (&units); - g_assert_cmpstr (string, ==, "3.00 em"); - - units.unit_type = CLUTTER_UNIT_PIXEL; - units.value = 0; - - g_assert (clutter_units_from_string (&units, string) == TRUE); - g_assert (clutter_units_get_unit_type (&units) != CLUTTER_UNIT_PIXEL); - g_assert (clutter_units_get_unit_type (&units) == CLUTTER_UNIT_EM); - g_assert_cmpint ((int) clutter_units_get_unit_value (&units), ==, 3); - - g_free (string); -} - -CLUTTER_TEST_SUITE ( - CLUTTER_TEST_UNIT ("/units/string", units_string) - CLUTTER_TEST_UNIT ("/units/cache", units_cache) - CLUTTER_TEST_UNIT ("/units/constructors", units_constructors) -) diff --git a/src/tests/clutter/interactive/light0.png b/src/tests/clutter/interactive/light0.png deleted file mode 100644 index 52c64e81a..000000000 Binary files a/src/tests/clutter/interactive/light0.png and /dev/null differ diff --git a/src/tests/clutter/interactive/meson.build b/src/tests/clutter/interactive/meson.build deleted file mode 100644 index e853184ef..000000000 --- a/src/tests/clutter/interactive/meson.build +++ /dev/null @@ -1,74 +0,0 @@ -clutter_tests_interactive_srcdir = meson.current_source_dir() -clutter_tests_interactive_includepath = include_directories('.') - -clutter_tests_interactive_c_args = [ - '-DTESTS_DATADIR="@0@"'.format(clutter_tests_interactive_srcdir), - '-DG_DISABLE_SINGLE_INCLUDES', - '-DGLIB_DISABLE_DEPRECATION_WARNINGS', - '-DCOGL_DISABLE_DEPRECATION_WARNINGS', - '-DCLUTTER_DISABLE_DEPRECATION_WARNINGS', - '-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name()), -] -clutter_tests_interactive_c_args += clutter_debug_c_args - -clutter_tests_interactive_link_args = [ - '-Wl,--export-dynamic', -] - -clutter_tests_interactive_test_sources = [ - 'test-events.c', - 'test-actors.c', - 'test-script.c', - 'test-grab.c', - 'test-cogl-shader-glsl.c', - 'test-cogl-tex-tile.c', - 'test-cogl-tex-convert.c', - 'test-cogl-offscreen.c', - 'test-cogl-tex-polygon.c', - 'test-animation.c', - 'test-easing.c', - 'test-binding-pool.c', - 'test-text.c', - 'test-text-field.c', - 'test-cairo-clock.c', - 'test-cairo-flowers.c', - 'test-stage-sizing.c', - 'test-swipe-action.c', - 'test-cogl-point-sprites.c', - 'test-devices.c', - 'test-content.c', - 'test-keyframe-transition.c', - 'test-touch-events.c', - 'test-rotate-zoom.c', - 'test-image.c', -] - -gen_test_unit_names = find_program('meson/gen-test-unit-names.sh') -clutter_interactive_test_unit_names_h = custom_target('gen-test-unit-names', - output: 'test-unit-names.h', - input: clutter_tests_interactive_test_sources, - command: [gen_test_unit_names, '@OUTPUT@', '@INPUT@'], - install: false, -) - -clutter_tests_interactive_sources = [ - 'test-main.c', - clutter_interactive_test_unit_names_h, - clutter_tests_interactive_test_sources, - clutter_test_utils, -] - -executable('test-interactive', - sources: clutter_tests_interactive_sources, - include_directories: [ - clutter_includes, - clutter_tests_includes, - clutter_tests_interactive_includepath, - ], - c_args: clutter_tests_interactive_c_args, - link_args: clutter_tests_interactive_link_args, - dependencies: [ - libmutter_test_dep, - ], - install: false, -) diff --git a/src/tests/clutter/interactive/meson/gen-test-unit-names.sh b/src/tests/clutter/interactive/meson/gen-test-unit-names.sh deleted file mode 100755 index 72c5bf362..000000000 --- a/src/tests/clutter/interactive/meson/gen-test-unit-names.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -outputfile=$1 -shift - -echo '/* ** This file is autogenerated. Do not edit. ** */' > "$outputfile" -echo '' >> "$outputfile" -echo 'const char *test_unit_names[] = {' >> "$outputfile" - -for test_source_file in "$@"; do - echo " \"$(echo "$test_source_file" | sed 's/.*\(test-[a-z0-9\-]\+\)\.c/\1/')\"," >> "$outputfile" -done - -echo '};' >> "$outputfile" diff --git a/src/tests/clutter/interactive/redhand.png b/src/tests/clutter/interactive/redhand.png deleted file mode 100644 index c07d8acd3..000000000 Binary files a/src/tests/clutter/interactive/redhand.png and /dev/null differ diff --git a/src/tests/clutter/interactive/redhand_alpha.png b/src/tests/clutter/interactive/redhand_alpha.png deleted file mode 100644 index 42a93c3a4..000000000 Binary files a/src/tests/clutter/interactive/redhand_alpha.png and /dev/null differ diff --git a/src/tests/clutter/interactive/test-actors.c b/src/tests/clutter/interactive/test-actors.c deleted file mode 100644 index 353adc750..000000000 --- a/src/tests/clutter/interactive/test-actors.c +++ /dev/null @@ -1,264 +0,0 @@ -#include - -#include -#include -#include -#include -#include - -#include "test-utils.h" -#include "tests/clutter-test-utils.h" - -#define NHANDS 6 - -typedef struct SuperOH -{ - ClutterActor **hand; - ClutterActor *bgtex; - ClutterActor *real_hand; - ClutterActor *group; - ClutterActor *stage; - - gint stage_width; - gint stage_height; - gfloat radius; - - ClutterTimeline *timeline; -} SuperOH; - -int -test_actors_main (int argc, char *argv[]); - -static void -on_group_destroy (ClutterActor *actor, - SuperOH *oh) -{ - oh->group = NULL; -} - -static void -on_hand_destroy (ClutterActor *actor, - SuperOH *oh) -{ - int i; - - for (i = 0; i < NHANDS; i++) - { - if (oh->hand[i] == actor) - oh->hand[i] = NULL; - } -} - -static gboolean -on_button_press_event (ClutterActor *actor, - ClutterEvent *event, - SuperOH *oh) -{ - gfloat x, y; - - clutter_event_get_coords (event, &x, &y); - - g_print ("*** button press event (button:%d) at %.2f, %.2f on %s ***\n", - clutter_event_get_button (event), - x, y, - clutter_actor_get_name (actor)); - - clutter_actor_hide (actor); - - return TRUE; -} - -static gboolean -input_cb (ClutterActor *stage, - ClutterEvent *event, - gpointer data) -{ - SuperOH *oh = data; - - if (event->type == CLUTTER_KEY_RELEASE) - { - g_print ("*** key press event (key:%c) ***\n", - clutter_event_get_key_symbol (event)); - - if (clutter_event_get_key_symbol (event) == CLUTTER_KEY_q) - { - clutter_test_quit (); - - return TRUE; - } - else if (clutter_event_get_key_symbol (event) == CLUTTER_KEY_r) - { - gint i; - - for (i = 0; i < NHANDS; i++) - { - if (oh->hand[i] != NULL) - clutter_actor_show (oh->hand[i]); - } - - return TRUE; - } - } - - return FALSE; -} - -/* Timeline handler */ -static void -frame_cb (ClutterTimeline *timeline, - gint msecs, - gpointer data) -{ - SuperOH *oh = data; - gint i; - float rotation = clutter_timeline_get_progress (timeline) * 360.0f; - - /* Rotate everything clockwise about stage center*/ - if (oh->group != NULL) - clutter_actor_set_rotation_angle (oh->group, CLUTTER_Z_AXIS, rotation); - - for (i = 0; i < NHANDS; i++) - { - /* Rotate each hand around there centers - to get this we need - * to take into account any scaling. - */ - if (oh->hand[i] != NULL) - clutter_actor_set_rotation_angle (oh->hand[i], - CLUTTER_Z_AXIS, - -6.0 * rotation); - } -} - -static void -stop_and_quit (ClutterActor *stage, - SuperOH *data) -{ - clutter_timeline_stop (data->timeline); - - clutter_test_quit (); -} - -G_MODULE_EXPORT int -test_actors_main (int argc, char *argv[]) -{ - SuperOH *oh; - gint i; - GError *error; - ClutterActor *real_hand; - gchar *file; - - error = NULL; - - clutter_test_init (&argc, &argv); - - oh = g_new (SuperOH, 1); - - oh->stage = clutter_test_get_stage (); - clutter_actor_set_size (oh->stage, 800, 600); - clutter_actor_set_name (oh->stage, "Default Stage"); - clutter_actor_set_background_color (oh->stage, CLUTTER_COLOR_LightSkyBlue); - g_signal_connect (oh->stage, "destroy", G_CALLBACK (stop_and_quit), oh); - - clutter_stage_set_title (CLUTTER_STAGE (oh->stage), "Actors"); - - /* Create a timeline to manage animation */ - oh->timeline = clutter_timeline_new_for_actor (oh->stage, 6000); - clutter_timeline_set_repeat_count (oh->timeline, -1); - - /* fire a callback for frame change */ - g_signal_connect (oh->timeline, "new-frame", G_CALLBACK (frame_cb), oh); - - file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL); - real_hand = clutter_test_utils_create_texture_from_file (file, &error); - if (real_hand == NULL) - g_error ("image load failed: %s", error->message); - - g_free (file); - - /* create a new actor to hold other actors */ - oh->group = clutter_actor_new (); - clutter_actor_set_pivot_point (oh->group, 0.5, 0.5); - clutter_actor_set_layout_manager (oh->group, clutter_fixed_layout_new ()); - clutter_actor_set_name (oh->group, "Group"); - g_signal_connect (oh->group, "destroy", G_CALLBACK (on_group_destroy), oh); - clutter_actor_add_constraint (oh->group, clutter_align_constraint_new (oh->stage, CLUTTER_ALIGN_BOTH, 0.5)); - clutter_actor_add_constraint (oh->group, clutter_bind_constraint_new (oh->stage, CLUTTER_BIND_SIZE, 0.0f)); - - oh->hand = g_new (ClutterActor *, NHANDS); - - oh->stage_width = clutter_actor_get_width (oh->stage); - oh->stage_height = clutter_actor_get_height (oh->stage); - oh->radius = (oh->stage_width + oh->stage_height) / NHANDS; - - for (i = 0; i < NHANDS; i++) - { - gint x, y, w, h; - - if (i == 0) - { - oh->hand[i] = real_hand; - clutter_actor_set_name (oh->hand[i], "Real Hand"); - } - else - { - oh->hand[i] = clutter_clone_new (real_hand); - clutter_actor_set_name (oh->hand[i], "Clone Hand"); - } - - clutter_actor_set_reactive (oh->hand[i], TRUE); - - clutter_actor_set_size (oh->hand[i], 200, 213); - - /* Place around a circle */ - w = clutter_actor_get_width (oh->hand[i]); - h = clutter_actor_get_height (oh->hand[i]); - - x = oh->stage_width / 2 - + oh->radius - * cos (i * G_PI / (NHANDS / 2)) - - w / 2; - - y = oh->stage_height / 2 - + oh->radius - * sin (i * G_PI / (NHANDS / 2)) - - h / 2; - - clutter_actor_set_position (oh->hand[i], x, y); - clutter_actor_set_translation (oh->hand[i], -100.f, -106.5, 0); - - /* Add to our group group */ - clutter_container_add_actor (CLUTTER_CONTAINER (oh->group), oh->hand[i]); - - g_signal_connect (oh->hand[i], "button-press-event", - G_CALLBACK (on_button_press_event), - oh); - - g_signal_connect (oh->hand[i], "destroy", - G_CALLBACK (on_hand_destroy), - oh); - } - - /* Add the group to the stage */ - clutter_container_add_actor (CLUTTER_CONTAINER (oh->stage), oh->group); - - /* Show everying */ - clutter_actor_show (oh->stage); - - g_signal_connect (oh->stage, "key-release-event", - G_CALLBACK (input_cb), - oh); - - /* and start it */ - clutter_timeline_start (oh->timeline); - - clutter_test_main (); - - clutter_timeline_stop (oh->timeline); - - /* clean up */ - g_object_unref (oh->timeline); - g_free (oh->hand); - g_free (oh); - - return EXIT_SUCCESS; -} diff --git a/src/tests/clutter/interactive/test-animation.c b/src/tests/clutter/interactive/test-animation.c deleted file mode 100644 index 12cea0f6d..000000000 --- a/src/tests/clutter/interactive/test-animation.c +++ /dev/null @@ -1,131 +0,0 @@ -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -static gboolean is_expanded = FALSE; - -int -test_animation_main (int argc, char *argv[]); - -const char * -test_animation_describe (void); - -static void -on_rect_transitions_completed (ClutterActor *actor) -{ - is_expanded = !is_expanded; - - g_print ("Animation complete\n"); - - clutter_actor_set_reactive (actor, TRUE); -} - -static void -on_clicked (ClutterClickAction *action, - ClutterActor *actor, - gpointer dummy G_GNUC_UNUSED) -{ - gfloat old_x, old_y, new_x, new_y; - gfloat old_width, old_height, new_width, new_height; - gdouble new_angle; - const ClutterColor *new_color; - guint8 new_opacity; - - clutter_actor_get_position (actor, &old_x, &old_y); - clutter_actor_get_size (actor, &old_width, &old_height); - - /* determine the final state of the animation depending on - * the state of the actor - */ - if (!is_expanded) - { - new_x = old_x - 100; - new_y = old_y - 100; - new_width = old_width + 200; - new_height = old_height + 200; - new_angle = 360.0; - - new_color = CLUTTER_COLOR_DarkScarletRed; - - new_opacity = 255; - } - else - { - new_x = old_x + 100; - new_y = old_y + 100; - new_width = old_width - 200; - new_height = old_height - 200; - new_angle = 0.0; - - new_color = CLUTTER_COLOR_LightOrange; - - new_opacity = 128; - } - - clutter_actor_save_easing_state (actor); - clutter_actor_set_easing_mode (actor, CLUTTER_EASE_IN_EXPO); - clutter_actor_set_easing_duration (actor, 2000); - - clutter_actor_set_position (actor, new_x, new_y); - clutter_actor_set_size (actor, new_width, new_height); - clutter_actor_set_background_color (actor, new_color); - clutter_actor_set_rotation_angle (actor, CLUTTER_Z_AXIS, new_angle); - clutter_actor_set_reactive (actor, FALSE); - - /* animate the opacity halfway through, with a different pacing */ - clutter_actor_save_easing_state (actor); - clutter_actor_set_easing_mode (actor, CLUTTER_LINEAR); - clutter_actor_set_easing_delay (actor, 1000); - clutter_actor_set_easing_duration (actor, 1000); - clutter_actor_set_opacity (actor, new_opacity); - clutter_actor_restore_easing_state (actor); - - clutter_actor_restore_easing_state (actor); -} - -G_MODULE_EXPORT int -test_animation_main (int argc, char *argv[]) -{ - ClutterActor *stage, *rect; - ClutterAction *action; - - clutter_test_init (&argc, &argv); - - stage = clutter_test_get_stage (); - clutter_actor_set_background_color (stage, CLUTTER_COLOR_LightSkyBlue); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Animation"); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - - rect = clutter_actor_new (); - clutter_actor_set_background_color (rect, CLUTTER_COLOR_LightOrange); - clutter_actor_add_child (stage, rect); - clutter_actor_set_size (rect, 50, 50); - clutter_actor_set_pivot_point (rect, .5f, .5f); - clutter_actor_set_translation (rect, -25, -25, 0); - clutter_actor_set_position (rect, - clutter_actor_get_width (stage) / 2, - clutter_actor_get_height (stage) / 2); - clutter_actor_set_opacity (rect, 128); - clutter_actor_set_reactive (rect, TRUE); - g_signal_connect (rect, "transitions-completed", - G_CALLBACK (on_rect_transitions_completed), - NULL); - - action = clutter_click_action_new (); - g_signal_connect (action, "clicked", G_CALLBACK (on_clicked), NULL); - clutter_actor_add_action_with_name (rect, "click", action); - - clutter_actor_show (stage); - - clutter_test_main (); - - return EXIT_SUCCESS; -} - -G_MODULE_EXPORT const char * -test_animation_describe (void) -{ - return "Simple animation demo"; -} diff --git a/src/tests/clutter/interactive/test-bind-constraint.c b/src/tests/clutter/interactive/test-bind-constraint.c deleted file mode 100644 index bc8da6cd6..000000000 --- a/src/tests/clutter/interactive/test-bind-constraint.c +++ /dev/null @@ -1,258 +0,0 @@ -#include -#include - -#include "tests/clutter-test-utils.h" - -#define RECT_SIZE 128 - -#define H_PADDING 32 -#define V_PADDING 32 - -enum -{ - NorthWest, North, NorthEast, - West, Center, East, - SouthWest, South, SouthEast, - - N_RECTS -}; - -static ClutterActor *rects[N_RECTS] = { NULL, }; -static const gchar *colors[N_RECTS] = { - "#8ae234", "#73d216", "#4e9a06", - "#729fcf", "#3465a4", "#204a87", - "#ef2929", "#cc0000", "#a40000" -}; -static const gchar *names[N_RECTS] = { - "North West", "North", "North East", - "West", "Center", "East", - "South West", "South", "South East" -}; - -static const gchar *desaturare_glsl_shader = -"uniform sampler2D tex;\n" -"uniform float factor;\n" -"\n" -"vec3 desaturate (const vec3 color, const float desaturation)\n" -"{\n" -" const vec3 gray_conv = vec3 (0.299, 0.587, 0.114);\n" -" vec3 gray = vec3 (dot (gray_conv, color));\n" -" return vec3 (mix (color.rgb, gray, desaturation));\n" -"}\n" -"\n" -"void main ()\n" -"{\n" -" vec4 color = cogl_color_in * texture2D (tex, vec2 (cogl_tex_coord_in[0].xy));\n" -" color.rgb = desaturate (color.rgb, factor);\n" -" cogl_color_out = color;\n" -"}\n"; - -static gboolean is_expanded = FALSE; - -const char * -test_bind_constraint_describe (void); - -int -test_bind_constraint_main (int argc, char *argv[]); - -static gboolean -on_button_release (ClutterActor *actor, - ClutterEvent *event, - gpointer data G_GNUC_UNUSED) -{ - if (!is_expanded) - { - gfloat north_offset, south_offset; - gfloat west_offset, east_offset; - - /* expand the 8 rectangles by animating the offset of the - * bind constraints - */ - - north_offset = (clutter_actor_get_height (rects[Center]) + V_PADDING) - * -1.0f; - south_offset = (clutter_actor_get_height (rects[Center]) + V_PADDING); - - west_offset = (clutter_actor_get_width (rects[Center]) + H_PADDING) - * -1.0f; - east_offset = (clutter_actor_get_width (rects[Center]) + H_PADDING); - - clutter_actor_animate (rects[NorthWest], CLUTTER_EASE_OUT_EXPO, 500, - "opacity", 255, - "@constraints.x-bind.offset", west_offset, - "@constraints.y-bind.offset", north_offset, - "reactive", TRUE, - NULL); - clutter_actor_animate (rects[North], CLUTTER_EASE_OUT_EXPO, 500, - "opacity", 255, - "@constraints.y-bind.offset", north_offset, - "reactive", TRUE, - NULL); - clutter_actor_animate (rects[NorthEast], CLUTTER_EASE_OUT_EXPO, 500, - "opacity", 255, - "@constraints.x-bind.offset", east_offset, - "@constraints.y-bind.offset", north_offset, - "reactive", TRUE, - NULL); - - clutter_actor_animate (rects[West], CLUTTER_EASE_OUT_EXPO, 500, - "opacity", 255, - "@constraints.x-bind.offset", west_offset, - "reactive", TRUE, - NULL); - /* turn on the desaturation effect and set the center - * rectangle not reactive - */ - clutter_actor_animate (rects[Center], CLUTTER_LINEAR, 500, - "@effects.desaturate.enabled", TRUE, - "reactive", FALSE, - NULL); - clutter_actor_animate (rects[East], CLUTTER_EASE_OUT_EXPO, 500, - "opacity", 255, - "@constraints.x-bind.offset", east_offset, - "reactive", TRUE, - NULL); - - clutter_actor_animate (rects[SouthWest], CLUTTER_EASE_OUT_EXPO, 500, - "opacity", 255, - "@constraints.x-bind.offset", west_offset, - "@constraints.y-bind.offset", south_offset, - "reactive", TRUE, - NULL); - clutter_actor_animate (rects[South], CLUTTER_EASE_OUT_EXPO, 500, - "opacity", 255, - "@constraints.y-bind.offset", south_offset, - "reactive", TRUE, - NULL); - clutter_actor_animate (rects[SouthEast], CLUTTER_EASE_OUT_EXPO, 500, - "opacity", 255, - "@constraints.x-bind.offset", east_offset, - "@constraints.y-bind.offset", south_offset, - "reactive", TRUE, - NULL); - } - else - { - gint i; - - clutter_actor_animate (rects[Center], CLUTTER_LINEAR, 500, - "@effects.desaturate.enabled", FALSE, - "reactive", TRUE, - NULL); - - for (i = NorthWest; i < N_RECTS; i++) - { - if (i == Center) - continue; - - /* put the 8 rectangles back into their initial state */ - clutter_actor_animate (rects[i], CLUTTER_EASE_OUT_EXPO, 500, - "opacity", 0, - "@constraints.x-bind.offset", 0.0f, - "@constraints.y-bind.offset", 0.0f, - "reactive", FALSE, - NULL); - } - } - - is_expanded = !is_expanded; - - g_print ("Selected: [%s]\n", clutter_actor_get_name (actor)); - - return TRUE; -} - -G_MODULE_EXPORT const char * -test_bind_constraint_describe (void) -{ - return "Demonstrate the usage of ClutterBindConstraint"; -} - -G_MODULE_EXPORT int -test_bind_constraint_main (int argc, char *argv[]) -{ - ClutterActor *stage, *rect; - ClutterConstraint *constraint; - ClutterEffect *effect; - ClutterColor rect_color; - gint i; - - clutter_test_init (&argc, &argv); - - stage = clutter_test_get_stage (); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Constraints"); - clutter_actor_set_size (stage, 800, 600); - - /* main rectangle */ - clutter_color_from_string (&rect_color, "#3465a4"); - rect = clutter_actor_new (); - g_signal_connect (rect, "button-release-event", - G_CALLBACK (on_button_release), - NULL); - clutter_actor_set_background_color (rect, &rect_color); - clutter_actor_set_size (rect, RECT_SIZE, RECT_SIZE); - clutter_actor_set_reactive (rect, TRUE); - clutter_actor_set_name (rect, names[Center]); - clutter_actor_add_child (stage, rect); - - /* align the center rectangle to the center of the stage */ - constraint = clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5); - clutter_actor_add_constraint_with_name (rect, "align", constraint); - - /* this is the equivalent of the DesaturateEffect; we cannot animate - * the factor because the animation API only understands GObject - * properties; so we use the ActorMeta:enabled property to toggle - * the shader - */ - effect = clutter_shader_effect_new (CLUTTER_FRAGMENT_SHADER); - clutter_shader_effect_set_shader_source (CLUTTER_SHADER_EFFECT (effect), - desaturare_glsl_shader); - clutter_shader_effect_set_uniform (CLUTTER_SHADER_EFFECT (effect), - "tex", G_TYPE_INT, 1, 0); - clutter_shader_effect_set_uniform (CLUTTER_SHADER_EFFECT (effect), - "factor", G_TYPE_FLOAT, 1, 0.66); - clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (effect), FALSE); - clutter_actor_add_effect_with_name (rect, "desaturate", effect); - - rects[Center] = rect; - - /* build the other rectangles, and bind their position and size - * to the center rectangle. we are going to animate the offset - * of the BindConstraints - */ - for (i = 0; i < N_RECTS; i++) - { - if (i == Center) - continue; - - clutter_color_from_string (&rect_color, colors[i]); - - rect = clutter_actor_new (); - clutter_actor_set_background_color (rect, &rect_color); - clutter_actor_set_opacity (rect, 0); - clutter_actor_set_name (rect, names[i]); - clutter_actor_add_child (stage, rect); - - constraint = clutter_bind_constraint_new (rects[Center], CLUTTER_BIND_X, 0.0); - clutter_actor_add_constraint_with_name (rect, "x-bind", constraint); - - constraint = clutter_bind_constraint_new (rects[Center], CLUTTER_BIND_Y, 0.0); - clutter_actor_add_constraint_with_name (rect, "y-bind", constraint); - - constraint = clutter_bind_constraint_new (rects[Center], CLUTTER_BIND_SIZE, 0.0); - clutter_actor_add_constraint_with_name (rect, "size-bind", constraint); - - g_signal_connect (rect, "button-release-event", - G_CALLBACK (on_button_release), - NULL); - - rects[i] = rect; - } - - clutter_actor_show (stage); - - clutter_test_main (); - - return EXIT_SUCCESS; -} diff --git a/src/tests/clutter/interactive/test-binding-pool.c b/src/tests/clutter/interactive/test-binding-pool.c deleted file mode 100644 index 3d869662c..000000000 --- a/src/tests/clutter/interactive/test-binding-pool.c +++ /dev/null @@ -1,326 +0,0 @@ -#include -#include - -#include -#include - -#include -#include - -#include "tests/clutter-test-utils.h" - -#define TYPE_KEY_GROUP (key_group_get_type ()) -#define KEY_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_KEY_GROUP, KeyGroup)) -#define IS_KEY_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_KEY_GROUP)) -#define KEY_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_KEY_GROUP, KeyGroupClass)) -#define IS_KEY_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_KEY_GROUP)) - -typedef struct _KeyGroup KeyGroup; -typedef struct _KeyGroupClass KeyGroupClass; - -struct _KeyGroup -{ - ClutterActor parent_instance; - - gint selected_index; -}; - -struct _KeyGroupClass -{ - ClutterActorClass parent_class; - - void (* activate) (KeyGroup *group, - ClutterActor *child); -}; - -GType key_group_get_type (void); - -int -test_binding_pool_main (int argc, char *argv[]); - -const char * -test_binding_pool_describe (void); - -G_DEFINE_TYPE (KeyGroup, key_group, CLUTTER_TYPE_ACTOR) - -enum -{ - ACTIVATE, - - LAST_SIGNAL -}; - -static guint group_signals[LAST_SIGNAL] = { 0, }; - -static gboolean -key_group_action_move_left (KeyGroup *self, - const gchar *action_name, - guint key_val, - ClutterModifierType modifiers) -{ - gint n_children; - - g_debug ("%s: activated '%s' (k:%d, m:%d)", - G_STRLOC, - action_name, - key_val, - modifiers); - - n_children = clutter_actor_get_n_children (CLUTTER_ACTOR (self)); - - self->selected_index -= 1; - - if (self->selected_index < 0) - self->selected_index = n_children - 1; - - return TRUE; -} - -static gboolean -key_group_action_move_right (KeyGroup *self, - const gchar *action_name, - guint key_val, - ClutterModifierType modifiers) -{ - gint n_children; - - g_debug ("%s: activated '%s' (k:%d, m:%d)", - G_STRLOC, - action_name, - key_val, - modifiers); - - n_children = clutter_actor_get_n_children (CLUTTER_ACTOR (self)); - - self->selected_index += 1; - - if (self->selected_index >= n_children) - self->selected_index = 0; - - return TRUE; -} - -static gboolean -key_group_action_activate (KeyGroup *self, - const gchar *action_name, - guint key_val, - ClutterModifierType modifiers) -{ - ClutterActor *child = NULL; - - g_debug ("%s: activated '%s' (k:%d, m:%d)", - G_STRLOC, - action_name, - key_val, - modifiers); - - if (self->selected_index == -1) - return FALSE; - - child = clutter_actor_get_child_at_index (CLUTTER_ACTOR (self), - self->selected_index); - - if (child != NULL) - { - g_signal_emit (self, group_signals[ACTIVATE], 0, child); - return TRUE; - } - else - return FALSE; -} - -static gboolean -key_group_key_press (ClutterActor *actor, - ClutterKeyEvent *event) -{ - ClutterBindingPool *pool; - gboolean res; - - pool = clutter_binding_pool_find (G_OBJECT_TYPE_NAME (actor)); - g_assert (pool != NULL); - - res = clutter_binding_pool_activate (pool, - event->keyval, - event->modifier_state, - G_OBJECT (actor)); - - /* if we activate a key binding, redraw the actor */ - if (res) - clutter_actor_queue_redraw (actor); - - return res ? CLUTTER_EVENT_STOP : CLUTTER_EVENT_PROPAGATE; -} - -static void -key_group_paint (ClutterActor *actor, - ClutterPaintContext *paint_context) -{ - KeyGroup *self = KEY_GROUP (actor); - ClutterActorIter iter; - ClutterActor *child; - gint i = 0; - CoglFramebuffer *framebuffer = - clutter_paint_context_get_framebuffer (paint_context); - CoglContext *ctx = cogl_framebuffer_get_context (framebuffer); - CoglPipeline *pipeline; - - pipeline = cogl_pipeline_new (ctx); - - clutter_actor_iter_init (&iter, actor); - while (clutter_actor_iter_next (&iter, &child)) - { - /* paint the selection rectangle */ - if (i == self->selected_index) - { - ClutterActorBox box = { 0, }; - - clutter_actor_get_allocation_box (child, &box); - - box.x1 -= 2; - box.y1 -= 2; - box.x2 += 2; - box.y2 += 2; - - cogl_pipeline_set_color4ub (pipeline, 255, 255, 0, 224); - - cogl_framebuffer_draw_rectangle (framebuffer, pipeline, - box.x1, box.y1, box.x2, box.y2); - } - - clutter_actor_paint (child, paint_context); - - i += 1; - } -} - -static void -key_group_class_init (KeyGroupClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); - ClutterBindingPool *binding_pool; - - actor_class->paint = key_group_paint; - actor_class->key_press_event = key_group_key_press; - - group_signals[ACTIVATE] = - g_signal_new (g_intern_static_string ("activate"), - G_OBJECT_CLASS_TYPE (gobject_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (KeyGroupClass, activate), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - CLUTTER_TYPE_ACTOR); - - binding_pool = clutter_binding_pool_get_for_class (klass); - - clutter_binding_pool_install_action (binding_pool, "move-right", - CLUTTER_KEY_Right, 0, - G_CALLBACK (key_group_action_move_right), - NULL, NULL); - clutter_binding_pool_install_action (binding_pool, "move-left", - CLUTTER_KEY_Left, 0, - G_CALLBACK (key_group_action_move_left), - NULL, NULL); - clutter_binding_pool_install_action (binding_pool, "activate", - CLUTTER_KEY_Return, 0, - G_CALLBACK (key_group_action_activate), - NULL, NULL); - clutter_binding_pool_install_action (binding_pool, "activate", - CLUTTER_KEY_KP_Enter, 0, - G_CALLBACK (key_group_action_activate), - NULL, NULL); - clutter_binding_pool_install_action (binding_pool, "activate", - CLUTTER_KEY_ISO_Enter, 0, - G_CALLBACK (key_group_action_activate), - NULL, NULL); -} - -static void -key_group_init (KeyGroup *self) -{ - self->selected_index = -1; -} - -static void -on_key_group_activate (KeyGroup *group, - ClutterActor *child) -{ - g_print ("Child '%s' activated!\n", clutter_actor_get_name (child)); -} - -G_MODULE_EXPORT int -test_binding_pool_main (int argc, char *argv[]) -{ - ClutterActor *stage, *key_group; - gint group_x, group_y; - - clutter_test_init (&argc, &argv); - - stage = clutter_test_get_stage (); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Key Binding Pool"); - g_signal_connect (stage, - "button-press-event", G_CALLBACK (clutter_test_quit), - NULL); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - - key_group = g_object_new (TYPE_KEY_GROUP, NULL); - clutter_actor_add_child (stage, key_group); - - /* add three rectangles to the key group */ - clutter_container_add (CLUTTER_CONTAINER (key_group), - g_object_new (CLUTTER_TYPE_ACTOR, - "background-color", CLUTTER_COLOR_Red, - "name", "Red Rectangle", - "width", 100.0, - "height", 100.0, - "x", 0.0, - "y", 0.0, - NULL), - g_object_new (CLUTTER_TYPE_ACTOR, - "background-color", CLUTTER_COLOR_Green, - "name", "Green Rectangle", - "width", 100.0, - "height", 100.0, - "x", 125.0, - "y", 0.0, - NULL), - g_object_new (CLUTTER_TYPE_ACTOR, - "background-color", CLUTTER_COLOR_Blue, - "name", "Blue Rectangle", - "width", 100.0, - "height", 100.0, - "x", 250.0, - "y", 0.0, - NULL), - NULL); - - g_signal_connect (key_group, - "activate", G_CALLBACK (on_key_group_activate), - NULL); - - group_x = - (clutter_actor_get_width (stage) - clutter_actor_get_width (key_group)) - / 2; - group_y = - (clutter_actor_get_height (stage) - clutter_actor_get_height (key_group)) - / 2; - - clutter_actor_set_position (key_group, group_x, group_y); - clutter_actor_set_reactive (key_group, TRUE); - - clutter_stage_set_key_focus (CLUTTER_STAGE (stage), key_group); - - clutter_actor_show (stage); - - clutter_test_main (); - - return EXIT_SUCCESS; -} - -G_MODULE_EXPORT const char * -test_binding_pool_describe (void) -{ - return "Binding pools example"; -} diff --git a/src/tests/clutter/interactive/test-cairo-clock.c b/src/tests/clutter/interactive/test-cairo-clock.c deleted file mode 100644 index 9f0d210bf..000000000 --- a/src/tests/clutter/interactive/test-cairo-clock.c +++ /dev/null @@ -1,125 +0,0 @@ -#include -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -int -test_cairo_clock_main (int argc, char *argv[]); - -const char * -test_cairo_clock_describe (void); - -static gboolean -draw_clock (ClutterCanvas *canvas, - cairo_t *cr, - int width, - int height) -{ - GDateTime *now; - float hours, minutes, seconds; - - /* get the current time and compute the angles */ - now = g_date_time_new_now_local (); - seconds = g_date_time_get_second (now) * G_PI / 30; - minutes = g_date_time_get_minute (now) * G_PI / 30; - hours = g_date_time_get_hour (now) * G_PI / 6; - - /* clear the contents of the canvas, to avoid painting - * over the previous frame - */ - cairo_save (cr); - cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0); - cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); - cairo_paint (cr); - cairo_restore (cr); - - /* scale the modelview to the size of the surface */ - cairo_scale (cr, width, height); - - cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); - cairo_set_line_width (cr, 0.1); - - /* the black rail that holds the seconds indicator */ - clutter_cairo_set_source_color (cr, CLUTTER_COLOR_Black); - cairo_translate (cr, 0.5, 0.5); - cairo_arc (cr, 0, 0, 0.4, 0, G_PI * 2); - cairo_stroke (cr); - - /* the seconds indicator */ - clutter_cairo_set_source_color (cr, CLUTTER_COLOR_White); - cairo_move_to (cr, 0, 0); - cairo_arc (cr, sinf (seconds) * 0.4, - cosf (seconds) * 0.4, 0.05, 0, G_PI * 2); - cairo_fill (cr); - - /* the minutes hand */ - clutter_cairo_set_source_color (cr, CLUTTER_COLOR_DarkChameleon); - cairo_move_to (cr, 0, 0); - cairo_line_to (cr, sinf (minutes) * 0.4, -cosf (minutes) * 0.4); - cairo_stroke (cr); - - /* the hours hand */ - cairo_move_to (cr, 0, 0); - cairo_line_to (cr, sinf (hours) * 0.2, -cosf (hours) * 0.2); - cairo_stroke (cr); - - g_date_time_unref (now); - - /* we're done drawing */ - return TRUE; -} - -static gboolean -invalidate_clock (gpointer data_) -{ - /* invalidate the contents of the canvas */ - clutter_content_invalidate (data_); - - /* keep the timeout source */ - return TRUE; -} - -G_MODULE_EXPORT int -test_cairo_clock_main (int argc, char *argv[]) -{ - ClutterActor *stage; - ClutterContent *canvas; - - /* initialize Clutter */ - clutter_test_init (&argc, &argv); - - /* create a resizable stage */ - stage = clutter_test_get_stage (); - clutter_stage_set_title (CLUTTER_STAGE (stage), "2D Clock"); - clutter_actor_set_background_color (stage, CLUTTER_COLOR_LightSkyBlue); - clutter_actor_set_size (stage, 300, 300); - clutter_actor_show (stage); - - /* our 2D canvas, courtesy of Cairo */ - canvas = clutter_canvas_new (); - clutter_canvas_set_size (CLUTTER_CANVAS (canvas), 300, 300); - clutter_actor_set_content (stage, canvas); - - /* quit on destroy */ - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - - /* connect our drawing code */ - g_signal_connect (canvas, "draw", G_CALLBACK (draw_clock), NULL); - - /* invalidate the canvas, so that we can draw before the main loop starts */ - clutter_content_invalidate (canvas); - - /* set up a timer that invalidates the canvas every second */ - clutter_threads_add_timeout (1000, invalidate_clock, canvas); - - clutter_test_main (); - - return EXIT_SUCCESS; -} - -G_MODULE_EXPORT const char * -test_cairo_clock_describe (void) -{ - return "Simple 2D canvas using a Cairo texture actor"; -} diff --git a/src/tests/clutter/interactive/test-cairo-flowers.c b/src/tests/clutter/interactive/test-cairo-flowers.c deleted file mode 100644 index 5cfce9a41..000000000 --- a/src/tests/clutter/interactive/test-cairo-flowers.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Pretty cairo flower hack. - */ -#include - -#include "tests/clutter-test-utils.h" - -#ifndef _MSC_VER -#include /* for sleep(), used for screenshots */ -#endif -#include -#ifdef _MSC_VER -#define _USE_MATH_DEFINES -#endif -#include - -#define PETAL_MIN 20 -#define PETAL_VAR 40 -#define N_FLOWERS 40 /* reduce if you have a small card */ - -typedef struct Flower -{ - ClutterActor *ctex; - gint x,y,rot,v,rv; -} -Flower; - -static ClutterActor *stage = NULL; - -int -test_cairo_flowers_main (int argc, char **argv); - -const char * -test_cairo_flowers_describe (void); - -static gboolean -draw_flower (ClutterCanvas *canvas, - cairo_t *cr, - gint width, - gint height, - gpointer user_data) -{ - /* No science here, just a hack from toying */ - gint i, j; - - double colors[] = { - 0.71, 0.81, 0.83, - 1.0, 0.78, 0.57, - 0.64, 0.30, 0.35, - 0.73, 0.40, 0.39, - 0.91, 0.56, 0.64, - 0.70, 0.47, 0.45, - 0.92, 0.75, 0.60, - 0.82, 0.86, 0.85, - 0.51, 0.56, 0.67, - 1.0, 0.79, 0.58, - - }; - - gint size; - gint petal_size; - gint n_groups; /* Num groups of petals 1-3 */ - gint n_petals; /* num of petals 4 - 8 */ - gint pm1, pm2; - - gint idx, last_idx = -1; - - petal_size = GPOINTER_TO_INT (user_data); - size = petal_size * 8; - - n_groups = rand() % 3 + 1; - - cairo_set_tolerance (cr, 0.1); - - /* Clear */ - cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); - cairo_paint(cr); - cairo_set_operator (cr, CAIRO_OPERATOR_OVER); - - cairo_translate(cr, size/2, size/2); - - for (i=0; iy += flowers[i]->v; - flowers[i]->rot += flowers[i]->rv; - - if (flowers[i]->y > (gint) clutter_actor_get_height (stage)) - flowers[i]->y = -clutter_actor_get_height (flowers[i]->ctex); - - clutter_actor_set_position (flowers[i]->ctex, - flowers[i]->x, flowers[i]->y); - - clutter_actor_set_rotation_angle (flowers[i]->ctex, - CLUTTER_Z_AXIS, - flowers[i]->rot); - } -} - -static void -stop_and_quit (ClutterActor *actor, - ClutterTimeline *timeline) -{ - clutter_timeline_stop (timeline); - clutter_test_quit (); -} - -G_MODULE_EXPORT int -test_cairo_flowers_main (int argc, char **argv) -{ - Flower *flowers[N_FLOWERS]; - ClutterTimeline *timeline; - int i; - - srand (time (NULL)); - - clutter_test_init (&argc, &argv); - - stage = clutter_test_get_stage (); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Cairo Flowers"); - - /* Create a timeline to manage animation */ - timeline = clutter_timeline_new_for_actor (stage, 6000); - clutter_timeline_set_repeat_count (timeline, -1); - g_signal_connect (stage, "destroy", G_CALLBACK (stop_and_quit), timeline); - - clutter_actor_set_background_color (stage, CLUTTER_COLOR_Black); - - for (i=0; i< N_FLOWERS; i++) - { - flowers[i] = g_new0(Flower, 1); - flowers[i]->ctex = make_flower_actor(); - flowers[i]->x = rand() % (int) clutter_actor_get_width (stage) - - (PETAL_MIN + PETAL_VAR) * 2; - flowers[i]->y = rand() % (int) clutter_actor_get_height (stage); - flowers[i]->rv = rand() % 5 + 1; - flowers[i]->v = rand() % 10 + 2; - - clutter_container_add_actor (CLUTTER_CONTAINER (stage), - flowers[i]->ctex); - clutter_actor_set_position (flowers[i]->ctex, - flowers[i]->x, flowers[i]->y); - } - - /* fire a callback for frame change */ - g_signal_connect (timeline, "new-frame", G_CALLBACK (tick), flowers); - - clutter_actor_show (stage); - - clutter_timeline_start (timeline); - - g_signal_connect (stage, "key-press-event", - G_CALLBACK (clutter_test_quit), - NULL); - - clutter_test_main (); - - g_object_unref (timeline); - - return EXIT_SUCCESS; -} - -G_MODULE_EXPORT const char * -test_cairo_flowers_describe (void) -{ - return "Drawing pretty flowers with Cairo"; -} diff --git a/src/tests/clutter/interactive/test-cogl-multitexture.c b/src/tests/clutter/interactive/test-cogl-multitexture.c deleted file mode 100644 index f14f0b7d8..000000000 --- a/src/tests/clutter/interactive/test-cogl-multitexture.c +++ /dev/null @@ -1,254 +0,0 @@ -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include "tests/clutter-test-utils.h" - -typedef struct _TestMultiLayerMaterialState -{ - ClutterActor *group; - CoglHandle alpha_tex; - CoglHandle redhand_tex; - gfloat *tex_coords; - - ClutterTimeline *timeline; - - CoglHandle material0; - graphene_matrix_t tex_matrix0; - graphene_matrix_t rot_matrix0; - CoglHandle light_tex0; - - CoglHandle material1; - graphene_matrix_t tex_matrix1; - graphene_matrix_t rot_matrix1; - CoglHandle light_tex1; - -} TestMultiLayerMaterialState; - -int -test_cogl_multitexture_main (int argc, char *argv[]); - -const char * -test_cogl_multitexture_describe (void); - -static void -frame_cb (ClutterTimeline *timeline, - gint frame_no, - gpointer data) -{ - TestMultiLayerMaterialState *state = data; - - graphene_matrix_multiply (&state->rot_matrix0, - &state->tex_matrix0, - &state->tex_matrix0); - cogl_material_set_layer_matrix (state->material0, 2, &state->tex_matrix0); - - graphene_matrix_multiply (&state->rot_matrix1, - &state->tex_matrix1, - &state->tex_matrix1); - cogl_material_set_layer_matrix (state->material1, 2, &state->tex_matrix1); -} - -static void -material_rectangle_paint (ClutterActor *actor, - ClutterPaintContext *paint_context, - gpointer data) -{ - TestMultiLayerMaterialState *state = data; - CoglFramebuffer *framebuffer = - clutter_paint_context_get_framebuffer (paint_context); - - cogl_framebuffer_push_matrix (framebuffer); - - cogl_framebuffer_translate (framebuffer, 150, 15, 0); - - cogl_framebuffer_draw_multitextured_rectangle (framebuffer, - COGL_FRAMEBUFFER (state->material0), - 0, 0, 200, 213, - state->tex_coords, - 12); - cogl_framebuffer_translate (framebuffer, -300, -30, 0); - cogl_framebuffer_draw_multitextured_rectangle (framebuffer, - COGL_FRAMEBUFFER (state->material1), - 0, 0, 200, 213, - state->tex_coords, - 12); - - cogl_framebuffer_pop_matrix (framebuffer); -} - -static void -animation_completed_cb (ClutterAnimation *animation, - TestMultiLayerMaterialState *state) -{ - static gboolean go_back = FALSE; - gdouble new_rotation_y; - - if (go_back) - new_rotation_y = 30; - else - new_rotation_y = -30; - go_back = !go_back; - - clutter_actor_animate_with_timeline (state->group, - CLUTTER_LINEAR, - state->timeline, - "rotation-angle-y", new_rotation_y, - "signal-after::completed", - animation_completed_cb, state, - NULL); - - -} - -G_MODULE_EXPORT int -test_cogl_multitexture_main (int argc, char *argv[]) -{ - GError *error = NULL; - ClutterActor *stage; - ClutterColor stage_color = { 0x61, 0x56, 0x56, 0xff }; - g_autofree TestMultiLayerMaterialState *state = g_new0 (TestMultiLayerMaterialState, 1); - gfloat stage_w, stage_h; - gchar **files; - gfloat tex_coords[] = - { - /* tx1 ty1 tx2 ty2 */ - 0, 0, 1, 1, - 0, 0, 1, 1, - 0, 0, 1, 1 - }; - - clutter_test_init (&argc, &argv); - - stage = clutter_test_get_stage (); - clutter_actor_get_size (stage, &stage_w, &stage_h); - - clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl: Multi-texturing"); - clutter_actor_set_background_color (CLUTTER_ACTOR (stage), &stage_color); - - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - - /* We create a non-descript actor that we know doesn't have a - * default paint handler, so that we can easily control - * painting in a paint signal handler, without having to - * sub-class anything etc. */ - state->group = clutter_actor_new (); - clutter_actor_set_position (state->group, stage_w / 2, stage_h / 2); - g_signal_connect (state->group, "paint", - G_CALLBACK(material_rectangle_paint), state); - - files = g_new (gchar*, 4); - files[0] = g_build_filename (TESTS_DATADIR, "redhand_alpha.png", NULL); - files[1] = g_build_filename (TESTS_DATADIR, "redhand.png", NULL); - files[2] = g_build_filename (TESTS_DATADIR, "light0.png", NULL); - files[3] = NULL; - - state->alpha_tex = - cogl_texture_new_from_file (files[0], - COGL_TEXTURE_NO_SLICING, - COGL_PIXEL_FORMAT_ANY, - &error); - if (!state->alpha_tex) - g_critical ("Failed to load redhand_alpha.png: %s", error->message); - - state->redhand_tex = - cogl_texture_new_from_file (files[1], - COGL_TEXTURE_NO_SLICING, - COGL_PIXEL_FORMAT_ANY, - &error); - if (!state->redhand_tex) - g_critical ("Failed to load redhand.png: %s", error->message); - - state->light_tex0 = - cogl_texture_new_from_file (files[2], - COGL_TEXTURE_NO_SLICING, - COGL_PIXEL_FORMAT_ANY, - &error); - if (!state->light_tex0) - g_critical ("Failed to load light0.png: %s", error->message); - - state->light_tex1 = - cogl_texture_new_from_file (files[2], - COGL_TEXTURE_NO_SLICING, - COGL_PIXEL_FORMAT_ANY, - &error); - if (!state->light_tex1) - g_critical ("Failed to load light0.png: %s", error->message); - - g_strfreev (files); - - state->material0 = cogl_material_new (); - cogl_material_set_layer (state->material0, 0, state->alpha_tex); - cogl_material_set_layer (state->material0, 1, state->redhand_tex); - cogl_material_set_layer (state->material0, 2, state->light_tex0); - - state->material1 = cogl_material_new (); - cogl_material_set_layer (state->material1, 0, state->alpha_tex); - cogl_material_set_layer (state->material1, 1, state->redhand_tex); - cogl_material_set_layer (state->material1, 2, state->light_tex1); - - state->tex_coords = tex_coords; - - graphene_matrix_init_identity (&state->tex_matrix0); - graphene_matrix_init_identity (&state->tex_matrix1); - graphene_matrix_init_identity (&state->rot_matrix0); - graphene_matrix_init_identity (&state->rot_matrix1); - - graohene_matrix_translate (&state->rot_matrix0, - &GRAPHENE_POINT3D_INIT (-0.5, -0.5, 0)); - graohene_matrix_rotate (&state->rot_matrix0, 10.0, graphene_vec3_z_axis ()); - graphene_matrix_translate (&state->rot_matrix0, - &GRAPHENE_POINT3D_INIT (0.5, 0.5, 0)); - - graphene_matrix_translate (&state->rot_matrix1, - &GRAPHENE_POINT3D_INIT (-0.5, -0.5, 0)); - graohene_matrix_rotate (&state->rot_matrix1, -10.0, graphene_vec3_z_axis ()); - graphene_matrix_translate (&state->rot_matrix1, - &GRAPHENE_POINT3D_INIT (0.5, 0.5, 0)); - - clutter_actor_set_translation (data->parent_container, -86.f, -125.f, 0.f); - clutter_container_add_actor (CLUTTER_CONTAINER(stage), - state->group); - - state->timeline = clutter_timeline_new_for_actor (stage, 2812); - - g_signal_connect (state->timeline, "new-frame", G_CALLBACK (frame_cb), state); - - clutter_actor_animate_with_timeline (state->group, - CLUTTER_LINEAR, - state->timeline, - "rotation-angle-y", 30.0, - "signal-after::completed", - animation_completed_cb, state, - NULL); - - /* start the timeline and thus the animations */ - clutter_timeline_start (state->timeline); - - clutter_actor_show (stage); - - clutter_test_main (); - - cogl_object_unref (state->material1); - cogl_object_unref (state->material0); - cogl_object_unref (state->alpha_tex); - cogl_object_unref (state->redhand_tex); - cogl_object_unref (state->light_tex0); - cogl_object_unref (state->light_tex1); - g_free (state); - - return 0; -} - -G_MODULE_EXPORT const char * -test_cogl_multitexture_describe (void) -{ - return "Multi-texturing support in Cogl."; -} diff --git a/src/tests/clutter/interactive/test-cogl-offscreen.c b/src/tests/clutter/interactive/test-cogl-offscreen.c deleted file mode 100644 index 4f2e6bddb..000000000 --- a/src/tests/clutter/interactive/test-cogl-offscreen.c +++ /dev/null @@ -1,353 +0,0 @@ -#include -#include -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -/* Coglbox declaration - *--------------------------------------------------*/ - -G_BEGIN_DECLS - -#define TEST_TYPE_COGLBOX test_coglbox_get_type() - -#define TEST_COGLBOX(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - TEST_TYPE_COGLBOX, TestCoglbox)) - -#define TEST_COGLBOX_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - TEST_TYPE_COGLBOX, TestCoglboxClass)) - -#define TEST_IS_COGLBOX(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ - TEST_TYPE_COGLBOX)) - -#define TEST_IS_COGLBOX_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), \ - TEST_TYPE_COGLBOX)) - -#define TEST_COGLBOX_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - TEST_TYPE_COGLBOX, TestCoglboxClass)) - -typedef struct _TestCoglbox TestCoglbox; -typedef struct _TestCoglboxClass TestCoglboxClass; -typedef struct _TestCoglboxPrivate TestCoglboxPrivate; - -struct _TestCoglbox -{ - ClutterActor parent; - - /*< private >*/ - TestCoglboxPrivate *priv; -}; - -struct _TestCoglboxClass -{ - ClutterActorClass parent_class; - - /* padding for future expansion */ - void (*_test_coglbox1) (void); - void (*_test_coglbox2) (void); - void (*_test_coglbox3) (void); - void (*_test_coglbox4) (void); -}; - -static GType test_coglbox_get_type (void) G_GNUC_CONST; - -int -test_cogl_offscreen_main (int argc, char *argv[]); - -const char * -test_cogl_offscreen_describe (void); - -G_END_DECLS - -/* Coglbox private declaration - *--------------------------------------------------*/ - -struct _TestCoglboxPrivate -{ - CoglHandle texhand_id; - CoglHandle texture_id; - CoglFramebuffer *framebuffer; -}; - -G_DEFINE_TYPE_WITH_PRIVATE (TestCoglbox, test_coglbox, CLUTTER_TYPE_ACTOR); - -#define TEST_COGLBOX_GET_PRIVATE(obj) \ -(test_coglbox_get_instance_private (TEST_COGLBOX ((obj)))) - -/* Coglbox implementation - *--------------------------------------------------*/ - -static void -test_coglbox_paint (ClutterActor *self, - ClutterPaintContext *paint_context) -{ - TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (self); - CoglFramebuffer *framebuffer = - clutter_paint_context_get_framebuffer (paint_context); - CoglContext *ctx = cogl_framebuffer_get_context (framebuffer); - gfloat texcoords[4] = { 0, 0, 1, 1 }; - CoglPipeline *pipeline; - - pipeline = cogl_pipeline_new (ctx); - cogl_pipeline_set_color4ub (pipeline, 0x66, 0x66, 0xdd, 0xff); - cogl_framebuffer_draw_rectangle (framebuffer, pipeline, 0, 0, 400, 400); - cogl_object_unref (pipeline); - - pipeline = cogl_pipeline_new (ctx); - cogl_pipeline_set_layer_texture (pipeline, 0, priv->texhand_id); - cogl_framebuffer_draw_textured_rectangle (framebuffer, pipeline, - 0, 0, - 400, 400, - 0, 0, - 6, 6); - cogl_object_unref (pipeline); - - pipeline = cogl_pipeline_new (ctx); - cogl_pipeline_set_color4ub (pipeline, 0xff, 0, 0, 0xff); - cogl_framebuffer_draw_rectangle (priv->framebuffer, pipeline, - 20, 20, 20 + 100, 20 + 100); - - cogl_pipeline_set_color4ub (pipeline, 0, 0xff, 0, 0xff); - cogl_framebuffer_draw_rectangle (priv->framebuffer, pipeline, - 80, 80, 80 + 100, 80 + 100); - cogl_object_unref (pipeline); - - pipeline = cogl_pipeline_new (ctx); - cogl_pipeline_set_color4ub (pipeline, 0x88, 0x88, 0x88, 0x88); - cogl_pipeline_set_layer_texture (pipeline, 0, priv->texture_id); - cogl_framebuffer_draw_textured_rectangle (framebuffer, pipeline, - 100, 100, - 300, 300, - texcoords[0], - texcoords[1], - texcoords[2], - texcoords[3]); - cogl_object_unref (pipeline); -} - -static void -test_coglbox_finalize (GObject *object) -{ - G_OBJECT_CLASS (test_coglbox_parent_class)->finalize (object); -} - -static void -test_coglbox_dispose (GObject *object) -{ - TestCoglboxPrivate *priv; - - priv = TEST_COGLBOX_GET_PRIVATE (object); - - cogl_object_unref (priv->texture_id); - g_object_unref (priv->framebuffer); - - G_OBJECT_CLASS (test_coglbox_parent_class)->dispose (object); -} - -/* A newly created Cogl framebuffer will be initialized with a - * viewport covering the size of the viewport i.e. equavalent to: - * - * calling cogl_framebuffer_set_viewport ( - * fb, - * 0, 0, - * cogl_framebuffer_get_viewport_width (fb), - * cogl_framebuffer_get_viewport_width (fb)); - * - * The projection matrix will be an identity matrix. - * - * The modelview matrix will be an identity matrix, and this will - * create a coordinate system - like OpenGL - with the viewport - * being mapped to a unit cube with the origin (0, 0, 0) in the - * center, x, y and z ranging from -1 to 1 with (-1, -1) being top - * left and (1, 1) bottom right. - * - * This sets up a Clutter like coordinate system for a Cogl - * framebuffer - */ -static void -setup_viewport (CoglFramebuffer *framebuffer, - unsigned int width, - unsigned int height, - float fovy, - float aspect, - float z_near, - float z_far) -{ - float z_camera; - graphene_matrix_t projection_matrix; - graphene_matrix_t mv_matrix; - - cogl_framebuffer_set_viewport (framebuffer, 0, 0, width, height); - - /* For Ortho projection. - * _cogl_matrix_stack_ortho (projection_stack, 0, width, 0, height, -1, 1); - */ - - cogl_framebuffer_perspective (framebuffer, fovy, aspect, z_near, z_far); - - /* - * In theory, we can compute the camera distance from screen as: - * - * 0.5 * tan (FOV) - * - * However, it's better to compute the z_camera from our projection - * matrix so that we get a 1:1 mapping at the screen distance. Consider - * the upper-left corner of the screen. It has object coordinates - * (0,0,0), so by the transform below, ends up with eye coordinate - * - * x_eye = x_object / width - 0.5 = - 0.5 - * y_eye = (height - y_object) / width - 0.5 = 0.5 - * z_eye = z_object / width - z_camera = - z_camera - * - * From cogl_perspective(), we know that the projection matrix has - * the form: - * - * (x, 0, 0, 0) - * (0, y, 0, 0) - * (0, 0, c, d) - * (0, 0, -1, 0) - * - * Applied to the above, we get clip coordinates of - * - * x_clip = x * (- 0.5) - * y_clip = y * 0.5 - * w_clip = - 1 * (- z_camera) = z_camera - * - * Dividing through by w to get normalized device coordinates, we - * have, x_nd = x * 0.5 / z_camera, y_nd = - y * 0.5 / z_camera. - * The upper left corner of the screen has normalized device coordinates, - * (-1, 1), so to have the correct 1:1 mapping, we have to have: - * - * z_camera = 0.5 * x = 0.5 * y - * - * If x != y, then we have a non-uniform aspect ration, and a 1:1 mapping - * doesn't make sense. - */ - - cogl_framebuffer_get_projection_matrix (framebuffer, &projection_matrix); - z_camera = 0.5 * graphene_matrix_get_value (&projection_matrix, 0, 0); - - graphene_matrix_init_translate (&mv_matrix, - &GRAPHENE_POINT3D_INIT (0.0f, - -1.0 * height, - 0.0f)); - graphene_matrix_scale (&mv_matrix, 1.0f / width, -1.0f / height, 1.0f / width); - graphene_matrix_translate (&mv_matrix, - &GRAPHENE_POINT3D_INIT (-0.5f, -0.5f, -z_camera)); - cogl_framebuffer_set_modelview_matrix (framebuffer, &mv_matrix); -} - -static void -test_coglbox_map (ClutterActor *actor) -{ - TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (actor); - ClutterActor *stage; - ClutterPerspective perspective; - float stage_width; - float stage_height; - GError *error = NULL; - - CLUTTER_ACTOR_CLASS (test_coglbox_parent_class)->map (actor); - - printf ("Creating offscreen\n"); - priv->framebuffer = - COGL_FRAMEBUFFER (cogl_offscreen_new_with_texture (priv->texture_id)); - if (!cogl_framebuffer_allocate (priv->framebuffer, &error)) - g_error ("Failed to allocate framebuffer: %s", error->message); - - stage = clutter_actor_get_stage (actor); - clutter_stage_get_perspective (CLUTTER_STAGE (stage), &perspective); - clutter_actor_get_size (stage, &stage_width, &stage_height); - - setup_viewport (priv->framebuffer, - stage_width, stage_height, - perspective.fovy, - perspective.aspect, - perspective.z_near, - perspective.z_far); - - if (!priv->framebuffer) - printf ("Failed creating offscreen to texture!\n"); -} - -static void -test_coglbox_init (TestCoglbox *self) -{ - TestCoglboxPrivate *priv; - gchar *file; - - self->priv = priv = TEST_COGLBOX_GET_PRIVATE(self); - - printf ("Loading redhand.png\n"); - file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL); - priv->texhand_id = cogl_texture_new_from_file (file, - COGL_TEXTURE_NONE, - COGL_PIXEL_FORMAT_ANY, - NULL); - g_free (file); - - printf ("Creating texture with size\n"); - priv->texture_id = cogl_texture_new_with_size (200, 200, - COGL_TEXTURE_NONE, - COGL_PIXEL_FORMAT_RGB_888); - - if (priv->texture_id == NULL) - printf ("Failed creating texture with size!\n"); -} - -static void -test_coglbox_class_init (TestCoglboxClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); - - gobject_class->finalize = test_coglbox_finalize; - gobject_class->dispose = test_coglbox_dispose; - - actor_class->map = test_coglbox_map; - actor_class->paint = test_coglbox_paint; -} - -static ClutterActor* -test_coglbox_new (void) -{ - return g_object_new (TEST_TYPE_COGLBOX, NULL); -} - -G_MODULE_EXPORT int -test_cogl_offscreen_main (int argc, char *argv[]) -{ - ClutterActor *stage; - ClutterActor *coglbox; - - clutter_test_init (&argc, &argv); - - /* Stage */ - stage = clutter_test_get_stage (); - clutter_actor_set_size (stage, 400, 400); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl Offscreen Buffers"); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - - /* Cogl Box */ - coglbox = test_coglbox_new (); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), coglbox); - - clutter_actor_show (stage); - - clutter_test_main (); - - return 0; -} - -G_MODULE_EXPORT const char * -test_cogl_offscreen_describe (void) -{ - return "Offscreen buffer support in Cogl."; -} diff --git a/src/tests/clutter/interactive/test-cogl-point-sprites.c b/src/tests/clutter/interactive/test-cogl-point-sprites.c deleted file mode 100644 index 9d6027274..000000000 --- a/src/tests/clutter/interactive/test-cogl-point-sprites.c +++ /dev/null @@ -1,282 +0,0 @@ -#include -#include -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -#define N_FIREWORKS 32 -/* Units per second per second */ -#define GRAVITY -1.5f - -#define N_SPARKS (N_FIREWORKS * 32) /* Must be a power of two */ -#define TIME_PER_SPARK 0.01f /* in seconds */ - -#define TEXTURE_SIZE 32 - -typedef struct _Firework Firework; - -struct _Firework -{ - float size; - float x, y; - float start_x, start_y; - ClutterColor color; - - /* Velocities are in units per second */ - float initial_x_velocity; - float initial_y_velocity; - - GTimer *timer; -}; - -typedef struct _Spark Spark; - -struct _Spark -{ - float x, y; - ClutterColor color; - ClutterColor base_color; -}; - -typedef struct _Data Data; - -struct _Data -{ - Firework fireworks[N_FIREWORKS]; - - int next_spark_num; - Spark sparks[N_SPARKS]; - GTimer *last_spark_time; - - CoglMaterial *material; -}; - -int -test_cogl_point_sprites_main (int argc, char *argv[]); - -const char * -test_cogl_point_sprites_describe (void); - -static CoglHandle -generate_round_texture (void) -{ - guint8 *p, *data; - int x, y; - CoglHandle tex; - - p = data = g_malloc (TEXTURE_SIZE * TEXTURE_SIZE * 4); - - /* Generate a yellow circle which gets transparent towards the edges */ - for (y = 0; y < TEXTURE_SIZE; y++) - for (x = 0; x < TEXTURE_SIZE; x++) - { - int dx = x - TEXTURE_SIZE / 2; - int dy = y - TEXTURE_SIZE / 2; - float value = sqrtf (dx * dx + dy * dy) * 255.0 / (TEXTURE_SIZE / 2); - if (value > 255.0f) - value = 255.0f; - value = 255.0f - value; - *(p++) = value; - *(p++) = value; - *(p++) = value; - *(p++) = value; - } - - tex = cogl_texture_new_from_data (TEXTURE_SIZE, TEXTURE_SIZE, - COGL_TEXTURE_NO_SLICING, - COGL_PIXEL_FORMAT_RGBA_8888_PRE, - COGL_PIXEL_FORMAT_ANY, - TEXTURE_SIZE * 4, - data); - - g_free (data); - - return tex; -} - -static void -on_after_paint (ClutterActor *stage, - ClutterPaintContext *paint_context, - Data *data) -{ - CoglFramebuffer *framebuffer = - clutter_paint_context_get_framebuffer (paint_context); - graphene_matrix_t old_matrix, new_matrix; - int i; - float diff_time; - - cogl_framebuffer_get_projection_matrix (framebuffer, &old_matrix); - /* Use an orthogonal projection from -1 -> 1 in both axes */ - graphene_matrix_init_identity (&new_matrix); - cogl_framebuffer_set_projection_matrix (framebuffer, &new_matrix); - - cogl_framebuffer_push_matrix (framebuffer); - cogl_framebuffer_set_modelview_matrix (framebuffer, &new_matrix); - - /* Update all of the firework's positions */ - for (i = 0; i < N_FIREWORKS; i++) - { - Firework *firework = data->fireworks + i; - - if ((fabsf (firework->x - firework->start_x) > 2.0f) || - firework->y < -1.0f) - { - firework->size = g_random_double_range (0.001f, 0.1f); - firework->start_x = 1.0f + firework->size; - firework->start_y = -1.0f; - firework->initial_x_velocity = g_random_double_range (-0.1f, -2.0f); - firework->initial_y_velocity = g_random_double_range (0.1f, 4.0f); - g_timer_reset (firework->timer); - - /* Pick a random color out of six */ - if (g_random_boolean ()) - { - memset (&firework->color, 0, sizeof (ClutterColor)); - ((guint8 *) &firework->color)[g_random_int_range (0, 3)] = 255; - } - else - { - memset (&firework->color, 255, sizeof (ClutterColor)); - ((guint8 *) &firework->color)[g_random_int_range (0, 3)] = 0; - } - firework->color.alpha = 255; - - /* Fire some of the fireworks from the other side */ - if (g_random_boolean ()) - { - firework->start_x = -firework->start_x; - firework->initial_x_velocity = -firework->initial_x_velocity; - } - } - - diff_time = g_timer_elapsed (firework->timer, NULL); - - firework->x = (firework->start_x + - firework->initial_x_velocity * diff_time); - - firework->y = ((firework->initial_y_velocity * diff_time + - 0.5f * GRAVITY * diff_time * diff_time) + - firework->start_y); - } - - diff_time = g_timer_elapsed (data->last_spark_time, NULL); - if (diff_time < 0.0f || diff_time >= TIME_PER_SPARK) - { - /* Add a new spark for each firework, overwriting the oldest ones */ - for (i = 0; i < N_FIREWORKS; i++) - { - Spark *spark = data->sparks + data->next_spark_num; - Firework *firework = data->fireworks + i; - - spark->x = (firework->x + - g_random_double_range (-firework->size / 2.0f, - firework->size / 2.0f)); - spark->y = (firework->y + - g_random_double_range (-firework->size / 2.0f, - firework->size / 2.0f)); - spark->base_color = firework->color; - - data->next_spark_num = (data->next_spark_num + 1) & (N_SPARKS - 1); - } - - /* Update the colour of each spark */ - for (i = 0; i < N_SPARKS; i++) - { - float color_value; - - /* First spark is the oldest */ - Spark *spark = data->sparks + ((data->next_spark_num + i) - & (N_SPARKS - 1)); - - color_value = i / (N_SPARKS - 1.0f); - spark->color.red = spark->base_color.red * color_value; - spark->color.green = spark->base_color.green * color_value; - spark->color.blue = spark->base_color.blue * color_value; - spark->color.alpha = 255.0f * color_value; - } - - g_timer_reset (data->last_spark_time); - } - - cogl_framebuffer_set_projection_matrix (framebuffer, &old_matrix); - cogl_framebuffer_pop_matrix (framebuffer); -} - -static gboolean -idle_cb (gpointer data) -{ - clutter_actor_queue_redraw (data); - - return G_SOURCE_CONTINUE; -} - -G_MODULE_EXPORT int -test_cogl_point_sprites_main (int argc, char *argv[]) -{ - ClutterActor *stage; - CoglHandle tex; - Data data; - GError *error = NULL; - int i; - - clutter_test_init (&argc, &argv); - - data.material = cogl_material_new (); - data.last_spark_time = g_timer_new (); - data.next_spark_num = 0; - cogl_material_set_point_size (data.material, TEXTURE_SIZE); - - tex = generate_round_texture (); - cogl_material_set_layer (data.material, 0, tex); - cogl_object_unref (tex); - - if (!cogl_material_set_layer_point_sprite_coords_enabled (data.material, - 0, TRUE, - &error)) - { - g_warning ("Failed to enable point sprite coords: %s", error->message); - g_clear_error (&error); - } - - for (i = 0; i < N_FIREWORKS; i++) - { - data.fireworks[i].x = -FLT_MAX; - data.fireworks[i].y = FLT_MAX; - data.fireworks[i].size = 0.0f; - data.fireworks[i].timer = g_timer_new (); - } - - for (i = 0; i < N_SPARKS; i++) - { - data.sparks[i].x = 2.0f; - data.sparks[i].y = 2.0f; - } - - stage = clutter_test_get_stage (); - clutter_actor_set_background_color (CLUTTER_ACTOR (stage), CLUTTER_COLOR_Black); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl Point Sprites"); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - g_signal_connect (CLUTTER_STAGE (stage), "after-paint", G_CALLBACK (on_after_paint), &data); - - clutter_actor_show (stage); - - clutter_threads_add_idle (idle_cb, stage); - - clutter_test_main (); - - cogl_object_unref (data.material); - g_timer_destroy (data.last_spark_time); - - for (i = 0; i < N_FIREWORKS; i++) - g_timer_destroy (data.fireworks[i].timer); - - return 0; -} - -G_MODULE_EXPORT const char * -test_cogl_point_sprites_describe (void) -{ - return "Point sprites support in Cogl."; -} diff --git a/src/tests/clutter/interactive/test-cogl-shader-glsl.c b/src/tests/clutter/interactive/test-cogl-shader-glsl.c deleted file mode 100644 index 62b16e772..000000000 --- a/src/tests/clutter/interactive/test-cogl-shader-glsl.c +++ /dev/null @@ -1,350 +0,0 @@ -#include - -#include -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -typedef struct -{ - const char *name; - const char *source; -} ShaderSource; - -int -test_cogl_shader_glsl_main (int argc, char *argv[]); - -/* a couple of boilerplate defines that are common amongst all the - * sample shaders - */ - -/* FRAGMENT_SHADER_BEGIN: generate boilerplate with a local vec4 color already - * initialized, from a sampler2D in a variable tex. - */ -#define FRAGMENT_SHADER_VARS \ - "uniform sampler2D tex;" \ - "uniform float x_step, y_step;" - -#define FRAGMENT_SHADER_BEGIN \ - "void main (){" \ - " vec4 color = texture2D (tex, vec2(cogl_tex_coord_in[0]));" - -/* FRAGMENT_SHADER_END: apply the changed color to the output buffer correctly - * blended with the gl specified color (makes the opacity of actors work - * correctly). - */ -#define FRAGMENT_SHADER_END \ - " cogl_color_out = color;" \ - " cogl_color_out = cogl_color_out * cogl_color_in;" \ - "}" - -static ShaderSource shaders[]= - { - {"brightness-contrast", - FRAGMENT_SHADER_VARS - "uniform float brightness, contrast;" - FRAGMENT_SHADER_BEGIN - " color.rgb /= color.a;" - " color.rgb = (color.rgb - vec3(0.5, 0.5, 0.5)) * contrast + " - "vec3 (brightness + 0.5, brightness + 0.5, brightness + 0.5);" - " color.rgb *= color.a;" - FRAGMENT_SHADER_END - }, - - {"box-blur", - FRAGMENT_SHADER_VARS - - "vec4 get_rgba_rel(sampler2D tex, float dx, float dy)" - "{" - " return texture2D (tex, cogl_tex_coord_in[0].st " - " + vec2(dx, dy) * 2.0);" - "}" - - FRAGMENT_SHADER_BEGIN - " float count = 1.0;" - " color += get_rgba_rel (tex, -x_step, -y_step); count++;" - " color += get_rgba_rel (tex, -x_step, 0.0); count++;" - " color += get_rgba_rel (tex, -x_step, y_step); count++;" - " color += get_rgba_rel (tex, 0.0, -y_step); count++;" - " color += get_rgba_rel (tex, 0.0, 0.0); count++;" - " color += get_rgba_rel (tex, 0.0, y_step); count++;" - " color += get_rgba_rel (tex, x_step, -y_step); count++;" - " color += get_rgba_rel (tex, x_step, 0.0); count++;" - " color += get_rgba_rel (tex, x_step, y_step); count++;" - " color = color / count;" - FRAGMENT_SHADER_END - }, - - {"invert", - FRAGMENT_SHADER_VARS - FRAGMENT_SHADER_BEGIN - " color.rgb /= color.a;" - " color.rgb = vec3(1.0, 1.0, 1.0) - color.rgb;\n" - " color.rgb *= color.a;" - FRAGMENT_SHADER_END - }, - - {"brightness-contrast", - FRAGMENT_SHADER_VARS - "uniform float brightness;" - "uniform float contrast;" - FRAGMENT_SHADER_BEGIN - " color.rgb /= color.a;" - " color.r = (color.r - 0.5) * contrast + brightness + 0.5;" - " color.g = (color.g - 0.5) * contrast + brightness + 0.5;" - " color.b = (color.b - 0.5) * contrast + brightness + 0.5;" - " color.rgb *= color.a;" - FRAGMENT_SHADER_END - }, - - {"gray", - FRAGMENT_SHADER_VARS - FRAGMENT_SHADER_BEGIN - " float avg = (color.r + color.g + color.b) / 3.0;" - " color.r = avg;" - " color.g = avg;" - " color.b = avg;" - FRAGMENT_SHADER_END - }, - - {"combined-mirror", - FRAGMENT_SHADER_VARS - FRAGMENT_SHADER_BEGIN - " vec4 colorB = texture2D (tex, vec2(cogl_tex_coord_in[0].ts));" - " float avg = (color.r + color.g + color.b) / 3.0;" - " color.r = avg;" - " color.g = avg;" - " color.b = avg;" - " color = (color + colorB)/2.0;" - FRAGMENT_SHADER_END - }, - - {"edge-detect", - FRAGMENT_SHADER_VARS - "float get_avg_rel(sampler2D texB, float dx, float dy)" - "{" - " vec4 colorB = texture2D (texB, cogl_tex_coord_in[0].st + vec2(dx, dy));" - " return (colorB.r + colorB.g + colorB.b) / 3.0;" - "}" - FRAGMENT_SHADER_BEGIN - " mat3 sobel_h = mat3( 1.0, 2.0, 1.0," - " 0.0, 0.0, 0.0," - " -1.0, -2.0, -1.0);" - " mat3 sobel_v = mat3( 1.0, 0.0, -1.0," - " 2.0, 0.0, -2.0," - " 1.0, 0.0, -1.0);" - " mat3 map = mat3( get_avg_rel(tex, -x_step, -y_step)," - " get_avg_rel(tex, -x_step, 0.0)," - " get_avg_rel(tex, -x_step, y_step)," - " get_avg_rel(tex, 0.0, -y_step)," - " get_avg_rel(tex, 0.0, 0.0)," - " get_avg_rel(tex, 0.0, y_step)," - " get_avg_rel(tex, x_step, -y_step)," - " get_avg_rel(tex, x_step, 0.0)," - " get_avg_rel(tex, x_step, y_step) );" - " mat3 gh = sobel_h * map;" - " mat3 gv = map * sobel_v;" - " float avgh = (gh[0][0] + gh[0][1] + gh[0][2] +" - " gh[1][0] + gh[1][1] + gh[1][2] +" - " gh[2][0] + gh[2][1] + gh[2][2]) / 18.0 + 0.5;" - " float avgv = (gv[0][0] + gv[0][1] + gv[0][2] +" - " gv[1][0] + gv[1][1] + gv[1][2] +" - " gv[2][0] + gv[2][1] + gv[2][2]) / 18.0 + 0.5;" - " float avg = (avgh + avgv) / 2.0;" - " color.r = avg * color.r;" - " color.g = avg * color.g;" - " color.b = avg * color.b;" - FRAGMENT_SHADER_END - } -}; - -static CoglHandle redhand; -static CoglMaterial *material; -static unsigned int timeout_id = 0; -static int shader_no = 0; - -static void -on_after_paint (ClutterActor *actor, - ClutterPaintContext *paint_context) -{ - CoglFramebuffer *framebuffer = - clutter_paint_context_get_framebuffer (paint_context); - float stage_width = clutter_actor_get_width (actor); - float stage_height = clutter_actor_get_height (actor); - float image_width = cogl_texture_get_width (redhand); - float image_height = cogl_texture_get_height (redhand); - - cogl_framebuffer_draw_rectangle (framebuffer, COGL_PIPELINE (material), - stage_width / 2.0f - image_width / 2.0f, - stage_height / 2.0f - image_height / 2.0f, - stage_width / 2.0f + image_width / 2.0f, - stage_height / 2.0f + image_height / 2.0f); -} - -static void -set_shader_num (int new_no) -{ - CoglHandle shader; - CoglHandle program; - int image_width = cogl_texture_get_width (redhand); - int image_height = cogl_texture_get_height (redhand); - int uniform_no; - - g_print ("setting shaders[%i] named '%s'\n", - new_no, - shaders[new_no].name); - - shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT); - cogl_shader_source (shader, shaders[new_no].source); - - program = cogl_create_program (); - cogl_program_attach_shader (program, shader); - cogl_object_unref (shader); - cogl_program_link (program); - - uniform_no = cogl_program_get_uniform_location (program, "tex"); - cogl_program_set_uniform_1i (program, uniform_no, 0); - uniform_no = cogl_program_get_uniform_location (program, "radius"); - cogl_program_set_uniform_1f (program, uniform_no, 3.0); - uniform_no = cogl_program_get_uniform_location (program, "brightness"); - cogl_program_set_uniform_1f (program, uniform_no, 0.4); - uniform_no = cogl_program_get_uniform_location (program, "contrast"); - cogl_program_set_uniform_1f (program, uniform_no, -1.9); - - uniform_no = cogl_program_get_uniform_location (program, "x_step"); - cogl_program_set_uniform_1f (program, uniform_no, 1.0f / image_width); - uniform_no = cogl_program_get_uniform_location (program, "y_step"); - cogl_program_set_uniform_1f (program, uniform_no, 1.0f / image_height); - - cogl_material_set_user_program (material, program); - cogl_object_unref (program); - - shader_no = new_no; -} - -static gboolean -button_release_cb (ClutterActor *actor, - ClutterEvent *event, - gpointer data) -{ - int new_no; - - /* Stop the automatic cycling if the user want to manually control - * which shader to display */ - g_clear_handle_id (&timeout_id, g_source_remove); - - if (event->button.button == 1) - { - new_no = shader_no - 1; - if (new_no < 0) - new_no = G_N_ELEMENTS (shaders) - 1; - } - else - { - new_no = shader_no + 1; - if (new_no >= G_N_ELEMENTS (shaders)) - new_no = 0; - } - - set_shader_num (new_no); - - return CLUTTER_EVENT_STOP; -} - -static gboolean -key_release_cb (ClutterActor *actor, - ClutterEvent *event, - gpointer user_data) -{ - guint keysym = clutter_event_get_key_symbol (event); - ClutterModifierType mods = clutter_event_get_state (event); - - if (keysym == CLUTTER_KEY_q || - ((mods & CLUTTER_SHIFT_MASK) && keysym == CLUTTER_KEY_q)) - clutter_test_quit (); - - return CLUTTER_EVENT_STOP; -} - -static gboolean -timeout_cb (gpointer user_data) -{ - shader_no++; - if (shader_no > (G_N_ELEMENTS (shaders) - 1)) - shader_no = 0; - - set_shader_num (shader_no); - - return G_SOURCE_CONTINUE; -} - -static gboolean -idle_cb (gpointer data) -{ - clutter_actor_queue_redraw (data); - - return G_SOURCE_CONTINUE; -} - -static gboolean -destroy_window_cb (ClutterStage *stage, - ClutterEvent *event, - gpointer user_data) -{ - clutter_test_quit (); - - return CLUTTER_EVENT_STOP; -} - -G_MODULE_EXPORT int -test_cogl_shader_glsl_main (int argc, char *argv[]) -{ - ClutterActor *stage; - char *file; - GError *error; - ClutterColor stage_color = { 0x61, 0x64, 0x8c, 0xff }; - - clutter_test_init (&argc, &argv); - - stage = clutter_test_get_stage (); - - clutter_stage_set_title (CLUTTER_STAGE (stage), "Assembly Shader Test"); - clutter_actor_set_background_color (CLUTTER_ACTOR (stage), &stage_color); - - file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL); - error = NULL; - redhand = cogl_texture_new_from_file (file, - COGL_TEXTURE_NO_ATLAS, - COGL_PIXEL_FORMAT_ANY, - &error); - if (redhand == NULL) - g_error ("image load failed: %s", error->message); - - material = cogl_material_new (); - cogl_material_set_layer (material, 0, redhand); - - set_shader_num (0); - g_signal_connect (CLUTTER_STAGE (stage), "after-paint", G_CALLBACK (on_after_paint), NULL); - - clutter_actor_set_reactive (stage, TRUE); - g_signal_connect (stage, "button-release-event", - G_CALLBACK (button_release_cb), NULL); - g_signal_connect (stage, "key-release-event", - G_CALLBACK (key_release_cb), NULL); - - g_signal_connect (stage, "delete-event", - G_CALLBACK (destroy_window_cb), NULL); - - timeout_id = clutter_threads_add_timeout (1000, timeout_cb, NULL); - - clutter_threads_add_idle (idle_cb, stage); - - clutter_actor_show (stage); - - clutter_test_main (); - - return EXIT_SUCCESS; -} - diff --git a/src/tests/clutter/interactive/test-cogl-tex-convert.c b/src/tests/clutter/interactive/test-cogl-tex-convert.c deleted file mode 100644 index c098ff6a3..000000000 --- a/src/tests/clutter/interactive/test-cogl-tex-convert.c +++ /dev/null @@ -1,245 +0,0 @@ -#include -#include -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -/* Coglbox declaration - *--------------------------------------------------*/ - -G_BEGIN_DECLS - -#define TEST_TYPE_COGLBOX test_coglbox_get_type() - -#define TEST_COGLBOX(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - TEST_TYPE_COGLBOX, TestCoglbox)) - -#define TEST_COGLBOX_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - TEST_TYPE_COGLBOX, TestCoglboxClass)) - -#define TEST_IS_COGLBOX(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ - TEST_TYPE_COGLBOX)) - -#define TEST_IS_COGLBOX_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), \ - TEST_TYPE_COGLBOX)) - -#define TEST_COGLBOX_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - TEST_TYPE_COGLBOX, TestCoglboxClass)) - -typedef struct _TestCoglbox TestCoglbox; -typedef struct _TestCoglboxClass TestCoglboxClass; -typedef struct _TestCoglboxPrivate TestCoglboxPrivate; - -struct _TestCoglbox -{ - ClutterActor parent; - - /*< private >*/ - TestCoglboxPrivate *priv; -}; - -struct _TestCoglboxClass -{ - ClutterActorClass parent_class; - - /* padding for future expansion */ - void (*_test_coglbox1) (void); - void (*_test_coglbox2) (void); - void (*_test_coglbox3) (void); - void (*_test_coglbox4) (void); -}; - -static GType test_coglbox_get_type (void) G_GNUC_CONST; - -int -test_cogl_tex_convert_main (int argc, char *argv[]); - -const char * -test_cogl_tex_convert_describe (void); - -G_END_DECLS - -/* Coglbox private declaration - *--------------------------------------------------*/ - -struct _TestCoglboxPrivate -{ - CoglHandle cogl_tex_id[4]; - gint frame; -}; - -G_DEFINE_TYPE_WITH_PRIVATE (TestCoglbox, test_coglbox, CLUTTER_TYPE_ACTOR); - -#define TEST_COGLBOX_GET_PRIVATE(obj) \ -(test_coglbox_get_instance_private (TEST_COGLBOX ((obj)))) - -/* Coglbox implementation - *--------------------------------------------------*/ - -static void -test_coglbox_paint (ClutterActor *self, - ClutterPaintContext *paint_context) -{ - TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (self); - CoglPipeline *pipeline; - CoglFramebuffer *framebuffer = - clutter_paint_context_get_framebuffer (paint_context); - CoglContext *ctx = cogl_framebuffer_get_context (framebuffer); - gfloat texcoords[4] = { 0.0, 0.0, 1.0, 1.0 }; - - priv = TEST_COGLBOX_GET_PRIVATE (self); - - pipeline = cogl_pipeline_new (ctx); - cogl_pipeline_set_color4ub (pipeline, 0x66, 0x66, 0xdd, 0xff); - cogl_framebuffer_draw_rectangle (framebuffer, pipeline, 0, 0, 400, 400); - cogl_object_unref (pipeline); - - pipeline = cogl_pipeline_new (ctx); - - cogl_framebuffer_push_matrix (framebuffer); - cogl_pipeline_set_layer_texture (pipeline, 0, priv->cogl_tex_id[0]); - cogl_framebuffer_draw_textured_rectangle (framebuffer, pipeline, - 0, 0, 200, 213, - texcoords[0], texcoords[1], - texcoords[2], texcoords[3]); - - cogl_framebuffer_pop_matrix (framebuffer); - cogl_framebuffer_push_matrix (framebuffer); - cogl_framebuffer_translate (framebuffer, 200, 0, 0); - cogl_pipeline_set_layer_texture (pipeline, 0, priv->cogl_tex_id[1]); - cogl_framebuffer_draw_textured_rectangle (framebuffer, pipeline, - 0, 0, 200, 213, - texcoords[0], texcoords[1], - texcoords[2], texcoords[3]); - - cogl_framebuffer_pop_matrix (framebuffer); - cogl_framebuffer_push_matrix (framebuffer); - cogl_framebuffer_translate (framebuffer, 0, 200, 0); - cogl_pipeline_set_layer_texture (pipeline, 0, priv->cogl_tex_id[2]); - cogl_framebuffer_draw_textured_rectangle (framebuffer, pipeline, - 0, 0, 200, 213, - texcoords[0], texcoords[1], - texcoords[2], texcoords[3]); - - cogl_framebuffer_pop_matrix (framebuffer); - cogl_framebuffer_push_matrix (framebuffer); - cogl_framebuffer_translate (framebuffer, 200, 200, 0); - cogl_pipeline_set_layer_texture (pipeline, 0, priv->cogl_tex_id[3]); - cogl_framebuffer_draw_textured_rectangle (framebuffer, pipeline, - 0, 0, 200, 213, - texcoords[0], texcoords[1], - texcoords[2], texcoords[3]); - cogl_framebuffer_pop_matrix (framebuffer); - - cogl_object_unref (pipeline); - -} - -static void -test_coglbox_finalize (GObject *object) -{ - G_OBJECT_CLASS (test_coglbox_parent_class)->finalize (object); -} - -static void -test_coglbox_dispose (GObject *object) -{ - TestCoglboxPrivate *priv; - - priv = TEST_COGLBOX_GET_PRIVATE (object); - cogl_object_unref (priv->cogl_tex_id); - - G_OBJECT_CLASS (test_coglbox_parent_class)->dispose (object); -} - -static void -test_coglbox_init (TestCoglbox *self) -{ - TestCoglboxPrivate *priv; - gchar *file; - - self->priv = priv = TEST_COGLBOX_GET_PRIVATE(self); - - file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL); - - priv->cogl_tex_id[0] = - cogl_texture_new_from_file (file, - COGL_TEXTURE_NONE, - COGL_PIXEL_FORMAT_ANY, - NULL); - - priv->cogl_tex_id[1] = - cogl_texture_new_from_file (file, - COGL_TEXTURE_NONE, - COGL_PIXEL_FORMAT_BGRA_8888, - NULL); - - priv->cogl_tex_id[2] = - cogl_texture_new_from_file (file, - COGL_TEXTURE_NONE, - COGL_PIXEL_FORMAT_ARGB_8888, - NULL); - - priv->cogl_tex_id[3] = - cogl_texture_new_from_file (file, - COGL_TEXTURE_NONE, - COGL_PIXEL_FORMAT_G_8, - NULL); - - g_free (file); -} - -static void -test_coglbox_class_init (TestCoglboxClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); - - gobject_class->finalize = test_coglbox_finalize; - gobject_class->dispose = test_coglbox_dispose; - actor_class->paint = test_coglbox_paint; -} - -static ClutterActor* -test_coglbox_new (void) -{ - return g_object_new (TEST_TYPE_COGLBOX, NULL); -} - -G_MODULE_EXPORT int -test_cogl_tex_convert_main (int argc, char *argv[]) -{ - ClutterActor *stage; - ClutterActor *coglbox; - - clutter_test_init (&argc, &argv); - - /* Stage */ - stage = clutter_test_get_stage (); - clutter_actor_set_size (stage, 400, 400); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl Texture Conversion"); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - - /* Cogl Box */ - coglbox = test_coglbox_new (); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), coglbox); - - clutter_actor_show (stage); - - clutter_test_main (); - - return 0; -} - -G_MODULE_EXPORT const char * -test_cogl_tex_convert_describe (void) -{ - return "Pixel format conversion of Cogl textures."; -} diff --git a/src/tests/clutter/interactive/test-cogl-tex-polygon.c b/src/tests/clutter/interactive/test-cogl-tex-polygon.c deleted file mode 100644 index 2479a3d7c..000000000 --- a/src/tests/clutter/interactive/test-cogl-tex-polygon.c +++ /dev/null @@ -1,455 +0,0 @@ -#include -#include -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -/* Coglbox declaration - *--------------------------------------------------*/ - -G_BEGIN_DECLS - -#define TEST_TYPE_COGLBOX test_coglbox_get_type() - -#define TEST_COGLBOX(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - TEST_TYPE_COGLBOX, TestCoglbox)) - -#define TEST_COGLBOX_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - TEST_TYPE_COGLBOX, TestCoglboxClass)) - -#define TEST_IS_COGLBOX(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ - TEST_TYPE_COGLBOX)) - -#define TEST_IS_COGLBOX_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), \ - TEST_TYPE_COGLBOX)) - -#define TEST_COGLBOX_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - TEST_TYPE_COGLBOX, TestCoglboxClass)) - -typedef struct _TestCoglbox TestCoglbox; -typedef struct _TestCoglboxClass TestCoglboxClass; -typedef struct _TestCoglboxPrivate TestCoglboxPrivate; - -struct _TestCoglbox -{ - ClutterActor parent; - - /*< private >*/ - TestCoglboxPrivate *priv; -}; - -struct _TestCoglboxClass -{ - ClutterActorClass parent_class; - - /* padding for future expansion */ - void (*_test_coglbox1) (void); - void (*_test_coglbox2) (void); - void (*_test_coglbox3) (void); - void (*_test_coglbox4) (void); -}; - -static GType test_coglbox_get_type (void) G_GNUC_CONST; - -int -test_cogl_tex_polygon_main (int argc, char *argv[]); - -const char * -test_cogl_tex_polygon_describe (void); - -G_END_DECLS - -/* Coglbox private declaration - *--------------------------------------------------*/ - -struct _TestCoglboxPrivate -{ - CoglHandle sliced_tex, not_sliced_tex; - gint frame; - gboolean use_sliced; - gboolean use_linear_filtering; -}; - -G_DEFINE_TYPE_WITH_PRIVATE (TestCoglbox, test_coglbox, CLUTTER_TYPE_ACTOR); - -#define TEST_COGLBOX_GET_PRIVATE(obj) \ -((TestCoglboxPrivate *)test_coglbox_get_instance_private (TEST_COGLBOX ((obj)))) - -/* Coglbox implementation - *--------------------------------------------------*/ - -static void -test_coglbox_fade_texture (CoglFramebuffer *framebuffer, - CoglPipeline *pipeline, - float x1, - float y1, - float x2, - float y2, - float tx1, - float ty1, - float tx2, - float ty2) -{ - CoglVertexP3T2C4 vertices[4]; - CoglPrimitive *primitive; - int i; - - vertices[0].x = x1; - vertices[0].y = y1; - vertices[0].z = 0; - vertices[0].s = tx1; - vertices[0].t = ty1; - vertices[1].x = x1; - vertices[1].y = y2; - vertices[1].z = 0; - vertices[1].s = tx1; - vertices[1].t = ty2; - vertices[2].x = x2; - vertices[2].y = y2; - vertices[2].z = 0; - vertices[2].s = tx2; - vertices[2].t = ty2; - vertices[3].x = x2; - vertices[3].y = y1; - vertices[3].z = 0; - vertices[3].s = tx2; - vertices[3].t = ty1; - - for (i = 0; i < 4; i++) - { - CoglColor cogl_color; - - cogl_color_init_from_4ub (&cogl_color, - 255, - 255, - 255, - ((i ^ (i >> 1)) & 1) ? 0 : 128); - cogl_color_premultiply (&cogl_color); - vertices[i].r = cogl_color_get_red_byte (&cogl_color); - vertices[i].g = cogl_color_get_green_byte (&cogl_color); - vertices[i].b = cogl_color_get_blue_byte (&cogl_color); - vertices[i].a = cogl_color_get_alpha_byte (&cogl_color); - } - - primitive = - cogl_primitive_new_p3t2c4 (cogl_framebuffer_get_context (framebuffer), - COGL_VERTICES_MODE_TRIANGLE_FAN, - 4, - vertices); - cogl_primitive_draw (primitive, framebuffer, pipeline); - cogl_object_unref (primitive); -} - -static void -test_coglbox_triangle_texture (CoglFramebuffer *framebuffer, - CoglHandle material, - int tex_width, - int tex_height, - float x, - float y, - float tx1, - float ty1, - float tx2, - float ty2, - float tx3, - float ty3) -{ - CoglVertexP3T2 vertices[3]; - CoglPrimitive *primitive; - - vertices[0].x = x + tx1 * tex_width; - vertices[0].y = y + ty1 * tex_height; - vertices[0].z = 0; - vertices[0].s = tx1; - vertices[0].t = ty1; - - vertices[1].x = x + tx2 * tex_width; - vertices[1].y = y + ty2 * tex_height; - vertices[1].z = 0; - vertices[1].s = tx2; - vertices[1].t = ty2; - - vertices[2].x = x + tx3 * tex_width; - vertices[2].y = y + ty3 * tex_height; - vertices[2].z = 0; - vertices[2].s = tx3; - vertices[2].t = ty3; - - primitive = cogl_primitive_new_p3t2 (cogl_framebuffer_get_context (framebuffer), - COGL_VERTICES_MODE_TRIANGLE_FAN, - 3, - vertices); - cogl_primitive_draw (primitive, framebuffer, material); - cogl_object_unref (primitive); -} - -static void -test_coglbox_paint (ClutterActor *self, - ClutterPaintContext *paint_context) -{ - TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (self); - CoglHandle tex_handle = priv->use_sliced ? priv->sliced_tex - : priv->not_sliced_tex; - int tex_width = cogl_texture_get_width (tex_handle); - int tex_height = cogl_texture_get_height (tex_handle); - CoglFramebuffer *framebuffer = - clutter_paint_context_get_framebuffer (paint_context); - CoglHandle material = cogl_material_new (); - - cogl_material_set_layer (material, 0, tex_handle); - - cogl_material_set_layer_filters (material, 0, - priv->use_linear_filtering - ? COGL_MATERIAL_FILTER_LINEAR : - COGL_MATERIAL_FILTER_NEAREST, - priv->use_linear_filtering - ? COGL_MATERIAL_FILTER_LINEAR : - COGL_MATERIAL_FILTER_NEAREST); - - cogl_framebuffer_push_matrix (framebuffer); - cogl_framebuffer_translate (framebuffer, tex_width / 2, 0, 0); - cogl_framebuffer_rotate (framebuffer, priv->frame, 0, 1, 0); - cogl_framebuffer_translate (framebuffer, -tex_width / 2, 0, 0); - - /* Draw a hand and reflect it */ - cogl_framebuffer_draw_textured_rectangle (framebuffer, material, - 0, 0, tex_width, tex_height, - 0, 0, 1, 1); - test_coglbox_fade_texture (framebuffer, material, - 0, tex_height, - tex_width, (tex_height * 3 / 2), - 0.0, 1.0, - 1.0, 0.5); - - cogl_framebuffer_pop_matrix (framebuffer); - - cogl_framebuffer_push_matrix (framebuffer); - cogl_framebuffer_translate (framebuffer, tex_width * 3 / 2 + 60, 0, 0); - cogl_framebuffer_rotate (framebuffer, priv->frame, 0, 1, 0); - cogl_framebuffer_translate (framebuffer, -tex_width / 2 - 10, 0, 0); - - /* Draw the texture split into two triangles */ - test_coglbox_triangle_texture (framebuffer, material, - tex_width, tex_height, - 0, 0, - 0, 0, - 0, 1, - 1, 1); - test_coglbox_triangle_texture (framebuffer, material, - tex_width, tex_height, - 20, 0, - 0, 0, - 1, 0, - 1, 1); - - cogl_framebuffer_pop_matrix (framebuffer); - - cogl_object_unref (material); -} - -static void -test_coglbox_finalize (GObject *object) -{ - G_OBJECT_CLASS (test_coglbox_parent_class)->finalize (object); -} - -static void -test_coglbox_dispose (GObject *object) -{ - TestCoglboxPrivate *priv; - - priv = TEST_COGLBOX_GET_PRIVATE (object); - cogl_object_unref (priv->not_sliced_tex); - cogl_object_unref (priv->sliced_tex); - - G_OBJECT_CLASS (test_coglbox_parent_class)->dispose (object); -} - -static void -test_coglbox_init (TestCoglbox *self) -{ - TestCoglboxPrivate *priv; - GError *error = NULL; - gchar *file; - - self->priv = priv = TEST_COGLBOX_GET_PRIVATE (self); - - priv->use_linear_filtering = FALSE; - priv->use_sliced = FALSE; - - file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL); - priv->sliced_tex = - cogl_texture_new_from_file (file, - COGL_TEXTURE_NONE, - COGL_PIXEL_FORMAT_ANY, - &error); - if (priv->sliced_tex == NULL) - { - if (error) - { - g_warning ("Texture loading failed: %s", error->message); - g_error_free (error); - error = NULL; - } - else - g_warning ("Texture loading failed: "); - } - - priv->not_sliced_tex = - cogl_texture_new_from_file (file, - COGL_TEXTURE_NO_SLICING, - COGL_PIXEL_FORMAT_ANY, - &error); - if (priv->not_sliced_tex == NULL) - { - if (error) - { - g_warning ("Texture loading failed: %s", error->message); - g_error_free (error); - } - else - g_warning ("Texture loading failed: "); - } - - g_free (file); -} - -static void -test_coglbox_class_init (TestCoglboxClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); - - gobject_class->finalize = test_coglbox_finalize; - gobject_class->dispose = test_coglbox_dispose; - actor_class->paint = test_coglbox_paint; -} - -static ClutterActor* -test_coglbox_new (void) -{ - return g_object_new (TEST_TYPE_COGLBOX, NULL); -} - -static void -frame_cb (ClutterTimeline *timeline, - gint elapsed_msecs, - gpointer data) -{ - TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (data); - gdouble progress = clutter_timeline_get_progress (timeline); - - priv->frame = 360.0 * progress; - clutter_actor_queue_redraw (CLUTTER_ACTOR (data)); -} - -static void -update_toggle_text (ClutterText *button, gboolean val) -{ - clutter_text_set_text (button, val ? "Enabled" : "Disabled"); -} - -static gboolean -on_toggle_click (ClutterActor *button, ClutterEvent *event, - gboolean *toggle_val) -{ - update_toggle_text (CLUTTER_TEXT (button), *toggle_val = !*toggle_val); - - return TRUE; -} - -static ClutterActor * -make_toggle (const char *label_text, gboolean *toggle_val) -{ - ClutterActor *group = clutter_actor_new (); - ClutterActor *label = clutter_text_new_with_text ("Sans 14", label_text); - ClutterActor *button = clutter_text_new_with_text ("Sans 14", ""); - - clutter_actor_set_reactive (button, TRUE); - - update_toggle_text (CLUTTER_TEXT (button), *toggle_val); - - clutter_actor_set_position (button, clutter_actor_get_width (label) + 10, 0); - clutter_container_add (CLUTTER_CONTAINER (group), label, button, NULL); - - g_signal_connect (button, "button-press-event", G_CALLBACK (on_toggle_click), - toggle_val); - - return group; -} - -G_MODULE_EXPORT int -test_cogl_tex_polygon_main (int argc, char *argv[]) -{ - ClutterActor *stage; - ClutterActor *coglbox; - ClutterActor *filtering_toggle; - ClutterActor *slicing_toggle; - ClutterActor *note; - ClutterTimeline *timeline; - ClutterColor blue = { 0x30, 0x30, 0xff, 0xff }; - - clutter_test_init (&argc, &argv); - - /* Stage */ - stage = clutter_test_get_stage (); - clutter_actor_set_background_color (CLUTTER_ACTOR (stage), &blue); - clutter_actor_set_size (stage, 640, 480); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl Texture Polygon"); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - - /* Cogl Box */ - coglbox = test_coglbox_new (); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), coglbox); - - /* Timeline for animation */ - timeline = clutter_timeline_new_for_actor (stage, 6000); - clutter_timeline_set_repeat_count (timeline, -1); - g_signal_connect (timeline, "new-frame", G_CALLBACK (frame_cb), coglbox); - clutter_timeline_start (timeline); - - /* Labels for toggling settings */ - slicing_toggle = make_toggle ("Texture slicing: ", - &(TEST_COGLBOX_GET_PRIVATE (coglbox) - ->use_sliced)); - clutter_actor_set_position (slicing_toggle, 0, - clutter_actor_get_height (stage) - - clutter_actor_get_height (slicing_toggle)); - filtering_toggle = make_toggle ("Linear filtering: ", - &(TEST_COGLBOX_GET_PRIVATE (coglbox) - ->use_linear_filtering)); - clutter_actor_set_position (filtering_toggle, 0, - clutter_actor_get_y (slicing_toggle) - - clutter_actor_get_height (filtering_toggle)); - note = clutter_text_new_with_text ("Sans 10", "<- Click to change"); - clutter_actor_set_position (note, - clutter_actor_get_width (filtering_toggle) + 10, - (clutter_actor_get_height (stage) - + clutter_actor_get_y (filtering_toggle)) / 2 - - clutter_actor_get_height (note) / 2); - - clutter_container_add (CLUTTER_CONTAINER (stage), - slicing_toggle, - filtering_toggle, - note, - NULL); - - clutter_actor_show (stage); - - clutter_test_main (); - - return 0; -} - -G_MODULE_EXPORT const char * -test_cogl_tex_polygon_describe (void) -{ - return "Texture polygon primitive."; -} diff --git a/src/tests/clutter/interactive/test-cogl-tex-tile.c b/src/tests/clutter/interactive/test-cogl-tex-tile.c deleted file mode 100644 index d51522491..000000000 --- a/src/tests/clutter/interactive/test-cogl-tex-tile.c +++ /dev/null @@ -1,235 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -/* Coglbox declaration - *--------------------------------------------------*/ - -G_BEGIN_DECLS - -#define TEST_TYPE_COGLBOX test_coglbox_get_type() - -#define TEST_COGLBOX(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ - TEST_TYPE_COGLBOX, TestCoglbox)) - -#define TEST_COGLBOX_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), \ - TEST_TYPE_COGLBOX, TestCoglboxClass)) - -#define TEST_IS_COGLBOX(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ - TEST_TYPE_COGLBOX)) - -#define TEST_IS_COGLBOX_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), \ - TEST_TYPE_COGLBOX)) - -#define TEST_COGLBOX_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), \ - TEST_TYPE_COGLBOX, TestCoglboxClass)) - -typedef struct _TestCoglbox TestCoglbox; -typedef struct _TestCoglboxClass TestCoglboxClass; -typedef struct _TestCoglboxPrivate TestCoglboxPrivate; - -struct _TestCoglbox -{ - ClutterActor parent; - - /*< private >*/ - TestCoglboxPrivate *priv; -}; - -struct _TestCoglboxClass -{ - ClutterActorClass parent_class; - - /* padding for future expansion */ - void (*_test_coglbox1) (void); - void (*_test_coglbox2) (void); - void (*_test_coglbox3) (void); - void (*_test_coglbox4) (void); -}; - -static GType test_coglbox_get_type (void) G_GNUC_CONST; - -int -test_cogl_tex_tile_main (int argc, char *argv[]); - -const char * -test_cogl_tex_tile_describe (void); - -G_END_DECLS - -/* Coglbox private declaration - *--------------------------------------------------*/ - -struct _TestCoglboxPrivate -{ - CoglHandle cogl_tex_id; - gdouble animation_progress; -}; - -G_DEFINE_TYPE_WITH_PRIVATE (TestCoglbox, test_coglbox, CLUTTER_TYPE_ACTOR); - -#define TEST_COGLBOX_GET_PRIVATE(obj) \ -(test_coglbox_get_instance_private (TEST_COGLBOX ((obj)))) - -/* Coglbox implementation - *--------------------------------------------------*/ - -static void -test_coglbox_paint (ClutterActor *self, - ClutterPaintContext *paint_context) -{ - TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (self); - CoglFramebuffer *framebuffer = - clutter_paint_context_get_framebuffer (paint_context); - CoglContext *ctx = cogl_framebuffer_get_context (framebuffer); - CoglPipeline *pipeline; - gfloat texcoords[4] = { 0.0f, 0.0f, 1.0f, 1.0f }; - gfloat angle; - gfloat frac; - gint t; - - angle = priv->animation_progress * 2 * G_PI; - - frac = ((priv->animation_progress <= 0.5f - ? priv->animation_progress - : 1.0f - priv->animation_progress) + 0.5f) * 2.0f; - - for (t=0; t<4; t+=2) - { - texcoords[t] += cos (angle); - texcoords[t+1] += sin (angle); - - texcoords[t] *= frac; - texcoords[t+1] *= frac; - } - - priv = TEST_COGLBOX_GET_PRIVATE (self); - - cogl_framebuffer_push_matrix (framebuffer); - - pipeline = cogl_pipeline_new (ctx); - cogl_pipeline_set_color4ub (pipeline, 0x66, 0x66, 0xdd, 0xff); - cogl_framebuffer_draw_rectangle (framebuffer, pipeline, 0, 0, 400, 400); - cogl_object_unref (pipeline); - - cogl_framebuffer_translate (framebuffer, 100, 100, 0); - - pipeline = cogl_pipeline_new (ctx); - cogl_pipeline_set_layer_texture (pipeline, 0, priv->cogl_tex_id); - cogl_framebuffer_draw_textured_rectangle (framebuffer, pipeline, - 0, 0, 200, 213, - texcoords[0], texcoords[1], - texcoords[2], texcoords[3]); - cogl_object_unref (pipeline); - - cogl_framebuffer_pop_matrix (framebuffer); -} - -static void -test_coglbox_finalize (GObject *object) -{ - G_OBJECT_CLASS (test_coglbox_parent_class)->finalize (object); -} - -static void -test_coglbox_dispose (GObject *object) -{ - TestCoglboxPrivate *priv; - - priv = TEST_COGLBOX_GET_PRIVATE (object); - cogl_object_unref (priv->cogl_tex_id); - - G_OBJECT_CLASS (test_coglbox_parent_class)->dispose (object); -} - -static void -test_coglbox_init (TestCoglbox *self) -{ - TestCoglboxPrivate *priv; - gchar *file; - - self->priv = priv = TEST_COGLBOX_GET_PRIVATE(self); - - file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL); - priv->cogl_tex_id = cogl_texture_new_from_file (file, - COGL_TEXTURE_NONE, - COGL_PIXEL_FORMAT_ANY, - NULL); - g_free (file); -} - -static void -test_coglbox_class_init (TestCoglboxClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); - - gobject_class->finalize = test_coglbox_finalize; - gobject_class->dispose = test_coglbox_dispose; - actor_class->paint = test_coglbox_paint; -} - -static ClutterActor* -test_coglbox_new (void) -{ - return g_object_new (TEST_TYPE_COGLBOX, NULL); -} - -static void -frame_cb (ClutterTimeline *timeline, - gint msecs, - gpointer data) -{ - TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (data); - - priv->animation_progress = clutter_timeline_get_progress (timeline); - clutter_actor_queue_redraw (CLUTTER_ACTOR (data)); -} - -G_MODULE_EXPORT int -test_cogl_tex_tile_main (int argc, char *argv[]) -{ - ClutterActor *stage; - ClutterActor *coglbox; - ClutterTimeline *timeline; - - clutter_test_init (&argc, &argv); - - /* Stage */ - stage = clutter_test_get_stage (); - clutter_actor_set_size (stage, 400, 400); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl Texture Tiling"); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - - /* Cogl Box */ - coglbox = test_coglbox_new (); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), coglbox); - - /* Timeline for animation */ - timeline = clutter_timeline_new_for_actor (stage, 6000); /* 6 second duration */ - clutter_timeline_set_repeat_count (timeline, -1); - g_signal_connect (timeline, "new-frame", G_CALLBACK (frame_cb), coglbox); - clutter_timeline_start (timeline); - - clutter_actor_show (stage); - - clutter_test_main (); - - return 0; -} - -G_MODULE_EXPORT const char * -test_cogl_tex_tile_describe (void) -{ - return "Texture tiling."; -} diff --git a/src/tests/clutter/interactive/test-content.c b/src/tests/clutter/interactive/test-content.c deleted file mode 100644 index fbeebaba3..000000000 --- a/src/tests/clutter/interactive/test-content.c +++ /dev/null @@ -1,242 +0,0 @@ -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -typedef struct _ColorContent { - GObject parent_instance; - - double red; - double green; - double blue; - double alpha; - - float padding; -} ColorContent; - -typedef struct _ColorContentClass { - GObjectClass parent_class; -} ColorContentClass; - -static void clutter_content_iface_init (ClutterContentInterface *iface); - -GType color_content_get_type (void); - -int -test_content_main (int argc, char *argv[]); - -const char * -test_content_describe (void); - -G_DEFINE_TYPE_WITH_CODE (ColorContent, color_content, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTENT, - clutter_content_iface_init)) - -static void -color_content_paint_content (ClutterContent *content, - ClutterActor *actor, - ClutterPaintNode *root, - ClutterPaintContext *paint_context) -{ - ColorContent *self = (ColorContent *) content; - ClutterActorBox box, content_box; - ClutterColor color; - PangoLayout *layout; - PangoRectangle logical; - ClutterPaintNode *node; - -#if 0 - g_debug ("Painting content [%p] " - "{ r:%.2f, g:%.2f, b:%.2f, a:%.2f } " - "for actor [%p] (context: [%p])", - content, - self->red, - self->green, - self->blue, - self->alpha, - actor, context); -#endif - - clutter_actor_get_content_box (actor, &content_box); - - box = content_box; - box.x1 += self->padding; - box.y1 += self->padding; - box.x2 -= self->padding; - box.y2 -= self->padding; - - color.alpha = self->alpha * 255; - - color.red = self->red * 255; - color.green = self->green * 255; - color.blue = self->blue * 255; - - node = clutter_color_node_new (&color); - clutter_paint_node_add_rectangle (node, &box); - clutter_paint_node_add_child (root, node); - clutter_paint_node_unref (node); - - color.red = (1.0 - self->red) * 255; - color.green = (1.0 - self->green) * 255; - color.blue = (1.0 - self->blue) * 255; - - layout = clutter_actor_create_pango_layout (actor, "A"); - pango_layout_get_pixel_extents (layout, NULL, &logical); - - node = clutter_text_node_new (layout, &color); - - /* top-left */ - box.x1 = clutter_actor_box_get_x (&content_box); - box.y1 = clutter_actor_box_get_y (&content_box); - box.x2 = box.x1 + logical.width; - box.y2 = box.y1 + logical.height; - clutter_paint_node_add_rectangle (node, &box); - - /* top-right */ - box.x1 = clutter_actor_box_get_x (&content_box) - + clutter_actor_box_get_width (&content_box) - - logical.width; - box.y1 = clutter_actor_box_get_y (&content_box); - box.x2 = box.x1 + logical.width; - box.y2 = box.y1 + logical.height; - clutter_paint_node_add_rectangle (node, &box); - - /* bottom-right */ - box.x1 = clutter_actor_box_get_x (&content_box) - + clutter_actor_box_get_width (&content_box) - - logical.width; - box.y1 = clutter_actor_box_get_y (&content_box) - + clutter_actor_box_get_height (&content_box) - - logical.height; - box.x2 = box.x1 + logical.width; - box.y2 = box.y1 + logical.height; - clutter_paint_node_add_rectangle (node, &box); - - /* bottom-left */ - box.x1 = clutter_actor_box_get_x (&content_box); - box.y1 = clutter_actor_box_get_y (&content_box) - + clutter_actor_box_get_height (&content_box) - - logical.height; - box.x2 = box.x1 + logical.width; - box.y2 = box.y1 + logical.height; - clutter_paint_node_add_rectangle (node, &box); - - /* center */ - box.x1 = clutter_actor_box_get_x (&content_box) - + (clutter_actor_box_get_width (&content_box) - logical.width) / 2.0; - box.y1 = clutter_actor_box_get_y (&content_box) - + (clutter_actor_box_get_height (&content_box) - logical.height) / 2.0; - box.x2 = box.x1 + logical.width; - box.y2 = box.y1 + logical.height; - clutter_paint_node_add_rectangle (node, &box); - - clutter_paint_node_add_child (root, node); - clutter_paint_node_unref (node); - - g_object_unref (layout); -} - -static void -clutter_content_iface_init (ClutterContentInterface *iface) -{ - iface->paint_content = color_content_paint_content; -} - -static void -color_content_class_init (ColorContentClass *klass) -{ -} - -static void -color_content_init (ColorContent *self) -{ -} - -static ClutterContent * -color_content_new (double red, - double green, - double blue, - double alpha, - float padding) -{ - ColorContent *self = g_object_new (color_content_get_type (), NULL); - - self->red = red; - self->green = green; - self->blue = blue; - self->alpha = alpha; - self->padding = padding; - - return (ClutterContent *) self; -} - -G_MODULE_EXPORT int -test_content_main (int argc, char *argv[]) -{ - ClutterActor *stage, *grid; - ClutterContent *content; - int i, n_rects; - - clutter_test_init (&argc, &argv); - - stage = clutter_test_get_stage (); - clutter_actor_set_name (stage, "Stage"); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Content"); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - clutter_actor_show (stage); - - grid = clutter_actor_new (); - clutter_actor_set_name (grid, "Grid"); - clutter_actor_set_margin_top (grid, 12); - clutter_actor_set_margin_right (grid, 12); - clutter_actor_set_margin_bottom (grid, 12); - clutter_actor_set_margin_left (grid, 12); - clutter_actor_set_layout_manager (grid, clutter_flow_layout_new (CLUTTER_FLOW_HORIZONTAL)); - clutter_actor_add_constraint (grid, clutter_bind_constraint_new (stage, CLUTTER_BIND_SIZE, 0.0)); - clutter_actor_add_child (stage, grid); - - content = color_content_new (g_random_double_range (0.0, 1.0), - g_random_double_range (0.0, 1.0), - g_random_double_range (0.0, 1.0), - 1.0, - 2.0); - - n_rects = g_random_int_range (12, 24); - for (i = 0; i < n_rects; i++) - { - ClutterActor *box = clutter_actor_new (); - ClutterColor bg_color = { - g_random_int_range (0, 255), - g_random_int_range (0, 255), - g_random_int_range (0, 255), - 255 - }; - char *name, *color; - - color = clutter_color_to_string (&bg_color); - name = g_strconcat ("Box <", color, ">", NULL); - clutter_actor_set_name (box, name); - - g_free (name); - g_free (color); - - clutter_actor_set_background_color (box, &bg_color); - clutter_actor_set_content (box, content); - clutter_actor_set_size (box, 64, 64); - - clutter_actor_add_child (grid, box); - } - - clutter_test_main (); - - g_object_unref (content); - - return EXIT_SUCCESS; -} - -G_MODULE_EXPORT const char * -test_content_describe (void) -{ - return "A simple test for ClutterContent"; -} diff --git a/src/tests/clutter/interactive/test-devices.c b/src/tests/clutter/interactive/test-devices.c deleted file mode 100644 index 7e2b11eb3..000000000 --- a/src/tests/clutter/interactive/test-devices.c +++ /dev/null @@ -1,234 +0,0 @@ -#include -#include -#include - -#include "test-utils.h" -#include "tests/clutter-test-utils.h" - -typedef struct { - ClutterActor *stage; - - GHashTable *devices; -} TestDevicesApp; - -int -test_devices_main (int argc, char **argv); - -static const gchar * -device_type_name (ClutterInputDevice *device) -{ - ClutterInputDeviceType d_type; - - d_type = clutter_input_device_get_device_type (device); - switch (d_type) - { - case CLUTTER_POINTER_DEVICE: - return "Pointer"; - - case CLUTTER_KEYBOARD_DEVICE: - return "Keyboard"; - - case CLUTTER_EXTENSION_DEVICE: - return "Extension"; - - case CLUTTER_PEN_DEVICE: - return "Pen"; - - case CLUTTER_ERASER_DEVICE: - return "Eraser"; - - case CLUTTER_CURSOR_DEVICE: - return "Cursor"; - - default: - return "Unknown"; - } -} - -static gboolean -stage_button_event_cb (ClutterActor *actor, - ClutterEvent *event, - TestDevicesApp *app) -{ - ClutterInputDevice *device; - ClutterInputDevice *source_device; - ClutterActor *hand = NULL; - - device = clutter_event_get_device (event); - source_device = clutter_event_get_source_device (event); - - hand = g_hash_table_lookup (app->devices, device); - - g_print ("Device: '%s' (type: %s, source: '%s')\n", - clutter_input_device_get_device_name (device), - device_type_name (device), - source_device != device - ? clutter_input_device_get_device_name (source_device) - : ""); - - if (hand != NULL) - { - gfloat event_x, event_y; - - clutter_event_get_coords (event, &event_x, &event_y); - clutter_actor_set_position (hand, event_x, event_y); - } - - return FALSE; -} - -static gboolean -stage_motion_event_cb (ClutterActor *actor, - ClutterEvent *event, - TestDevicesApp *app) -{ - ClutterInputDevice *device; - ClutterActor *hand = NULL; - - device = clutter_event_get_device (event); - - hand = g_hash_table_lookup (app->devices, device); - if (hand != NULL) - { - gfloat event_x, event_y; - - clutter_event_get_coords (event, &event_x, &event_y); - clutter_actor_set_position (hand, event_x, event_y); - - return TRUE; - } - - return FALSE; -} - -static void -seat_device_added_cb (ClutterSeat *seat, - ClutterInputDevice *device, - TestDevicesApp *app) -{ - ClutterInputDeviceType device_type; - ClutterActor *hand = NULL; - - g_print ("got a %s device '%s'\n", - device_type_name (device), - clutter_input_device_get_device_name (device)); - - device_type = clutter_input_device_get_device_type (device); - if (device_type == CLUTTER_POINTER_DEVICE || - device_type == CLUTTER_PEN_DEVICE || - device_type == CLUTTER_POINTER_DEVICE) - { - g_print ("*** enabling device '%s' ***\n", - clutter_input_device_get_device_name (device)); - - hand = clutter_test_utils_create_texture_from_file (TESTS_DATADIR - G_DIR_SEPARATOR_S - "redhand.png", - NULL); - g_hash_table_insert (app->devices, device, hand); - - clutter_container_add_actor (CLUTTER_CONTAINER (app->stage), hand); - } -} - -static void -seat_device_removed_cb (ClutterSeat *seat, - ClutterInputDevice *device, - TestDevicesApp *app) -{ - ClutterInputDeviceType device_type; - ClutterActor *hand = NULL; - - g_print ("removed a %s device '%s'\n", - device_type_name (device), - clutter_input_device_get_device_name (device)); - - device_type = clutter_input_device_get_device_type (device); - if (device_type == CLUTTER_POINTER_DEVICE || - device_type == CLUTTER_PEN_DEVICE || - device_type == CLUTTER_POINTER_DEVICE) - { - hand = g_hash_table_lookup (app->devices, device); - if (hand != NULL) - clutter_container_add_actor (CLUTTER_CONTAINER (app->stage), hand); - - g_hash_table_remove (app->devices, device); - } -} - -G_MODULE_EXPORT int -test_devices_main (int argc, char **argv) -{ - ClutterActor *stage; - TestDevicesApp *app; - ClutterSeat *seat; - GList *stage_devices, *l; - - clutter_test_init (&argc, &argv); - - app = g_new0 (TestDevicesApp, 1); - app->devices = g_hash_table_new (g_direct_hash, g_direct_equal) ; - - stage = clutter_test_get_stage (); - clutter_actor_set_background_color (stage, CLUTTER_COLOR_LightSkyBlue); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Devices"); - g_signal_connect (stage, - "destroy", G_CALLBACK (clutter_test_quit), - NULL); - g_signal_connect (stage, - "motion-event", G_CALLBACK (stage_motion_event_cb), - app); - g_signal_connect (stage, - "button-press-event", G_CALLBACK (stage_button_event_cb), - app); - app->stage = stage; - - clutter_actor_show (stage); - - seat = clutter_backend_get_default_seat (clutter_get_default_backend ()); - g_signal_connect (seat, - "device-added", G_CALLBACK (seat_device_added_cb), - app); - g_signal_connect (seat, - "device-removed", G_CALLBACK (seat_device_removed_cb), - app); - - stage_devices = clutter_seat_list_devices (seat); - - if (stage_devices == NULL) - g_error ("No input devices found."); - - for (l = stage_devices; l != NULL; l = l->next) - { - ClutterInputDevice *device = l->data; - ClutterInputDeviceType device_type; - ClutterActor *hand = NULL; - - g_print ("got a %s device '%s'\n", - device_type_name (device), - clutter_input_device_get_device_name (device)); - - device_type = clutter_input_device_get_device_type (device); - if (device_type == CLUTTER_POINTER_DEVICE || - device_type == CLUTTER_PEN_DEVICE || - device_type == CLUTTER_POINTER_DEVICE) - { - g_print ("*** enabling device '%s' ***\n", - clutter_input_device_get_device_name (device)); - - hand = clutter_test_utils_create_texture_from_file (TESTS_DATADIR - G_DIR_SEPARATOR_S - "redhand.png", - NULL); - g_hash_table_insert (app->devices, device, hand); - - clutter_container_add_actor (CLUTTER_CONTAINER (stage), hand); - } - } - - g_list_free (stage_devices); - - clutter_test_main (); - - return EXIT_SUCCESS; -} diff --git a/src/tests/clutter/interactive/test-easing.c b/src/tests/clutter/interactive/test-easing.c deleted file mode 100644 index 9af10bee7..000000000 --- a/src/tests/clutter/interactive/test-easing.c +++ /dev/null @@ -1,252 +0,0 @@ -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -/* all the easing modes provided by Clutter */ -static const struct { - const gchar *name; - ClutterAnimationMode mode; -} easing_modes[] = { - { "linear", CLUTTER_LINEAR }, - { "easeInQuad", CLUTTER_EASE_IN_QUAD }, - { "easeOutQuad", CLUTTER_EASE_OUT_QUAD }, - { "easeInOutQuad", CLUTTER_EASE_IN_OUT_QUAD }, - { "easeInCubic", CLUTTER_EASE_IN_CUBIC }, - { "easeOutCubic", CLUTTER_EASE_OUT_CUBIC }, - { "easeInOutCubic", CLUTTER_EASE_IN_OUT_CUBIC }, - { "easeInQuart", CLUTTER_EASE_IN_QUART }, - { "easeOutQuart", CLUTTER_EASE_OUT_QUART }, - { "easeInOutQuart", CLUTTER_EASE_IN_OUT_QUART }, - { "easeInQuint", CLUTTER_EASE_IN_QUINT }, - { "easeOutQuint", CLUTTER_EASE_OUT_QUINT }, - { "easeInOutQuint", CLUTTER_EASE_IN_OUT_QUINT }, - { "easeInSine", CLUTTER_EASE_IN_SINE }, - { "easeOutSine", CLUTTER_EASE_OUT_SINE }, - { "easeInOutSine", CLUTTER_EASE_IN_OUT_SINE }, - { "easeInExpo", CLUTTER_EASE_IN_EXPO }, - { "easeOutExpo", CLUTTER_EASE_OUT_EXPO }, - { "easeInOutExpo", CLUTTER_EASE_IN_OUT_EXPO }, - { "easeInCirc", CLUTTER_EASE_IN_CIRC }, - { "easeOutCirc", CLUTTER_EASE_OUT_CIRC }, - { "easeInOutCirc", CLUTTER_EASE_IN_OUT_CIRC }, - { "easeInElastic", CLUTTER_EASE_IN_ELASTIC }, - { "easeOutElastic", CLUTTER_EASE_OUT_ELASTIC }, - { "easeInOutElastic", CLUTTER_EASE_IN_OUT_ELASTIC }, - { "easeInBack", CLUTTER_EASE_IN_BACK }, - { "easeOutBack", CLUTTER_EASE_OUT_BACK }, - { "easeInOutBack", CLUTTER_EASE_IN_OUT_BACK }, - { "easeInBounce", CLUTTER_EASE_IN_BOUNCE }, - { "easeOutBounce", CLUTTER_EASE_OUT_BOUNCE }, - { "easeInOutBounce", CLUTTER_EASE_IN_OUT_BOUNCE }, -}; - -#define HELP_TEXT "Easing mode: %s (%d of %d)\n" \ - "Left click to tween\n" \ - "Right click to change the easing mode" - -static const gint n_easing_modes = G_N_ELEMENTS (easing_modes); -static gint current_mode = 0; - -#define DURATION 1 - -static ClutterActor *main_stage = NULL; -static ClutterActor *easing_mode_label = NULL; - -int -test_easing_main (int argc, char *argv[]); - -const char * -test_easing_describe (void); - -/* recenter_bouncer: - * - * repositions (through an animation) the bouncer at the center of the stage - */ -static void -recenter_bouncer (ClutterActor *rectangle) -{ - gfloat base_x, base_y; - gint cur_mode; - - - cur_mode = easing_modes[current_mode].mode; - base_x = clutter_actor_get_width (main_stage) / 2; - base_y = clutter_actor_get_height (main_stage) / 2; - - clutter_actor_set_easing_duration (rectangle, 250); - clutter_actor_set_easing_mode (rectangle, cur_mode); - clutter_actor_set_position (rectangle, base_x, base_y); - - g_signal_connect_after (rectangle, "transition-completed", - G_CALLBACK (clutter_actor_restore_easing_state), - NULL); -} - -static gboolean -on_button_press (ClutterActor *actor, - ClutterButtonEvent *event, - ClutterActor *rectangle) -{ - if (event->button == CLUTTER_BUTTON_SECONDARY) - { - gchar *text; - - /* cycle through the various easing modes */ - current_mode = (current_mode + 1 < n_easing_modes) - ? current_mode + 1 - : 0; - - /* update the text of the label */ - text = g_strdup_printf (HELP_TEXT, - easing_modes[current_mode].name, - current_mode + 1, - n_easing_modes); - - clutter_text_set_text (CLUTTER_TEXT (easing_mode_label), text); - g_free (text); - } - else if (event->button == CLUTTER_BUTTON_PRIMARY) - { - ClutterAnimationMode cur_mode; - - cur_mode = easing_modes[current_mode].mode; - - clutter_actor_save_easing_state (rectangle); - clutter_actor_set_easing_duration (rectangle, DURATION * 1000); - clutter_actor_set_easing_mode (rectangle, cur_mode); - clutter_actor_set_position (rectangle, event->x, event->y); - - /* if we were asked to, recenter the bouncer at the end of the - * animation. we keep track of the animation to avoid connecting - * the signal handler to the same Animation twice. - */ - g_signal_connect_after (rectangle, "transition-completed", - G_CALLBACK (recenter_bouncer), - rectangle); - } - - return TRUE; -} - -static gboolean -draw_bouncer (ClutterCanvas *canvas, - cairo_t *cr, - int width, - int height) -{ - const ClutterColor *bouncer_color; - cairo_pattern_t *pattern; - float radius; - - radius = MAX (width, height); - - cairo_save (cr); - cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); - cairo_paint (cr); - cairo_restore (cr); - - cairo_arc (cr, radius / 2, radius / 2, radius / 2, 0.0, 2.0 * G_PI); - - bouncer_color = CLUTTER_COLOR_DarkScarletRed; - - pattern = cairo_pattern_create_radial (radius / 2, radius / 2, 0, - radius, radius, radius); - cairo_pattern_add_color_stop_rgba (pattern, - 0, - bouncer_color->red / 255.0, - bouncer_color->green / 255.0, - bouncer_color->blue / 255.0, - bouncer_color->alpha / 255.0); - cairo_pattern_add_color_stop_rgba (pattern, - 0.85, - bouncer_color->red / 255.0, - bouncer_color->green / 255.0, - bouncer_color->blue / 255.0, - 0.25); - - cairo_set_source (cr, pattern); - cairo_fill_preserve (cr); - - cairo_pattern_destroy (pattern); - - return TRUE; -} - -static ClutterActor * -make_bouncer (gfloat width, - gfloat height) -{ - ClutterContent *canvas; - ClutterActor *retval; - - canvas = clutter_canvas_new (); - clutter_canvas_set_size (CLUTTER_CANVAS (canvas), width, height); - g_signal_connect (canvas, "draw", G_CALLBACK (draw_bouncer), NULL); - - retval = g_object_new (CLUTTER_TYPE_ACTOR, - "content", canvas, - NULL); - clutter_actor_set_name (retval, "bouncer"); - clutter_actor_set_size (retval, width, height); - clutter_actor_set_translation (retval, -width / 2.f, -height / 2.f, 0.f); - clutter_actor_set_reactive (retval, TRUE); - - clutter_content_invalidate (canvas); - - return retval; -} - -G_MODULE_EXPORT int -test_easing_main (int argc, char *argv[]) -{ - ClutterActor *stage, *rect, *label; - gchar *text; - gfloat stage_width, stage_height; - - clutter_test_init (&argc, &argv); - - stage = clutter_test_get_stage (); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Easing Modes"); - clutter_actor_set_background_color (stage, CLUTTER_COLOR_LightSkyBlue); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - main_stage = stage; - - clutter_actor_get_size (stage, &stage_width, &stage_height); - - /* create the actor that we want to tween */ - rect = make_bouncer (50, 50); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); - clutter_actor_set_position (rect, stage_width / 2, stage_height / 2); - - text = g_strdup_printf (HELP_TEXT, - easing_modes[current_mode].name, - current_mode + 1, - n_easing_modes); - - label = clutter_text_new (); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), label); - clutter_text_set_text (CLUTTER_TEXT (label), text); - clutter_actor_add_constraint (label, clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0.95)); - clutter_actor_add_constraint (label, clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.95)); - easing_mode_label = label; - - g_free (text); - - g_signal_connect (stage, - "button-press-event", G_CALLBACK (on_button_press), - rect); - - clutter_actor_show (stage); - - clutter_test_main (); - - return EXIT_SUCCESS; -} - -G_MODULE_EXPORT const char * -test_easing_describe (void) -{ - return "Visualize all easing modes provided by Clutter"; -} diff --git a/src/tests/clutter/interactive/test-events.c b/src/tests/clutter/interactive/test-events.c deleted file mode 100644 index e8408b5e2..000000000 --- a/src/tests/clutter/interactive/test-events.c +++ /dev/null @@ -1,477 +0,0 @@ -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -gboolean IsMotion = TRUE; - -int -test_events_main (int argc, char *argv[]); - -const char * -test_events_describe (void); - -static const gchar * -get_event_type_name (const ClutterEvent *event) -{ - switch (event->type) - { - case CLUTTER_BUTTON_PRESS: - return "BUTTON PRESS"; - - case CLUTTER_BUTTON_RELEASE: - return "BUTTON_RELEASE"; - - case CLUTTER_KEY_PRESS: - return "KEY PRESS"; - - case CLUTTER_KEY_RELEASE: - return "KEY RELEASE"; - - case CLUTTER_ENTER: - return "ENTER"; - - case CLUTTER_LEAVE: - return "LEAVE"; - - case CLUTTER_MOTION: - return "MOTION"; - - case CLUTTER_TOUCH_BEGIN: - return "TOUCH BEGIN"; - - case CLUTTER_TOUCH_UPDATE: - return "TOUCH UPDATE"; - - case CLUTTER_TOUCH_END: - return "TOUCH END"; - - case CLUTTER_TOUCH_CANCEL: - return "TOUCH CANCEL"; - - default: - return "EVENT"; - } -} - -static gchar * -get_event_state_string (const ClutterEvent *event) -{ - const char *mods[18]; - int i = 0; - ClutterModifierType state = clutter_event_get_state (event); - - if (state & CLUTTER_SHIFT_MASK) - mods[i++] = "shift"; - if (state & CLUTTER_LOCK_MASK) - mods[i++] = "lock"; - if (state & CLUTTER_CONTROL_MASK) - mods[i++] = "ctrl"; - if (state & CLUTTER_MOD1_MASK) - mods[i++] = "mod1"; - if (state & CLUTTER_MOD2_MASK) - mods[i++] = "mod2"; - if (state & CLUTTER_MOD3_MASK) - mods[i++] = "mod3"; - if (state & CLUTTER_MOD4_MASK) - mods[i++] = "mod4"; - if (state & CLUTTER_MOD5_MASK) - mods[i++] = "mod5"; - if (state & CLUTTER_BUTTON1_MASK) - mods[i++] = "btn1"; - if (state & CLUTTER_BUTTON2_MASK) - mods[i++] = "btn2"; - if (state & CLUTTER_BUTTON3_MASK) - mods[i++] = "btn3"; - if (state & CLUTTER_BUTTON4_MASK) - mods[i++] = "btn4"; - if (state & CLUTTER_BUTTON5_MASK) - mods[i++] = "btn5"; - if (state & CLUTTER_SUPER_MASK) - mods[i++] = "super"; - if (state & CLUTTER_HYPER_MASK) - mods[i++] = "hyper"; - if (state & CLUTTER_META_MASK) - mods[i++] = "meta"; - if (state & CLUTTER_RELEASE_MASK) - mods[i++] = "release"; - - if (i == 0) - mods[i++] = "-"; - - mods[i] = NULL; - return g_strjoinv (",", (char **) mods); -} - -static gboolean -red_button_cb (ClutterActor *actor, - ClutterEvent *event, - gpointer data) -{ - ClutterActor *stage; - - if (IsMotion) - IsMotion = FALSE; - else - IsMotion = TRUE; - - stage = clutter_actor_get_stage (actor); - clutter_stage_set_motion_events_enabled (CLUTTER_STAGE (stage), - IsMotion); - - g_print ("*** Per actor motion events %s ***\n", - IsMotion ? "enabled" : "disabled"); - - return FALSE; -} - -static gboolean -capture_cb (ClutterActor *actor, - ClutterEvent *event, - gpointer data) -{ - g_print ("* captured event '%s' for type '%s' *\n", - get_event_type_name (event), - G_OBJECT_TYPE_NAME (actor)); - - return FALSE; -} - -static void -key_focus_in_cb (ClutterActor *actor, - gpointer data) -{ - ClutterActor *focus_box = CLUTTER_ACTOR (data); - - if (CLUTTER_IS_STAGE (actor)) - clutter_actor_hide (focus_box); - else - { - clutter_actor_set_position (focus_box, - clutter_actor_get_x (actor) - 5, - clutter_actor_get_y (actor) - 5); - - clutter_actor_set_size (focus_box, - clutter_actor_get_width (actor) + 10, - clutter_actor_get_height (actor) + 10); - clutter_actor_show (focus_box); - } -} - -static void -fill_keybuf (char *keybuf, ClutterKeyEvent *event) -{ - char utf8[6]; - int len; - - /* printable character, if any (ß, ∑) */ - len = g_unichar_to_utf8 (event->unicode_value, utf8); - utf8[len] = '\0'; - sprintf (keybuf, "'%s' ", utf8); - - /* key combination (s, S, Delete) */ - len = g_unichar_to_utf8 (clutter_keysym_to_unicode (event->keyval), utf8); - utf8[len] = '\0'; - - if (event->modifier_state & CLUTTER_SHIFT_MASK) - strcat (keybuf, ""); - - if (event->modifier_state & CLUTTER_LOCK_MASK) - strcat (keybuf, ""); - - if (event->modifier_state & CLUTTER_CONTROL_MASK) - strcat (keybuf, ""); - - if (event->modifier_state & CLUTTER_MOD1_MASK) - strcat (keybuf, ""); - - if (event->modifier_state & CLUTTER_MOD2_MASK) - strcat (keybuf, ""); - - if (event->modifier_state & CLUTTER_MOD3_MASK) - strcat (keybuf, ""); - - if (event->modifier_state & CLUTTER_MOD4_MASK) - strcat (keybuf, ""); - - if (event->modifier_state & CLUTTER_MOD5_MASK) - strcat (keybuf, ""); - - strcat (keybuf, utf8); -} - -static gboolean -input_cb (ClutterActor *actor, - ClutterEvent *event, - gpointer data) -{ - ClutterActor *stage = clutter_actor_get_stage (actor); - ClutterActor *source_actor = clutter_event_get_source (event); - graphene_point_t position; - gchar *state; - gchar keybuf[128]; - ClutterInputDevice *device, *source; - const gchar *device_name, *source_name = NULL; - - device = clutter_event_get_device (event); - device_name = clutter_input_device_get_device_name (device); - - source = clutter_event_get_source_device (event); - if (source) - source_name = clutter_input_device_get_device_name (source); - else - source_name = "None"; - - state = get_event_state_string (event); - - switch (event->type) - { - case CLUTTER_KEY_PRESS: - fill_keybuf (keybuf, &event->key); - printf ("[%s] KEY PRESS %s", - clutter_actor_get_name (source_actor), - keybuf); - break; - case CLUTTER_KEY_RELEASE: - fill_keybuf (keybuf, &event->key); - printf ("[%s] KEY RELEASE %s", - clutter_actor_get_name (source_actor), - keybuf); - break; - case CLUTTER_MOTION: - clutter_event_get_position (event, &position); - g_print ("[%s] MOTION (coords:%.02f,%.02f device:%s/%s state:%s)", - clutter_actor_get_name (source_actor), position.x, position.y, - device_name, source_name, state); - break; - case CLUTTER_ENTER: - g_print ("[%s] ENTER (from:%s device:%s/%s state:%s)", - clutter_actor_get_name (source_actor), - clutter_event_get_related (event) != NULL - ? clutter_actor_get_name (clutter_event_get_related (event)) - : "", - device_name, source_name, state); - break; - case CLUTTER_LEAVE: - g_print ("[%s] LEAVE (to:%s device:%s/%s state:%s)", - clutter_actor_get_name (source_actor), - clutter_event_get_related (event) != NULL - ? clutter_actor_get_name (clutter_event_get_related (event)) - : "", - device_name, source_name, state); - break; - case CLUTTER_BUTTON_PRESS: - clutter_event_get_position (event, &position); - g_print ("[%s] BUTTON PRESS (button:%i, click count:%i coords:%.02f,%.02f device:%s/%s, state:%s)", - clutter_actor_get_name (source_actor), - clutter_event_get_button (event), - clutter_event_get_click_count (event), - position.x, position.y, - device_name, source_name, state); - break; - case CLUTTER_BUTTON_RELEASE: - clutter_event_get_position (event, &position); - g_print ("[%s] BUTTON RELEASE (button:%i, click count:%i coords:%.02f,%.02f device:%s/%s state:%s)", - clutter_actor_get_name (source_actor), - clutter_event_get_button (event), - clutter_event_get_click_count (event), - position.x, position.y, - device_name, source_name, state); - - if (source_actor == stage) - clutter_stage_set_key_focus (CLUTTER_STAGE (stage), NULL); - else if (source_actor == actor && - clutter_actor_get_parent (actor) == stage) - clutter_stage_set_key_focus (CLUTTER_STAGE (stage), actor); - break; - case CLUTTER_TOUCH_BEGIN: - clutter_event_get_position (event, &position); - g_print ("[%s] TOUCH BEGIN (seq:%p coords:%.02f,%.02f device:%s/%s state:%s)", - clutter_actor_get_name (source_actor), - clutter_event_get_event_sequence (event), - position.x, position.y, - device_name, source_name, state); - break; - case CLUTTER_TOUCH_UPDATE: - clutter_event_get_position (event, &position); - g_print ("[%s] TOUCH UPDATE (seq:%p coords:%.02f,%.02f device:%s/%s state:%s)", - clutter_actor_get_name (source_actor), - clutter_event_get_event_sequence (event), - position.x, position.y, - device_name, source_name, state); - break; - case CLUTTER_TOUCH_END: - clutter_event_get_position (event, &position); - g_print ("[%s] TOUCH END (seq:%p coords:%.02f,%.02f device:%s/%s state:%s)", - clutter_actor_get_name (source_actor), - clutter_event_get_event_sequence (event), - position.x, position.y, - device_name, source_name, state); - break; - case CLUTTER_TOUCH_CANCEL: - clutter_event_get_position (event, &position); - g_print ("[%s] TOUCH CANCEL (seq:%p coords:%.02f,%.02f device:%s/%s state:%s)", - clutter_actor_get_name (source_actor), - clutter_event_get_event_sequence (event), - position.x, position.y, - device_name, source_name, state); - break; - case CLUTTER_SCROLL: - { - ClutterScrollDirection dir = clutter_event_get_scroll_direction (event); - - if (dir == CLUTTER_SCROLL_SMOOTH) - { - gdouble dx, dy; - clutter_event_get_scroll_delta (event, &dx, &dy); - g_print ("[%s] BUTTON SCROLL (direction:smooth %.02f,%.02f state:%s)", - clutter_actor_get_name (source_actor), dx, dy, state); - } - else - g_print ("[%s] BUTTON SCROLL (direction:%s state:%s)", - clutter_actor_get_name (source_actor), - dir == CLUTTER_SCROLL_UP ? "up" : - dir == CLUTTER_SCROLL_DOWN ? "down" : - dir == CLUTTER_SCROLL_LEFT ? "left" : - dir == CLUTTER_SCROLL_RIGHT ? "right" : "?", - state); - } - break; - case CLUTTER_TOUCHPAD_PINCH: - g_print ("[%s] TOUCHPAD PINCH", clutter_actor_get_name (source_actor)); - break; - case CLUTTER_TOUCHPAD_SWIPE: - g_print ("[%s] TOUCHPAD SWIPE", clutter_actor_get_name (source_actor)); - break; - case CLUTTER_PROXIMITY_IN: - g_print ("[%s] PROXIMITY IN", clutter_actor_get_name (source_actor)); - break; - case CLUTTER_PROXIMITY_OUT: - g_print ("[%s] PROXIMITY OUT", clutter_actor_get_name (source_actor)); - break; - case CLUTTER_PAD_BUTTON_PRESS: - g_print ("[%s] PAD BUTTON PRESS", clutter_actor_get_name (source_actor)); - break; - case CLUTTER_PAD_BUTTON_RELEASE: - g_print ("[%s] PAD BUTTON RELEASE", clutter_actor_get_name (source_actor)); - break; - case CLUTTER_PAD_STRIP: - g_print ("[%s] PAD STRIP", clutter_actor_get_name (source_actor)); - break; - case CLUTTER_PAD_RING: - g_print ("[%s] PAD RING", clutter_actor_get_name (source_actor)); - break; - case CLUTTER_NOTHING: - default: - return FALSE; - } - - g_free (state); - - if (source_actor == actor) - g_print (" *source*"); - - g_print ("\n"); - - return FALSE; -} - -G_MODULE_EXPORT int -test_events_main (int argc, char *argv[]) -{ - ClutterActor *stage, *actor, *focus_box, *group; - - clutter_test_init (&argc, &argv); - - stage = clutter_test_get_stage (); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Events"); - clutter_actor_set_name (stage, "Stage"); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - g_signal_connect (stage, "event", G_CALLBACK (input_cb), (char *) "stage"); - - focus_box = clutter_actor_new (); - clutter_actor_set_background_color (focus_box, CLUTTER_COLOR_Black); - clutter_actor_set_name (focus_box, "Focus Box"); - clutter_container_add (CLUTTER_CONTAINER(stage), focus_box, NULL); - - actor = clutter_actor_new (); - clutter_actor_set_background_color (actor, CLUTTER_COLOR_Red); - clutter_actor_set_name (actor, "Red Box"); - clutter_actor_set_size (actor, 100, 100); - clutter_actor_set_position (actor, 100, 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 *) "red box"); - g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb), - focus_box); - /* Toggle motion - enter/leave capture */ - g_signal_connect (actor, "button-press-event", - G_CALLBACK (red_button_cb), NULL); - - clutter_stage_set_key_focus (CLUTTER_STAGE (stage), actor); - - actor = clutter_actor_new (); - clutter_actor_set_background_color (actor, CLUTTER_COLOR_Green); - clutter_actor_set_name (actor, "Green Box"); - clutter_actor_set_size (actor, 100, 100); - clutter_actor_set_position (actor, 250, 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 *) "green box"); - g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb), - focus_box); - g_signal_connect (actor, "captured-event", G_CALLBACK (capture_cb), NULL); - - /* non reactive */ - actor = clutter_actor_new (); - clutter_actor_set_background_color (actor, CLUTTER_COLOR_Black); - clutter_actor_set_name (actor, "Black Box"); - clutter_actor_set_size (actor, 400, 50); - clutter_actor_set_position (actor, 100, 250); - 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); - g_signal_connect (stage, "key-focus-in", G_CALLBACK (key_focus_in_cb), - focus_box); - - /* non reactive group, with reactive child */ - actor = clutter_actor_new (); - clutter_actor_set_background_color (actor, CLUTTER_COLOR_Yellow); - clutter_actor_set_name (actor, "Yellow Box"); - clutter_actor_set_size (actor, 100, 100); - clutter_actor_set_reactive (actor, TRUE); - - g_signal_connect (actor, "event", G_CALLBACK (input_cb), (char *) "yellow box"); - - /* note group not reactive */ - group = clutter_actor_new (); - clutter_container_add (CLUTTER_CONTAINER (group), actor, NULL); - clutter_container_add (CLUTTER_CONTAINER (stage), group, NULL); - clutter_actor_set_position (group, 100, 350); - - /* border actor */ - actor = clutter_actor_new (); - clutter_actor_set_background_color (actor, CLUTTER_COLOR_Magenta); - clutter_actor_set_name (actor, "Border Box"); - clutter_actor_set_size (actor, 100, 100); - clutter_actor_set_position (actor, - (clutter_actor_get_width (stage) - 100) / 2, - clutter_actor_get_height (stage) - 100); - clutter_actor_set_reactive (actor, TRUE); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), actor); - g_signal_connect (actor, "event", G_CALLBACK (input_cb), NULL); - - clutter_actor_show (CLUTTER_ACTOR (stage)); - - clutter_test_main (); - - return 0; -} - -G_MODULE_EXPORT const char * -test_events_describe (void) -{ - return "Event handling and propagation."; -} diff --git a/src/tests/clutter/interactive/test-grab.c b/src/tests/clutter/interactive/test-grab.c deleted file mode 100644 index 1de60985b..000000000 --- a/src/tests/clutter/interactive/test-grab.c +++ /dev/null @@ -1,283 +0,0 @@ -#include -#include - -#include "tests/clutter-test-utils.h" - -int -test_grab_main (int argc, char *argv[]); - -const char * -test_grab_describe (void); - -static gboolean -debug_event_cb (ClutterActor *actor, - ClutterEvent *event, - gpointer data) -{ - gchar keybuf[9], *source = (gchar*)data; - int len = 0; - - switch (event->type) - { - case CLUTTER_KEY_PRESS: - len = g_unichar_to_utf8 (clutter_keysym_to_unicode (event->key.keyval), - keybuf); - keybuf[len] = '\0'; - printf ("[%s] KEY PRESS '%s'", source, keybuf); - break; - case CLUTTER_KEY_RELEASE: - len = g_unichar_to_utf8 (clutter_keysym_to_unicode (event->key.keyval), - keybuf); - keybuf[len] = '\0'; - printf ("[%s] KEY RELEASE '%s'", source, keybuf); - break; - case CLUTTER_MOTION: - printf("[%s] MOTION", source); - break; - case CLUTTER_ENTER: - printf("[%s] ENTER", source); - break; - case CLUTTER_LEAVE: - printf("[%s] LEAVE", source); - break; - case CLUTTER_BUTTON_PRESS: - printf("[%s] BUTTON PRESS (click count:%i)", - source, event->button.click_count); - break; - case CLUTTER_BUTTON_RELEASE: - printf("[%s] BUTTON RELEASE", source); - break; - case CLUTTER_SCROLL: - printf("[%s] BUTTON SCROLL", source); - break; - case CLUTTER_TOUCH_BEGIN: - g_print ("[%s] TOUCH BEGIN", source); - break; - case CLUTTER_TOUCH_UPDATE: - g_print ("[%s] TOUCH UPDATE", source); - break; - case CLUTTER_TOUCH_END: - g_print ("[%s] TOUCH END", source); - break; - case CLUTTER_TOUCH_CANCEL: - g_print ("[%s] TOUCH CANCEL", source); - break; - case CLUTTER_TOUCHPAD_PINCH: - g_print ("[%s] TOUCHPAD PINCH", source); - break; - case CLUTTER_TOUCHPAD_SWIPE: - g_print ("[%s] TOUCHPAD SWIPE", source); - break; - case CLUTTER_PROXIMITY_IN: - g_print ("[%s] PROXIMITY IN", source); - break; - case CLUTTER_PROXIMITY_OUT: - g_print ("[%s] PROXIMITY OUT", source); - break; - case CLUTTER_PAD_BUTTON_PRESS: - g_print ("[%s] PAD BUTTON PRESS", source); - break; - case CLUTTER_PAD_BUTTON_RELEASE: - g_print ("[%s] PAD BUTTON RELEASE", source); - break; - case CLUTTER_PAD_STRIP: - g_print ("[%s] PAD STRIP", source); - break; - case CLUTTER_PAD_RING: - g_print ("[%s] PAD RING", source); - break; - case CLUTTER_NOTHING: - default: - return FALSE; - } - - if (clutter_event_get_source (event) == actor) - printf(" *source*"); - - printf("\n"); - - return FALSE; -} - -static gboolean -grab_pointer_cb (ClutterActor *actor, - ClutterEvent *event, - gpointer data) -{ - ClutterInputDevice *device = clutter_event_get_device (event); - - clutter_input_device_grab (device, actor); - return FALSE; -} - -static gboolean -red_release_cb (ClutterActor *actor, - ClutterEvent *event, - gpointer data) -{ - ClutterInputDevice *device = clutter_event_get_device (event); - - clutter_input_device_ungrab (device); - return FALSE; -} - -static gboolean -blue_release_cb (ClutterActor *actor, - ClutterEvent *event, - gpointer data) -{ - clutter_actor_destroy (actor); - return FALSE; -} - -static gboolean -green_press_cb (ClutterActor *actor, - ClutterEvent *event, - gpointer data) -{ - ClutterActor *stage; - gboolean enabled; - - stage = clutter_actor_get_stage (actor); - enabled = !clutter_stage_get_motion_events_enabled (CLUTTER_STAGE (stage)); - - clutter_stage_set_motion_events_enabled (CLUTTER_STAGE (stage), enabled); - - g_print ("per actor motion events are now %s\n", - enabled ? "enabled" : "disabled"); - - return FALSE; -} - -static gboolean -toggle_grab_pointer_cb (ClutterActor *actor, - ClutterEvent *event, - gpointer data) -{ - ClutterInputDevice *device = clutter_event_get_device (event); - - /* we only deal with the event if the source is ourself */ - if (event->button.source == actor) - { - if (clutter_input_device_get_grabbed_actor (device) != NULL) - clutter_input_device_ungrab (device); - else - clutter_input_device_grab (device, actor); - } - - return FALSE; -} - -static gboolean -cyan_press_cb (ClutterActor *actor, - ClutterEvent *event, - gpointer data) -{ - ClutterBackend *backend = clutter_get_default_backend (); - ClutterSeat *seat = clutter_backend_get_default_seat (backend); - ClutterInputDevice *device = clutter_seat_get_pointer (seat); - - if (clutter_input_device_get_grabbed_actor (device) != NULL) - clutter_input_device_ungrab (device); - else - clutter_input_device_grab (device, actor); - - return FALSE; -} - - - -G_MODULE_EXPORT int -test_grab_main (int argc, char *argv[]) -{ - ClutterActor *stage, *actor; - ClutterColor rcol = { 0xff, 0, 0, 0xff}, - bcol = { 0, 0, 0xff, 0xff }, - gcol = { 0, 0xff, 0, 0xff }, - ccol = { 0, 0xff, 0xff, 0xff }, - ycol = { 0xff, 0xff, 0, 0xff }; - - clutter_test_init (&argc, &argv); - - g_print ("Red box: acquire grab on press, releases it on next button release\n"); - g_print ("Blue box: acquire grab on press, destroys the blue box actor on release\n"); - g_print ("Yellow box: acquire grab on press, releases grab on next press on yellow box\n"); - g_print ("Green box: toggle per actor motion events.\n\n"); - g_print ("Cyan box: toggle grab (from cyan box) for keyboard events.\n\n"); - - stage = clutter_test_get_stage (); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Grabs"); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - g_signal_connect (stage, "event", - G_CALLBACK (debug_event_cb), (char *) "stage"); - - actor = clutter_actor_new (); - clutter_actor_set_background_color (actor, &rcol); - clutter_actor_set_size (actor, 100, 100); - clutter_actor_set_position (actor, 100, 100); - clutter_actor_set_reactive (actor, TRUE); - clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL); - g_signal_connect (actor, "event", G_CALLBACK (debug_event_cb), (char *) "red box"); - g_signal_connect (actor, "button-press-event", - G_CALLBACK (grab_pointer_cb), NULL); - g_signal_connect (actor, "button-release-event", - G_CALLBACK (red_release_cb), NULL); - - actor = clutter_actor_new (); - clutter_actor_set_background_color (actor, &ycol); - clutter_actor_set_size (actor, 100, 100); - clutter_actor_set_position (actor, 100, 300); - clutter_actor_set_reactive (actor, TRUE); - clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL); - g_signal_connect (actor, "event", G_CALLBACK (debug_event_cb), (char *) "yellow box"); - g_signal_connect (actor, "button-press-event", - G_CALLBACK (toggle_grab_pointer_cb), NULL); - - actor = clutter_actor_new (); - clutter_actor_set_background_color (actor, &bcol); - clutter_actor_set_size (actor, 100, 100); - clutter_actor_set_position (actor, 300, 100); - clutter_actor_set_reactive (actor, TRUE); - clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL); - g_signal_connect (actor, "event", - G_CALLBACK (debug_event_cb), (char *) "blue box"); - g_signal_connect (actor, "button-press-event", - G_CALLBACK (grab_pointer_cb), NULL); - g_signal_connect (actor, "button-release-event", - G_CALLBACK (blue_release_cb), NULL); - - actor = clutter_actor_new (); - clutter_actor_set_background_color (actor, &gcol); - clutter_actor_set_size (actor, 100, 100); - clutter_actor_set_position (actor, 300, 300); - clutter_actor_set_reactive (actor, TRUE); - clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL); - g_signal_connect (actor, "event", - G_CALLBACK (debug_event_cb), (char *) "green box"); - g_signal_connect (actor, "button-press-event", - G_CALLBACK (green_press_cb), NULL); - - - actor = clutter_actor_new (); - clutter_actor_set_background_color (actor, &ccol); - clutter_actor_set_size (actor, 100, 100); - clutter_actor_set_position (actor, 500, 100); - clutter_actor_set_reactive (actor, TRUE); - clutter_container_add (CLUTTER_CONTAINER (stage), actor, NULL); - g_signal_connect (actor, "event", - G_CALLBACK (debug_event_cb), (char *) "cyan box"); - g_signal_connect (actor, "button-press-event", - G_CALLBACK (cyan_press_cb), NULL); - - clutter_actor_show (CLUTTER_ACTOR (stage)); - - clutter_test_main (); - - return 0; -} - -G_MODULE_EXPORT const char * -test_grab_describe (void) -{ - return "Examples of using actor grabs"; -} diff --git a/src/tests/clutter/interactive/test-image.c b/src/tests/clutter/interactive/test-image.c deleted file mode 100644 index 11c07e64b..000000000 --- a/src/tests/clutter/interactive/test-image.c +++ /dev/null @@ -1,261 +0,0 @@ -#include -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -typedef struct _SolidContent { - GObject parent_instance; - - double red; - double green; - double blue; - double alpha; - - float padding; -} SolidContent; - -typedef struct _SolidContentClass { - GObjectClass parent_class; -} SolidContentClass; - -static void clutter_content_iface_init (ClutterContentInterface *iface); - -GType solid_content_get_type (void); - -const char * -test_image_describe (void); - -int -test_image_main (int argc, char *argv[]); - -G_DEFINE_TYPE_WITH_CODE (SolidContent, solid_content, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTENT, - clutter_content_iface_init)) - -static void -solid_content_paint_content (ClutterContent *content, - ClutterActor *actor, - ClutterPaintNode *root, - ClutterPaintContext *paint_context) -{ - SolidContent *self = (SolidContent *) content; - ClutterActorBox box, content_box; - ClutterColor color; - PangoLayout *layout; - PangoRectangle logical; - ClutterPaintNode *node; - -#if 0 - g_debug ("Painting content [%p] " - "{ r:%.2f, g:%.2f, b:%.2f, a:%.2f } " - "for actor [%p] (context: [%p])", - content, - self->red, - self->green, - self->blue, - self->alpha, - actor, context); -#endif - - clutter_actor_get_content_box (actor, &content_box); - - box = content_box; - box.x1 += self->padding; - box.y1 += self->padding; - box.x2 -= self->padding; - box.y2 -= self->padding; - - color.alpha = self->alpha * 255; - - color.red = self->red * 255; - color.green = self->green * 255; - color.blue = self->blue * 255; - - node = clutter_color_node_new (&color); - clutter_paint_node_add_rectangle (node, &box); - clutter_paint_node_add_child (root, node); - clutter_paint_node_unref (node); - - color.red = (1.0 - self->red) * 255; - color.green = (1.0 - self->green) * 255; - color.blue = (1.0 - self->blue) * 255; - - layout = clutter_actor_create_pango_layout (actor, "A"); - pango_layout_get_pixel_extents (layout, NULL, &logical); - - node = clutter_text_node_new (layout, &color); - - /* top-left */ - box.x1 = clutter_actor_box_get_x (&content_box); - box.y1 = clutter_actor_box_get_y (&content_box); - box.x2 = box.x1 + logical.width; - box.y2 = box.y1 + logical.height; - clutter_paint_node_add_rectangle (node, &box); - - /* top-right */ - box.x1 = clutter_actor_box_get_x (&content_box) - + clutter_actor_box_get_width (&content_box) - - logical.width; - box.y1 = clutter_actor_box_get_y (&content_box); - box.x2 = box.x1 + logical.width; - box.y2 = box.y1 + logical.height; - clutter_paint_node_add_rectangle (node, &box); - - /* bottom-right */ - box.x1 = clutter_actor_box_get_x (&content_box) - + clutter_actor_box_get_width (&content_box) - - logical.width; - box.y1 = clutter_actor_box_get_y (&content_box) - + clutter_actor_box_get_height (&content_box) - - logical.height; - box.x2 = box.x1 + logical.width; - box.y2 = box.y1 + logical.height; - clutter_paint_node_add_rectangle (node, &box); - - /* bottom-left */ - box.x1 = clutter_actor_box_get_x (&content_box); - box.y1 = clutter_actor_box_get_y (&content_box) - + clutter_actor_box_get_height (&content_box) - - logical.height; - box.x2 = box.x1 + logical.width; - box.y2 = box.y1 + logical.height; - clutter_paint_node_add_rectangle (node, &box); - - /* center */ - box.x1 = clutter_actor_box_get_x (&content_box) - + (clutter_actor_box_get_width (&content_box) - logical.width) / 2.0; - box.y1 = clutter_actor_box_get_y (&content_box) - + (clutter_actor_box_get_height (&content_box) - logical.height) / 2.0; - box.x2 = box.x1 + logical.width; - box.y2 = box.y1 + logical.height; - clutter_paint_node_add_rectangle (node, &box); - - clutter_paint_node_add_child (root, node); - clutter_paint_node_unref (node); - - g_object_unref (layout); -} - -static void -clutter_content_iface_init (ClutterContentInterface *iface) -{ - iface->paint_content = solid_content_paint_content; -} - -static void -solid_content_class_init (SolidContentClass *klass) -{ -} - -static void -solid_content_init (SolidContent *self) -{ -} - -static ClutterContent * -solid_content_new (double red, - double green, - double blue, - double alpha, - float padding) -{ - SolidContent *self = g_object_new (solid_content_get_type (), NULL); - - self->red = red; - self->green = green; - self->blue = blue; - self->alpha = alpha; - self->padding = padding; - - return (ClutterContent *) self; -} - -G_MODULE_EXPORT const char * -test_image_describe (void) -{ - return "A test with image content."; -} - -G_MODULE_EXPORT int -test_image_main (int argc, char *argv[]) -{ - ClutterActor *stage, *grid; - ClutterContent *color, *image; - GdkPixbuf *pixbuf; - int i, n_rects; - - clutter_test_init (&argc, &argv); - - stage = clutter_test_get_stage (); - clutter_actor_set_name (stage, "Stage"); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Content"); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - clutter_actor_show (stage); - - grid = clutter_actor_new (); - clutter_actor_set_name (grid, "Grid"); - clutter_actor_set_margin_top (grid, 12); - clutter_actor_set_margin_right (grid, 12); - clutter_actor_set_margin_bottom (grid, 12); - clutter_actor_set_margin_left (grid, 12); - clutter_actor_set_layout_manager (grid, clutter_flow_layout_new (CLUTTER_FLOW_HORIZONTAL)); - clutter_actor_add_constraint (grid, clutter_bind_constraint_new (stage, CLUTTER_BIND_SIZE, 0.0)); - clutter_actor_add_child (stage, grid); - - color = solid_content_new (g_random_double_range (0.0, 1.0), - g_random_double_range (0.0, 1.0), - g_random_double_range (0.0, 1.0), - 1.0, - 2.0); - - pixbuf = gdk_pixbuf_new_from_file (TESTS_DATADIR G_DIR_SEPARATOR_S "redhand.png", NULL); - image = clutter_image_new (); - clutter_image_set_data (CLUTTER_IMAGE (image), - gdk_pixbuf_get_pixels (pixbuf), - gdk_pixbuf_get_has_alpha (pixbuf) - ? COGL_PIXEL_FORMAT_RGBA_8888 - : COGL_PIXEL_FORMAT_RGB_888, - gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf), - gdk_pixbuf_get_rowstride (pixbuf), - NULL); - g_object_unref (pixbuf); - - n_rects = g_random_int_range (12, 24); - for (i = 0; i < n_rects; i++) - { - ClutterActor *box = clutter_actor_new (); - ClutterColor bg_color = { - g_random_int_range (0, 255), - g_random_int_range (0, 255), - g_random_int_range (0, 255), - 255 - }; - char *name, *str; - - str = clutter_color_to_string (&bg_color); - name = g_strconcat ("Box <", color, ">", NULL); - clutter_actor_set_name (box, name); - - g_free (name); - g_free (str); - - if ((i % 2) == 0) - clutter_actor_set_content (box, color); - else - clutter_actor_set_content (box, image); - - clutter_actor_set_size (box, 64, 64); - - clutter_actor_add_child (grid, box); - } - - clutter_test_main (); - - g_object_unref (color); - g_object_unref (image); - - return EXIT_SUCCESS; -} diff --git a/src/tests/clutter/interactive/test-keyframe-transition.c b/src/tests/clutter/interactive/test-keyframe-transition.c deleted file mode 100644 index 3deabc2f7..000000000 --- a/src/tests/clutter/interactive/test-keyframe-transition.c +++ /dev/null @@ -1,115 +0,0 @@ -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -static const ClutterColor colors[] = { - { 255, 0, 0, 255 }, - { 0, 255, 0, 255 }, - { 0, 0, 255, 255 }, -}; - -#define PADDING (64.0f) -#define SIZE (64.0f) - -const char * -test_keyframe_transition_describe (void); - -int -test_keyframe_transition_main (int argc, char *argv[]); - -static void -on_transition_stopped (ClutterActor *actor, - const gchar *transition_name, - gboolean is_finished) -{ - g_print ("%s: transition stopped: %s (finished: %s)\n", - clutter_actor_get_name (actor), - transition_name, - is_finished ? "yes" : "no"); -} - -G_MODULE_EXPORT const char * -test_keyframe_transition_describe (void) -{ - return "Demonstrate the keyframe transition."; -} - -G_MODULE_EXPORT int -test_keyframe_transition_main (int argc, char *argv[]) -{ - ClutterActor *stage; - int i; - - clutter_test_init (&argc, &argv); - - stage = clutter_test_get_stage (); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Keyframe Transitions"); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - - for (i = 0; i < 3; i++) - { - ClutterTransition *transition, *group; - ClutterActor *rect; - float cur_x, cur_y; - float new_x, new_y; - gchar *name; - - cur_x = PADDING; - cur_y = PADDING + ((SIZE + PADDING) * i); - - new_x = clutter_actor_get_width (stage) - PADDING - SIZE; - new_y = g_random_double_range (PADDING, clutter_actor_get_height (stage) - PADDING - SIZE); - - name = g_strdup_printf ("rect%02d", i); - - rect = clutter_actor_new (); - - clutter_actor_set_name (rect, name); - clutter_actor_set_background_color (rect, &colors[i]); - clutter_actor_set_size (rect, SIZE, SIZE); - clutter_actor_set_position (rect, PADDING, cur_y); - clutter_actor_add_child (stage, rect); - - group = clutter_transition_group_new (); - clutter_timeline_set_duration (CLUTTER_TIMELINE (group), 2000); - clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (group), 1); - clutter_timeline_set_auto_reverse (CLUTTER_TIMELINE (group), TRUE); - - transition = clutter_keyframe_transition_new ("x"); - clutter_transition_set_from (transition, G_TYPE_FLOAT, cur_x); - clutter_transition_set_to (transition, G_TYPE_FLOAT, new_x); - - clutter_keyframe_transition_set (CLUTTER_KEYFRAME_TRANSITION (transition), - G_TYPE_FLOAT, 1, - 0.5, new_x / 2.0f, CLUTTER_EASE_OUT_EXPO); - clutter_transition_group_add_transition (CLUTTER_TRANSITION_GROUP (group), transition); - g_object_unref (transition); - - transition = clutter_keyframe_transition_new ("y"); - clutter_transition_set_from (transition, G_TYPE_FLOAT, cur_y); - clutter_transition_set_to (transition, G_TYPE_FLOAT, cur_y); - - clutter_keyframe_transition_set (CLUTTER_KEYFRAME_TRANSITION (transition), - G_TYPE_FLOAT, 1, - 0.5, new_y, CLUTTER_EASE_OUT_EXPO); - clutter_transition_group_add_transition (CLUTTER_TRANSITION_GROUP (group), transition); - g_object_unref (transition); - - clutter_actor_add_transition (rect, "rectAnimation", group); - - g_signal_connect (rect, "transition-stopped", - G_CALLBACK (on_transition_stopped), - NULL); - g_object_unref (group); - - g_free (name); - } - - clutter_actor_show (stage); - - clutter_test_main (); - - return EXIT_SUCCESS; -} diff --git a/src/tests/clutter/interactive/test-layout.c b/src/tests/clutter/interactive/test-layout.c deleted file mode 100644 index ce8202cfd..000000000 --- a/src/tests/clutter/interactive/test-layout.c +++ /dev/null @@ -1,684 +0,0 @@ -#include -#include - -#include -#include - -#include -#include "test-utils.h" -#include "tests/clutter-test-utils.h" - -/* layout actor, by Lucas Rocha */ - -#define MY_TYPE_THING (my_thing_get_type ()) -#define MY_THING(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MY_TYPE_THING, MyThing)) -#define MY_IS_THING(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MY_TYPE_THING)) -#define MY_THING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MY_TYPE_THING, MyThingClass)) -#define MY_IS_THING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MY_TYPE_THING)) -#define MY_THING_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MY_TYPE_THING, MyThingClass)) - -typedef struct _MyThing MyThing; -typedef struct _MyThingPrivate MyThingPrivate; -typedef struct _MyThingClass MyThingClass; - -struct _MyThing -{ - ClutterActor parent_instance; - - MyThingPrivate *priv; -}; - -struct _MyThingClass -{ - ClutterActorClass parent_class; -}; - -enum -{ - PROP_0, - - PROP_SPACING, - PROP_PADDING, - PROP_USE_TRANSFORMED_BOX -}; - -struct _MyThingPrivate -{ - gfloat spacing; - gfloat padding; - - guint use_transformed_box : 1; -}; - -GType my_thing_get_type (void); - -int -test_layout_main (int argc, char *argv[]); - -const char * -test_layout_describe (void); - -G_DEFINE_TYPE_WITH_PRIVATE (MyThing, my_thing, CLUTTER_TYPE_ACTOR) - -#define MY_THING_GET_PRIVATE(obj) \ -(G_TYPE_INSTANCE_GET_PRIVATE ((obj), MY_TYPE_THING, MyThingPrivate)) - -static void -my_thing_set_property (GObject *gobject, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MyThingPrivate *priv = MY_THING (gobject)->priv; - gboolean needs_relayout = TRUE; - - switch (prop_id) - { - case PROP_SPACING: - priv->spacing = g_value_get_float (value); - break; - - case PROP_PADDING: - priv->padding = g_value_get_float (value); - break; - - case PROP_USE_TRANSFORMED_BOX: - priv->use_transformed_box = g_value_get_boolean (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); - needs_relayout = FALSE; - break; - } - - /* setting spacing or padding queues a relayout - because they are supposed to change the internal - allocation of children */ - if (needs_relayout) - clutter_actor_queue_relayout (CLUTTER_ACTOR (gobject)); -} - -static void -my_thing_get_property (GObject *gobject, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MyThingPrivate *priv = MY_THING (gobject)->priv; - - switch (prop_id) - { - case PROP_SPACING: - g_value_set_float (value, priv->spacing); - break; - - case PROP_PADDING: - g_value_set_float (value, priv->padding); - break; - - case PROP_USE_TRANSFORMED_BOX: - g_value_set_boolean (value, priv->use_transformed_box); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); - break; - } -} - -static void -my_thing_get_preferred_width (ClutterActor *self, - gfloat for_height, - gfloat *min_width_p, - gfloat *natural_width_p) -{ - ClutterActorIter iter; - ClutterActor *child; - gfloat min_left, min_right; - gfloat natural_left, natural_right; - - min_left = 0; - min_right = 0; - natural_left = 0; - natural_right = 0; - - clutter_actor_iter_init (&iter, self); - while (clutter_actor_iter_next (&iter, &child)) - { - gfloat child_x, child_min, child_natural; - - child_x = clutter_actor_get_x (child); - - clutter_actor_get_preferred_size (child, - &child_min, NULL, - &child_natural, NULL); - - if (child == clutter_actor_get_first_child (self)) - { - /* First child */ - min_left = child_x; - natural_left = child_x; - min_right = min_left + child_min; - natural_right = natural_left + child_natural; - } - else - { - /* Union of extents with previous children */ - if (child_x < min_left) - min_left = child_x; - - if (child_x < natural_left) - natural_left = child_x; - - if (child_x + child_min > min_right) - min_right = child_x + child_min; - - if (child_x + child_natural > natural_right) - natural_right = child_x + child_natural; - } - } - - if (min_left < 0) - min_left = 0; - - if (natural_left < 0) - natural_left = 0; - - if (min_right < 0) - min_right = 0; - - if (natural_right < 0) - natural_right = 0; - - g_assert (min_right >= min_left); - g_assert (natural_right >= natural_left); - - if (min_width_p) - *min_width_p = min_right - min_left; - - if (natural_width_p) - *natural_width_p = natural_right - min_left; -} - -static void -my_thing_get_preferred_height (ClutterActor *self, - gfloat for_width, - gfloat *min_height_p, - gfloat *natural_height_p) -{ - ClutterActorIter iter; - ClutterActor *child; - gfloat min_top, min_bottom; - gfloat natural_top, natural_bottom; - - min_top = 0; - min_bottom = 0; - natural_top = 0; - natural_bottom = 0; - - clutter_actor_iter_init (&iter, self); - while (clutter_actor_iter_next (&iter, &child)) - { - gfloat child_y, child_min, child_natural; - - child_y = clutter_actor_get_y (child); - - clutter_actor_get_preferred_size (child, - NULL, &child_min, - NULL, &child_natural); - - if (child == clutter_actor_get_first_child (self)) - { - /* First child */ - min_top = child_y; - natural_top = child_y; - min_bottom = min_top + child_min; - natural_bottom = natural_top + child_natural; - } - else - { - /* Union of extents with previous children */ - if (child_y < min_top) - min_top = child_y; - - if (child_y < natural_top) - natural_top = child_y; - - if (child_y + child_min > min_bottom) - min_bottom = child_y + child_min; - - if (child_y + child_natural > natural_bottom) - natural_bottom = child_y + child_natural; - } - } - - if (min_top < 0) - min_top = 0; - - if (natural_top < 0) - natural_top = 0; - - if (min_bottom < 0) - min_bottom = 0; - - if (natural_bottom < 0) - natural_bottom = 0; - - g_assert (min_bottom >= min_top); - g_assert (natural_bottom >= natural_top); - - if (min_height_p) - *min_height_p = min_bottom - min_top; - - if (natural_height_p) - *natural_height_p = natural_bottom - min_top; -} - -static void -my_thing_allocate (ClutterActor *self, - const ClutterActorBox *box) -{ - MyThingPrivate *priv; - gfloat current_x, current_y, max_row_height; - ClutterActorIter iter; - ClutterActor *child; - - clutter_actor_set_allocation (self, box); - - priv = MY_THING (self)->priv; - - current_x = priv->padding; - current_y = priv->padding; - max_row_height = 0; - - /* The allocation logic here is to horizontally place children - * side-by-side and reflow into a new row when we run out of - * space - */ - clutter_actor_iter_init (&iter, self); - while (clutter_actor_iter_next (&iter, &child)) - { - gfloat natural_width, natural_height; - ClutterActorBox child_box; - - clutter_actor_get_preferred_size (child, - NULL, NULL, - &natural_width, - &natural_height); - - /* if it fits in the current row, keep it there; otherwise - * reflow into another row - */ - if (current_x + natural_width > box->x2 - box->x1 - priv->padding) - { - current_x = priv->padding; - current_y += max_row_height + priv->spacing; - max_row_height = 0; - } - - child_box.x1 = current_x; - child_box.y1 = current_y; - child_box.x2 = child_box.x1 + natural_width; - child_box.y2 = child_box.y1 + natural_height; - - clutter_actor_allocate (child, &child_box); - - /* if we take into account the transformation of the children - * then we first check if it's transformed; then we get the - * onscreen coordinates of the two points of the bounding box - * of the actor (origin(x, y) and (origin + size)(x,y)) and - * we update the coordinates and area given to the next child - */ - if (priv->use_transformed_box) - { - if (clutter_actor_is_scaled (child) || - clutter_actor_is_rotated (child)) - { - graphene_point3d_t v1 = { 0, }, v2 = { 0, }; - ClutterActorBox transformed_box = { 0, }; - - v1.x = box->x1; - v1.y = box->y1; - - clutter_actor_apply_transform_to_point (child, &v1, &v2); - transformed_box.x1 = v2.x; - transformed_box.y1 = v2.y; - - /* size */ - v1.x = natural_width; - v1.y = natural_height; - clutter_actor_apply_transform_to_point (child, &v1, &v2); - transformed_box.x2 = v2.x; - transformed_box.y2 = v2.y; - - natural_width = transformed_box.x2 - transformed_box.x1; - natural_height = transformed_box.y2 - transformed_box.y1; - } - } - - /* Record the maximum child height on current row to know - * what's the increment that should be used for the next - * row - */ - if (natural_height > max_row_height) - max_row_height = natural_height; - - current_x += natural_width + priv->spacing; - } -} - -#define MIN_SIZE 24 -#define MAX_SIZE 64 - -static void -my_thing_class_init (MyThingClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); - - gobject_class->set_property = my_thing_set_property; - gobject_class->get_property = my_thing_get_property; - - actor_class->get_preferred_width = my_thing_get_preferred_width; - actor_class->get_preferred_height = my_thing_get_preferred_height; - actor_class->allocate = my_thing_allocate; - - g_object_class_install_property (gobject_class, - PROP_SPACING, - g_param_spec_float ("spacing", - "Spacing", - "Spacing of the thing", - 0, G_MAXFLOAT, - 0, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, - PROP_PADDING, - g_param_spec_float ("padding", - "Padding", - "Padding around the thing", - 0, G_MAXFLOAT, - 0, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, - PROP_USE_TRANSFORMED_BOX, - g_param_spec_boolean ("use-transformed-box", - "Use Transformed Box", - "Use transformed box when allocating", - FALSE, - G_PARAM_READWRITE)); -} - -static void -my_thing_init (MyThing *thing) -{ - thing->priv = MY_THING_GET_PRIVATE (thing); -} - -static ClutterActor * -my_thing_new (gfloat padding, - gfloat spacing) -{ - return g_object_new (MY_TYPE_THING, - "padding", padding, - "spacing", spacing, - NULL); -} - -/* test code */ - -static ClutterActor *box = NULL; -static ClutterActor *icon = NULL; -static ClutterTimeline *main_timeline = NULL; - -static void -toggle_property_value (ClutterActor *actor, - const gchar *property_name) -{ - gboolean value; - - g_object_get (actor, property_name, &value, NULL); - - value = !value; - - g_object_set (box, property_name, value, NULL); -} - -static void -increase_property_value (ClutterActor *actor, - const char *property_name) -{ - gfloat value; - - g_object_get (actor, property_name, &value, NULL); - - value = value + 10.0; - - g_object_set (box, property_name, value, NULL); -} - -static void -decrease_property_value (ClutterActor *actor, - const char *property_name) -{ - gfloat value; - - g_object_get (actor, property_name, &value, NULL); - - value = MAX (0, value - 10.0); - - g_object_set (box, property_name, value, NULL); -} - -static ClutterActor * -create_item (void) -{ - ClutterActor *clone = clutter_clone_new (icon); - - gint32 size = g_random_int_range (MIN_SIZE, MAX_SIZE); - - clutter_actor_set_size (clone, size, size); - clutter_actor_animate_with_timeline (clone, CLUTTER_EASE_OUT_CUBIC, - main_timeline, - "scale-x", 2.0, - "scale-y", 2.0, - "fixed::scale-gravity", CLUTTER_GRAVITY_CENTER, - NULL); - - return clone; -} - -static gboolean -keypress_cb (ClutterActor *actor, - ClutterEvent *event, - gpointer data) -{ - switch (clutter_event_get_key_symbol (event)) - { - case CLUTTER_KEY_q: - clutter_test_quit (); - break; - - case CLUTTER_KEY_a: - { - if (icon != NULL) - { - ClutterActor *clone = create_item (); - - /* Add one item to container */ - clutter_actor_add_child (box, clone); - } - break; - } - - case CLUTTER_KEY_d: - { - ClutterActor *last_child; - - last_child = clutter_actor_get_last_child (box); - if (last_child != NULL) - { - /* Remove last item on container */ - clutter_actor_remove_child (box, last_child); - } - break; - } - - case CLUTTER_KEY_w: - { - decrease_property_value (box, "padding"); - break; - } - - case CLUTTER_KEY_e: - { - increase_property_value (box, "padding"); - break; - } - - case CLUTTER_KEY_r: - { - decrease_property_value (box, "spacing"); - break; - } - - case CLUTTER_KEY_s: - { - toggle_property_value (box, "use-transformed-box"); - break; - } - - case CLUTTER_KEY_t: - { - increase_property_value (box, "spacing"); - break; - } - - case CLUTTER_KEY_z: - { - if (clutter_timeline_is_playing (main_timeline)) - clutter_timeline_pause (main_timeline); - else - clutter_timeline_start (main_timeline); - - break; - } - - default: - break; - } - - return FALSE; -} - -static void -relayout_on_frame (ClutterTimeline *timeline) -{ - gboolean use_transformed_box; - - /* if we care about transformations updating the layout, we need to inform - * the layout that a transformation is happening; this is either done by - * attaching a notification on the transformation properties or by simply - * queuing a relayout on each frame of the timeline used to drive the - * behaviour. for simplicity's sake, we used the latter - */ - - g_object_get (G_OBJECT (box), - "use-transformed-box", &use_transformed_box, - NULL); - - if (use_transformed_box) - clutter_actor_queue_relayout (box); -} - -G_MODULE_EXPORT int -test_layout_main (int argc, char *argv[]) -{ - ClutterActor *stage, *instructions; - gint i, size; - GError *error = NULL; - - clutter_test_init (&argc, &argv); - - stage = clutter_test_get_stage (); - clutter_actor_set_size (stage, 800, 600); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Layout"); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - - main_timeline = clutter_timeline_new_for_actor (stage, 2000); - clutter_timeline_set_repeat_count (main_timeline, -1); - clutter_timeline_set_auto_reverse (main_timeline, TRUE); - g_signal_connect (main_timeline, "new-frame", - G_CALLBACK (relayout_on_frame), - NULL); - - - box = my_thing_new (10, 10); - - clutter_actor_set_position (box, 20, 20); - clutter_actor_set_size (box, 350, -1); - - icon = clutter_test_utils_create_texture_from_file (TESTS_DATADIR - G_DIR_SEPARATOR_S - "redhand.png", - &error); - if (error) - g_error ("Unable to load 'redhand.png': %s", error->message); - - size = g_random_int_range (MIN_SIZE, MAX_SIZE); - clutter_actor_set_size (icon, size, size); - clutter_actor_add_child (box, icon); - clutter_actor_animate_with_timeline (icon, CLUTTER_EASE_OUT_CUBIC, - main_timeline, - "scale-x", 2.0, - "scale-y", 2.0, - "fixed::scale-gravity", CLUTTER_GRAVITY_CENTER, - NULL); - - for (i = 1; i < 33; i++) - { - ClutterActor *clone = create_item (); - - clutter_actor_add_child (box, clone); - } - - clutter_actor_add_child (stage, box); - - instructions = clutter_text_new_with_text (NULL, - "Instructions:\n" - "a - add a new item\n" - "d - remove last item\n" - "z - start/pause behaviour\n" - "w - decrease padding\n" - "e - increase padding\n" - "r - decrease spacing\n" - "t - increase spacing\n" - "s - use transformed box\n" - "q - quit"); - - clutter_text_set_use_markup (CLUTTER_TEXT (instructions), TRUE); - clutter_actor_set_position (instructions, 450, 10); - clutter_actor_add_child (stage, instructions); - - g_signal_connect (stage, "key-release-event", - G_CALLBACK (keypress_cb), - NULL); - - clutter_timeline_stop (main_timeline); - - clutter_actor_show (stage); - - clutter_test_main (); - - g_object_unref (main_timeline); - - return EXIT_SUCCESS; -} - -G_MODULE_EXPORT const char * -test_layout_describe (void) -{ - return "Container implementing a layout policy."; -} diff --git a/src/tests/clutter/interactive/test-main.c b/src/tests/clutter/interactive/test-main.c deleted file mode 100644 index 29fc82a6a..000000000 --- a/src/tests/clutter/interactive/test-main.c +++ /dev/null @@ -1,227 +0,0 @@ -#include "config.h" - -#include -#include -#include -#include - -#include "backends/x11/nested/meta-backend-x11-nested.h" -#include "meta-test/meta-context-test.h" -#include "tests/clutter-test-utils.h" - -#include "test-unit-names.h" - -#define MAX_DESC_SIZE 72 - -static GModule *module = NULL; - -static gpointer -get_symbol_with_suffix (const char *unit_name, - const char *suffix) -{ - char *main_symbol_name; - gpointer func; - - main_symbol_name = g_strconcat (unit_name, "_", suffix, NULL); - main_symbol_name = g_strdelimit (main_symbol_name, "-", '_'); - - g_module_symbol (module, main_symbol_name, &func); - - g_free (main_symbol_name); - - return func; -} - -static gpointer -get_unit_name_main (const char *unit_name) -{ - return get_symbol_with_suffix (unit_name, "main"); -} -static char * -get_unit_name_description (const char *unit_name, - gssize max_len) -{ - const char *description; - gpointer func; - char *retval; - - func = get_symbol_with_suffix (unit_name, "describe"); - if (func == NULL) - description = "No description found"; - else - { - const char *(* unit_test_describe) (void); - - unit_test_describe = func; - - description = unit_test_describe (); - } - - if (max_len > 0 && strlen (description) >= max_len) - { - GString *buf = g_string_sized_new (max_len); - char *newline; - - newline = strchr (description, '\n'); - if (newline != NULL) - { - g_string_append_len (buf, description, - MIN (newline - description - 1, max_len - 3)); - } - else - g_string_append_len (buf, description, max_len - 3); - - g_string_append (buf, "..."); - - retval = g_string_free (buf, FALSE); - } - else - retval = g_strdup (description); - - return retval; -} - -static gboolean list_all = FALSE; -static gboolean describe = FALSE; -static char **unit_names = NULL; - -static GOptionEntry entries[] = { - { - "describe", 'd', - 0, - G_OPTION_ARG_NONE, &describe, - "Describe the interactive unit test", NULL, - }, - { - "list-all", 'l', - 0, - G_OPTION_ARG_NONE, &list_all, - "List all available units", NULL, - }, - { - G_OPTION_REMAINING, 0, - 0, - G_OPTION_ARG_STRING_ARRAY, &unit_names, - "The interactive unit test", "UNIT_NAME" - }, - { NULL } -}; - -int -main (int argc, char **argv) -{ - int ret, i, n_unit_names; - GOptionContext *context; - - context = g_option_context_new (" - Interactive test suite"); - g_option_context_add_main_entries (context, entries, NULL); - g_option_context_set_help_enabled (context, TRUE); - g_option_context_set_ignore_unknown_options (context, TRUE); - if (!g_option_context_parse (context, &argc, &argv, NULL)) - { - g_print ("Usage: test-interactive \n"); - return EXIT_FAILURE; - } - - g_option_context_free (context); - - module = g_module_open (NULL, 0); - if (!module) - g_error ("*** Failed to open self for symbol lookup"); - - ret = EXIT_SUCCESS; - - if (list_all) - { - g_print ("* Available unit tests:\n"); - - for (i = 0; i < G_N_ELEMENTS (test_unit_names); i++) - { - char *str; - gsize len; - - len = MAX_DESC_SIZE - strlen (test_unit_names[i]); - str = get_unit_name_description (test_unit_names[i], len - 2); - - g_print (" - %s:%*s%s\n", - test_unit_names[i], - (int) (len - strlen (str)), " ", - str); - - g_free (str); - } - - ret = EXIT_SUCCESS; - goto out; - } - - if (unit_names != NULL) - n_unit_names = g_strv_length (unit_names); - else - { - g_print ("Usage: test-interactive \n"); - ret = EXIT_FAILURE; - goto out; - } - - for (i = 0; i < n_unit_names; i++) - { - const char *unit_name = unit_names[i]; - char *unit_test = NULL; - gboolean found; - int j; - - unit_test = g_path_get_basename (unit_name); - - found = FALSE; - for (j = 0; j < G_N_ELEMENTS (test_unit_names); j++) - { - if (strcmp (test_unit_names[j], unit_test) == 0) - { - found = TRUE; - break; - } - } - - if (!found) - g_error ("*** Unit '%s' does not exist", unit_test); - - if (describe) - { - char *str; - - str = get_unit_name_description (unit_test, -1); - - g_print ("* %s:\n%s\n\n", unit_test, str); - - g_free (str); - - ret = EXIT_SUCCESS; - } - else - { - int (* unit_test_main) (int argc, char **argv); - gpointer func; - - func = get_unit_name_main (unit_test); - if (func == NULL) - g_error ("*** Unable to find the main entry point for '%s'", unit_test); - - unit_test_main = func; - - ret = unit_test_main (n_unit_names, unit_names); - - g_free (unit_test); - - break; - } - - g_free (unit_test); - } - -out: - g_module_close (module); - - return ret; -} - diff --git a/src/tests/clutter/interactive/test-path-constraint.c b/src/tests/clutter/interactive/test-path-constraint.c deleted file mode 100644 index baa1ea790..000000000 --- a/src/tests/clutter/interactive/test-path-constraint.c +++ /dev/null @@ -1,138 +0,0 @@ -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -#define PATH_DESCRIPTION \ - "M 0, 0 " \ - "L 0, 300 " \ - "L 300, 300 " \ - "L 300, 0 " \ - "L 0, 0" - -static gboolean toggled = FALSE; - -int -test_path_constraint_main (int argc, - char *argv[]); - -static gboolean -on_button_press (ClutterActor *actor, - const ClutterEvent *event, - gpointer dummy G_GNUC_UNUSED) -{ - if (!toggled) - clutter_actor_animate (actor, CLUTTER_EASE_OUT_CUBIC, 500, - "@constraints.path.offset", 1.0, - NULL); - else - clutter_actor_animate (actor, CLUTTER_EASE_OUT_CUBIC, 500, - "@constraints.path.offset", 0.0, - NULL); - - toggled = !toggled; - - return TRUE; -} - -static gchar * -node_to_string (const ClutterPathNode *node) -{ - GString *buffer = g_string_sized_new (256); - gsize len = 0, i; - - switch (node->type) - { - case CLUTTER_PATH_MOVE_TO: - g_string_append (buffer, "move-to "); - len = 1; - break; - - case CLUTTER_PATH_LINE_TO: - g_string_append (buffer, "line-to "); - len = 1; - break; - - case CLUTTER_PATH_CURVE_TO: - g_string_append (buffer, "curve-to "); - len = 3; - break; - - case CLUTTER_PATH_CLOSE: - g_string_append (buffer, "close"); - len = 0; - break; - - default: - break; - } - - for (i = 0; i < len; i++) - { - if (i == 0) - g_string_append (buffer, "[ "); - - g_string_append_printf (buffer, "[ %d, %d ]", - node->points[i].x, - node->points[i].y); - - if (i == len - 1) - g_string_append (buffer, " ]"); - } - - return g_string_free (buffer, FALSE); -} - -static void -on_node_reached (ClutterPathConstraint *constraint, - ClutterActor *actor, - guint index_) -{ - ClutterPath *path = clutter_path_constraint_get_path (constraint); - ClutterPathNode node; - gchar *str; - - clutter_path_get_node (path, index_, &node); - - str = node_to_string (&node); - g_print ("Node %d reached: %s\n", index_, str); - g_free (str); -} - -G_MODULE_EXPORT int -test_path_constraint_main (int argc, - char *argv[]) -{ - ClutterActor *stage, *rect; - ClutterPath *path; - ClutterColor rect_color = { 0xcc, 0x00, 0x00, 0xff }; - - clutter_test_init (&argc, &argv); - - stage = clutter_test_get_stage (); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Path Constraint"); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - - path = clutter_path_new (); - clutter_path_set_description (path, PATH_DESCRIPTION); - - rect = clutter_actor_new (); - clutter_actor_set_background_color (rect, &rect_color); - clutter_actor_set_size (rect, 128, 128); - clutter_actor_set_reactive (rect, TRUE); - clutter_actor_add_constraint_with_name (rect, "path", clutter_path_constraint_new (path, 0.0)); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); - - g_signal_connect (rect, "button-press-event", G_CALLBACK (on_button_press), NULL); - g_signal_connect (clutter_actor_get_constraint (rect, "path"), - "node-reached", - G_CALLBACK (on_node_reached), - NULL); - - clutter_actor_show (stage); - - clutter_test_main (); - - return EXIT_SUCCESS; -} diff --git a/src/tests/clutter/interactive/test-rotate-zoom.c b/src/tests/clutter/interactive/test-rotate-zoom.c deleted file mode 100644 index f21492158..000000000 --- a/src/tests/clutter/interactive/test-rotate-zoom.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2013 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU Lesser General Public License, - * version 2.1, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * Boston, MA 02111-1307, USA. - * - */ -#include -#include -#include -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -#define STAGE_WIDTH 800 -#define STAGE_HEIGHT 550 - -int -test_rotate_zoom_main (int argc, char *argv[]); - -const char * -test_rotate_zoom_describe (void); - -static ClutterActor * -create_hand (void) -{ - GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (TESTS_DATADIR G_DIR_SEPARATOR_S "redhand.png", NULL); - ClutterContent *image = clutter_image_new (); - ClutterActor *actor = clutter_actor_new (); - - clutter_image_set_data (CLUTTER_IMAGE (image), - gdk_pixbuf_get_pixels (pixbuf), - gdk_pixbuf_get_has_alpha (pixbuf) - ? COGL_PIXEL_FORMAT_RGBA_8888 - : COGL_PIXEL_FORMAT_RGB_888, - gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf), - gdk_pixbuf_get_rowstride (pixbuf), - NULL); - clutter_actor_set_content (actor, image); - clutter_actor_set_size (actor, - gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf)); - clutter_actor_set_reactive (actor, TRUE); - - g_object_unref (pixbuf); - - return actor; -} - -G_MODULE_EXPORT int -test_rotate_zoom_main (int argc, char *argv[]) -{ - ClutterActor *stage, *actor; - gfloat width, height; - - /* initialize Clutter */ - clutter_test_init (&argc, &argv); - - /* create a resizable stage */ - stage = clutter_test_get_stage (); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Rotate and Zoom actions"); - clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT); - clutter_actor_set_reactive (stage, FALSE); - clutter_actor_show (stage); - - actor = create_hand (); - clutter_actor_add_action (actor, clutter_rotate_action_new ()); - clutter_actor_add_action (actor, clutter_zoom_action_new ()); - clutter_actor_add_child (stage, actor); - - clutter_actor_get_size (actor, &width, &height); - clutter_actor_set_position (actor, - STAGE_WIDTH / 2 - width / 2, - STAGE_HEIGHT / 2 - height / 2); - - clutter_test_main (); - - return EXIT_SUCCESS; -} - -G_MODULE_EXPORT const char * -test_rotate_zoom_describe (void) -{ - return "Rotates and zooms an actor using touch events"; -} diff --git a/src/tests/clutter/interactive/test-script.c b/src/tests/clutter/interactive/test-script.c deleted file mode 100644 index e15ff32b4..000000000 --- a/src/tests/clutter/interactive/test-script.c +++ /dev/null @@ -1,154 +0,0 @@ -#include -#include - -#include - -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -static ClutterScript *script = NULL; -static guint merge_id = 0; - -int -test_script_main (int argc, char *argv[]); - -static const gchar *test_unmerge = -"[" -" {" -" \"id\" : \"main-stage\"," -" \"type\" : \"ClutterStage\"," -" \"children\" : [ \"blue-button\" ]" -" }," -" {" -" \"id\" : \"blue-button\"," -" \"type\" : \"ClutterActor\"," -" \"background-color\" : \"#0000ffff\"," -" \"x\" : 350," -" \"y\" : 50," -" \"width\" : 100," -" \"height\" : 100," -" \"visible\" : true," -" \"reactive\" : true" -" }" -"]"; - -static const gchar *test_behaviour = -"[" -" {" -" \"id\" : \"main-timeline\"," -" \"type\" : \"ClutterTimeline\"," -" \"duration\" : 5000," -" \"loop\" : true" -" }" -"]"; - -static gboolean -blue_button_press (ClutterActor *actor, - ClutterButtonEvent *event, - gpointer data) -{ - g_print ("[*] Pressed '%s'\n", clutter_get_script_id (G_OBJECT (actor))); - g_print ("[*] Unmerging objects with merge id: %d\n", merge_id); - - clutter_script_unmerge_objects (script, merge_id); - - return TRUE; -} - -static gboolean -red_button_press (ClutterActor *actor, - ClutterButtonEvent *event, - gpointer data) -{ - GObject *timeline; - - g_print ("[*] Pressed '%s'\n", clutter_get_script_id (G_OBJECT (actor))); - - timeline = clutter_script_get_object (script, "main-timeline"); - g_assert (CLUTTER_IS_TIMELINE (timeline)); - - if (!clutter_timeline_is_playing (CLUTTER_TIMELINE (timeline))) - clutter_timeline_start (CLUTTER_TIMELINE (timeline)); - else - clutter_timeline_pause (CLUTTER_TIMELINE (timeline)); - - return TRUE; -} - -G_MODULE_EXPORT int -test_script_main (int argc, char *argv[]) -{ - GObject *stage, *blue_button, *red_button; - GError *error = NULL; - gchar *file; - gint res; - - clutter_test_init (&argc, &argv); - - script = clutter_script_new (); - g_assert (CLUTTER_IS_SCRIPT (script)); - - clutter_script_load_from_data (script, test_behaviour, -1, &error); - if (error) - { - g_print ("*** Error:\n" - "*** %s\n", error->message); - g_error_free (error); - g_object_unref (script); - return EXIT_FAILURE; - } - - file = g_build_filename (TESTS_DATADIR, "test-script.json", NULL); - clutter_script_load_from_file (script, file, &error); - if (error) - { - g_print ("*** Error:\n" - "*** %s\n", error->message); - g_error_free (error); - g_object_unref (script); - g_free (file); - return EXIT_FAILURE; - } - - g_free (file); - - merge_id = clutter_script_load_from_data (script, test_unmerge, -1, &error); - if (error) - { - g_print ("*** Error:\n" - "*** %s\n", error->message); - g_error_free (error); - g_object_unref (script); - return EXIT_FAILURE; - } - - clutter_script_connect_signals (script, NULL); - - res = clutter_script_get_objects (script, - "main-stage", &stage, - "red-button", &red_button, - "blue-button", &blue_button, - NULL); - g_assert (res == 3); - - clutter_actor_show (CLUTTER_ACTOR (stage)); - - g_signal_connect (red_button, - "button-press-event", - G_CALLBACK (red_button_press), - NULL); - - g_signal_connect (blue_button, - "button-press-event", - G_CALLBACK (blue_button_press), - NULL); - - clutter_test_main (); - - g_object_unref (script); - - return EXIT_SUCCESS; -} diff --git a/src/tests/clutter/interactive/test-script.json b/src/tests/clutter/interactive/test-script.json deleted file mode 100644 index b958315ae..000000000 --- a/src/tests/clutter/interactive/test-script.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "My Scene" : { - "id" : "main-stage", - "type" : "ClutterStage", - "title" : { "translatable" : true, "string" : "ClutterScript test" }, - "color" : "white", - "signals" : [ - { "name" : "key-press-event", "handler" : "clutter_test_quit" }, - { "name" : "destroy", "handler" : "clutter_test_quit" } - ], - "children" : [ - { - "id" : "red-button", - "type" : "ClutterActor", - "background-color" : "#ff0000ff", - "x" : 50, "y" : 50, "width" : 100, "height" : 100, - "reactive" : true, - "rotation" : [ - { "z-axis" : [ 45.0, [ 75, 75 ] ] } - ] - }, - { - "id" : "green-button", - "type" : "ClutterActor", - "background-color" : "#00ff00ff", - "border-width" : 5, - "border-color" : "#00cc00ff", - "position" : [ 200.0, 50.0 ], - "size" : { "width" : 100.0, "height" : 100.0 }, - "depth" : -200.0, - "reactive" : true, - "signals" : [ - { "name" : "button-press-event", "handler" : "clutter_test_quit" } - ] - }, - { - "id" : "label", - "type" : "ClutterText", - "x" : 50, - "y" : 200, - "text" : { "translatable" : true, "string" : "Clutter Script" }, - "font-name" : "Sans 24px", - "color" : "black", - "line-alignment" : "center", - "line-wrap" : false, - "ellipsize" : "none", - "rotation" : [ - { "y-axis" : [ 60.0, [ 275, 100 ] ] }, - { "z-axis" : [ 45.0, [ 75, 75 ] ] } - ] - } - ] - } -} diff --git a/src/tests/clutter/interactive/test-shader-effects.c b/src/tests/clutter/interactive/test-shader-effects.c deleted file mode 100644 index 992587c58..000000000 --- a/src/tests/clutter/interactive/test-shader-effects.c +++ /dev/null @@ -1,88 +0,0 @@ -#include -#include -#include - -#include -#include - -#include -#include "test-utils.h" -#include "tests/clutter-test-utils.h" - -int -test_shader_effects_main (int argc, char *argv[]); - -G_MODULE_EXPORT int -test_shader_effects_main (int argc, char *argv[]) -{ - ClutterTimeline *timeline; - ClutterActor *stage, *hand, *label, *rect; - gchar *file; - - clutter_test_init (&argc, &argv); - - stage = clutter_test_get_stage (); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Rotations"); - clutter_actor_set_background_color (stage, CLUTTER_COLOR_Aluminium3); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - - /* Make a timeline */ - timeline = clutter_timeline_new_for_actor (stage, 7692); - clutter_timeline_set_repeat_count (timeline, -1); - - /* Make a hand */ - file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL); - hand = clutter_test_utils_create_texture_from_file (file, NULL); - if (!hand) - g_error("Unable to load '%s'", file); - - g_free (file); - - clutter_actor_set_position (hand, 326, 265); - clutter_actor_add_effect_with_name (hand, "desaturate", clutter_desaturate_effect_new (0.75)); - clutter_actor_add_effect_with_name (hand, "blur", clutter_blur_effect_new ()); - clutter_actor_animate_with_timeline (hand, CLUTTER_LINEAR, timeline, - "@effects.desaturate.factor", 1.0, - "rotation-angle-z", 360.0, - "fixed::anchor-x", 86.0, - "fixed::anchor-y", 125.0, - "opacity", 128, - NULL); - - rect = clutter_actor_new (); - clutter_actor_set_background_color (rect, CLUTTER_COLOR_DarkOrange); - clutter_actor_add_effect_with_name (rect, "blur", clutter_blur_effect_new ()); - clutter_actor_set_position (rect, 415, 215); - clutter_actor_set_size (rect, 150, 150); - clutter_actor_animate_with_timeline (rect, CLUTTER_LINEAR, timeline, - "rotation-angle-z", 360.0, - "fixed::anchor-x", 75.0, - "fixed::anchor-y", 75.0, - NULL); - - label = clutter_text_new_with_text ("Mono 16", - "The Wonder\n" - "of the\n" - "Spinning Hand"); - clutter_text_set_line_alignment (CLUTTER_TEXT (label), PANGO_ALIGN_CENTER); - clutter_actor_set_position (label, 336, 275); - clutter_actor_set_size (label, 500, 100); - clutter_actor_animate_with_timeline (label, CLUTTER_LINEAR, timeline, - "rotation-angle-z", 360.0, - "fixed::anchor-x", 86.0, - "fixed::anchor-y", 125.0, - NULL); - - clutter_container_add (CLUTTER_CONTAINER (stage), rect, hand, label, NULL); - - /* start the timeline and thus the animations */ - clutter_timeline_start (timeline); - - clutter_actor_show (stage); - - clutter_test_main (); - - g_object_unref (timeline); - - return 0; -} diff --git a/src/tests/clutter/interactive/test-stage-sizing.c b/src/tests/clutter/interactive/test-stage-sizing.c deleted file mode 100644 index 020b4be86..000000000 --- a/src/tests/clutter/interactive/test-stage-sizing.c +++ /dev/null @@ -1,89 +0,0 @@ -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -int -test_stage_sizing_main (int argc, char *argv[]); - -const char * -test_stage_sizing_describe (void); - -static gboolean -shrink_clicked_cb (ClutterActor *stage) -{ - gfloat width, height; - clutter_actor_get_size (stage, &width, &height); - clutter_actor_set_size (stage, MAX (0, width - 10.f), MAX (0, height - 10.f)); - return CLUTTER_EVENT_STOP; -} - -static gboolean -expand_clicked_cb (ClutterActor *stage) -{ - gfloat width, height; - clutter_actor_get_size (stage, &width, &height); - clutter_actor_set_size (stage, width + 10.f, height + 10.f); - return CLUTTER_EVENT_STOP; -} - -G_MODULE_EXPORT int -test_stage_sizing_main (int argc, char *argv[]) -{ - ClutterActor *stage, *rect, *label, *box; - ClutterMargin margin = { 12.f, 12.f, 6.f, 6.f }; - - clutter_test_init (&argc, &argv); - - stage = clutter_test_get_stage (); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Stage Sizing"); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), 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_SkyBlue); - clutter_actor_set_reactive (rect, TRUE); - g_signal_connect_swapped (rect, "button-press-event", - G_CALLBACK (shrink_clicked_cb), stage); - label = clutter_text_new_with_text ("Sans 16", "Shrink"); - 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_Butter); - clutter_actor_set_reactive (rect, TRUE); - g_signal_connect_swapped (rect, "button-press-event", - G_CALLBACK (expand_clicked_cb), stage); - label = clutter_text_new_with_text ("Sans 16", "Expand"); - clutter_actor_set_margin (label, &margin); - clutter_actor_add_child (rect, label); - clutter_actor_add_child (box, rect); - - clutter_stage_set_minimum_size (CLUTTER_STAGE (stage), - clutter_actor_get_width (box), - clutter_actor_get_height (box)); - - clutter_actor_show (stage); - - clutter_test_main (); - - return EXIT_SUCCESS; -} - -G_MODULE_EXPORT const char * -test_stage_sizing_describe (void) -{ - return "Check stage sizing policies."; -} diff --git a/src/tests/clutter/interactive/test-state-script.c b/src/tests/clutter/interactive/test-state-script.c deleted file mode 100644 index 5905704f0..000000000 --- a/src/tests/clutter/interactive/test-state-script.c +++ /dev/null @@ -1,46 +0,0 @@ -#include - -#include - -#include - -#include "tests/clutter-test-utils.h" - -#define TEST_STATE_SCRIPT_FILE "test-script-signals.json" - -int -test_state_script_main (int argc, char *argv[]); - -G_MODULE_EXPORT int -test_state_script_main (int argc, char *argv[]) -{ - ClutterActor *stage, *button; - ClutterScript *script; - GError *error = NULL; - - clutter_test_init (&argc, &argv); - - script = clutter_script_new (); - clutter_script_load_from_file (script, TEST_STATE_SCRIPT_FILE, &error); - if (error != NULL) - g_error ("Unable to load '%s': %s\n", - TEST_STATE_SCRIPT_FILE, - error->message); - - stage = clutter_test_get_stage (); - clutter_stage_set_title (CLUTTER_STAGE (stage), "State Script"); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - clutter_actor_show (stage); - - button = CLUTTER_ACTOR (clutter_script_get_object (script, "button")); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), button); - clutter_actor_add_constraint (button, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5)); - - clutter_script_connect_signals (script, NULL); - - clutter_test_main (); - - g_object_unref (script); - - return EXIT_SUCCESS; -} diff --git a/src/tests/clutter/interactive/test-swipe-action.c b/src/tests/clutter/interactive/test-swipe-action.c deleted file mode 100644 index d160ff288..000000000 --- a/src/tests/clutter/interactive/test-swipe-action.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include - -#include "tests/clutter-test-utils.h" - -enum -{ - VERTICAL = 0, - HORIZONTAL = 1, - BOTH = 2 -}; - -int -test_swipe_action_main (int argc, char *argv[]); - -const char * -test_swipe_action_describe (void); - -static void -swept_cb (ClutterSwipeAction *action, - ClutterActor *actor, - ClutterSwipeDirection direction, - gpointer data_) -{ - guint axis = GPOINTER_TO_UINT (data_); - gchar *direction_str = g_strdup (""); - - if (axis == HORIZONTAL && - ((direction & CLUTTER_SWIPE_DIRECTION_UP) != 0 || - (direction & CLUTTER_SWIPE_DIRECTION_DOWN) != 0)) - { - g_print ("discarding non-horizontal swipe on '%s'\n", - clutter_actor_get_name (actor)); - return; - } - - if (axis == VERTICAL && - ((direction & CLUTTER_SWIPE_DIRECTION_LEFT) != 0 || - (direction & CLUTTER_SWIPE_DIRECTION_RIGHT) != 0)) - { - g_print ("discarding non-vertical swipe on '%s'\n", - clutter_actor_get_name (actor)); - return; - } - - if (direction & CLUTTER_SWIPE_DIRECTION_UP) - { - char *old_str = direction_str; - - direction_str = g_strconcat (direction_str, " up", NULL); - g_free (old_str); - } - - if (direction & CLUTTER_SWIPE_DIRECTION_DOWN) - { - char *old_str = direction_str; - - direction_str = g_strconcat (direction_str, " down", NULL); - g_free (old_str); - } - - if (direction & CLUTTER_SWIPE_DIRECTION_LEFT) - { - char *old_str = direction_str; - - direction_str = g_strconcat (direction_str, " left", NULL); - g_free (old_str); - } - - if (direction & CLUTTER_SWIPE_DIRECTION_RIGHT) - { - char *old_str = direction_str; - - direction_str = g_strconcat (direction_str, " right", NULL); - g_free (old_str); - } - - g_print ("swept: '%s': %s\n", clutter_actor_get_name (actor), direction_str); - - g_free (direction_str); -} - -static void -gesture_cancel_cb (ClutterSwipeAction *action, - ClutterActor *actor, - gpointer user_data) -{ - g_debug ("gesture cancelled: '%s'", clutter_actor_get_name (actor)); -} - -static void -attach_action (ClutterActor *actor, guint axis) -{ - ClutterAction *action; - - action = g_object_new (CLUTTER_TYPE_SWIPE_ACTION, NULL); - clutter_actor_add_action (actor, action); - g_signal_connect (action, "swept", G_CALLBACK (swept_cb), GUINT_TO_POINTER (axis)); - g_signal_connect (action, "gesture-cancel", G_CALLBACK (gesture_cancel_cb), NULL); -} - -static ClutterActor * -create_label (const char *markup) -{ - return CLUTTER_ACTOR (g_object_new (CLUTTER_TYPE_TEXT, - "text", markup, - "use-markup", TRUE, - "x-expand", TRUE, - "y-expand", TRUE, - "x-align", CLUTTER_ACTOR_ALIGN_START, - "y-align", CLUTTER_ACTOR_ALIGN_CENTER, - NULL)); -} - -G_MODULE_EXPORT int -test_swipe_action_main (int argc, char *argv[]) -{ - ClutterActor *stage, *rect; - - clutter_test_init (&argc, &argv); - - stage = clutter_test_get_stage (); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Swipe action"); - clutter_actor_set_size (stage, 640, 480); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - - rect = clutter_actor_new (); - clutter_actor_set_background_color (rect, CLUTTER_COLOR_Red); - clutter_actor_set_name (rect, "Vertical swipes"); - clutter_actor_set_size (rect, 150, 150); - clutter_actor_set_position (rect, 10, 100); - clutter_actor_set_reactive (rect, TRUE); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); - attach_action (rect, VERTICAL); - - rect = clutter_actor_new (); - clutter_actor_set_background_color (rect, CLUTTER_COLOR_Blue); - clutter_actor_set_name (rect, "Horizontal swipes"); - clutter_actor_set_size (rect, 150, 150); - clutter_actor_set_position (rect, 170, 100); - clutter_actor_set_reactive (rect, TRUE); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); - attach_action (rect, HORIZONTAL); - - rect = clutter_actor_new (); - clutter_actor_set_background_color (rect, CLUTTER_COLOR_Green); - clutter_actor_set_name (rect, "All swipes"); - clutter_actor_set_size (rect, 150, 150); - clutter_actor_set_position (rect, 330, 100); - clutter_actor_set_reactive (rect, TRUE); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); - attach_action (rect, BOTH); - - { - ClutterLayoutManager *layout = clutter_box_layout_new (); - ClutterActor *box; - float offset; - - clutter_box_layout_set_orientation (CLUTTER_BOX_LAYOUT (layout), - CLUTTER_ORIENTATION_VERTICAL); - clutter_box_layout_set_spacing (CLUTTER_BOX_LAYOUT (layout), 6); - - box = clutter_actor_new (); - clutter_actor_set_layout_manager (box, layout); - - clutter_actor_add_child (box, - create_label ("Red: vertical swipes only")); - - clutter_actor_add_child (box, - create_label ("Blue: horizontal swipes only")); - - clutter_actor_add_child (box, - create_label ("Green: both")); - - offset = clutter_actor_get_height (stage) - - clutter_actor_get_height (box) - - 12.0; - - clutter_container_add_actor (CLUTTER_CONTAINER (stage), box); - clutter_actor_add_constraint (box, clutter_bind_constraint_new (stage, - CLUTTER_BIND_X, - 12.0)); - clutter_actor_add_constraint (box, clutter_bind_constraint_new (stage, - CLUTTER_BIND_Y, - offset)); - } - - clutter_actor_show (stage); - - clutter_test_main (); - - return EXIT_SUCCESS; -} - -G_MODULE_EXPORT const char * -test_swipe_action_describe (void) -{ - return "Swipe gesture recognizer."; -} diff --git a/src/tests/clutter/interactive/test-text-field.c b/src/tests/clutter/interactive/test-text-field.c deleted file mode 100644 index a145b6758..000000000 --- a/src/tests/clutter/interactive/test-text-field.c +++ /dev/null @@ -1,339 +0,0 @@ -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -gint -test_text_field_main (gint argc, - gchar **argv); - -const char * -test_text_field_describe (void); - -static void -on_entry_activate (ClutterText *text, - gpointer data) -{ - g_print ("Text activated: %s (cursor: %d, selection at: %d)\n", - clutter_text_get_text (text), - clutter_text_get_cursor_position (text), - clutter_text_get_selection_bound (text)); -} - -#define is_hex_digit(c) (((c) >= '0' && (c) <= '9') || \ - ((c) >= 'a' && (c) <= 'f') || \ - ((c) >= 'A' && (c) <= 'F')) -#define to_hex_digit(c) (((c) <= '9') ? (c) - '0' : ((c) & 7) + 9) - -static gboolean -on_captured_event (ClutterText *text, - ClutterEvent *event, - gpointer dummy G_GNUC_UNUSED) -{ - gboolean is_unicode_mode = FALSE; - gunichar c; - guint keyval; - - if (event->type != CLUTTER_KEY_PRESS) - return FALSE; - - is_unicode_mode = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (text), - "unicode-mode")); - - c = clutter_event_get_key_unicode (event); - keyval = clutter_event_get_key_symbol (event); - if (keyval == CLUTTER_KEY_U) - { - if (is_unicode_mode) - { - GString *str = g_object_get_data (G_OBJECT (text), "unicode-str"); - - clutter_text_set_preedit_string (text, NULL, NULL, 0); - - g_object_set_data (G_OBJECT (text), "unicode-mode", - GINT_TO_POINTER (FALSE)); - g_object_set_data (G_OBJECT (text), "unicode-str", - NULL); - - g_string_free (str, TRUE); - - return FALSE; - } - - if (clutter_event_has_control_modifier (event)) - { - PangoAttrList *attrs; - PangoAttribute *a; - GString *str = g_string_sized_new (5); - - g_string_append (str, "u"); - - g_object_set_data (G_OBJECT (text), - "unicode-mode", - GINT_TO_POINTER (TRUE)); - g_object_set_data (G_OBJECT (text), - "unicode-str", - str); - - attrs = pango_attr_list_new (); - - a = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); - a->start_index = 0; - a->end_index = str->len; - pango_attr_list_insert (attrs, a); - - clutter_text_set_preedit_string (text, str->str, attrs, str->len); - - pango_attr_list_unref (attrs); - - return TRUE; - } - - return FALSE; - } - else if (is_unicode_mode && is_hex_digit (c)) - { - GString *str = g_object_get_data (G_OBJECT (text), "unicode-str"); - PangoAttrList *attrs; - PangoAttribute *a; - gchar buf[8]; - gsize len; - - len = g_unichar_to_utf8 (c, buf); - buf[len] = '\0'; - - g_string_append (str, buf); - - g_print ("added '%s' to '%s' (len:%d)\n", - buf, - str->str, - (int) str->len); - - attrs = pango_attr_list_new (); - - a = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); - a->start_index = 0; - a->end_index = str->len; - pango_attr_list_insert (attrs, a); - - clutter_text_set_preedit_string (text, str->str, attrs, str->len); - - pango_attr_list_unref (attrs); - - return TRUE; - } - else if (is_unicode_mode && (keyval == CLUTTER_KEY_BackSpace)) - { - GString *str = g_object_get_data (G_OBJECT (text), "unicode-str"); - PangoAttrList *attrs; - PangoAttribute *a; - - g_string_truncate (str, str->len - 1); - - attrs = pango_attr_list_new (); - - a = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); - a->start_index = 0; - a->end_index = str->len; - pango_attr_list_insert (attrs, a); - - clutter_text_set_preedit_string (text, str->str, attrs, str->len); - - pango_attr_list_unref (attrs); - - return TRUE; - } - else if (is_unicode_mode && - (keyval == CLUTTER_KEY_Return || - keyval == CLUTTER_KEY_KP_Enter || - keyval == CLUTTER_KEY_ISO_Enter || - keyval == CLUTTER_KEY_KP_Space)) - { - GString *str = g_object_get_data (G_OBJECT (text), "unicode-str"); - const gchar *contents = clutter_text_get_text (text); - gunichar uchar = 0; - gchar ch; - gint i; - - clutter_text_set_preedit_string (text, NULL, NULL, 0); - - g_object_set_data (G_OBJECT (text), "unicode-mode", - GINT_TO_POINTER (FALSE)); - g_object_set_data (G_OBJECT (text), "unicode-str", - NULL); - - for (i = 0; i < str->len; i++) - { - ch = str->str[i]; - - if (is_hex_digit (ch)) - uchar += ((gunichar) to_hex_digit (ch) << ((4 - i) * 4)); - } - - g_assert (g_unichar_validate (uchar)); - - g_string_overwrite (str, 0, contents); - g_string_insert_unichar (str, - clutter_text_get_cursor_position (text), - uchar); - - i = clutter_text_get_cursor_position (text); - clutter_text_set_text (text, str->str); - - if (i >= 0) - i += 1; - else - i = -1; - - clutter_text_set_cursor_position (text, i); - clutter_text_set_selection_bound (text, i); - - g_string_free (str, TRUE); - - return TRUE; - } - else - return FALSE; -} - -static ClutterActor * -create_label (const ClutterColor *color, - const gchar *text) -{ - ClutterActor *retval = clutter_text_new (); - - clutter_text_set_color (CLUTTER_TEXT (retval), color); - clutter_text_set_markup (CLUTTER_TEXT (retval), text); - clutter_text_set_editable (CLUTTER_TEXT (retval), FALSE); - clutter_text_set_selectable (CLUTTER_TEXT (retval), FALSE); - clutter_text_set_single_line_mode (CLUTTER_TEXT (retval), TRUE); - clutter_text_set_ellipsize (CLUTTER_TEXT (retval), PANGO_ELLIPSIZE_END); - - return retval; -} - -static ClutterActor * -create_entry (const ClutterColor *color, - const gchar *text, - PangoAttrList *attrs, - gunichar password_char, - gint max_length) -{ - ClutterActor *retval = clutter_text_new_full (NULL, text, color); - ClutterColor selection = { 0, }; - ClutterColor selected_text = { 0x00, 0x00, 0xff, 0xff }; - - clutter_actor_set_reactive (retval, TRUE); - - clutter_color_darken (color, &selection); - - clutter_text_set_editable (CLUTTER_TEXT (retval), TRUE); - clutter_text_set_selectable (CLUTTER_TEXT (retval), TRUE); - clutter_text_set_activatable (CLUTTER_TEXT (retval), TRUE); - clutter_text_set_single_line_mode (CLUTTER_TEXT (retval), TRUE); - clutter_text_set_password_char (CLUTTER_TEXT (retval), password_char); - clutter_text_set_cursor_color (CLUTTER_TEXT (retval), &selection); - clutter_text_set_max_length (CLUTTER_TEXT (retval), max_length); - clutter_text_set_selected_text_color (CLUTTER_TEXT (retval), &selected_text); - clutter_actor_set_background_color (retval, CLUTTER_COLOR_LightGray); - if (attrs) - clutter_text_set_attributes (CLUTTER_TEXT (retval), attrs); - - g_signal_connect (retval, "activate", - G_CALLBACK (on_entry_activate), - NULL); - g_signal_connect (retval, "captured-event", - G_CALLBACK (on_captured_event), - NULL); - - return retval; -} - -G_MODULE_EXPORT gint -test_text_field_main (gint argc, - gchar **argv) -{ - ClutterActor *stage; - ClutterActor *box, *label, *entry; - ClutterLayoutManager *grid; - PangoAttrList *entry_attrs; - - clutter_test_init (&argc, &argv); - - stage = clutter_test_get_stage (); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Text Fields"); - clutter_actor_set_background_color (stage, CLUTTER_COLOR_Black); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - - grid = clutter_grid_layout_new (); - clutter_grid_layout_set_column_spacing (CLUTTER_GRID_LAYOUT (grid), 6); - clutter_grid_layout_set_row_spacing (CLUTTER_GRID_LAYOUT (grid), 6); - - box = clutter_actor_new (); - clutter_actor_set_layout_manager (box, grid); - clutter_actor_add_constraint (box, clutter_bind_constraint_new (stage, CLUTTER_BIND_WIDTH, -24.0)); - clutter_actor_add_constraint (box, clutter_bind_constraint_new (stage, CLUTTER_BIND_HEIGHT, -24.0)); - clutter_actor_set_position (box, 12, 12); - clutter_actor_add_child (stage, box); - - label = create_label (CLUTTER_COLOR_White, "Input field:"); - g_object_set (label, "min-width", 150.0, NULL); - clutter_actor_add_child (box, label); - clutter_layout_manager_child_set (grid, CLUTTER_CONTAINER (box), label, - "row", 0, - "column", 0, - "x-expand", FALSE, - "y-expand", FALSE, - NULL); - - entry_attrs = pango_attr_list_new (); - pango_attr_list_insert (entry_attrs, pango_attr_underline_new (PANGO_UNDERLINE_ERROR)); - pango_attr_list_insert (entry_attrs, pango_attr_underline_color_new (65535, 0, 0)); - entry = create_entry (CLUTTER_COLOR_Black, "somme misspeeled textt", entry_attrs, 0, 0); - clutter_actor_add_child (box, entry); - clutter_layout_manager_child_set (grid, CLUTTER_CONTAINER (box), entry, - "row", 0, - "column", 1, - "x-expand", TRUE, - "x-fill", TRUE, - "y-expand", FALSE, - NULL); - clutter_actor_grab_key_focus (entry); - - label = create_label (CLUTTER_COLOR_White, "A very long password field:"); - clutter_actor_add_child (box, label); - clutter_layout_manager_child_set (grid, CLUTTER_CONTAINER (box), label, - "row", 1, - "column", 0, - "x-expand", FALSE, - "y-expand", FALSE, - NULL); - - entry = create_entry (CLUTTER_COLOR_Black, "password", NULL, '*', 8); - clutter_actor_add_child (box, entry); - clutter_layout_manager_child_set (grid, CLUTTER_CONTAINER (box), entry, - "row", 1, - "column", 1, - "x-expand", TRUE, - "x-fill", TRUE, - "y-expand", FALSE, - NULL); - - clutter_actor_show (stage); - - clutter_test_main (); - - return EXIT_SUCCESS; -} - -G_MODULE_EXPORT const char * -test_text_field_describe (void) -{ - return -"Text actor single-line and password mode support\n" -"\n" -"This test checks the :single-line-mode and :password-char properties of\n" -"the ClutterText actor, plus the password hint feature and the :max-length\n" -"property."; -} diff --git a/src/tests/clutter/interactive/test-text.c b/src/tests/clutter/interactive/test-text.c deleted file mode 100644 index 308482d73..000000000 --- a/src/tests/clutter/interactive/test-text.c +++ /dev/null @@ -1,102 +0,0 @@ -#include - -#include -#include - -#include "tests/clutter-test-utils.h" - -#define FONT "Mono Bold 24px" - -static const gchar *runes = -"ᚠᛇᚻ᛫ᛒᛦᚦ᛫ᚠᚱᚩᚠᚢᚱ᛫ᚠᛁᚱᚪ᛫ᚷᛖᚻᚹᛦᛚᚳᚢᛗ\n" -"ᛋᚳᛖᚪᛚ᛫ᚦᛖᚪᚻ᛫ᛗᚪᚾᚾᚪ᛫ᚷᛖᚻᚹᛦᛚᚳ᛫ᛗᛁᚳᛚᚢᚾ᛫ᚻᛦᛏ᛫ᛞᚫᛚᚪᚾ\n" -"ᚷᛁᚠ᛫ᚻᛖ᛫ᚹᛁᛚᛖ᛫ᚠᚩᚱ᛫ᛞᚱᛁᚻᛏᚾᛖ᛫ᛞᚩᛗᛖᛋ᛫ᚻᛚᛇᛏᚪᚾ᛬\n"; - -gint -test_text_main (gint argc, - gchar **argv); - -const char * -test_text_describe (void); - -G_MODULE_EXPORT gint -test_text_main (gint argc, - gchar **argv) -{ - ClutterActor *stage; - ClutterActor *text, *text2; - ClutterColor text_color = { 0x33, 0xff, 0x33, 0xff }; - ClutterColor cursor_color = { 0xff, 0x33, 0x33, 0xff }; - ClutterTextBuffer *buffer; - - clutter_test_init (&argc, &argv); - - stage = clutter_test_get_stage (); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Text Editing"); - clutter_actor_set_background_color (stage, CLUTTER_COLOR_Black); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - - buffer = clutter_text_buffer_new_with_text ("·", -1); - - text = clutter_text_new_with_buffer (buffer); - clutter_text_set_font_name (CLUTTER_TEXT (text), FONT); - clutter_text_set_color (CLUTTER_TEXT (text), &text_color); - - clutter_container_add (CLUTTER_CONTAINER (stage), text, NULL); - clutter_actor_set_position (text, 40, 30); - clutter_actor_set_width (text, 1024); - clutter_text_set_line_wrap (CLUTTER_TEXT (text), TRUE); - - clutter_actor_set_reactive (text, TRUE); - clutter_stage_set_key_focus (CLUTTER_STAGE (stage), text); - - clutter_text_set_editable (CLUTTER_TEXT (text), TRUE); - clutter_text_set_selectable (CLUTTER_TEXT (text), TRUE); - clutter_text_set_cursor_color (CLUTTER_TEXT (text), &cursor_color); - clutter_text_set_selected_text_color (CLUTTER_TEXT (text), CLUTTER_COLOR_Blue); - - text2 = clutter_text_new_with_buffer (buffer); - clutter_text_set_color (CLUTTER_TEXT (text2), &text_color); - clutter_container_add (CLUTTER_CONTAINER (stage), text2, NULL); - clutter_actor_set_position (text2, 40, 300); - clutter_actor_set_width (text2, 1024); - clutter_text_set_line_wrap (CLUTTER_TEXT (text2), TRUE); - - clutter_actor_set_reactive (text2, TRUE); - clutter_text_set_editable (CLUTTER_TEXT (text2), TRUE); - clutter_text_set_selectable (CLUTTER_TEXT (text2), TRUE); - clutter_text_set_cursor_color (CLUTTER_TEXT (text2), &cursor_color); - clutter_text_set_selected_text_color (CLUTTER_TEXT (text2), CLUTTER_COLOR_Green); - - if (argv[1]) - { - GError *error = NULL; - gchar *utf8; - - g_file_get_contents (argv[1], &utf8, NULL, &error); - if (error) - { - utf8 = g_strconcat ("Unable to open '", argv[1], "':\n", - error->message, - NULL); - g_error_free (error); - } - - clutter_text_set_text (CLUTTER_TEXT (text), utf8); - } - else - clutter_text_set_text (CLUTTER_TEXT (text), runes); - - clutter_actor_set_size (stage, 1024, 768); - clutter_actor_show (stage); - - clutter_test_main (); - - return EXIT_SUCCESS; -} - -G_MODULE_EXPORT const char * -test_text_describe (void) -{ - return "Multi-line text editing."; -} diff --git a/src/tests/clutter/interactive/test-touch-events.c b/src/tests/clutter/interactive/test-touch-events.c deleted file mode 100644 index 6dd2befa3..000000000 --- a/src/tests/clutter/interactive/test-touch-events.c +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2012 Collabora Ltd. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU Lesser General Public License, - * version 2.1, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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 program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * Boston, MA 02111-1307, USA. - * - */ -#include -#include -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -#define STAGE_WIDTH 800 -#define STAGE_HEIGHT 550 -#define NUM_COLORS 10 -#define NUM_ACTORS 10 - -static GQueue events = G_QUEUE_INIT; -static GQueue all_events = G_QUEUE_INIT; -static gboolean new_surface = TRUE; - -static const ClutterColor static_colors[] = { - { 0xff, 0x00, 0x00, 0xff }, /* red */ - { 0x80, 0x00, 0x00, 0xff }, /* dark red */ - { 0x00, 0xff, 0x00, 0xff }, /* green */ - { 0x00, 0x80, 0x00, 0xff }, /* dark green */ - { 0x00, 0x00, 0xff, 0xff }, /* blue */ - { 0x00, 0x00, 0x80, 0xff }, /* dark blue */ - { 0x00, 0xff, 0xff, 0xff }, /* cyan */ - { 0x00, 0x80, 0x80, 0xff }, /* dark cyan */ - { 0xff, 0x00, 0xff, 0xff }, /* magenta */ - { 0xff, 0xff, 0x00, 0xff }, /* yellow */ -}; -static GHashTable *sequence_to_color = NULL; - -int -test_touch_events_main (int argc, char *argv[]); - -const char * -test_touch_events_describe (void); - -static void -draw_touch (ClutterEvent *event, - cairo_t *cr) -{ - ClutterEventSequence *sequence = clutter_event_get_event_sequence (event); - const ClutterColor *color; - - color = g_hash_table_lookup (sequence_to_color, sequence); - if (color == NULL) - { - color = &static_colors[g_random_int_range (0, NUM_COLORS)]; - g_hash_table_insert (sequence_to_color, (gpointer) sequence, (gpointer) color); - } - - cairo_set_source_rgba (cr, color->red / 255, - color->green / 255, - color->blue / 255, - color->alpha / 255); - cairo_arc (cr, event->touch.x, event->touch.y, 5, 0, 2 * G_PI); - cairo_fill (cr); -} - -static gboolean -draw_touches (ClutterCanvas *canvas, - cairo_t *cr, - int width, - int height) -{ - g_queue_foreach (new_surface ? &all_events : &events, (GFunc) draw_touch, cr); - g_queue_clear (&events); - - new_surface = FALSE; - - return TRUE; -} - -static gboolean -event_cb (ClutterActor *actor, ClutterEvent *event, ClutterActor *canvas) -{ - ClutterEvent *copy; - - if (event->type != CLUTTER_TOUCH_UPDATE) - return FALSE; - - copy = clutter_event_copy (event); - g_queue_push_tail (&events, copy); - g_queue_push_tail (&all_events, copy); - clutter_actor_queue_redraw (canvas); - - return TRUE; -} - -static gboolean -rect_event_cb (ClutterActor *actor, ClutterEvent *event, gpointer data) -{ - ClutterColor color; - - if (event->type != CLUTTER_TOUCH_BEGIN) - return FALSE; - - color = static_colors[g_random_int_range (0, NUM_COLORS)]; - clutter_actor_set_background_color (actor, &color); - - return TRUE; -} - -G_MODULE_EXPORT int -test_touch_events_main (int argc, char *argv[]) -{ - ClutterActor *stage, *canvas_actor; - ClutterContent *canvas; - int i; - - /* initialize Clutter */ - clutter_test_init (&argc, &argv); - - /* create a resizable stage */ - stage = clutter_test_get_stage (); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Touch events"); - clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT); - clutter_actor_set_reactive (stage, TRUE); - clutter_actor_show (stage); - - /* our 2D canvas, courtesy of Cairo */ - canvas = clutter_canvas_new (); - clutter_canvas_set_size (CLUTTER_CANVAS (canvas), STAGE_WIDTH, STAGE_HEIGHT); - g_signal_connect (canvas, "draw", G_CALLBACK (draw_touches), NULL); - - canvas_actor = g_object_new (CLUTTER_TYPE_ACTOR, - "content", canvas, - NULL); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), canvas_actor); - - g_signal_connect (stage, "event", G_CALLBACK (event_cb), canvas_actor); - - for (i = 0; i < NUM_ACTORS; i++) - { - gfloat size = STAGE_HEIGHT / NUM_ACTORS; - ClutterColor color = static_colors[i % NUM_COLORS]; - ClutterActor *rectangle = clutter_actor_new (); - - clutter_actor_set_background_color (rectangle, &color); - - /* Test that event delivery to actors work */ - g_signal_connect (rectangle, "event", G_CALLBACK (rect_event_cb), NULL); - - clutter_container_add_actor (CLUTTER_CONTAINER (stage), rectangle); - clutter_actor_set_size (rectangle, size, size); - clutter_actor_set_position (rectangle, 0, i * size); - clutter_actor_set_reactive (rectangle, TRUE); - } - - sequence_to_color = g_hash_table_new (NULL, NULL); - - clutter_test_main (); - - g_queue_foreach (&all_events, (GFunc) clutter_event_free, NULL); - g_queue_clear (&events); - g_queue_clear (&all_events); - g_hash_table_destroy (sequence_to_color); - - return EXIT_SUCCESS; -} - -G_MODULE_EXPORT const char * -test_touch_events_describe (void) -{ - return "Draw shapes based on touch events"; -} diff --git a/src/tests/clutter/interactive/wrapper.sh.in b/src/tests/clutter/interactive/wrapper.sh.in deleted file mode 100755 index 90aa4e1b6..000000000 --- a/src/tests/clutter/interactive/wrapper.sh.in +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -UNIT_TEST=$1 - -shift - -echo "Running ./test-interactive $UNIT_TEST $@" -echo "" -echo "NOTE: For debugging purposes, you can run this single test as follows:" -echo "$ libtool --mode=execute \\" -echo " gdb --eval-command=\"b `echo $UNIT_TEST|tr '-' '_'`_main\" \\" -echo " --args ./test-interactive $UNIT_TEST" - -@abs_builddir@/test-interactive $UNIT_TEST "$@" - diff --git a/src/tests/clutter/meson.build b/src/tests/clutter/meson.build deleted file mode 100644 index ae05ae064..000000000 --- a/src/tests/clutter/meson.build +++ /dev/null @@ -1,11 +0,0 @@ -clutter_tests_includepath = include_directories('.') -clutter_tests_includes = [ - tests_includepath, - clutter_tests_includepath, -] - -subdir('accessibility') -subdir('conform') -subdir('interactive') -subdir('micro-bench') -subdir('performance') diff --git a/src/tests/clutter/micro-bench/meson.build b/src/tests/clutter/micro-bench/meson.build deleted file mode 100644 index 7fa2a8fca..000000000 --- a/src/tests/clutter/micro-bench/meson.build +++ /dev/null @@ -1,31 +0,0 @@ -clutter_tests_micro_bench_c_args = [ - '-DG_DISABLE_SINGLE_INCLUDES', - '-DGLIB_DISABLE_DEPRECATION_WARNINGS', - '-DCOGL_DISABLE_DEPRECATION_WARNINGS', - '-DCLUTTER_DISABLE_DEPRECATION_WARNINGS', - '-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name()), -] -clutter_tests_micro_bench_c_args += clutter_debug_c_args - -clutter_tests_micro_bench_tests = [ - 'test-text', - 'test-picking', - 'test-text-perf', - 'test-random-text', - 'test-cogl-perf', -] - -foreach test : clutter_tests_micro_bench_tests - executable(test, - sources: [ - '@0@.c'.format(test), - clutter_test_utils, - ], - include_directories: clutter_includes, - c_args: clutter_tests_micro_bench_c_args, - dependencies: [ - libmutter_test_dep, - ], - install: false, - ) -endforeach diff --git a/src/tests/clutter/micro-bench/test-cogl-perf.c b/src/tests/clutter/micro-bench/test-cogl-perf.c deleted file mode 100644 index 3f3f29843..000000000 --- a/src/tests/clutter/micro-bench/test-cogl-perf.c +++ /dev/null @@ -1,150 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -#define STAGE_WIDTH 800 -#define STAGE_HEIGHT 600 - -typedef struct _TestState -{ - ClutterActor *stage; - int current_test; -} TestState; - -typedef void (*TestCallback) (TestState *state, - ClutterPaintContext *paint_context); - -static void -test_rectangles (TestState *state, - ClutterPaintContext *paint_context) -{ -#define RECT_WIDTH 5 -#define RECT_HEIGHT 5 - CoglFramebuffer *framebuffer = - clutter_paint_context_get_framebuffer (paint_context); - CoglContext *ctx = cogl_framebuffer_get_context (framebuffer); - int x; - int y; - CoglPipeline *pipeline; - - /* Should the rectangles be randomly positioned/colored/rotated? - * - * It could be good to develop equivalent GL and Cairo tests so we can - * have a sanity check for our Cogl performance. - * - * The color should vary to check that we correctly batch color changes - * The use of alpha should vary so we have a variation of which rectangles - * require blending. - * Should this be a random variation? - * It could be good to experiment with focibly enabling blending for - * rectangles that don't technically need it for the sake of extending - * batching. E.g. if you a long run of interleved rectangles with every - * other rectangle needing blending then it may be worth enabling blending - * for all the rectangles to avoid the state changes. - * The modelview should change between rectangles to check the software - * transform codepath. - * Should we group some rectangles under the same modelview? Potentially - * we could avoid software transform for long runs of rectangles with the - * same modelview. - * - */ - - pipeline = cogl_pipeline_new (ctx); - - for (y = 0; y < STAGE_HEIGHT; y += RECT_HEIGHT) - { - for (x = 0; x < STAGE_WIDTH; x += RECT_WIDTH) - { - cogl_framebuffer_push_matrix (framebuffer); - cogl_framebuffer_translate (framebuffer, x, y, 0); - cogl_framebuffer_rotate (framebuffer, 45, 0, 0, 1); - cogl_pipeline_set_color4f (pipeline, - 1, - (1.0f / STAGE_WIDTH) * y, - (1.0f / STAGE_HEIGHT) * x, - 1); - cogl_framebuffer_draw_rectangle (framebuffer, pipeline, - 0, 0, RECT_WIDTH, RECT_HEIGHT); - cogl_framebuffer_pop_matrix (framebuffer); - } - } - - for (y = 0; y < STAGE_HEIGHT; y += RECT_HEIGHT) - { - for (x = 0; x < STAGE_WIDTH; x += RECT_WIDTH) - { - cogl_framebuffer_push_matrix (framebuffer); - cogl_framebuffer_translate (framebuffer, x, y, 0); - cogl_framebuffer_rotate (framebuffer, 0, 0, 0, 1); - cogl_pipeline_set_color4f (pipeline, - 1, - (1.0f / STAGE_WIDTH) * x, - (1.0f / STAGE_HEIGHT) * y, - (1.0f / STAGE_WIDTH) * x); - cogl_framebuffer_draw_rectangle (framebuffer, pipeline, - 0, 0, RECT_WIDTH, RECT_HEIGHT); - cogl_framebuffer_pop_matrix (framebuffer); - } - } -} - -TestCallback tests[] = -{ - test_rectangles -}; - -static void -on_after_paint (ClutterActor *actor, - ClutterPaintContext *paint_context, - TestState *state) -{ - tests[state->current_test] (state, paint_context); -} - -static gboolean -queue_redraw (gpointer stage) -{ - clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); - - return TRUE; -} - -int -main (int argc, char *argv[]) -{ - TestState state; - ClutterActor *stage; - - g_setenv ("CLUTTER_VBLANK", "none", FALSE); - g_setenv ("CLUTTER_SHOW_FPS", "1", FALSE); - - clutter_test_init (&argc, &argv); - - state.current_test = 0; - - state.stage = stage = clutter_test_get_stage (); - - clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT); - clutter_actor_set_background_color (CLUTTER_ACTOR (stage), CLUTTER_COLOR_White); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl Performance Test"); - - /* We want continuous redrawing of the stage... */ - clutter_threads_add_idle (queue_redraw, stage); - - g_signal_connect (CLUTTER_STAGE (stage), "after-paint", G_CALLBACK (on_after_paint), &state); - - clutter_actor_show (stage); - - clutter_test_main (); - - clutter_actor_destroy (stage); - - return 0; -} - diff --git a/src/tests/clutter/micro-bench/test-picking.c b/src/tests/clutter/micro-bench/test-picking.c deleted file mode 100644 index 2e02671ba..000000000 --- a/src/tests/clutter/micro-bench/test-picking.c +++ /dev/null @@ -1,119 +0,0 @@ - -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -#define N_ACTORS 100 -#define N_EVENTS 5 - -static gboolean -motion_event_cb (ClutterActor *actor, ClutterEvent *event, gpointer user_data) -{ - return FALSE; -} - -static void -do_events (ClutterActor *stage) -{ - glong i; - static gdouble angle = 0; - - for (i = 0; i < N_EVENTS; i++) - { - angle += (2.0 * G_PI) / (double) N_ACTORS; - while (angle > G_PI * 2.0) - angle -= G_PI * 2.0; - - /* If we synthesized events, they would be motion compressed; - * calling get_actor_at_position() doesn't have that problem - */ - clutter_stage_get_actor_at_pos (CLUTTER_STAGE (stage), - CLUTTER_PICK_REACTIVE, - 256.0 + 206.0 * cos (angle), - 256.0 + 206.0 * sin (angle)); - } -} - -static void -on_after_paint (ClutterActor *stage, - ClutterPaintContext *paint_context, - gconstpointer *data) -{ - do_events (stage); -} - -static gboolean -queue_redraw (gpointer stage) -{ - clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); - - return TRUE; -} - -int -main (int argc, char **argv) -{ - glong i; - gdouble angle; - ClutterColor color = { 0x00, 0x00, 0x00, 0xff }; - ClutterActor *stage, *rect; - - g_setenv ("CLUTTER_VBLANK", "none", FALSE); - g_setenv ("CLUTTER_DEFAULT_FPS", "1000", FALSE); - g_setenv ("CLUTTER_SHOW_FPS", "1", FALSE); - - clutter_test_init (&argc, &argv); - - stage = clutter_test_get_stage (); - clutter_actor_set_size (stage, 512, 512); - clutter_actor_set_background_color (CLUTTER_ACTOR (stage), CLUTTER_COLOR_Black); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Picking"); - - printf ("Picking performance test with " - "%d actors and %d events per frame\n", - N_ACTORS, - N_EVENTS); - - for (i = N_ACTORS - 1; i >= 0; i--) - { - angle = ((2.0 * G_PI) / (double) N_ACTORS) * i; - - color.red = (1.0 - ABS ((MAX (0, MIN (N_ACTORS / 2.0 + 0, i))) / - (double) (N_ACTORS / 4.0) - 1.0)) * 255.0; - color.green = (1.0 - ABS ((MAX (0, MIN (N_ACTORS / 2.0 + 0, - fmod (i + (N_ACTORS / 3.0) * 2, N_ACTORS)))) / - (double) (N_ACTORS / 4) - 1.0)) * 255.0; - color.blue = (1.0 - ABS ((MAX (0, MIN (N_ACTORS / 2.0 + 0, - fmod ((i + (N_ACTORS / 3.0)), N_ACTORS)))) / - (double) (N_ACTORS / 4.0) - 1.0)) * 255.0; - - rect = clutter_actor_new (); - clutter_actor_set_background_color (rect, &color); - clutter_actor_set_size (rect, 100, 100); - clutter_actor_set_translation (rect, -50.f, -50.f, 0.f); - clutter_actor_set_position (rect, - 256 + 206 * cos (angle), - 256 + 206 * sin (angle)); - clutter_actor_set_reactive (rect, TRUE); - g_signal_connect (rect, "motion-event", - G_CALLBACK (motion_event_cb), NULL); - - clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); - } - - clutter_actor_show (stage); - - clutter_threads_add_idle (queue_redraw, stage); - - g_signal_connect (CLUTTER_STAGE (stage), "after-paint", G_CALLBACK (on_after_paint), NULL); - - clutter_test_main (); - - clutter_actor_destroy (stage); - - return 0; -} - - diff --git a/src/tests/clutter/micro-bench/test-random-text.c b/src/tests/clutter/micro-bench/test-random-text.c deleted file mode 100644 index c5612924f..000000000 --- a/src/tests/clutter/micro-bench/test-random-text.c +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -#define MAX_TEXT_LEN 10 -#define MIN_FONT_SIZE 10 -#define MAX_FONT_SIZE 30 - -static const char * const font_names[] = - { - "Sans", "Sans Italic", "Serif", "Serif Bold", "Times", "Monospace" - }; -#define FONT_NAME_COUNT 6 - -static gboolean -on_idle (gpointer data) -{ - ClutterActor *stage = CLUTTER_ACTOR (data); - int line_height = 0, xpos = 0, ypos = 0; - int stage_width = clutter_actor_get_width (stage); - int stage_height = clutter_actor_get_height (stage); - char text[MAX_TEXT_LEN + 1]; - char font_name[64]; - int i; - GList *children, *node; - static GTimer *timer = NULL; - static int frame_count = 0; - - /* Remove all of the children of the stage */ - children = clutter_container_get_children (CLUTTER_CONTAINER (stage)); - for (node = children; node; node = node->next) - clutter_container_remove_actor (CLUTTER_CONTAINER (stage), - CLUTTER_ACTOR (node->data)); - g_list_free (children); - - /* Fill the stage with new random labels */ - while (ypos < stage_height) - { - int text_len = rand () % MAX_TEXT_LEN + 1; - ClutterActor *label; - - for (i = 0; i < text_len; i++) - text[i] = rand () % (128 - 32) + 32; - text[text_len] = '\0'; - - sprintf (font_name, "%s %i", - font_names[rand () % FONT_NAME_COUNT], - rand () % (MAX_FONT_SIZE - MIN_FONT_SIZE) + MIN_FONT_SIZE); - - label = clutter_text_new_with_text (font_name, text); - - if (clutter_actor_get_height (label) > line_height) - line_height = clutter_actor_get_height (label); - - if (xpos + clutter_actor_get_width (label) > stage_width) - { - xpos = 0; - ypos += line_height; - line_height = 0; - } - - clutter_actor_set_position (label, xpos, ypos); - - clutter_container_add (CLUTTER_CONTAINER (stage), label, NULL); - - xpos += clutter_actor_get_width (label); - } - - if (timer == NULL) - timer = g_timer_new (); - else - { - if (++frame_count >= 10) - { - printf ("10 frames in %f seconds\n", - g_timer_elapsed (timer, NULL)); - g_timer_start (timer); - frame_count = 0; - } - } - - return TRUE; -} - -int -main (int argc, char *argv[]) -{ - ClutterActor *stage; - - clutter_test_init (&argc, &argv); - - stage = clutter_test_get_stage (); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Random Text"); - - clutter_actor_show (stage); - - clutter_threads_add_idle (on_idle, stage); - - clutter_test_main (); - - clutter_actor_destroy (stage); - - return 0; -} diff --git a/src/tests/clutter/micro-bench/test-text-perf.c b/src/tests/clutter/micro-bench/test-text-perf.c deleted file mode 100644 index 4f302870d..000000000 --- a/src/tests/clutter/micro-bench/test-text-perf.c +++ /dev/null @@ -1,190 +0,0 @@ -#include - -#include -#include - -#include "tests/clutter-test-utils.h" - -#define STAGE_WIDTH 800 -#define STAGE_HEIGHT 600 - -static int font_size; -static int n_chars; -static int rows, cols; - -static void -on_after_paint (ClutterActor *actor, - ClutterPaintContext *paint_context, - gconstpointer *data) -{ - static GTimer *timer = NULL; - static int fps = 0; - - if (!timer) - { - timer = g_timer_new (); - g_timer_start (timer); - } - - if (g_timer_elapsed (timer, NULL) >= 1) - { - printf ("fps=%d, strings/sec=%d, chars/sec=%d\n", - fps, - fps * rows * cols, - fps * rows * cols * n_chars); - g_timer_start (timer); - fps = 0; - } - - ++fps; -} - -static gboolean -queue_redraw (gpointer stage) -{ - clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); - - return G_SOURCE_CONTINUE; -} - -static gunichar -get_character (int ch) -{ - int total_letters = 0; - int i; - - static const struct - { - gunichar first_letter; - int n_letters; - } - ranges[] = - { - { 'a', 26 }, /* lower case letters */ - { 'A', 26 }, /* upper case letters */ - { '0', 10 }, /* digits */ - { 0x410, 0x40 }, /* cyrillic alphabet */ - { 0x3b1, 18 } /* greek alphabet */ - }; - - for (i = 0; i < G_N_ELEMENTS (ranges); i++) - total_letters += ranges[i].n_letters; - - ch %= total_letters; - - for (i = 0; i < G_N_ELEMENTS (ranges) - 1; i++) - if (ch < ranges[i].n_letters) - return ch + ranges[i].first_letter; - else - ch -= ranges[i].n_letters; - - return ch + ranges[i].first_letter; -} - -static ClutterActor * -create_label (void) -{ - ClutterColor label_color = { 0xff, 0xff, 0xff, 0xff }; - ClutterActor *label; - char *font_name; - GString *str; - int i; - - font_name = g_strdup_printf ("Monospace %dpx", font_size); - - str = g_string_new (NULL); - for (i = 0; i < n_chars; i++) - g_string_append_unichar (str, get_character (i)); - - label = clutter_text_new_with_text (font_name, str->str); - clutter_text_set_color (CLUTTER_TEXT (label), &label_color); - - g_free (font_name); - g_string_free (str, TRUE); - - return label; -} - -int -main (int argc, char *argv[]) -{ - ClutterActor *stage; - ClutterActor *label; - int w, h; - int row, col; - float scale = 1.0f; - - g_setenv ("CLUTTER_VBLANK", "none", FALSE); - g_setenv ("CLUTTER_DEFAULT_FPS", "1000", FALSE); - - clutter_test_init (&argc, &argv); - - if (argc != 3) - { - g_printerr ("Usage test-text-perf FONT_SIZE N_CHARS\n"); - exit (1); - } - - font_size = atoi (argv[1]); - n_chars = atoi (argv[2]); - - g_print ("Monospace %dpx, string length = %d\n", font_size, n_chars); - - stage = clutter_test_get_stage (); - clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT); - clutter_actor_set_background_color (CLUTTER_ACTOR (stage), CLUTTER_COLOR_Black); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Text Performance"); - - g_signal_connect (CLUTTER_STAGE (stage), "after-paint", G_CALLBACK (on_after_paint), NULL); - - label = create_label (); - w = clutter_actor_get_width (label); - h = clutter_actor_get_height (label); - - /* If the label is too big to fit on the stage then scale it so that - it will fit */ - if (w > STAGE_WIDTH || h > STAGE_HEIGHT) - { - float x_scale = STAGE_WIDTH / (float) w; - float y_scale = STAGE_HEIGHT / (float) h; - - if (x_scale < y_scale) - { - scale = x_scale; - cols = 1; - rows = STAGE_HEIGHT / (h * scale); - } - else - { - scale = y_scale; - cols = STAGE_WIDTH / (w * scale); - rows = 1; - } - - g_print ("Text scaled by %f to fit on the stage\n", scale); - } - else - { - cols = STAGE_WIDTH / w; - rows = STAGE_HEIGHT / h; - } - - clutter_actor_destroy (label); - - for (row=0; row - -#include -#include - -#include "tests/clutter-test-utils.h" - -#define STAGE_WIDTH 640 -#define STAGE_HEIGHT 480 - -#define COLS 18 -#define ROWS 20 - -static void -on_after_paint (ClutterActor *actor, - ClutterPaintContext *paint_context, - gconstpointer *data) -{ - static GTimer *timer = NULL; - static int fps = 0; - - if (!timer) - { - timer = g_timer_new (); - g_timer_start (timer); - } - - if (g_timer_elapsed (timer, NULL) >= 1) - { - printf ("fps: %d\n", fps); - g_timer_start (timer); - fps = 0; - } - - ++fps; -} - -static gboolean -queue_redraw (gpointer stage) -{ - clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); - - return G_SOURCE_CONTINUE; -} - -int -main (int argc, char *argv[]) -{ - ClutterActor *stage; - ClutterActor *group; - - g_setenv ("CLUTTER_VBLANK", "none", FALSE); - g_setenv ("CLUTTER_DEFAULT_FPS", "1000", FALSE); - - clutter_test_init (&argc, &argv); - - stage = clutter_test_get_stage (); - clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT); - clutter_actor_set_background_color (CLUTTER_ACTOR (stage), CLUTTER_COLOR_Black); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Text"); - - group = clutter_actor_new (); - clutter_actor_set_size (group, STAGE_WIDTH, STAGE_WIDTH); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), group); - - clutter_threads_add_idle (queue_redraw, stage); - - g_signal_connect (CLUTTER_STAGE (stage), "after-paint", G_CALLBACK (on_after_paint), NULL); - - { - gint row, col; - - for (row=0; row max - max = val - end - } - max - end - def val_min(key) - min=9999990 - @runs.each { |run| - val = @vals[key][run] - min = val if val and val < min - } - #min - 0 # this shows the relative noise in measurements better - end - def add_run(run) - @runs = @runs + [run] - end - def add_entry(run, name, val) - if !@vals[name] - @vals[name]=Hash.new - end - # check if there is an existing value, - # and perhaps have different behaviors - # associated with - @vals[name][run] = val.to_f - end - - def drawbg cr - cr.set_source_rgba(0.2, 0.2, 0.2, 1) - cr.paint - - i=0 - @runs.each { |run| - if i % 2 == 1 - cr.move_to 1.0 * i / @runs.length * (@width - @marginlx-@marginrx) + @marginlx, 0 * (@height - @marginy*2) + @marginy - cr.line_to 1.0 * i / @runs.length * (@width - @marginlx-@marginrx) + @marginlx, 1.0 * (@height - @marginy*2) + @marginy - cr.rel_line_to(1.0 / @runs.length * (@width - @marginlx-@marginrx), 0) - cr.rel_line_to(0, -(@height - @marginy*2)) - - cr.set_source_rgba([0.25,0.25,0.25,1]) - cr.fill - end - i+=1 - } - end - - def drawtext cr - i = 0 - @runs.each { |run| - y = i * 10 + 20 - while y > @height - @marginy - y = y - @height + @marginy + 10 - end - cr.move_to 1.0 * i / @runs.length * (@width - @marginlx-@marginrx) + @marginlx, y - - cr.set_source_rgba(0.6,0.6,0.6,1) - cr.show_text(run[0..6]) - i+=1 - } - end - - def draw_limits cr, key - cr.move_to @width - @marginrx + @rgap, 20 - cr.set_source_rgba(1.0, 1.0, 1.0, 1.0) - cr.show_text(" #{val_max(key)} ") - cr.move_to @width - @marginrx + @rgap, @height - @marginy - cr.show_text(" #{val_min(key)} ") - end - - def draw_val cr, key, valno - min = val_min(key) - max = val_max(key) - - cr.set_source_rgba(@colors[valno]) - cr.move_to(@width - @marginrx + @rgap, valno * 14 + @marginy + 20) - cr.show_text(key) - - cr.line_width = 2 - cr.new_path - - i = 0 - @runs.each { |run| - val = @vals[key][run] - if val - cr.line_to 1.0 * (i+0.5) / @runs.length * (@width - @marginlx-@marginrx) + @marginlx, - (1.0 - ((val-min) * 1.0 / (max - min))) * (@height - @marginy*2) + @marginy - end - i = i + 1 - } - cr.stroke - end - - def create_report - cairo_surface(@width, @height) { |cr| - drawbg cr - valno = 0 - @vals.each { |key, value| - draw_val cr, key, valno - valno += 1 - } - drawtext cr - cr.target.write_to_png("report.png") - - valno = 0 - @vals.each { |key, value| - cr.show_page - drawbg cr - draw_val cr, key, valno - drawtext cr - draw_limits cr, key - valno += 1 - } - } - end -end - -generator = Database.new - -items = File.open('jobs').each { |rev| - rev.strip! - generator.add_run(rev) - filename = "reports/" + rev; - if File.exist?(filename) - File.open(filename).each { |line| - if line =~ /^@ (.*):(.*)/ - generator.add_entry(rev, $1, $2) - end - } - end -} - -generator.create_report diff --git a/src/tests/clutter/performance/joblist b/src/tests/clutter/performance/joblist deleted file mode 100644 index ce046cc71..000000000 --- a/src/tests/clutter/performance/joblist +++ /dev/null @@ -1,27 +0,0 @@ -# This file lists the commits that we want to do retrospective testing -# of, aborting the retrospective testing and adjusting this file will -# add the commit range to be tested without having to redo the initial one -# thus allowing a sparse distributed range to first be tested, with -# detailed ranges added in later. - -master~500..master % 32 # every 32th commit, to provide context - -# various spans of commits around which "interesting things happen" - -#eeac7~1..985a4 -#6c6e93d~1..3142b15 -#0486c56..88b026 -#732eecf..8cfb158 -#b499696..b77d9a6 -#ba09e9c..7bdbbe6 -#b424bd7..c1878 -#bc58de4..d03c3a6 -#5640a6..a29623e -#6fd2663..6ec9c32 -# 012e4ab..1a8d577 # -#120d759~4..2235e70 - -# ef8be9e25ebe77fc63055191cc48af53d731c108 - actor: Use paint volumes to always queue clipped redraws - -# 5d16000 going up, and 3b78949 going down,. was a case of clipped redraws being broken - diff --git a/src/tests/clutter/performance/makejobs.rb b/src/tests/clutter/performance/makejobs.rb deleted file mode 100755 index 79499df9b..000000000 --- a/src/tests/clutter/performance/makejobs.rb +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env ruby - -# this ruby script generates a chronologically sorted - -res = "" -input = File.read(ARGV[0]) -input = input.gsub(/#.*/, "") -input.split("\n").each {|a| - if a =~ /([^ ]*)\.\.([^ ]*) %(.*)/ - res += `git log #{$1}..#{$2} | grep '^commit' | sed 's/commit //' | sed -n '0~#{$3}p'` - elsif a =~ /([^ ]*)\.\.([^ ]*)/ - res += `git log #{$1}..#{$2} | grep '^commit' | sed 's/commit //'` - else - res += `echo #{a}` - end -} - -all = `git log | grep '^commit' | sed 's/commit//' ` -all.split("\n").reverse.each {|a| - if res.match(a.strip) != nil - puts "#{a.strip}" - end -} - diff --git a/src/tests/clutter/performance/meson.build b/src/tests/clutter/performance/meson.build deleted file mode 100644 index 2c7637bad..000000000 --- a/src/tests/clutter/performance/meson.build +++ /dev/null @@ -1,34 +0,0 @@ -clutter_tests_performance_c_args = [ - '-DTESTS_DATA_DIR="@0@"'.format(clutter_tests_interactive_srcdir), - '-DG_DISABLE_SINGLE_INCLUDES', - '-DGLIB_DISABLE_DEPRECATION_WARNINGS', - '-DCOGL_DISABLE_DEPRECATION_WARNINGS', - '-DCLUTTER_DISABLE_DEPRECATION_WARNINGS', - '-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name()), -] - -clutter_tests_performance_c_args += clutter_debug_c_args - -clutter_tests_performance_tests = [ - 'test-picking', - 'test-text-perf', -] - -foreach test : clutter_tests_performance_tests - executable(test, - sources: [ - '@0@.c'.format(test), - 'test-common.h', - clutter_test_utils, - ], - include_directories: [ - clutter_includes, - clutter_tests_includes, - ], - c_args: clutter_tests_performance_c_args, - dependencies: [ - libmutter_test_dep, - ], - install: false, - ) -endforeach diff --git a/src/tests/clutter/performance/test-common.h b/src/tests/clutter/performance/test-common.h deleted file mode 100644 index ea4210ddc..000000000 --- a/src/tests/clutter/performance/test-common.h +++ /dev/null @@ -1,144 +0,0 @@ -#include -#include -#include -#include - -#include "tests/clutter-test-utils.h" - -static GTimer *testtimer = NULL; -static gint testframes = 0; -static float testmaxtime = 1.0; - -/* initialize environment to be suitable for fps testing */ -static inline void -clutter_perf_fps_init (void) -{ - /* Force not syncing to vblank, we want free-running maximum FPS */ - g_setenv ("vblank_mode", "0", FALSE); - g_setenv ("CLUTTER_VBLANK", "none", FALSE); - - /* also override internal default FPS */ - g_setenv ("CLUTTER_DEFAULT_FPS", "1000", FALSE); - - if (g_getenv ("CLUTTER_PERFORMANCE_TEST_DURATION")) - testmaxtime = atof(g_getenv("CLUTTER_PERFORMANCE_TEST_DURATION")); - else - testmaxtime = 10.0; - - g_random_set_seed (12345678); -} - -static void perf_stage_after_paint_cb (ClutterStage *stage, - ClutterPaintContext *paint_context, - gpointer *data); -static gboolean perf_fake_mouse_cb (gpointer stage); - -static inline void -clutter_perf_fps_start (ClutterStage *stage) -{ - g_signal_connect (stage, "after-paint", G_CALLBACK (perf_stage_after_paint_cb), NULL); -} - -static inline void -clutter_perf_fake_mouse (ClutterStage *stage) -{ - clutter_threads_add_timeout (1000/60, perf_fake_mouse_cb, stage); -} - -static inline void -clutter_perf_fps_report (const gchar *id) -{ - g_print ("\n@ %s: %.2f fps \n", - id, testframes / g_timer_elapsed (testtimer, NULL)); -} - -static void -perf_stage_after_paint_cb (ClutterStage *stage, - ClutterPaintContext *paint_context, - gpointer *data) -{ - if (!testtimer) - testtimer = g_timer_new (); - testframes ++; - if (g_timer_elapsed (testtimer, NULL) > testmaxtime) - { - clutter_test_quit (); - } -} - -static void wrap (gfloat *value, gfloat min, gfloat max) -{ - if (*value > max) - *value = min; - else if (*value < min) - *value = max; -} - -static gboolean perf_fake_mouse_cb (gpointer stage) -{ - ClutterEvent *event = clutter_event_new (CLUTTER_MOTION); - static ClutterInputDevice *device = NULL; - int i; - static float x = 0.0; - static float y = 0.0; - static float xd = 0.0; - static float yd = 0.0; - static gboolean inited = FALSE; - - gfloat w, h; - - if (!inited) /* XXX: - force clutter to do handle our motion events, - by forcibly updating the input device's state - this should be possible to do in a better - manner in the future, a versioning check - will have to be added when this is possible - without a hack... and the means to do the - hack is deprecated - */ - { - ClutterEvent *event2 = clutter_event_new (CLUTTER_ENTER); - ClutterBackend *backend = clutter_get_default_backend (); - ClutterSeat *seat = clutter_backend_get_default_seat (backend); - - device = clutter_seat_get_pointer (seat); - - event2->crossing.stage = stage; - event2->crossing.source = stage; - event2->crossing.x = 10; - event2->crossing.y = 10; - event2->crossing.related = NULL; - - clutter_event_set_device (event2, device); - - clutter_event_put (event2); - clutter_event_free (event2); - inited = TRUE; - } - - clutter_actor_get_size (stage, &w, &h); - event->motion.stage = stage; - clutter_event_set_device (event, device); - - /* called about every 60fps, and do 10 picks per stage */ - for (i = 0; i < 10; i++) - { - event->motion.x = x; - event->motion.y = y; - - clutter_event_put (event); - - x += xd; - y += yd; - xd += g_random_double_range (-0.1, 0.1); - yd += g_random_double_range (-0.1, 0.1); - - wrap (&x, 0, w); - wrap (&y, 0, h); - - xd = CLAMP(xd, -1.3, 1.3); - yd = CLAMP(yd, -1.3, 1.3); - } - clutter_event_free (event); - return G_SOURCE_CONTINUE; -} diff --git a/src/tests/clutter/performance/test-picking.c b/src/tests/clutter/performance/test-picking.c deleted file mode 100644 index a65132559..000000000 --- a/src/tests/clutter/performance/test-picking.c +++ /dev/null @@ -1,109 +0,0 @@ - -#include -#include -#include -#include "test-common.h" - -#define N_ACTORS 100 -#define N_EVENTS 5 - -static gint n_actors = N_ACTORS; -static gint n_events = N_EVENTS; - -static gboolean -motion_event_cb (ClutterActor *actor, ClutterEvent *event, gpointer user_data) -{ - return FALSE; -} - -static void -do_events (ClutterActor *stage) -{ - glong i; - static gdouble angle = 0; - - for (i = 0; i < n_events; i++) - { - angle += (2.0 * G_PI) / (gdouble)n_actors; - while (angle > G_PI * 2.0) - angle -= G_PI * 2.0; - - /* If we synthesized events, they would be motion compressed; - * calling get_actor_at_position() doesn't have that problem - */ - clutter_stage_get_actor_at_pos (CLUTTER_STAGE (stage), - CLUTTER_PICK_REACTIVE, - 256.0 + 206.0 * cos (angle), - 256.0 + 206.0 * sin (angle)); - } -} - -static gboolean queue_redraw (gpointer data) -{ - ClutterActor *stage = CLUTTER_ACTOR (data); - clutter_actor_queue_redraw (stage); - do_events (stage); - return TRUE; -} - -int -main (int argc, char **argv) -{ - glong i; - gdouble angle; - ClutterColor color = { 0x00, 0x00, 0x00, 0xff }; - ClutterActor *stage, *rect; - - clutter_perf_fps_init (); - - clutter_test_init (&argc, &argv); - - stage = clutter_test_get_stage (); - clutter_actor_set_size (stage, 512, 512); - clutter_actor_set_background_color (CLUTTER_ACTOR (stage), CLUTTER_COLOR_Black); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Picking Performance"); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - - printf ("Picking performance test with " - "%d actors and %d events per frame\n", - n_actors, - n_events); - - for (i = n_actors - 1; i >= 0; i--) - { - angle = ((2.0 * G_PI) / (gdouble) n_actors) * i; - - color.red = (1.0 - ABS ((MAX (0, MIN (n_actors/2.0 + 0, i))) / - (gdouble)(n_actors/4.0) - 1.0)) * 255.0; - color.green = (1.0 - ABS ((MAX (0, MIN (n_actors/2.0 + 0, - fmod (i + (n_actors/3.0)*2, n_actors)))) / - (gdouble)(n_actors/4) - 1.0)) * 255.0; - color.blue = (1.0 - ABS ((MAX (0, MIN (n_actors/2.0 + 0, - fmod ((i + (n_actors/3.0)), n_actors)))) / - (gdouble)(n_actors/4.0) - 1.0)) * 255.0; - - rect = clutter_actor_new (); - clutter_actor_set_background_color (rect, &color); - clutter_actor_set_size (rect, 100, 100); - clutter_actor_set_translation (rect, -50.f, -50.f, 0.f); - clutter_actor_set_position (rect, - 256 + 206 * cos (angle), - 256 + 206 * sin (angle)); - clutter_actor_set_reactive (rect, TRUE); - g_signal_connect (rect, "motion-event", - G_CALLBACK (motion_event_cb), NULL); - - clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); - } - - clutter_actor_show (stage); - - clutter_perf_fps_start (CLUTTER_STAGE (stage)); - clutter_threads_add_idle (queue_redraw, stage); - clutter_test_main (); - clutter_perf_fps_report ("test-picking"); - - return 0; -} - - diff --git a/src/tests/clutter/performance/test-text-perf.c b/src/tests/clutter/performance/test-text-perf.c deleted file mode 100644 index bce727f38..000000000 --- a/src/tests/clutter/performance/test-text-perf.c +++ /dev/null @@ -1,166 +0,0 @@ -#include - -#include -#include -#include "test-common.h" - -#define STAGE_WIDTH 800 -#define STAGE_HEIGHT 600 - -static int font_size; -static int n_chars; -static int rows, cols; - -static gboolean -queue_redraw (gpointer stage) -{ - clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); - - return G_SOURCE_CONTINUE; -} - -static gunichar -get_character (int ch) -{ - int total_letters = 0; - int i; - - static const struct - { - gunichar first_letter; - int n_letters; - } - ranges[] = - { - { 'a', 26 }, /* lower case letters */ - { 'A', 26 }, /* upper case letters */ - { '0', 10 }, /* digits */ - { 0x410, 0x40 }, /* cyrillic alphabet */ - { 0x3b1, 18 } /* greek alphabet */ - }; - - for (i = 0; i < G_N_ELEMENTS (ranges); i++) - total_letters += ranges[i].n_letters; - - ch %= total_letters; - - for (i = 0; i < G_N_ELEMENTS (ranges) - 1; i++) - if (ch < ranges[i].n_letters) - return ch + ranges[i].first_letter; - else - ch -= ranges[i].n_letters; - - return ch + ranges[i].first_letter; -} - -static ClutterActor * -create_label (void) -{ - ClutterColor label_color = { 0xff, 0xff, 0xff, 0xff }; - ClutterActor *label; - char *font_name; - GString *str; - int i; - - font_name = g_strdup_printf ("Monospace %dpx", font_size); - - str = g_string_new (NULL); - for (i = 0; i < n_chars; i++) - g_string_append_unichar (str, get_character (i)); - - label = clutter_text_new_with_text (font_name, str->str); - clutter_text_set_color (CLUTTER_TEXT (label), &label_color); - - g_free (font_name); - g_string_free (str, TRUE); - - return label; -} - -int -main (int argc, char *argv[]) -{ - ClutterActor *stage; - ClutterColor stage_color = { 0x00, 0x00, 0x00, 0xff }; - ClutterActor *label; - int w, h; - int row, col; - float scale = 1.0f; - - clutter_perf_fps_init (); - - clutter_test_init (&argc, &argv); - - if (argc != 3) - { - //g_printerr ("Usage test-text-perf FONT_SIZE N_CHARS\n"); - //exit (1); - font_size = 30; - n_chars = 400; - } - else - { - font_size = atoi (argv[1]); - n_chars = atoi (argv[2]); - } - - g_print ("Monospace %dpx, string length = %d\n", font_size, n_chars); - - stage = clutter_test_get_stage (); - clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT); - clutter_actor_set_background_color (CLUTTER_ACTOR (stage), &stage_color); - clutter_stage_set_title (CLUTTER_STAGE (stage), "Text Performance"); - g_signal_connect (stage, "destroy", G_CALLBACK (clutter_test_quit), NULL); - - label = create_label (); - w = clutter_actor_get_width (label); - h = clutter_actor_get_height (label); - - /* If the label is too big to fit on the stage then scale it so that - it will fit */ - if (w > STAGE_WIDTH || h > STAGE_HEIGHT) - { - float x_scale = STAGE_WIDTH / (float) w; - float y_scale = STAGE_HEIGHT / (float) h; - - if (x_scale < y_scale) - { - scale = x_scale; - cols = 1; - rows = STAGE_HEIGHT / (h * scale); - } - else - { - scale = y_scale; - cols = STAGE_WIDTH / (w * scale); - rows = 1; - } - - g_print ("Text scaled by %f to fit on the stage\n", scale); - } - else - { - cols = STAGE_WIDTH / w; - rows = STAGE_HEIGHT / h; - } - - clutter_actor_destroy (label); - - for (row=0; row -#include - -static inline ClutterActor * -clutter_test_utils_create_texture_from_file (const char *filename, - GError **error) -{ - g_autoptr (ClutterContent) image = NULL; - g_autoptr (GdkPixbuf) pixbuf = NULL; - - pixbuf = gdk_pixbuf_new_from_file (filename, error); - if (!pixbuf) - return NULL; - - image = clutter_image_new (); - if (!clutter_image_set_data (CLUTTER_IMAGE (image), - gdk_pixbuf_get_pixels (pixbuf), - gdk_pixbuf_get_has_alpha (pixbuf) - ? COGL_PIXEL_FORMAT_RGBA_8888 - : COGL_PIXEL_FORMAT_RGB_888, - gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf), - gdk_pixbuf_get_rowstride (pixbuf), - error)) - return NULL; - - return g_object_new (CLUTTER_TYPE_ACTOR, - "content", image, - NULL); -} diff --git a/src/tests/headless-start-test.c b/src/tests/headless-start-test.c deleted file mode 100644 index 85f1b8ee2..000000000 --- a/src/tests/headless-start-test.c +++ /dev/null @@ -1,180 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 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 . - */ - -#include "config.h" - -#include "backends/meta-monitor-manager-private.h" -#include "backends/meta-crtc.h" -#include "backends/meta-output.h" -#include "core/display-private.h" -#include "meta-test/meta-context-test.h" -#include "tests/meta-monitor-manager-test.h" - -static void -meta_test_headless_start (void) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - GList *gpus; - MetaGpu *gpu; - - gpus = meta_backend_get_gpus (backend); - g_assert_cmpint ((int) g_list_length (gpus), ==, 1); - - gpu = gpus->data; - g_assert_null (meta_gpu_get_modes (gpu)); - g_assert_null (meta_gpu_get_outputs (gpu)); - g_assert_null (meta_gpu_get_crtcs (gpu)); - g_assert_null (monitor_manager->monitors); - g_assert_null (monitor_manager->logical_monitors); - - g_assert_cmpint (monitor_manager->screen_width, - ==, - META_MONITOR_MANAGER_MIN_SCREEN_WIDTH); - g_assert_cmpint (monitor_manager->screen_height, - ==, - META_MONITOR_MANAGER_MIN_SCREEN_HEIGHT); -} - -static void -meta_test_headless_monitor_getters (void) -{ - MetaDisplay *display; - int index; - - display = meta_get_display (); - - index = meta_display_get_monitor_index_for_rect (display, - &(MetaRectangle) { 0 }); - g_assert_cmpint (index, ==, -1); -} - -static void -meta_test_headless_monitor_connect (void) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerTest *monitor_manager_test = - META_MONITOR_MANAGER_TEST (monitor_manager); - MetaMonitorTestSetup *test_setup; - MetaCrtcMode **modes; - g_autoptr (MetaCrtcModeInfo) crtc_mode_info = NULL; - MetaCrtcMode *crtc_mode; - MetaGpu *gpu; - MetaCrtc *crtc; - MetaCrtc **possible_crtcs; - g_autoptr (MetaOutputInfo) output_info = NULL; - MetaOutput *output; - GList *logical_monitors; - ClutterActor *stage; - - test_setup = g_new0 (MetaMonitorTestSetup, 1); - - crtc_mode_info = meta_crtc_mode_info_new (); - crtc_mode_info->width = 1024; - crtc_mode_info->height = 768; - crtc_mode_info->refresh_rate = 60.0; - - crtc_mode = g_object_new (META_TYPE_CRTC_MODE, - "id", (uint64_t) 1, - "info", crtc_mode_info, - NULL); - test_setup->modes = g_list_append (NULL, crtc_mode); - - gpu = META_GPU (meta_backend_get_gpus (meta_get_backend ())->data); - crtc = g_object_new (META_TYPE_CRTC_TEST, - "id", (uint64_t) 1, - "gpu", gpu, - NULL); - test_setup->crtcs = g_list_append (NULL, crtc); - - modes = g_new0 (MetaCrtcMode *, 1); - modes[0] = crtc_mode; - - possible_crtcs = g_new0 (MetaCrtc *, 1); - possible_crtcs[0] = g_list_first (test_setup->crtcs)->data; - - output_info = meta_output_info_new (); - - output_info->name = g_strdup ("DP-1"); - output_info->vendor = g_strdup ("MetaProduct's Inc."); - output_info->product = g_strdup ("MetaMonitor"); - output_info->serial = g_strdup ("0x987654"); - output_info->preferred_mode = modes[0]; - output_info->n_modes = 1; - output_info->modes = modes; - output_info->n_possible_crtcs = 1; - output_info->possible_crtcs = possible_crtcs; - output_info->connector_type = META_CONNECTOR_TYPE_DisplayPort; - - output = g_object_new (META_TYPE_OUTPUT_TEST, - "id", (uint64_t) 1, - "gpu", gpu, - "info", output_info, - NULL); - - test_setup->outputs = g_list_append (NULL, output); - - meta_monitor_manager_test_emulate_hotplug (monitor_manager_test, test_setup); - - logical_monitors = - meta_monitor_manager_get_logical_monitors (monitor_manager); - g_assert_cmpint (g_list_length (logical_monitors), ==, 1); - - g_assert_cmpint (monitor_manager->screen_width, ==, 1024); - g_assert_cmpint (monitor_manager->screen_height, ==, 768); - - stage = meta_backend_get_stage (backend); - g_assert_cmpint (clutter_actor_get_width (stage), ==, 1024); - g_assert_cmpint (clutter_actor_get_height (stage), ==, 768); -} - -static MetaMonitorTestSetup * -create_headless_test_setup (void) -{ - return g_new0 (MetaMonitorTestSetup, 1); -} - -static void -init_tests (void) -{ - meta_monitor_manager_test_init_test_setup (create_headless_test_setup); - - g_test_add_func ("/headless-start/start", meta_test_headless_start); - g_test_add_func ("/headless-start/monitor-getters", - meta_test_headless_monitor_getters); - g_test_add_func ("/headless-start/connect", - meta_test_headless_monitor_connect); -} - -int -main (int argc, char *argv[]) -{ - g_autoptr (MetaContext) context = NULL; - - context = meta_create_test_context (META_CONTEXT_TEST_TYPE_NESTED, - META_CONTEXT_TEST_FLAG_NO_X11); - g_assert (meta_context_configure (context, &argc, &argv, NULL)); - - init_tests (); - - return meta_context_test_run_tests (META_CONTEXT_TEST (context)); -} diff --git a/src/tests/kms-utils-unit-tests.c b/src/tests/kms-utils-unit-tests.c deleted file mode 100644 index 40b768b3e..000000000 --- a/src/tests/kms-utils-unit-tests.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright (C) 2021 Akihiko Odaki - * - * 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 . - */ - - -#include "config.h" - -#include - -#include "backends/native/meta-kms-utils.h" -#include "backends/native/meta-kms-update.h" - -typedef struct { - drmModeModeInfo drm_mode; - float expected_refresh_rate; -} RefreshRateTestCase; - -static const RefreshRateTestCase refresh_rate_test_cases[] = { - /* "cvt 640 480" */ - { - .drm_mode = { - .clock = 23975, - .hdisplay = 640, - .hsync_start = 664, - .hsync_end = 720, - .htotal = 800, - .vdisplay = 480, - .vsync_start = 483, - .vsync_end = 487, - .vtotal = 500, - .vscan = 0, - .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC, - }, - .expected_refresh_rate = 59.9375, - }, - - /* "cvt 640 480" with htotal 0 */ - { - .drm_mode = { - .clock = 23975, - .hdisplay = 640, - .hsync_start = 664, - .hsync_end = 720, - .htotal = 0, - .vdisplay = 480, - .vsync_start = 483, - .vsync_end = 487, - .vtotal = 500, - .vscan = 0, - .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC, - }, - .expected_refresh_rate = 0.0, - }, - - /* "cvt 640 480" with vtotal 0 */ - { - .drm_mode = { - .clock = 23975, - .hdisplay = 640, - .hsync_start = 664, - .hsync_end = 720, - .htotal = 800, - .vdisplay = 480, - .vsync_start = 483, - .vsync_end = 487, - .vtotal = 0, - .vscan = 0, - .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC, - }, - .expected_refresh_rate = 0.0, - }, - - /* "cvt 320 240" with doubled clock and vscan 2 */ - { - .drm_mode = { - .clock = 12062, - .hdisplay = 320, - .hsync_start = 336, - .hsync_end = 360, - .htotal = 400, - .vdisplay = 240, - .vsync_start = 243, - .vsync_end = 247, - .vtotal = 252, - .vscan = 2, - .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC, - }, - .expected_refresh_rate = 59.8313, - }, - - /* "cvt 15360 8640 180" */ - { - .drm_mode = { - .clock = 37793603, - .hdisplay = 15360, - .hsync_start = 16880, - .hsync_end = 18624, - .htotal = 21888, - .vdisplay = 8640, - .vsync_start = 8643, - .vsync_end = 8648, - .vtotal = 9593, - .vscan = 0, - .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC, - }, - .expected_refresh_rate = 179.9939, - }, -}; - -static void -meta_test_kms_refresh_rate (void) -{ - size_t index; - - for (index = 0; index < G_N_ELEMENTS (refresh_rate_test_cases); index++) - { - const RefreshRateTestCase *test_case = refresh_rate_test_cases + index; - float refresh_rate; - - refresh_rate = - meta_calculate_drm_mode_refresh_rate (&test_case->drm_mode); - g_assert_cmpfloat_with_epsilon (refresh_rate, - test_case->expected_refresh_rate, - 0.0001); - } -} - -typedef struct -{ - drmModeModeInfo drm_mode; - int64_t expected_vblank_duration_us; -} VblankDurationTestCase; - -static const VblankDurationTestCase vblank_duration_test_cases[] = { - /* "cvt 640 480" */ - { - .drm_mode = { - .clock = 23975, - .hdisplay = 640, - .hsync_start = 664, - .hsync_end = 720, - .htotal = 800, - .vdisplay = 480, - .vsync_start = 483, - .vsync_end = 487, - .vtotal = 500, - .vscan = 0, - .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC, - }, - .expected_vblank_duration_us = 668, - }, - - /* "cvt 640 480" with htotal 0 */ - { - .drm_mode = { - .clock = 23975, - .hdisplay = 640, - .hsync_start = 664, - .hsync_end = 720, - .htotal = 0, - .vdisplay = 480, - .vsync_start = 483, - .vsync_end = 487, - .vtotal = 500, - .vscan = 0, - .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC, - }, - .expected_vblank_duration_us = 0, - }, - - /* "cvt 640 480" with vtotal 0 */ - { - .drm_mode = { - .clock = 23975, - .hdisplay = 640, - .hsync_start = 664, - .hsync_end = 720, - .htotal = 800, - .vdisplay = 480, - .vsync_start = 483, - .vsync_end = 487, - .vtotal = 0, - .vscan = 0, - .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC, - }, - .expected_vblank_duration_us = 0, - }, - - /* "cvt 640 480" with DBLSCAN */ - { - .drm_mode = { - .clock = 23975, - .hdisplay = 640, - .hsync_start = 664, - .hsync_end = 720, - .htotal = 800, - .vdisplay = 480, - .vsync_start = 483, - .vsync_end = 487, - .vtotal = 500, - .vscan = 0, - .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC | - DRM_MODE_FLAG_DBLSCAN, - }, - .expected_vblank_duration_us = 1335, - }, -}; - -static void -meta_test_kms_vblank_duration (void) -{ - size_t index; - - for (index = 0; index < G_N_ELEMENTS (vblank_duration_test_cases); index++) - { - const VblankDurationTestCase *test_case = vblank_duration_test_cases + index; - int64_t vblank_duration_us; - - vblank_duration_us = - meta_calculate_drm_mode_vblank_duration_us (&test_case->drm_mode); - g_assert_cmpint (vblank_duration_us, - ==, - test_case->expected_vblank_duration_us); - } -} - -static void -meta_test_kms_update_fixed16 (void) -{ - g_assert_cmpint (meta_fixed_16_from_int (12345), ==, 809041920); - g_assert_cmpint (meta_fixed_16_to_int (809041920), ==, 12345); - g_assert_cmpint (meta_fixed_16_from_int (-12345), ==, -809041920); - g_assert_cmpint (meta_fixed_16_to_int (-809041920), ==, -12345); -} - -static void -init_kms_utils_tests (void) -{ - g_test_add_func ("/backends/native/kms/refresh-rate", - meta_test_kms_refresh_rate); - g_test_add_func ("/backends/native/kms/vblank-duration", - meta_test_kms_vblank_duration); - g_test_add_func ("/backends/native/kms/update/fixed16", - meta_test_kms_update_fixed16); -} - -int -main (int argc, - char **argv) -{ - g_test_init (&argc, &argv, NULL); - init_kms_utils_tests (); - return g_test_run (); -} diff --git a/src/tests/meson.build b/src/tests/meson.build deleted file mode 100644 index a809cef8a..000000000 --- a/src/tests/meson.build +++ /dev/null @@ -1,351 +0,0 @@ -mutter_test_sources = [ - 'meta-backend-test.c', - 'meta-backend-test.h', - 'meta-context-test.c', - 'meta-gpu-test.c', - 'meta-gpu-test.h', - 'meta-monitor-manager-test.c', - 'meta-monitor-manager-test.h', - 'monitor-test-utils.c', - 'monitor-test-utils.h', - 'meta-test-utils.c', - 'meta-test-utils.h', -] - -libmutter_test_name = 'mutter-test-' + libmutter_api_version - -clutter_test_utils = files ( - 'clutter-test-utils.c', - 'clutter-test-utils.h', -) - -tests_includepath = include_directories('.') -tests_includes = mutter_includes -tests_c_args = mutter_c_args - -tests_deps = [ - mutter_deps, - libmutter_dep, - libmutter_cogl_dep, - libmutter_clutter_dep, -] - -libmutter_test = shared_library(libmutter_test_name, - mutter_test_sources, - gnu_symbol_visibility: 'hidden', - include_directories: tests_includes, - c_args: tests_c_args, - dependencies: tests_deps, - install_rpath: pkglibdir, - install_dir: libdir, - install: true, -) - -libmutter_test_dep = declare_dependency( - link_with: libmutter_test, - include_directories: tests_includes, - dependencies: tests_deps, -) - -pkg.generate(libmutter_test, - name: 'Meta (test framework)', - filebase: 'libmutter-test-' + libmutter_api_version, - description: 'Mutter test framework', - subdirs: pkgname, - requires: ['libmutter-' + libmutter_api_version], - version: meson.project_version(), - variables: [ - 'apiversion=' + libmutter_api_version, - ], - install_dir: pcdir, -) - -if have_clutter_tests - subdir('clutter') -endif - -subdir('meta-test') -subdir('wayland-test-clients') - -if have_installed_tests - stacking_files_datadir = join_paths(pkgdatadir, 'tests') - - installed_tests_cdata = configuration_data() - installed_tests_cdata.set('libexecdir', libexecdir) - installed_tests_cdata.set('apiversion', libmutter_api_version) - - configure_file( - input: 'mutter-all.test.in', - output: 'mutter-all.test', - configuration: installed_tests_cdata, - install: true, - install_dir: mutter_installed_tests_datadir, - ) - - install_subdir('stacking', install_dir: stacking_files_datadir) -endif - -test_env = environment() -test_env.set('G_TEST_SRCDIR', join_paths(meson.source_root(), 'src')) -test_env.set('G_TEST_BUILDDIR', meson.build_root()) -test_env.set('MUTTER_TEST_PLUGIN_PATH', '@0@'.format(default_plugin.full_path())) - -test_client = executable('mutter-test-client', - sources: ['test-client.c'], - include_directories: tests_includes, - c_args: tests_c_args, - dependencies: [ - gtk3_dep, - gio_unix_dep, - x11_dep, - xext_dep, - ], - install: have_installed_tests, - install_dir: mutter_installed_tests_libexecdir, -) - -test_runner = executable('mutter-test-runner', - sources: [ - 'test-runner.c', - ], - include_directories: tests_includes, - c_args: tests_c_args, - dependencies: libmutter_test_dep, - install: have_installed_tests, - install_dir: mutter_installed_tests_libexecdir, -) - -unit_tests = executable('mutter-test-unit-tests', - sources: [ - 'unit-tests.c', - 'boxes-tests.c', - 'boxes-tests.h', - 'meta-wayland-test-driver.c', - 'meta-wayland-test-driver.h', - 'monitor-config-migration-unit-tests.c', - 'monitor-config-migration-unit-tests.h', - 'monitor-store-unit-tests.c', - 'monitor-store-unit-tests.h', - 'monitor-test-utils.c', - 'monitor-test-utils.h', - 'monitor-transform-tests.c', - 'monitor-transform-tests.h', - 'monitor-unit-tests.c', - 'monitor-unit-tests.h', - 'wayland-unit-tests.c', - 'wayland-unit-tests.h', - test_driver_server_header, - test_driver_protocol_code, - ], - include_directories: tests_includes, - c_args: tests_c_args, - dependencies: libmutter_test_dep, - install: have_installed_tests, - install_dir: mutter_installed_tests_libexecdir, -) - -headless_start_test = executable('mutter-headless-start-test', - sources: [ - 'headless-start-test.c', - ], - include_directories: tests_includes, - c_args: tests_c_args, - dependencies: libmutter_test_dep, - install: have_installed_tests, - install_dir: mutter_installed_tests_libexecdir, -) - -stage_view_tests = executable('mutter-stage-view-tests', - sources: [ - 'monitor-test-utils.c', - 'monitor-test-utils.h', - 'stage-view-tests.c', - ], - include_directories: tests_includes, - c_args: tests_c_args, - dependencies: libmutter_test_dep, - install: have_installed_tests, - install_dir: mutter_installed_tests_libexecdir, -) - -anonymous_file_test = executable('anonymous-file-tests', - sources: [ - 'anonymous-file.c', - ], - include_directories: tests_includes, - c_args: tests_c_args, - dependencies: [tests_deps], - install: have_installed_tests, - install_dir: mutter_installed_tests_libexecdir, -) - -ref_test_sources = [ - 'meta-ref-test.c', - 'meta-ref-test.h', -] - -if have_native_tests - native_kms_utils_tests = executable('mutter-native-kms-utils-tests', - sources: [ - 'kms-utils-unit-tests.c', - ], - include_directories: tests_includepath, - c_args: tests_c_args, - dependencies: [tests_deps], - install: have_installed_tests, - install_dir: mutter_installed_tests_libexecdir, - ) - - native_headless_tests = executable('mutter-native-headless-tests', - sources: [ - 'native-headless.c', - 'native-screen-cast.c', - 'native-screen-cast.h', - 'native-virtual-monitor.c', - 'native-virtual-monitor.h', - ref_test_sources, - ], - include_directories: tests_includes, - c_args: tests_c_args, - dependencies: libmutter_test_dep, - install: have_installed_tests, - install_dir: mutter_installed_tests_libexecdir, - ) - - ref_test_sanity = executable('mutter-ref-test-sanity', - sources: [ - 'ref-test-sanity.c', - ref_test_sources, - ], - include_directories: tests_includes, - c_args: tests_c_args, - dependencies: libmutter_test_dep, - install: have_installed_tests, - install_dir: mutter_installed_tests_libexecdir, - ) - - screen_cast_client = executable('mutter-screen-cast-client', - sources: [ - 'screen-cast-client.c', - dbus_screen_cast_built_sources, - ], - include_directories: tests_includes, - c_args: tests_c_args, - dependencies: [ - gio_dep, - libpipewire_dep, - ], - install: have_installed_tests, - install_dir: mutter_installed_tests_libexecdir, - ) - - native_persistent_virtual_monitor = executable( - 'mutter-persistent-virtual-monitor', - sources: [ - 'native-persistent-virtual-monitor.c', - ], - include_directories: tests_includes, - c_args: tests_c_args, - dependencies: libmutter_test_dep, - install: have_installed_tests, - install_dir: mutter_installed_tests_libexecdir, - ) -endif - -stacking_tests = [ - 'basic-x11', - 'basic-wayland', - 'client-side-decorated', - 'closed-transient', - 'closed-transient-no-default-focus', - 'closed-transient-no-input-no-take-focus-parent', - 'closed-transient-no-input-no-take-focus-parents', - 'closed-transient-no-input-parent', - 'closed-transient-no-input-parent-delayed-focus-default-cancelled', - 'closed-transient-no-input-parents', - 'closed-transient-no-input-parents-queued-default-focus-destroyed', - 'closed-transient-only-take-focus-parents', - 'minimized', - 'mixed-windows', - 'set-parent', - 'override-redirect', - 'set-override-redirect-parent', - 'set-parent-exported', - 'restore-size', - 'unmaximize-new-size', - 'fullscreen-maximize', - 'restore-position', - 'default-size', - 'modals', - 'map-fixed-size', -] - -foreach stacking_test: stacking_tests - test(stacking_test, test_runner, - suite: ['core', 'mutter/stacking'], - env: test_env, - args: [ - files(join_paths('stacking', stacking_test + '.metatest')), - ], - is_parallel: false, - timeout: 60, - ) -endforeach - -test('normal', unit_tests, - suite: ['core', 'mutter/unit'], - env: test_env, - is_parallel: false, - timeout: 60, -) - -test('headless-start', headless_start_test, - suite: ['core', 'mutter/unit'], - env: test_env, - is_parallel: false, - timeout: 60, -) - -test('stage-view', stage_view_tests, - suite: ['core', 'mutter/unit'], - env: test_env, - is_parallel: false, - timeout: 60, -) - -test('anonymous-file', anonymous_file_test, - suite: ['core', 'mutter/unit'], - env: test_env, - is_parallel: false, - timeout: 60, -) - -if have_native_tests - test('native-kms-utils', native_kms_utils_tests, - suite: ['core', 'mutter/native/kms'], - env: test_env, - is_parallel: false, - timeout: 60, - ) - - test('native-headless', native_headless_tests, - suite: ['core', 'mutter/native/headless'], - env: test_env, - is_parallel: false, - timeout: 60, - ) - - test('ref-test-sanity', ref_test_sanity, - suite: ['core', 'mutter/ref-test/sanity'], - env: test_env, - is_parallel: false, - timeout: 60, - ) - - test('native-persistent-virtual-monitor', native_persistent_virtual_monitor, - suite: ['core', 'mutter/native/persistent-virtual-monitor'], - env: test_env, - is_parallel: false, - timeout: 60, - ) -endif diff --git a/src/tests/meta-backend-test.c b/src/tests/meta-backend-test.c deleted file mode 100644 index 0bc30d04d..000000000 --- a/src/tests/meta-backend-test.c +++ /dev/null @@ -1,95 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 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 . - */ - -#include "config.h" - -#include "tests/meta-backend-test.h" - -#include "tests/meta-gpu-test.h" -#include "tests/meta-monitor-manager-test.h" - -struct _MetaBackendTest -{ - MetaBackendX11Nested parent; - - MetaGpu *gpu; - - gboolean is_lid_closed; -}; - -G_DEFINE_TYPE (MetaBackendTest, meta_backend_test, META_TYPE_BACKEND_X11_NESTED) - -void -meta_backend_test_set_is_lid_closed (MetaBackendTest *backend_test, - gboolean is_lid_closed) -{ - backend_test->is_lid_closed = is_lid_closed; -} - -MetaGpu * -meta_backend_test_get_gpu (MetaBackendTest *backend_test) -{ - return backend_test->gpu; -} - -static gboolean -meta_backend_test_is_lid_closed (MetaBackend *backend) -{ - MetaBackendTest *backend_test = META_BACKEND_TEST (backend); - - return backend_test->is_lid_closed; -} - -static void -meta_backend_test_init_gpus (MetaBackendX11Nested *backend_x11_nested) -{ - MetaBackendTest *backend_test = META_BACKEND_TEST (backend_x11_nested); - - backend_test->gpu = g_object_new (META_TYPE_GPU_TEST, - "backend", backend_test, - NULL); - meta_backend_add_gpu (META_BACKEND (backend_test), backend_test->gpu); -} - -static void -meta_backend_test_init (MetaBackendTest *backend_test) -{ -} - -static MetaMonitorManager * -meta_backend_test_create_monitor_manager (MetaBackend *backend, - GError **error) -{ - return g_object_new (META_TYPE_MONITOR_MANAGER_TEST, - "backend", backend, - NULL); -} - -static void -meta_backend_test_class_init (MetaBackendTestClass *klass) -{ - MetaBackendClass *backend_class = META_BACKEND_CLASS (klass); - MetaBackendX11NestedClass *backend_x11_nested_class = - META_BACKEND_X11_NESTED_CLASS (klass); - - backend_class->create_monitor_manager = meta_backend_test_create_monitor_manager; - backend_class->is_lid_closed = meta_backend_test_is_lid_closed; - - backend_x11_nested_class->init_gpus = meta_backend_test_init_gpus; -} diff --git a/src/tests/meta-backend-test.h b/src/tests/meta-backend-test.h deleted file mode 100644 index ad57a42e8..000000000 --- a/src/tests/meta-backend-test.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 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 . - */ - -#ifndef META_BACKEND_TEST_H -#define META_BACKEND_TEST_H - -#include "backends/x11/nested/meta-backend-x11-nested.h" - -#define META_TYPE_BACKEND_TEST (meta_backend_test_get_type ()) -META_EXPORT -G_DECLARE_FINAL_TYPE (MetaBackendTest, meta_backend_test, - META, BACKEND_TEST, MetaBackendX11Nested) - -META_EXPORT -void meta_backend_test_set_is_lid_closed (MetaBackendTest *backend_test, - gboolean is_lid_closed); - -META_EXPORT -MetaGpu * meta_backend_test_get_gpu (MetaBackendTest *backend_test); - -#endif /* META_BACKEND_TEST_H */ diff --git a/src/tests/meta-context-test.c b/src/tests/meta-context-test.c deleted file mode 100644 index 7ba6c6b51..000000000 --- a/src/tests/meta-context-test.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (C) 2021 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "meta-test/meta-context-test.h" - -#include -#include - -#include "core/meta-context-private.h" -#include "tests/meta-backend-test.h" -#include "tests/meta-test-utils-private.h" -#include "wayland/meta-wayland.h" -#include "wayland/meta-xwayland.h" - -#ifdef HAVE_NATIVE_BACKEND -#include "backends/native/meta-backend-native.h" -#endif - -enum -{ - BEFORE_TESTS, - RUN_TESTS, - AFTER_TESTS, - N_SIGNALS -}; - -static guint signals[N_SIGNALS]; - -typedef struct _MetaContextTestPrivate -{ - MetaContextTestType type; - MetaContextTestFlag flags; -} MetaContextTestPrivate; - -struct _MetaContextTestClass -{ - MetaContextClass parent_class; -}; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaContextTest, meta_context_test, - META_TYPE_CONTEXT) - -static gboolean -meta_context_test_configure (MetaContext *context, - int *argc, - char ***argv, - GError **error) -{ - MetaContextTest *context_test = META_CONTEXT_TEST (context); - MetaContextTestPrivate *priv = - meta_context_test_get_instance_private (context_test); - MetaContextClass *context_class = - META_CONTEXT_CLASS (meta_context_test_parent_class); - const char *plugin_name; - - if (!context_class->configure (context, argc, argv, error)) - return FALSE; - - g_test_init (argc, argv, NULL); - g_test_bug_base ("https://gitlab.gnome.org/GNOME/mutter/issues/"); - - if (priv->flags & META_CONTEXT_TEST_FLAG_TEST_CLIENT) - meta_ensure_test_client_path (*argc, *argv); - - meta_wayland_override_display_name ("mutter-test-display"); - meta_xwayland_override_display_number (512); - - plugin_name = g_getenv ("MUTTER_TEST_PLUGIN_PATH"); - if (!plugin_name) - plugin_name = "libdefault"; - meta_context_set_plugin_name (context, plugin_name); - - return TRUE; -} - -static MetaCompositorType -meta_context_test_get_compositor_type (MetaContext *context) -{ - return META_COMPOSITOR_TYPE_WAYLAND; -} - -static MetaX11DisplayPolicy -meta_context_test_get_x11_display_policy (MetaContext *context) -{ - MetaContextTest *context_test = META_CONTEXT_TEST (context); - MetaContextTestPrivate *priv = - meta_context_test_get_instance_private (context_test); - - if (priv->flags & META_CONTEXT_TEST_FLAG_NO_X11) - return META_X11_DISPLAY_POLICY_DISABLED; - else - return META_X11_DISPLAY_POLICY_ON_DEMAND; -} - -static gboolean -meta_context_test_is_replacing (MetaContext *context) -{ - return FALSE; -} - -static gboolean -meta_context_test_setup (MetaContext *context, - GError **error) -{ - MetaBackend *backend; - MetaSettings *settings; - - if (!META_CONTEXT_CLASS (meta_context_test_parent_class)->setup (context, - error)) - return FALSE; - - backend = meta_get_backend (); - settings = meta_backend_get_settings (backend); - meta_settings_override_experimental_features (settings); - meta_settings_enable_experimental_feature ( - settings, - META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER); - - meta_set_syncing (!!g_getenv ("MUTTER_SYNC")); - - return TRUE; -} - -static MetaBackend * -create_nested_backend (MetaContext *context, - GError **error) -{ - return g_initable_new (META_TYPE_BACKEND_TEST, - NULL, error, - "context", context, - NULL); -} - -#ifdef HAVE_NATIVE_BACKEND -static MetaBackend * -create_headless_backend (MetaContext *context, - GError **error) -{ - return g_initable_new (META_TYPE_BACKEND_NATIVE, - NULL, error, - "context", context, - "headless", TRUE, - NULL); -} -#endif /* HAVE_NATIVE_BACKEND */ - -static MetaBackend * -meta_context_test_create_backend (MetaContext *context, - GError **error) -{ - MetaContextTest *context_test = META_CONTEXT_TEST (context); - MetaContextTestPrivate *priv = - meta_context_test_get_instance_private (context_test); - - switch (priv->type) - { - case META_CONTEXT_TEST_TYPE_NESTED: - return create_nested_backend (context, error); -#ifdef HAVE_NATIVE_BACKEND - case META_CONTEXT_TEST_TYPE_HEADLESS: - return create_headless_backend (context, error); -#endif /* HAVE_NATIVE_BACKEND */ - } - - g_assert_not_reached (); -} - -static void -meta_context_test_notify_ready (MetaContext *context) -{ -} - -static gboolean -run_tests_idle (gpointer user_data) -{ - MetaContext *context = user_data; - int ret; - - g_signal_emit (context, signals[BEFORE_TESTS], 0); - if (g_signal_has_handler_pending (context, signals[RUN_TESTS], 0, TRUE)) - { - g_signal_emit (context, signals[RUN_TESTS], 0, &ret); - g_assert (ret == 1 || ret == 0); - } - else - { - ret = g_test_run (); - } - g_signal_emit (context, signals[AFTER_TESTS], 0); - - if (ret != 0) - { - GError *error; - - error = g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED, - "One or more tests failed"); - meta_context_terminate_with_error (context, error); - } - else - { - meta_context_terminate (context); - } - - return G_SOURCE_REMOVE; -} - -int -meta_context_test_run_tests (MetaContextTest *context_test) -{ - MetaContext *context = META_CONTEXT (context_test); - g_autoptr (GError) error = NULL; - - if (!meta_context_setup (context, &error)) - { - g_printerr ("Test case failed to start: %s\n", error->message); - return EXIT_FAILURE; - } - - if (!meta_context_start (context, &error)) - { - g_printerr ("Test case failed to start: %s\n", error->message); - return EXIT_FAILURE; - } - - g_idle_add (run_tests_idle, context_test); - - meta_context_notify_ready (context); - - if (!meta_context_run_main_loop (context, &error)) - { - g_printerr ("Test case failed: %s\n", error->message); - return EXIT_FAILURE; - } - else - { - return EXIT_SUCCESS; - } -} - -void -meta_context_test_wait_for_x11_display (MetaContextTest *context_test) -{ - MetaDisplay *display = meta_context_get_display (META_CONTEXT (context_test)); - - while (!meta_display_get_x11_display (display)) - g_main_context_iteration (NULL, TRUE); - - g_assert_nonnull (meta_display_get_x11_display (display)); -} - -/** - * meta_create_test_context: (skip) - */ -MetaContext * -meta_create_test_context (MetaContextTestType type, - MetaContextTestFlag flags) -{ - MetaContextTest *context_test; - MetaContextTestPrivate *priv; - - context_test = g_object_new (META_TYPE_CONTEXT_TEST, - "name", "Mutter Test", - NULL); - priv = meta_context_test_get_instance_private (context_test); - priv->type = type; - priv->flags = flags; - - return META_CONTEXT (context_test); -} - -static void -meta_context_test_class_init (MetaContextTestClass *klass) -{ - MetaContextClass *context_class = META_CONTEXT_CLASS (klass); - - context_class->configure = meta_context_test_configure; - context_class->get_compositor_type = meta_context_test_get_compositor_type; - context_class->get_x11_display_policy = - meta_context_test_get_x11_display_policy; - context_class->is_replacing = meta_context_test_is_replacing; - context_class->setup = meta_context_test_setup; - context_class->create_backend = meta_context_test_create_backend; - context_class->notify_ready = meta_context_test_notify_ready; - - signals[BEFORE_TESTS] = - g_signal_new ("before-tests", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, - 0); - signals[RUN_TESTS] = - g_signal_new ("run-tests", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_INT, - 0); - signals[AFTER_TESTS] = - g_signal_new ("after-tests", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, - 0); -} - -static void -meta_context_test_init (MetaContextTest *context_test) -{ -} diff --git a/src/tests/meta-gpu-test.c b/src/tests/meta-gpu-test.c deleted file mode 100644 index d483fd211..000000000 --- a/src/tests/meta-gpu-test.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2016-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 . - */ - -#include "config.h" - -#include "tests/meta-gpu-test.h" - -#include "backends/meta-backend-private.h" -#include "tests/meta-monitor-manager-test.h" - -struct _MetaGpuTest -{ - MetaGpu parent; -}; - -G_DEFINE_TYPE (MetaGpuTest, meta_gpu_test, META_TYPE_GPU) - -static gboolean -meta_gpu_test_read_current (MetaGpu *gpu, - GError **error) -{ - MetaBackend *backend = meta_gpu_get_backend (gpu); - MetaMonitorManager *manager = meta_backend_get_monitor_manager (backend); - - meta_monitor_manager_test_read_current (manager); - - return TRUE; -} - -static void -meta_gpu_test_init (MetaGpuTest *gpu_test) -{ -} - -static void -meta_gpu_test_class_init (MetaGpuTestClass *klass) -{ - MetaGpuClass *gpu_class = META_GPU_CLASS (klass); - - gpu_class->read_current = meta_gpu_test_read_current; -} diff --git a/src/tests/meta-gpu-test.h b/src/tests/meta-gpu-test.h deleted file mode 100644 index 46bbc80e2..000000000 --- a/src/tests/meta-gpu-test.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2016-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 . - */ - -#ifndef META_GPU_TEST_H -#define META_GPU_TEST_H - -#include "backends/meta-gpu.h" - -#define META_TYPE_GPU_TEST (meta_gpu_test_get_type ()) -G_DECLARE_FINAL_TYPE (MetaGpuTest, meta_gpu_test, META, GPU_TEST, MetaGpu) - -#endif /* META_GPU_TEST_H */ diff --git a/src/tests/meta-monitor-manager-test.c b/src/tests/meta-monitor-manager-test.c deleted file mode 100644 index e3b4f46cf..000000000 --- a/src/tests/meta-monitor-manager-test.c +++ /dev/null @@ -1,490 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 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 . - */ - -#include "config.h" - -#include "tests/meta-monitor-manager-test.h" - -#include "backends/meta-backend-private.h" -#include "backends/meta-crtc.h" -#include "backends/meta-gpu.h" -#include "backends/meta-monitor-config-manager.h" -#include "backends/meta-output.h" -#include "tests/meta-backend-test.h" -#include "tests/monitor-test-utils.h" - -G_DEFINE_TYPE (MetaCrtcTest, meta_crtc_test, META_TYPE_CRTC) -G_DEFINE_TYPE (MetaOutputTest, meta_output_test, META_TYPE_OUTPUT) - -struct _MetaMonitorManagerTest -{ - MetaMonitorManager parent; - - gboolean handles_transforms; - - int tiled_monitor_count; - - MetaMonitorTestSetup *test_setup; -}; - -G_DEFINE_TYPE (MetaMonitorManagerTest, meta_monitor_manager_test, - META_TYPE_MONITOR_MANAGER) - -static CreateTestSetupFunc initial_setup_func; - -void -meta_monitor_manager_test_init_test_setup (CreateTestSetupFunc func) -{ - initial_setup_func = func; -} - -void -meta_monitor_manager_test_emulate_hotplug (MetaMonitorManagerTest *manager_test, - MetaMonitorTestSetup *test_setup) -{ - MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_test); - MetaMonitorTestSetup *old_test_setup; - - old_test_setup = manager_test->test_setup; - manager_test->test_setup = test_setup; - - meta_monitor_manager_reload (manager); - - g_free (old_test_setup); -} - -void -meta_monitor_manager_test_set_handles_transforms (MetaMonitorManagerTest *manager_test, - gboolean handles_transforms) -{ - g_assert (handles_transforms || meta_is_stage_views_enabled()); - - manager_test->handles_transforms = handles_transforms; -} - -int -meta_monitor_manager_test_get_tiled_monitor_count (MetaMonitorManagerTest *manager_test) -{ - return manager_test->tiled_monitor_count; -} - -void -meta_monitor_manager_test_read_current (MetaMonitorManager *manager) -{ - MetaMonitorManagerTest *manager_test = META_MONITOR_MANAGER_TEST (manager); - MetaBackend *backend = meta_monitor_manager_get_backend (manager); - MetaBackendTest *backend_test = META_BACKEND_TEST (backend); - MetaGpu *gpu = meta_backend_test_get_gpu (backend_test); - - g_assert (manager_test->test_setup); - - meta_gpu_take_modes (gpu, manager_test->test_setup->modes); - meta_gpu_take_crtcs (gpu, manager_test->test_setup->crtcs); - meta_gpu_take_outputs (gpu, manager_test->test_setup->outputs); -} - -static void -meta_monitor_manager_test_ensure_initial_config (MetaMonitorManager *manager) -{ - MetaMonitorsConfig *config; - - config = meta_monitor_manager_ensure_configured (manager); - - if (meta_is_stage_views_enabled ()) - { - meta_monitor_manager_update_logical_state (manager, config); - } - else - { - meta_monitor_manager_update_logical_state_derived (manager, NULL); - } -} - -static void -apply_crtc_assignments (MetaMonitorManager *manager, - MetaCrtcAssignment **crtcs, - unsigned int n_crtcs, - MetaOutputAssignment **outputs, - unsigned int n_outputs) -{ - MetaBackend *backend = meta_monitor_manager_get_backend (manager); - MetaBackendTest *backend_test = META_BACKEND_TEST (backend); - MetaGpu *gpu = meta_backend_test_get_gpu (backend_test); - g_autoptr (GList) to_configure_outputs = NULL; - g_autoptr (GList) to_configure_crtcs = NULL; - unsigned int i; - - to_configure_outputs = g_list_copy (meta_gpu_get_outputs (gpu)); - to_configure_crtcs = g_list_copy (meta_gpu_get_crtcs (gpu)); - - for (i = 0; i < n_crtcs; i++) - { - MetaCrtcAssignment *crtc_assignment = crtcs[i]; - MetaCrtc *crtc = crtc_assignment->crtc; - - to_configure_crtcs = g_list_remove (to_configure_crtcs, crtc); - - if (crtc_assignment->mode == NULL) - { - meta_crtc_unset_config (crtc); - } - else - { - unsigned int j; - - meta_crtc_set_config (crtc, - &crtc_assignment->layout, - crtc_assignment->mode, - crtc_assignment->transform); - - for (j = 0; j < crtc_assignment->outputs->len; j++) - { - MetaOutput *output; - MetaOutputAssignment *output_assignment; - - output = ((MetaOutput**) crtc_assignment->outputs->pdata)[j]; - - to_configure_outputs = g_list_remove (to_configure_outputs, - output); - - output_assignment = meta_find_output_assignment (outputs, - n_outputs, - output); - meta_output_assign_crtc (output, crtc, output_assignment); - } - } - } - - g_list_foreach (to_configure_crtcs, - (GFunc) meta_crtc_unset_config, - NULL); - g_list_foreach (to_configure_outputs, - (GFunc) meta_output_unassign_crtc, - NULL); -} - -static void -update_screen_size (MetaMonitorManager *manager, - MetaMonitorsConfig *config) -{ - GList *l; - int screen_width = 0; - int screen_height = 0; - - for (l = config->logical_monitor_configs; l; l = l->next) - { - MetaLogicalMonitorConfig *logical_monitor_config = l->data; - int right_edge; - int bottom_edge; - - right_edge = (logical_monitor_config->layout.width + - logical_monitor_config->layout.x); - if (right_edge > screen_width) - screen_width = right_edge; - - bottom_edge = (logical_monitor_config->layout.height + - logical_monitor_config->layout.y); - if (bottom_edge > screen_height) - screen_height = bottom_edge; - } - - manager->screen_width = screen_width; - manager->screen_height = screen_height; -} - -static gboolean -meta_monitor_manager_test_apply_monitors_config (MetaMonitorManager *manager, - MetaMonitorsConfig *config, - MetaMonitorsConfigMethod method, - GError **error) -{ - GPtrArray *crtc_assignments; - GPtrArray *output_assignments; - - if (!config) - { - manager->screen_width = META_MONITOR_MANAGER_MIN_SCREEN_WIDTH; - manager->screen_height = META_MONITOR_MANAGER_MIN_SCREEN_HEIGHT; - - if (meta_is_stage_views_enabled ()) - meta_monitor_manager_rebuild (manager, NULL); - else - meta_monitor_manager_rebuild_derived (manager, config); - - return TRUE; - } - - if (!meta_monitor_config_manager_assign (manager, config, - &crtc_assignments, - &output_assignments, - error)) - return FALSE; - - if (method == META_MONITORS_CONFIG_METHOD_VERIFY) - { - g_ptr_array_free (crtc_assignments, TRUE); - g_ptr_array_free (output_assignments, TRUE); - return TRUE; - } - - apply_crtc_assignments (manager, - (MetaCrtcAssignment **) crtc_assignments->pdata, - crtc_assignments->len, - (MetaOutputAssignment **) output_assignments->pdata, - output_assignments->len); - - g_ptr_array_free (crtc_assignments, TRUE); - g_ptr_array_free (output_assignments, TRUE); - - update_screen_size (manager, config); - - if (meta_is_stage_views_enabled ()) - meta_monitor_manager_rebuild (manager, config); - else - meta_monitor_manager_rebuild_derived (manager, config); - - return TRUE; -} - -static void -meta_monitor_manager_test_tiled_monitor_added (MetaMonitorManager *manager, - MetaMonitor *monitor) -{ - MetaMonitorManagerTest *manager_test = META_MONITOR_MANAGER_TEST (manager); - - manager_test->tiled_monitor_count++; -} - -static void -meta_monitor_manager_test_tiled_monitor_removed (MetaMonitorManager *manager, - MetaMonitor *monitor) -{ - MetaMonitorManagerTest *manager_test = META_MONITOR_MANAGER_TEST (manager); - - manager_test->tiled_monitor_count--; -} - -static gboolean -meta_monitor_manager_test_is_transform_handled (MetaMonitorManager *manager, - MetaCrtc *crtc, - MetaMonitorTransform transform) -{ - MetaMonitorManagerTest *manager_test = META_MONITOR_MANAGER_TEST (manager); - - return manager_test->handles_transforms; -} - -static float -meta_monitor_manager_test_calculate_monitor_mode_scale (MetaMonitorManager *manager, - MetaMonitor *monitor, - MetaMonitorMode *monitor_mode) -{ - MetaOutput *output; - MetaOutputTest *output_test; - - output = meta_monitor_get_main_output (monitor); - output_test = META_OUTPUT_TEST (output); - - if (output_test) - return output_test->scale; - else - return 1; -} - -static float * -meta_monitor_manager_test_calculate_supported_scales (MetaMonitorManager *manager, - MetaLogicalMonitorLayoutMode layout_mode, - MetaMonitor *monitor, - MetaMonitorMode *monitor_mode, - int *n_supported_scales) -{ - MetaMonitorScalesConstraint constraints = - META_MONITOR_SCALES_CONSTRAINT_NONE; - - switch (layout_mode) - { - case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL: - break; - case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL: - constraints |= META_MONITOR_SCALES_CONSTRAINT_NO_FRAC; - break; - } - - return meta_monitor_calculate_supported_scales (monitor, monitor_mode, - constraints, - n_supported_scales); -} - -static gboolean -is_monitor_framebuffer_scaled (void) -{ - MetaBackend *backend = meta_get_backend (); - MetaSettings *settings = meta_backend_get_settings (backend); - - return meta_settings_is_experimental_feature_enabled ( - settings, - META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER); -} - -static MetaMonitorManagerCapability -meta_monitor_manager_test_get_capabilities (MetaMonitorManager *manager) -{ - MetaMonitorManagerCapability capabilities = - META_MONITOR_MANAGER_CAPABILITY_NONE; - - if (is_monitor_framebuffer_scaled ()) - capabilities |= META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE; - - return capabilities; -} - -static gboolean -meta_monitor_manager_test_get_max_screen_size (MetaMonitorManager *manager, - int *max_width, - int *max_height) -{ - if (meta_is_stage_views_enabled ()) - return FALSE; - - *max_width = 65535; - *max_height = 65535; - - return TRUE; -} - -static MetaLogicalMonitorLayoutMode -meta_monitor_manager_test_get_default_layout_mode (MetaMonitorManager *manager) -{ - if (!meta_is_stage_views_enabled ()) - return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL; - - if (is_monitor_framebuffer_scaled ()) - return META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL; - else - return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL; -} - -static void -meta_monitor_manager_test_dispose (GObject *object) -{ - MetaMonitorManagerTest *manager_test = META_MONITOR_MANAGER_TEST (object); - - g_clear_pointer (&manager_test->test_setup, g_free); - - G_OBJECT_CLASS (meta_monitor_manager_test_parent_class)->dispose (object); -} - -static MonitorTestCaseSetup default_test_case_setup = { - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.0 - } - }, - .n_modes = 1, - .outputs = { - { - .crtc = 0, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125 - }, - - }, - .n_outputs = 1, - .crtcs = { - { - .current_mode = 0 - }, - }, - .n_crtcs = 1, -}; - -static MetaMonitorTestSetup * -create_default_test_setup (void) -{ - return create_monitor_test_setup (&default_test_case_setup, - MONITOR_TEST_FLAG_NO_STORED); -} - -static void -meta_monitor_manager_test_constructed (GObject *object) -{ - MetaMonitorManagerTest *manager_test = META_MONITOR_MANAGER_TEST (object); - - if (initial_setup_func) - manager_test->test_setup = initial_setup_func (); - else - manager_test->test_setup = create_default_test_setup (); - - G_OBJECT_CLASS (meta_monitor_manager_test_parent_class)->constructed (object); -} - -static void -meta_monitor_manager_test_init (MetaMonitorManagerTest *manager_test) -{ - manager_test->handles_transforms = TRUE; -} - -static void -meta_monitor_manager_test_class_init (MetaMonitorManagerTestClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass); - - object_class->dispose = meta_monitor_manager_test_dispose; - object_class->constructed = meta_monitor_manager_test_constructed; - - manager_class->ensure_initial_config = meta_monitor_manager_test_ensure_initial_config; - manager_class->apply_monitors_config = meta_monitor_manager_test_apply_monitors_config; - manager_class->tiled_monitor_added = meta_monitor_manager_test_tiled_monitor_added; - manager_class->tiled_monitor_removed = meta_monitor_manager_test_tiled_monitor_removed; - manager_class->is_transform_handled = meta_monitor_manager_test_is_transform_handled; - manager_class->calculate_monitor_mode_scale = meta_monitor_manager_test_calculate_monitor_mode_scale; - manager_class->calculate_supported_scales = meta_monitor_manager_test_calculate_supported_scales; - manager_class->get_capabilities = meta_monitor_manager_test_get_capabilities; - manager_class->get_max_screen_size = meta_monitor_manager_test_get_max_screen_size; - manager_class->get_default_layout_mode = meta_monitor_manager_test_get_default_layout_mode; -} - -static void -meta_output_test_init (MetaOutputTest *output_test) -{ - output_test->scale = 1; -} - -static void -meta_output_test_class_init (MetaOutputTestClass *klass) -{ -} - -static void -meta_crtc_test_init (MetaCrtcTest *crtc_test) -{ -} - -static void -meta_crtc_test_class_init (MetaCrtcTestClass *klass) -{ -} diff --git a/src/tests/meta-monitor-manager-test.h b/src/tests/meta-monitor-manager-test.h deleted file mode 100644 index 5b0b6d8e7..000000000 --- a/src/tests/meta-monitor-manager-test.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 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 . - */ - -#ifndef META_MONITOR_MANAGER_TEST_H -#define META_MONITOR_MANAGER_TEST_H - -#include "backends/meta-crtc.h" -#include "backends/meta-monitor-manager-private.h" -#include "backends/meta-output.h" - -typedef struct _MetaMonitorTestSetup -{ - GList *modes; - GList *outputs; - GList *crtcs; -} MetaMonitorTestSetup; - -struct _MetaCrtcTest -{ - MetaCrtc parent; -}; - -struct _MetaOutputTest -{ - MetaOutput parent; - - float scale; -}; - -typedef MetaMonitorTestSetup * (* CreateTestSetupFunc) (void); - -#define META_TYPE_CRTC_TEST (meta_crtc_test_get_type ()) -META_EXPORT -G_DECLARE_FINAL_TYPE (MetaCrtcTest, meta_crtc_test, - META, CRTC_TEST, - MetaCrtc) - -#define META_TYPE_OUTPUT_TEST (meta_output_test_get_type ()) -META_EXPORT -G_DECLARE_FINAL_TYPE (MetaOutputTest, meta_output_test, - META, OUTPUT_TEST, - MetaOutput) - -#define META_TYPE_MONITOR_MANAGER_TEST (meta_monitor_manager_test_get_type ()) -META_EXPORT -G_DECLARE_FINAL_TYPE (MetaMonitorManagerTest, meta_monitor_manager_test, - META, MONITOR_MANAGER_TEST, MetaMonitorManager) - -META_EXPORT -void meta_monitor_manager_test_init_test_setup (CreateTestSetupFunc func); - -void meta_monitor_manager_test_read_current (MetaMonitorManager *manager); - -META_EXPORT -void meta_monitor_manager_test_emulate_hotplug (MetaMonitorManagerTest *manager_test, - MetaMonitorTestSetup *test_setup); - -META_EXPORT -void meta_monitor_manager_test_set_handles_transforms (MetaMonitorManagerTest *manager_test, - gboolean handles_transforms); - -META_EXPORT -int meta_monitor_manager_test_get_tiled_monitor_count (MetaMonitorManagerTest *manager_test); - -#endif /* META_MONITOR_MANAGER_TEST_H */ diff --git a/src/tests/meta-ref-test.c b/src/tests/meta-ref-test.c deleted file mode 100644 index 84ac8876d..000000000 --- a/src/tests/meta-ref-test.c +++ /dev/null @@ -1,610 +0,0 @@ -/* - * Copyright (C) 2021 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 . - */ - -/* - * The image difference code is originally a reformatted and simplified - * copy of weston-test-client-helper.c from the weston repository, with - * the following copyright and license note: - * - * Copyright © 2012 Intel Corporation - * Copyright © 2015 Samsung Electronics Co., Ltd - * Copyright 2016, 2017 Collabora, Ltd. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* - * To update or initialize reference images for tests, set the - * MUTTER_REF_TEST_UPDATE environment variable. - * - * The MUTTER_REF_TEST_UPDATE is interpreted as a comma seperated list of - * regular expressions. If the test path matches any of the regular - * expressions, the test reference image will be updated, unless the - * existing reference image is pixel identical to the newly created one. - * - * Updating test reference images also requires using a software OpenGL - * renderer, which can be achieved using LIBGL_ALWAYS_SOFTWARE=1 - * - * For example, for the test case '/path/to/test/case', run the test - * inside - * - * ``` - * env LIBGL_ALWAYS_SOFTWARE=1 MUTTER_REF_TEST_UPDATE='/path/to/test/case` - * ``` - * - */ - -#include "config.h" - -#include "tests/meta-ref-test.h" - -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-stage-private.h" -#include "clutter/clutter/clutter-stage-view-private.h" - -typedef struct _Range -{ - int a; - int b; -} Range; - -typedef struct _ImageIterator -{ - uint8_t *data; - int stride; -} ImageIterator; - -typedef struct _PixelDiffStat -{ - /* Pixel diff stat channel */ - struct { - int min_diff; - int max_diff; - } ch[4]; -} PixelDiffStat; - -/** - * range_get: - * @range: Range to validate or NULL. - * - * Validate and get range. - * - * Returns the given range, or {0, 0} for NULL. - * - * Will abort if range is invalid, that is a > b. - */ -static Range -range_get (const Range *range) -{ - if (!range) - return (Range) { 0, 0 }; - - g_assert_cmpint (range->a, <=, range->b); - return *range; -} - -static void -image_iterator_init (ImageIterator *it, - cairo_surface_t *image) -{ - it->stride = cairo_image_surface_get_stride (image); - it->data = cairo_image_surface_get_data (image); - - g_assert_cmpint (cairo_image_surface_get_format (image), ==, - CAIRO_FORMAT_ARGB32); -} - -static uint32_t * -image_iterator_get_row (ImageIterator *it, - int y) -{ - return (uint32_t *) (it->data + y * it->stride); -} - -static gboolean -fuzzy_match_pixels (uint32_t pix_a, - uint32_t pix_b, - const Range *fuzz, - PixelDiffStat *diff_stat) -{ - gboolean ret = TRUE; - int shift; - int i; - - for (shift = 0, i = 0; i < 4; shift += 8, i++) - { - int val_a = (pix_a >> shift) & 0xffu; - int val_b = (pix_b >> shift) & 0xffu; - int d = val_b - val_a; - - if (diff_stat) - { - diff_stat->ch[i].min_diff = MIN (diff_stat->ch[i].min_diff, d); - diff_stat->ch[i].max_diff = MAX (diff_stat->ch[i].max_diff, d); - } - - if (d < fuzz->a || d > fuzz->b) - ret = FALSE; - } - - return ret; -} - -static gboolean -compare_images (cairo_surface_t *ref_image, - cairo_surface_t *result_image, - const Range *precision, - PixelDiffStat *diff_stat) -{ - Range fuzz = range_get (precision); - ImageIterator it_ref; - ImageIterator it_result; - int x, y; - uint32_t *pix_ref; - uint32_t *pix_result; - - g_assert_cmpint (cairo_image_surface_get_width (ref_image), ==, - cairo_image_surface_get_width (result_image)); - g_assert_cmpint (cairo_image_surface_get_height (ref_image), ==, - cairo_image_surface_get_height (result_image)); - - image_iterator_init (&it_ref, ref_image); - image_iterator_init (&it_result, result_image); - - for (y = 0; y < cairo_image_surface_get_height (ref_image); y++) - { - pix_ref = image_iterator_get_row (&it_ref, y); - pix_result = image_iterator_get_row (&it_result, y); - - for (x = 0; x < cairo_image_surface_get_width (ref_image); x++) - { - if (!fuzzy_match_pixels (*pix_ref, *pix_result, - &fuzz, diff_stat)) - return FALSE; - - pix_ref++; - pix_result++; - } - } - - return TRUE; -} - -static void -assert_software_rendered (void) -{ - MetaBackend *backend = meta_get_backend (); - - g_assert_false (meta_backend_is_rendering_hardware_accelerated (backend)); -} - -static void -capture_view_into (ClutterStageView *view, - MetaRectangle *rect, - uint8_t *buffer, - int stride) -{ - CoglFramebuffer *framebuffer; - ClutterBackend *backend; - CoglContext *context; - CoglBitmap *bitmap; - cairo_rectangle_int_t view_layout; - float view_scale; - float texture_width; - float texture_height; - int x, y; - - framebuffer = clutter_stage_view_get_framebuffer (view); - - view_scale = clutter_stage_view_get_scale (view); - texture_width = roundf (rect->width * view_scale); - texture_height = roundf (rect->height * view_scale); - - backend = clutter_get_default_backend (); - context = clutter_backend_get_cogl_context (backend); - bitmap = cogl_bitmap_new_for_data (context, - texture_width, texture_height, - CLUTTER_CAIRO_FORMAT_ARGB32, - stride, - buffer); - - clutter_stage_view_get_layout (view, &view_layout); - - x = roundf ((rect->x - view_layout.x) * view_scale); - y = roundf ((rect->y - view_layout.y) * view_scale); - cogl_framebuffer_read_pixels_into_bitmap (framebuffer, - x, y, - COGL_READ_PIXELS_COLOR_BUFFER, - bitmap); - - cogl_object_unref (bitmap); -} - -typedef struct -{ - MetaStageWatch *watch; - GMainLoop *loop; - - cairo_surface_t *out_image; -} CaptureViewData; - -static void -on_after_paint (MetaStage *stage, - ClutterStageView *view, - ClutterPaintContext *paint_context, - gpointer user_data) -{ - CaptureViewData *data = user_data; - MetaRectangle rect; - float view_scale; - int texture_width, texture_height; - cairo_surface_t *image; - uint8_t *buffer; - int stride; - - meta_stage_remove_watch (stage, data->watch); - data->watch = NULL; - - clutter_stage_view_get_layout (view, &rect); - view_scale = clutter_stage_view_get_scale (view); - texture_width = roundf (rect.width * view_scale); - texture_height = roundf (rect.height * view_scale); - image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - texture_width, texture_height); - cairo_surface_set_device_scale (image, view_scale, view_scale); - - buffer = cairo_image_surface_get_data (image); - stride = cairo_image_surface_get_stride (image); - - capture_view_into (view, &rect, buffer, stride); - - data->out_image = image; - - cairo_surface_mark_dirty (data->out_image); - - g_main_loop_quit (data->loop); -} - -static cairo_surface_t * -capture_view (ClutterStageView *view) -{ - MetaBackend *backend = meta_get_backend (); - MetaStage *stage = META_STAGE (meta_backend_get_stage (backend)); - CaptureViewData data = { 0 }; - - data.loop = g_main_loop_new (NULL, FALSE); - data.watch = meta_stage_watch_view (stage, view, - META_STAGE_WATCH_AFTER_PAINT, - on_after_paint, - &data); - clutter_stage_view_add_redraw_clip (view, NULL); - clutter_stage_view_schedule_update (view); - - g_main_loop_run (data.loop); - g_main_loop_unref (data.loop); - - g_assert_null (data.watch); - g_assert_nonnull (data.out_image); - - return data.out_image; -} - -static void -depathify (char *path) -{ - int len = strlen (path); - int i; - - for (i = 0; i < len; i++) - { - if (path[i] == '/') - path[i] = '_'; - } -} - -static void -ensure_expected_format (cairo_surface_t **ref_image) -{ - int width, height; - cairo_surface_t *target; - cairo_t *cr; - - if (cairo_image_surface_get_format (*ref_image) == - CAIRO_FORMAT_ARGB32) - return; - - width = cairo_image_surface_get_width (*ref_image); - height = cairo_image_surface_get_height (*ref_image); - target = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); - - cr = cairo_create (target); - cairo_set_source_surface (cr, *ref_image, 0.0, 0.0); - cairo_paint (cr); - cairo_destroy (cr); - - cairo_surface_destroy (*ref_image); - *ref_image = target; -} - -/** - * Tint a color: - * @src Source pixel as x8r8g8b8. - * @add The tint as x8r8g8b8, x8 must be zero; r8, g8 and b8 must be - * no greater than 0xc0 to avoid overflow to another channel. - * Returns: The tinted pixel color as x8r8g8b8, x8 guaranteed to be 0xff. - * - * The source pixel RGB values are divided by 4, and then the tint is added. - * To achieve colors outside of the range of src, a tint color channel must be - * at least 0x40. (0xff / 4 = 0x3f, 0xff - 0x3f = 0xc0) - */ -static uint32_t -tint (uint32_t src, - uint32_t add) -{ - uint32_t v; - - v = ((src & 0xfcfcfcfc) >> 2) | 0xff000000; - - return v + add; -} - -static cairo_surface_t * -visualize_difference (cairo_surface_t *ref_image, - cairo_surface_t *result_image, - const Range *precision) -{ - Range fuzz = range_get (precision); - int width, height; - cairo_surface_t *diff_image; - cairo_t *cr; - ImageIterator it_ref; - ImageIterator it_result; - ImageIterator it_diff; - int y; - - width = cairo_image_surface_get_width (ref_image); - height = cairo_image_surface_get_height (ref_image); - - diff_image = cairo_surface_create_similar_image (ref_image, - CAIRO_FORMAT_ARGB32, - width, - height); - cr = cairo_create (diff_image); - cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0); - cairo_paint (cr); - cairo_set_source_surface (cr, ref_image, 0.0, 0.0); - cairo_set_operator (cr, CAIRO_OPERATOR_HSL_LUMINOSITY); - cairo_paint (cr); - cairo_destroy (cr); - - image_iterator_init (&it_ref, ref_image); - image_iterator_init (&it_result, result_image); - image_iterator_init (&it_diff, diff_image); - - for (y = 0; y < cairo_image_surface_get_height (ref_image); y++) - { - uint32_t *ref_pixel; - uint32_t *result_pixel; - uint32_t *diff_pixel; - int x; - - ref_pixel = image_iterator_get_row (&it_ref, y); - result_pixel = image_iterator_get_row (&it_result, y); - diff_pixel = image_iterator_get_row (&it_diff, y); - - for (x = 0; x < cairo_image_surface_get_width (ref_image); x++) - { - if (fuzzy_match_pixels (*ref_pixel, *result_pixel, - &fuzz, NULL)) - *diff_pixel = tint (*diff_pixel, 0x00008000); /* green */ - else - *diff_pixel = tint (*diff_pixel, 0x00c00000); /* red */ - - ref_pixel++; - result_pixel++; - diff_pixel++; - } - } - - return diff_image; -} - -void -meta_ref_test_verify_view (ClutterStageView *view, - const char *test_name_unescaped, - int test_seq_no, - MetaReftestFlag flags) -{ - cairo_surface_t *view_image; - const char *dist_dir; - g_autofree char *test_name = NULL; - g_autofree char *ref_image_path = NULL; - cairo_surface_t *ref_image; - cairo_status_t ref_status; - - if (flags & META_REFTEST_FLAG_UPDATE_REF) - assert_software_rendered (); - - view_image = capture_view (view); - - test_name = g_strdup (test_name_unescaped + 1); - depathify (test_name); - - dist_dir = g_test_get_dir (G_TEST_DIST); - ref_image_path = g_strdup_printf ("%s/tests/ref-tests/%s_%d.ref.png", - dist_dir, - test_name, test_seq_no); - - ref_image = cairo_image_surface_create_from_png (ref_image_path); - g_assert_nonnull (ref_image); - ref_status = cairo_surface_status (ref_image); - - if (flags & META_REFTEST_FLAG_UPDATE_REF) - { - g_assert (ref_status == CAIRO_STATUS_FILE_NOT_FOUND || - ref_status == CAIRO_STATUS_SUCCESS); - - if (ref_status == CAIRO_STATUS_SUCCESS) - ensure_expected_format (&ref_image); - - if (ref_status == CAIRO_STATUS_SUCCESS && - cairo_image_surface_get_width (ref_image) == - cairo_image_surface_get_width (view_image) && - cairo_image_surface_get_height (ref_image) == - cairo_image_surface_get_height (view_image) && - compare_images (ref_image, view_image, NULL, NULL)) - { - g_message ("Not updating '%s', it didn't change.", ref_image_path); - } - else - { - g_message ("Updating '%s'.", ref_image_path); - g_assert_cmpint (cairo_surface_write_to_png (view_image, ref_image_path), - ==, - CAIRO_STATUS_SUCCESS); - } - } - else - { - const Range gl_fuzz = { -3, 4 }; - PixelDiffStat diff_stat = {}; - - g_assert_cmpint (ref_status, ==, CAIRO_STATUS_SUCCESS); - ensure_expected_format (&ref_image); - - if (!compare_images (ref_image, view_image, &gl_fuzz, - &diff_stat)) - { - cairo_surface_t *diff_image; - const char *build_dir; - g_autofree char *ref_image_copy_path = NULL; - g_autofree char *result_image_path = NULL; - g_autofree char *diff_image_path = NULL; - - diff_image = visualize_difference (ref_image, view_image, - &gl_fuzz); - - build_dir = g_test_get_dir (G_TEST_BUILT); - ref_image_copy_path = - g_strdup_printf ("%s/meson-logs/tests/ref-tests/%s_%d.ref.png", - build_dir, - test_name, test_seq_no); - result_image_path = - g_strdup_printf ("%s/meson-logs/tests/ref-tests/%s_%d.result.png", - build_dir, - test_name, test_seq_no); - diff_image_path = - g_strdup_printf ("%s/meson-logs/tests/ref-tests/%s_%d.diff.png", - build_dir, - test_name, test_seq_no); - - g_mkdir_with_parents (g_path_get_dirname (ref_image_copy_path), - 0755); - - g_assert_cmpint (cairo_surface_write_to_png (ref_image, - ref_image_copy_path), - ==, - CAIRO_STATUS_SUCCESS); - g_assert_cmpint (cairo_surface_write_to_png (view_image, - result_image_path), - ==, - CAIRO_STATUS_SUCCESS); - g_assert_cmpint (cairo_surface_write_to_png (diff_image, - diff_image_path), - ==, - CAIRO_STATUS_SUCCESS); - - g_critical ("Pixel difference exceeds limits " - "(min: [%d, %d, %d, %d], " - "max: [%d, %d, %d, %d])\n" - "See %s, %s, and %s for details.", - diff_stat.ch[0].min_diff, - diff_stat.ch[1].min_diff, - diff_stat.ch[2].min_diff, - diff_stat.ch[3].min_diff, - diff_stat.ch[0].max_diff, - diff_stat.ch[1].max_diff, - diff_stat.ch[2].max_diff, - diff_stat.ch[3].max_diff, - ref_image_copy_path, - result_image_path, - diff_image_path); - } - } - - cairo_surface_destroy (view_image); - cairo_surface_destroy (ref_image); -} - -MetaReftestFlag -meta_ref_test_determine_ref_test_flag (void) -{ - const char *update_tests; - char **update_test_rules; - int n_update_test_rules; - MetaReftestFlag flags; - int i; - - update_tests = g_getenv ("MUTTER_REF_TEST_UPDATE"); - if (!update_tests) - return META_REFTEST_FLAG_NONE; - - if (strcmp (update_tests, "all") == 0) - return META_REFTEST_FLAG_UPDATE_REF; - - update_test_rules = g_strsplit (update_tests, ",", -1); - n_update_test_rules = g_strv_length (update_test_rules); - g_assert_cmpint (n_update_test_rules, >, 0); - - flags = META_REFTEST_FLAG_NONE; - for (i = 0; i < n_update_test_rules; i++) - { - char *rule = update_test_rules[i]; - - if (g_regex_match_simple (rule, g_test_get_path (), 0, 0)) - { - flags |= META_REFTEST_FLAG_UPDATE_REF; - break; - } - } - - g_strfreev (update_test_rules); - - return flags; -} diff --git a/src/tests/meta-ref-test.h b/src/tests/meta-ref-test.h deleted file mode 100644 index 7a71e388f..000000000 --- a/src/tests/meta-ref-test.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2021 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 . - */ - -#ifndef META_REF_TEST_H -#define META_REF_TEST_H - -#include - -#include "clutter/clutter/clutter.h" -#include "meta/boxes.h" - -typedef enum _MetaReftestFlag -{ - META_REFTEST_FLAG_NONE = 0, - META_REFTEST_FLAG_UPDATE_REF = 1 << 0, -} MetaReftestFlag; - -void meta_ref_test_verify_view (ClutterStageView *view, - const char *test_name, - int test_seq_no, - MetaReftestFlag flags); - -MetaReftestFlag meta_ref_test_determine_ref_test_flag (void); - -#endif /* META_REF_TEST_H */ diff --git a/src/tests/meta-test-utils-private.h b/src/tests/meta-test-utils-private.h deleted file mode 100644 index 2b36c58b4..000000000 --- a/src/tests/meta-test-utils-private.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2017-2021 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 . - */ - -#ifndef META_TEST_UTILS_PRIVATE_H -#define META_TEST_UTILS_PRIVATE_H - -#include "tests/meta-test-utils.h" - -void meta_ensure_test_client_path (int argc, - char **argv); - -#endif /* META_TEST_UTILS_PRIVATE_H */ diff --git a/src/tests/meta-test-utils.c b/src/tests/meta-test-utils.c deleted file mode 100644 index 24b7106d1..000000000 --- a/src/tests/meta-test-utils.c +++ /dev/null @@ -1,567 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014-2017 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 . - */ - -#include "config.h" - -#include "tests/meta-test-utils-private.h" - -#include -#include -#include - -#include "core/display-private.h" -#include "core/window-private.h" -#include "meta-test/meta-context-test.h" -#include "wayland/meta-wayland.h" -#include "wayland/meta-xwayland.h" -#include "x11/meta-x11-display-private.h" - -struct _MetaTestClient -{ - char *id; - MetaWindowClientType type; - GSubprocess *subprocess; - GCancellable *cancellable; - GMainLoop *loop; - GDataOutputStream *in; - GDataInputStream *out; - - char *line; - GError **error; - - MetaAsyncWaiter *waiter; -}; - -struct _MetaAsyncWaiter { - XSyncCounter counter; - int counter_value; - XSyncAlarm alarm; - - GMainLoop *loop; - int counter_wait_value; -}; - -G_DEFINE_QUARK (meta-test-client-error-quark, meta_test_client_error) - -static char *test_client_path; - -void -meta_ensure_test_client_path (int argc, - char **argv) -{ - test_client_path = g_test_build_filename (G_TEST_BUILT, - "src", - "tests", - "mutter-test-client", - NULL); - if (!g_file_test (test_client_path, - G_FILE_TEST_EXISTS | G_FILE_TEST_IS_EXECUTABLE)) - { - g_autofree char *basename = NULL; - g_autofree char *dirname = NULL; - - basename = g_path_get_basename (argv[0]); - - dirname = g_path_get_dirname (argv[0]); - test_client_path = g_build_filename (dirname, - "mutter-test-client", NULL); - } - - if (!g_file_test (test_client_path, - G_FILE_TEST_EXISTS | G_FILE_TEST_IS_EXECUTABLE)) - g_error ("mutter-test-client executable not found"); -} - -MetaAsyncWaiter * -meta_async_waiter_new (void) -{ - MetaAsyncWaiter *waiter = g_new0 (MetaAsyncWaiter, 1); - - MetaDisplay *display = meta_get_display (); - Display *xdisplay = display->x11_display->xdisplay; - XSyncValue value; - XSyncAlarmAttributes attr; - - waiter->counter_value = 0; - XSyncIntToValue (&value, waiter->counter_value); - - waiter->counter = XSyncCreateCounter (xdisplay, value); - - attr.trigger.counter = waiter->counter; - attr.trigger.test_type = XSyncPositiveComparison; - - /* Initialize to one greater than the current value */ - attr.trigger.value_type = XSyncRelative; - XSyncIntToValue (&attr.trigger.wait_value, 1); - - /* After triggering, increment test_value by this until - * until the test condition is false */ - XSyncIntToValue (&attr.delta, 1); - - /* we want events (on by default anyway) */ - attr.events = True; - - waiter->alarm = XSyncCreateAlarm (xdisplay, - XSyncCACounter | - XSyncCAValueType | - XSyncCAValue | - XSyncCATestType | - XSyncCADelta | - XSyncCAEvents, - &attr); - - waiter->loop = g_main_loop_new (NULL, FALSE); - - return waiter; -} - -void -meta_async_waiter_destroy (MetaAsyncWaiter *waiter) -{ - MetaDisplay *display = meta_get_display (); - Display *xdisplay = display->x11_display->xdisplay; - - XSyncDestroyAlarm (xdisplay, waiter->alarm); - XSyncDestroyCounter (xdisplay, waiter->counter); - g_main_loop_unref (waiter->loop); -} - -static int -meta_async_waiter_next_value (MetaAsyncWaiter *waiter) -{ - return waiter->counter_value + 1; -} - -static void -meta_async_waiter_wait (MetaAsyncWaiter *waiter, - int wait_value) -{ - if (waiter->counter_value < wait_value) - { - waiter->counter_wait_value = wait_value; - g_main_loop_run (waiter->loop); - waiter->counter_wait_value = 0; - } -} - -void -meta_async_waiter_set_and_wait (MetaAsyncWaiter *waiter) -{ - MetaDisplay *display = meta_get_display (); - Display *xdisplay = display->x11_display->xdisplay; - int wait_value = meta_async_waiter_next_value (waiter); - - XSyncValue sync_value; - XSyncIntToValue (&sync_value, wait_value); - - XSyncSetCounter (xdisplay, waiter->counter, sync_value); - meta_async_waiter_wait (waiter, wait_value); -} - -gboolean -meta_async_waiter_process_x11_event (MetaAsyncWaiter *waiter, - MetaX11Display *x11_display, - XSyncAlarmNotifyEvent *event) -{ - - if (event->alarm != waiter->alarm) - return FALSE; - - waiter->counter_value = XSyncValueLow32 (event->counter_value); - - if (waiter->counter_wait_value != 0 && - waiter->counter_value >= waiter->counter_wait_value) - g_main_loop_quit (waiter->loop); - - return TRUE; -} - -char * -meta_test_client_get_id (MetaTestClient *client) -{ - return client->id; -} - -static void -test_client_line_read (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - MetaTestClient *client = user_data; - - client->line = g_data_input_stream_read_line_finish_utf8 (client->out, - result, - NULL, - client->error); - g_main_loop_quit (client->loop); -} - -gboolean -meta_test_client_do (MetaTestClient *client, - GError **error, - ...) -{ - GString *command = g_string_new (NULL); - char *line = NULL; - va_list vap; - - va_start (vap, error); - - while (TRUE) - { - char *word = va_arg (vap, char *); - char *quoted; - - if (word == NULL) - break; - - if (command->len > 0) - g_string_append_c (command, ' '); - - quoted = g_shell_quote (word); - g_string_append (command, quoted); - g_free (quoted); - } - - va_end (vap); - - g_string_append_c (command, '\n'); - - if (!g_data_output_stream_put_string (client->in, command->str, - client->cancellable, error)) - goto out; - - g_data_input_stream_read_line_async (client->out, - G_PRIORITY_DEFAULT, - client->cancellable, - test_client_line_read, - client); - - client->error = error; - g_main_loop_run (client->loop); - line = client->line; - client->line = NULL; - client->error = NULL; - - if (!line) - { - if (*error == NULL) - { - g_set_error (error, - META_TEST_CLIENT_ERROR, - META_TEST_CLIENT_ERROR_RUNTIME_ERROR, - "test client exited"); - } - goto out; - } - - if (strcmp (line, "OK") != 0) - { - g_set_error (error, - META_TEST_CLIENT_ERROR, - META_TEST_CLIENT_ERROR_RUNTIME_ERROR, - "%s", line); - goto out; - } - - out: - g_string_free (command, TRUE); - g_free (line); - - return *error == NULL; -} - -gboolean -meta_test_client_wait (MetaTestClient *client, - GError **error) -{ - if (client->type == META_WINDOW_CLIENT_TYPE_WAYLAND) - { - return meta_test_client_do (client, error, "sync", NULL); - } - else - { - int wait_value = meta_async_waiter_next_value (client->waiter); - char *counter_str = g_strdup_printf ("%lu", client->waiter->counter); - char *wait_value_str = g_strdup_printf ("%d", wait_value); - gboolean success; - - success = meta_test_client_do (client, error, - "set_counter", counter_str, wait_value_str, - NULL); - g_free (counter_str); - g_free (wait_value_str); - if (!success) - return FALSE; - - meta_async_waiter_wait (client->waiter, wait_value); - return TRUE; - } -} - -MetaWindow * -meta_test_client_find_window (MetaTestClient *client, - const char *window_id, - GError **error) -{ - MetaDisplay *display = meta_get_display (); - GSList *windows; - GSList *l; - MetaWindow *result; - char *expected_title; - - windows = - meta_display_list_windows (display, - META_LIST_INCLUDE_OVERRIDE_REDIRECT); - - expected_title = g_strdup_printf ("test/%s/%s", client->id, window_id); - - result = NULL; - for (l = windows; l; l = l->next) - { - MetaWindow *window = l->data; - - if (g_strcmp0 (window->title, expected_title) == 0) - { - result = window; - break; - } - } - - g_slist_free (windows); - g_free (expected_title); - - if (result == NULL) - { - g_set_error (error, - META_TEST_CLIENT_ERROR, - META_TEST_CLIENT_ERROR_RUNTIME_ERROR, - "window %s/%s isn't known to Mutter", client->id, window_id); - } - - return result; -} - -typedef struct _WaitForShownData -{ - GMainLoop *loop; - MetaWindow *window; - gulong shown_handler_id; -} WaitForShownData; - -static void -on_window_shown (MetaWindow *window, - WaitForShownData *data) -{ - g_main_loop_quit (data->loop); -} - -static gboolean -wait_for_showing_before_redraw (gpointer user_data) -{ - WaitForShownData *data = user_data; - - if (meta_window_is_hidden (data->window)) - { - data->shown_handler_id = g_signal_connect (data->window, "shown", - G_CALLBACK (on_window_shown), - data); - } - else - { - g_main_loop_quit (data->loop); - } - - return FALSE; -} - -void -meta_test_client_wait_for_window_shown (MetaTestClient *client, - MetaWindow *window) -{ - WaitForShownData data = { - .loop = g_main_loop_new (NULL, FALSE), - .window = window, - }; - meta_later_add (META_LATER_BEFORE_REDRAW, - wait_for_showing_before_redraw, - &data, - NULL); - g_main_loop_run (data.loop); - g_clear_signal_handler (&data.shown_handler_id, window); - g_main_loop_unref (data.loop); -} - -gboolean -meta_test_client_process_x11_event (MetaTestClient *client, - MetaX11Display *x11_display, - XSyncAlarmNotifyEvent *event) -{ - if (client->waiter) - { - return meta_async_waiter_process_x11_event (client->waiter, - x11_display, - event); - } - else - { - return FALSE; - } -} - -static gpointer -spawn_xwayland (gpointer user_data) -{ - xcb_connection_t *connection; - - connection = xcb_connect (NULL, NULL); - g_assert_nonnull (connection); - xcb_disconnect (connection); - - return NULL; -} - -MetaTestClient * -meta_test_client_new (MetaContext *context, - const char *id, - MetaWindowClientType type, - GError **error) -{ - MetaTestClient *client; - GSubprocessLauncher *launcher; - GSubprocess *subprocess; - MetaWaylandCompositor *compositor; - const char *wayland_display_name; - const char *x11_display_name; - - launcher = g_subprocess_launcher_new ((G_SUBPROCESS_FLAGS_STDIN_PIPE | - G_SUBPROCESS_FLAGS_STDOUT_PIPE)); - - g_assert (meta_is_wayland_compositor ()); - compositor = meta_context_get_wayland_compositor (context); - wayland_display_name = meta_wayland_get_wayland_display_name (compositor); - x11_display_name = meta_wayland_get_public_xwayland_display_name (compositor); - - g_subprocess_launcher_setenv (launcher, - "WAYLAND_DISPLAY", wayland_display_name, - TRUE); - g_subprocess_launcher_setenv (launcher, - "DISPLAY", x11_display_name, - TRUE); - - subprocess = g_subprocess_launcher_spawn (launcher, - error, - test_client_path, - "--client-id", - id, - (type == META_WINDOW_CLIENT_TYPE_WAYLAND ? - "--wayland" : NULL), - NULL); - g_object_unref (launcher); - - if (!subprocess) - return NULL; - - client = g_new0 (MetaTestClient, 1); - client->type = type; - client->id = g_strdup (id); - client->cancellable = g_cancellable_new (); - client->subprocess = subprocess; - client->in = - g_data_output_stream_new (g_subprocess_get_stdin_pipe (subprocess)); - client->out = - g_data_input_stream_new (g_subprocess_get_stdout_pipe (subprocess)); - client->loop = g_main_loop_new (NULL, FALSE); - - if (client->type == META_WINDOW_CLIENT_TYPE_X11) - { - MetaDisplay *display = meta_get_display (); - - if (!display->x11_display) - { - GThread *thread; - - thread = g_thread_new ("Mutter Spawn Xwayland Thread", - spawn_xwayland, - NULL); - meta_context_test_wait_for_x11_display (META_CONTEXT_TEST (context)); - g_thread_join (thread); - } - - client->waiter = meta_async_waiter_new (); - } - - return client; -} - -gboolean -meta_test_client_quit (MetaTestClient *client, - GError **error) -{ - if (!meta_test_client_do (client, error, "destroy_all", NULL)) - return FALSE; - - if (!meta_test_client_wait (client, error)) - return FALSE; - - return TRUE; -} - -void -meta_test_client_destroy (MetaTestClient *client) -{ - GError *error = NULL; - - if (client->waiter) - meta_async_waiter_destroy (client->waiter); - - g_output_stream_close (G_OUTPUT_STREAM (client->in), NULL, &error); - if (error) - { - g_warning ("Error closing client stdin: %s", error->message); - g_clear_error (&error); - } - g_object_unref (client->in); - - g_input_stream_close (G_INPUT_STREAM (client->out), NULL, &error); - if (error) - { - g_warning ("Error closing client stdout: %s", error->message); - g_clear_error (&error); - } - g_object_unref (client->out); - - g_object_unref (client->cancellable); - g_object_unref (client->subprocess); - g_main_loop_unref (client->loop); - g_free (client->id); - g_free (client); -} - -const char * -meta_test_get_plugin_name (void) -{ - const char *name; - - name = g_getenv ("MUTTER_TEST_PLUGIN_PATH"); - if (name) - return name; - else - return "libdefault"; -} diff --git a/src/tests/meta-test-utils.h b/src/tests/meta-test-utils.h deleted file mode 100644 index 2d8673e13..000000000 --- a/src/tests/meta-test-utils.h +++ /dev/null @@ -1,100 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 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 . - */ - -#ifndef META_TEST_UTILS_H -#define META_TEST_UTILS_H - -#include -#include -#include - -#include "meta/window.h" - -#define META_TEST_CLIENT_ERROR meta_test_client_error_quark () - -typedef enum _MetaClientError -{ - META_TEST_CLIENT_ERROR_BAD_COMMAND, - META_TEST_CLIENT_ERROR_RUNTIME_ERROR, - META_TEST_CLIENT_ERROR_ASSERTION_FAILED -} MetaClientError; - -META_EXPORT -GQuark meta_test_client_error_quark (void); - -typedef struct _MetaAsyncWaiter MetaAsyncWaiter; -typedef struct _MetaTestClient MetaTestClient; - -META_EXPORT -gboolean meta_async_waiter_process_x11_event (MetaAsyncWaiter *waiter, - MetaX11Display *display, - XSyncAlarmNotifyEvent *event); - -META_EXPORT -void meta_async_waiter_set_and_wait (MetaAsyncWaiter *waiter); - -META_EXPORT -MetaAsyncWaiter * meta_async_waiter_new (void); - -META_EXPORT -void meta_async_waiter_destroy (MetaAsyncWaiter *waiter); - -META_EXPORT -char * meta_test_client_get_id (MetaTestClient *client); - -META_EXPORT -gboolean meta_test_client_process_x11_event (MetaTestClient *client, - MetaX11Display *x11_display, - XSyncAlarmNotifyEvent *event); - -META_EXPORT -gboolean meta_test_client_wait (MetaTestClient *client, - GError **error); - -META_EXPORT -gboolean meta_test_client_do (MetaTestClient *client, - GError **error, - ...) G_GNUC_NULL_TERMINATED; - -META_EXPORT -MetaWindow * meta_test_client_find_window (MetaTestClient *client, - const char *window_id, - GError **error); - -META_EXPORT -void meta_test_client_wait_for_window_shown (MetaTestClient *client, - MetaWindow *window); - -META_EXPORT -gboolean meta_test_client_quit (MetaTestClient *client, - GError **error); - -META_EXPORT -MetaTestClient * meta_test_client_new (MetaContext *context, - const char *id, - MetaWindowClientType type, - GError **error); - -META_EXPORT -void meta_test_client_destroy (MetaTestClient *client); - -META_EXPORT -const char * meta_test_get_plugin_name (void); - -#endif /* TEST_UTILS_H */ diff --git a/src/tests/meta-test/meson.build b/src/tests/meta-test/meson.build deleted file mode 100644 index 8cb4e9a9e..000000000 --- a/src/tests/meta-test/meson.build +++ /dev/null @@ -1,9 +0,0 @@ -mutter_test_includesubdir = join_paths(pkgname, 'meta-test') - -mutter_test_public_headers = [ - 'meta-context-test.h', -] - -install_headers(mutter_test_public_headers, - subdir: mutter_test_includesubdir -) diff --git a/src/tests/meta-test/meta-context-test.h b/src/tests/meta-test/meta-context-test.h deleted file mode 100644 index b1f678030..000000000 --- a/src/tests/meta-test/meta-context-test.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2021 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_CONTEXT_TEST_H -#define META_CONTEXT_TEST_H - -#include -#include - -typedef enum _MetaContextTestType -{ - META_CONTEXT_TEST_TYPE_HEADLESS, - META_CONTEXT_TEST_TYPE_NESTED, -} MetaContextTestType; - -typedef enum _MetaContextTestFlag -{ - META_CONTEXT_TEST_FLAG_NONE = 0, - META_CONTEXT_TEST_FLAG_TEST_CLIENT = 1 << 0, - META_CONTEXT_TEST_FLAG_NO_X11 = 1 << 1, -} MetaContextTestFlag; - -#define META_TYPE_CONTEXT_TEST (meta_context_test_get_type ()) -META_EXPORT -G_DECLARE_DERIVABLE_TYPE (MetaContextTest, meta_context_test, - META, CONTEXT_TEST, - MetaContext) - -META_EXPORT -MetaContext * meta_create_test_context (MetaContextTestType type, - MetaContextTestFlag flags); - -META_EXPORT -int meta_context_test_run_tests (MetaContextTest *context_test); - -META_EXPORT -void meta_context_test_wait_for_x11_display (MetaContextTest *context_test); - -#endif /* META_CONTEXT_TEST_H */ diff --git a/src/tests/meta-wayland-test-driver.c b/src/tests/meta-wayland-test-driver.c deleted file mode 100644 index 0eecf8d45..000000000 --- a/src/tests/meta-wayland-test-driver.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (C) 2019 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 . - */ - -#include "config.h" - -#include "tests/meta-wayland-test-driver.h" - -#include - -#include "wayland/meta-wayland-actor-surface.h" -#include "wayland/meta-wayland-private.h" - -#include "test-driver-server-protocol.h" - -enum -{ - SYNC_POINT, - - N_SIGNALS -}; - -static int signals[N_SIGNALS]; - -struct _MetaWaylandTestDriver -{ - GObject parent; - - struct wl_global *test_driver; -}; - -G_DEFINE_TYPE (MetaWaylandTestDriver, meta_wayland_test_driver, - G_TYPE_OBJECT) - -static void -on_actor_destroyed (ClutterActor *actor, - struct wl_resource *callback) -{ - wl_callback_send_done (callback, 0); - wl_resource_destroy (callback); -} - -static void -sync_actor_destroy (struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *surface_resource) -{ - MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); - MetaWaylandActorSurface *actor_surface; - MetaSurfaceActor *actor; - struct wl_resource *callback; - - g_assert_nonnull (surface); - - actor_surface = (MetaWaylandActorSurface *) surface->role; - g_assert_nonnull (actor_surface); - - actor = meta_wayland_actor_surface_get_actor (actor_surface); - g_assert_nonnull (actor); - - callback = wl_resource_create (client, &wl_callback_interface, 1, id); - - g_signal_connect (actor, "destroy", G_CALLBACK (on_actor_destroyed), - callback); -} - -static void -sync_point (struct wl_client *client, - struct wl_resource *resource, - uint32_t sequence) -{ - MetaWaylandTestDriver *test_driver = wl_resource_get_user_data (resource); - - g_signal_emit (test_driver, signals[SYNC_POINT], 0, - sequence, - client); -} - -static const struct test_driver_interface meta_test_driver_interface = { - sync_actor_destroy, - sync_point, -}; - -static void -bind_test_driver (struct wl_client *client, - void *user_data, - uint32_t version, - uint32_t id) -{ - MetaWaylandTestDriver *test_driver = user_data; - struct wl_resource *resource; - - resource = wl_resource_create (client, &test_driver_interface, - version, id); - wl_resource_set_implementation (resource, &meta_test_driver_interface, - test_driver, NULL); -} - -static void -meta_wayland_test_driver_finalize (GObject *object) -{ - MetaWaylandTestDriver *test_driver = META_WAYLAND_TEST_DRIVER (object); - - g_clear_pointer (&test_driver->test_driver, wl_global_destroy); - - G_OBJECT_CLASS (meta_wayland_test_driver_parent_class)->finalize (object); -} - -static void -meta_wayland_test_driver_class_init (MetaWaylandTestDriverClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_wayland_test_driver_finalize; - - signals[SYNC_POINT] = - g_signal_new ("sync-point", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 2, - G_TYPE_UINT, - G_TYPE_POINTER); -} - -static void -meta_wayland_test_driver_init (MetaWaylandTestDriver *test_driver) -{ -} - -MetaWaylandTestDriver * -meta_wayland_test_driver_new (MetaWaylandCompositor *compositor) -{ - MetaWaylandTestDriver *test_driver; - - test_driver = g_object_new (META_TYPE_WAYLAND_TEST_DRIVER, NULL); - test_driver->test_driver = wl_global_create (compositor->wayland_display, - &test_driver_interface, - 1, - test_driver, bind_test_driver); - if (!test_driver->test_driver) - g_error ("Failed to register a global wl-subcompositor object"); - - return test_driver; -} diff --git a/src/tests/meta-wayland-test-driver.h b/src/tests/meta-wayland-test-driver.h deleted file mode 100644 index ccbfe1312..000000000 --- a/src/tests/meta-wayland-test-driver.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2019 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 . - */ - -#ifndef META_WAYLAND_TEST_DRIVER_H -#define META_WAYLAND_TEST_DRIVER_H - -#include "wayland/meta-wayland.h" - -#define META_TYPE_WAYLAND_TEST_DRIVER (meta_wayland_test_driver_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandTestDriver, meta_wayland_test_driver, - META, WAYLAND_TEST_DRIVER, - GObject) - -MetaWaylandTestDriver * meta_wayland_test_driver_new (MetaWaylandCompositor *compositor); - -#endif /* META_WAYLAND_TEST_DRIVER_H */ diff --git a/src/tests/migration/basic-new.xml b/src/tests/migration/basic-new.xml deleted file mode 100644 index 569d1e7cd..000000000 --- a/src/tests/migration/basic-new.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - 0 - 0 - - - HDMI-1 - DEL - DELL P2415Q - GTTPW67P0WFB - - - 3840 - 2160 - 29.981103897094727 - - - - - 3840 - 0 - yes - - - eDP-1 - AUO - 0x123d - 0x00000000 - - - 1920 - 1080 - 60.049972534179688 - - - - - - - - 1920 - 0 - - - DP-2 - ACI - VX239 - ECLMRS004144 - - - 1920 - 1080 - 60 - - - - - 0 - 0 - yes - - - eDP-1 - AUO - 0x123d - 0x00000000 - - - 1920 - 1080 - 60.049468994140625 - - - - - diff --git a/src/tests/migration/basic-old.xml b/src/tests/migration/basic-old.xml deleted file mode 100644 index c47dc55c1..000000000 --- a/src/tests/migration/basic-old.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - no - - DEL - DELL P2415Q - GTTPW67P0WFB - 3840 - 2160 - 29.981103897094727 - 0 - 0 - normal - no - no - no - no - no - - - AUO - 0x123d - 0x00000000 - 1920 - 1080 - 60.049972534179688 - 3840 - 0 - normal - no - no - yes - no - no - - - - no - - ACI - VX239 - ECLMRS004144 - 1920 - 1080 - 60 - 1920 - 0 - normal - no - no - no - no - no - - - AUO - 0x123d - 0x00000000 - 1920 - 1080 - 60.049468994140625 - 0 - 0 - normal - no - no - yes - no - no - - - diff --git a/src/tests/migration/first-rotated-new.xml b/src/tests/migration/first-rotated-new.xml deleted file mode 100644 index 9f875c21f..000000000 --- a/src/tests/migration/first-rotated-new.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - 0 - 0 - - left - no - - - - HDMI-1 - DEL - DELL P2415Q - GTTPW67P0WFB - - - 3840 - 2160 - 29.981103897094727 - - - - - 2160 - 0 - yes - - - eDP-1 - AUO - 0x123d - 0x00000000 - - - 1920 - 1080 - 60.049972534179688 - - - - - diff --git a/src/tests/migration/first-rotated-old.xml b/src/tests/migration/first-rotated-old.xml deleted file mode 100644 index b00a35963..000000000 --- a/src/tests/migration/first-rotated-old.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - no - - DEL - DELL P2415Q - GTTPW67P0WFB - 2160 - 3840 - 29.981103897094727 - 0 - 0 - left - no - no - no - no - no - - - AUO - 0x123d - 0x00000000 - 1920 - 1080 - 60.049972534179688 - 2160 - 0 - normal - no - no - yes - no - no - - - diff --git a/src/tests/migration/oneoff-new-finished.xml b/src/tests/migration/oneoff-new-finished.xml deleted file mode 100644 index 9e71069de..000000000 --- a/src/tests/migration/oneoff-new-finished.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - 0 - 0 - 1 - yes - - - DP-1 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 800 - 600 - 60 - - - - - - DP-2 - MetaProduct's Inc. - MetaMonitor - 0x654321 - - - - diff --git a/src/tests/migration/oneoff-new.xml b/src/tests/migration/oneoff-new.xml deleted file mode 100644 index 02d85f4de..000000000 --- a/src/tests/migration/oneoff-new.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - 0 - 0 - yes - - - DP-1 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 800 - 600 - 60 - - - - - - DP-2 - MetaProduct's Inc. - MetaMonitor - 0x654321 - - - - diff --git a/src/tests/migration/oneoff-old.xml b/src/tests/migration/oneoff-old.xml deleted file mode 100644 index 229379146..000000000 --- a/src/tests/migration/oneoff-old.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - no - - MetaProduct's Inc. - MetaMonitor - 0x123456 - 800 - 600 - 60 - 0 - 0 - normal - no - no - yes - no - no - - - MetaProduct's Inc. - MetaMonitor - 0x654321 - - - diff --git a/src/tests/migration/rotated-new-finished.xml b/src/tests/migration/rotated-new-finished.xml deleted file mode 100644 index a67c376dc..000000000 --- a/src/tests/migration/rotated-new-finished.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - 0 - 0 - 1 - yes - - right - no - - - - DP-1 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 800 - 600 - 60 - - - - - diff --git a/src/tests/migration/rotated-new.xml b/src/tests/migration/rotated-new.xml deleted file mode 100644 index f41964546..000000000 --- a/src/tests/migration/rotated-new.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - 0 - 0 - yes - - right - no - - - - DP-1 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 800 - 600 - 60 - - - - - diff --git a/src/tests/migration/rotated-old.xml b/src/tests/migration/rotated-old.xml deleted file mode 100644 index d252f0117..000000000 --- a/src/tests/migration/rotated-old.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - no - - MetaProduct's Inc. - MetaMonitor - 0x123456 - 600 - 800 - 60 - 0 - 0 - right - no - no - yes - no - no - - - diff --git a/src/tests/migration/tiled-new.xml b/src/tests/migration/tiled-new.xml deleted file mode 100644 index 9fe285ac8..000000000 --- a/src/tests/migration/tiled-new.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - 0 - 0 - yes - - - DP-1 - DEL - DELL P2415Q - GTTPW67P0WFB - - - 3840 - 2160 - 60 - - - - - diff --git a/src/tests/migration/tiled-old.xml b/src/tests/migration/tiled-old.xml deleted file mode 100644 index 8235b31e3..000000000 --- a/src/tests/migration/tiled-old.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - no - - DEL - DELL P2415Q - GTTPW67P0WFB - 1920 - 2160 - 60 - 0 - 0 - normal - no - no - yes - no - no - - - DEL - DELL P2415Q - GTTPW67P0WFB - 1920 - 2160 - 60 - 1920 - 0 - normal - no - no - yes - no - no - - - diff --git a/src/tests/migration/wiggle-new-discarded.xml b/src/tests/migration/wiggle-new-discarded.xml deleted file mode 100644 index fa4090a11..000000000 --- a/src/tests/migration/wiggle-new-discarded.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/src/tests/migration/wiggle-new-finished.xml b/src/tests/migration/wiggle-new-finished.xml deleted file mode 100644 index c4a56556f..000000000 --- a/src/tests/migration/wiggle-new-finished.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - 0 - 0 - 1 - yes - - left - no - - - - DP-1 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 800 - 600 - 60.000801086425781 - - - - - diff --git a/src/tests/migration/wiggle-new.xml b/src/tests/migration/wiggle-new.xml deleted file mode 100644 index cd1acf717..000000000 --- a/src/tests/migration/wiggle-new.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - 0 - 0 - yes - - left - no - - - - DP-1 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 800 - 600 - 60.000801086425781 - - - - - diff --git a/src/tests/migration/wiggle-old.xml b/src/tests/migration/wiggle-old.xml deleted file mode 100644 index b0c996c03..000000000 --- a/src/tests/migration/wiggle-old.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - no - - MetaProduct's Inc. - MetaMonitor - 0x123456 - 600 - 800 - 60.000801086425781 - 0 - 0 - left - no - no - yes - no - no - - - diff --git a/src/tests/monitor-config-migration-unit-tests.c b/src/tests/monitor-config-migration-unit-tests.c deleted file mode 100644 index bb2ac62cc..000000000 --- a/src/tests/monitor-config-migration-unit-tests.c +++ /dev/null @@ -1,136 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 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 . - */ - -#include "config.h" - -#include "tests/monitor-config-migration-unit-tests.h" - -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-monitor-config-manager.h" -#include "backends/meta-monitor-config-store.h" -#include "backends/meta-monitor-manager-private.h" -#include "backends/meta-monitor-config-migration.h" -#include "tests/monitor-test-utils.h" - -static void -test_migration (const char *old_config, - const char *new_config) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorConfigManager *config_manager = monitor_manager->config_manager; - MetaMonitorConfigStore *config_store = - meta_monitor_config_manager_get_store (config_manager); - GError *error = NULL; - const char *old_config_path; - g_autoptr (GFile) old_config_file = NULL; - g_autofree char *migrated_path = NULL; - const char *expected_path; - g_autofree char *migrated_data = NULL; - g_autofree char *expected_data = NULL; - g_autoptr (GFile) migrated_file = NULL; - - migrated_path = g_build_filename (g_get_tmp_dir (), - "test-migrated-monitors.xml", - NULL); - if (!meta_monitor_config_store_set_custom (config_store, "/dev/null", - migrated_path, - &error)) - g_error ("Failed to set custom config store: %s", error->message); - - old_config_path = g_test_get_filename (G_TEST_DIST, "tests", "migration", - old_config, NULL); - old_config_file = g_file_new_for_path (old_config_path); - if (!meta_migrate_old_monitors_config (config_store, - old_config_file, - &error)) - g_error ("Failed to migrate config: %s", error->message); - - expected_path = g_test_get_filename (G_TEST_DIST, "tests", "migration", - new_config, NULL); - - expected_data = read_file (expected_path); - migrated_data = read_file (migrated_path); - - g_assert_nonnull (expected_data); - g_assert_nonnull (migrated_data); - - g_assert_cmpstr (expected_data, ==, migrated_data); - - migrated_file = g_file_new_for_path (migrated_path); - if (!g_file_delete (migrated_file, NULL, &error)) - g_error ("Failed to remove test data output file: %s", error->message); -} - -static void -meta_test_monitor_config_migration_basic (void) -{ - test_migration ("basic-old.xml", "basic-new.xml"); -} - -static void -meta_test_monitor_config_migration_rotated (void) -{ - test_migration ("rotated-old.xml", "rotated-new.xml"); -} - -static void -meta_test_monitor_config_migration_tiled (void) -{ - test_migration ("tiled-old.xml", "tiled-new.xml"); -} - -static void -meta_test_monitor_config_migration_first_rotated (void) -{ - test_migration ("first-rotated-old.xml", "first-rotated-new.xml"); -} - -static void -meta_test_monitor_config_migration_oneoff (void) -{ - test_migration ("oneoff-old.xml", "oneoff-new.xml"); -} - -static void -meta_test_monitor_config_migration_wiggle (void) -{ - test_migration ("wiggle-old.xml", "wiggle-new.xml"); -} - -void -init_monitor_config_migration_tests (void) -{ - g_test_add_func ("/backends/monitor-config-migration/basic", - meta_test_monitor_config_migration_basic); - g_test_add_func ("/backends/monitor-config-migration/rotated", - meta_test_monitor_config_migration_rotated); - g_test_add_func ("/backends/monitor-config-migration/tiled", - meta_test_monitor_config_migration_tiled); - g_test_add_func ("/backends/monitor-config-migration/first-rotated", - meta_test_monitor_config_migration_first_rotated); - g_test_add_func ("/backends/monitor-config-migration/oneoff", - meta_test_monitor_config_migration_oneoff); - g_test_add_func ("/backends/monitor-config-migration/wiggle", - meta_test_monitor_config_migration_wiggle); -} diff --git a/src/tests/monitor-config-migration-unit-tests.h b/src/tests/monitor-config-migration-unit-tests.h deleted file mode 100644 index a8d18de9a..000000000 --- a/src/tests/monitor-config-migration-unit-tests.h +++ /dev/null @@ -1,25 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 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 . - */ - -#ifndef MONITOR_CONFIG_MIGRATION_UNIT_TESTS_H -#define MONITOR_CONFIG_MIGRATION_UNIT_TESTS_H - -void init_monitor_config_migration_tests (void); - -#endif /* MONITOR_CONFIG_MIGRATION_UNIT_TESTS_H */ diff --git a/src/tests/monitor-configs/first-rotated.xml b/src/tests/monitor-configs/first-rotated.xml deleted file mode 100644 index 59a42bef5..000000000 --- a/src/tests/monitor-configs/first-rotated.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - 0 - 0 - yes - - right - no - - - - DP-1 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 1024 - 768 - 60.000495910644531 - - - - - 768 - 0 - - normal - no - - - - DP-2 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 1024 - 768 - 60.000495910644531 - - - - - diff --git a/src/tests/monitor-configs/fractional-scale.xml b/src/tests/monitor-configs/fractional-scale.xml deleted file mode 100644 index 991a47d14..000000000 --- a/src/tests/monitor-configs/fractional-scale.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - 0 - 0 - yes - 1.5 - - - DP-1 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 1200 - 900 - 60.000495910644531 - - - - - diff --git a/src/tests/monitor-configs/high-precision-fractional-scale.xml b/src/tests/monitor-configs/high-precision-fractional-scale.xml deleted file mode 100644 index 2a0d43912..000000000 --- a/src/tests/monitor-configs/high-precision-fractional-scale.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - 0 - 0 - yes - 1.3763440847396851 - - - DP-1 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 1024 - 768 - 60.000495910644531 - - - - - diff --git a/src/tests/monitor-configs/interlaced.xml b/src/tests/monitor-configs/interlaced.xml deleted file mode 100644 index b02f1cf94..000000000 --- a/src/tests/monitor-configs/interlaced.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - 0 - 0 - yes - - - DP-1 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 1024 - 768 - 60.000495910644531 - interlace - - - - - diff --git a/src/tests/monitor-configs/lid-scale.xml b/src/tests/monitor-configs/lid-scale.xml deleted file mode 100644 index d5bfecb11..000000000 --- a/src/tests/monitor-configs/lid-scale.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - 0 - 0 - yes - 2 - - - eDP-1 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 1920 - 1080 - 60.000495910644531 - - - - - diff --git a/src/tests/monitor-configs/lid-switch.xml b/src/tests/monitor-configs/lid-switch.xml deleted file mode 100644 index 1d43c98bd..000000000 --- a/src/tests/monitor-configs/lid-switch.xml +++ /dev/null @@ -1,91 +0,0 @@ - - - - 0 - 0 - yes - - - eDP-1 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 1024 - 768 - 60.000495910644531 - - - - - 1024 - 0 - - right - no - - - - DP-1 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 1024 - 768 - 60.000495910644531 - - - - - - - 0 - 0 - yes - - left - no - - - - DP-1 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 1024 - 768 - 60.000495910644531 - - - - - - - 0 - 0 - yes - - right - no - - - - eDP-1 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 1024 - 768 - 60.000495910644531 - - - - - diff --git a/src/tests/monitor-configs/mirrored.xml b/src/tests/monitor-configs/mirrored.xml deleted file mode 100644 index 7866b4aae..000000000 --- a/src/tests/monitor-configs/mirrored.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - 0 - 0 - yes - - - DP-1 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 800 - 600 - 60.000495910644531 - - - - - DP-2 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 800 - 600 - 60.000495910644531 - - - - - diff --git a/src/tests/monitor-configs/non-preferred-tiled-custom-resolution.xml b/src/tests/monitor-configs/non-preferred-tiled-custom-resolution.xml deleted file mode 100644 index 5f46583eb..000000000 --- a/src/tests/monitor-configs/non-preferred-tiled-custom-resolution.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - 0 - 0 - yes - - - DP-2 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 800 - 600 - 60 - - - - - diff --git a/src/tests/monitor-configs/oneoff.xml b/src/tests/monitor-configs/oneoff.xml deleted file mode 100644 index 63e641cf0..000000000 --- a/src/tests/monitor-configs/oneoff.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - 0 - 0 - 1 - yes - - - DP-1 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 800 - 600 - 60 - - - - - - DP-2 - MetaProduct's Inc. - MetaMonitor - 0x654321 - - - - diff --git a/src/tests/monitor-configs/primary.xml b/src/tests/monitor-configs/primary.xml deleted file mode 100644 index ce78b1099..000000000 --- a/src/tests/monitor-configs/primary.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - 0 - 0 - no - - - DP-1 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 1024 - 768 - 60.000495910644531 - - - - - 1024 - 0 - yes - - - DP-2 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 800 - 600 - 60.000495910644531 - - - - - diff --git a/src/tests/monitor-configs/scale.xml b/src/tests/monitor-configs/scale.xml deleted file mode 100644 index c011900ef..000000000 --- a/src/tests/monitor-configs/scale.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - 0 - 0 - yes - 2 - - - DP-1 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 1920 - 1080 - 60.000495910644531 - - - - - diff --git a/src/tests/monitor-configs/second-rotated-tiled.xml b/src/tests/monitor-configs/second-rotated-tiled.xml deleted file mode 100644 index 14ba91b4e..000000000 --- a/src/tests/monitor-configs/second-rotated-tiled.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - 0 - 256 - yes - - - DP-1 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 1024 - 768 - 60.000495910644531 - - - - - 1024 - 0 - - left - no - - - - DP-2 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 800 - 600 - 60.000495910644531 - - - - - diff --git a/src/tests/monitor-configs/second-rotated.xml b/src/tests/monitor-configs/second-rotated.xml deleted file mode 100644 index 885b2bf83..000000000 --- a/src/tests/monitor-configs/second-rotated.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - 0 - 256 - yes - - - DP-1 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 1024 - 768 - 60.000495910644531 - - - - - 1024 - 0 - - left - no - - - - DP-2 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 1024 - 768 - 60.000495910644531 - - - - - diff --git a/src/tests/monitor-configs/single.xml b/src/tests/monitor-configs/single.xml deleted file mode 100644 index cc01b4a63..000000000 --- a/src/tests/monitor-configs/single.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - 0 - 0 - yes - - - DP-1 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 1920 - 1080 - 60.000495910644531 - - - - - diff --git a/src/tests/monitor-configs/tiled-custom-resolution.xml b/src/tests/monitor-configs/tiled-custom-resolution.xml deleted file mode 100644 index 85939dd1f..000000000 --- a/src/tests/monitor-configs/tiled-custom-resolution.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - 0 - 0 - yes - 2 - - - DP-1 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 640 - 480 - 60.000495910644531 - - - - - diff --git a/src/tests/monitor-configs/tiled.xml b/src/tests/monitor-configs/tiled.xml deleted file mode 100644 index 0ed149ffc..000000000 --- a/src/tests/monitor-configs/tiled.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - 0 - 0 - yes - 2 - - - DP-1 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 800 - 600 - 60.000495910644531 - - - - - diff --git a/src/tests/monitor-configs/underscanning.xml b/src/tests/monitor-configs/underscanning.xml deleted file mode 100644 index 3ab02476d..000000000 --- a/src/tests/monitor-configs/underscanning.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - 0 - 0 - yes - - - DP-1 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 1024 - 768 - 60.000495910644531 - - yes - - - - diff --git a/src/tests/monitor-configs/vertical.xml b/src/tests/monitor-configs/vertical.xml deleted file mode 100644 index 0546b055c..000000000 --- a/src/tests/monitor-configs/vertical.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - 0 - 0 - yes - - - DP-1 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 1024 - 768 - 60.000495910644531 - - - - - 0 - 768 - - - DP-2 - MetaProduct's Inc. - MetaMonitor - 0x123456 - - - 800 - 600 - 60.000495910644531 - - - - - diff --git a/src/tests/monitor-store-unit-tests.c b/src/tests/monitor-store-unit-tests.c deleted file mode 100644 index b9d5622b7..000000000 --- a/src/tests/monitor-store-unit-tests.c +++ /dev/null @@ -1,864 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 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 . - */ - -#include "config.h" - -#include "tests/monitor-store-unit-tests.h" - -#include "backends/meta-backend-private.h" -#include "backends/meta-monitor-config-store.h" -#include "backends/meta-monitor-config-manager.h" -#include "backends/meta-monitor-manager-private.h" -#include "tests/monitor-test-utils.h" - -#define MAX_N_MONITORS 10 -#define MAX_N_LOGICAL_MONITORS 10 -#define MAX_N_CONFIGURATIONS 10 - -typedef struct _MonitorStoreTestCaseMonitorMode -{ - int width; - int height; - float refresh_rate; - MetaCrtcModeFlag flags; -} MonitorStoreTestCaseMonitorMode; - -typedef struct _MonitorStoreTestCaseMonitor -{ - const char *connector; - const char *vendor; - const char *product; - const char *serial; - MonitorStoreTestCaseMonitorMode mode; - gboolean is_underscanning; -} MonitorStoreTestCaseMonitor; - -typedef struct _MonitorStoreTestCaseLogicalMonitor -{ - MetaRectangle layout; - float scale; - MetaMonitorTransform transform; - gboolean is_primary; - gboolean is_presentation; - MonitorStoreTestCaseMonitor monitors[MAX_N_MONITORS]; - int n_monitors; -} MonitorStoreTestCaseLogicalMonitor; - -typedef struct _MonitorStoreTestConfiguration -{ - MonitorStoreTestCaseLogicalMonitor logical_monitors[MAX_N_LOGICAL_MONITORS]; - int n_logical_monitors; -} MonitorStoreTestConfiguration; - -typedef struct _MonitorStoreTestExpect -{ - MonitorStoreTestConfiguration configurations[MAX_N_CONFIGURATIONS]; - int n_configurations; -} MonitorStoreTestExpect; - -static MetaMonitorsConfigKey * -create_config_key_from_expect (MonitorStoreTestConfiguration *expect_config) -{ - MetaMonitorsConfigKey *config_key; - GList *monitor_specs; - int i; - - monitor_specs = NULL; - for (i = 0; i < expect_config->n_logical_monitors; i++) - { - int j; - - for (j = 0; j < expect_config->logical_monitors[i].n_monitors; j++) - { - MetaMonitorSpec *monitor_spec; - MonitorStoreTestCaseMonitor *test_monitor = - &expect_config->logical_monitors[i].monitors[j]; - - monitor_spec = g_new0 (MetaMonitorSpec, 1); - - monitor_spec->connector = g_strdup (test_monitor->connector); - monitor_spec->vendor = g_strdup (test_monitor->vendor); - monitor_spec->product = g_strdup (test_monitor->product); - monitor_spec->serial = g_strdup (test_monitor->serial); - - monitor_specs = g_list_prepend (monitor_specs, monitor_spec); - } - } - - g_assert_nonnull (monitor_specs); - - monitor_specs = g_list_sort (monitor_specs, - (GCompareFunc) meta_monitor_spec_compare); - - config_key = g_new0 (MetaMonitorsConfigKey, 1); - *config_key = (MetaMonitorsConfigKey) { - .monitor_specs = monitor_specs - }; - - return config_key; -} - -static void -check_monitor_store_configuration (MetaMonitorConfigStore *config_store, - MonitorStoreTestConfiguration *config_expect) -{ - MetaMonitorsConfigKey *config_key; - MetaMonitorsConfig *config; - GList *l; - int i; - - config_key = create_config_key_from_expect (config_expect); - config = meta_monitor_config_store_lookup (config_store, config_key); - g_assert_nonnull (config); - - g_assert (meta_monitors_config_key_equal (config->key, config_key)); - meta_monitors_config_key_free (config_key); - - g_assert_cmpuint (g_list_length (config->logical_monitor_configs), - ==, - config_expect->n_logical_monitors); - - for (l = config->logical_monitor_configs, i = 0; l; l = l->next, i++) - { - MetaLogicalMonitorConfig *logical_monitor_config = l->data; - GList *k; - int j; - - g_assert (meta_rectangle_equal (&logical_monitor_config->layout, - &config_expect->logical_monitors[i].layout)); - g_assert_cmpfloat (logical_monitor_config->scale, - ==, - config_expect->logical_monitors[i].scale); - g_assert_cmpint (logical_monitor_config->transform, - ==, - config_expect->logical_monitors[i].transform); - g_assert_cmpint (logical_monitor_config->is_primary, - ==, - config_expect->logical_monitors[i].is_primary); - g_assert_cmpint (logical_monitor_config->is_presentation, - ==, - config_expect->logical_monitors[i].is_presentation); - - g_assert_cmpint ((int) g_list_length (logical_monitor_config->monitor_configs), - ==, - config_expect->logical_monitors[i].n_monitors); - - for (k = logical_monitor_config->monitor_configs, j = 0; - k; - k = k->next, j++) - { - MetaMonitorConfig *monitor_config = k->data; - MonitorStoreTestCaseMonitor *test_monitor = - &config_expect->logical_monitors[i].monitors[j]; - - g_assert_cmpstr (monitor_config->monitor_spec->connector, - ==, - test_monitor->connector); - g_assert_cmpstr (monitor_config->monitor_spec->vendor, - ==, - test_monitor->vendor); - g_assert_cmpstr (monitor_config->monitor_spec->product, - ==, - test_monitor->product); - g_assert_cmpstr (monitor_config->monitor_spec->serial, - ==, - test_monitor->serial); - - g_assert_cmpint (monitor_config->mode_spec->width, - ==, - test_monitor->mode.width); - g_assert_cmpint (monitor_config->mode_spec->height, - ==, - test_monitor->mode.height); - g_assert_cmpfloat (monitor_config->mode_spec->refresh_rate, - ==, - test_monitor->mode.refresh_rate); - g_assert_cmpint (monitor_config->mode_spec->flags, - ==, - test_monitor->mode.flags); - g_assert_cmpint (monitor_config->enable_underscanning, - ==, - test_monitor->is_underscanning); - } - } -} - -static void -check_monitor_store_configurations (MonitorStoreTestExpect *expect) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorConfigManager *config_manager = monitor_manager->config_manager; - MetaMonitorConfigStore *config_store = - meta_monitor_config_manager_get_store (config_manager); - int i; - - g_assert_cmpint (meta_monitor_config_store_get_config_count (config_store), - ==, - expect->n_configurations); - - for (i = 0; i < expect->n_configurations; i++) - check_monitor_store_configuration (config_store, &expect->configurations[i]); -} - -static void -meta_test_monitor_store_single (void) -{ - MonitorStoreTestExpect expect = { - .configurations = { - { - .logical_monitors = { - { - .layout = { - .x = 0, - .y = 0, - .width = 1920, - .height = 1080 - }, - .scale = 1, - .is_primary = TRUE, - .is_presentation = FALSE, - .monitors = { - { - .connector = "DP-1", - .vendor = "MetaProduct's Inc.", - .product = "MetaMonitor", - .serial = "0x123456", - .mode = { - .width = 1920, - .height = 1080, - .refresh_rate = 60.000495910644531 - } - } - }, - .n_monitors = 1, - } - }, - .n_logical_monitors = 1 - } - }, - .n_configurations = 1 - }; - - set_custom_monitor_config ("single.xml"); - - check_monitor_store_configurations (&expect); -} - -static void -meta_test_monitor_store_vertical (void) -{ - MonitorStoreTestExpect expect = { - .configurations = { - { - .logical_monitors = { - { - .layout = { - .x = 0, - .y = 0, - .width = 1024, - .height = 768 - }, - .scale = 1, - .is_primary = TRUE, - .is_presentation = FALSE, - .monitors = { - { - .connector = "DP-1", - .vendor = "MetaProduct's Inc.", - .product = "MetaMonitor", - .serial = "0x123456", - .mode = { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531 - } - } - }, - .n_monitors = 1, - }, - { - .layout = { - .x = 0, - .y = 768, - .width = 800, - .height = 600 - }, - .scale = 1, - .is_primary = FALSE, - .is_presentation = FALSE, - .monitors = { - { - .connector = "DP-2", - .vendor = "MetaProduct's Inc.", - .product = "MetaMonitor", - .serial = "0x123456", - .mode = { - .width = 800, - .height = 600, - .refresh_rate = 60.000495910644531 - } - } - }, - .n_monitors = 1, - } - }, - .n_logical_monitors = 2 - } - }, - .n_configurations = 1 - }; - - set_custom_monitor_config ("vertical.xml"); - - check_monitor_store_configurations (&expect); -} - -static void -meta_test_monitor_store_primary (void) -{ - MonitorStoreTestExpect expect = { - .configurations = { - { - .logical_monitors = { - { - .layout = { - .x = 0, - .y = 0, - .width = 1024, - .height = 768 - }, - .scale = 1, - .is_primary = FALSE, - .is_presentation = FALSE, - .monitors = { - { - .connector = "DP-1", - .vendor = "MetaProduct's Inc.", - .product = "MetaMonitor", - .serial = "0x123456", - .mode = { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531 - } - } - }, - .n_monitors = 1, - }, - { - .layout = { - .x = 1024, - .y = 0, - .width = 800, - .height = 600 - }, - .scale = 1, - .is_primary = TRUE, - .is_presentation = FALSE, - .monitors = { - { - .connector = "DP-2", - .vendor = "MetaProduct's Inc.", - .product = "MetaMonitor", - .serial = "0x123456", - .mode = { - .width = 800, - .height = 600, - .refresh_rate = 60.000495910644531 - } - } - }, - .n_monitors = 1, - } - }, - .n_logical_monitors = 2 - } - }, - .n_configurations = 1 - }; - - set_custom_monitor_config ("primary.xml"); - - check_monitor_store_configurations (&expect); -} - -static void -meta_test_monitor_store_underscanning (void) -{ - MonitorStoreTestExpect expect = { - .configurations = { - { - .logical_monitors = { - { - .layout = { - .x = 0, - .y = 0, - .width = 1024, - .height = 768 - }, - .scale = 1, - .is_primary = TRUE, - .is_presentation = FALSE, - .monitors = { - { - .connector = "DP-1", - .vendor = "MetaProduct's Inc.", - .product = "MetaMonitor", - .serial = "0x123456", - .is_underscanning = TRUE, - .mode = { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531 - } - } - }, - .n_monitors = 1, - }, - }, - .n_logical_monitors = 1 - } - }, - .n_configurations = 1 - }; - - set_custom_monitor_config ("underscanning.xml"); - - check_monitor_store_configurations (&expect); -} - -static void -meta_test_monitor_store_scale (void) -{ - MonitorStoreTestExpect expect = { - .configurations = { - { - .logical_monitors = { - { - .layout = { - .x = 0, - .y = 0, - .width = 960, - .height = 540 - }, - .scale = 2, - .is_primary = TRUE, - .is_presentation = FALSE, - .monitors = { - { - .connector = "DP-1", - .vendor = "MetaProduct's Inc.", - .product = "MetaMonitor", - .serial = "0x123456", - .mode = { - .width = 1920, - .height = 1080, - .refresh_rate = 60.000495910644531 - } - } - }, - .n_monitors = 1, - } - }, - .n_logical_monitors = 1 - } - }, - .n_configurations = 1 - }; - - if (!meta_is_stage_views_enabled ()) - { - g_test_skip ("Not using stage views"); - return; - } - - set_custom_monitor_config ("scale.xml"); - - check_monitor_store_configurations (&expect); -} - -static void -meta_test_monitor_store_fractional_scale (void) -{ - MonitorStoreTestExpect expect = { - .configurations = { - { - .logical_monitors = { - { - .layout = { - .x = 0, - .y = 0, - .width = 800, - .height = 600 - }, - .scale = 1.5, - .is_primary = TRUE, - .is_presentation = FALSE, - .monitors = { - { - .connector = "DP-1", - .vendor = "MetaProduct's Inc.", - .product = "MetaMonitor", - .serial = "0x123456", - .mode = { - .width = 1200, - .height = 900, - .refresh_rate = 60.000495910644531 - } - } - }, - .n_monitors = 1, - } - }, - .n_logical_monitors = 1 - } - }, - .n_configurations = 1 - }; - - if (!meta_is_stage_views_enabled ()) - { - g_test_skip ("Not using stage views"); - return; - } - - set_custom_monitor_config ("fractional-scale.xml"); - - check_monitor_store_configurations (&expect); -} - -static void -meta_test_monitor_store_high_precision_fractional_scale (void) -{ - MonitorStoreTestExpect expect = { - .configurations = { - { - .logical_monitors = { - { - .layout = { - .x = 0, - .y = 0, - .width = 744, - .height = 558 - }, - .scale = 1.3763440847396851, - .is_primary = TRUE, - .is_presentation = FALSE, - .monitors = { - { - .connector = "DP-1", - .vendor = "MetaProduct's Inc.", - .product = "MetaMonitor", - .serial = "0x123456", - .mode = { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531 - } - } - }, - .n_monitors = 1, - } - }, - .n_logical_monitors = 1 - } - }, - .n_configurations = 1 - }; - - if (!meta_is_stage_views_enabled ()) - { - g_test_skip ("Not using stage views"); - return; - } - - set_custom_monitor_config ("high-precision-fractional-scale.xml"); - - check_monitor_store_configurations (&expect); -} - -static void -meta_test_monitor_store_mirrored (void) -{ - MonitorStoreTestExpect expect = { - .configurations = { - { - .logical_monitors = { - { - .layout = { - .x = 0, - .y = 0, - .width = 800, - .height = 600 - }, - .scale = 1, - .is_primary = TRUE, - .monitors = { - { - .connector = "DP-1", - .vendor = "MetaProduct's Inc.", - .product = "MetaMonitor", - .serial = "0x123456", - .mode = { - .width = 800, - .height = 600, - .refresh_rate = 60.000495910644531 - } - }, - { - .connector = "DP-2", - .vendor = "MetaProduct's Inc.", - .product = "MetaMonitor", - .serial = "0x123456", - .mode = { - .width = 800, - .height = 600, - .refresh_rate = 60.000495910644531 - } - } - }, - .n_monitors = 2, - } - }, - .n_logical_monitors = 1 - } - }, - .n_configurations = 1 - }; - - set_custom_monitor_config ("mirrored.xml"); - - check_monitor_store_configurations (&expect); -} - -static void -meta_test_monitor_store_first_rotated (void) -{ - MonitorStoreTestExpect expect = { - .configurations = { - { - .logical_monitors = { - { - .layout = { - .x = 0, - .y = 0, - .width = 768, - .height = 1024 - }, - .scale = 1, - .transform = META_MONITOR_TRANSFORM_270, - .is_primary = TRUE, - .is_presentation = FALSE, - .monitors = { - { - .connector = "DP-1", - .vendor = "MetaProduct's Inc.", - .product = "MetaMonitor", - .serial = "0x123456", - .mode = { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531 - } - } - }, - .n_monitors = 1, - }, - { - .layout = { - .x = 768, - .y = 0, - .width = 1024, - .height = 768 - }, - .scale = 1, - .transform = META_MONITOR_TRANSFORM_NORMAL, - .is_primary = FALSE, - .is_presentation = FALSE, - .monitors = { - { - .connector = "DP-2", - .vendor = "MetaProduct's Inc.", - .product = "MetaMonitor", - .serial = "0x123456", - .mode = { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531 - } - } - }, - .n_monitors = 1, - } - }, - .n_logical_monitors = 2 - } - }, - .n_configurations = 1 - }; - - set_custom_monitor_config ("first-rotated.xml"); - - check_monitor_store_configurations (&expect); -} - -static void -meta_test_monitor_store_second_rotated (void) -{ - MonitorStoreTestExpect expect = { - .configurations = { - { - .logical_monitors = { - { - .layout = { - .x = 0, - .y = 256, - .width = 1024, - .height = 768 - }, - .scale = 1, - .transform = META_MONITOR_TRANSFORM_NORMAL, - .is_primary = TRUE, - .is_presentation = FALSE, - .monitors = { - { - .connector = "DP-1", - .vendor = "MetaProduct's Inc.", - .product = "MetaMonitor", - .serial = "0x123456", - .mode = { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531 - } - } - }, - .n_monitors = 1, - }, - { - .layout = { - .x = 1024, - .y = 0, - .width = 768, - .height = 1024 - }, - .scale = 1, - .transform = META_MONITOR_TRANSFORM_90, - .is_primary = FALSE, - .is_presentation = FALSE, - .monitors = { - { - .connector = "DP-2", - .vendor = "MetaProduct's Inc.", - .product = "MetaMonitor", - .serial = "0x123456", - .mode = { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531 - } - } - }, - .n_monitors = 1, - } - }, - .n_logical_monitors = 2 - } - }, - .n_configurations = 1 - }; - - set_custom_monitor_config ("second-rotated.xml"); - - check_monitor_store_configurations (&expect); -} - -static void -meta_test_monitor_store_interlaced (void) -{ - MonitorStoreTestExpect expect = { - .configurations = { - { - .logical_monitors = { - { - .layout = { - .x = 0, - .y = 0, - .width = 1024, - .height = 768 - }, - .scale = 1, - .is_primary = TRUE, - .is_presentation = FALSE, - .monitors = { - { - .connector = "DP-1", - .vendor = "MetaProduct's Inc.", - .product = "MetaMonitor", - .serial = "0x123456", - .mode = { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531, - .flags = META_CRTC_MODE_FLAG_INTERLACE, - } - } - }, - .n_monitors = 1, - }, - }, - .n_logical_monitors = 1 - } - }, - .n_configurations = 1 - }; - - set_custom_monitor_config ("interlaced.xml"); - - check_monitor_store_configurations (&expect); -} - -void -init_monitor_store_tests (void) -{ - g_test_add_func ("/backends/monitor-store/single", - meta_test_monitor_store_single); - g_test_add_func ("/backends/monitor-store/vertical", - meta_test_monitor_store_vertical); - g_test_add_func ("/backends/monitor-store/primary", - meta_test_monitor_store_primary); - g_test_add_func ("/backends/monitor-store/underscanning", - meta_test_monitor_store_underscanning); - g_test_add_func ("/backends/monitor-store/scale", - meta_test_monitor_store_scale); - g_test_add_func ("/backends/monitor-store/fractional-scale", - meta_test_monitor_store_fractional_scale); - g_test_add_func ("/backends/monitor-store/high-precision-fractional-scale", - meta_test_monitor_store_high_precision_fractional_scale); - g_test_add_func ("/backends/monitor-store/mirrored", - meta_test_monitor_store_mirrored); - g_test_add_func ("/backends/monitor-store/first-rotated", - meta_test_monitor_store_first_rotated); - g_test_add_func ("/backends/monitor-store/second-rotated", - meta_test_monitor_store_second_rotated); - g_test_add_func ("/backends/monitor-store/interlaced", - meta_test_monitor_store_interlaced); -} diff --git a/src/tests/monitor-store-unit-tests.h b/src/tests/monitor-store-unit-tests.h deleted file mode 100644 index 2e9496d32..000000000 --- a/src/tests/monitor-store-unit-tests.h +++ /dev/null @@ -1,25 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 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 . - */ - -#ifndef MONITOR_STORE_UNIT_TESTS_H -#define MONITOR_STORE_UNIT_TESTS_H - -void init_monitor_store_tests (void); - -#endif /* MONITOR_STORE_UNIT_TESTS_H */ diff --git a/src/tests/monitor-test-utils.c b/src/tests/monitor-test-utils.c deleted file mode 100644 index 933b8912a..000000000 --- a/src/tests/monitor-test-utils.c +++ /dev/null @@ -1,780 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 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 . - */ - -#include "config.h" - -#include "tests/monitor-test-utils.h" - -#include "backends/meta-backend-private.h" -#include "backends/meta-crtc.h" -#include "backends/meta-logical-monitor.h" -#include "backends/meta-monitor-config-manager.h" -#include "backends/meta-monitor-config-store.h" -#include "backends/meta-output.h" -#include "tests/meta-test-utils.h" -#include "meta-backend-test.h" - -MetaGpu * -test_get_gpu (void) -{ - return META_GPU (meta_backend_get_gpus (meta_get_backend ())->data); -} - -void -set_custom_monitor_config (const char *filename) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorConfigManager *config_manager = monitor_manager->config_manager; - MetaMonitorConfigStore *config_store; - GError *error = NULL; - const char *path; - - g_assert_nonnull (config_manager); - - config_store = meta_monitor_config_manager_get_store (config_manager); - - path = g_test_get_filename (G_TEST_DIST, "tests", "monitor-configs", - filename, NULL); - if (!meta_monitor_config_store_set_custom (config_store, path, NULL, - &error)) - g_error ("Failed to set custom config: %s", error->message); -} - -char * -read_file (const char *file_path) -{ - g_autoptr (GFile) file = NULL; - g_autoptr (GFileInputStream) input_stream = NULL; - g_autoptr (GFileInfo) file_info = NULL; - goffset file_size; - gsize bytes_read; - g_autofree char *buffer = NULL; - GError *error = NULL; - - file = g_file_new_for_path (file_path); - input_stream = g_file_read (file, NULL, &error); - if (!input_stream) - g_error ("Failed to read migrated config file: %s", error->message); - - file_info = g_file_input_stream_query_info (input_stream, - G_FILE_ATTRIBUTE_STANDARD_SIZE, - NULL, &error); - if (!file_info) - g_error ("Failed to read file info: %s", error->message); - - file_size = g_file_info_get_size (file_info); - buffer = g_malloc0 (file_size + 1); - - if (!g_input_stream_read_all (G_INPUT_STREAM (input_stream), - buffer, file_size, &bytes_read, NULL, &error)) - g_error ("Failed to read file content: %s", error->message); - g_assert_cmpint ((goffset) bytes_read, ==, file_size); - - return g_steal_pointer (&buffer); -} - -static MetaOutput * -output_from_winsys_id (MetaBackend *backend, - uint64_t output_id) -{ - MetaGpu *gpu = meta_backend_test_get_gpu (META_BACKEND_TEST (backend)); - GList *l; - - for (l = meta_gpu_get_outputs (gpu); l; l = l->next) - { - MetaOutput *output = l->data; - - if (meta_output_get_id (output) == output_id) - return output; - } - - return NULL; -} - -typedef struct _CheckMonitorModeData -{ - MetaBackend *backend; - MetaTestCaseMonitorCrtcMode *expect_crtc_mode_iter; -} CheckMonitorModeData; - -static gboolean -check_monitor_mode (MetaMonitor *monitor, - MetaMonitorMode *mode, - MetaMonitorCrtcMode *monitor_crtc_mode, - gpointer user_data, - GError **error) -{ - CheckMonitorModeData *data = user_data; - MetaBackend *backend = data->backend; - MetaOutput *output; - MetaCrtcMode *crtc_mode; - int expect_crtc_mode_index; - - output = output_from_winsys_id (backend, - data->expect_crtc_mode_iter->output); - g_assert (monitor_crtc_mode->output == output); - - expect_crtc_mode_index = data->expect_crtc_mode_iter->crtc_mode; - if (expect_crtc_mode_index == -1) - { - crtc_mode = NULL; - } - else - { - MetaGpu *gpu = meta_output_get_gpu (output); - - crtc_mode = g_list_nth_data (meta_gpu_get_modes (gpu), - expect_crtc_mode_index); - } - g_assert (monitor_crtc_mode->crtc_mode == crtc_mode); - - if (crtc_mode) - { - const MetaCrtcModeInfo *crtc_mode_info = - meta_crtc_mode_get_info (crtc_mode); - float refresh_rate; - MetaCrtcModeFlag flags; - - refresh_rate = meta_monitor_mode_get_refresh_rate (mode); - flags = meta_monitor_mode_get_flags (mode); - - g_assert_cmpfloat (refresh_rate, ==, crtc_mode_info->refresh_rate); - g_assert_cmpint (flags, ==, (crtc_mode_info->flags & - HANDLED_CRTC_MODE_FLAGS)); - } - - data->expect_crtc_mode_iter++; - - return TRUE; -} - -static gboolean -check_current_monitor_mode (MetaMonitor *monitor, - MetaMonitorMode *mode, - MetaMonitorCrtcMode *monitor_crtc_mode, - gpointer user_data, - GError **error) -{ - CheckMonitorModeData *data = user_data; - MetaBackend *backend = data->backend; - MetaOutput *output; - MetaCrtc *crtc; - - output = output_from_winsys_id (backend, - data->expect_crtc_mode_iter->output); - crtc = meta_output_get_assigned_crtc (output); - - if (data->expect_crtc_mode_iter->crtc_mode == -1) - { - g_assert_null (crtc); - } - else - { - const MetaCrtcConfig *crtc_config; - MetaLogicalMonitor *logical_monitor; - - g_assert_nonnull (crtc); - - crtc_config = meta_crtc_get_config (crtc); - g_assert_nonnull (crtc_config); - - g_assert (monitor_crtc_mode->crtc_mode == crtc_config->mode); - - logical_monitor = meta_monitor_get_logical_monitor (monitor); - g_assert_nonnull (logical_monitor); - } - - - data->expect_crtc_mode_iter++; - - return TRUE; -} - -static MetaLogicalMonitor * -logical_monitor_from_layout (MetaMonitorManager *monitor_manager, - MetaRectangle *layout) -{ - GList *l; - - for (l = monitor_manager->logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - - if (meta_rectangle_equal (layout, &logical_monitor->rect)) - return logical_monitor; - } - - return NULL; -} - -static void -check_logical_monitor (MetaMonitorManager *monitor_manager, - MonitorTestCaseLogicalMonitor *test_logical_monitor, - GList **all_crtcs) -{ - MetaLogicalMonitor *logical_monitor; - MetaOutput *primary_output; - GList *monitors; - GList *l; - int i; - - logical_monitor = logical_monitor_from_layout (monitor_manager, - &test_logical_monitor->layout); - g_assert_nonnull (logical_monitor); - - g_assert_cmpint (logical_monitor->rect.x, - ==, - test_logical_monitor->layout.x); - g_assert_cmpint (logical_monitor->rect.y, - ==, - test_logical_monitor->layout.y); - g_assert_cmpint (logical_monitor->rect.width, - ==, - test_logical_monitor->layout.width); - g_assert_cmpint (logical_monitor->rect.height, - ==, - test_logical_monitor->layout.height); - g_assert_cmpfloat (logical_monitor->scale, - ==, - test_logical_monitor->scale); - g_assert_cmpuint (logical_monitor->transform, - ==, - test_logical_monitor->transform); - - if (logical_monitor == monitor_manager->primary_logical_monitor) - g_assert (meta_logical_monitor_is_primary (logical_monitor)); - - primary_output = NULL; - monitors = meta_logical_monitor_get_monitors (logical_monitor); - g_assert_cmpint ((int) g_list_length (monitors), - ==, - test_logical_monitor->n_monitors); - - for (i = 0; i < test_logical_monitor->n_monitors; i++) - { - MetaMonitor *monitor = - g_list_nth (monitor_manager->monitors, - test_logical_monitor->monitors[i])->data; - - g_assert_nonnull (g_list_find (monitors, monitor)); - } - - for (l = monitors; l; l = l->next) - { - MetaMonitor *monitor = l->data; - GList *outputs; - GList *l_output; - - outputs = meta_monitor_get_outputs (monitor); - for (l_output = outputs; l_output; l_output = l_output->next) - { - MetaOutput *output = l_output->data; - MetaCrtc *crtc; - - g_assert (meta_output_get_monitor (output) == monitor); - - if (meta_output_is_primary (output)) - { - g_assert_null (primary_output); - primary_output = output; - } - - crtc = meta_output_get_assigned_crtc (output); - if (crtc) - { - g_assert (meta_monitor_get_logical_monitor (monitor) == - logical_monitor); - g_assert (g_list_find ((GList *) meta_crtc_get_outputs (crtc), - output)); - *all_crtcs = g_list_remove (*all_crtcs, crtc); - } - else - { - g_assert_null (crtc); - } - - g_assert_cmpint (logical_monitor->is_presentation, - ==, - meta_output_is_presentation (output)); - } - } - - if (logical_monitor == monitor_manager->primary_logical_monitor) - g_assert_nonnull (primary_output); -} - -void -check_monitor_configuration (MonitorTestCaseExpect *expect) -{ - MetaBackend *backend = meta_get_backend (); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerTest *monitor_manager_test = - META_MONITOR_MANAGER_TEST (monitor_manager); - MetaGpu *gpu = meta_backend_test_get_gpu (META_BACKEND_TEST (backend)); - int tiled_monitor_count; - GList *monitors; - GList *crtcs; - int n_logical_monitors; - GList *all_crtcs; - GList *l; - int i; - - g_assert_cmpint (monitor_manager->screen_width, - ==, - expect->screen_width); - g_assert_cmpint (monitor_manager->screen_height, - ==, - expect->screen_height); - g_assert_cmpint ((int) g_list_length (meta_gpu_get_outputs (gpu)), - ==, - expect->n_outputs); - g_assert_cmpint ((int) g_list_length (meta_gpu_get_crtcs (gpu)), - ==, - expect->n_crtcs); - - tiled_monitor_count = - meta_monitor_manager_test_get_tiled_monitor_count (monitor_manager_test); - g_assert_cmpint (tiled_monitor_count, - ==, - expect->n_tiled_monitors); - - monitors = meta_monitor_manager_get_monitors (monitor_manager); - g_assert_cmpint ((int) g_list_length (monitors), - ==, - expect->n_monitors); - for (l = monitors, i = 0; l; l = l->next, i++) - { - MetaMonitor *monitor = l->data; - MetaOutput *main_output; - const MetaOutputInfo *main_output_info; - GList *outputs; - GList *l_output; - int j; - int width_mm, height_mm; - GList *modes; - GList *l_mode; - MetaMonitorMode *current_mode; - int expected_current_mode_index; - MetaMonitorMode *expected_current_mode; - - outputs = meta_monitor_get_outputs (monitor); - - g_assert_cmpint ((int) g_list_length (outputs), - ==, - expect->monitors[i].n_outputs); - - for (l_output = outputs, j = 0; l_output; l_output = l_output->next, j++) - { - MetaOutput *output = l_output->data; - uint64_t winsys_id = expect->monitors[i].outputs[j]; - - g_assert (output == output_from_winsys_id (backend, winsys_id)); - g_assert_cmpint (expect->monitors[i].is_underscanning, - ==, - meta_output_is_underscanning (output)); - } - - meta_monitor_get_physical_dimensions (monitor, &width_mm, &height_mm); - g_assert_cmpint (width_mm, - ==, - expect->monitors[i].width_mm); - g_assert_cmpint (height_mm, - ==, - expect->monitors[i].height_mm); - - main_output = meta_monitor_get_main_output (monitor); - main_output_info = meta_output_get_info (main_output); - g_assert_cmpstr (meta_monitor_get_connector (monitor), ==, - main_output_info->name); - g_assert_cmpstr (meta_monitor_get_vendor (monitor), ==, - main_output_info->vendor); - g_assert_cmpstr (meta_monitor_get_product (monitor), ==, - main_output_info->product); - g_assert_cmpstr (meta_monitor_get_serial (monitor), ==, - main_output_info->serial); - g_assert_cmpint (meta_monitor_get_connector_type (monitor), ==, - main_output_info->connector_type); - - modes = meta_monitor_get_modes (monitor); - g_assert_cmpint (g_list_length (modes), - ==, - expect->monitors[i].n_modes); - - for (l_mode = modes, j = 0; l_mode; l_mode = l_mode->next, j++) - { - MetaMonitorMode *mode = l_mode->data; - int width; - int height; - float refresh_rate; - MetaCrtcModeFlag flags; - CheckMonitorModeData data; - - meta_monitor_mode_get_resolution (mode, &width, &height); - refresh_rate = meta_monitor_mode_get_refresh_rate (mode); - flags = meta_monitor_mode_get_flags (mode); - - g_assert_cmpint (width, - ==, - expect->monitors[i].modes[j].width); - g_assert_cmpint (height, - ==, - expect->monitors[i].modes[j].height); - g_assert_cmpfloat (refresh_rate, - ==, - expect->monitors[i].modes[j].refresh_rate); - g_assert_cmpint (flags, - ==, - expect->monitors[i].modes[j].flags); - - data = (CheckMonitorModeData) { - .backend = backend, - .expect_crtc_mode_iter = - expect->monitors[i].modes[j].crtc_modes - }; - meta_monitor_mode_foreach_output (monitor, mode, - check_monitor_mode, - &data, - NULL); - } - - current_mode = meta_monitor_get_current_mode (monitor); - expected_current_mode_index = expect->monitors[i].current_mode; - if (expected_current_mode_index == -1) - expected_current_mode = NULL; - else - expected_current_mode = g_list_nth (modes, - expected_current_mode_index)->data; - - g_assert (current_mode == expected_current_mode); - if (current_mode) - g_assert (meta_monitor_is_active (monitor)); - else - g_assert (!meta_monitor_is_active (monitor)); - - if (current_mode) - { - CheckMonitorModeData data; - - data = (CheckMonitorModeData) { - .backend = backend, - .expect_crtc_mode_iter = - expect->monitors[i].modes[expected_current_mode_index].crtc_modes - }; - meta_monitor_mode_foreach_output (monitor, expected_current_mode, - check_current_monitor_mode, - &data, - NULL); - } - - meta_monitor_derive_current_mode (monitor); - g_assert (current_mode == meta_monitor_get_current_mode (monitor)); - } - - n_logical_monitors = - meta_monitor_manager_get_num_logical_monitors (monitor_manager); - g_assert_cmpint (n_logical_monitors, - ==, - expect->n_logical_monitors); - - /* - * Check that we have a primary logical monitor (except for headless), - * and that the main output of the first monitor is the only output - * that is marked as primary (further below). Note: outputs being primary or - * not only matters on X11. - */ - if (expect->primary_logical_monitor == -1) - { - g_assert_null (monitor_manager->primary_logical_monitor); - g_assert_null (monitor_manager->logical_monitors); - } - else - { - MonitorTestCaseLogicalMonitor *test_logical_monitor = - &expect->logical_monitors[expect->primary_logical_monitor]; - MetaLogicalMonitor *logical_monitor; - - logical_monitor = - logical_monitor_from_layout (monitor_manager, - &test_logical_monitor->layout); - g_assert (logical_monitor == monitor_manager->primary_logical_monitor); - } - - all_crtcs = NULL; - for (l = meta_backend_get_gpus (backend); l; l = l->next) - { - MetaGpu *gpu = l->data; - - all_crtcs = g_list_concat (all_crtcs, - g_list_copy (meta_gpu_get_crtcs (gpu))); - } - - for (i = 0; i < expect->n_logical_monitors; i++) - { - MonitorTestCaseLogicalMonitor *test_logical_monitor = - &expect->logical_monitors[i]; - - check_logical_monitor (monitor_manager, test_logical_monitor, &all_crtcs); - } - g_assert_cmpint (n_logical_monitors, ==, i); - - for (l = all_crtcs; l; l = l->next) - { - MetaCrtc *crtc = l->data; - - g_assert_null (meta_crtc_get_outputs (crtc)); - } - g_list_free (all_crtcs); - - crtcs = meta_gpu_get_crtcs (gpu); - for (l = crtcs, i = 0; l; l = l->next, i++) - { - MetaCrtc *crtc = l->data; - const MetaCrtcConfig *crtc_config = meta_crtc_get_config (crtc); - - if (expect->crtcs[i].current_mode == -1) - { - g_assert_null (meta_crtc_get_outputs (crtc)); - g_assert_null (crtc_config); - } - else - { - MetaCrtcMode *expected_current_mode; - const GList *l_output; - MetaRendererView *view; - cairo_rectangle_int_t view_layout; - - for (l_output = meta_crtc_get_outputs (crtc); - l_output; - l_output = l_output->next) - { - MetaOutput *output = l_output->data; - - g_assert (meta_output_get_assigned_crtc (output) == crtc); - g_assert_null (g_list_find (l_output->next, output)); - } - - g_assert_nonnull (crtc_config); - - expected_current_mode = - g_list_nth_data (meta_gpu_get_modes (gpu), - expect->crtcs[i].current_mode); - g_assert (crtc_config->mode == expected_current_mode); - - g_assert_cmpuint (crtc_config->transform, - ==, - expect->crtcs[i].transform); - - g_assert_cmpfloat_with_epsilon (crtc_config->layout.origin.x, - expect->crtcs[i].x, - FLT_EPSILON); - g_assert_cmpfloat_with_epsilon (crtc_config->layout.origin.y, - expect->crtcs[i].y, - FLT_EPSILON); - - view = meta_renderer_get_view_for_crtc (renderer, crtc); - g_assert_nonnull (view); - clutter_stage_view_get_layout (CLUTTER_STAGE_VIEW (view), - &view_layout); - g_assert_cmpfloat_with_epsilon (crtc_config->layout.origin.x, - view_layout.x, - FLT_EPSILON); - g_assert_cmpfloat_with_epsilon (crtc_config->layout.origin.y, - view_layout.y, - FLT_EPSILON); - g_assert_cmpfloat_with_epsilon (crtc_config->layout.size.width, - view_layout.width, - FLT_EPSILON); - g_assert_cmpfloat_with_epsilon (crtc_config->layout.size.height, - view_layout.height, - FLT_EPSILON); - } - } -} - -MetaMonitorTestSetup * -create_monitor_test_setup (MonitorTestCaseSetup *setup, - MonitorTestFlag flags) -{ - MetaMonitorTestSetup *test_setup; - int i; - int n_laptop_panels = 0; - int n_normal_panels = 0; - - test_setup = g_new0 (MetaMonitorTestSetup, 1); - - test_setup->modes = NULL; - for (i = 0; i < setup->n_modes; i++) - { - g_autoptr (MetaCrtcModeInfo) crtc_mode_info = NULL; - MetaCrtcMode *mode; - - crtc_mode_info = meta_crtc_mode_info_new (); - crtc_mode_info->width = setup->modes[i].width; - crtc_mode_info->height = setup->modes[i].height; - crtc_mode_info->refresh_rate = setup->modes[i].refresh_rate; - crtc_mode_info->flags = setup->modes[i].flags; - - mode = g_object_new (META_TYPE_CRTC_MODE, - "id", (uint64_t) i, - "info", crtc_mode_info, - NULL); - - test_setup->modes = g_list_append (test_setup->modes, mode); - } - - test_setup->crtcs = NULL; - for (i = 0; i < setup->n_crtcs; i++) - { - MetaCrtc *crtc; - - crtc = g_object_new (META_TYPE_CRTC_TEST, - "id", (uint64_t) i + 1, - "gpu", test_get_gpu (), - NULL); - - test_setup->crtcs = g_list_append (test_setup->crtcs, crtc); - } - - test_setup->outputs = NULL; - for (i = 0; i < setup->n_outputs; i++) - { - MetaOutput *output; - MetaOutputTest *output_test; - int crtc_index; - MetaCrtc *crtc; - int preferred_mode_index; - MetaCrtcMode *preferred_mode; - MetaCrtcMode **modes; - int n_modes; - int j; - MetaCrtc **possible_crtcs; - int n_possible_crtcs; - int scale; - gboolean is_laptop_panel; - const char *serial; - g_autoptr (MetaOutputInfo) output_info = NULL; - - crtc_index = setup->outputs[i].crtc; - if (crtc_index == -1) - crtc = NULL; - else - crtc = g_list_nth_data (test_setup->crtcs, crtc_index); - - preferred_mode_index = setup->outputs[i].preferred_mode; - if (preferred_mode_index == -1) - preferred_mode = NULL; - else - preferred_mode = g_list_nth_data (test_setup->modes, - preferred_mode_index); - - n_modes = setup->outputs[i].n_modes; - modes = g_new0 (MetaCrtcMode *, n_modes); - for (j = 0; j < n_modes; j++) - { - int mode_index; - - mode_index = setup->outputs[i].modes[j]; - modes[j] = g_list_nth_data (test_setup->modes, mode_index); - } - - n_possible_crtcs = setup->outputs[i].n_possible_crtcs; - possible_crtcs = g_new0 (MetaCrtc *, n_possible_crtcs); - for (j = 0; j < n_possible_crtcs; j++) - { - int possible_crtc_index; - - possible_crtc_index = setup->outputs[i].possible_crtcs[j]; - possible_crtcs[j] = g_list_nth_data (test_setup->crtcs, - possible_crtc_index); - } - - scale = setup->outputs[i].scale; - if (scale < 1) - scale = 1; - - is_laptop_panel = setup->outputs[i].is_laptop_panel; - - serial = setup->outputs[i].serial; - if (!serial) - serial = "0x123456"; - - output_info = meta_output_info_new (); - - output_info->name = (is_laptop_panel - ? g_strdup_printf ("eDP-%d", ++n_laptop_panels) - : g_strdup_printf ("DP-%d", ++n_normal_panels)); - output_info->vendor = g_strdup ("MetaProduct's Inc."); - output_info->product = g_strdup ("MetaMonitor"); - output_info->serial = g_strdup (serial); - if (setup->outputs[i].hotplug_mode) - { - output_info->hotplug_mode_update = TRUE; - output_info->suggested_x = setup->outputs[i].suggested_x; - output_info->suggested_y = setup->outputs[i].suggested_y; - } - else if (flags & MONITOR_TEST_FLAG_NO_STORED) - { - output_info->hotplug_mode_update = TRUE; - output_info->suggested_x = -1; - output_info->suggested_y = -1; - } - output_info->width_mm = setup->outputs[i].width_mm; - output_info->height_mm = setup->outputs[i].height_mm; - output_info->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN; - output_info->preferred_mode = preferred_mode; - output_info->n_modes = n_modes; - output_info->modes = modes; - output_info->n_possible_crtcs = n_possible_crtcs; - output_info->possible_crtcs = possible_crtcs; - output_info->n_possible_clones = 0; - output_info->possible_clones = NULL; - output_info->connector_type = (is_laptop_panel ? META_CONNECTOR_TYPE_eDP - : META_CONNECTOR_TYPE_DisplayPort); - output_info->tile_info = setup->outputs[i].tile_info; - output_info->panel_orientation_transform = - setup->outputs[i].panel_orientation_transform; - - output = g_object_new (META_TYPE_OUTPUT_TEST, - "id", (uint64_t) i, - "gpu", test_get_gpu (), - "info", output_info, - NULL); - - output_test = META_OUTPUT_TEST (output); - output_test->scale = scale; - - if (crtc) - { - MetaOutputAssignment output_assignment; - - output_assignment = (MetaOutputAssignment) { - .is_underscanning = setup->outputs[i].is_underscanning, - }; - meta_output_assign_crtc (output, crtc, &output_assignment); - } - - test_setup->outputs = g_list_append (test_setup->outputs, output); - } - - return test_setup; -} diff --git a/src/tests/monitor-test-utils.h b/src/tests/monitor-test-utils.h deleted file mode 100644 index 3ebf1ff79..000000000 --- a/src/tests/monitor-test-utils.h +++ /dev/null @@ -1,206 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2017 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 . - */ - -#ifndef MONITOR_TEST_UTILS_H -#define MONITOR_TEST_UTILS_H - -#include - -#include "tests/meta-monitor-manager-test.h" -#include "backends/meta-crtc.h" -#include "backends/meta-output.h" - -#define MAX_N_MODES 10 -#define MAX_N_OUTPUTS 10 -#define MAX_N_CRTCS 10 -#define MAX_N_MONITORS 10 -#define MAX_N_LOGICAL_MONITORS 10 - -/* - * The following structures are used to define test cases. - * - * Each test case consists of a test case setup and a test case expectaction. - * and a expected result, consisting - * of an array of monitors, logical monitors and a screen size. - * - * TEST CASE SETUP: - * - * A test case setup consists of an array of modes, an array of outputs and an - * array of CRTCs. - * - * A mode has a width and height in pixels, and a refresh rate in updates per - * second. - * - * An output has an array of available modes, and a preferred mode. Modes are - * defined as indices into the modes array of the test case setup. - * - * It also has CRTc and an array of possible CRTCs. Crtcs are defined as indices - * into the CRTC array. The CRTC value -1 means no CRTC. - * - * It also has various meta data, such as physical dimension, tile info and - * scale. - * - * A CRTC only has a current mode. A mode is defined as an index into the modes - * array. - * - * - * TEST CASE EXPECTS: - * - * A test case expects consists of an array of monitors, an array of logical - * monitors, a output and crtc count, and a screen width. - * - * A monitor represents a physical monitor (such as an external monitor, or a - * laptop panel etc). A monitor consists of an array of outputs, defined by - * indices into the setup output array, an array of monitor modes, and the - * current mode, defined by an index into the monitor modes array, and the - * physical dimensions. - * - * A logical monitor represents a region of the total screen area. It contains - * the expected layout and a scale. - */ - -typedef enum _MonitorTestFlag -{ - MONITOR_TEST_FLAG_NONE, - MONITOR_TEST_FLAG_NO_STORED -} MonitorTestFlag; - -typedef struct _MonitorTestCaseMode -{ - int width; - int height; - float refresh_rate; - MetaCrtcModeFlag flags; -} MonitorTestCaseMode; - -typedef struct _MonitorTestCaseOutput -{ - int crtc; - int modes[MAX_N_MODES]; - int n_modes; - int preferred_mode; - int possible_crtcs[MAX_N_CRTCS]; - int n_possible_crtcs; - int width_mm; - int height_mm; - MetaTileInfo tile_info; - float scale; - gboolean is_laptop_panel; - gboolean is_underscanning; - const char *serial; - MetaMonitorTransform panel_orientation_transform; - gboolean hotplug_mode; - int suggested_x; - int suggested_y; -} MonitorTestCaseOutput; - -typedef struct _MonitorTestCaseCrtc -{ - int current_mode; -} MonitorTestCaseCrtc; - -typedef struct _MonitorTestCaseSetup -{ - MonitorTestCaseMode modes[MAX_N_MODES]; - int n_modes; - - MonitorTestCaseOutput outputs[MAX_N_OUTPUTS]; - int n_outputs; - - MonitorTestCaseCrtc crtcs[MAX_N_CRTCS]; - int n_crtcs; -} MonitorTestCaseSetup; - -typedef struct _MonitorTestCaseMonitorCrtcMode -{ - uint64_t output; - int crtc_mode; -} MetaTestCaseMonitorCrtcMode; - -typedef struct _MonitorTestCaseMonitorMode -{ - int width; - int height; - float refresh_rate; - MetaCrtcModeFlag flags; - MetaTestCaseMonitorCrtcMode crtc_modes[MAX_N_CRTCS]; -} MetaMonitorTestCaseMonitorMode; - -typedef struct _MonitorTestCaseMonitor -{ - uint64_t outputs[MAX_N_OUTPUTS]; - int n_outputs; - MetaMonitorTestCaseMonitorMode modes[MAX_N_MODES]; - int n_modes; - int current_mode; - int width_mm; - int height_mm; - gboolean is_underscanning; -} MonitorTestCaseMonitor; - -typedef struct _MonitorTestCaseLogicalMonitor -{ - MetaRectangle layout; - float scale; - int monitors[MAX_N_MONITORS]; - int n_monitors; - MetaMonitorTransform transform; -} MonitorTestCaseLogicalMonitor; - -typedef struct _MonitorTestCaseCrtcExpect -{ - MetaMonitorTransform transform; - int current_mode; - float x; - float y; -} MonitorTestCaseCrtcExpect; - -typedef struct _MonitorTestCaseExpect -{ - MonitorTestCaseMonitor monitors[MAX_N_MONITORS]; - int n_monitors; - MonitorTestCaseLogicalMonitor logical_monitors[MAX_N_LOGICAL_MONITORS]; - int n_logical_monitors; - int primary_logical_monitor; - int n_outputs; - MonitorTestCaseCrtcExpect crtcs[MAX_N_CRTCS]; - int n_crtcs; - int n_tiled_monitors; - int screen_width; - int screen_height; -} MonitorTestCaseExpect; - -struct _MonitorTestCase -{ - MonitorTestCaseSetup setup; - MonitorTestCaseExpect expect; -}; - -MetaGpu * test_get_gpu (void); - -void set_custom_monitor_config (const char *filename); - -char * read_file (const char *file_path); - -void check_monitor_configuration (MonitorTestCaseExpect *expect); - -MetaMonitorTestSetup * create_monitor_test_setup (MonitorTestCaseSetup *setup, - MonitorTestFlag flags); - -#endif /* MONITOR_TEST_UTILS_H */ diff --git a/src/tests/monitor-transform-tests.c b/src/tests/monitor-transform-tests.c deleted file mode 100644 index 871a06b10..000000000 --- a/src/tests/monitor-transform-tests.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2020 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 . - */ - -#include "config.h" - -#include "tests/monitor-transform-tests.h" - -#include "backends/meta-monitor-transform.h" - -static void -test_transform (void) -{ - const struct - { - MetaMonitorTransform transform; - MetaMonitorTransform other; - MetaMonitorTransform expect; - } tests[] = { - { - .transform = META_MONITOR_TRANSFORM_NORMAL, - .other = META_MONITOR_TRANSFORM_90, - .expect = META_MONITOR_TRANSFORM_90, - }, - { - .transform = META_MONITOR_TRANSFORM_NORMAL, - .other = META_MONITOR_TRANSFORM_FLIPPED_90, - .expect = META_MONITOR_TRANSFORM_FLIPPED_90, - }, - { - .transform = META_MONITOR_TRANSFORM_90, - .other = META_MONITOR_TRANSFORM_90, - .expect = META_MONITOR_TRANSFORM_180, - }, - { - .transform = META_MONITOR_TRANSFORM_FLIPPED_90, - .other = META_MONITOR_TRANSFORM_90, - .expect = META_MONITOR_TRANSFORM_FLIPPED_180, - }, - { - .transform = META_MONITOR_TRANSFORM_FLIPPED_90, - .other = META_MONITOR_TRANSFORM_180, - .expect = META_MONITOR_TRANSFORM_FLIPPED_270, - }, - { - .transform = META_MONITOR_TRANSFORM_FLIPPED_180, - .other = META_MONITOR_TRANSFORM_FLIPPED_180, - .expect = META_MONITOR_TRANSFORM_NORMAL, - }, - { - .transform = META_MONITOR_TRANSFORM_NORMAL, - .other = meta_monitor_transform_invert (META_MONITOR_TRANSFORM_90), - .expect = META_MONITOR_TRANSFORM_270, - }, - { - .transform = META_MONITOR_TRANSFORM_FLIPPED, - .other = meta_monitor_transform_invert (META_MONITOR_TRANSFORM_90), - .expect = META_MONITOR_TRANSFORM_FLIPPED_270, - }, - { - .transform = META_MONITOR_TRANSFORM_FLIPPED_180, - .other = meta_monitor_transform_invert (META_MONITOR_TRANSFORM_270), - .expect = META_MONITOR_TRANSFORM_FLIPPED_270, - }, - { - .transform = META_MONITOR_TRANSFORM_FLIPPED_180, - .other = - meta_monitor_transform_invert (META_MONITOR_TRANSFORM_FLIPPED_180), - .expect = META_MONITOR_TRANSFORM_NORMAL, - }, - }; - int i; - - for (i = 0; i < G_N_ELEMENTS (tests); i++) - { - MetaMonitorTransform result; - - result = meta_monitor_transform_transform (tests[i].transform, - tests[i].other); - g_assert_cmpint (result, ==, tests[i].expect); - } -} - -void -init_monitor_transform_tests (void) -{ - g_test_add_func ("/util/monitor-transform/transform", test_transform); -} diff --git a/src/tests/monitor-transform-tests.h b/src/tests/monitor-transform-tests.h deleted file mode 100644 index f6d019132..000000000 --- a/src/tests/monitor-transform-tests.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 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 . - */ - -#ifndef MONITOR_TRANSFORM_UNIT_TESTS_H -#define MONITOR_TRANSFORM_UNIT_TESTS_H - -void init_monitor_transform_tests (void); - -#endif /* MONITOR_TRANSFORM_TESTS_H */ diff --git a/src/tests/monitor-unit-tests.c b/src/tests/monitor-unit-tests.c deleted file mode 100644 index 6d6d5fce4..000000000 --- a/src/tests/monitor-unit-tests.c +++ /dev/null @@ -1,5868 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 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 . - */ - -#include "config.h" - -#include "tests/monitor-unit-tests.h" - -#include "backends/meta-backend-private.h" -#include "backends/meta-crtc.h" -#include "backends/meta-logical-monitor.h" -#include "backends/meta-monitor.h" -#include "backends/meta-monitor-config-migration.h" -#include "backends/meta-monitor-config-store.h" -#include "backends/meta-output.h" -#include "core/window-private.h" -#include "meta-backend-test.h" -#include "tests/meta-monitor-manager-test.h" -#include "tests/monitor-test-utils.h" -#include "tests/meta-test-utils.h" -#include "tests/unit-tests.h" -#include "x11/meta-x11-display-private.h" - -static MonitorTestCase initial_test_case = { - .setup = { - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0 - } - }, - .n_modes = 1, - .outputs = { - { - .crtc = 0, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125 - }, - { - .crtc = 1, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 1 }, - .n_possible_crtcs = 1, - .width_mm = 220, - .height_mm = 124 - } - }, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0 - }, - { - .current_mode = 0 - } - }, - .n_crtcs = 2 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125 - }, - { - .outputs = { 1 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 1, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 220, - .height_mm = 124 - } - }, - .n_monitors = 2, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - }, - { - .monitors = { 1 }, - .n_monitors = 1, - .layout = { .x = 1024, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - } - }, - .n_logical_monitors = 2, - .primary_logical_monitor = 0, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0, - }, - { - .current_mode = 0, - .x = 1024, - } - }, - .n_crtcs = 2, - .screen_width = 1024 * 2, - .screen_height = 768 - } -}; - -static MetaTestClient *wayland_monitor_test_client = NULL; -static MetaTestClient *x11_monitor_test_client = NULL; - -#define WAYLAND_TEST_CLIENT_NAME "wayland_monitor_test_client" -#define WAYLAND_TEST_CLIENT_WINDOW "window1" -#define X11_TEST_CLIENT_NAME "x11_monitor_test_client" -#define X11_TEST_CLIENT_WINDOW "window1" - -static gboolean -monitor_tests_alarm_filter (MetaX11Display *x11_display, - XSyncAlarmNotifyEvent *event, - gpointer data) -{ - return meta_test_client_process_x11_event (x11_monitor_test_client, - x11_display, event); -} - -static void -create_monitor_test_clients (MetaContext *context) -{ - GError *error = NULL; - - wayland_monitor_test_client = meta_test_client_new (context, - WAYLAND_TEST_CLIENT_NAME, - META_WINDOW_CLIENT_TYPE_WAYLAND, - &error); - if (!wayland_monitor_test_client) - g_error ("Failed to launch Wayland test client: %s", error->message); - - x11_monitor_test_client = meta_test_client_new (context, - X11_TEST_CLIENT_NAME, - META_WINDOW_CLIENT_TYPE_X11, - &error); - if (!x11_monitor_test_client) - g_error ("Failed to launch X11 test client: %s", error->message); - - meta_x11_display_set_alarm_filter (meta_get_display ()->x11_display, - monitor_tests_alarm_filter, NULL); - - if (!meta_test_client_do (wayland_monitor_test_client, &error, - "create", WAYLAND_TEST_CLIENT_WINDOW, - NULL)) - g_error ("Failed to create Wayland window: %s", error->message); - - if (!meta_test_client_do (x11_monitor_test_client, &error, - "create", X11_TEST_CLIENT_WINDOW, - NULL)) - g_error ("Failed to create X11 window: %s", error->message); - - if (!meta_test_client_do (wayland_monitor_test_client, &error, - "show", WAYLAND_TEST_CLIENT_WINDOW, - NULL)) - g_error ("Failed to show the window: %s", error->message); - - if (!meta_test_client_do (x11_monitor_test_client, &error, - "show", X11_TEST_CLIENT_WINDOW, - NULL)) - g_error ("Failed to show the window: %s", error->message); -} - -static void -check_test_client_state (MetaTestClient *test_client) -{ - GError *error = NULL; - - if (!meta_test_client_wait (test_client, &error)) - { - g_error ("Failed to sync test client '%s': %s", - meta_test_client_get_id (test_client), error->message); - } -} - -static void -check_monitor_test_clients_state (void) -{ - check_test_client_state (wayland_monitor_test_client); - check_test_client_state (x11_monitor_test_client); -} - -static void -destroy_monitor_test_clients (void) -{ - GError *error = NULL; - - if (!meta_test_client_quit (wayland_monitor_test_client, &error)) - g_error ("Failed to quit Wayland test client: %s", error->message); - - if (!meta_test_client_quit (x11_monitor_test_client, &error)) - g_error ("Failed to quit X11 test client: %s", error->message); - - meta_test_client_destroy (wayland_monitor_test_client); - meta_test_client_destroy (x11_monitor_test_client); - - meta_x11_display_set_alarm_filter (meta_get_display ()->x11_display, - NULL, NULL); -} - -static void -meta_test_monitor_initial_linear_config (void) -{ - check_monitor_configuration (&initial_test_case.expect); - check_monitor_test_clients_state (); -} - -static void -emulate_hotplug (MetaMonitorTestSetup *test_setup) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerTest *monitor_manager_test = - META_MONITOR_MANAGER_TEST (monitor_manager); - - meta_monitor_manager_test_emulate_hotplug (monitor_manager_test, test_setup); - g_usleep (G_USEC_PER_SEC / 100); -} - -static void -meta_test_monitor_one_disconnected_linear_config (void) -{ - MonitorTestCase test_case = initial_test_case; - MetaMonitorTestSetup *test_setup; - - test_case.setup.n_outputs = 1; - - test_case.expect = (MonitorTestCaseExpect) { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125 - } - }, - .n_monitors = 1, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - }, - }, - .n_logical_monitors = 1, - .primary_logical_monitor = 0, - .n_outputs = 1, - .crtcs = { - { - .current_mode = 0, - }, - { - .current_mode = -1, - } - }, - .n_crtcs = 2, - .screen_width = 1024, - .screen_height = 768 - }; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_one_off_linear_config (void) -{ - MonitorTestCase test_case; - MetaMonitorTestSetup *test_setup; - MonitorTestCaseOutput outputs[] = { - { - .crtc = 0, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125 - }, - { - .crtc = -1, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 1 }, - .n_possible_crtcs = 1, - .width_mm = 224, - .height_mm = 126 - } - }; - - test_case = initial_test_case; - - memcpy (&test_case.setup.outputs, &outputs, sizeof (outputs)); - test_case.setup.n_outputs = G_N_ELEMENTS (outputs); - - test_case.setup.crtcs[1].current_mode = -1; - - test_case.expect = (MonitorTestCaseExpect) { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125 - }, - { - .outputs = { 1 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 1, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 224, - .height_mm = 126 - } - }, - .n_monitors = 2, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - }, - { - .monitors = { 1 }, - .n_monitors = 1, - .layout = { .x = 1024, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - }, - }, - .n_logical_monitors = 2, - .primary_logical_monitor = 0, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0, - }, - { - .current_mode = 0, - .x = 1024, - } - }, - .n_crtcs = 2, - .screen_width = 1024 * 2, - .screen_height = 768 - }; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_preferred_linear_config (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.0 - }, - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0 - }, - { - .width = 1280, - .height = 720, - .refresh_rate = 60.0 - } - }, - .n_modes = 3, - .outputs = { - { - .crtc = -1, - .modes = { 0, 1, 2 }, - .n_modes = 3, - .preferred_mode = 1, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125 - } - }, - .n_outputs = 1, - .crtcs = { - { - .current_mode = -1 - } - }, - .n_crtcs = 1 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - }, - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 1 - } - } - }, - { - .width = 1280, - .height = 720, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 2 - } - } - } - }, - .n_modes = 3, - .current_mode = 1, - .width_mm = 222, - .height_mm = 125 - } - }, - .n_monitors = 1, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - }, - }, - .n_logical_monitors = 1, - .primary_logical_monitor = 0, - .n_outputs = 1, - .crtcs = { - { - .current_mode = 1, - } - }, - .n_crtcs = 1, - .screen_width = 1024, - .screen_height = 768, - } - }; - MetaMonitorTestSetup *test_setup; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_tiled_linear_config (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 400, - .height = 600, - .refresh_rate = 60.0 - }, - }, - .n_modes = 1, - .outputs = { - { - .crtc = -1, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - .tile_info = { - .group_id = 1, - .max_h_tiles = 2, - .max_v_tiles = 1, - .loc_h_tile = 0, - .loc_v_tile = 0, - .tile_w = 400, - .tile_h = 600 - } - }, - { - .crtc = -1, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 1 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - .tile_info = { - .group_id = 1, - .max_h_tiles = 2, - .max_v_tiles = 1, - .loc_h_tile = 1, - .loc_v_tile = 0, - .tile_w = 400, - .tile_h = 600 - } - } - }, - .n_outputs = 2, - .crtcs = { - { - .current_mode = -1 - }, - { - .current_mode = -1 - } - }, - .n_crtcs = 2 - }, - - .expect = { - .monitors = { - { - .outputs = { 0, 1 }, - .n_outputs = 2, - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - }, - { - .output = 1, - .crtc_mode = 0, - } - } - }, - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125, - } - }, - .n_monitors = 1, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 800, .height = 600 }, - .scale = 1 - }, - }, - .n_logical_monitors = 1, - .primary_logical_monitor = 0, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0, - }, - { - .current_mode = 0, - .x = 400, - .y = 0 - } - }, - .n_crtcs = 2, - .n_tiled_monitors = 1, - .screen_width = 800, - .screen_height = 600, - } - }; - MetaMonitorTestSetup *test_setup; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_tiled_non_preferred_linear_config (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 640, - .height = 480, - .refresh_rate = 60.0 - }, - { - .width = 800, - .height = 600, - .refresh_rate = 60.0 - }, - { - .width = 512, - .height = 768, - .refresh_rate = 120.0 - }, - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0 - }, - }, - .n_modes = 4, - .outputs = { - { - .crtc = -1, - .modes = { 0, 2 }, - .n_modes = 2, - .preferred_mode = 1, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - .tile_info = { - .group_id = 1, - .max_h_tiles = 2, - .max_v_tiles = 1, - .loc_h_tile = 0, - .loc_v_tile = 0, - .tile_w = 512, - .tile_h = 768 - } - }, - { - .crtc = -1, - .modes = { 1, 2, 3 }, - .n_modes = 3, - .preferred_mode = 0, - .possible_crtcs = { 1 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - .tile_info = { - .group_id = 1, - .max_h_tiles = 2, - .max_v_tiles = 1, - .loc_h_tile = 1, - .loc_v_tile = 0, - .tile_w = 512, - .tile_h = 768 - } - } - }, - .n_outputs = 2, - .crtcs = { - { - .current_mode = -1 - }, - { - .current_mode = -1 - } - }, - .n_crtcs = 2 - }, - - .expect = { - .monitors = { - { - .outputs = { 0, 1 }, - .n_outputs = 2, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 120.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 2 - }, - { - .output = 1, - .crtc_mode = 2, - } - } - }, - { - .width = 800, - .height = 600, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = -1 - }, - { - .output = 1, - .crtc_mode = 1, - } - } - }, - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = -1 - }, - { - .output = 1, - .crtc_mode = 3, - } - } - }, - }, - .n_modes = 3, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125, - } - }, - .n_monitors = 1, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - }, - }, - .n_logical_monitors = 1, - .primary_logical_monitor = 0, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 2, - }, - { - .current_mode = 2, - .x = 512 - } - }, - .n_crtcs = 2, - .n_tiled_monitors = 1, - .screen_width = 1024, - .screen_height = 768, - } - }; - MetaMonitorTestSetup *test_setup; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_tiled_non_main_origin_linear_config (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 400, - .height = 600, - .refresh_rate = 60.0 - }, - { - .width = 800, - .height = 600, - .refresh_rate = 30.0 - }, - }, - .n_modes = 2, - .outputs = { - { - .crtc = -1, - .modes = { 0, 1 }, - .n_modes = 2, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - .tile_info = { - .group_id = 1, - .max_h_tiles = 2, - .max_v_tiles = 1, - .loc_h_tile = 1, - .loc_v_tile = 0, - .tile_w = 400, - .tile_h = 600 - } - }, - { - .crtc = -1, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 1 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - .tile_info = { - .group_id = 1, - .max_h_tiles = 2, - .max_v_tiles = 1, - .loc_h_tile = 0, - .loc_v_tile = 0, - .tile_w = 400, - .tile_h = 600 - } - } - }, - .n_outputs = 2, - .crtcs = { - { - .current_mode = -1 - }, - { - .current_mode = -1 - } - }, - .n_crtcs = 2 - }, - - .expect = { - .monitors = { - { - .outputs = { 0, 1 }, - .n_outputs = 2, - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0, - }, - { - .output = 1, - .crtc_mode = 0, - } - } - }, - { - .width = 800, - .height = 600, - .refresh_rate = 30.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 1 - }, - { - .output = 1, - .crtc_mode = -1, - } - } - }, - }, - .n_modes = 2, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125, - } - }, - .n_monitors = 1, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 800, .height = 600 }, - .scale = 1 - }, - }, - .n_logical_monitors = 1, - .primary_logical_monitor = 0, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0, - .x = 400, - .y = 0 - }, - { - .current_mode = 0, - } - }, - .n_crtcs = 2, - .n_tiled_monitors = 1, - .screen_width = 800, - .screen_height = 600, - } - }; - MetaMonitorTestSetup *test_setup; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_hidpi_linear_config (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 1280, - .height = 720, - .refresh_rate = 60.0 - }, - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0 - } - }, - .n_modes = 2, - .outputs = { - { - .crtc = 0, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - /* These will result in DPI of about 216" */ - .width_mm = 150, - .height_mm = 85, - .scale = 2, - }, - { - .crtc = 1, - .modes = { 1 }, - .n_modes = 1, - .preferred_mode = 1, - .possible_crtcs = { 1 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - .scale = 1, - } - }, - .n_outputs = 2, - .crtcs = { - { - .current_mode = -1 - }, - { - .current_mode = -1 - } - }, - .n_crtcs = 2 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 1280, - .height = 720, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - }, - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 150, - .height_mm = 85 - }, - { - .outputs = { 1 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 1, - .crtc_mode = 1 - } - } - }, - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125 - } - }, - .n_monitors = 2, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 640, .height = 360 }, - .scale = 2 - }, - { - .monitors = { 1 }, - .n_monitors = 1, - .layout = { .x = 640, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - } - }, - .n_logical_monitors = 2, - .primary_logical_monitor = 0, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0, - }, - { - .current_mode = 1, - .x = 640, - } - }, - .n_crtcs = 2, - .screen_width = 640 + 1024, - .screen_height = 768 - } - }; - MetaMonitorTestSetup *test_setup; - - if (!meta_is_stage_views_enabled ()) - { - g_test_skip ("Not using stage views"); - return; - } - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_suggested_config (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.0 - }, - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0 - } - }, - .n_modes = 2, - .outputs = { - { - .crtc = 0, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - .hotplug_mode = TRUE, - .suggested_x = 1024, - .suggested_y = 758, - }, - { - .crtc = 1, - .modes = { 1 }, - .n_modes = 1, - .preferred_mode = 1, - .possible_crtcs = { 1 }, - .n_possible_crtcs = 1, - .width_mm = 220, - .height_mm = 124, - .hotplug_mode = TRUE, - .suggested_x = 0, - .suggested_y = 0, - } - }, - .n_outputs = 2, - .crtcs = { - { - .current_mode = -1 - }, - { - .current_mode = -1 - } - }, - .n_crtcs = 2 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125 - }, - { - .outputs = { 1 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 1, - .crtc_mode = 1 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 220, - .height_mm = 124 - } - }, - .n_monitors = 2, - /* - * Logical monitors expectations altered to correspond to the - * "suggested_x/y" changed further below. - */ - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 1024, .y = 758, .width = 800, .height = 600 }, - .scale = 1 - }, - { - .monitors = { 1 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - } - }, - .n_logical_monitors = 2, - .primary_logical_monitor = 1, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0, - .x = 1024, - .y = 758, - }, - { - .current_mode = 1, - } - }, - .n_crtcs = 2, - .n_tiled_monitors = 0, - .screen_width = 1024 + 800, - .screen_height = 1358 - } - }; - MetaMonitorTestSetup *test_setup; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_limited_crtcs (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0 - } - }, - .n_modes = 1, - .outputs = { - { - .crtc = -1, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125 - }, - { - .crtc = -1, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 220, - .height_mm = 124 - } - }, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0 - } - }, - .n_crtcs = 1 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125 - }, - { - .outputs = { 1 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 1, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = -1, - .width_mm = 220, - .height_mm = 124 - } - }, - .n_monitors = 2, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - }, - }, - .n_logical_monitors = 1, - .primary_logical_monitor = 0, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0, - } - }, - .n_crtcs = 1, - .n_tiled_monitors = 0, - .screen_width = 1024, - .screen_height = 768 - } - }; - MetaMonitorTestSetup *test_setup; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - - g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, - "Failed to use linear *"); - - emulate_hotplug (test_setup); - g_test_assert_expected_messages (); - - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_lid_switch_config (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0 - } - }, - .n_modes = 1, - .outputs = { - { - .crtc = 0, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - .is_laptop_panel = TRUE - }, - { - .crtc = 1, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 1 }, - .n_possible_crtcs = 1, - .width_mm = 220, - .height_mm = 124 - } - }, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0 - }, - { - .current_mode = 0 - } - }, - .n_crtcs = 2 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125 - }, - { - .outputs = { 1 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 1, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 220, - .height_mm = 124 - } - }, - .n_monitors = 2, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - }, - { - .monitors = { 1 }, - .n_monitors = 1, - .layout = { .x = 1024, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - } - }, - .n_logical_monitors = 2, - .primary_logical_monitor = 0, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0, - }, - { - .current_mode = 0, - .x = 1024, - } - }, - .n_crtcs = 2, - .n_tiled_monitors = 0, - .screen_width = 1024 * 2, - .screen_height = 768 - } - }; - MetaMonitorTestSetup *test_setup; - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); - - meta_backend_test_set_is_lid_closed (META_BACKEND_TEST (backend), TRUE); - meta_monitor_manager_lid_is_closed_changed (monitor_manager); - - test_case.expect.logical_monitors[0] = (MonitorTestCaseLogicalMonitor) { - .monitors = { 1 }, - .n_monitors = 1, - .layout = {.x = 0, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - }; - test_case.expect.n_logical_monitors = 1; - test_case.expect.screen_width = 1024; - test_case.expect.monitors[0].current_mode = -1; - test_case.expect.crtcs[0].current_mode = -1; - test_case.expect.crtcs[1].x = 0; - - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); - - meta_backend_test_set_is_lid_closed (META_BACKEND_TEST (backend), FALSE); - meta_monitor_manager_lid_is_closed_changed (monitor_manager); - - test_case.expect.logical_monitors[0] = (MonitorTestCaseLogicalMonitor) { - .monitors = { 0 }, - .n_monitors = 1, - .layout = {.x = 0, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - }; - test_case.expect.n_logical_monitors = 2; - test_case.expect.screen_width = 1024 * 2; - test_case.expect.monitors[0].current_mode = 0; - test_case.expect.primary_logical_monitor = 0; - - test_case.expect.crtcs[0].current_mode = 0; - test_case.expect.crtcs[1].current_mode = 0; - test_case.expect.crtcs[1].x = 1024; - - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_lid_opened_config (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0 - } - }, - .n_modes = 1, - .outputs = { - { - .crtc = 0, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - .is_laptop_panel = TRUE - }, - { - .crtc = 1, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 1 }, - .n_possible_crtcs = 1, - .width_mm = 220, - .height_mm = 124 - } - }, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0 - }, - { - .current_mode = 0 - } - }, - .n_crtcs = 2 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = -1, - .width_mm = 222, - .height_mm = 125 - }, - { - .outputs = { 1 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 1, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 220, - .height_mm = 124 - } - }, - .n_monitors = 2, - .logical_monitors = { - { - .monitors = { 1 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - }, - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 1024, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - } - }, - .n_logical_monitors = 1, /* Second one checked after lid opened. */ - .primary_logical_monitor = 0, - .n_outputs = 2, - .crtcs = { - { - .current_mode = -1, - }, - { - .current_mode = 0, - } - }, - .n_crtcs = 2, - .n_tiled_monitors = 0, - .screen_width = 1024, - .screen_height = 768 - } - }; - MetaMonitorTestSetup *test_setup; - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - meta_backend_test_set_is_lid_closed (META_BACKEND_TEST (backend), TRUE); - - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); - - meta_backend_test_set_is_lid_closed (META_BACKEND_TEST (backend), FALSE); - meta_monitor_manager_lid_is_closed_changed (monitor_manager); - - test_case.expect.n_logical_monitors = 2; - test_case.expect.screen_width = 1024 * 2; - test_case.expect.monitors[0].current_mode = 0; - test_case.expect.crtcs[0].current_mode = 0; - test_case.expect.crtcs[0].x = 1024; - test_case.expect.crtcs[1].current_mode = 0; - test_case.expect.crtcs[1].x = 0; - - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_lid_closed_no_external (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0 - } - }, - .n_modes = 1, - .outputs = { - { - .crtc = 0, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - .is_laptop_panel = TRUE - } - }, - .n_outputs = 1, - .crtcs = { - { - .current_mode = 0 - } - }, - .n_crtcs = 1 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125 - } - }, - .n_monitors = 1, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - } - }, - .n_logical_monitors = 1, - .primary_logical_monitor = 0, - .n_outputs = 1, - .crtcs = { - { - .current_mode = 0, - }, - }, - .n_crtcs = 1, - .n_tiled_monitors = 0, - .screen_width = 1024, - .screen_height = 768 - } - }; - MetaMonitorTestSetup *test_setup; - MetaBackend *backend = meta_get_backend (); - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - meta_backend_test_set_is_lid_closed (META_BACKEND_TEST (backend), TRUE); - - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_lid_closed_with_hotplugged_external (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0 - } - }, - .n_modes = 1, - .outputs = { - { - .crtc = -1, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - .is_laptop_panel = TRUE - }, - { - .crtc = -1, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 1 }, - .n_possible_crtcs = 1, - .width_mm = 220, - .height_mm = 124 - } - }, - .n_outputs = 1, /* Second is hotplugged later */ - .crtcs = { - { - .current_mode = -1 - }, - { - .current_mode = -1 - } - }, - .n_crtcs = 2 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125 - }, - { - .outputs = { 1 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 1, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 220, - .height_mm = 124 - } - }, - .n_monitors = 1, /* Second is hotplugged later */ - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - }, - { - .monitors = { 1 }, - .n_monitors = 1, - .layout = { .x = 1024, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - } - }, - .n_logical_monitors = 1, /* Second is hotplugged later */ - .primary_logical_monitor = 0, - .n_outputs = 1, - .crtcs = { - { - .current_mode = 0, - }, - { - .current_mode = -1, - } - }, - .n_crtcs = 2, - .n_tiled_monitors = 0, - .screen_width = 1024, - .screen_height = 768 - } - }; - MetaMonitorTestSetup *test_setup; - MetaBackend *backend = meta_get_backend (); - - /* - * The first part of this test emulate the following: - * 1) Start with the lid open - * 2) Connect external monitor - * 3) Close lid - */ - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - meta_backend_test_set_is_lid_closed (META_BACKEND_TEST (backend), FALSE); - - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); - - /* External monitor connected */ - - test_case.setup.n_outputs = 2; - test_case.expect.n_outputs = 2; - test_case.expect.n_monitors = 2; - test_case.expect.n_logical_monitors = 2; - test_case.expect.crtcs[1].current_mode = 0; - test_case.expect.crtcs[1].x = 1024; - test_case.expect.screen_width = 1024 * 2; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); - - /* Lid closed */ - - test_case.expect.monitors[0].current_mode = -1; - test_case.expect.logical_monitors[0].monitors[0] = 1, - test_case.expect.n_logical_monitors = 1; - test_case.expect.crtcs[0].current_mode = -1; - test_case.expect.crtcs[1].x = 0; - test_case.expect.screen_width = 1024; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - meta_backend_test_set_is_lid_closed (META_BACKEND_TEST (backend), TRUE); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); - - /* - * The second part of this test emulate the following: - * 1) Open lid - * 2) Disconnect external monitor - * 3) Close lid - * 4) Open lid - */ - - /* Lid opened */ - - test_case.expect.monitors[0].current_mode = 0; - test_case.expect.logical_monitors[0].monitors[0] = 0, - test_case.expect.logical_monitors[1].monitors[0] = 1, - test_case.expect.n_logical_monitors = 2; - test_case.expect.crtcs[0].current_mode = 0; - test_case.expect.crtcs[1].x = 1024; - test_case.expect.screen_width = 1024 * 2; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - meta_backend_test_set_is_lid_closed (META_BACKEND_TEST (backend), FALSE); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); - - /* External monitor disconnected */ - - test_case.setup.n_outputs = 1; - test_case.expect.n_outputs = 1; - test_case.expect.n_monitors = 1; - test_case.expect.n_logical_monitors = 1; - test_case.expect.crtcs[1].current_mode = -1; - test_case.expect.screen_width = 1024; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); - - /* Lid closed */ - - test_case.expect.logical_monitors[0].monitors[0] = 0, - test_case.expect.n_logical_monitors = 1; - test_case.expect.screen_width = 1024; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - meta_backend_test_set_is_lid_closed (META_BACKEND_TEST (backend), TRUE); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); - - /* Lid opened */ - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - meta_backend_test_set_is_lid_closed (META_BACKEND_TEST (backend), FALSE); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_lid_scaled_closed_opened (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 1920, - .height = 1080, - .refresh_rate = 60.000495910644531 - } - }, - .n_modes = 1, - .outputs = { - { - .crtc = 0, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - .is_laptop_panel = TRUE - }, - }, - .n_outputs = 1, - .crtcs = { - { - .current_mode = 0 - }, - }, - .n_crtcs = 1 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 1920, - .height = 1080, - .refresh_rate = 60.000495910644531, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125, - } - }, - .n_monitors = 1, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 960, .height = 540 }, - .scale = 2 - } - }, - .n_logical_monitors = 1, - .primary_logical_monitor = 0, - .n_outputs = 1, - .crtcs = { - { - .current_mode = 0, - } - }, - .n_crtcs = 1, - .n_tiled_monitors = 0, - .screen_width = 960, - .screen_height = 540 - } - }; - MetaMonitorTestSetup *test_setup; - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - - if (!meta_is_stage_views_enabled ()) - { - g_test_skip ("Not using stage views"); - return; - } - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NONE); - set_custom_monitor_config ("lid-scale.xml"); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); - - meta_backend_test_set_is_lid_closed (META_BACKEND_TEST (backend), TRUE); - meta_monitor_manager_lid_is_closed_changed (monitor_manager); - - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); - - meta_backend_test_set_is_lid_closed (META_BACKEND_TEST (backend), FALSE); - meta_monitor_manager_lid_is_closed_changed (monitor_manager); - - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_no_outputs (void) -{ - MonitorTestCase test_case = { - .setup = { - .n_modes = 0, - .n_outputs = 0, - .n_crtcs = 0 - }, - - .expect = { - .n_monitors = 0, - .n_logical_monitors = 0, - .primary_logical_monitor = -1, - .n_outputs = 0, - .n_crtcs = 0, - .n_tiled_monitors = 0, - .screen_width = META_MONITOR_MANAGER_MIN_SCREEN_WIDTH, - .screen_height = META_MONITOR_MANAGER_MIN_SCREEN_HEIGHT - } - }; - MetaMonitorTestSetup *test_setup; - GError *error = NULL; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); - - if (!meta_test_client_do (x11_monitor_test_client, &error, - "resize", X11_TEST_CLIENT_WINDOW, - "123", "210", - NULL)) - g_error ("Failed to resize X11 window: %s", error->message); - - if (!meta_test_client_do (wayland_monitor_test_client, &error, - "resize", WAYLAND_TEST_CLIENT_WINDOW, - "123", "210", - NULL)) - g_error ("Failed to resize Wayland window: %s", error->message); - - check_monitor_test_clients_state (); - - /* Also check that we handle going headless -> headless */ - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_underscanning_config (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0 - } - }, - .n_modes = 1, - .outputs = { - { - .crtc = 0, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - .is_underscanning = TRUE, - } - }, - .n_outputs = 1, - .crtcs = { - { - .current_mode = 0 - } - }, - .n_crtcs = 1 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125, - .is_underscanning = TRUE, - } - }, - .n_monitors = 1, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - } - }, - .n_logical_monitors = 1, - .primary_logical_monitor = 0, - .n_outputs = 1, - .crtcs = { - { - .current_mode = 0, - } - }, - .n_crtcs = 1, - .screen_width = 1024, - .screen_height = 768 - } - }; - MetaMonitorTestSetup *test_setup; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_preferred_non_first_mode (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.0, - .flags = META_CRTC_MODE_FLAG_NHSYNC, - }, - { - .width = 800, - .height = 600, - .refresh_rate = 60.0, - .flags = META_CRTC_MODE_FLAG_PHSYNC, - }, - }, - .n_modes = 2, - .outputs = { - { - .crtc = -1, - .modes = { 0, 1 }, - .n_modes = 2, - .preferred_mode = 1, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125 - } - }, - .n_outputs = 1, - .crtcs = { - { - .current_mode = -1 - } - }, - .n_crtcs = 1 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 1 - } - } - }, - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125 - } - }, - .n_monitors = 1, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 800, .height = 600 }, - .scale = 1 - }, - }, - .n_logical_monitors = 1, - .primary_logical_monitor = 0, - .n_outputs = 1, - .crtcs = { - { - .current_mode = 1, - } - }, - .n_crtcs = 1, - .screen_width = 800, - .screen_height = 600, - } - }; - MetaMonitorTestSetup *test_setup; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_non_upright_panel (void) -{ - MonitorTestCase test_case = initial_test_case; - MetaMonitorTestSetup *test_setup; - - test_case.setup.modes[1] = (MonitorTestCaseMode) { - .width = 768, - .height = 1024, - .refresh_rate = 60.0, - }; - test_case.setup.n_modes = 2; - test_case.setup.outputs[0].modes[0] = 1; - test_case.setup.outputs[0].preferred_mode = 1; - test_case.setup.outputs[0].panel_orientation_transform = - META_MONITOR_TRANSFORM_90; - /* - * Note we do not swap outputs[0].width_mm and height_mm, because these get - * swapped for rotated panels inside the xrandr / kms code and we directly - * create a dummy output here, skipping this code. - */ - test_case.setup.crtcs[0].current_mode = 1; - - test_case.expect.monitors[0].modes[0].crtc_modes[0].crtc_mode = 1; - test_case.expect.crtcs[0].current_mode = 1; - test_case.expect.crtcs[0].transform = META_MONITOR_TRANSFORM_90; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_switch_external_without_external (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0 - } - }, - .n_modes = 1, - .outputs = { - { - .crtc = 0, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - .is_laptop_panel = TRUE - }, - { - .crtc = 1, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 1 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - .is_laptop_panel = TRUE - } - }, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0 - }, - { - .current_mode = 0 - } - }, - .n_crtcs = 2 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125 - }, - { - .outputs = { 1 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 1, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125 - } - }, - .n_monitors = 2, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - }, - { - .monitors = { 1 }, - .n_monitors = 1, - .layout = { .x = 1024, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - } - }, - .n_logical_monitors = 2, - .primary_logical_monitor = 0, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0, - }, - { - .current_mode = 0, - .x = 1024, - }, - }, - .n_crtcs = 2, - .n_tiled_monitors = 0, - .screen_width = 2048, - .screen_height = 768 - } - }; - MetaMonitorTestSetup *test_setup; - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - - meta_monitor_manager_switch_config (monitor_manager, - META_MONITOR_SWITCH_CONFIG_EXTERNAL); - check_monitor_configuration (&test_case.expect); - - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_custom_vertical_config (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531 - }, - { - .width = 800, - .height = 600, - .refresh_rate = 60.000495910644531 - } - }, - .n_modes = 2, - .outputs = { - { - .crtc = 0, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125 - }, - { - .crtc = 1, - .modes = { 1 }, - .n_modes = 1, - .preferred_mode = 1, - .possible_crtcs = { 1 }, - .n_possible_crtcs = 1, - .width_mm = 220, - .height_mm = 124 - } - }, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0 - }, - { - .current_mode = 0 - } - }, - .n_crtcs = 2 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125 - }, - { - .outputs = { 1 }, - .n_outputs = 1, - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.000495910644531, - .crtc_modes = { - { - .output = 1, - .crtc_mode = 1 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 220, - .height_mm = 124 - } - }, - .n_monitors = 2, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - }, - { - .monitors = { 1 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 768, .width = 800, .height = 600 }, - .scale = 1 - } - }, - .n_logical_monitors = 2, - .primary_logical_monitor = 0, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0, - }, - { - .current_mode = 1, - .y = 768, - } - }, - .n_crtcs = 2, - .n_tiled_monitors = 0, - .screen_width = 1024, - .screen_height = 768 + 600 - } - }; - MetaMonitorTestSetup *test_setup; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NONE); - set_custom_monitor_config ("vertical.xml"); - emulate_hotplug (test_setup); - - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_custom_primary_config (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531 - }, - { - .width = 800, - .height = 600, - .refresh_rate = 60.000495910644531 - } - }, - .n_modes = 2, - .outputs = { - { - .crtc = 0, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125 - }, - { - .crtc = 1, - .modes = { 1 }, - .n_modes = 1, - .preferred_mode = 1, - .possible_crtcs = { 1 }, - .n_possible_crtcs = 1, - .width_mm = 220, - .height_mm = 124 - } - }, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0 - }, - { - .current_mode = 0 - } - }, - .n_crtcs = 2 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125 - }, - { - .outputs = { 1 }, - .n_outputs = 1, - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.000495910644531, - .crtc_modes = { - { - .output = 1, - .crtc_mode = 1 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 220, - .height_mm = 124 - } - }, - .n_monitors = 2, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - }, - { - .monitors = { 1 }, - .n_monitors = 1, - .layout = { .x = 1024, .y = 0, .width = 800, .height = 600 }, - .scale = 1 - } - }, - .n_logical_monitors = 2, - .primary_logical_monitor = 1, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0, - }, - { - .current_mode = 1, - .x = 1024, - } - }, - .n_crtcs = 2, - .n_tiled_monitors = 0, - .screen_width = 1024 + 800, - .screen_height = 768 - } - }; - MetaMonitorTestSetup *test_setup; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NONE); - set_custom_monitor_config ("primary.xml"); - emulate_hotplug (test_setup); - - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_custom_underscanning_config (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531 - } - }, - .n_modes = 1, - .outputs = { - { - .crtc = 0, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125 - }, - }, - .n_outputs = 1, - .crtcs = { - { - .current_mode = 0 - }, - }, - .n_crtcs = 1 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125, - .is_underscanning = TRUE, - } - }, - .n_monitors = 1, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - } - }, - .n_logical_monitors = 1, - .primary_logical_monitor = 0, - .n_outputs = 1, - .crtcs = { - { - .current_mode = 0, - } - }, - .n_crtcs = 1, - .n_tiled_monitors = 0, - .screen_width = 1024, - .screen_height = 768 - } - }; - MetaMonitorTestSetup *test_setup; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NONE); - set_custom_monitor_config ("underscanning.xml"); - emulate_hotplug (test_setup); - - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_custom_scale_config (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 1920, - .height = 1080, - .refresh_rate = 60.000495910644531 - } - }, - .n_modes = 1, - .outputs = { - { - .crtc = 0, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125 - }, - }, - .n_outputs = 1, - .crtcs = { - { - .current_mode = 0 - }, - }, - .n_crtcs = 1 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 1920, - .height = 1080, - .refresh_rate = 60.000495910644531, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125, - } - }, - .n_monitors = 1, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 960, .height = 540 }, - .scale = 2 - } - }, - .n_logical_monitors = 1, - .primary_logical_monitor = 0, - .n_outputs = 1, - .crtcs = { - { - .current_mode = 0, - } - }, - .n_crtcs = 1, - .n_tiled_monitors = 0, - .screen_width = 960, - .screen_height = 540 - } - }; - MetaMonitorTestSetup *test_setup; - - if (!meta_is_stage_views_enabled ()) - { - g_test_skip ("Not using stage views"); - return; - } - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NONE); - set_custom_monitor_config ("scale.xml"); - emulate_hotplug (test_setup); - - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_custom_fractional_scale_config (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 1200, - .height = 900, - .refresh_rate = 60.000495910644531 - } - }, - .n_modes = 1, - .outputs = { - { - .crtc = 0, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125 - }, - }, - .n_outputs = 1, - .crtcs = { - { - .current_mode = 0 - }, - }, - .n_crtcs = 1 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 1200, - .height = 900, - .refresh_rate = 60.000495910644531, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125, - } - }, - .n_monitors = 1, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 800, .height = 600 }, - .scale = 1.5 - } - }, - .n_logical_monitors = 1, - .primary_logical_monitor = 0, - .n_outputs = 1, - .crtcs = { - { - .current_mode = 0, - } - }, - .n_crtcs = 1, - .n_tiled_monitors = 0, - .screen_width = 800, - .screen_height = 600 - } - }; - MetaMonitorTestSetup *test_setup; - - if (!meta_is_stage_views_enabled ()) - { - g_test_skip ("Not using stage views"); - return; - } - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NONE); - set_custom_monitor_config ("fractional-scale.xml"); - emulate_hotplug (test_setup); - - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_custom_high_precision_fractional_scale_config (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531 - } - }, - .n_modes = 1, - .outputs = { - { - .crtc = 0, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125 - }, - }, - .n_outputs = 1, - .crtcs = { - { - .current_mode = 0 - }, - }, - .n_crtcs = 1 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125, - } - }, - .n_monitors = 1, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 744, .height = 558 }, - .scale = 1024.0/744.0 /* 1.3763440847396851 */ - } - }, - .n_logical_monitors = 1, - .primary_logical_monitor = 0, - .n_outputs = 1, - .crtcs = { - { - .current_mode = 0, - } - }, - .n_crtcs = 1, - .n_tiled_monitors = 0, - .screen_width = 744, - .screen_height = 558 - } - }; - MetaMonitorTestSetup *test_setup; - - if (!meta_is_stage_views_enabled ()) - { - g_test_skip ("Not using stage views"); - return; - } - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NONE); - set_custom_monitor_config ("high-precision-fractional-scale.xml"); - emulate_hotplug (test_setup); - - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_custom_tiled_config (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 400, - .height = 600, - .refresh_rate = 60.000495910644531 - } - }, - .n_modes = 1, - .outputs = { - { - .crtc = -1, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0, 1 }, - .n_possible_crtcs = 2, - .width_mm = 222, - .height_mm = 125, - .tile_info = { - .group_id = 1, - .max_h_tiles = 2, - .max_v_tiles = 1, - .loc_h_tile = 0, - .loc_v_tile = 0, - .tile_w = 400, - .tile_h = 600 - } - }, - { - .crtc = -1, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0, 1 }, - .n_possible_crtcs = 2, - .width_mm = 222, - .height_mm = 125, - .tile_info = { - .group_id = 1, - .max_h_tiles = 2, - .max_v_tiles = 1, - .loc_h_tile = 1, - .loc_v_tile = 0, - .tile_w = 400, - .tile_h = 600 - } - } - }, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0 - }, - { - .current_mode = -1 - } - }, - .n_crtcs = 2 - }, - - .expect = { - .monitors = { - { - .outputs = { 0, 1 }, - .n_outputs = 2, - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.000495910644531, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0, - }, - { - .output = 1, - .crtc_mode = 0, - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125, - } - }, - .n_monitors = 1, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 400, .height = 300 }, - .scale = 2 - } - }, - .n_logical_monitors = 1, - .primary_logical_monitor = 0, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0, - }, - { - .current_mode = 0, - .x = 200, - .y = 0 - } - }, - .n_crtcs = 2, - .n_tiled_monitors = 1, - .screen_width = 400, - .screen_height = 300 - } - }; - MetaMonitorTestSetup *test_setup; - - if (!meta_is_stage_views_enabled ()) - { - g_test_skip ("Not using stage views"); - return; - } - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NONE); - set_custom_monitor_config ("tiled.xml"); - emulate_hotplug (test_setup); - - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_custom_tiled_custom_resolution_config (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 400, - .height = 600, - .refresh_rate = 60.000495910644531 - }, - { - .width = 640, - .height = 480, - .refresh_rate = 60.000495910644531 - } - }, - .n_modes = 2, - .outputs = { - { - .crtc = -1, - .modes = { 0, 1 }, - .n_modes = 2, - .preferred_mode = 0, - .possible_crtcs = { 0, 1 }, - .n_possible_crtcs = 2, - .width_mm = 222, - .height_mm = 125, - .tile_info = { - .group_id = 1, - .max_h_tiles = 2, - .max_v_tiles = 1, - .loc_h_tile = 0, - .loc_v_tile = 0, - .tile_w = 400, - .tile_h = 600 - } - }, - { - .crtc = -1, - .modes = { 0, 1 }, - .n_modes = 2, - .preferred_mode = 0, - .possible_crtcs = { 0, 1 }, - .n_possible_crtcs = 2, - .width_mm = 222, - .height_mm = 125, - .tile_info = { - .group_id = 1, - .max_h_tiles = 2, - .max_v_tiles = 1, - .loc_h_tile = 1, - .loc_v_tile = 0, - .tile_w = 400, - .tile_h = 600 - } - } - }, - .n_outputs = 2, - .crtcs = { - { - .current_mode = -1 - }, - { - .current_mode = -1 - } - }, - .n_crtcs = 2 - }, - - .expect = { - .monitors = { - { - .outputs = { 0, 1 }, - .n_outputs = 2, - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.000495910644531, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0, - }, - { - .output = 1, - .crtc_mode = 0, - } - } - }, - { - .width = 640, - .height = 480, - .refresh_rate = 60.000495910644531, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 1, - }, - { - .output = 1, - .crtc_mode = -1, - } - } - } - }, - .n_modes = 2, - .current_mode = 1, - .width_mm = 222, - .height_mm = 125, - } - }, - .n_monitors = 1, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 320, .height = 240 }, - .scale = 2 - } - }, - .n_logical_monitors = 1, - .primary_logical_monitor = 0, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 1, - }, - { - .current_mode = -1, - .x = 400, - .y = 0, - } - }, - .n_crtcs = 2, - .n_tiled_monitors = 1, - .screen_width = 320, - .screen_height = 240 - } - }; - MetaMonitorTestSetup *test_setup; - - if (!meta_is_stage_views_enabled ()) - { - g_test_skip ("Not using stage views"); - return; - } - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NONE); - set_custom_monitor_config ("tiled-custom-resolution.xml"); - emulate_hotplug (test_setup); - - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_custom_tiled_non_preferred_config (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 640, - .height = 480, - .refresh_rate = 60.0 - }, - { - .width = 800, - .height = 600, - .refresh_rate = 60.0 - }, - { - .width = 512, - .height = 768, - .refresh_rate = 120.0 - }, - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0 - }, - }, - .n_modes = 4, - .outputs = { - { - .crtc = -1, - .modes = { 0, 2 }, - .n_modes = 2, - .preferred_mode = 1, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - .tile_info = { - .group_id = 1, - .max_h_tiles = 2, - .max_v_tiles = 1, - .loc_h_tile = 0, - .loc_v_tile = 0, - .tile_w = 512, - .tile_h = 768 - } - }, - { - .crtc = -1, - .modes = { 1, 2, 3 }, - .n_modes = 3, - .preferred_mode = 0, - .possible_crtcs = { 1 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - .tile_info = { - .group_id = 1, - .max_h_tiles = 2, - .max_v_tiles = 1, - .loc_h_tile = 1, - .loc_v_tile = 0, - .tile_w = 512, - .tile_h = 768 - } - } - }, - .n_outputs = 2, - .crtcs = { - { - .current_mode = -1 - }, - { - .current_mode = -1 - } - }, - .n_crtcs = 2 - }, - - .expect = { - .monitors = { - { - .outputs = { 0, 1 }, - .n_outputs = 2, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 120.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 2 - }, - { - .output = 1, - .crtc_mode = 2, - } - } - }, - { - .width = 800, - .height = 600, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = -1 - }, - { - .output = 1, - .crtc_mode = 1, - } - } - }, - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = -1 - }, - { - .output = 1, - .crtc_mode = 3, - } - } - }, - }, - .n_modes = 3, - .current_mode = 1, - .width_mm = 222, - .height_mm = 125, - } - }, - .n_monitors = 1, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 800, .height = 600 }, - .scale = 1 - }, - }, - .n_logical_monitors = 1, - .primary_logical_monitor = 0, - .n_outputs = 2, - .crtcs = { - { - .current_mode = -1, - }, - { - .current_mode = 1, - } - }, - .n_crtcs = 2, - .n_tiled_monitors = 1, - .screen_width = 800, - .screen_height = 600, - } - }; - MetaMonitorTestSetup *test_setup; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NONE); - set_custom_monitor_config ("non-preferred-tiled-custom-resolution.xml"); - emulate_hotplug (test_setup); - - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_custom_mirrored_config (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.000495910644531 - } - }, - .n_modes = 1, - .outputs = { - { - .crtc = 0, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125 - }, - { - .crtc = 1, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 1 }, - .n_possible_crtcs = 1, - .width_mm = 220, - .height_mm = 124 - } - }, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0 - }, - { - .current_mode = 0 - } - }, - .n_crtcs = 2 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.000495910644531, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125 - }, - { - .outputs = { 1 }, - .n_outputs = 1, - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.000495910644531, - .crtc_modes = { - { - .output = 1, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 220, - .height_mm = 124 - } - }, - .n_monitors = 2, - .logical_monitors = { - { - .monitors = { 0, 1 }, - .n_monitors = 2, - .layout = { .x = 0, .y = 0, .width = 800, .height = 600 }, - .scale = 1 - } - }, - .n_logical_monitors = 1, - .primary_logical_monitor = 0, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0, - }, - { - .current_mode = 0, - } - }, - .n_crtcs = 2, - .n_tiled_monitors = 0, - .screen_width = 800, - .screen_height = 600 - } - }; - MetaMonitorTestSetup *test_setup; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NONE); - set_custom_monitor_config ("mirrored.xml"); - emulate_hotplug (test_setup); - - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_custom_first_rotated_config (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531 - } - }, - .n_modes = 1, - .outputs = { - { - .crtc = 0, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - }, - { - .crtc = 1, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 1 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - } - }, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0, - }, - { - .current_mode = 0 - } - }, - .n_crtcs = 2 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125, - }, - { - .outputs = { 1 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531, - .crtc_modes = { - { - .output = 1, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125, - } - }, - .n_monitors = 2, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 768, .height = 1024 }, - .scale = 1, - .transform = META_MONITOR_TRANSFORM_270 - }, - { - .monitors = { 1 }, - .n_monitors = 1, - .layout = { .x = 768, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - } - }, - .n_logical_monitors = 2, - .primary_logical_monitor = 0, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0, - .transform = META_MONITOR_TRANSFORM_270 - }, - { - .current_mode = 0, - .x = 768, - } - }, - .n_crtcs = 2, - .screen_width = 768 + 1024, - .screen_height = 1024 - } - }; - MetaMonitorTestSetup *test_setup; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NONE); - set_custom_monitor_config ("first-rotated.xml"); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_custom_second_rotated_config (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531 - } - }, - .n_modes = 1, - .outputs = { - { - .crtc = 0, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - }, - { - .crtc = 1, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 1 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - } - }, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0 - }, - { - .current_mode = 0 - } - }, - .n_crtcs = 2 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125, - }, - { - .outputs = { 1 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531, - .crtc_modes = { - { - .output = 1, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125, - } - }, - .n_monitors = 2, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 256, .width = 1024, .height = 768 }, - .scale = 1 - }, - { - .monitors = { 1 }, - .n_monitors = 1, - .layout = { .x = 1024, .y = 0, .width = 768, .height = 1024 }, - .scale = 1, - .transform = META_MONITOR_TRANSFORM_90 - } - }, - .n_logical_monitors = 2, - .primary_logical_monitor = 0, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0, - .y = 256, - }, - { - .current_mode = 0, - .transform = META_MONITOR_TRANSFORM_90, - .x = 1024, - } - }, - .n_crtcs = 2, - .screen_width = 768 + 1024, - .screen_height = 1024 - } - }; - MetaMonitorTestSetup *test_setup; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NONE); - set_custom_monitor_config ("second-rotated.xml"); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_custom_second_rotated_tiled_config (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531 - }, - { - .width = 400, - .height = 600, - .refresh_rate = 60.000495910644531 - } - }, - .n_modes = 2, - .outputs = { - { - .crtc = 0, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - }, - { - .crtc = -1, - .modes = { 1 }, - .n_modes = 1, - .preferred_mode = 1, - .possible_crtcs = { 1, 2 }, - .n_possible_crtcs = 2, - .width_mm = 222, - .height_mm = 125, - .tile_info = { - .group_id = 1, - .max_h_tiles = 2, - .max_v_tiles = 1, - .loc_h_tile = 0, - .loc_v_tile = 0, - .tile_w = 400, - .tile_h = 600 - } - }, - { - .crtc = -1, - .modes = { 1 }, - .n_modes = 1, - .preferred_mode = 1, - .possible_crtcs = { 1, 2 }, - .n_possible_crtcs = 2, - .width_mm = 222, - .height_mm = 125, - .tile_info = { - .group_id = 1, - .max_h_tiles = 2, - .max_v_tiles = 1, - .loc_h_tile = 1, - .loc_v_tile = 0, - .tile_w = 400, - .tile_h = 600 - } - } - }, - .n_outputs = 3, - .crtcs = { - { - .current_mode = -1 - }, - { - .current_mode = -1 - }, - { - .current_mode = -1 - } - }, - .n_crtcs = 3 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125, - }, - { - .outputs = { 1, 2 }, - .n_outputs = 2, - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.000495910644531, - .crtc_modes = { - { - .output = 1, - .crtc_mode = 1, - }, - { - .output = 2, - .crtc_mode = 1, - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125, - } - }, - .n_monitors = 2, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 256, .width = 1024, .height = 768 }, - .scale = 1 - }, - { - .monitors = { 1 }, - .n_monitors = 1, - .layout = { .x = 1024, .y = 0, .width = 600, .height = 800 }, - .scale = 1, - .transform = META_MONITOR_TRANSFORM_90 - } - }, - .n_logical_monitors = 2, - .primary_logical_monitor = 0, - .n_outputs = 3, - .crtcs = { - { - .current_mode = 0, - .y = 256, - }, - { - .current_mode = 1, - .transform = META_MONITOR_TRANSFORM_90, - .x = 1024, - .y = 0, - }, - { - .current_mode = 1, - .transform = META_MONITOR_TRANSFORM_90, - .x = 1024, - .y = 400, - } - }, - .n_crtcs = 3, - .n_tiled_monitors = 1, - .screen_width = 1024 + 600, - .screen_height = 1024 - } - }; - MetaMonitorTestSetup *test_setup; - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerTest *monitor_manager_test = - META_MONITOR_MANAGER_TEST (monitor_manager); - - meta_monitor_manager_test_set_handles_transforms (monitor_manager_test, - TRUE); - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NONE); - set_custom_monitor_config ("second-rotated-tiled.xml"); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_custom_second_rotated_nonnative_tiled_config (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531 - }, - { - .width = 400, - .height = 600, - .refresh_rate = 60.000495910644531 - } - }, - .n_modes = 2, - .outputs = { - { - .crtc = 0, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - }, - { - .crtc = -1, - .modes = { 1 }, - .n_modes = 1, - .preferred_mode = 1, - .possible_crtcs = { 1, 2 }, - .n_possible_crtcs = 2, - .width_mm = 222, - .height_mm = 125, - .tile_info = { - .group_id = 1, - .max_h_tiles = 2, - .max_v_tiles = 1, - .loc_h_tile = 0, - .loc_v_tile = 0, - .tile_w = 400, - .tile_h = 600 - } - }, - { - .crtc = -1, - .modes = { 1 }, - .n_modes = 1, - .preferred_mode = 1, - .possible_crtcs = { 1, 2 }, - .n_possible_crtcs = 2, - .width_mm = 222, - .height_mm = 125, - .tile_info = { - .group_id = 1, - .max_h_tiles = 2, - .max_v_tiles = 1, - .loc_h_tile = 1, - .loc_v_tile = 0, - .tile_w = 400, - .tile_h = 600 - } - } - }, - .n_outputs = 3, - .crtcs = { - { - .current_mode = -1 - }, - { - .current_mode = -1 - }, - { - .current_mode = -1 - } - }, - .n_crtcs = 3 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125, - }, - { - .outputs = { 1, 2 }, - .n_outputs = 2, - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.000495910644531, - .crtc_modes = { - { - .output = 1, - .crtc_mode = 1, - }, - { - .output = 2, - .crtc_mode = 1, - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125, - } - }, - .n_monitors = 2, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 256, .width = 1024, .height = 768 }, - .scale = 1 - }, - { - .monitors = { 1 }, - .n_monitors = 1, - .layout = { .x = 1024, .y = 0, .width = 600, .height = 800 }, - .scale = 1, - .transform = META_MONITOR_TRANSFORM_90 - } - }, - .n_logical_monitors = 2, - .primary_logical_monitor = 0, - .n_outputs = 3, - .crtcs = { - { - .current_mode = 0, - .y = 256, - }, - { - .current_mode = 1, - .transform = META_MONITOR_TRANSFORM_NORMAL, - .x = 1024, - .y = 0, - }, - { - .current_mode = 1, - .transform = META_MONITOR_TRANSFORM_NORMAL, - .x = 1024, - .y = 400, - } - }, - .n_crtcs = 3, - .n_tiled_monitors = 1, - .screen_width = 1024 + 600, - .screen_height = 1024 - } - }; - MetaMonitorTestSetup *test_setup; - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerTest *monitor_manager_test = - META_MONITOR_MANAGER_TEST (monitor_manager); - - meta_monitor_manager_test_set_handles_transforms (monitor_manager_test, - FALSE); - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NONE); - set_custom_monitor_config ("second-rotated-tiled.xml"); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_custom_second_rotated_nonnative_config (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531 - } - }, - .n_modes = 1, - .outputs = { - { - .crtc = 0, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - }, - { - .crtc = 1, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 1 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - } - }, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0 - }, - { - .current_mode = 0 - } - }, - .n_crtcs = 2 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125, - }, - { - .outputs = { 1 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531, - .crtc_modes = { - { - .output = 1, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125, - } - }, - .n_monitors = 2, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 256, .width = 1024, .height = 768 }, - .scale = 1 - }, - { - .monitors = { 1 }, - .n_monitors = 1, - .layout = { .x = 1024, .y = 0, .width = 768, .height = 1024 }, - .scale = 1, - .transform = META_MONITOR_TRANSFORM_90 - } - }, - .n_logical_monitors = 2, - .primary_logical_monitor = 0, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0, - .y = 256, - }, - { - .current_mode = 0, - .transform = META_MONITOR_TRANSFORM_NORMAL, - .x = 1024, - } - }, - .n_crtcs = 2, - .screen_width = 768 + 1024, - .screen_height = 1024 - } - }; - MetaMonitorTestSetup *test_setup; - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerTest *monitor_manager_test = - META_MONITOR_MANAGER_TEST (monitor_manager); - - if (!meta_is_stage_views_enabled ()) - { - g_test_skip ("Not using stage views"); - return; - } - - meta_monitor_manager_test_set_handles_transforms (monitor_manager_test, - FALSE); - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NONE); - set_custom_monitor_config ("second-rotated.xml"); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_custom_interlaced_config (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531 - }, - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531, - .flags = META_CRTC_MODE_FLAG_INTERLACE, - } - }, - .n_modes = 2, - .outputs = { - { - .crtc = 0, - .modes = { 0, 1 }, - .n_modes = 2, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125 - }, - }, - .n_outputs = 1, - .crtcs = { - { - .current_mode = 0 - }, - }, - .n_crtcs = 1 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531, - .flags = META_CRTC_MODE_FLAG_NONE, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0, - }, - } - }, - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531, - .flags = META_CRTC_MODE_FLAG_INTERLACE, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 1, - } - } - } - }, - .n_modes = 2, - .current_mode = 1, - .width_mm = 222, - .height_mm = 125, - } - }, - .n_monitors = 1, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 1024, .height = 768 }, - .scale = 1 - } - }, - .n_logical_monitors = 1, - .primary_logical_monitor = 0, - .n_outputs = 1, - .crtcs = { - { - .current_mode = 1, - } - }, - .n_crtcs = 1, - .n_tiled_monitors = 0, - .screen_width = 1024, - .screen_height = 768 - } - }; - MetaMonitorTestSetup *test_setup; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NONE); - set_custom_monitor_config ("interlaced.xml"); - emulate_hotplug (test_setup); - - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_custom_oneoff (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.0 - } - }, - .n_modes = 1, - .outputs = { - { - .crtc = -1, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0, 1 }, - .n_possible_crtcs = 2, - .width_mm = 222, - .height_mm = 125 - }, - { - .crtc = -1, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0, 1 }, - .n_possible_crtcs = 2, - .width_mm = 222, - .height_mm = 125, - .serial = "0x654321" - } - }, - .n_outputs = 2, - .crtcs = { - { - .current_mode = -1 - }, - { - .current_mode = -1 - } - }, - .n_crtcs = 2 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125 - }, - { - .outputs = { 1 }, - .n_outputs = 1, - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 1, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = -1, - .width_mm = 222, - .height_mm = 125 - } - }, - .n_monitors = 2, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 800, .height = 600 }, - .scale = 1, - .transform = META_MONITOR_TRANSFORM_NORMAL - }, - }, - .n_logical_monitors = 1, - .primary_logical_monitor = 0, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0, - }, - { - .current_mode = -1, - } - }, - .n_crtcs = 2, - .screen_width = 800, - .screen_height = 600, - } - }; - MetaMonitorTestSetup *test_setup; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NONE); - set_custom_monitor_config ("oneoff.xml"); - emulate_hotplug (test_setup); - - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_custom_lid_switch_config (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531 - } - }, - .n_modes = 1, - .outputs = { - { - .crtc = -1, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - .is_laptop_panel = TRUE - }, - { - .crtc = -1, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 1 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125, - } - }, - .n_outputs = 1, /* Second one hot plugged later */ - .crtcs = { - { - .current_mode = 0, - }, - { - .current_mode = 0 - } - }, - .n_crtcs = 2 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125, - }, - { - .outputs = { 1 }, - .n_outputs = 1, - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.000495910644531, - .crtc_modes = { - { - .output = 1, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125, - } - }, - .n_monitors = 1, /* Second one hot plugged later */ - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 768, .height = 1024 }, - .scale = 1, - .transform = META_MONITOR_TRANSFORM_270 - }, - { - .monitors = { 1 }, - .n_monitors = 1, - .layout = { .x = 1024, .y = 0, .width = 768, .height = 1024 }, - .scale = 1 - } - }, - .n_logical_monitors = 1, /* Second one hot plugged later */ - .primary_logical_monitor = 0, - .n_outputs = 1, - .crtcs = { - { - .current_mode = 0, - .transform = META_MONITOR_TRANSFORM_270 - }, - { - .current_mode = -1, - } - }, - .n_crtcs = 2, - .screen_width = 768, - .screen_height = 1024 - } - }; - MetaMonitorTestSetup *test_setup; - MetaBackend *backend = meta_get_backend (); - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NONE); - set_custom_monitor_config ("lid-switch.xml"); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); - - /* External monitor connected */ - - test_case.setup.n_outputs = 2; - test_case.expect.n_monitors = 2; - test_case.expect.n_outputs = 2; - test_case.expect.crtcs[0].transform = META_MONITOR_TRANSFORM_NORMAL; - test_case.expect.crtcs[1].current_mode = 0; - test_case.expect.crtcs[1].x = 1024; - test_case.expect.crtcs[1].transform = META_MONITOR_TRANSFORM_270; - test_case.expect.logical_monitors[0].layout = - (MetaRectangle) { .width = 1024, .height = 768 }; - test_case.expect.logical_monitors[0].transform = META_MONITOR_TRANSFORM_NORMAL; - test_case.expect.logical_monitors[1].transform = META_MONITOR_TRANSFORM_270; - test_case.expect.n_logical_monitors = 2; - test_case.expect.screen_width = 1024 + 768; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NONE); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); - - /* Lid was closed */ - - test_case.expect.crtcs[0].current_mode = -1; - test_case.expect.crtcs[1].transform = META_MONITOR_TRANSFORM_90; - test_case.expect.crtcs[1].x = 0; - test_case.expect.monitors[0].current_mode = -1; - test_case.expect.logical_monitors[0].layout = - (MetaRectangle) { .width = 768, .height = 1024 }; - test_case.expect.logical_monitors[0].monitors[0] = 1; - test_case.expect.logical_monitors[0].transform = META_MONITOR_TRANSFORM_90; - test_case.expect.n_logical_monitors = 1; - test_case.expect.screen_width = 768; - meta_backend_test_set_is_lid_closed (META_BACKEND_TEST (backend), TRUE); - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NONE); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); - - /* Lid was opened */ - - test_case.expect.crtcs[0].current_mode = 0; - test_case.expect.crtcs[0].transform = META_MONITOR_TRANSFORM_NORMAL; - test_case.expect.crtcs[1].current_mode = 0; - test_case.expect.crtcs[1].transform = META_MONITOR_TRANSFORM_270; - test_case.expect.crtcs[1].x = 1024; - test_case.expect.monitors[0].current_mode = 0; - test_case.expect.logical_monitors[0].layout = - (MetaRectangle) { .width = 1024, .height = 768 }; - test_case.expect.logical_monitors[0].monitors[0] = 0; - test_case.expect.logical_monitors[0].transform = META_MONITOR_TRANSFORM_NORMAL; - test_case.expect.logical_monitors[1].transform = META_MONITOR_TRANSFORM_270; - test_case.expect.n_logical_monitors = 2; - test_case.expect.screen_width = 1024 + 768; - meta_backend_test_set_is_lid_closed (META_BACKEND_TEST (backend), FALSE); - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NONE); - emulate_hotplug (test_setup); - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); -} - -static void -meta_test_monitor_migrated_rotated (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.0 - } - }, - .n_modes = 1, - .outputs = { - { - .crtc = -1, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125 - } - }, - .n_outputs = 1, - .crtcs = { - { - .current_mode = -1 - } - }, - .n_crtcs = 1 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125 - } - }, - .n_monitors = 1, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 600, .height = 800 }, - .scale = 1, - .transform = META_MONITOR_TRANSFORM_270 - }, - }, - .n_logical_monitors = 1, - .primary_logical_monitor = 0, - .n_outputs = 1, - .crtcs = { - { - .current_mode = 0, - .transform = META_MONITOR_TRANSFORM_270 - } - }, - .n_crtcs = 1, - .screen_width = 600, - .screen_height = 800, - } - }; - MetaMonitorTestSetup *test_setup; - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorConfigManager *config_manager = monitor_manager->config_manager; - MetaMonitorConfigStore *config_store = - meta_monitor_config_manager_get_store (config_manager); - g_autofree char *migrated_path = NULL; - const char *old_config_path; - g_autoptr (GFile) old_config_file = NULL; - GError *error = NULL; - const char *expected_path; - g_autofree char *migrated_data = NULL; - g_autofree char *expected_data = NULL; - g_autoptr (GFile) migrated_file = NULL; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NONE); - - migrated_path = g_build_filename (g_get_tmp_dir (), - "test-finished-migrated-monitors.xml", - NULL); - if (!meta_monitor_config_store_set_custom (config_store, - "/dev/null", - migrated_path, - &error)) - g_error ("Failed to set custom config store files: %s", error->message); - - old_config_path = g_test_get_filename (G_TEST_DIST, - "tests", "migration", - "rotated-old.xml", - NULL); - old_config_file = g_file_new_for_path (old_config_path); - if (!meta_migrate_old_monitors_config (config_store, - old_config_file, - &error)) - g_error ("Failed to migrate config: %s", error->message); - - emulate_hotplug (test_setup); - - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); - - expected_path = g_test_get_filename (G_TEST_DIST, - "tests", "migration", - "rotated-new-finished.xml", - NULL); - expected_data = read_file (expected_path); - migrated_data = read_file (migrated_path); - - g_assert_nonnull (expected_data); - g_assert_nonnull (migrated_data); - - g_assert (strcmp (expected_data, migrated_data) == 0); - - migrated_file = g_file_new_for_path (migrated_path); - if (!g_file_delete (migrated_file, NULL, &error)) - g_error ("Failed to remove test data output file: %s", error->message); -} - -static void -meta_test_monitor_migrated_wiggle_discard (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 59.0 - } - }, - .n_modes = 1, - .outputs = { - { - .crtc = -1, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125 - } - }, - .n_outputs = 1, - .crtcs = { - { - .current_mode = -1 - } - }, - .n_crtcs = 1 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 59.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125 - } - }, - .n_monitors = 1, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 800, .height = 600 }, - .scale = 1, - .transform = META_MONITOR_TRANSFORM_NORMAL - }, - }, - .n_logical_monitors = 1, - .primary_logical_monitor = 0, - .n_outputs = 1, - .crtcs = { - { - .current_mode = 0, - } - }, - .n_crtcs = 1, - .screen_width = 800, - .screen_height = 600, - } - }; - MetaMonitorTestSetup *test_setup; - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorConfigManager *config_manager = monitor_manager->config_manager; - MetaMonitorConfigStore *config_store = - meta_monitor_config_manager_get_store (config_manager); - g_autofree char *migrated_path = NULL; - const char *old_config_path; - g_autoptr (GFile) old_config_file = NULL; - GError *error = NULL; - const char *expected_path; - g_autofree char *migrated_data = NULL; - g_autofree char *expected_data = NULL; - g_autoptr (GFile) migrated_file = NULL; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NONE); - - migrated_path = g_build_filename (g_get_tmp_dir (), - "test-finished-migrated-monitors.xml", - NULL); - if (!meta_monitor_config_store_set_custom (config_store, - "/dev/null", - migrated_path, - &error)) - g_error ("Failed to set custom config store files: %s", error->message); - - old_config_path = g_test_get_filename (G_TEST_DIST, - "tests", "migration", - "wiggle-old.xml", - NULL); - old_config_file = g_file_new_for_path (old_config_path); - if (!meta_migrate_old_monitors_config (config_store, - old_config_file, - &error)) - g_error ("Failed to migrate config: %s", error->message); - - g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, - "Failed to finish monitors config migration: " - "Mode not available on monitor"); - emulate_hotplug (test_setup); - g_test_assert_expected_messages (); - - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); - - expected_path = g_test_get_filename (G_TEST_DIST, - "tests", "migration", - "wiggle-new-discarded.xml", - NULL); - expected_data = read_file (expected_path); - migrated_data = read_file (migrated_path); - - g_assert_nonnull (expected_data); - g_assert_nonnull (migrated_data); - - g_assert (strcmp (expected_data, migrated_data) == 0); - - migrated_file = g_file_new_for_path (migrated_path); - if (!g_file_delete (migrated_file, NULL, &error)) - g_error ("Failed to remove test data output file: %s", error->message); -} - -static gboolean -quit_main_loop (gpointer data) -{ - GMainLoop *loop = data; - - g_main_loop_quit (loop); - - return G_SOURCE_REMOVE; -} - -static void -dispatch (void) -{ - GMainLoop *loop; - - loop = g_main_loop_new (NULL, FALSE); - meta_later_add (META_LATER_BEFORE_REDRAW, - quit_main_loop, - loop, - NULL); - g_main_loop_run (loop); -} - -static MetaTestClient * -create_test_window (MetaContext *context, - const char *window_name) -{ - MetaTestClient *test_client; - static int client_count = 0; - g_autofree char *client_name = NULL; - g_autoptr (GError) error = NULL; - - client_name = g_strdup_printf ("test_client_%d", client_count++); - test_client = meta_test_client_new (context, - client_name, META_WINDOW_CLIENT_TYPE_WAYLAND, - &error); - if (!test_client) - g_error ("Failed to launch test client: %s", error->message); - - if (!meta_test_client_do (test_client, &error, - "create", window_name, - NULL)) - g_error ("Failed to create window: %s", error->message); - - return test_client; -} - -static void -meta_test_monitor_wm_tiling (void) -{ - MetaContext *context = test_context; - MonitorTestCase test_case = initial_test_case; - MetaMonitorTestSetup *test_setup; - g_autoptr (GError) error = NULL; - MetaTestClient *test_client; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - emulate_hotplug (test_setup); - - /* - * 1) Start with two monitors connected. - * 2) Tile it on the second monitor. - * 3) Unplug both monitors. - * 4) Replug in first monitor. - */ - - const char *test_window_name= "window1"; - test_client = create_test_window (context, test_window_name); - - if (!meta_test_client_do (test_client, &error, - "show", test_window_name, - NULL)) - g_error ("Failed to show the window: %s", error->message); - - MetaWindow *test_window = - meta_test_client_find_window (test_client, - test_window_name, - &error); - if (!test_window) - g_error ("Failed to find the window: %s", error->message); - meta_test_client_wait_for_window_shown (test_client, test_window); - - meta_window_tile (test_window, META_TILE_MAXIMIZED); - meta_window_move_to_monitor (test_window, 1); - check_test_client_state (test_client); - - test_case.setup.n_outputs = 0; - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - emulate_hotplug (test_setup); - test_case.setup.n_outputs = 1; - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - emulate_hotplug (test_setup); - - dispatch (); - - /* - * 1) Start with two monitors connected. - * 2) Tile a window on the second monitor. - * 3) Untile window. - * 4) Unplug monitor. - * 5) Tile window again. - */ - - test_case.setup.n_outputs = 2; - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - emulate_hotplug (test_setup); - - meta_window_move_to_monitor (test_window, 1); - meta_window_tile (test_window, META_TILE_NONE); - - test_case.setup.n_outputs = 1; - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); - emulate_hotplug (test_setup); - - meta_window_tile (test_window, META_TILE_MAXIMIZED); - - meta_test_client_destroy (test_client); -} - -static void -meta_test_monitor_migrated_wiggle (void) -{ - MonitorTestCase test_case = { - .setup = { - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.0 - } - }, - .n_modes = 1, - .outputs = { - { - .crtc = -1, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125 - } - }, - .n_outputs = 1, - .crtcs = { - { - .current_mode = -1 - } - }, - .n_crtcs = 1 - }, - - .expect = { - .monitors = { - { - .outputs = { 0 }, - .n_outputs = 1, - .modes = { - { - .width = 800, - .height = 600, - .refresh_rate = 60.0, - .crtc_modes = { - { - .output = 0, - .crtc_mode = 0 - } - } - } - }, - .n_modes = 1, - .current_mode = 0, - .width_mm = 222, - .height_mm = 125 - } - }, - .n_monitors = 1, - .logical_monitors = { - { - .monitors = { 0 }, - .n_monitors = 1, - .layout = { .x = 0, .y = 0, .width = 600, .height = 800 }, - .scale = 1, - .transform = META_MONITOR_TRANSFORM_90 - }, - }, - .n_logical_monitors = 1, - .primary_logical_monitor = 0, - .n_outputs = 1, - .crtcs = { - { - .current_mode = 0, - .transform = META_MONITOR_TRANSFORM_90 - } - }, - .n_crtcs = 1, - .screen_width = 600, - .screen_height = 800, - } - }; - MetaMonitorTestSetup *test_setup; - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorConfigManager *config_manager = monitor_manager->config_manager; - MetaMonitorConfigStore *config_store = - meta_monitor_config_manager_get_store (config_manager); - g_autofree char *migrated_path = NULL; - const char *old_config_path; - g_autoptr (GFile) old_config_file = NULL; - GError *error = NULL; - const char *expected_path; - g_autofree char *migrated_data = NULL; - g_autofree char *expected_data = NULL; - g_autoptr (GFile) migrated_file = NULL; - - test_setup = create_monitor_test_setup (&test_case.setup, - MONITOR_TEST_FLAG_NONE); - - migrated_path = g_build_filename (g_get_tmp_dir (), - "test-finished-migrated-monitors.xml", - NULL); - if (!meta_monitor_config_store_set_custom (config_store, - "/dev/null", - migrated_path, - &error)) - g_error ("Failed to set custom config store files: %s", error->message); - - old_config_path = g_test_get_filename (G_TEST_DIST, - "tests", "migration", - "wiggle-old.xml", - NULL); - old_config_file = g_file_new_for_path (old_config_path); - if (!meta_migrate_old_monitors_config (config_store, - old_config_file, - &error)) - g_error ("Failed to migrate config: %s", error->message); - - emulate_hotplug (test_setup); - - check_monitor_configuration (&test_case.expect); - check_monitor_test_clients_state (); - - expected_path = g_test_get_filename (G_TEST_DIST, - "tests", "migration", - "wiggle-new-finished.xml", - NULL); - expected_data = read_file (expected_path); - migrated_data = read_file (migrated_path); - - g_assert_nonnull (expected_data); - g_assert_nonnull (migrated_data); - - g_assert (strcmp (expected_data, migrated_data) == 0); - - migrated_file = g_file_new_for_path (migrated_path); - if (!g_file_delete (migrated_file, NULL, &error)) - g_error ("Failed to remove test data output file: %s", error->message); -} - -static void -test_case_setup (void **fixture, - const void *data) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerTest *monitor_manager_test = - META_MONITOR_MANAGER_TEST (monitor_manager); - MetaMonitorConfigManager *config_manager = monitor_manager->config_manager; - - meta_monitor_manager_test_set_handles_transforms (monitor_manager_test, - TRUE); - meta_monitor_config_manager_set_current (config_manager, NULL); - meta_monitor_config_manager_clear_history (config_manager); -} - -static void -add_monitor_test (const char *test_path, - GTestFunc test_func) -{ - g_test_add (test_path, gpointer, NULL, - test_case_setup, - (void (* ) (void **, const void *)) test_func, - NULL); -} - -static MetaMonitorTestSetup * -create_initial_test_setup (void) -{ - return create_monitor_test_setup (&initial_test_case.setup, - MONITOR_TEST_FLAG_NO_STORED); -} - -void -init_monitor_tests (void) -{ - meta_monitor_manager_test_init_test_setup (create_initial_test_setup); - - add_monitor_test ("/backends/monitor/initial-linear-config", - meta_test_monitor_initial_linear_config); - add_monitor_test ("/backends/monitor/one-disconnected-linear-config", - meta_test_monitor_one_disconnected_linear_config); - add_monitor_test ("/backends/monitor/one-off-linear-config", - meta_test_monitor_one_off_linear_config); - add_monitor_test ("/backends/monitor/preferred-linear-config", - meta_test_monitor_preferred_linear_config); - add_monitor_test ("/backends/monitor/tiled-linear-config", - meta_test_monitor_tiled_linear_config); - add_monitor_test ("/backends/monitor/tiled-non-preferred-linear-config", - meta_test_monitor_tiled_non_preferred_linear_config); - add_monitor_test ("/backends/monitor/tiled-non-main-origin-linear-config", - meta_test_monitor_tiled_non_main_origin_linear_config); - add_monitor_test ("/backends/monitor/hidpi-linear-config", - meta_test_monitor_hidpi_linear_config); - add_monitor_test ("/backends/monitor/suggested-config", - meta_test_monitor_suggested_config); - add_monitor_test ("/backends/monitor/limited-crtcs", - meta_test_monitor_limited_crtcs); - add_monitor_test ("/backends/monitor/lid-switch-config", - meta_test_monitor_lid_switch_config); - add_monitor_test ("/backends/monitor/lid-opened-config", - meta_test_monitor_lid_opened_config); - add_monitor_test ("/backends/monitor/lid-closed-no-external", - meta_test_monitor_lid_closed_no_external); - add_monitor_test ("/backends/monitor/lid-closed-with-hotplugged-external", - meta_test_monitor_lid_closed_with_hotplugged_external); - add_monitor_test ("/backends/monitor/lid-scaled-closed-opened", - meta_test_monitor_lid_scaled_closed_opened); - add_monitor_test ("/backends/monitor/no-outputs", - meta_test_monitor_no_outputs); - add_monitor_test ("/backends/monitor/underscanning-config", - meta_test_monitor_underscanning_config); - add_monitor_test ("/backends/monitor/preferred-non-first-mode", - meta_test_monitor_preferred_non_first_mode); - add_monitor_test ("/backends/monitor/non-upright-panel", - meta_test_monitor_non_upright_panel); - add_monitor_test ("/backends/monitor/switch-external-without-external", - meta_test_monitor_switch_external_without_external); - - add_monitor_test ("/backends/monitor/custom/vertical-config", - meta_test_monitor_custom_vertical_config); - add_monitor_test ("/backends/monitor/custom/primary-config", - meta_test_monitor_custom_primary_config); - add_monitor_test ("/backends/monitor/custom/underscanning-config", - meta_test_monitor_custom_underscanning_config); - add_monitor_test ("/backends/monitor/custom/scale-config", - meta_test_monitor_custom_scale_config); - add_monitor_test ("/backends/monitor/custom/fractional-scale-config", - meta_test_monitor_custom_fractional_scale_config); - add_monitor_test ("/backends/monitor/custom/high-precision-fractional-scale-config", - meta_test_monitor_custom_high_precision_fractional_scale_config); - add_monitor_test ("/backends/monitor/custom/tiled-config", - meta_test_monitor_custom_tiled_config); - add_monitor_test ("/backends/monitor/custom/tiled-custom-resolution-config", - meta_test_monitor_custom_tiled_custom_resolution_config); - add_monitor_test ("/backends/monitor/custom/tiled-non-preferred-config", - meta_test_monitor_custom_tiled_non_preferred_config); - add_monitor_test ("/backends/monitor/custom/mirrored-config", - meta_test_monitor_custom_mirrored_config); - add_monitor_test ("/backends/monitor/custom/first-rotated-config", - meta_test_monitor_custom_first_rotated_config); - add_monitor_test ("/backends/monitor/custom/second-rotated-config", - meta_test_monitor_custom_second_rotated_config); - add_monitor_test ("/backends/monitor/custom/second-rotated-tiled-config", - meta_test_monitor_custom_second_rotated_tiled_config); - add_monitor_test ("/backends/monitor/custom/second-rotated-nonnative-tiled-config", - meta_test_monitor_custom_second_rotated_nonnative_tiled_config); - add_monitor_test ("/backends/monitor/custom/second-rotated-nonnative-config", - meta_test_monitor_custom_second_rotated_nonnative_config); - add_monitor_test ("/backends/monitor/custom/interlaced-config", - meta_test_monitor_custom_interlaced_config); - add_monitor_test ("/backends/monitor/custom/oneoff-config", - meta_test_monitor_custom_oneoff); - add_monitor_test ("/backends/monitor/custom/lid-switch-config", - meta_test_monitor_custom_lid_switch_config); - - add_monitor_test ("/backends/monitor/migrated/rotated", - meta_test_monitor_migrated_rotated); - add_monitor_test ("/backends/monitor/migrated/wiggle", - meta_test_monitor_migrated_wiggle); - add_monitor_test ("/backends/monitor/migrated/wiggle-discard", - meta_test_monitor_migrated_wiggle_discard); - - add_monitor_test ("/backends/monitor/wm/tiling", - meta_test_monitor_wm_tiling); -} - -void -pre_run_monitor_tests (MetaContext *context) -{ - create_monitor_test_clients (context); -} - -void -finish_monitor_tests (void) -{ - destroy_monitor_test_clients (); -} diff --git a/src/tests/monitor-unit-tests.h b/src/tests/monitor-unit-tests.h deleted file mode 100644 index bbf096b39..000000000 --- a/src/tests/monitor-unit-tests.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 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 . - */ - -#ifndef MONITOR_UNIT_TESTS_H -#define MONITOR_UNIT_TESTS_H - -#include "core/util-private.h" -#include "tests/monitor-test-utils.h" - -typedef struct _MonitorTestCase MonitorTestCase; - -void init_monitor_tests (void); - -void pre_run_monitor_tests (MetaContext *context); - -void finish_monitor_tests (void); - -MonitorTestCase * test_get_initial_monitor_test_case (void); - -#endif /* MONITOR_UNIT_TESTS_H */ diff --git a/src/tests/mutter-all.test.in b/src/tests/mutter-all.test.in deleted file mode 100644 index 6e103c51d..000000000 --- a/src/tests/mutter-all.test.in +++ /dev/null @@ -1,6 +0,0 @@ -[Test] -Description=All Mutter tests -TestEnvironment=GSETTINGS_BACKEND=memory; -Exec=sh -c 'env XDG_RUNTIME_DIR="$(mktemp -d -t mutter-@apiversion@-all-tests-XXXXXX)" dbus-run-session -- xvfb-run -a -s "+iglx -noreset" -- @libexecdir@/installed-tests/mutter-@apiversion@/mutter-test-runner --all' -Type=session -Output=TAP diff --git a/src/tests/native-headless.c b/src/tests/native-headless.c deleted file mode 100644 index 6680ba7b9..000000000 --- a/src/tests/native-headless.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2021 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "meta-test/meta-context-test.h" -#include "tests/native-screen-cast.h" -#include "tests/native-virtual-monitor.h" - -static void -init_tests (void) -{ - init_virtual_monitor_tests (); - init_screen_cast_tests (); -} - -int -main (int argc, - char **argv) -{ - g_autoptr (MetaContext) context = NULL; - - context = meta_create_test_context (META_CONTEXT_TEST_TYPE_HEADLESS, - META_CONTEXT_TEST_FLAG_NO_X11); - g_assert (meta_context_configure (context, &argc, &argv, NULL)); - - init_tests (); - - return meta_context_test_run_tests (META_CONTEXT_TEST (context)); -} diff --git a/src/tests/native-persistent-virtual-monitor.c b/src/tests/native-persistent-virtual-monitor.c deleted file mode 100644 index 19a16cc5e..000000000 --- a/src/tests/native-persistent-virtual-monitor.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2021 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "backends/meta-logical-monitor.h" -#include "backends/meta-monitor-manager-private.h" -#include "meta/meta-context.h" -#include "meta/meta-backend.h" -#include "tests/meta-test-utils.h" - -static gboolean -wait_for_paint (gpointer user_data) -{ - MetaContext *context = user_data; - MetaBackend *backend = meta_get_backend (); - ClutterActor *stage = meta_backend_get_stage (backend); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - GMainLoop *loop; - GList *monitors; - GList *logical_monitors; - MetaLogicalMonitor *logical_monitor; - MetaRectangle layout; - - loop = g_main_loop_new (NULL, FALSE); - g_signal_connect_swapped (stage, "presented", - G_CALLBACK (g_main_loop_quit), - loop); - clutter_actor_queue_redraw (stage); - - monitors = meta_monitor_manager_get_monitors (monitor_manager); - g_assert_cmpint (g_list_length (monitors), ==, 1); - - logical_monitors = - meta_monitor_manager_get_logical_monitors (monitor_manager); - g_assert_cmpint (g_list_length (logical_monitors), ==, 1); - - logical_monitor = logical_monitors->data; - g_assert (meta_logical_monitor_get_monitors (logical_monitor)->data == - monitors->data); - - layout = meta_logical_monitor_get_layout (logical_monitor); - g_assert_cmpint (layout.x, ==, 0); - g_assert_cmpint (layout.y, ==, 0); - g_assert_cmpint (layout.width, ==, 800); - g_assert_cmpint (layout.height, ==, 600); - - g_main_loop_run (loop); - - meta_context_terminate (context); - - return G_SOURCE_REMOVE; -} - -int -main (int argc, - char **argv) -{ - char *fake_args[] = { - argv[0], - (char *) "--wayland", - (char *) "--headless", - (char *) "--virtual-monitor", - (char *) "800x600", - }; - char **fake_argv = fake_args; - int fake_argc = G_N_ELEMENTS (fake_args); - g_autoptr (MetaContext) context = NULL; - g_autoptr (GError) error = NULL; - - context = meta_create_context ("Persistent virtual monitor test"); - g_assert (meta_context_configure (context, &fake_argc, &fake_argv, &error)); - meta_context_set_plugin_name (context, meta_test_get_plugin_name ()); - g_assert (meta_context_setup (context, &error)); - g_assert (meta_context_start (context, &error)); - - g_idle_add (wait_for_paint, context); - - g_assert (meta_context_run_main_loop (context, &error)); - - return EXIT_SUCCESS; -} diff --git a/src/tests/native-screen-cast.c b/src/tests/native-screen-cast.c deleted file mode 100644 index bcde15665..000000000 --- a/src/tests/native-screen-cast.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2021 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "tests/native-screen-cast.h" - -#include -#include -#include - -static void -test_client_exited (GObject *source_object, - GAsyncResult *result, - gpointer user_data) -{ - GError *error = NULL; - - if (!g_subprocess_wait_finish (G_SUBPROCESS (source_object), - result, - &error)) - g_error ("Screen cast test client exited with an error: %s", error->message); - - g_main_loop_quit (user_data); -} - -static void -meta_test_screen_cast_record_virtual (void) -{ - GSubprocessLauncher *launcher; - g_autofree char *test_client_path = NULL; - GError *error = NULL; - GSubprocess *subprocess; - GMainLoop *loop; - - launcher = g_subprocess_launcher_new ((G_SUBPROCESS_FLAGS_STDIN_PIPE | - G_SUBPROCESS_FLAGS_STDOUT_PIPE)); - - test_client_path = g_test_build_filename (G_TEST_BUILT, - "src", - "tests", - "mutter-screen-cast-client", - NULL); - g_subprocess_launcher_setenv (launcher, - "XDG_RUNTIME_DIR", getenv ("XDG_RUNTIME_DIR"), - TRUE); - subprocess = g_subprocess_launcher_spawn (launcher, - &error, - test_client_path, - NULL); - if (!subprocess) - g_error ("Failed to launch screen cast test client: %s", error->message); - - loop = g_main_loop_new (NULL, FALSE); - g_subprocess_wait_check_async (subprocess, - NULL, - test_client_exited, - loop); - g_main_loop_run (loop); - g_assert_true (g_subprocess_get_successful (subprocess)); - g_object_unref (subprocess); -} - -void -init_screen_cast_tests (void) -{ - g_test_add_func ("/backends/native/screen-cast/record-virtual", - meta_test_screen_cast_record_virtual); -} diff --git a/src/tests/native-screen-cast.h b/src/tests/native-screen-cast.h deleted file mode 100644 index 3c79676c7..000000000 --- a/src/tests/native-screen-cast.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2021 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef NATIVE_SCREEN_CAST_H -#define NATIVE_SCREEN_CAST_H - -void init_screen_cast_tests (void); - -#endif /* NATIVE_SCREEN_CAST_H */ diff --git a/src/tests/native-virtual-monitor.c b/src/tests/native-virtual-monitor.c deleted file mode 100644 index 15fc78f88..000000000 --- a/src/tests/native-virtual-monitor.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2021 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "tests/native-virtual-monitor.h" - -#include "backends/meta-backend-private.h" -#include "backends/meta-logical-monitor.h" -#include "backends/meta-monitor-config-manager.h" -#include "backends/meta-virtual-monitor.h" -#include "backends/native/meta-renderer-native.h" -#include "tests/meta-ref-test.h" - -static void -meta_test_virtual_monitor_create (void) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = meta_backend_get_monitor_manager (backend); - MetaMonitorConfigManager *config_manager = - meta_monitor_manager_get_config_manager (monitor_manager); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - MetaVirtualMonitor *virtual_monitor; - g_autoptr (MetaVirtualMonitorInfo) monitor_info = NULL; - GError *error = NULL; - GList *monitors; - MetaMonitor *monitor; - MetaMonitorsConfig *monitors_config; - GList *logical_monitors; - GList *logical_monitor_monitors; - GList *views; - int i; - ClutterActor *actor; - - g_assert_null (meta_monitor_config_manager_get_current (config_manager)); - g_assert_null (meta_monitor_manager_get_logical_monitors (monitor_manager)); - g_assert_null (meta_monitor_manager_get_monitors (monitor_manager)); - g_assert_null (meta_renderer_get_views (renderer)); - - monitor_info = meta_virtual_monitor_info_new (80, 60, 60.0, - "MetaTestVendor", - "MetaVirtualMonitor", - "0x1234"); - virtual_monitor = meta_monitor_manager_create_virtual_monitor (monitor_manager, - monitor_info, - &error); - if (!virtual_monitor) - g_error ("Failed to create virtual monitor: %s", error->message); - - meta_monitor_manager_reload (monitor_manager); - - monitors = meta_monitor_manager_get_monitors (monitor_manager); - g_assert_cmpint (g_list_length (monitors), ==, 1); - monitor = META_MONITOR (monitors->data); - g_assert_cmpstr (meta_monitor_get_vendor (monitor), ==, "MetaTestVendor"); - g_assert_cmpstr (meta_monitor_get_product (monitor), ==, "MetaVirtualMonitor"); - g_assert_cmpstr (meta_monitor_get_serial (monitor), ==, "0x1234"); - g_assert (meta_monitor_get_main_output (monitor) == - meta_virtual_monitor_get_output (virtual_monitor)); - - monitors_config = meta_monitor_manager_ensure_configured (monitor_manager); - g_assert_nonnull (monitors_config); - g_assert_cmpint (g_list_length (monitors_config->logical_monitor_configs), - ==, - 1); - - g_assert_cmpint (g_list_length (monitors_config->disabled_monitor_specs), - ==, - 0); - - logical_monitors = - meta_monitor_manager_get_logical_monitors (monitor_manager); - g_assert_cmpint (g_list_length (logical_monitors), ==, 1); - logical_monitor_monitors = - meta_logical_monitor_get_monitors (logical_monitors->data); - g_assert_cmpint (g_list_length (logical_monitor_monitors), ==, 1); - g_assert (logical_monitor_monitors->data == monitor); - - views = meta_renderer_get_views (renderer); - g_assert_cmpint (g_list_length (views), ==, 1); - - for (i = 0; i < 5; i++) - { - meta_ref_test_verify_view (CLUTTER_STAGE_VIEW (views->data), - g_test_get_path (), 0, - meta_ref_test_determine_ref_test_flag ()); - } - - actor = clutter_actor_new (); - clutter_actor_set_position (actor, 10, 10); - clutter_actor_set_size (actor, 40, 40); - clutter_actor_set_background_color (actor, CLUTTER_COLOR_LightSkyBlue); - clutter_actor_add_child (meta_backend_get_stage (backend), actor); - - for (i = 0; i < 5; i++) - { - meta_ref_test_verify_view (CLUTTER_STAGE_VIEW (views->data), - g_test_get_path (), 1, - meta_ref_test_determine_ref_test_flag ()); - } - - g_object_unref (virtual_monitor); - meta_monitor_manager_reload (monitor_manager); - - g_assert_null (meta_monitor_manager_ensure_configured (monitor_manager)); - g_assert_null (meta_monitor_manager_get_logical_monitors (monitor_manager)); - g_assert_null (meta_monitor_manager_get_monitors (monitor_manager)); - g_assert_null (meta_renderer_get_views (renderer)); - - clutter_actor_destroy (actor); -} - -void -init_virtual_monitor_tests (void) -{ - g_test_add_func ("/backends/native/virtual-monitor/create", - meta_test_virtual_monitor_create); -} diff --git a/src/tests/native-virtual-monitor.h b/src/tests/native-virtual-monitor.h deleted file mode 100644 index 0c4c34f02..000000000 --- a/src/tests/native-virtual-monitor.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2021 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef NATIVE_VIRTUAL_MONITOR_H -#define NATIVE_VIRTUAL_MONITOR_H - -void init_virtual_monitor_tests (void); - -#endif /* NATIVE_VIRTUAL_MONITOR_H */ diff --git a/src/tests/ref-test-sanity.c b/src/tests/ref-test-sanity.c deleted file mode 100644 index 0a9472b13..000000000 --- a/src/tests/ref-test-sanity.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2021 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 . - * - */ - -#include "config.h" - -#include "backends/meta-virtual-monitor.h" -#include "backends/native/meta-renderer-native.h" -#include "meta-test/meta-context-test.h" -#include "tests/meta-ref-test.h" - -static MetaVirtualMonitor *virtual_monitor; - -static void -setup_test_environment (void) -{ - MetaBackend *backend = meta_get_backend (); - MetaSettings *settings = meta_backend_get_settings (backend); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - g_autoptr (MetaVirtualMonitorInfo) monitor_info = NULL; - GError *error = NULL; - GList *views; - - meta_settings_override_experimental_features (settings); - meta_settings_enable_experimental_feature ( - settings, - META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER); - - monitor_info = meta_virtual_monitor_info_new (100, 100, 60.0, - "MetaTestVendor", - "MetaVirtualMonitor", - "0x1234"); - virtual_monitor = meta_monitor_manager_create_virtual_monitor (monitor_manager, - monitor_info, - &error); - if (!virtual_monitor) - g_error ("Failed to create virtual monitor: %s", error->message); - - meta_monitor_manager_reload (monitor_manager); - - views = meta_renderer_get_views (renderer); - g_assert_cmpint (g_list_length (views), ==, 1); -} - -static void -tear_down_test_environment (void) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - - g_object_unref (virtual_monitor); - meta_monitor_manager_reload (monitor_manager); -} - -static ClutterStageView * -get_view (void) -{ - MetaBackend *backend = meta_get_backend (); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - - return CLUTTER_STAGE_VIEW (meta_renderer_get_views (renderer)->data); -} - -static void -meta_test_ref_test_sanity (void) -{ - MetaBackend *backend = meta_get_backend (); - ClutterActor *stage = meta_backend_get_stage (backend); - ClutterActor *actor1; - ClutterActor *actor2; - - meta_ref_test_verify_view (get_view (), - g_test_get_path (), 0, - meta_ref_test_determine_ref_test_flag ()); - - actor1 = clutter_actor_new (); - clutter_actor_set_position (actor1, 10, 10); - clutter_actor_set_size (actor1, 50, 50); - clutter_actor_set_background_color (actor1, CLUTTER_COLOR_Orange); - clutter_actor_add_child (stage, actor1); - - meta_ref_test_verify_view (get_view (), - g_test_get_path (), 1, - meta_ref_test_determine_ref_test_flag ()); - - actor2 = clutter_actor_new (); - clutter_actor_set_position (actor2, 20, 20); - clutter_actor_set_size (actor2, 50, 50); - clutter_actor_set_background_color (actor2, CLUTTER_COLOR_SkyBlue); - clutter_actor_add_child (stage, actor2); - - g_test_expect_message (G_LOG_DOMAIN, - G_LOG_LEVEL_CRITICAL, - "Pixel difference exceeds limits*"); - - meta_ref_test_verify_view (get_view (), - g_test_get_path (), 1, - meta_ref_test_determine_ref_test_flag ()); - - g_test_assert_expected_messages (); - - clutter_actor_destroy (actor2); - clutter_actor_destroy (actor1); -} - -static void -init_ref_test_sanity_tests (void) -{ - g_test_add_func ("/tests/ref-test/sanity", - meta_test_ref_test_sanity); -} - -int -main (int argc, - char **argv) -{ - g_autoptr (MetaContext) context = NULL; - - context = meta_create_test_context (META_CONTEXT_TEST_TYPE_HEADLESS, - META_CONTEXT_TEST_FLAG_NO_X11); - g_assert (meta_context_configure (context, &argc, &argv, NULL)); - - init_ref_test_sanity_tests (); - - g_signal_connect (context, "before-tests", - G_CALLBACK (setup_test_environment), NULL); - g_signal_connect (context, "after-tests", - G_CALLBACK (tear_down_test_environment), NULL); - - return meta_context_test_run_tests (META_CONTEXT_TEST (context)); -} diff --git a/src/tests/ref-tests/backends_native_virtual-monitor_create_0.ref.png b/src/tests/ref-tests/backends_native_virtual-monitor_create_0.ref.png deleted file mode 100644 index 55ed4d9e0..000000000 Binary files a/src/tests/ref-tests/backends_native_virtual-monitor_create_0.ref.png and /dev/null differ diff --git a/src/tests/ref-tests/backends_native_virtual-monitor_create_1.ref.png b/src/tests/ref-tests/backends_native_virtual-monitor_create_1.ref.png deleted file mode 100644 index c75a6e161..000000000 Binary files a/src/tests/ref-tests/backends_native_virtual-monitor_create_1.ref.png and /dev/null differ diff --git a/src/tests/ref-tests/tests_ref-test_sanity_0.ref.png b/src/tests/ref-tests/tests_ref-test_sanity_0.ref.png deleted file mode 100644 index f434827f8..000000000 Binary files a/src/tests/ref-tests/tests_ref-test_sanity_0.ref.png and /dev/null differ diff --git a/src/tests/ref-tests/tests_ref-test_sanity_1.ref.png b/src/tests/ref-tests/tests_ref-test_sanity_1.ref.png deleted file mode 100644 index 29567348e..000000000 Binary files a/src/tests/ref-tests/tests_ref-test_sanity_1.ref.png and /dev/null differ diff --git a/src/tests/screen-cast-client.c b/src/tests/screen-cast-client.c deleted file mode 100644 index cc118f7ae..000000000 --- a/src/tests/screen-cast-client.c +++ /dev/null @@ -1,572 +0,0 @@ -/* - * Copyright (C) 2021 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "meta-dbus-screen-cast.h" - -typedef struct _Stream -{ - MetaDBusScreenCastStream *proxy; - uint32_t pipewire_node_id; - struct spa_video_info_raw spa_format; - struct pw_stream *pipewire_stream; - struct spa_hook pipewire_stream_listener; - enum pw_stream_state state; - int buffer_count; -} Stream; - -typedef struct _Session -{ - MetaDBusScreenCastSession *proxy; -} Session; - -typedef struct _ScreenCast -{ - MetaDBusScreenCast *proxy; -} ScreenCast; - -typedef struct _PipeWireSource -{ - GSource base; - - struct pw_loop *pipewire_loop; -} PipeWireSource; - -static PipeWireSource *_pipewire_source; -static struct pw_context *_pipewire_context; -static struct pw_core *_pipewire_core; -static struct spa_hook _pipewire_core_listener; - -static gboolean -pipewire_loop_source_prepare (GSource *base, - int *timeout) -{ - *timeout = -1; - return FALSE; -} - -static gboolean -pipewire_loop_source_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data) -{ - PipeWireSource *pipewire_source = (PipeWireSource *) source; - int result; - - result = pw_loop_iterate (pipewire_source->pipewire_loop, 0); - if (result < 0) - g_error ("pipewire_loop_iterate failed: %s", spa_strerror (result)); - - return TRUE; -} - -static void -pipewire_loop_source_finalize (GSource *source) -{ - PipeWireSource *pipewire_source = (PipeWireSource *) source; - - pw_loop_leave (pipewire_source->pipewire_loop); - pw_loop_destroy (pipewire_source->pipewire_loop); -} - -static GSourceFuncs pipewire_source_funcs = -{ - pipewire_loop_source_prepare, - NULL, - pipewire_loop_source_dispatch, - pipewire_loop_source_finalize -}; - -static PipeWireSource * -create_pipewire_source (void) -{ - PipeWireSource *pipewire_source; - - pipewire_source = - (PipeWireSource *) g_source_new (&pipewire_source_funcs, - sizeof (PipeWireSource)); - pipewire_source->pipewire_loop = pw_loop_new (NULL); - g_assert_nonnull (pipewire_source->pipewire_loop); - g_source_add_unix_fd (&pipewire_source->base, - pw_loop_get_fd (pipewire_source->pipewire_loop), - G_IO_IN | G_IO_ERR); - - pw_loop_enter (pipewire_source->pipewire_loop); - g_source_attach (&pipewire_source->base, NULL); - - return pipewire_source; -} - -static void -on_core_error (void *user_data, - uint32_t id, - int seq, - int res, - const char *message) -{ - g_error ("PipeWire core error: id:%u %s", id, message); -} - -static const struct pw_core_events core_events = { - PW_VERSION_CORE_EVENTS, - .error = on_core_error, -}; - -static void -init_pipewire (void) -{ - pw_init (NULL, NULL); - _pipewire_source = create_pipewire_source (); - _pipewire_context = pw_context_new (_pipewire_source->pipewire_loop, - NULL, 0); - g_assert_nonnull (_pipewire_context); - _pipewire_core = pw_context_connect (_pipewire_context, NULL, 0); - g_assert_nonnull (_pipewire_core); - - pw_core_add_listener (_pipewire_core, - &_pipewire_core_listener, - &core_events, - NULL); -} - -static void -release_pipewire (void) -{ - g_clear_pointer (&_pipewire_core, pw_core_disconnect); - g_clear_pointer (&_pipewire_context, pw_context_destroy); - if (_pipewire_source) - { - g_source_destroy ((GSource *) _pipewire_source); - g_source_unref ((GSource *) _pipewire_source); - _pipewire_source = NULL; - } -} - -static void -on_stream_state_changed (void *user_data, - enum pw_stream_state old, - enum pw_stream_state state, - const char *error) -{ - Stream *stream = user_data; - - switch (state) - { - case PW_STREAM_STATE_ERROR: - g_warning ("PipeWire stream error: %s", error); - break; - case PW_STREAM_STATE_PAUSED: - case PW_STREAM_STATE_STREAMING: - case PW_STREAM_STATE_UNCONNECTED: - case PW_STREAM_STATE_CONNECTING: - break; - } - - stream->state = state; -} - -static void -on_stream_param_changed (void *user_data, - uint32_t id, - const struct spa_pod *format) -{ - Stream *stream = user_data; - uint8_t params_buffer[1024]; - struct spa_pod_builder pod_builder; - const struct spa_pod *params[2]; - - if (!format || id != SPA_PARAM_Format) - return; - - spa_format_video_raw_parse (format, &stream->spa_format); - - pod_builder = SPA_POD_BUILDER_INIT (params_buffer, sizeof (params_buffer)); - - params[0] = spa_pod_builder_add_object ( - &pod_builder, - SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers, - SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int (8, 1, 8), - SPA_PARAM_BUFFERS_dataType, SPA_POD_Int ((1 << SPA_DATA_MemPtr) | - (1 << SPA_DATA_MemFd)), - 0); - - params[1] = spa_pod_builder_add_object ( - &pod_builder, - SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, - SPA_PARAM_META_type, SPA_POD_Id (SPA_META_Header), - SPA_PARAM_META_size, SPA_POD_Int (sizeof (struct spa_meta_header)), - 0); - - pw_stream_update_params (stream->pipewire_stream, - params, G_N_ELEMENTS (params)); -} - -static void -sanity_check_memfd (struct spa_buffer *buffer) -{ - size_t size; - uint8_t *map; - - size = buffer->datas[0].maxsize + buffer->datas[0].mapoffset; - g_assert_cmpint (size, >, 0); - map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, buffer->datas[0].fd, 0); - g_assert (map != MAP_FAILED); - munmap (map, size); -} - -static void -sanity_check_memptr (struct spa_buffer *buffer) -{ - size_t size; - - size = buffer->datas[0].maxsize + buffer->datas[0].mapoffset; - g_assert_cmpint (size, >, 0); - - g_assert_nonnull (buffer->datas[0].data); -} - -static void -process_buffer (Stream *stream, - struct spa_buffer *buffer) -{ - if (buffer->datas[0].chunk->size == 0) - g_assert_not_reached (); - else if (buffer->datas[0].type == SPA_DATA_MemFd) - sanity_check_memfd (buffer); - else if (buffer->datas[0].type == SPA_DATA_DmaBuf) - g_assert_not_reached (); - else if (buffer->datas[0].type == SPA_DATA_MemPtr) - sanity_check_memptr (buffer); - else - g_assert_not_reached (); -} - -static void -on_stream_process (void *user_data) -{ - Stream *stream = user_data; - struct pw_buffer *next_buffer; - struct pw_buffer *buffer = NULL; - - next_buffer = pw_stream_dequeue_buffer (stream->pipewire_stream); - while (next_buffer) - { - buffer = next_buffer; - next_buffer = pw_stream_dequeue_buffer (stream->pipewire_stream); - - if (next_buffer) - pw_stream_queue_buffer (stream->pipewire_stream, buffer); - } - if (!buffer) - return; - - process_buffer (stream, buffer->buffer); - pw_stream_queue_buffer (stream->pipewire_stream, buffer); - - stream->buffer_count++; -} - -static const struct pw_stream_events stream_events = { - PW_VERSION_STREAM_EVENTS, - .state_changed = on_stream_state_changed, - .param_changed = on_stream_param_changed, - .process = on_stream_process, -}; - -static void -stream_connect (Stream *stream) -{ - struct pw_stream *pipewire_stream; - uint8_t params_buffer[1024]; - struct spa_pod_builder pod_builder; - struct spa_rectangle min_rect; - struct spa_rectangle max_rect; - struct spa_fraction min_framerate; - struct spa_fraction max_framerate; - const struct spa_pod *params[2]; - int ret; - - pipewire_stream = pw_stream_new (_pipewire_core, - "mutter-test-pipewire-stream", - NULL); - - min_rect = SPA_RECTANGLE (1, 1); - max_rect = SPA_RECTANGLE (50 , 50); - min_framerate = SPA_FRACTION (1, 1); - max_framerate = SPA_FRACTION (30, 1); - - pod_builder = SPA_POD_BUILDER_INIT (params_buffer, sizeof (params_buffer)); - params[0] = spa_pod_builder_add_object ( - &pod_builder, - SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, - SPA_FORMAT_mediaType, SPA_POD_Id (SPA_MEDIA_TYPE_video), - SPA_FORMAT_mediaSubtype, SPA_POD_Id (SPA_MEDIA_SUBTYPE_raw), - SPA_FORMAT_VIDEO_format, SPA_POD_Id (SPA_VIDEO_FORMAT_BGRx), - SPA_FORMAT_VIDEO_size, SPA_POD_CHOICE_RANGE_Rectangle (&min_rect, - &min_rect, - &max_rect), - SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction (&SPA_FRACTION(0, 1)), - SPA_FORMAT_VIDEO_maxFramerate, SPA_POD_CHOICE_RANGE_Fraction (&min_framerate, - &min_framerate, - &max_framerate), - 0); - - stream->pipewire_stream = pipewire_stream; - - pw_stream_add_listener (pipewire_stream, - &stream->pipewire_stream_listener, - &stream_events, - stream); - - ret = pw_stream_connect (stream->pipewire_stream, - PW_DIRECTION_INPUT, - stream->pipewire_node_id, - PW_STREAM_FLAG_AUTOCONNECT, - params, 1); - if (ret < 0) - g_error ("Failed to connect PipeWire stream: %s", g_strerror (-ret)); -} - -static void -stream_wait_for_node (Stream *stream) -{ - while (!stream->pipewire_node_id) - g_main_context_iteration (NULL, TRUE); -} - -static G_GNUC_UNUSED void -stream_wait_for_streaming (Stream *stream) -{ - while (stream->state != PW_STREAM_STATE_STREAMING) - g_main_context_iteration (NULL, TRUE); -} - -static G_GNUC_UNUSED void -stream_wait_for_render (Stream *stream) -{ - while (stream->buffer_count == 0) - g_main_context_iteration (NULL, TRUE); -} - -static void -on_pipewire_stream_added (MetaDBusScreenCastStream *proxy, - unsigned int node_id, - Stream *stream) -{ - stream->pipewire_node_id = (uint32_t) node_id; - stream_connect (stream); -} - -static Stream * -stream_new (const char *path) -{ - Stream *stream; - GError *error = NULL; - - stream = g_new0 (Stream, 1); - stream->proxy = meta_dbus_screen_cast_stream_proxy_new_for_bus_sync ( - G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, - "org.gnome.Mutter.ScreenCast", - path, - NULL, - &error); - if (!stream->proxy) - g_error ("Failed to acquire proxy: %s", error->message); - - g_signal_connect (stream->proxy, "pipewire-stream-added", - G_CALLBACK (on_pipewire_stream_added), - stream); - - return stream; -} - -static void -stream_free (Stream *stream) -{ - g_clear_pointer (&stream->pipewire_stream, pw_stream_destroy); - g_clear_object (&stream->proxy); - g_free (stream); -} - -static void -session_start (Session *session) -{ - GError *error = NULL; - - if (!meta_dbus_screen_cast_session_call_start_sync (session->proxy, - NULL, - &error)) - g_error ("Failed to start session: %s", error->message); -} - -static void -session_stop (Session *session) -{ - GError *error = NULL; - - if (!meta_dbus_screen_cast_session_call_stop_sync (session->proxy, - NULL, - &error)) - g_error ("Failed to stop session: %s", error->message); -} - -static Stream * -session_record_virtual (Session *session) -{ - GVariantBuilder properties_builder; - GVariant *properties_variant; - GError *error = NULL; - g_autofree char *stream_path = NULL; - Stream *stream; - - g_variant_builder_init (&properties_builder, G_VARIANT_TYPE ("a{sv}")); - properties_variant = g_variant_builder_end (&properties_builder); - - if (!meta_dbus_screen_cast_session_call_record_virtual_sync ( - session->proxy, - properties_variant, - &stream_path, - NULL, - &error)) - g_error ("Failed to create session: %s", error->message); - - stream = stream_new (stream_path); - g_assert_nonnull (stream); - return stream; -} - -static Session * -session_new (const char *path) -{ - Session *session; - GError *error = NULL; - - session = g_new0 (Session, 1); - session->proxy = meta_dbus_screen_cast_session_proxy_new_for_bus_sync ( - G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, - "org.gnome.Mutter.ScreenCast", - path, - NULL, - &error); - if (!session->proxy) - g_error ("Failed to acquire proxy: %s", error->message); - - return session; -} - -static void -session_free (Session *session) -{ - g_clear_object (&session->proxy); - g_free (session); -} - -static Session * -screen_cast_create_session (ScreenCast *screen_cast) -{ - GVariantBuilder properties_builder; - GVariant *properties_variant; - GError *error = NULL; - g_autofree char *session_path = NULL; - Session *session; - - g_variant_builder_init (&properties_builder, G_VARIANT_TYPE ("a{sv}")); - properties_variant = g_variant_builder_end (&properties_builder); - - if (!meta_dbus_screen_cast_call_create_session_sync (screen_cast->proxy, - properties_variant, - &session_path, - NULL, - &error)) - g_error ("Failed to create session: %s", error->message); - - session = session_new (session_path); - g_assert_nonnull (session); - return session; -} - -static ScreenCast * -screen_cast_new (void) -{ - ScreenCast *screen_cast; - GError *error = NULL; - - screen_cast = g_new0 (ScreenCast, 1); - screen_cast->proxy = meta_dbus_screen_cast_proxy_new_for_bus_sync ( - G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, - "org.gnome.Mutter.ScreenCast", - "/org/gnome/Mutter/ScreenCast", - NULL, - &error); - if (!screen_cast->proxy) - g_error ("Failed to acquire proxy: %s", error->message); - - return screen_cast; -} - -static void -screen_cast_free (ScreenCast *screen_cast) -{ - g_clear_object (&screen_cast->proxy); - g_free (screen_cast); -} - -int -main (int argc, - char **argv) -{ - ScreenCast *screen_cast; - Session *session; - Stream *stream; - - init_pipewire (); - - screen_cast = screen_cast_new (); - session = screen_cast_create_session (screen_cast); - stream = session_record_virtual (session); - - session_start (session); - - stream_wait_for_node (stream); - stream_wait_for_streaming (stream); - stream_wait_for_render (stream); - - session_stop (session); - - stream_free (stream); - session_free (session); - screen_cast_free (screen_cast); - - release_pipewire (); - - return EXIT_SUCCESS; -} diff --git a/src/tests/stacking/basic-wayland.metatest b/src/tests/stacking/basic-wayland.metatest deleted file mode 100644 index 63ce6082b..000000000 --- a/src/tests/stacking/basic-wayland.metatest +++ /dev/null @@ -1,22 +0,0 @@ -new_client 1 wayland -create 1/1 -show 1/1 -create 1/2 -show 1/2 -wait -assert_stacking 1/1 1/2 - -# Currently Wayland clients have no wait to bring themselves to the user's -# attention; gtk_window_present() is a no-op with the X11 backend of GTK+ - -# activate 1/1 -# wait -# assert_stacking 1/2 1/1 -# activate 1/2 -# wait -# assert_stacking 1/1 1/2 - -local_activate 1/1 -assert_stacking 1/2 1/1 -local_activate 1/2 -assert_stacking 1/1 1/2 diff --git a/src/tests/stacking/basic-x11.metatest b/src/tests/stacking/basic-x11.metatest deleted file mode 100644 index ee261ece0..000000000 --- a/src/tests/stacking/basic-x11.metatest +++ /dev/null @@ -1,19 +0,0 @@ -new_client 1 x11 -create 1/1 -show 1/1 -create 1/2 -show 1/2 -wait -assert_stacking 1/1 1/2 - -activate 1/1 -wait -assert_stacking 1/2 1/1 -activate 1/2 -wait -assert_stacking 1/1 1/2 - -local_activate 1/1 -assert_stacking 1/2 1/1 -local_activate 1/2 -assert_stacking 1/1 1/2 diff --git a/src/tests/stacking/client-side-decorated.metatest b/src/tests/stacking/client-side-decorated.metatest deleted file mode 100644 index 1d5dfc646..000000000 --- a/src/tests/stacking/client-side-decorated.metatest +++ /dev/null @@ -1,22 +0,0 @@ -new_client 1 x11 -create 1/1 -show 1/1 -create 1/2 csd -show 1/2 -wait -assert_stacking 1/1 1/2 - -destroy 1/2 -wait -assert_stacking 1/1 - -create 1/2 csd -show 1/2 -create 1/3 csd -show 1/3 -wait -assert_stacking 1/1 1/2 1/3 - -destroy 1/2 -wait -assert_stacking 1/1 1/3 diff --git a/src/tests/stacking/closed-transient-no-default-focus.metatest b/src/tests/stacking/closed-transient-no-default-focus.metatest deleted file mode 100644 index a2db12d5b..000000000 --- a/src/tests/stacking/closed-transient-no-default-focus.metatest +++ /dev/null @@ -1,29 +0,0 @@ -new_client 1 x11 -create 1/1 -accept_focus 1/1 false -show 1/1 - -create 1/2 csd -set_parent 1/2 1 -accept_focus 1/2 false -show 1/2 - -create 1/3 csd -set_parent 1/3 2 -show 1/3 - -wait -assert_focused 1/3 -assert_stacking 1/1 1/2 1/3 - -destroy 1/3 -wait - -assert_focused none -assert_stacking 1/1 1/2 - -sleep 150 -wait - -assert_focused none -assert_stacking 1/1 1/2 diff --git a/src/tests/stacking/closed-transient-no-input-no-take-focus-parent.metatest b/src/tests/stacking/closed-transient-no-input-no-take-focus-parent.metatest deleted file mode 100644 index 0c0649c07..000000000 --- a/src/tests/stacking/closed-transient-no-input-no-take-focus-parent.metatest +++ /dev/null @@ -1,23 +0,0 @@ -new_client 1 x11 -create 1/1 -show 1/1 - -create 1/2 csd -set_parent 1/2 1 -can_take_focus 1/2 false -accept_focus 1/2 false -show 1/2 - -create 1/3 csd -set_parent 1/3 2 -show 1/3 - -wait -assert_focused 1/3 -assert_stacking 1/1 1/2 1/3 - -destroy 1/3 - -wait -assert_focused 1/1 -assert_stacking 1/1 1/2 diff --git a/src/tests/stacking/closed-transient-no-input-no-take-focus-parents.metatest b/src/tests/stacking/closed-transient-no-input-no-take-focus-parents.metatest deleted file mode 100644 index 6556803e1..000000000 --- a/src/tests/stacking/closed-transient-no-input-no-take-focus-parents.metatest +++ /dev/null @@ -1,30 +0,0 @@ -new_client 2 x11 -create 2/1 -show 2/1 -wait - -new_client 1 x11 -create 1/1 -accept_focus 1/1 false -can_take_focus 1/1 false -show 1/1 - -create 1/2 csd -set_parent 1/2 1 -can_take_focus 1/2 false -accept_focus 1/2 false -show 1/2 - -create 1/3 csd -set_parent 1/3 2 -show 1/3 - -wait -assert_focused 1/3 -assert_stacking 2/1 1/1 1/2 1/3 - -destroy 1/3 - -wait -assert_stacking 1/1 1/2 2/1 -assert_focused 2/1 diff --git a/src/tests/stacking/closed-transient-no-input-parent-delayed-focus-default-cancelled.metatest b/src/tests/stacking/closed-transient-no-input-parent-delayed-focus-default-cancelled.metatest deleted file mode 100644 index 90a65e659..000000000 --- a/src/tests/stacking/closed-transient-no-input-parent-delayed-focus-default-cancelled.metatest +++ /dev/null @@ -1,37 +0,0 @@ -new_client 2 x11 -create 2/1 -show 2/1 - -new_client 1 x11 -create 1/1 -show 1/1 - -create 1/2 csd -set_parent 1/2 1 -accept_focus 1/2 false -show 1/2 - -create 1/3 csd -set_parent 1/3 2 -show 1/3 - -wait -assert_focused 1/3 -assert_stacking 2/1 1/1 1/2 1/3 - -destroy 1/3 -wait - -assert_stacking 2/1 1/1 1/2 - -activate 2/1 -wait - -assert_focused 2/1 -assert_stacking 1/1 1/2 2/1 - -sleep 250 -wait - -assert_focused 2/1 -assert_stacking 1/1 1/2 2/1 diff --git a/src/tests/stacking/closed-transient-no-input-parent.metatest b/src/tests/stacking/closed-transient-no-input-parent.metatest deleted file mode 100644 index 5c2be11fb..000000000 --- a/src/tests/stacking/closed-transient-no-input-parent.metatest +++ /dev/null @@ -1,31 +0,0 @@ -new_client 2 x11 -create 2/1 -show 2/1 - -new_client 1 x11 -create 1/1 -show 1/1 - -create 1/2 csd -set_parent 1/2 1 -accept_focus 1/2 false -show 1/2 - -create 1/3 csd -set_parent 1/3 2 -show 1/3 - -wait -assert_focused 1/3 -assert_stacking 2/1 1/1 1/2 1/3 - -destroy 1/3 -wait - -assert_stacking 2/1 1/1 1/2 - -sleep 150 -wait - -assert_focused 1/1 -assert_stacking 2/1 1/1 1/2 diff --git a/src/tests/stacking/closed-transient-no-input-parents-queued-default-focus-destroyed.metatest b/src/tests/stacking/closed-transient-no-input-parents-queued-default-focus-destroyed.metatest deleted file mode 100644 index e361fbdf6..000000000 --- a/src/tests/stacking/closed-transient-no-input-parents-queued-default-focus-destroyed.metatest +++ /dev/null @@ -1,44 +0,0 @@ -new_client 0 x11 -create 0/1 -show 0/1 - -new_client 1 x11 -create 1/1 -show 1/1 - -create 1/2 csd -set_parent 1/2 1 -accept_focus 1/2 false -show 1/2 - -create 1/3 csd -set_parent 1/3 2 -accept_focus 1/3 false -show 1/3 - -create 1/4 csd -set_parent 1/4 3 -accept_focus 1/4 false -show 1/4 - -create 1/5 csd -set_parent 1/5 3 -show 1/5 - -wait -assert_focused 1/5 -assert_stacking 0/1 1/1 1/2 1/3 1/4 1/5 - -destroy 1/5 -wait - -assert_stacking 0/1 1/1 1/2 1/3 1/4 - -destroy 1/2 -wait - -sleep 450 -wait - -assert_focused 1/1 -assert_stacking 0/1 1/1 1/3 1/4 diff --git a/src/tests/stacking/closed-transient-no-input-parents.metatest b/src/tests/stacking/closed-transient-no-input-parents.metatest deleted file mode 100644 index 365f6f444..000000000 --- a/src/tests/stacking/closed-transient-no-input-parents.metatest +++ /dev/null @@ -1,47 +0,0 @@ -new_client 0 x11 -create 0/1 -show 0/1 - -new_client 1 x11 -create 1/1 -show 1/1 - -create 1/2 csd -set_parent 1/2 1 -accept_focus 1/2 false -show 1/2 - -create 1/3 csd -set_parent 1/3 2 -accept_focus 1/3 false -show 1/3 - -create 1/4 csd -set_parent 1/4 3 -accept_focus 1/4 false -show 1/4 - -create 1/5 csd -set_parent 1/5 3 -show 1/5 - -wait -assert_focused 1/5 -assert_stacking 0/1 1/1 1/2 1/3 1/4 1/5 - -destroy 1/5 -wait - -assert_stacking 0/1 1/1 1/2 1/3 1/4 - -sleep 600 -wait - -assert_focused 1/1 -assert_stacking 0/1 1/1 1/2 1/3 1/4 - -destroy 1/3 -wait - -assert_focused 1/1 -assert_stacking 0/1 1/1 1/2 1/4 diff --git a/src/tests/stacking/closed-transient-only-take-focus-parents.metatest b/src/tests/stacking/closed-transient-only-take-focus-parents.metatest deleted file mode 100644 index 88bf7865c..000000000 --- a/src/tests/stacking/closed-transient-only-take-focus-parents.metatest +++ /dev/null @@ -1,36 +0,0 @@ -new_client 0 x11 -create 0/1 -show 0/1 - -new_client 1 x11 -create 1/1 -accept_focus 1/1 false -can_take_focus 1/1 true -accept_take_focus 1/1 true -show 1/1 - -create 1/2 csd -set_parent 1/2 1 -accept_focus 1/2 false -can_take_focus 1/2 true -accept_take_focus 1/2 true -show 1/2 - -create 1/3 -set_parent 1/3 2 -show 1/3 - -assert_focused 1/3 -assert_stacking 0/1 1/1 1/2 1/3 - -destroy 1/3 -wait - -assert_focused 1/2 -assert_stacking 0/1 1/1 1/2 - -sleep 150 -wait - -assert_focused 1/2 -assert_stacking 0/1 1/1 1/2 diff --git a/src/tests/stacking/closed-transient.metatest b/src/tests/stacking/closed-transient.metatest deleted file mode 100644 index 5ca95ba0f..000000000 --- a/src/tests/stacking/closed-transient.metatest +++ /dev/null @@ -1,19 +0,0 @@ -new_client 1 wayland -create 1/1 -show 1/1 - -new_client 2 wayland -create 2/1 -show 2/1 - -create 1/2 -show 1/2 -set_parent 1/2 1 - -wait -assert_stacking 1/1 2/1 1/2 - -destroy 1/2 - -wait -assert_stacking 2/1 1/1 diff --git a/src/tests/stacking/default-size.metatest b/src/tests/stacking/default-size.metatest deleted file mode 100644 index d1c692959..000000000 --- a/src/tests/stacking/default-size.metatest +++ /dev/null @@ -1,36 +0,0 @@ -new_client x x11 -create x/1 csd - -resize x/1 300 400 -show x/1 -wait - -assert_size x/1 300 400 - -resize x/1 200 300 -wait_reconfigure -assert_size x/1 200 300 - -hide x/1 -show x/1 -wait -assert_size x/1 200 300 - - -new_client w wayland -create w/1 csd - -resize w/1 300 400 -show w/1 -wait - -assert_size w/1 300 400 - -resize w/1 200 300 -wait_reconfigure -assert_size w/1 200 300 - -hide w/1 -show w/1 -wait_reconfigure -assert_size w/1 200 300 diff --git a/src/tests/stacking/fullscreen-maximize.metatest b/src/tests/stacking/fullscreen-maximize.metatest deleted file mode 100644 index 433c8b252..000000000 --- a/src/tests/stacking/fullscreen-maximize.metatest +++ /dev/null @@ -1,73 +0,0 @@ -# Tests that the following works, both on Wayland and X11 -# 1. Create a window with a known size -# 2. Maximize window results in maximized size -# 3. Fullscreen window results in fullscreen size -# 4. Unfullscreen window results in maximized size -# 5. Unmaximize window results in original size -# 6. Toggling fullscreen ends up with original size - -new_client w wayland -create w/1 csd - -resize w/1 500 400 -show w/1 -wait - -assert_size w/1 500 400 - -maximize w/1 -wait_reconfigure -assert_size w/1 MONITOR_WIDTH MONITOR_HEIGHT - -fullscreen w/1 -wait_reconfigure -assert_size w/1 MONITOR_WIDTH MONITOR_HEIGHT - -unfullscreen w/1 -wait_reconfigure -assert_size w/1 MONITOR_WIDTH MONITOR_HEIGHT - -unmaximize w/1 -wait_reconfigure -assert_size w/1 500 400 - -fullscreen w/1 -wait_reconfigure -assert_size w/1 MONITOR_WIDTH MONITOR_HEIGHT - -unfullscreen w/1 -wait_reconfigure -assert_size w/1 500 400 - -new_client x x11 -create x/1 csd - -resize x/1 500 400 -show x/1 -wait - -assert_size x/1 500 400 - -maximize x/1 -wait_reconfigure -assert_size x/1 MONITOR_WIDTH MONITOR_HEIGHT - -fullscreen x/1 -wait_reconfigure -assert_size x/1 MONITOR_WIDTH MONITOR_HEIGHT - -unfullscreen x/1 -wait_reconfigure -assert_size x/1 MONITOR_WIDTH MONITOR_HEIGHT - -unmaximize x/1 -wait_reconfigure -assert_size x/1 500 400 - -fullscreen x/1 -wait_reconfigure -assert_size x/1 MONITOR_WIDTH MONITOR_HEIGHT - -unfullscreen x/1 -wait_reconfigure -assert_size x/1 500 400 diff --git a/src/tests/stacking/map-fixed-size.metatest b/src/tests/stacking/map-fixed-size.metatest deleted file mode 100644 index 992de0df7..000000000 --- a/src/tests/stacking/map-fixed-size.metatest +++ /dev/null @@ -1,75 +0,0 @@ -# Map an initially maximized window - -# Map a Wayland window initially maximized - -new_client w wayland -create w/1 csd -maximize w/1 - -wait - -assert_stacking - -show w/1 - -wait - -assert_stacking w/1 -assert_size w/1 MONITOR_WIDTH MONITOR_HEIGHT - -hide w/1 - -# Map a Wayland window initially fullscreen - -create w/2 csd -fullscreen w/2 - -wait - -assert_stacking - -show w/2 - -wait - -assert_stacking w/2 -assert_size w/2 MONITOR_WIDTH MONITOR_HEIGHT - -hide w/2 - -# Map a X11 window initially maximized - -new_client x x11 -create x/1 csd -maximize x/1 - -wait - -assert_stacking - -show x/1 - -wait - -assert_stacking x/1 -assert_size x/1 MONITOR_WIDTH MONITOR_HEIGHT - -hide x/1 - -# Map a X11 window initially fullscreen - -create x/2 csd -fullscreen x/2 - -wait - -assert_stacking - -show x/2 - -wait - -assert_stacking x/2 -assert_size x/2 MONITOR_WIDTH MONITOR_HEIGHT - -hide x/2 diff --git a/src/tests/stacking/minimized.metatest b/src/tests/stacking/minimized.metatest deleted file mode 100644 index 3da236d19..000000000 --- a/src/tests/stacking/minimized.metatest +++ /dev/null @@ -1,18 +0,0 @@ -new_client 1 x11 -create 1/1 -show 1/1 -create 1/2 -show 1/2 -wait -assert_stacking 1/1 1/2 - -minimize 1/2 -wait -assert_stacking 1/2 | 1/1 - -# unminimize doesn't work for GTK+ currently, because GTK+ expects -# to be able to de-iconify with MapWindow, but the window is already -# mapped. -activate 1/2 -wait -assert_stacking 1/1 1/2 diff --git a/src/tests/stacking/mixed-windows.metatest b/src/tests/stacking/mixed-windows.metatest deleted file mode 100644 index 38058b582..000000000 --- a/src/tests/stacking/mixed-windows.metatest +++ /dev/null @@ -1,26 +0,0 @@ -new_client w wayland -new_client x x11 - -create w/1 -show w/1 -create w/2 -show w/2 -wait - -create x/1 -show x/1 -create x/2 -show x/2 -wait - -assert_stacking w/1 w/2 x/1 x/2 - -local_activate w/1 -assert_stacking w/2 x/1 x/2 w/1 - -local_activate x/1 -assert_stacking w/2 x/2 w/1 x/1 - -lower x/1 -wait -assert_stacking x/1 w/2 x/2 w/1 diff --git a/src/tests/stacking/modals.metatest b/src/tests/stacking/modals.metatest deleted file mode 100644 index 6c76eadf8..000000000 --- a/src/tests/stacking/modals.metatest +++ /dev/null @@ -1,32 +0,0 @@ -new_client w wayland - -# Create two Wayland windows, and make the second a transient of the -# first. Then make the parent not actually ever show, but show the -# transient. - -# Then make sure that hiding the transient can hide without causing -# issues. - -# https://gitlab.gnome.org/GNOME/mutter/-/issues/862 - -create w/1 csd -create w/2 csd - -set_parent w/2 1 - -freeze w/1 - -show w/1 async -show w/2 - -wait - -assert_stacking w/1 w/2 - -hide w/2 -wait - -assert_stacking w/1 - -hide w/2 -wait diff --git a/src/tests/stacking/override-redirect.metatest b/src/tests/stacking/override-redirect.metatest deleted file mode 100644 index b313d240b..000000000 --- a/src/tests/stacking/override-redirect.metatest +++ /dev/null @@ -1,19 +0,0 @@ -new_client 1 x11 -create 1/1 -show 1/1 -create 1/2 override -show 1/2 -wait -assert_stacking 1/1 1/2 - -activate 1/1 -wait -assert_stacking 1/1 1/2 - -lower 1/2 -wait -assert_stacking 1/2 | 1/1 - -raise 1/2 -wait -assert_stacking 1/1 1/2 diff --git a/src/tests/stacking/restore-position.metatest b/src/tests/stacking/restore-position.metatest deleted file mode 100644 index b4e7a7e97..000000000 --- a/src/tests/stacking/restore-position.metatest +++ /dev/null @@ -1,73 +0,0 @@ -# X11 - -new_client x x11 -create x/1 csd -show x/1 - -move x/1 100 100 -assert_position x/1 100 100 - -maximize x/1 -wait_reconfigure -assert_position x/1 0 0 - -unmaximize x/1 -wait_reconfigure -assert_position x/1 100 100 - -tile x/1 left -wait_reconfigure -assert_position x/1 0 0 - -untile x/1 -wait_reconfigure -assert_position x/1 100 100 - -tile x/1 left -wait -assert_position x/1 0 0 - -maximize x/1 -wait_reconfigure -assert_position x/1 0 0 - -unmaximize x/1 -wait_reconfigure -assert_position x/1 100 100 - -# Wayland - -new_client w wayland -create w/1 csd -show w/1 - -move w/1 100 100 -assert_position w/1 100 100 - -maximize w/1 -wait_reconfigure -assert_position w/1 0 0 - -unmaximize w/1 -wait_reconfigure -assert_position w/1 100 100 - -tile w/1 left -wait_reconfigure -assert_position w/1 0 0 - -untile w/1 -wait_reconfigure -assert_position w/1 100 100 - -tile w/1 left -wait_reconfigure -assert_position w/1 0 0 - -maximize w/1 -wait_reconfigure -assert_position w/1 0 0 - -unmaximize w/1 -wait_reconfigure -assert_position w/1 100 100 diff --git a/src/tests/stacking/restore-size.metatest b/src/tests/stacking/restore-size.metatest deleted file mode 100644 index 58941b017..000000000 --- a/src/tests/stacking/restore-size.metatest +++ /dev/null @@ -1,95 +0,0 @@ -# Check that X11 clients restore to their right size after unmaximize -# or untile - -new_client x x11 -create x/1 csd - -resize x/1 500 400 -maximize x/1 -show x/1 - -wait - -assert_size x/1 MONITOR_WIDTH MONITOR_HEIGHT - -unmaximize x/1 -wait - -assert_size x/1 500 400 - -resize x/1 300 200 -wait -maximize x/1 -wait_reconfigure -unmaximize x/1 -wait_reconfigure - -assert_size x/1 300 200 - -tile x/1 right -wait_reconfigure -assert_size x/1 MONITOR_WIDTH/2 MONITOR_HEIGHT - -untile x/1 -wait_reconfigure -assert_size x/1 300 200 - -tile x/1 left -wait_reconfigure -assert_size x/1 MONITOR_WIDTH/2 MONITOR_HEIGHT - -maximize x/1 -wait_reconfigure -assert_size x/1 MONITOR_WIDTH MONITOR_HEIGHT - -unmaximize x/1 -wait_reconfigure -assert_size x/1 300 200 - -# Check that Wayland clients restore to their right size after unmaximize -# or untile - -new_client w wayland -create w/1 csd - -resize w/1 150 300 -maximize w/1 -show w/1 - -wait - -assert_size w/1 MONITOR_WIDTH MONITOR_HEIGHT - -unmaximize w/1 -wait_reconfigure - -assert_size w/1 150 300 - -resize w/1 300 200 -wait -maximize w/1 -wait_reconfigure -unmaximize w/1 -wait_reconfigure - -assert_size w/1 300 200 - -tile w/1 right -wait_reconfigure -assert_size w/1 MONITOR_WIDTH/2 MONITOR_HEIGHT - -untile w/1 -wait_reconfigure -assert_size w/1 300 200 - -tile w/1 left -wait_reconfigure -assert_size w/1 MONITOR_WIDTH/2 MONITOR_HEIGHT - -maximize w/1 -wait_reconfigure -assert_size w/1 MONITOR_WIDTH MONITOR_HEIGHT - -unmaximize w/1 -wait_reconfigure -assert_size w/1 300 200 diff --git a/src/tests/stacking/set-override-redirect-parent.metatest b/src/tests/stacking/set-override-redirect-parent.metatest deleted file mode 100644 index 4c98bee22..000000000 --- a/src/tests/stacking/set-override-redirect-parent.metatest +++ /dev/null @@ -1,37 +0,0 @@ -new_client 1 x11 -create 1/1 override -show 1/1 - -create 1/2 -set_parent 1/2 1 -show 1/2 - -create 1/3 -set_parent 1/3 2 -show 1/3 - - -new_client 2 x11 -create 2/1 -show 2/1 - -create 2/2 override -set_parent 2/2 1 -show 2/2 - -create 2/3 -set_parent 2/3 2 -show 2/3 - - -new_client 3 x11 -create 3/1 override -show 3/1 - -create 3/2 override -set_parent 3/2 1 -show 3/2 - -create 3/3 override -set_parent 3/3 2 -show 3/3 diff --git a/src/tests/stacking/set-parent-exported.metatest b/src/tests/stacking/set-parent-exported.metatest deleted file mode 100644 index 8dbb9c932..000000000 --- a/src/tests/stacking/set-parent-exported.metatest +++ /dev/null @@ -1,15 +0,0 @@ -new_client 1 wayland -create 1/1 -show 1/1 -create 1/2 -show 1/2 -wait - -set_parent_exported 1/1 2 -wait -assert_stacking 1/2 1/1 - -local_activate 1/2 -assert_stacking 1/2 1/1 - -destroy 1/2 diff --git a/src/tests/stacking/set-parent.metatest b/src/tests/stacking/set-parent.metatest deleted file mode 100644 index e95eaca29..000000000 --- a/src/tests/stacking/set-parent.metatest +++ /dev/null @@ -1,14 +0,0 @@ -new_client 1 wayland -create 1/1 -show 1/1 -create 1/2 -show 1/2 -wait -assert_stacking 1/1 1/2 - -set_parent 1/1 2 -wait -assert_stacking 1/2 1/1 - -local_activate 1/2 -assert_stacking 1/2 1/1 diff --git a/src/tests/stacking/unmaximize-new-size.metatest b/src/tests/stacking/unmaximize-new-size.metatest deleted file mode 100644 index b25922a70..000000000 --- a/src/tests/stacking/unmaximize-new-size.metatest +++ /dev/null @@ -1,22 +0,0 @@ -# This is only tested on Wayland since it's broken on X11 - -new_client w wayland -create w/1 csd - -resize w/1 500 400 -show w/1 -wait - -assert_size w/1 500 400 - -maximize w/1 -wait_reconfigure -assert_size w/1 MONITOR_WIDTH MONITOR_HEIGHT - -resize w/1 300 500 -wait_reconfigure -assert_size w/1 MONITOR_WIDTH MONITOR_HEIGHT - -unmaximize w/1 -wait_reconfigure -assert_size w/1 300 500 diff --git a/src/tests/stage-view-tests.c b/src/tests/stage-view-tests.c deleted file mode 100644 index 509af37fb..000000000 --- a/src/tests/stage-view-tests.c +++ /dev/null @@ -1,1171 +0,0 @@ -/* - * Copyright (C) 2020 Jonas Dreßler - * - * 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 . - */ - -#include "config.h" - -#include "clutter/clutter.h" -#include "clutter/clutter-stage-view-private.h" -#include "meta-test/meta-context-test.h" -#include "tests/meta-backend-test.h" -#include "tests/monitor-test-utils.h" - -static MonitorTestCaseSetup initial_test_case_setup = { - .modes = { - { - .width = 1024, - .height = 768, - .refresh_rate = 60.0 - } - }, - .n_modes = 1, - .outputs = { - { - .crtc = 0, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 0 }, - .n_possible_crtcs = 1, - .width_mm = 222, - .height_mm = 125 - }, - { - .crtc = 1, - .modes = { 0 }, - .n_modes = 1, - .preferred_mode = 0, - .possible_crtcs = { 1 }, - .n_possible_crtcs = 1, - .width_mm = 220, - .height_mm = 124 - } - }, - .n_outputs = 2, - .crtcs = { - { - .current_mode = 0 - }, - { - .current_mode = 0 - } - }, - .n_crtcs = 2 -}; - -static void -meta_test_stage_views_exist (void) -{ - MetaBackend *backend = meta_get_backend (); - ClutterActor *stage; - GList *stage_views; - - stage = meta_backend_get_stage (backend); - g_assert_cmpint (clutter_actor_get_width (stage), ==, 1024 * 2); - g_assert_cmpint (clutter_actor_get_height (stage), ==, 768); - - stage_views = clutter_stage_peek_stage_views (CLUTTER_STAGE (stage)); - g_assert_cmpint (g_list_length (stage_views), ==, 2); -} - -static void -on_after_paint (ClutterStage *stage, - ClutterStageView *view, - gboolean *was_painted) -{ - *was_painted = TRUE; -} - -static void -wait_for_paint (ClutterActor *stage) -{ - gboolean was_painted = FALSE; - gulong was_painted_id; - - was_painted_id = g_signal_connect (CLUTTER_STAGE (stage), - "after-paint", - G_CALLBACK (on_after_paint), - &was_painted); - - while (!was_painted) - g_main_context_iteration (NULL, TRUE); - - g_signal_handler_disconnect (stage, was_painted_id); -} - -static void -on_stage_views_changed (ClutterActor *actor, - gboolean *stage_views_changed) -{ - *stage_views_changed = TRUE; -} - -static void -is_on_stage_views (ClutterActor *actor, - unsigned int n_views, - ...) -{ - va_list valist; - int i = 0; - GList *stage_views = clutter_actor_peek_stage_views (actor); - - va_start (valist, n_views); - for (i = 0; i < n_views; i++) - { - ClutterStageView *view = va_arg (valist, ClutterStageView*); - g_assert_nonnull (g_list_find (stage_views, view)); - } - - va_end (valist); - g_assert (g_list_length (stage_views) == n_views); -} - -static void -meta_test_actor_stage_views (void) -{ - MetaBackend *backend = meta_get_backend (); - ClutterActor *stage, *container, *test_actor; - GList *stage_views; - gboolean stage_views_changed_container = FALSE; - gboolean stage_views_changed_test_actor = FALSE; - gboolean *stage_views_changed_container_ptr = - &stage_views_changed_container; - gboolean *stage_views_changed_test_actor_ptr = - &stage_views_changed_test_actor; - - stage = meta_backend_get_stage (backend); - stage_views = clutter_stage_peek_stage_views (CLUTTER_STAGE (stage)); - - container = clutter_actor_new (); - clutter_actor_set_size (container, 100, 100); - clutter_actor_add_child (stage, container); - - test_actor = clutter_actor_new (); - clutter_actor_set_size (test_actor, 50, 50); - clutter_actor_add_child (container, test_actor); - - g_signal_connect (container, "stage-views-changed", - G_CALLBACK (on_stage_views_changed), - stage_views_changed_container_ptr); - g_signal_connect (test_actor, "stage-views-changed", - G_CALLBACK (on_stage_views_changed), - stage_views_changed_test_actor_ptr); - - clutter_actor_show (stage); - - wait_for_paint (stage); - - is_on_stage_views (container, 1, stage_views->data); - is_on_stage_views (test_actor, 1, stage_views->data); - - /* The signal was emitted for the initial change */ - g_assert (stage_views_changed_container); - g_assert (stage_views_changed_test_actor); - stage_views_changed_container = FALSE; - stage_views_changed_test_actor = FALSE; - - /* Move the container to the second stage view */ - clutter_actor_set_x (container, 1040); - - wait_for_paint (stage); - - is_on_stage_views (container, 1, stage_views->next->data); - is_on_stage_views (test_actor, 1, stage_views->next->data); - - /* The signal was emitted again */ - g_assert (stage_views_changed_container); - g_assert (stage_views_changed_test_actor); - stage_views_changed_container = FALSE; - stage_views_changed_test_actor = FALSE; - - /* Move the container so it's on both stage views while the test_actor - * is only on the first one. - */ - clutter_actor_set_x (container, 940); - - wait_for_paint (stage); - - is_on_stage_views (container, 2, stage_views->data, stage_views->next->data); - is_on_stage_views (test_actor, 1, stage_views->data); - - /* The signal was emitted again */ - g_assert (stage_views_changed_container); - g_assert (stage_views_changed_test_actor); - - g_signal_handlers_disconnect_by_func (container, on_stage_views_changed, - stage_views_changed_container_ptr); - g_signal_handlers_disconnect_by_func (test_actor, on_stage_views_changed, - stage_views_changed_test_actor_ptr); - clutter_actor_destroy (container); -} - -static void -on_relayout_actor_frame (ClutterTimeline *timeline, - int msec, - ClutterActor *actor) -{ - MetaBackend *backend = meta_get_backend (); - ClutterActor *stage = meta_backend_get_stage (backend); - - clutter_stage_clear_stage_views (CLUTTER_STAGE (stage)); -} - -static void -meta_test_actor_stage_views_relayout (void) -{ - MetaBackend *backend = meta_get_backend (); - ClutterActor *stage, *actor; - ClutterTransition *transition; - GMainLoop *main_loop; - - stage = meta_backend_get_stage (backend); - - actor = clutter_actor_new (); - clutter_actor_set_size (actor, 100, 100); - clutter_actor_set_easing_duration (actor, 100); - clutter_actor_add_child (stage, actor); - - clutter_actor_show (stage); - - wait_for_paint (stage); - clutter_actor_set_position (actor, 1000.0, 0.0); - transition = clutter_actor_get_transition (actor, "position"); - g_signal_connect_after (transition, "new-frame", - G_CALLBACK (on_relayout_actor_frame), - actor); - - main_loop = g_main_loop_new (NULL, FALSE); - g_signal_connect_swapped (transition, "stopped", - G_CALLBACK (g_main_loop_quit), - main_loop); - - g_main_loop_run (main_loop); - - clutter_actor_destroy (actor); - g_main_loop_unref (main_loop); -} - -static void -meta_test_actor_stage_views_reparent (void) -{ - MetaBackend *backend = meta_get_backend (); - ClutterActor *stage, *container, *test_actor; - GList *stage_views; - gboolean stage_views_changed_container = FALSE; - gboolean stage_views_changed_test_actor = FALSE; - gboolean *stage_views_changed_container_ptr = - &stage_views_changed_container; - gboolean *stage_views_changed_test_actor_ptr = - &stage_views_changed_test_actor; - - stage = meta_backend_get_stage (backend); - stage_views = clutter_stage_peek_stage_views (CLUTTER_STAGE (stage)); - - container = clutter_actor_new (); - clutter_actor_set_size (container, 100, 100); - clutter_actor_set_x (container, 1020); - clutter_actor_add_child (stage, container); - - test_actor = clutter_actor_new (); - clutter_actor_set_size (test_actor, 20, 20); - clutter_actor_add_child (container, test_actor); - - g_signal_connect (container, "stage-views-changed", - G_CALLBACK (on_stage_views_changed), - stage_views_changed_container_ptr); - g_signal_connect (test_actor, "stage-views-changed", - G_CALLBACK (on_stage_views_changed), - stage_views_changed_test_actor_ptr); - - clutter_actor_show (stage); - - wait_for_paint (stage); - - is_on_stage_views (container, 2, stage_views->data, stage_views->next->data); - is_on_stage_views (test_actor, 2, stage_views->data, stage_views->next->data); - - /* The signal was emitted for both actors */ - g_assert (stage_views_changed_container); - g_assert (stage_views_changed_test_actor); - stage_views_changed_container = FALSE; - stage_views_changed_test_actor = FALSE; - - /* Remove the test_actor from the scene-graph */ - g_object_ref (test_actor); - clutter_actor_remove_child (container, test_actor); - - /* While the test_actor is not on stage, it must be on no stage views */ - is_on_stage_views (test_actor, 0); - - /* When the test_actor left the stage, the signal was emitted */ - g_assert (!stage_views_changed_container); - g_assert (stage_views_changed_test_actor); - stage_views_changed_test_actor = FALSE; - - /* Add the test_actor again as a child of the stage */ - clutter_actor_add_child (stage, test_actor); - g_object_unref (test_actor); - - wait_for_paint (stage); - - /* The container is still on both stage views... */ - is_on_stage_views (container, 2, stage_views->data, stage_views->next->data); - - /* ...while the test_actor is only on the first one now */ - is_on_stage_views (test_actor, 1, stage_views->data); - - /* The signal was emitted for the test_actor again */ - g_assert (!stage_views_changed_container); - g_assert (stage_views_changed_test_actor); - stage_views_changed_test_actor = FALSE; - - /* Move the container out of the stage... */ - clutter_actor_set_y (container, 2000); - g_object_ref (test_actor); - clutter_actor_remove_child (stage, test_actor); - - /* When the test_actor left the stage, the signal was emitted */ - g_assert (!stage_views_changed_container); - g_assert (stage_views_changed_test_actor); - stage_views_changed_test_actor = FALSE; - - /* ...and reparent the test_actor to the container again */ - clutter_actor_add_child (container, test_actor); - g_object_unref (test_actor); - - wait_for_paint (stage); - - /* Now both actors are on no stage views */ - is_on_stage_views (container, 0); - is_on_stage_views (test_actor, 0); - - /* The signal was emitted only for the container, the test_actor already - * has no stage-views. - */ - g_assert (stage_views_changed_container); - g_assert (!stage_views_changed_test_actor); - - g_signal_handlers_disconnect_by_func (container, on_stage_views_changed, - stage_views_changed_container_ptr); - g_signal_handlers_disconnect_by_func (test_actor, on_stage_views_changed, - stage_views_changed_test_actor_ptr); - clutter_actor_destroy (container); -} - -static void -meta_test_actor_stage_views_hide_parent (void) -{ - MetaBackend *backend = meta_get_backend (); - ClutterActor *stage, *outer_container, *inner_container, *test_actor; - GList *stage_views; - gboolean stage_views_changed_outer_container = FALSE; - gboolean stage_views_changed_inner_container = FALSE; - gboolean stage_views_changed_test_actor = FALSE; - gboolean *stage_views_changed_outer_container_ptr = - &stage_views_changed_outer_container; - gboolean *stage_views_changed_inner_container_ptr = - &stage_views_changed_inner_container; - gboolean *stage_views_changed_test_actor_ptr = - &stage_views_changed_test_actor; - - stage = meta_backend_get_stage (backend); - stage_views = clutter_stage_peek_stage_views (CLUTTER_STAGE (stage)); - - outer_container = clutter_actor_new (); - clutter_actor_add_child (stage, outer_container); - - inner_container = clutter_actor_new (); - clutter_actor_add_child (outer_container, inner_container); - - test_actor = clutter_actor_new (); - clutter_actor_set_size (test_actor, 20, 20); - clutter_actor_add_child (inner_container, test_actor); - - g_signal_connect (outer_container, "stage-views-changed", - G_CALLBACK (on_stage_views_changed), - stage_views_changed_outer_container_ptr); - g_signal_connect (inner_container, "stage-views-changed", - G_CALLBACK (on_stage_views_changed), - stage_views_changed_inner_container_ptr); - g_signal_connect (test_actor, "stage-views-changed", - G_CALLBACK (on_stage_views_changed), - stage_views_changed_test_actor_ptr); - - clutter_actor_show (stage); - - wait_for_paint (stage); - - /* The containers and the test_actor are on all on the first view */ - is_on_stage_views (outer_container, 1, stage_views->data); - is_on_stage_views (inner_container, 1, stage_views->data); - is_on_stage_views (test_actor, 1, stage_views->data); - - /* The signal was emitted for all three */ - g_assert (stage_views_changed_outer_container); - g_assert (stage_views_changed_inner_container); - g_assert (stage_views_changed_test_actor); - stage_views_changed_outer_container = FALSE; - stage_views_changed_inner_container = FALSE; - stage_views_changed_test_actor = FALSE; - - /* Hide the inner_container */ - clutter_actor_hide (inner_container); - - /* Move the outer_container so it's still on the first view */ - clutter_actor_set_x (outer_container, 1023); - - wait_for_paint (stage); - - /* The outer_container is still expanded so it should be on both views */ - is_on_stage_views (outer_container, 2, - stage_views->data, stage_views->next->data); - - /* The inner_container and test_actor aren't updated because they're hidden */ - is_on_stage_views (inner_container, 1, stage_views->data); - is_on_stage_views (test_actor, 1, stage_views->data); - - /* The signal was emitted for the outer_container */ - g_assert (stage_views_changed_outer_container); - g_assert (!stage_views_changed_inner_container); - g_assert (!stage_views_changed_test_actor); - stage_views_changed_outer_container = FALSE; - - /* Show the inner_container again */ - clutter_actor_show (inner_container); - - wait_for_paint (stage); - - /* All actors are on both views now */ - is_on_stage_views (outer_container, 2, - stage_views->data, stage_views->next->data); - is_on_stage_views (inner_container, 2, - stage_views->data, stage_views->next->data); - is_on_stage_views (test_actor, 2, - stage_views->data, stage_views->next->data); - - /* The signal was emitted for the inner_container and test_actor */ - g_assert (!stage_views_changed_outer_container); - g_assert (stage_views_changed_inner_container); - g_assert (stage_views_changed_test_actor); - - g_signal_handlers_disconnect_by_func (outer_container, on_stage_views_changed, - stage_views_changed_outer_container_ptr); - g_signal_handlers_disconnect_by_func (inner_container, on_stage_views_changed, - stage_views_changed_inner_container_ptr); - g_signal_handlers_disconnect_by_func (test_actor, on_stage_views_changed, - stage_views_changed_test_actor_ptr); - clutter_actor_destroy (outer_container); -} - -static MetaMonitorTestSetup * -create_stage_view_test_setup (void) -{ - return create_monitor_test_setup (&initial_test_case_setup, - MONITOR_TEST_FLAG_NO_STORED); -} - -static void -assert_is_stage_view (ClutterStageView *stage_view, - int x, - int y, - int width, - int height) -{ - cairo_rectangle_int_t layout; - - g_assert_nonnull (stage_view); - g_assert_true (CLUTTER_IS_STAGE_VIEW (stage_view)); - - clutter_stage_view_get_layout (stage_view, &layout); - g_assert_cmpint (layout.x, ==, x); - g_assert_cmpint (layout.y, ==, y); - g_assert_cmpint (layout.width, ==, width); - g_assert_cmpint (layout.height, ==, height); -} - -static void -meta_test_actor_stage_views_hot_plug (void) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerTest *monitor_manager_test = - META_MONITOR_MANAGER_TEST (monitor_manager); - ClutterActor *stage = meta_backend_get_stage (backend); - ClutterActor *actor_1; - ClutterActor *actor_2; - GList *stage_views; - GList *prev_stage_views; - MonitorTestCaseSetup hotplug_test_case_setup = initial_test_case_setup; - MetaMonitorTestSetup *test_setup; - - stage_views = clutter_stage_peek_stage_views (CLUTTER_STAGE (stage)); - g_assert_cmpint (g_list_length (stage_views), ==, 2); - assert_is_stage_view (stage_views->data, 0, 0, 1024, 768); - assert_is_stage_view (stage_views->next->data, 1024, 0, 1024, 768); - - actor_1 = clutter_actor_new (); - clutter_actor_set_size (actor_1, 100, 100); - clutter_actor_set_position (actor_1, 100, 100); - clutter_actor_add_child (stage, actor_1); - - actor_2 = clutter_actor_new (); - clutter_actor_set_size (actor_2, 100, 100); - clutter_actor_set_position (actor_2, 1100, 100); - clutter_actor_add_child (stage, actor_2); - - clutter_actor_show (stage); - - wait_for_paint (stage); - - is_on_stage_views (actor_1, 1, stage_views->data); - is_on_stage_views (actor_2, 1, stage_views->next->data); - - prev_stage_views = g_list_copy_deep (stage_views, - (GCopyFunc) g_object_ref, NULL); - - test_setup = create_monitor_test_setup (&hotplug_test_case_setup, - MONITOR_TEST_FLAG_NO_STORED); - meta_monitor_manager_test_emulate_hotplug (monitor_manager_test, test_setup); - - stage_views = clutter_stage_peek_stage_views (CLUTTER_STAGE (stage)); - - g_assert (stage_views != prev_stage_views); - g_assert_cmpint (g_list_length (stage_views), ==, 2); - g_assert (prev_stage_views->data != stage_views->data); - g_assert (prev_stage_views->next->data != stage_views->next->data); - assert_is_stage_view (stage_views->data, 0, 0, 1024, 768); - assert_is_stage_view (stage_views->next->data, 1024, 0, 1024, 768); - - g_list_free_full (prev_stage_views, (GDestroyNotify) g_object_unref); - - is_on_stage_views (actor_1, 0); - is_on_stage_views (actor_2, 0); - - wait_for_paint (stage); - - is_on_stage_views (actor_1, 1, stage_views->data); - is_on_stage_views (actor_2, 1, stage_views->next->data); - - clutter_actor_destroy (actor_1); - clutter_actor_destroy (actor_2); -} - -static void -meta_test_actor_stage_views_frame_clock (void) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerTest *monitor_manager_test = - META_MONITOR_MANAGER_TEST (monitor_manager); - ClutterActor *stage = meta_backend_get_stage (backend); - ClutterActor *actor_1; - ClutterActor *actor_2; - ClutterActor *actor_3; - GList *stage_views; - MonitorTestCaseSetup frame_clock_test_setup = initial_test_case_setup; - MetaMonitorTestSetup *test_setup; - ClutterFrameClock *frame_clock; - - frame_clock_test_setup.modes[1].width = 1024; - frame_clock_test_setup.modes[1].height = 768; - frame_clock_test_setup.modes[1].refresh_rate = 30.0; - frame_clock_test_setup.n_modes = 2; - frame_clock_test_setup.outputs[1].modes[0] = 1; - frame_clock_test_setup.outputs[1].preferred_mode = 1; - test_setup = create_monitor_test_setup (&frame_clock_test_setup, - MONITOR_TEST_FLAG_NO_STORED); - meta_monitor_manager_test_emulate_hotplug (monitor_manager_test, test_setup); - - stage_views = clutter_stage_peek_stage_views (CLUTTER_STAGE (stage)); - - g_assert_cmpfloat (clutter_stage_view_get_refresh_rate (stage_views->data), - ==, - 60.0); - g_assert_cmpfloat (clutter_stage_view_get_refresh_rate (stage_views->next->data), - ==, - 30.0); - - actor_1 = clutter_actor_new (); - clutter_actor_set_size (actor_1, 100, 100); - clutter_actor_set_position (actor_1, 100, 100); - clutter_actor_add_child (stage, actor_1); - - actor_2 = clutter_actor_new (); - clutter_actor_set_size (actor_2, 100, 100); - clutter_actor_set_position (actor_2, 1100, 100); - clutter_actor_add_child (stage, actor_2); - - actor_3 = clutter_actor_new (); - clutter_actor_set_size (actor_3, 100, 100); - clutter_actor_set_position (actor_3, 1000, 400); - clutter_actor_add_child (stage, actor_3); - - clutter_actor_show (stage); - - wait_for_paint (stage); - - is_on_stage_views (actor_1, 1, stage_views->data); - is_on_stage_views (actor_2, 1, stage_views->next->data); - is_on_stage_views (actor_3, 2, - stage_views->data, - stage_views->next->data); - - frame_clock = clutter_actor_pick_frame_clock (actor_1, NULL); - g_assert_cmpfloat (clutter_frame_clock_get_refresh_rate (frame_clock), - ==, - 60.0); - frame_clock = clutter_actor_pick_frame_clock (actor_2, NULL); - g_assert_cmpfloat (clutter_frame_clock_get_refresh_rate (frame_clock), - ==, - 30.0); - frame_clock = clutter_actor_pick_frame_clock (actor_3, NULL); - g_assert_cmpfloat (clutter_frame_clock_get_refresh_rate (frame_clock), - ==, - 60.0); - - clutter_actor_destroy (actor_1); - clutter_actor_destroy (actor_2); - clutter_actor_destroy (actor_3); -} - -typedef struct _TimelineTest -{ - GMainLoop *main_loop; - ClutterFrameClock *frame_clock_1; - ClutterFrameClock *frame_clock_2; - int phase; - - int frame_counter[2]; -} TimelineTest; - -static void -on_transition_stopped (ClutterTransition *transition, - gboolean is_finished, - TimelineTest *test) -{ - g_assert_true (is_finished); - - g_assert_cmpint (test->phase, ==, 2); - - test->phase = 3; - - g_main_loop_quit (test->main_loop); -} - -static void -on_transition_new_frame (ClutterTransition *transition, - int elapsed_time_ms, - TimelineTest *test) -{ - ClutterTimeline *timeline = CLUTTER_TIMELINE (transition); - - if (test->phase == 1) - { - g_assert (clutter_timeline_get_frame_clock (timeline) == - test->frame_clock_1); - test->frame_counter[0]++; - } - else if (test->phase == 2) - { - g_assert (clutter_timeline_get_frame_clock (timeline) == - test->frame_clock_2); - test->frame_counter[1]++; - } - else - { - g_assert_not_reached (); - } -} - -static void -on_transition_frame_clock_changed (ClutterTimeline *timeline, - GParamSpec *pspec, - TimelineTest *test) -{ - ClutterFrameClock *frame_clock; - - frame_clock = clutter_timeline_get_frame_clock (timeline); - g_assert (frame_clock == test->frame_clock_2); - g_assert_cmpint (test->phase, ==, 1); - - test->phase = 2; -} - -static void -meta_test_actor_stage_views_timeline (void) -{ - TimelineTest test = { 0 }; - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerTest *monitor_manager_test = - META_MONITOR_MANAGER_TEST (monitor_manager); - ClutterActor *stage = meta_backend_get_stage (backend); - MonitorTestCaseSetup frame_clock_test_setup; - ClutterActor *actor; - GList *stage_views; - ClutterStageView *stage_view_1; - ClutterStageView *stage_view_2; - MetaMonitorTestSetup *test_setup; - ClutterTransition *transition; - - frame_clock_test_setup = initial_test_case_setup; - frame_clock_test_setup.modes[1].width = 1024; - frame_clock_test_setup.modes[1].height = 768; - frame_clock_test_setup.modes[1].refresh_rate = 30.0; - frame_clock_test_setup.n_modes = 2; - frame_clock_test_setup.outputs[1].modes[0] = 1; - frame_clock_test_setup.outputs[1].preferred_mode = 1; - test_setup = create_monitor_test_setup (&frame_clock_test_setup, - MONITOR_TEST_FLAG_NO_STORED); - meta_monitor_manager_test_emulate_hotplug (monitor_manager_test, test_setup); - - stage_views = clutter_stage_peek_stage_views (CLUTTER_STAGE (stage)); - stage_view_1 = stage_views->data; - stage_view_2 = stage_views->next->data; - g_assert_nonnull (stage_view_1); - g_assert_nonnull (stage_view_2); - test.frame_clock_1 = clutter_stage_view_get_frame_clock (stage_view_1); - test.frame_clock_2 = clutter_stage_view_get_frame_clock (stage_view_2); - g_assert_nonnull (test.frame_clock_1); - g_assert_nonnull (test.frame_clock_2); - - actor = clutter_actor_new (); - clutter_actor_set_size (actor, 100, 100); - clutter_actor_set_position (actor, 800, 100); - clutter_actor_add_child (stage, actor); - - clutter_actor_show (stage); - - wait_for_paint (stage); - - is_on_stage_views (actor, 1, stage_views->data); - - clutter_actor_set_easing_duration (actor, 1000); - clutter_actor_set_position (actor, 1200, 300); - - transition = clutter_actor_get_transition (actor, "position"); - g_assert_nonnull (transition); - g_assert (clutter_timeline_get_frame_clock (CLUTTER_TIMELINE (transition)) == - test.frame_clock_1); - - test.main_loop = g_main_loop_new (NULL, FALSE); - g_signal_connect (transition, "stopped", - G_CALLBACK (on_transition_stopped), - &test); - g_signal_connect (transition, "new-frame", - G_CALLBACK (on_transition_new_frame), - &test); - g_signal_connect (transition, "notify::frame-clock", - G_CALLBACK (on_transition_frame_clock_changed), - &test); - - test.phase = 1; - - g_main_loop_run (test.main_loop); - - g_assert_cmpint (test.phase, ==, 3); - g_assert_cmpint (test.frame_counter[0], >, 0); - g_assert_cmpint (test.frame_counter[1], >, 0); - - clutter_actor_destroy (actor); - g_main_loop_unref (test.main_loop); -} - -static void -meta_test_actor_stage_views_parent_views_rebuilt (void) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerTest *monitor_manager_test = - META_MONITOR_MANAGER_TEST (monitor_manager); - MonitorTestCaseSetup frame_clock_test_setup; - MetaMonitorTestSetup *test_setup; - ClutterActor *stage, *container, *test_actor; - GList *stage_views; - ClutterTimeline *timeline; - ClutterFrameClock *timeline_frame_clock; - ClutterFrameClock *view_frame_clock; - ClutterStageView *old_stage_view; - ClutterFrameClock *old_frame_clock; - - stage = meta_backend_get_stage (backend); - - frame_clock_test_setup = initial_test_case_setup; - frame_clock_test_setup.n_outputs = 1; - frame_clock_test_setup.n_crtcs = 1; - test_setup = create_monitor_test_setup (&frame_clock_test_setup, - MONITOR_TEST_FLAG_NO_STORED); - meta_monitor_manager_test_emulate_hotplug (monitor_manager_test, test_setup); - - stage_views = clutter_stage_peek_stage_views (CLUTTER_STAGE (stage)); - g_assert_cmpint (g_list_length (stage_views), ==, 1); - - container = clutter_actor_new (); - clutter_actor_set_size (container, 100, 100); - clutter_actor_set_position (container, 0, 0); - clutter_actor_add_child (stage, container); - - test_actor = clutter_actor_new (); - clutter_actor_set_size (test_actor, 0, 0); - clutter_actor_add_child (container, test_actor); - - clutter_actor_show (stage); - wait_for_paint (stage); - - is_on_stage_views (test_actor, 0); - is_on_stage_views (container, 1, stage_views->data); - is_on_stage_views (stage, 1, stage_views->data); - - timeline = clutter_timeline_new_for_actor (test_actor, 100); - clutter_timeline_start (timeline); - - timeline_frame_clock = clutter_timeline_get_frame_clock (timeline); - view_frame_clock = clutter_stage_view_get_frame_clock (stage_views->data); - g_assert_nonnull (timeline_frame_clock); - g_assert_nonnull (view_frame_clock); - g_assert (timeline_frame_clock == view_frame_clock); - - /* Keep the stage view alive so it can be used to compare with later. */ - old_stage_view = g_object_ref (stage_views->data); - old_frame_clock = - g_object_ref (clutter_stage_view_get_frame_clock (old_stage_view)); - - test_setup = create_monitor_test_setup (&frame_clock_test_setup, - MONITOR_TEST_FLAG_NO_STORED); - meta_monitor_manager_test_emulate_hotplug (monitor_manager_test, test_setup); - wait_for_paint (stage); - - stage_views = clutter_stage_peek_stage_views (CLUTTER_STAGE (stage)); - g_assert_cmpint (g_list_length (stage_views), ==, 1); - - g_assert (stage_views->data != old_stage_view); - view_frame_clock = clutter_stage_view_get_frame_clock (stage_views->data); - g_assert_nonnull (view_frame_clock); - g_assert (view_frame_clock != old_frame_clock); - - timeline_frame_clock = clutter_timeline_get_frame_clock (timeline); - g_assert_nonnull (timeline_frame_clock); - g_assert (timeline_frame_clock == view_frame_clock); - - g_object_unref (old_stage_view); - g_object_unref (old_frame_clock); - - clutter_actor_destroy (test_actor); - clutter_actor_destroy (container); -} - -static void -meta_test_actor_stage_views_parent_views_changed (void) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerTest *monitor_manager_test = - META_MONITOR_MANAGER_TEST (monitor_manager); - MonitorTestCaseSetup frame_clock_test_setup; - MetaMonitorTestSetup *test_setup; - ClutterActor *stage, *container, *test_actor; - GList *stage_views; - ClutterTimeline *timeline; - ClutterFrameClock *timeline_frame_clock; - ClutterFrameClock *first_view_frame_clock; - ClutterFrameClock *second_view_frame_clock; - - stage = meta_backend_get_stage (backend); - - frame_clock_test_setup = initial_test_case_setup; - test_setup = create_monitor_test_setup (&frame_clock_test_setup, - MONITOR_TEST_FLAG_NO_STORED); - meta_monitor_manager_test_emulate_hotplug (monitor_manager_test, test_setup); - - stage_views = clutter_stage_peek_stage_views (CLUTTER_STAGE (stage)); - g_assert_cmpint (g_list_length (stage_views), ==, 2); - - container = clutter_actor_new (); - clutter_actor_set_size (container, 100, 100); - clutter_actor_set_position (container, 0, 0); - clutter_actor_add_child (stage, container); - - test_actor = clutter_actor_new (); - clutter_actor_set_size (test_actor, 0, 0); - clutter_actor_add_child (container, test_actor); - - stage_views = clutter_stage_peek_stage_views (CLUTTER_STAGE (stage)); - g_assert_cmpint (g_list_length (stage_views), ==, 2); - clutter_actor_show (stage); - wait_for_paint (stage); - stage_views = clutter_stage_peek_stage_views (CLUTTER_STAGE (stage)); - g_assert_cmpint (g_list_length (stage_views), ==, 2); - - is_on_stage_views (test_actor, 0); - is_on_stage_views (container, 1, stage_views->data); - is_on_stage_views (stage, 2, - stage_views->data, - stage_views->next->data); - - timeline = clutter_timeline_new_for_actor (test_actor, 100); - clutter_timeline_start (timeline); - - first_view_frame_clock = - clutter_stage_view_get_frame_clock (stage_views->data); - second_view_frame_clock = - clutter_stage_view_get_frame_clock (stage_views->next->data); - g_assert_nonnull (first_view_frame_clock); - g_assert_nonnull (second_view_frame_clock); - - timeline_frame_clock = clutter_timeline_get_frame_clock (timeline); - - g_assert_nonnull (timeline_frame_clock); - g_assert (timeline_frame_clock == first_view_frame_clock); - - clutter_actor_set_x (container, 1200); - wait_for_paint (stage); - - timeline_frame_clock = clutter_timeline_get_frame_clock (timeline); - g_assert_nonnull (timeline_frame_clock); - g_assert (timeline_frame_clock == second_view_frame_clock); - - clutter_actor_destroy (test_actor); - clutter_actor_destroy (container); -} - -static void -meta_test_actor_stage_views_and_frame_clocks_freed (void) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerTest *monitor_manager_test = - META_MONITOR_MANAGER_TEST (monitor_manager); - ClutterActor *stage = meta_backend_get_stage (backend); - ClutterActor *actor_1; - ClutterActor *actor_2; - GList *stage_views; - ClutterStageView *first_view; - ClutterStageView *second_view; - ClutterTimeline *timeline; - ClutterFrameClock *timeline_frame_clock; - ClutterFrameClock *first_view_frame_clock; - ClutterFrameClock *second_view_frame_clock; - MonitorTestCaseSetup frame_clock_test_setup; - MetaMonitorTestSetup *test_setup; - - stage_views = clutter_stage_peek_stage_views (CLUTTER_STAGE (stage)); - first_view = stage_views->data; - second_view = stage_views->next->data; - - g_object_add_weak_pointer (G_OBJECT (first_view), (gpointer *) &first_view); - g_object_add_weak_pointer (G_OBJECT (second_view), (gpointer *) &second_view); - - /* Create two actors, one on the first stage view, another one on the - * second view. - */ - actor_1 = clutter_actor_new (); - clutter_actor_set_size (actor_1, 100, 100); - clutter_actor_set_position (actor_1, 100, 100); - clutter_actor_add_child (stage, actor_1); - - actor_2 = clutter_actor_new (); - clutter_actor_set_size (actor_2, 100, 100); - clutter_actor_set_position (actor_2, 1100, 100); - clutter_actor_add_child (stage, actor_2); - - clutter_actor_show (stage); - - wait_for_paint (stage); - - is_on_stage_views (actor_1, 1, first_view); - is_on_stage_views (actor_2, 1, second_view); - - /* Now create a timeline for the first actor and make sure its using the - * frame clock of the first view. - */ - timeline = clutter_timeline_new_for_actor (actor_1, 100); - clutter_timeline_start (timeline); - - first_view_frame_clock = - clutter_stage_view_get_frame_clock (first_view); - second_view_frame_clock = - clutter_stage_view_get_frame_clock (second_view); - g_assert_nonnull (first_view_frame_clock); - g_assert_nonnull (second_view_frame_clock); - - g_object_add_weak_pointer (G_OBJECT (first_view_frame_clock), - (gpointer *) &first_view_frame_clock); - g_object_add_weak_pointer (G_OBJECT (second_view_frame_clock), - (gpointer *) &second_view_frame_clock); - - timeline_frame_clock = clutter_timeline_get_frame_clock (timeline); - - g_assert_nonnull (timeline_frame_clock); - g_assert (timeline_frame_clock == first_view_frame_clock); - - /* Now set the timeline actor to actor_2 and make sure the timeline is - * using the second frame clock. - */ - clutter_timeline_set_actor (timeline, actor_2); - - timeline_frame_clock = clutter_timeline_get_frame_clock (timeline); - - g_assert_nonnull (timeline_frame_clock); - g_assert (timeline_frame_clock == second_view_frame_clock); - - /* Trigger a hotplug and remove both monitors, after that the timeline - * should have no frame clock set and both stage views and their - * frame clocks should have been freed. - */ - frame_clock_test_setup = initial_test_case_setup; - frame_clock_test_setup.n_outputs = 0; - frame_clock_test_setup.n_crtcs = 0; - test_setup = create_monitor_test_setup (&frame_clock_test_setup, - MONITOR_TEST_FLAG_NO_STORED); - meta_monitor_manager_test_emulate_hotplug (monitor_manager_test, test_setup); - - timeline_frame_clock = clutter_timeline_get_frame_clock (timeline); - - g_assert_null (timeline_frame_clock); - g_assert_null (first_view); - g_assert_null (first_view_frame_clock); - g_assert_null (second_view); - g_assert_null (second_view_frame_clock); - - clutter_actor_destroy (actor_1); - clutter_actor_destroy (actor_2); -} - -static void -ensure_view_count (int n_views) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaMonitorManagerTest *monitor_manager_test = - META_MONITOR_MANAGER_TEST (monitor_manager); - MonitorTestCaseSetup test_case_setup; - MetaMonitorTestSetup *test_setup; - - test_case_setup = initial_test_case_setup; - test_case_setup.n_outputs = n_views; - test_case_setup.n_crtcs = n_views; - test_setup = create_monitor_test_setup (&test_case_setup, - MONITOR_TEST_FLAG_NO_STORED); - meta_monitor_manager_test_emulate_hotplug (monitor_manager_test, test_setup); -} - -static void -meta_test_timeline_actor_destroyed (void) -{ - MetaBackend *backend = meta_get_backend (); - ClutterActor *stage; - GList *stage_views; - ClutterActor *persistent_actor; - ClutterActor *actor; - ClutterTimeline *timeline; - gboolean did_stage_views_changed = FALSE; - - ensure_view_count (0); - - stage = meta_backend_get_stage (backend); - clutter_actor_show (stage); - - persistent_actor = clutter_actor_new (); - clutter_actor_add_child (stage, persistent_actor); - - stage_views = clutter_stage_peek_stage_views (CLUTTER_STAGE (stage)); - g_assert_null (stage_views); - stage_views = clutter_actor_peek_stage_views (stage); - g_assert_null (stage_views); - g_assert_null (clutter_actor_pick_frame_clock (stage, NULL)); - - actor = clutter_actor_new (); - clutter_actor_add_child (stage, actor); - g_assert_null (clutter_actor_pick_frame_clock (actor, NULL)); - - timeline = clutter_timeline_new_for_actor (actor, 100); - clutter_timeline_start (timeline); - - g_signal_connect (stage, "stage-views-changed", - G_CALLBACK (on_stage_views_changed), - &did_stage_views_changed); - - clutter_actor_destroy (actor); - g_object_unref (timeline); - - ensure_view_count (1); - - stage_views = clutter_stage_peek_stage_views (CLUTTER_STAGE (stage)); - g_assert_cmpint (g_list_length (stage_views), ==, 1); - - g_assert_false (did_stage_views_changed); - clutter_actor_queue_redraw (persistent_actor); - clutter_stage_schedule_update (CLUTTER_STAGE (stage)); - wait_for_paint (stage); - g_assert_true (did_stage_views_changed); - - g_signal_handlers_disconnect_by_func (stage, on_stage_views_changed, - &did_stage_views_changed); - - clutter_actor_destroy (persistent_actor); -} - -static void -init_tests (void) -{ - meta_monitor_manager_test_init_test_setup (create_stage_view_test_setup); - - g_test_add_func ("/stage-view/stage-views-exist", - meta_test_stage_views_exist); - g_test_add_func ("/stage-views/actor-stage-views", - meta_test_actor_stage_views); - g_test_add_func ("/stage-views/actor-stage-views-relayout", - meta_test_actor_stage_views_relayout); - g_test_add_func ("/stage-views/actor-stage-views-reparent", - meta_test_actor_stage_views_reparent); - g_test_add_func ("/stage-views/actor-stage-views-hide-parent", - meta_test_actor_stage_views_hide_parent); - g_test_add_func ("/stage-views/actor-stage-views-hot-plug", - meta_test_actor_stage_views_hot_plug); - g_test_add_func ("/stage-views/actor-stage-views-frame-clock", - meta_test_actor_stage_views_frame_clock); - g_test_add_func ("/stage-views/actor-stage-views-timeline", - meta_test_actor_stage_views_timeline); - g_test_add_func ("/stage-views/actor-stage-views-parent-rebuilt", - meta_test_actor_stage_views_parent_views_rebuilt); - g_test_add_func ("/stage-views/actor-stage-views-parent-changed", - meta_test_actor_stage_views_parent_views_changed); - g_test_add_func ("/stage-views/actor-stage-views-and-frame-clocks-freed", - meta_test_actor_stage_views_and_frame_clocks_freed); - g_test_add_func ("/stage-views/timeline/actor-destroyed", - meta_test_timeline_actor_destroyed); -} - -int -main (int argc, char *argv[]) -{ - g_autoptr (MetaContext) context = NULL; - - context = meta_create_test_context (META_CONTEXT_TEST_TYPE_NESTED, - META_CONTEXT_TEST_FLAG_NO_X11); - g_assert (meta_context_configure (context, &argc, &argv, NULL)); - - init_tests (); - - return meta_context_test_run_tests (META_CONTEXT_TEST (context)); -} diff --git a/src/tests/test-client.c b/src/tests/test-client.c deleted file mode 100644 index 73931375e..000000000 --- a/src/tests/test-client.c +++ /dev/null @@ -1,944 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 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 . - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -const char *client_id = "0"; -static gboolean wayland; -GHashTable *windows; -GQuark event_source_quark; -GQuark event_handlers_quark; -GQuark can_take_focus_quark; - -typedef void (*XEventHandler) (GtkWidget *window, XEvent *event); - -static void read_next_line (GDataInputStream *in); - -static void -window_export_handle_cb (GdkWindow *window, - const char *handle_str, - gpointer user_data) -{ - GdkWindow *gdk_window = gtk_widget_get_window (GTK_WIDGET (user_data)); - - if (!gdk_wayland_window_set_transient_for_exported (gdk_window, - (gchar *) handle_str)) - g_print ("Fail to set transient_for exported window handle %s\n", handle_str); - gdk_window_set_modal_hint (gdk_window, TRUE); -} - -static GtkWidget * -lookup_window (const char *window_id) -{ - GtkWidget *window = g_hash_table_lookup (windows, window_id); - if (!window) - g_print ("Window %s doesn't exist\n", window_id); - - return window; -} - -typedef struct { - GSource base; - GSource **self_ref; - GPollFD event_poll_fd; - Display *xdisplay; -} XClientEventSource; - -static gboolean -x_event_source_prepare (GSource *source, - int *timeout) -{ - XClientEventSource *x_source = (XClientEventSource *) source; - - *timeout = -1; - - return XPending (x_source->xdisplay); -} - -static gboolean -x_event_source_check (GSource *source) -{ - XClientEventSource *x_source = (XClientEventSource *) source; - - return XPending (x_source->xdisplay); -} - -static gboolean -x_event_source_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data) -{ - XClientEventSource *x_source = (XClientEventSource *) source; - - while (XPending (x_source->xdisplay)) - { - GHashTableIter iter; - XEvent event; - gpointer value; - - XNextEvent (x_source->xdisplay, &event); - - g_hash_table_iter_init (&iter, windows); - while (g_hash_table_iter_next (&iter, NULL, &value)) - { - GList *l; - GtkWidget *window = value; - GList *handlers = - g_object_get_qdata (G_OBJECT (window), event_handlers_quark); - - for (l = handlers; l; l = l->next) - { - XEventHandler handler = l->data; - handler (window, &event); - } - } - } - - return TRUE; -} - -static void -x_event_source_finalize (GSource *source) -{ - XClientEventSource *x_source = (XClientEventSource *) source; - - *x_source->self_ref = NULL; -} - -static GSourceFuncs x_event_funcs = { - x_event_source_prepare, - x_event_source_check, - x_event_source_dispatch, - x_event_source_finalize, -}; - -static GSource* -ensure_xsource_handler (GdkDisplay *gdkdisplay) -{ - static GSource *source = NULL; - Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdkdisplay); - XClientEventSource *x_source; - - if (source) - return g_source_ref (source); - - source = g_source_new (&x_event_funcs, sizeof (XClientEventSource)); - x_source = (XClientEventSource *) source; - x_source->self_ref = &source; - x_source->xdisplay = xdisplay; - x_source->event_poll_fd.fd = ConnectionNumber (xdisplay); - x_source->event_poll_fd.events = G_IO_IN; - g_source_add_poll (source, &x_source->event_poll_fd); - - g_source_set_priority (source, GDK_PRIORITY_EVENTS - 1); - g_source_set_can_recurse (source, TRUE); - g_source_attach (source, NULL); - - return source; -} - -static gboolean -window_has_x11_event_handler (GtkWidget *window, - XEventHandler handler) -{ - GList *handlers = - g_object_get_qdata (G_OBJECT (window), event_handlers_quark); - - g_return_val_if_fail (handler, FALSE); - g_return_val_if_fail (!wayland, FALSE); - - return g_list_find (handlers, handler) != NULL; -} - -static void -unref_and_maybe_destroy_gsource (GSource *source) -{ - g_source_unref (source); - - if (source->ref_count == 1) - g_source_destroy (source); -} - -static void -window_add_x11_event_handler (GtkWidget *window, - XEventHandler handler) -{ - GSource *source; - GList *handlers = - g_object_get_qdata (G_OBJECT (window), event_handlers_quark); - - g_return_if_fail (!window_has_x11_event_handler (window, handler)); - - source = ensure_xsource_handler (gtk_widget_get_display (window)); - g_object_set_qdata_full (G_OBJECT (window), event_source_quark, source, - (GDestroyNotify) unref_and_maybe_destroy_gsource); - - handlers = g_list_append (handlers, handler); - g_object_set_qdata (G_OBJECT (window), event_handlers_quark, handlers); -} - -static void -window_remove_x11_event_handler (GtkWidget *window, - XEventHandler handler) -{ - GList *handlers = - g_object_get_qdata (G_OBJECT (window), event_handlers_quark); - - g_return_if_fail (window_has_x11_event_handler (window, handler)); - - g_object_set_qdata (G_OBJECT (window), event_source_quark, NULL); - - handlers = g_list_remove (handlers, handler); - g_object_set_qdata (G_OBJECT (window), event_handlers_quark, handlers); -} - -static void -handle_take_focus (GtkWidget *window, - XEvent *xevent) -{ - GdkWindow *gdkwindow = gtk_widget_get_window (window); - GdkDisplay *display = gtk_widget_get_display (window); - Atom wm_protocols = - gdk_x11_get_xatom_by_name_for_display (display, "WM_PROTOCOLS"); - Atom wm_take_focus = - gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS"); - - if (xevent->xany.type != ClientMessage || - xevent->xany.window != GDK_WINDOW_XID (gdkwindow)) - return; - - if (xevent->xclient.message_type == wm_protocols && - xevent->xclient.data.l[0] == wm_take_focus) - { - XSetInputFocus (xevent->xany.display, - GDK_WINDOW_XID (gdkwindow), - RevertToParent, - xevent->xclient.data.l[1]); - } -} - -static int -calculate_titlebar_height (GtkWindow *window) -{ - GtkWidget *titlebar; - GdkWindow *gdk_window; - - gdk_window = gtk_widget_get_window (GTK_WIDGET (window)); - if (gdk_window_get_state (gdk_window) & GDK_WINDOW_STATE_FULLSCREEN) - return 0; - - titlebar = gtk_window_get_titlebar (window); - if (!titlebar) - return 0; - - return gtk_widget_get_allocated_height (titlebar); -} - -static void -process_line (const char *line) -{ - GError *error = NULL; - int argc; - char **argv; - - if (!g_shell_parse_argv (line, &argc, &argv, &error)) - { - g_print ("error parsing command: %s\n", error->message); - g_error_free (error); - return; - } - - if (argc < 1) - { - g_print ("Empty command\n"); - goto out; - } - - if (strcmp (argv[0], "create") == 0) - { - int i; - - if (argc < 2) - { - g_print ("usage: create [override|csd]\n"); - goto out; - } - - if (g_hash_table_lookup (windows, argv[1])) - { - g_print ("window %s already exists\n", argv[1]); - goto out; - } - - gboolean override = FALSE; - gboolean csd = FALSE; - for (i = 2; i < argc; i++) - { - if (strcmp (argv[i], "override") == 0) - override = TRUE; - if (strcmp (argv[i], "csd") == 0) - csd = TRUE; - } - - if (override && csd) - { - g_print ("override and csd keywords are exclusive\n"); - goto out; - } - - GtkWidget *window = gtk_window_new (override ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL); - g_hash_table_insert (windows, g_strdup (argv[1]), window); - - if (csd) - { - GtkWidget *headerbar = gtk_header_bar_new (); - gtk_window_set_titlebar (GTK_WINDOW (window), headerbar); - gtk_widget_show (headerbar); - } - - gtk_window_set_default_size (GTK_WINDOW (window), 100, 100); - - gchar *title = g_strdup_printf ("test/%s/%s", client_id, argv[1]); - gtk_window_set_title (GTK_WINDOW (window), title); - g_free (title); - - g_object_set_qdata (G_OBJECT (window), can_take_focus_quark, - GUINT_TO_POINTER (TRUE)); - - gtk_widget_realize (window); - - if (!wayland) - { - /* The cairo xlib backend creates a window when initialized, which - * confuses our testing if it happens asynchronously the first - * time a window is painted. By creating an Xlib surface and - * destroying it, we force initialization at a more predictable time. - */ - GdkWindow *window_gdk = gtk_widget_get_window (window); - cairo_surface_t *surface = gdk_window_create_similar_surface (window_gdk, - CAIRO_CONTENT_COLOR, - 1, 1); - cairo_surface_destroy (surface); - } - - } - else if (strcmp (argv[0], "set_parent") == 0) - { - if (argc != 3) - { - g_print ("usage: set_parent \n"); - goto out; - } - - GtkWidget *window = lookup_window (argv[1]); - if (!window) - { - g_print ("unknown window %s\n", argv[1]); - goto out; - } - - GtkWidget *parent_window = lookup_window (argv[2]); - if (!parent_window) - { - g_print ("unknown parent window %s\n", argv[2]); - goto out; - } - - gtk_window_set_transient_for (GTK_WINDOW (window), - GTK_WINDOW (parent_window)); - } - else if (strcmp (argv[0], "set_parent_exported") == 0) - { - if (argc != 3) - { - g_print ("usage: set_parent_exported \n"); - goto out; - } - - GtkWidget *window = lookup_window (argv[1]); - if (!window) - { - g_print ("unknown window %s\n", argv[1]); - goto out; - } - - GtkWidget *parent_window = lookup_window (argv[2]); - if (!parent_window) - { - g_print ("unknown parent window %s\n", argv[2]); - goto out; - } - - GdkWindow *parent_gdk_window = gtk_widget_get_window (parent_window); - if (!gdk_wayland_window_export_handle (parent_gdk_window, - window_export_handle_cb, - window, - NULL)) - g_print ("Fail to export handle for window id %s\n", argv[2]); - } - else if (strcmp (argv[0], "accept_focus") == 0) - { - if (argc != 3) - { - g_print ("usage: %s [true|false]\n", argv[0]); - goto out; - } - - GtkWidget *window = lookup_window (argv[1]); - if (!window) - { - g_print ("unknown window %s\n", argv[1]); - goto out; - } - - if (!wayland && - window_has_x11_event_handler (window, handle_take_focus)) - { - g_print ("Impossible to use %s for windows accepting take focus\n", - argv[1]); - goto out; - } - - gboolean enabled = g_ascii_strcasecmp (argv[2], "true") == 0; - gtk_window_set_accept_focus (GTK_WINDOW (window), enabled); - } - else if (strcmp (argv[0], "can_take_focus") == 0) - { - if (argc != 3) - { - g_print ("usage: %s [true|false]\n", argv[0]); - goto out; - } - - GtkWidget *window = lookup_window (argv[1]); - if (!window) - { - g_print ("unknown window %s\n", argv[1]); - goto out; - } - - if (wayland) - { - g_print ("%s not supported under wayland\n", argv[0]); - goto out; - } - - if (window_has_x11_event_handler (window, handle_take_focus)) - { - g_print ("Impossible to change %s for windows accepting take focus\n", - argv[1]); - goto out; - } - - GdkDisplay *display = gdk_display_get_default (); - GdkWindow *gdkwindow = gtk_widget_get_window (window); - Display *xdisplay = gdk_x11_display_get_xdisplay (display); - Window xwindow = GDK_WINDOW_XID (gdkwindow); - Atom wm_take_focus = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS"); - gboolean add = g_ascii_strcasecmp(argv[2], "true") == 0; - Atom *protocols = NULL; - Atom *new_protocols; - int n_protocols = 0; - int i, n = 0; - - gdk_display_sync (display); - XGetWMProtocols (xdisplay, xwindow, &protocols, &n_protocols); - new_protocols = g_new0 (Atom, n_protocols + (add ? 1 : 0)); - - for (i = 0; i < n_protocols; ++i) - { - if (protocols[i] != wm_take_focus) - new_protocols[n++] = protocols[i]; - } - - if (add) - new_protocols[n++] = wm_take_focus; - - XSetWMProtocols (xdisplay, xwindow, new_protocols, n); - g_object_set_qdata (G_OBJECT (window), can_take_focus_quark, - GUINT_TO_POINTER (add)); - - XFree (new_protocols); - XFree (protocols); - } - else if (strcmp (argv[0], "accept_take_focus") == 0) - { - if (argc != 3) - { - g_print ("usage: %s [true|false]\n", argv[0]); - goto out; - } - - GtkWidget *window = lookup_window (argv[1]); - if (!window) - { - g_print ("unknown window %s\n", argv[1]); - goto out; - } - - if (wayland) - { - g_print ("%s not supported under wayland\n", argv[0]); - goto out; - } - - if (gtk_window_get_accept_focus (GTK_WINDOW (window))) - { - g_print ("%s not supported for input windows\n", argv[0]); - goto out; - } - - if (!g_object_get_qdata (G_OBJECT (window), can_take_focus_quark)) - { - g_print ("%s not supported for windows with no WM_TAKE_FOCUS set\n", - argv[0]); - goto out; - } - - if (g_ascii_strcasecmp (argv[2], "true") == 0) - window_add_x11_event_handler (window, handle_take_focus); - else - window_remove_x11_event_handler (window, handle_take_focus); - } - else if (strcmp (argv[0], "show") == 0) - { - if (argc != 2) - { - g_print ("usage: show \n"); - goto out; - } - - GtkWidget *window = lookup_window (argv[1]); - if (!window) - goto out; - - gtk_widget_show (window); - gdk_display_sync (gdk_display_get_default ()); - } - else if (strcmp (argv[0], "hide") == 0) - { - if (argc != 2) - { - g_print ("usage: hide \n"); - goto out; - } - - GtkWidget *window = lookup_window (argv[1]); - if (!window) - goto out; - - gtk_widget_hide (window); - } - else if (strcmp (argv[0], "activate") == 0) - { - if (argc != 2) - { - g_print ("usage: activate \n"); - goto out; - } - - GtkWidget *window = lookup_window (argv[1]); - if (!window) - goto out; - - gtk_window_present (GTK_WINDOW (window)); - } - else if (strcmp (argv[0], "resize") == 0) - { - if (argc != 4) - { - g_print ("usage: resize \n"); - goto out; - } - - GtkWidget *window = lookup_window (argv[1]); - if (!window) - goto out; - - int width = atoi (argv[2]); - int height = atoi (argv[3]); - int titlebar_height = calculate_titlebar_height (GTK_WINDOW (window)); - gtk_window_resize (GTK_WINDOW (window), - width, - height - titlebar_height); - } - else if (strcmp (argv[0], "raise") == 0) - { - if (argc != 2) - { - g_print ("usage: raise \n"); - goto out; - } - - GtkWidget *window = lookup_window (argv[1]); - if (!window) - goto out; - - gdk_window_raise (gtk_widget_get_window (window)); - } - else if (strcmp (argv[0], "lower") == 0) - { - if (argc != 2) - { - g_print ("usage: lower \n"); - goto out; - } - - GtkWidget *window = lookup_window (argv[1]); - if (!window) - goto out; - - gdk_window_lower (gtk_widget_get_window (window)); - } - else if (strcmp (argv[0], "destroy") == 0) - { - if (argc != 2) - { - g_print ("usage: destroy \n"); - goto out; - } - - GtkWidget *window = lookup_window (argv[1]); - if (!window) - goto out; - - g_hash_table_remove (windows, argv[1]); - gtk_widget_destroy (window); - } - else if (strcmp (argv[0], "destroy_all") == 0) - { - if (argc != 1) - { - g_print ("usage: destroy_all\n"); - goto out; - } - - GHashTableIter iter; - gpointer key, value; - - g_hash_table_iter_init (&iter, windows); - while (g_hash_table_iter_next (&iter, &key, &value)) - gtk_widget_destroy (value); - - g_hash_table_remove_all (windows); - } - else if (strcmp (argv[0], "sync") == 0) - { - if (argc != 1) - { - g_print ("usage: sync\n"); - goto out; - } - - gdk_display_sync (gdk_display_get_default ()); - } - else if (strcmp (argv[0], "set_counter") == 0) - { - XSyncCounter counter; - int value; - - if (argc != 3) - { - g_print ("usage: set_counter \n"); - goto out; - } - - if (wayland) - { - g_print ("usage: set_counter can only be used for X11\n"); - goto out; - } - - counter = strtoul(argv[1], NULL, 10); - value = atoi(argv[2]); - XSyncValue sync_value; - XSyncIntToValue (&sync_value, value); - - XSyncSetCounter (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), - counter, sync_value); - } - else if (strcmp (argv[0], "minimize") == 0) - { - if (argc != 2) - { - g_print ("usage: minimize \n"); - goto out; - } - - GtkWidget *window = lookup_window (argv[1]); - if (!window) - goto out; - - gtk_window_iconify (GTK_WINDOW (window)); - } - else if (strcmp (argv[0], "unminimize") == 0) - { - if (argc != 2) - { - g_print ("usage: unminimize \n"); - goto out; - } - - GtkWidget *window = lookup_window (argv[1]); - if (!window) - goto out; - - gtk_window_deiconify (GTK_WINDOW (window)); - } - else if (strcmp (argv[0], "maximize") == 0) - { - if (argc != 2) - { - g_print ("usage: maximize \n"); - goto out; - } - - GtkWidget *window = lookup_window (argv[1]); - if (!window) - goto out; - - gtk_window_maximize (GTK_WINDOW (window)); - } - else if (strcmp (argv[0], "unmaximize") == 0) - { - if (argc != 2) - { - g_print ("usage: unmaximize \n"); - goto out; - } - - GtkWidget *window = lookup_window (argv[1]); - if (!window) - goto out; - - gtk_window_unmaximize (GTK_WINDOW (window)); - } - else if (strcmp (argv[0], "fullscreen") == 0) - { - if (argc != 2) - { - g_print ("usage: fullscreen \n"); - goto out; - } - - GtkWidget *window = lookup_window (argv[1]); - if (!window) - goto out; - - gtk_window_fullscreen (GTK_WINDOW (window)); - } - else if (strcmp (argv[0], "unfullscreen") == 0) - { - if (argc != 2) - { - g_print ("usage: unfullscreen \n"); - goto out; - } - - GtkWidget *window = lookup_window (argv[1]); - if (!window) - goto out; - - gtk_window_unfullscreen (GTK_WINDOW (window)); - } - else if (strcmp (argv[0], "freeze") == 0) - { - if (argc != 2) - { - g_print ("usage: freeze \n"); - goto out; - } - - GtkWidget *window = lookup_window (argv[1]); - if (!window) - goto out; - - gdk_window_freeze_updates (gtk_widget_get_window (window)); - } - else if (strcmp (argv[0], "thaw") == 0) - { - if (argc != 2) - { - g_print ("usage: thaw \n"); - goto out; - } - - GtkWidget *window = lookup_window (argv[1]); - if (!window) - goto out; - - gdk_window_thaw_updates (gtk_widget_get_window (window)); - } - else if (strcmp (argv[0], "assert_size") == 0) - { - int expected_width; - int expected_height; - int width; - int height; - - if (argc != 4) - { - g_print ("usage: assert_size \n"); - goto out; - } - - GtkWidget *window = lookup_window (argv[1]); - if (!window) - goto out; - - gtk_window_get_size (GTK_WINDOW (window), &width, &height); - height += calculate_titlebar_height (GTK_WINDOW (window)); - - expected_width = atoi (argv[2]); - expected_height = atoi (argv[3]); - if (expected_width != width || expected_height != height) - { - g_print ("Expected size %dx%d didn't match actual size %dx%d\n", - expected_width, expected_height, - width, height); - goto out; - } - } - else - { - g_print ("Unknown command %s\n", argv[0]); - goto out; - } - - g_print ("OK\n"); - - out: - g_strfreev (argv); -} - -static void -on_line_received (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - GDataInputStream *in = G_DATA_INPUT_STREAM (source); - GError *error = NULL; - gsize length; - char *line = g_data_input_stream_read_line_finish_utf8 (in, result, &length, &error); - - if (line == NULL) - { - if (error != NULL) - g_printerr ("Error reading from stdin: %s\n", error->message); - gtk_main_quit (); - return; - } - - process_line (line); - g_free (line); - read_next_line (in); -} - -static void -read_next_line (GDataInputStream *in) -{ - g_data_input_stream_read_line_async (in, G_PRIORITY_DEFAULT, NULL, - on_line_received, NULL); -} - -const GOptionEntry options[] = { - { - "wayland", 0, 0, G_OPTION_ARG_NONE, - &wayland, - "Create a wayland client, not an X11 one", - NULL - }, - { - "client-id", 0, 0, G_OPTION_ARG_STRING, - &client_id, - "Identifier used in Window titles for this client", - "CLIENT_ID", - }, - { NULL } -}; - -int -main(int argc, char **argv) -{ - GOptionContext *context = g_option_context_new (NULL); - GdkScreen *screen; - GtkCssProvider *provider; - GError *error = NULL; - - g_option_context_add_main_entries (context, options, NULL); - - if (!g_option_context_parse (context, - &argc, &argv, &error)) - { - g_printerr ("%s", error->message); - return 1; - } - - if (wayland) - gdk_set_allowed_backends ("wayland"); - else - gdk_set_allowed_backends ("x11"); - - gtk_init (NULL, NULL); - - screen = gdk_screen_get_default (); - provider = gtk_css_provider_new (); - static const char *no_decoration_css = - "decoration {" - " border-radius: 0 0 0 0;" - " border-width: 0;" - " padding: 0 0 0 0;" - " box-shadow: 0 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0 rgba(0, 0, 0, 0);" - " margin: 0px;" - "}"; - if (!gtk_css_provider_load_from_data (provider, - no_decoration_css, - strlen (no_decoration_css), - &error)) - { - g_printerr ("%s", error->message); - return 1; - } - gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER (provider), - GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); - - windows = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, NULL); - event_source_quark = g_quark_from_static_string ("event-source"); - event_handlers_quark = g_quark_from_static_string ("event-handlers"); - can_take_focus_quark = g_quark_from_static_string ("can-take-focus"); - - GInputStream *raw_in = g_unix_input_stream_new (0, FALSE); - GDataInputStream *in = g_data_input_stream_new (raw_in); - - read_next_line (in); - - gtk_main (); - - return 0; -} diff --git a/src/tests/test-runner.c b/src/tests/test-runner.c deleted file mode 100644 index bdf2ef109..000000000 --- a/src/tests/test-runner.c +++ /dev/null @@ -1,1202 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 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 . - */ - -#include "config.h" - -#include -#include -#include -#include - -#include "core/window-private.h" -#include "meta-test/meta-context-test.h" -#include "meta/util.h" -#include "meta/window.h" -#include "tests/meta-test-utils.h" -#include "ui/ui.h" -#include "wayland/meta-wayland.h" -#include "x11/meta-x11-display-private.h" - -typedef struct { - MetaContext *context; - GHashTable *clients; - MetaAsyncWaiter *waiter; - GString *warning_messages; - GMainLoop *loop; - gulong x11_display_opened_handler_id; -} TestCase; - -static gboolean -test_case_alarm_filter (MetaX11Display *x11_display, - XSyncAlarmNotifyEvent *event, - gpointer data) -{ - TestCase *test = data; - GHashTableIter iter; - gpointer key, value; - - if (meta_async_waiter_process_x11_event (test->waiter, x11_display, event)) - return TRUE; - - g_hash_table_iter_init (&iter, test->clients); - while (g_hash_table_iter_next (&iter, &key, &value)) - { - MetaTestClient *client = value; - - if (meta_test_client_process_x11_event (client, x11_display, event)) - return TRUE; - } - - return FALSE; -} - -static void -on_x11_display_opened (MetaDisplay *display, - TestCase *test) -{ - meta_x11_display_set_alarm_filter (display->x11_display, - test_case_alarm_filter, test); - test->waiter = meta_async_waiter_new (); -} - -static TestCase * -test_case_new (MetaContext *context) -{ - TestCase *test = g_new0 (TestCase, 1); - MetaDisplay *display = meta_context_get_display (context); - - if (!meta_is_wayland_compositor ()) - { - meta_context_test_wait_for_x11_display (META_CONTEXT_TEST (context)); - on_x11_display_opened (display, test); - } - else - { - if (display->x11_display) - on_x11_display_opened (display, test); - else - test->x11_display_opened_handler_id = - g_signal_connect (meta_get_display (), "x11-display-opened", - G_CALLBACK (on_x11_display_opened), - test); - } - - test->context = context; - test->clients = g_hash_table_new (g_str_hash, g_str_equal); - test->loop = g_main_loop_new (NULL, FALSE); - - return test; -} - -static gboolean -test_case_loop_quit (gpointer data) -{ - TestCase *test = data; - - g_main_loop_quit (test->loop); - - return FALSE; -} - -static gboolean -test_case_dispatch (TestCase *test, - GError **error) -{ - /* Wait until we've done any outstanding queued up work. - * Though we add this as BEFORE_REDRAW, the iteration that runs the - * BEFORE_REDRAW idles will proceed on and do the redraw, so we're - * waiting until after *all* frame processing. - */ - meta_later_add (META_LATER_BEFORE_REDRAW, - test_case_loop_quit, - test, - NULL); - g_main_loop_run (test->loop); - - return TRUE; -} - -static gboolean -test_case_wait (TestCase *test, - GError **error) -{ - GHashTableIter iter; - gpointer key, value; - - /* First have each client set a XSync counter, and wait until - * we receive the resulting event - so we know we've received - * everything that the client have sent us. - */ - g_hash_table_iter_init (&iter, test->clients); - while (g_hash_table_iter_next (&iter, &key, &value)) - if (!meta_test_client_wait (value, error)) - return FALSE; - - /* Then wait until we've done any outstanding queued up work. */ - test_case_dispatch (test, error); - - /* Then set an XSync counter ourselves and and wait until - * we receive the resulting event - this makes sure that we've - * received back any X events we generated. - */ - if (test->waiter) - meta_async_waiter_set_and_wait (test->waiter); - return TRUE; -} - -static gboolean -test_case_sleep (TestCase *test, - guint32 interval, - GError **error) -{ - g_timeout_add_full (G_PRIORITY_LOW, interval, test_case_loop_quit, test, NULL); - g_main_loop_run (test->loop); - - return TRUE; -} - -#define BAD_COMMAND(...) \ - G_STMT_START { \ - g_set_error (error, \ - META_TEST_CLIENT_ERROR, \ - META_TEST_CLIENT_ERROR_BAD_COMMAND, \ - __VA_ARGS__); \ - return FALSE; \ - } G_STMT_END - -static MetaTestClient * -test_case_lookup_client (TestCase *test, - char *client_id, - GError **error) -{ - MetaTestClient *client = g_hash_table_lookup (test->clients, client_id); - if (!client) - { - g_set_error (error, - META_TEST_CLIENT_ERROR, - META_TEST_CLIENT_ERROR_BAD_COMMAND, - "No such client %s", client_id); - } - - return client; -} - -static gboolean -test_case_parse_window_id (TestCase *test, - const char *client_and_window_id, - MetaTestClient **client, - const char **window_id, - GError **error) -{ - const char *slash = strchr (client_and_window_id, '/'); - char *tmp; - if (slash == NULL) - BAD_COMMAND ("client/window ID %s doesn't contain a /", client_and_window_id); - - *window_id = slash + 1; - - tmp = g_strndup (client_and_window_id, slash - client_and_window_id); - *client = test_case_lookup_client (test, tmp, error); - g_free (tmp); - - return client != NULL; -} - -static gboolean -test_case_assert_stacking (TestCase *test, - char **expected_windows, - int n_expected_windows, - GError **error) -{ - MetaDisplay *display = meta_get_display (); - guint64 *windows; - int n_windows; - GString *stack_string = g_string_new (NULL); - GString *expected_string = g_string_new (NULL); - int i; - - meta_stack_tracker_get_stack (display->stack_tracker, &windows, &n_windows); - for (i = 0; i < n_windows; i++) - { - MetaWindow *window = meta_display_lookup_stack_id (display, windows[i]); - if (window != NULL && window->title) - { - /* See comment in meta_ui_new() about why the dummy window for GTK+ theming - * is managed as a MetaWindow. - */ - if (META_STACK_ID_IS_X11 (windows[i]) && - meta_ui_window_is_dummy (display->x11_display->ui, windows[i])) - continue; - - if (stack_string->len > 0) - g_string_append_c (stack_string, ' '); - - if (g_str_has_prefix (window->title, "test/")) - g_string_append (stack_string, window->title + 5); - else - g_string_append_printf (stack_string, "(%s)", window->title); - } - else if (windows[i] == display->x11_display->guard_window) - { - if (stack_string->len > 0) - g_string_append_c (stack_string, ' '); - - g_string_append_c (stack_string, '|'); - } - } - - for (i = 0; i < n_expected_windows; i++) - { - if (expected_string->len > 0) - g_string_append_c (expected_string, ' '); - - g_string_append (expected_string, expected_windows[i]); - } - - /* Don't require '| ' as a prefix if there are no hidden windows - we - * remove the prefix from the actual string instead of adding it to the - * expected string for clarity of the error message - */ - if (index (expected_string->str, '|') == NULL && stack_string->str[0] == '|') - { - g_string_erase (stack_string, - 0, stack_string->str[1] == ' ' ? 2 : 1); - } - - if (strcmp (expected_string->str, stack_string->str) != 0) - { - g_set_error (error, - META_TEST_CLIENT_ERROR, - META_TEST_CLIENT_ERROR_ASSERTION_FAILED, - "stacking: expected='%s', actual='%s'", - expected_string->str, stack_string->str); - } - - g_string_free (stack_string, TRUE); - g_string_free (expected_string, TRUE); - - return *error == NULL; -} - -static gboolean -test_case_assert_focused (TestCase *test, - const char *expected_window, - GError **error) -{ - MetaDisplay *display = meta_get_display (); - - if (!display->focus_window) - { - if (g_strcmp0 (expected_window, "none") != 0) - { - g_set_error (error, - META_TEST_CLIENT_ERROR, - META_TEST_CLIENT_ERROR_ASSERTION_FAILED, - "focus: expected='%s', actual='none'", expected_window); - } - } - else - { - const char *focused = display->focus_window->title; - - if (g_str_has_prefix (focused, "test/")) - focused += 5; - - if (g_strcmp0 (focused, expected_window) != 0) - g_set_error (error, - META_TEST_CLIENT_ERROR, - META_TEST_CLIENT_ERROR_ASSERTION_FAILED, - "focus: expected='%s', actual='%s'", - expected_window, focused); - } - - return *error == NULL; -} - -static gboolean -test_case_assert_size (TestCase *test, - MetaWindow *window, - int expected_width, - int expected_height, - GError **error) -{ - MetaRectangle frame_rect; - - meta_window_get_frame_rect (window, &frame_rect); - - if (frame_rect.width != expected_width || - frame_rect.height != expected_height) - { - g_set_error (error, - META_TEST_CLIENT_ERROR, - META_TEST_CLIENT_ERROR_ASSERTION_FAILED, - "Expected size %dx%d didn't match actual size %dx%d", - expected_width, expected_height, - frame_rect.width, frame_rect.height); - return FALSE; - } - - return TRUE; -} - -static gboolean -test_case_check_xserver_stacking (TestCase *test, - GError **error) -{ - MetaDisplay *display = meta_get_display (); - GString *local_string = g_string_new (NULL); - GString *x11_string = g_string_new (NULL); - int i; - - if (!display->x11_display) - return TRUE; - - guint64 *windows; - int n_windows; - meta_stack_tracker_get_stack (display->stack_tracker, &windows, &n_windows); - - for (i = 0; i < n_windows; i++) - { - if (META_STACK_ID_IS_X11 (windows[i])) - { - if (local_string->len > 0) - g_string_append_c (local_string, ' '); - - g_string_append_printf (local_string, "%#lx", (Window)windows[i]); - } - } - - Window root; - Window parent; - Window *children; - unsigned int n_children; - XQueryTree (display->x11_display->xdisplay, - display->x11_display->xroot, - &root, &parent, &children, &n_children); - - for (i = 0; i < (int)n_children; i++) - { - if (x11_string->len > 0) - g_string_append_c (x11_string, ' '); - - g_string_append_printf (x11_string, "%#lx", (Window)children[i]); - } - - if (strcmp (x11_string->str, local_string->str) != 0) - g_set_error (error, - META_TEST_CLIENT_ERROR, - META_TEST_CLIENT_ERROR_ASSERTION_FAILED, - "xserver stacking: x11='%s', local='%s'", - x11_string->str, local_string->str); - - XFree (children); - - g_string_free (local_string, TRUE); - g_string_free (x11_string, TRUE); - - return *error == NULL; -} - -static int -maybe_divide (const char *str, - int value) -{ - if (strstr (str, "/") == str) - { - int divisor; - - str += 1; - divisor = atoi (str); - - value /= divisor; - } - - return value; -} - -static int -parse_window_size (MetaWindow *window, - const char *size_str) -{ - MetaLogicalMonitor *logical_monitor; - MetaRectangle logical_monitor_layout; - int value; - - logical_monitor = meta_window_calculate_main_logical_monitor (window); - g_assert_nonnull (logical_monitor); - - logical_monitor_layout = meta_logical_monitor_get_layout (logical_monitor); - - if (strstr (size_str, "MONITOR_WIDTH") == size_str) - { - value = logical_monitor_layout.width; - size_str += strlen ("MONITOR_WIDTH"); - value = maybe_divide (size_str, value); - } - else if (strstr (size_str, "MONITOR_HEIGHT") == size_str) - { - value = logical_monitor_layout.height; - size_str += strlen ("MONITOR_HEIGHT"); - value = maybe_divide (size_str, value); - } - else - { - value = atoi (size_str); - } - - return value; -} - -static gboolean -test_case_do (TestCase *test, - int argc, - char **argv, - GError **error) -{ - if (strcmp (argv[0], "new_client") == 0) - { - MetaWindowClientType type; - MetaTestClient *client; - - if (argc != 3) - BAD_COMMAND("usage: new_client [wayland|x11]"); - - if (strcmp (argv[2], "x11") == 0) - type = META_WINDOW_CLIENT_TYPE_X11; - else if (strcmp (argv[2], "wayland") == 0) - type = META_WINDOW_CLIENT_TYPE_WAYLAND; - else - BAD_COMMAND("usage: new_client [wayland|x11]"); - - if (g_hash_table_lookup (test->clients, argv[1])) - BAD_COMMAND("client %s already exists", argv[1]); - - client = meta_test_client_new (test->context, argv[1], type, error); - if (!client) - return FALSE; - - g_hash_table_insert (test->clients, meta_test_client_get_id (client), client); - } - else if (strcmp (argv[0], "quit_client") == 0) - { - if (argc != 2) - BAD_COMMAND("usage: quit_client "); - - MetaTestClient *client = test_case_lookup_client (test, argv[1], error); - if (!client) - return FALSE; - - if (!meta_test_client_quit (client, error)) - return FALSE; - - g_hash_table_remove (test->clients, meta_test_client_get_id (client)); - meta_test_client_destroy (client); - } - else if (strcmp (argv[0], "create") == 0) - { - if (!(argc == 2 || - (argc == 3 && strcmp (argv[2], "override") == 0) || - (argc == 3 && strcmp (argv[2], "csd") == 0))) - BAD_COMMAND("usage: %s / [override|csd]", argv[0]); - - MetaTestClient *client; - const char *window_id; - if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error)) - return FALSE; - - if (!meta_test_client_do (client, error, - "create", window_id, - argc == 3 ? argv[2] : NULL, - NULL)) - return FALSE; - - if (!meta_test_client_wait (client, error)) - return FALSE; - } - else if (strcmp (argv[0], "set_parent") == 0 || - strcmp (argv[0], "set_parent_exported") == 0) - { - if (argc != 3) - BAD_COMMAND("usage: %s / ", - argv[0]); - - MetaTestClient *client; - const char *window_id; - if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error)) - return FALSE; - - if (!meta_test_client_do (client, error, - argv[0], window_id, - argv[2], - NULL)) - return FALSE; - } - else if (strcmp (argv[0], "accept_focus") == 0) - { - if (argc != 3 || - (g_ascii_strcasecmp (argv[2], "true") != 0 && - g_ascii_strcasecmp (argv[2], "false") != 0)) - BAD_COMMAND("usage: %s / [true|false]", - argv[0]); - - MetaTestClient *client; - const char *window_id; - if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error)) - return FALSE; - - if (!meta_test_client_do (client, error, - argv[0], window_id, - argv[2], - NULL)) - return FALSE; - } - else if (strcmp (argv[0], "can_take_focus") == 0) - { - if (argc != 3 || - (g_ascii_strcasecmp (argv[2], "true") != 0 && - g_ascii_strcasecmp (argv[2], "false") != 0)) - BAD_COMMAND("usage: %s / [true|false]", - argv[0]); - - MetaTestClient *client; - const char *window_id; - if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error)) - return FALSE; - - if (!meta_test_client_do (client, error, - argv[0], window_id, - argv[2], - NULL)) - return FALSE; - } - else if (strcmp (argv[0], "accept_take_focus") == 0) - { - if (argc != 3 || - (g_ascii_strcasecmp (argv[2], "true") != 0 && - g_ascii_strcasecmp (argv[2], "false") != 0)) - BAD_COMMAND("usage: %s / [true|false]", - argv[0]); - - MetaTestClient *client; - const char *window_id; - if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error)) - return FALSE; - - if (!meta_test_client_do (client, error, - argv[0], window_id, - argv[2], - NULL)) - return FALSE; - } - else if (strcmp (argv[0], "show") == 0) - { - MetaWindow *window; - gboolean show_async = FALSE; - - if (argc != 2 && argc != 3) - BAD_COMMAND("usage: %s / [async]", argv[0]); - - if (argc == 3 && strcmp (argv[2], "async") == 0) - show_async = TRUE; - - MetaTestClient *client; - const char *window_id; - if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error)) - return FALSE; - - if (!meta_test_client_do (client, error, argv[0], window_id, NULL)) - return FALSE; - - if (!test_case_wait (test, error)) - return FALSE; - - window = meta_test_client_find_window (client, window_id, error); - if (!window) - return FALSE; - - if (!show_async) - meta_test_client_wait_for_window_shown (client, window); - } - else if (strcmp (argv[0], "resize") == 0) - { - if (argc != 4) - BAD_COMMAND("usage: %s / width height", argv[0]); - - MetaTestClient *client; - const char *window_id; - if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error)) - return FALSE; - - if (!meta_test_client_do (client, error, argv[0], window_id, - argv[2], argv[3], NULL)) - return FALSE; - } - else if (strcmp (argv[0], "move") == 0) - { - MetaWindow *window; - - if (argc != 4) - BAD_COMMAND("usage: %s / x y", argv[0]); - - MetaTestClient *client; - const char *window_id; - if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error)) - return FALSE; - - window = meta_test_client_find_window (client, window_id, error); - if (!window) - return FALSE; - - meta_window_move_frame (window, TRUE, atoi (argv[2]), atoi (argv[3])); - } - else if (strcmp (argv[0], "tile") == 0) - { - MetaWindow *window; - - if (argc != 3) - BAD_COMMAND("usage: %s / [right|left]", argv[0]); - - MetaTestClient *client; - const char *window_id; - if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error)) - return FALSE; - - window = meta_test_client_find_window (client, window_id, error); - if (!window) - return FALSE; - - MetaTileMode tile_mode; - if (strcmp (argv[2], "right") == 0) - { - tile_mode = META_TILE_RIGHT; - } - else if (strcmp (argv[2], "left") == 0) - { - tile_mode = META_TILE_LEFT; - } - else - { - g_set_error (error, - META_TEST_CLIENT_ERROR, - META_TEST_CLIENT_ERROR_ASSERTION_FAILED, - "Invalid tile mode '%s'", argv[2]); - return FALSE; - } - - meta_window_tile (window, tile_mode); - } - else if (strcmp (argv[0], "untile") == 0) - { - MetaWindow *window; - - if (argc != 2) - BAD_COMMAND("usage: %s /", argv[0]); - - MetaTestClient *client; - const char *window_id; - if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error)) - return FALSE; - - window = meta_test_client_find_window (client, window_id, error); - if (!window) - return FALSE; - - meta_window_untile (window); - } - else if (strcmp (argv[0], "hide") == 0 || - strcmp (argv[0], "activate") == 0 || - strcmp (argv[0], "raise") == 0 || - strcmp (argv[0], "lower") == 0 || - strcmp (argv[0], "minimize") == 0 || - strcmp (argv[0], "unminimize") == 0 || - strcmp (argv[0], "maximize") == 0 || - strcmp (argv[0], "unmaximize") == 0 || - strcmp (argv[0], "fullscreen") == 0 || - strcmp (argv[0], "unfullscreen") == 0 || - strcmp (argv[0], "freeze") == 0 || - strcmp (argv[0], "thaw") == 0 || - strcmp (argv[0], "destroy") == 0) - { - if (argc != 2) - BAD_COMMAND("usage: %s /", argv[0]); - - MetaTestClient *client; - const char *window_id; - if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error)) - return FALSE; - - if (!meta_test_client_do (client, error, argv[0], window_id, NULL)) - return FALSE; - } - else if (strcmp (argv[0], "local_activate") == 0) - { - MetaWindow *window; - - if (argc != 2) - BAD_COMMAND("usage: %s /", argv[0]); - - MetaTestClient *client; - const char *window_id; - if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error)) - return FALSE; - - window = meta_test_client_find_window (client, window_id, error); - if (!window) - return FALSE; - - meta_window_activate (window, 0); - } - else if (strcmp (argv[0], "wait") == 0) - { - if (argc != 1) - BAD_COMMAND("usage: %s", argv[0]); - - if (!test_case_wait (test, error)) - return FALSE; - } - else if (strcmp (argv[0], "wait_reconfigure") == 0) - { - if (argc != 1) - BAD_COMMAND("usage: %s", argv[0]); - - /* - * Wait twice, so that we - * 1) First wait for any requests to configure being made - * 2) Then wait until the new configuration has been applied - */ - - if (!test_case_wait (test, error)) - return FALSE; - if (!test_case_dispatch (test, error)) - return FALSE; - if (!test_case_wait (test, error)) - return FALSE; - } - else if (strcmp (argv[0], "dispatch") == 0) - { - if (argc != 1) - BAD_COMMAND("usage: %s", argv[0]); - - if (!test_case_dispatch (test, error)) - return FALSE; - } - else if (strcmp (argv[0], "sleep") == 0) - { - guint64 interval; - - if (argc != 2) - BAD_COMMAND("usage: %s ", argv[0]); - - if (!g_ascii_string_to_unsigned (argv[1], 10, 0, G_MAXUINT32, - &interval, error)) - return FALSE; - - if (!test_case_sleep (test, (guint32) interval, error)) - return FALSE; - } - else if (strcmp (argv[0], "assert_stacking") == 0) - { - if (!test_case_assert_stacking (test, argv + 1, argc - 1, error)) - return FALSE; - - if (!test_case_check_xserver_stacking (test, error)) - return FALSE; - } - else if (strcmp (argv[0], "assert_focused") == 0) - { - if (!test_case_assert_focused (test, argv[1], error)) - return FALSE; - } - else if (strcmp (argv[0], "assert_size") == 0) - { - MetaWindow *window; - - if (argc != 4) - { - BAD_COMMAND("usage: %s / ", - argv[0]); - } - - MetaTestClient *client; - const char *window_id; - if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error)) - return FALSE; - - window = meta_test_client_find_window (client, window_id, error); - if (!window) - return FALSE; - - if (meta_window_get_frame (window)) - { - g_set_error (error, - META_TEST_CLIENT_ERROR, - META_TEST_CLIENT_ERROR_ASSERTION_FAILED, - "Can only assert size of CSD window"); - return FALSE; - } - - int width = parse_window_size (window, argv[2]); - int height = parse_window_size (window, argv[3]); - g_autofree char *width_str = g_strdup_printf ("%d", width); - g_autofree char *height_str = g_strdup_printf ("%d", height); - - if (!meta_test_client_do (client, error, argv[0], - window_id, - width_str, - height_str, - NULL)) - return FALSE; - - if (!test_case_assert_size (test, window, - width, height, - error)) - return FALSE; - } - else if (strcmp (argv[0], "assert_position") == 0) - { - MetaWindow *window; - - if (argc != 4) - { - BAD_COMMAND("usage: %s / ", - argv[0]); - } - - MetaTestClient *client; - const char *window_id; - if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error)) - return FALSE; - - window = meta_test_client_find_window (client, window_id, error); - if (!window) - return FALSE; - - MetaRectangle frame_rect; - meta_window_get_frame_rect (window, &frame_rect); - int x = atoi (argv[2]); - int y = atoi (argv[3]); - if (frame_rect.x != x || frame_rect.y != y) - { - g_set_error (error, - META_TEST_CLIENT_ERROR, - META_TEST_CLIENT_ERROR_ASSERTION_FAILED, - "Expected window position (%d, %d) doesn't match (%d, %d)", - x, y, frame_rect.x, frame_rect.y); - return FALSE; - } - } - else - { - BAD_COMMAND("Unknown command %s", argv[0]); - } - - return TRUE; -} - -static gboolean -test_case_destroy (TestCase *test, - GError **error) -{ - /* Failures when cleaning up the test case aren't recoverable, since we'll - * pollute the subsequent test cases, so we just return the error, and - * skip the rest of the cleanup. - */ - GHashTableIter iter; - gpointer key, value; - MetaDisplay *display; - - g_hash_table_iter_init (&iter, test->clients); - while (g_hash_table_iter_next (&iter, &key, &value)) - { - if (!meta_test_client_do (value, error, "destroy_all", NULL)) - return FALSE; - - } - - if (!test_case_wait (test, error)) - return FALSE; - - if (!test_case_assert_stacking (test, NULL, 0, error)) - return FALSE; - - g_hash_table_iter_init (&iter, test->clients); - while (g_hash_table_iter_next (&iter, &key, &value)) - meta_test_client_destroy (value); - - g_clear_pointer (&test->waiter, meta_async_waiter_destroy); - - display = meta_get_display (); - g_clear_signal_handler (&test->x11_display_opened_handler_id, display); - if (display->x11_display) - meta_x11_display_set_alarm_filter (display->x11_display, NULL, NULL); - - g_hash_table_destroy (test->clients); - g_free (test); - - return TRUE; -} - -/**********************************************************************/ - -static gboolean -run_test (MetaContext *context, - const char *filename, - int index) -{ - TestCase *test = test_case_new (context); - GError *error = NULL; - - GFile *file = g_file_new_for_path (filename); - - GDataInputStream *in = NULL; - - GFileInputStream *in_raw = g_file_read (file, NULL, &error); - g_object_unref (file); - if (in_raw == NULL) - goto out; - - in = g_data_input_stream_new (G_INPUT_STREAM (in_raw)); - g_object_unref (in_raw); - - int line_no = 0; - while (error == NULL) - { - char *line = g_data_input_stream_read_line_utf8 (in, NULL, NULL, &error); - if (line == NULL) - break; - - line_no++; - - int argc; - char **argv = NULL; - if (!g_shell_parse_argv (line, &argc, &argv, &error)) - { - if (g_error_matches (error, G_SHELL_ERROR, G_SHELL_ERROR_EMPTY_STRING)) - { - g_clear_error (&error); - goto next; - } - - goto next; - } - - test_case_do (test, argc, argv, &error); - - next: - if (error) - g_prefix_error (&error, "%d: ", line_no); - - g_free (line); - g_strfreev (argv); - } - - { - GError *tmp_error = NULL; - if (!g_input_stream_close (G_INPUT_STREAM (in), NULL, &tmp_error)) - { - if (error != NULL) - g_clear_error (&tmp_error); - else - g_propagate_error (&error, tmp_error); - } - } - - out: - if (in != NULL) - g_object_unref (in); - - GError *cleanup_error = NULL; - test_case_destroy (test, &cleanup_error); - - const char *testspos = strstr (filename, "tests/"); - char *pretty_name; - if (testspos) - pretty_name = g_strdup (testspos + strlen("tests/")); - else - pretty_name = g_strdup (filename); - - if (error || cleanup_error) - { - g_print ("not ok %d %s\n", index, pretty_name); - - if (error) - g_print (" %s\n", error->message); - - if (cleanup_error) - { - g_print (" Fatal Error During Cleanup\n"); - g_print (" %s\n", cleanup_error->message); - exit (1); - } - } - else - { - g_print ("ok %d %s\n", index, pretty_name); - } - - g_free (pretty_name); - - gboolean success = error == NULL; - - g_clear_error (&error); - g_clear_error (&cleanup_error); - - return success; -} - -typedef struct -{ - int n_tests; - char **tests; -} RunTestsInfo; - -static int -run_tests (MetaContext *context, - RunTestsInfo *info) -{ - int i; - gboolean success = TRUE; - - g_print ("1..%d\n", info->n_tests); - - for (i = 0; i < info->n_tests; i++) - { - if (!run_test (context, info->tests[i], i + 1)) - success = FALSE; - } - - return success ? 0 : 1; -} - -/**********************************************************************/ - -static gboolean -find_metatests_in_directory (GFile *directory, - GPtrArray *results, - GError **error) -{ - GFileEnumerator *enumerator = g_file_enumerate_children (directory, - "standard::name,standard::type", - G_FILE_QUERY_INFO_NONE, - NULL, error); - if (!enumerator) - return FALSE; - - while (*error == NULL) - { - GFileInfo *info = g_file_enumerator_next_file (enumerator, NULL, error); - if (info == NULL) - break; - - GFile *child = g_file_enumerator_get_child (enumerator, info); - switch (g_file_info_get_file_type (info)) - { - case G_FILE_TYPE_REGULAR: - { - const char *name = g_file_info_get_name (info); - if (g_str_has_suffix (name, ".metatest")) - g_ptr_array_add (results, g_file_get_path (child)); - break; - } - case G_FILE_TYPE_DIRECTORY: - find_metatests_in_directory (child, results, error); - break; - default: - break; - } - - g_object_unref (child); - g_object_unref (info); - } - - { - GError *tmp_error = NULL; - if (!g_file_enumerator_close (enumerator, NULL, &tmp_error)) - { - if (*error != NULL) - g_clear_error (&tmp_error); - else - g_propagate_error (error, tmp_error); - } - } - - g_object_unref (enumerator); - return *error == NULL; -} - -static gboolean all_tests = FALSE; - -const GOptionEntry options[] = { - { - "all", 0, 0, G_OPTION_ARG_NONE, - &all_tests, - "Run all installed tests", - NULL - }, - { NULL } -}; - -int -main (int argc, char **argv) -{ - g_autoptr (MetaContext) context = NULL; - GPtrArray *tests; - RunTestsInfo info; - - context = meta_create_test_context (META_CONTEXT_TEST_TYPE_NESTED, - META_CONTEXT_TEST_FLAG_TEST_CLIENT); - - meta_context_add_option_entries (context, options, NULL); - - g_assert (meta_context_configure (context, &argc, &argv, NULL)); - - tests = g_ptr_array_new (); - if (all_tests) - { - GFile *test_dir = g_file_new_for_path (MUTTER_PKGDATADIR "/tests"); - g_autoptr (GError) error = NULL; - - if (!find_metatests_in_directory (test_dir, tests, &error)) - { - g_printerr ("Error enumerating tests: %s\n", error->message); - return EXIT_FAILURE; - } - } - else - { - int i; - char *curdir = g_get_current_dir (); - - for (i = 1; i < argc; i++) - { - if (g_path_is_absolute (argv[i])) - g_ptr_array_add (tests, g_strdup (argv[i])); - else - g_ptr_array_add (tests, g_build_filename (curdir, argv[i], NULL)); - } - - g_free (curdir); - } - - info.tests = (char **) tests->pdata; - info.n_tests = tests->len; - g_signal_connect (context, "run-tests", G_CALLBACK (run_tests), &info); - - return meta_context_test_run_tests (META_CONTEXT_TEST (context)); -} diff --git a/src/tests/unit-tests.c b/src/tests/unit-tests.c deleted file mode 100644 index a31f50536..000000000 --- a/src/tests/unit-tests.c +++ /dev/null @@ -1,258 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015 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 . - */ - -#include "config.h" - -#include "tests/unit-tests.h" - -#include -#include - -#include -#include - -#include "core/boxes-private.h" -#include "meta-test/meta-context-test.h" -#include "meta/meta-context.h" -#include "tests/boxes-tests.h" -#include "tests/monitor-config-migration-unit-tests.h" -#include "tests/monitor-unit-tests.h" -#include "tests/monitor-store-unit-tests.h" -#include "tests/monitor-transform-tests.h" -#include "tests/wayland-unit-tests.h" - -MetaContext *test_context; - -typedef struct _MetaTestLaterOrderCallbackData -{ - GMainLoop *loop; /* Loop to terminate when done. */ - int callback_num; /* Callback number integer. */ - int *expected_callback_num; /* Pointer to the expected callback number. */ -} MetaTestLaterOrderCallbackData; - -static gboolean -test_later_order_callback (gpointer user_data) -{ - MetaTestLaterOrderCallbackData *data = user_data; - - g_assert_cmpint (data->callback_num, ==, *data->expected_callback_num); - - if (*data->expected_callback_num == 0) - g_main_loop_quit (data->loop); - else - (*data->expected_callback_num)--; - - return FALSE; -} - -static void -meta_test_util_later_order (void) -{ - GMainLoop *loop; - int expected_callback_num; - int i; - const int num_callbacks = 3; - MetaTestLaterOrderCallbackData callback_data[num_callbacks]; - - loop = g_main_loop_new (NULL, FALSE); - - /* Schedule three BEFORE_DRAW callbacks each with its own number associated - * with it. - */ - for (i = 0; i < num_callbacks; i++) - { - callback_data[i] = (MetaTestLaterOrderCallbackData) { - .loop = loop, - .callback_num = i, - .expected_callback_num = &expected_callback_num, - }; - meta_later_add (META_LATER_BEFORE_REDRAW, - test_later_order_callback, - &callback_data[i], - NULL); - } - - /* Check that the callbacks are invoked in the opposite order that they were - * scheduled. Each callback will decrease the number by 1 after it checks the - * validity. - */ - expected_callback_num = num_callbacks - 1; - g_main_loop_run (loop); - g_assert_cmpint (expected_callback_num, ==, 0); - g_main_loop_unref (loop); -} - -typedef enum _MetaTestLaterScheduleFromLaterState -{ - META_TEST_LATER_EXPECT_CALC_SHOWING, - META_TEST_LATER_EXPECT_SYNC_STACK, - META_TEST_LATER_EXPECT_BEFORE_REDRAW, - META_TEST_LATER_FINISHED, -} MetaTestLaterScheduleFromLaterState; - -typedef struct _MetaTestLaterScheduleFromLaterData -{ - GMainLoop *loop; - MetaTestLaterScheduleFromLaterState state; -} MetaTestLaterScheduleFromLaterData; - -static gboolean -test_later_schedule_from_later_sync_stack_callback (gpointer user_data); - -static gboolean -test_later_schedule_from_later_calc_showing_callback (gpointer user_data) -{ - MetaTestLaterScheduleFromLaterData *data = user_data; - - g_assert_cmpint (data->state, ==, META_TEST_LATER_EXPECT_CALC_SHOWING); - - meta_later_add (META_LATER_SYNC_STACK, - test_later_schedule_from_later_sync_stack_callback, - data, - NULL); - - data->state = META_TEST_LATER_EXPECT_SYNC_STACK; - - return FALSE; -} - -static gboolean -test_later_schedule_from_later_sync_stack_callback (gpointer user_data) -{ - MetaTestLaterScheduleFromLaterData *data = user_data; - - g_assert_cmpint (data->state, ==, META_TEST_LATER_EXPECT_SYNC_STACK); - - data->state = META_TEST_LATER_EXPECT_BEFORE_REDRAW; - - return FALSE; -} - -static gboolean -test_later_schedule_from_later_before_redraw_callback (gpointer user_data) -{ - MetaTestLaterScheduleFromLaterData *data = user_data; - - g_assert_cmpint (data->state, ==, META_TEST_LATER_EXPECT_BEFORE_REDRAW); - data->state = META_TEST_LATER_FINISHED; - g_main_loop_quit (data->loop); - - return FALSE; -} - -static void -meta_test_util_later_schedule_from_later (void) -{ - MetaTestLaterScheduleFromLaterData data; - - data.loop = g_main_loop_new (NULL, FALSE); - - /* Test that scheduling a MetaLater with 'when' being later than the one being - * invoked causes it to be invoked before any callback with a later 'when' - * value being invoked. - * - * The first and last callback is queued here. The one to be invoked in - * between is invoked in test_later_schedule_from_later_calc_showing_callback. - */ - meta_later_add (META_LATER_CALC_SHOWING, - test_later_schedule_from_later_calc_showing_callback, - &data, - NULL); - meta_later_add (META_LATER_BEFORE_REDRAW, - test_later_schedule_from_later_before_redraw_callback, - &data, - NULL); - - data.state = META_TEST_LATER_EXPECT_CALC_SHOWING; - - g_main_loop_run (data.loop); - g_main_loop_unref (data.loop); - - g_assert_cmpint (data.state, ==, META_TEST_LATER_FINISHED); -} - -static void -meta_test_adjacent_to (void) -{ - MetaRectangle base = { .x = 10, .y = 10, .width = 10, .height = 10 }; - MetaRectangle adjacent[] = { - { .x = 20, .y = 10, .width = 10, .height = 10 }, - { .x = 0, .y = 10, .width = 10, .height = 10 }, - { .x = 0, .y = 1, .width = 10, .height = 10 }, - { .x = 20, .y = 19, .width = 10, .height = 10 }, - { .x = 10, .y = 20, .width = 10, .height = 10 }, - { .x = 10, .y = 0, .width = 10, .height = 10 }, - }; - MetaRectangle not_adjacent[] = { - { .x = 0, .y = 0, .width = 10, .height = 10 }, - { .x = 20, .y = 20, .width = 10, .height = 10 }, - { .x = 21, .y = 10, .width = 10, .height = 10 }, - { .x = 10, .y = 21, .width = 10, .height = 10 }, - { .x = 10, .y = 5, .width = 10, .height = 10 }, - { .x = 11, .y = 10, .width = 10, .height = 10 }, - { .x = 19, .y = 10, .width = 10, .height = 10 }, - }; - unsigned int i; - - for (i = 0; i < G_N_ELEMENTS (adjacent); i++) - g_assert (meta_rectangle_is_adjacent_to (&base, &adjacent[i])); - - for (i = 0; i < G_N_ELEMENTS (not_adjacent); i++) - g_assert (!meta_rectangle_is_adjacent_to (&base, ¬_adjacent[i])); -} - -static void -init_tests (void) -{ - g_test_add_func ("/util/meta-later/order", meta_test_util_later_order); - g_test_add_func ("/util/meta-later/schedule-from-later", - meta_test_util_later_schedule_from_later); - - g_test_add_func ("/core/boxes/adjacent-to", meta_test_adjacent_to); - - init_monitor_store_tests (); - init_monitor_config_migration_tests (); - init_monitor_tests (); - init_boxes_tests (); - init_wayland_tests (); - init_monitor_transform_tests (); -} - -int -main (int argc, char *argv[]) -{ - g_autoptr (MetaContext) context = NULL; - - context = meta_create_test_context (META_CONTEXT_TEST_TYPE_NESTED, - META_CONTEXT_TEST_FLAG_TEST_CLIENT); - g_assert (meta_context_configure (context, &argc, &argv, NULL)); - - test_context = context; - - init_tests (); - - g_signal_connect (context, "before-tests", - G_CALLBACK (pre_run_monitor_tests), NULL); - g_signal_connect (context, "before-tests", - G_CALLBACK (pre_run_wayland_tests), NULL); - g_signal_connect (context, "after-tests", - G_CALLBACK (finish_monitor_tests), NULL); - - return meta_context_test_run_tests (META_CONTEXT_TEST (context)); -} diff --git a/src/tests/unit-tests.h b/src/tests/unit-tests.h deleted file mode 100644 index 30f24979e..000000000 --- a/src/tests/unit-tests.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2021 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 . - */ - -#ifndef UNIT_TESTS_H -#define UNIT_TESTS_H - -#include "meta/meta-context.h" - -extern MetaContext *test_context; - -#endif /* UNIT_TESTS_H */ diff --git a/src/tests/wayland-test-clients/invalid-subsurfaces.c b/src/tests/wayland-test-clients/invalid-subsurfaces.c deleted file mode 100644 index f186dfbc9..000000000 --- a/src/tests/wayland-test-clients/invalid-subsurfaces.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) 2020 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 . - */ - -#include "config.h" - -#include -#include -#include -#include - -#include "wayland-test-client-utils.h" - -#include "xdg-shell-client-protocol.h" - -static struct wl_display *display; -static struct wl_registry *registry; -static struct wl_compositor *compositor; -static struct wl_subcompositor *subcompositor; - -static void -handle_registry_global (void *data, - struct wl_registry *registry, - uint32_t id, - const char *interface, - uint32_t version) -{ - if (strcmp (interface, "wl_compositor") == 0) - { - compositor = wl_registry_bind (registry, id, &wl_compositor_interface, 1); - } - else if (strcmp (interface, "wl_subcompositor") == 0) - { - subcompositor = wl_registry_bind (registry, - id, &wl_subcompositor_interface, 1); - } -} - -static void -handle_registry_global_remove (void *data, - struct wl_registry *registry, - uint32_t name) -{ -} - -static const struct wl_registry_listener registry_listener = { - handle_registry_global, - handle_registry_global_remove -}; - -static void -connect_to_display (void) -{ - g_assert_null (display); - g_assert_null (registry); - g_assert_null (subcompositor); - - display = wl_display_connect (NULL); - g_assert_nonnull (display); - registry = wl_display_get_registry (display); - g_assert_nonnull (registry); - wl_registry_add_listener (registry, ®istry_listener, NULL); - - g_assert_cmpint (wl_display_roundtrip (display), !=, -1); - - g_assert_nonnull (subcompositor); -} - -static void -clean_up_display (void) -{ - wl_display_disconnect (display); - display = NULL; - registry = NULL; - subcompositor = NULL; -} - -static void -test_circular_subsurfaces1 (void) -{ - struct wl_surface *surface1; - struct wl_subsurface *subsurface1; - struct wl_surface *surface2; - struct wl_subsurface *subsurface2; - - connect_to_display (); - - surface1 = wl_compositor_create_surface (compositor); - surface2 = wl_compositor_create_surface (compositor); - g_assert_nonnull (surface1); - g_assert_nonnull (surface2); - - subsurface1 = wl_subcompositor_get_subsurface (subcompositor, - surface1, - surface2); - subsurface2 = wl_subcompositor_get_subsurface (subcompositor, - surface2, - surface1); - g_assert_nonnull (subsurface1); - g_assert_nonnull (subsurface2); - - g_assert_cmpint (wl_display_roundtrip (display), ==, -1); - - clean_up_display (); -} - -static void -test_circular_subsurfaces2 (void) -{ - struct wl_surface *surface1; - struct wl_subsurface *subsurface1; - struct wl_surface *surface2; - struct wl_subsurface *subsurface2; - struct wl_surface *surface3; - struct wl_subsurface *subsurface3; - - connect_to_display (); - - surface1 = wl_compositor_create_surface (compositor); - surface2 = wl_compositor_create_surface (compositor); - surface3 = wl_compositor_create_surface (compositor); - g_assert_nonnull (surface1); - g_assert_nonnull (surface2); - g_assert_nonnull (surface3); - - subsurface1 = wl_subcompositor_get_subsurface (subcompositor, - surface1, - surface2); - subsurface2 = wl_subcompositor_get_subsurface (subcompositor, - surface2, - surface3); - subsurface3 = wl_subcompositor_get_subsurface (subcompositor, - surface3, - surface1); - g_assert_nonnull (subsurface1); - g_assert_nonnull (subsurface2); - g_assert_nonnull (subsurface3); - - g_assert_cmpint (wl_display_roundtrip (display), ==, -1); - - clean_up_display (); -} - -int -main (int argc, - char **argv) -{ - test_circular_subsurfaces1 (); - test_circular_subsurfaces2 (); - - return EXIT_SUCCESS; -} diff --git a/src/tests/wayland-test-clients/invalid-xdg-shell-actions.c b/src/tests/wayland-test-clients/invalid-xdg-shell-actions.c deleted file mode 100644 index 67ff3671e..000000000 --- a/src/tests/wayland-test-clients/invalid-xdg-shell-actions.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (C) 2020 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 . - */ - -#include "config.h" - -#include -#include -#include -#include - -#include "wayland-test-client-utils.h" - -#include "test-driver-client-protocol.h" -#include "xdg-shell-client-protocol.h" - -static struct wl_display *display; -static struct wl_registry *registry; -static struct wl_compositor *compositor; -static struct xdg_wm_base *xdg_wm_base; -static struct wl_shm *shm; - -static struct wl_surface *surface; -static struct xdg_surface *xdg_surface; -static struct xdg_toplevel *xdg_toplevel; - -static gboolean running; - -static void -init_surface (void) -{ - xdg_toplevel_set_title (xdg_toplevel, "bogus window geometry"); - wl_surface_commit (surface); -} - -static void -handle_buffer_release (void *data, - struct wl_buffer *buffer) -{ - wl_buffer_destroy (buffer); -} - -static const struct wl_buffer_listener buffer_listener = { - handle_buffer_release -}; - -static gboolean -create_shm_buffer (int width, - int height, - struct wl_buffer **out_buffer, - void **out_data, - int *out_size) -{ - struct wl_shm_pool *pool; - static struct wl_buffer *buffer; - int fd, size, stride; - int bytes_per_pixel; - void *data; - - bytes_per_pixel = 4; - stride = width * bytes_per_pixel; - size = stride * height; - - fd = create_anonymous_file (size); - if (fd < 0) - { - fprintf (stderr, "Creating a buffer file for %d B failed: %m\n", - size); - return FALSE; - } - - data = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (data == MAP_FAILED) - { - fprintf (stderr, "mmap failed: %m\n"); - close (fd); - return FALSE; - } - - pool = wl_shm_create_pool (shm, fd, size); - buffer = wl_shm_pool_create_buffer (pool, 0, - width, height, - stride, - WL_SHM_FORMAT_ARGB8888); - wl_buffer_add_listener (buffer, &buffer_listener, buffer); - wl_shm_pool_destroy (pool); - close (fd); - - *out_buffer = buffer; - *out_data = data; - *out_size = size; - - return TRUE; -} - -static void -fill (void *buffer_data, - int width, - int height, - uint32_t color) -{ - uint32_t *pixels = buffer_data; - int x, y; - - for (y = 0; y < height; y++) - { - for (x = 0; x < width; x++) - pixels[y * width + x] = color; - } -} - -static void -draw (struct wl_surface *surface, - int width, - int height, - uint32_t color) -{ - struct wl_buffer *buffer; - void *buffer_data; - int size; - - if (!create_shm_buffer (width, height, - &buffer, &buffer_data, &size)) - g_error ("Failed to create shm buffer"); - - fill (buffer_data, width, height, color); - - wl_surface_attach (surface, buffer, 0, 0); -} - -static void -draw_main (void) -{ - draw (surface, 700, 500, 0xff00ff00); -} - -static void -handle_xdg_toplevel_configure (void *data, - struct xdg_toplevel *xdg_toplevel, - int32_t width, - int32_t height, - struct wl_array *state) -{ -} - -static void -handle_xdg_toplevel_close (void *data, - struct xdg_toplevel *xdg_toplevel) -{ - g_assert_not_reached (); -} - -static const struct xdg_toplevel_listener xdg_toplevel_listener = { - handle_xdg_toplevel_configure, - handle_xdg_toplevel_close, -}; - -static void -handle_xdg_surface_configure (void *data, - struct xdg_surface *xdg_surface, - uint32_t serial) -{ - xdg_surface_set_window_geometry (xdg_surface, 0, 0, 0, 0); - draw_main (); - wl_surface_commit (surface); - - g_assert_cmpint (wl_display_roundtrip (display), !=, -1); - running = FALSE; -} - -static const struct xdg_surface_listener xdg_surface_listener = { - handle_xdg_surface_configure, -}; - -static void -handle_xdg_wm_base_ping (void *data, - struct xdg_wm_base *xdg_wm_base, - uint32_t serial) -{ - xdg_wm_base_pong (xdg_wm_base, serial); -} - -static const struct xdg_wm_base_listener xdg_wm_base_listener = { - handle_xdg_wm_base_ping, -}; - -static void -handle_registry_global (void *data, - struct wl_registry *registry, - uint32_t id, - const char *interface, - uint32_t version) -{ - if (strcmp (interface, "wl_compositor") == 0) - { - compositor = wl_registry_bind (registry, id, &wl_compositor_interface, 1); - } - else if (strcmp (interface, "xdg_wm_base") == 0) - { - xdg_wm_base = wl_registry_bind (registry, id, - &xdg_wm_base_interface, 1); - xdg_wm_base_add_listener (xdg_wm_base, &xdg_wm_base_listener, NULL); - } - else if (strcmp (interface, "wl_shm") == 0) - { - shm = wl_registry_bind (registry, - id, &wl_shm_interface, 1); - } -} - -static void -handle_registry_global_remove (void *data, - struct wl_registry *registry, - uint32_t name) -{ -} - -static const struct wl_registry_listener registry_listener = { - handle_registry_global, - handle_registry_global_remove -}; - -static void -test_empty_window_geometry (void) -{ - display = wl_display_connect (NULL); - registry = wl_display_get_registry (display); - wl_registry_add_listener (registry, ®istry_listener, NULL); - wl_display_roundtrip (display); - - g_assert_nonnull (shm); - g_assert_nonnull (xdg_wm_base); - - wl_display_roundtrip (display); - - surface = wl_compositor_create_surface (compositor); - xdg_surface = xdg_wm_base_get_xdg_surface (xdg_wm_base, surface); - xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); - xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); - xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); - - init_surface (); - - running = TRUE; - while (running) - { - if (wl_display_dispatch (display) == -1) - return; - } - - g_clear_pointer (&xdg_toplevel, xdg_toplevel_destroy); - g_clear_pointer (&xdg_surface, xdg_surface_destroy); - g_clear_pointer (&xdg_wm_base, xdg_wm_base_destroy); - g_clear_pointer (&compositor, wl_compositor_destroy); - g_clear_pointer (&shm, wl_shm_destroy); - g_clear_pointer (®istry, wl_registry_destroy); - g_clear_pointer (&display, wl_display_disconnect); -} - -int -main (int argc, - char **argv) -{ - test_empty_window_geometry (); - - return EXIT_SUCCESS; -} diff --git a/src/tests/wayland-test-clients/meson.build b/src/tests/wayland-test-clients/meson.build deleted file mode 100644 index e26325d70..000000000 --- a/src/tests/wayland-test-clients/meson.build +++ /dev/null @@ -1,70 +0,0 @@ -wayland_test_client_installed_tests_libexecdir = join_paths( - mutter_installed_tests_libexecdir, - 'wayland-test-clients', -) - -test_driver_server_header = custom_target( - 'test-driver server header', - input: 'test-driver.xml', - output: 'test-driver-server-protocol.h', - command: [ - wayland_scanner, - 'server-header', - '@INPUT@', '@OUTPUT@', - ] -) - -test_driver_client_header = custom_target( - 'test-driver client header', - input: 'test-driver.xml', - output: 'test-driver-client-protocol.h', - command: [ - wayland_scanner, - 'client-header', - '@INPUT@', '@OUTPUT@', - ] -) - -test_driver_protocol_code = custom_target( - 'test-driver source', - input: 'test-driver.xml', - output: 'test-driver-protocol.c', - command: [ - wayland_scanner, - 'private-code', - '@INPUT@', '@OUTPUT@', - ] -) - -common_sources = [ - 'wayland-test-client-utils.c', - 'wayland-test-client-utils.h', - wayland_protocol_client_headers, - wayland_protocol_sources, - test_driver_client_header, - test_driver_protocol_code, -] - -wayland_test_clients = [ - 'subsurface-remap-toplevel', - 'invalid-subsurfaces', - 'invalid-xdg-shell-actions', - 'xdg-apply-limits', -] - -foreach test : wayland_test_clients - executable(test, - sources: [ - '@0@.c'.format(test), - common_sources, - ], - include_directories: tests_includes, - c_args: tests_c_args, - dependencies: [ - glib_dep, - wayland_client_dep, - ], - install: have_installed_tests, - install_dir: wayland_test_client_installed_tests_libexecdir, - ) -endforeach diff --git a/src/tests/wayland-test-clients/subsurface-remap-toplevel.c b/src/tests/wayland-test-clients/subsurface-remap-toplevel.c deleted file mode 100644 index 25ff3a2d1..000000000 --- a/src/tests/wayland-test-clients/subsurface-remap-toplevel.c +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Copyright (C) 2019 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 . - */ - -#include "config.h" - -#include -#include -#include -#include - -#include "wayland-test-client-utils.h" - -#include "test-driver-client-protocol.h" -#include "xdg-shell-client-protocol.h" - -typedef enum _State -{ - STATE_INIT = 0, - STATE_WAIT_FOR_CONFIGURE_1, - STATE_WAIT_FOR_FRAME_1, - STATE_WAIT_FOR_ACTOR_DESTROYED, - STATE_WAIT_FOR_CONFIGURE_2, - STATE_WAIT_FOR_FRAME_2 -} State; - -static struct wl_display *display; -static struct wl_registry *registry; -static struct wl_compositor *compositor; -static struct wl_subcompositor *subcompositor; -static struct xdg_wm_base *xdg_wm_base; -static struct wl_shm *shm; -static struct test_driver *test_driver; - -static struct wl_surface *surface; -static struct xdg_surface *xdg_surface; -static struct xdg_toplevel *xdg_toplevel; - -static struct wl_surface *subsurface_surface; -static struct wl_subsurface *subsurface; - -static struct wl_callback *frame_callback; - -static gboolean running; - -static State state; - -static void -init_surface (void) -{ - xdg_toplevel_set_title (xdg_toplevel, "gradient-test"); - wl_surface_commit (surface); -} - -static void -actor_destroyed (void *data, - struct wl_callback *callback, - uint32_t serial) -{ - g_assert_cmpint (state, ==, STATE_WAIT_FOR_ACTOR_DESTROYED); - - init_surface (); - state = STATE_WAIT_FOR_CONFIGURE_2; - - wl_callback_destroy (callback); -} - -static const struct wl_callback_listener actor_destroy_listener = { - actor_destroyed, -}; - -static void -reset_surface (void) -{ - struct wl_callback *callback; - - callback = test_driver_sync_actor_destroyed (test_driver, surface); - wl_callback_add_listener (callback, &actor_destroy_listener, NULL); - - wl_surface_attach (surface, NULL, 0, 0); - wl_surface_commit (surface); - - state = STATE_WAIT_FOR_ACTOR_DESTROYED; -} - -static void -handle_buffer_release (void *data, - struct wl_buffer *buffer) -{ - wl_buffer_destroy (buffer); -} - -static const struct wl_buffer_listener buffer_listener = { - handle_buffer_release -}; - -static gboolean -create_shm_buffer (int width, - int height, - struct wl_buffer **out_buffer, - void **out_data, - int *out_size) -{ - struct wl_shm_pool *pool; - static struct wl_buffer *buffer; - int fd, size, stride; - int bytes_per_pixel; - void *data; - - bytes_per_pixel = 4; - stride = width * bytes_per_pixel; - size = stride * height; - - fd = create_anonymous_file (size); - if (fd < 0) - { - fprintf (stderr, "Creating a buffer file for %d B failed: %m\n", - size); - return FALSE; - } - - data = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (data == MAP_FAILED) - { - fprintf (stderr, "mmap failed: %m\n"); - close (fd); - return FALSE; - } - - pool = wl_shm_create_pool (shm, fd, size); - buffer = wl_shm_pool_create_buffer (pool, 0, - width, height, - stride, - WL_SHM_FORMAT_ARGB8888); - wl_buffer_add_listener (buffer, &buffer_listener, buffer); - wl_shm_pool_destroy (pool); - close (fd); - - *out_buffer = buffer; - *out_data = data; - *out_size = size; - - return TRUE; -} - -static void -fill (void *buffer_data, - int width, - int height, - uint32_t color) -{ - uint32_t *pixels = buffer_data; - int x, y; - - for (y = 0; y < height; y++) - { - for (x = 0; x < width; x++) - pixels[y * width + x] = color; - } -} - -static void -draw (struct wl_surface *surface, - int width, - int height, - uint32_t color) -{ - struct wl_buffer *buffer; - void *buffer_data; - int size; - - if (!create_shm_buffer (width, height, - &buffer, &buffer_data, &size)) - g_error ("Failed to create shm buffer"); - - fill (buffer_data, width, height, color); - - wl_surface_attach (surface, buffer, 0, 0); -} - -static void -draw_main (void) -{ - draw (surface, 700, 500, 0xff00ff00); -} - -static void -draw_subsurface (void) -{ - draw (subsurface_surface, 500, 300, 0xff007f00); -} - -static void -handle_xdg_toplevel_configure (void *data, - struct xdg_toplevel *xdg_toplevel, - int32_t width, - int32_t height, - struct wl_array *state) -{ -} - -static void -handle_xdg_toplevel_close(void *data, - struct xdg_toplevel *xdg_toplevel) -{ - g_assert_not_reached (); -} - -static const struct xdg_toplevel_listener xdg_toplevel_listener = { - handle_xdg_toplevel_configure, - handle_xdg_toplevel_close, -}; - -static void -handle_frame_callback (void *data, - struct wl_callback *callback, - uint32_t time) -{ - switch (state) - { - case STATE_WAIT_FOR_FRAME_1: - reset_surface (); - break; - case STATE_WAIT_FOR_FRAME_2: - exit (EXIT_SUCCESS); - case STATE_INIT: - g_assert_not_reached (); - case STATE_WAIT_FOR_CONFIGURE_1: - g_assert_not_reached (); - case STATE_WAIT_FOR_ACTOR_DESTROYED: - g_assert_not_reached (); - case STATE_WAIT_FOR_CONFIGURE_2: - g_assert_not_reached (); - } -} - -static const struct wl_callback_listener frame_listener = { - handle_frame_callback, -}; - -static void -handle_xdg_surface_configure (void *data, - struct xdg_surface *xdg_surface, - uint32_t serial) -{ - switch (state) - { - case STATE_INIT: - g_assert_not_reached (); - case STATE_WAIT_FOR_CONFIGURE_1: - draw_main (); - state = STATE_WAIT_FOR_FRAME_1; - break; - case STATE_WAIT_FOR_CONFIGURE_2: - draw_main (); - state = STATE_WAIT_FOR_FRAME_2; - break; - case STATE_WAIT_FOR_ACTOR_DESTROYED: - g_assert_not_reached (); - case STATE_WAIT_FOR_FRAME_1: - case STATE_WAIT_FOR_FRAME_2: - /* ignore */ - return; - } - - xdg_surface_ack_configure (xdg_surface, serial); - frame_callback = wl_surface_frame (surface); - wl_callback_add_listener (frame_callback, &frame_listener, NULL); - wl_surface_commit (surface); - wl_display_flush (display); -} - -static const struct xdg_surface_listener xdg_surface_listener = { - handle_xdg_surface_configure, -}; - -static void -handle_xdg_wm_base_ping (void *data, - struct xdg_wm_base *xdg_wm_base, - uint32_t serial) -{ - xdg_wm_base_pong (xdg_wm_base, serial); -} - -static const struct xdg_wm_base_listener xdg_wm_base_listener = { - handle_xdg_wm_base_ping, -}; - -static void -handle_registry_global (void *data, - struct wl_registry *registry, - uint32_t id, - const char *interface, - uint32_t version) -{ - if (strcmp (interface, "wl_compositor") == 0) - { - compositor = wl_registry_bind (registry, id, &wl_compositor_interface, 1); - } - else if (strcmp (interface, "wl_subcompositor") == 0) - { - subcompositor = wl_registry_bind (registry, - id, &wl_subcompositor_interface, 1); - } - else if (strcmp (interface, "xdg_wm_base") == 0) - { - xdg_wm_base = wl_registry_bind (registry, id, - &xdg_wm_base_interface, 1); - xdg_wm_base_add_listener (xdg_wm_base, &xdg_wm_base_listener, NULL); - } - else if (strcmp (interface, "wl_shm") == 0) - { - shm = wl_registry_bind (registry, - id, &wl_shm_interface, 1); - } - else if (strcmp (interface, "test_driver") == 0) - { - test_driver = wl_registry_bind (registry, id, &test_driver_interface, 1); - } -} - -static void -handle_registry_global_remove (void *data, - struct wl_registry *registry, - uint32_t name) -{ -} - -static const struct wl_registry_listener registry_listener = { - handle_registry_global, - handle_registry_global_remove -}; - -int -main (int argc, - char **argv) -{ - display = wl_display_connect (NULL); - registry = wl_display_get_registry (display); - wl_registry_add_listener (registry, ®istry_listener, NULL); - wl_display_roundtrip (display); - - if (!shm) - { - fprintf (stderr, "No wl_shm global\n"); - return EXIT_FAILURE; - } - - if (!xdg_wm_base) - { - fprintf (stderr, "No xdg_wm_base global\n"); - return EXIT_FAILURE; - } - - wl_display_roundtrip (display); - - g_assert_nonnull (test_driver); - - surface = wl_compositor_create_surface (compositor); - xdg_surface = xdg_wm_base_get_xdg_surface (xdg_wm_base, surface); - xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); - xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); - xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); - - subsurface_surface = wl_compositor_create_surface (compositor); - subsurface = wl_subcompositor_get_subsurface (subcompositor, - subsurface_surface, - surface); - wl_subsurface_set_position (subsurface, 100, 100); - draw_subsurface (); - wl_surface_commit (subsurface_surface); - - init_surface (); - state = STATE_WAIT_FOR_CONFIGURE_1; - - running = TRUE; - while (running) - { - if (wl_display_dispatch (display) == -1) - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} diff --git a/src/tests/wayland-test-clients/test-driver.xml b/src/tests/wayland-test-clients/test-driver.xml deleted file mode 100644 index 2433cf111..000000000 --- a/src/tests/wayland-test-clients/test-driver.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/tests/wayland-test-clients/wayland-test-client-utils.c b/src/tests/wayland-test-clients/wayland-test-client-utils.c deleted file mode 100644 index 9deb122cb..000000000 --- a/src/tests/wayland-test-clients/wayland-test-client-utils.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright © 2012 Collabora, Ltd. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "wayland-test-client-utils.h" - -#include -#include -#include -#include -#include - -static int -create_tmpfile_cloexec (char *tmpname) -{ - int fd; - - fd = mkostemp (tmpname, O_CLOEXEC); - if (fd >= 0) - unlink (tmpname); - - return fd; -} - -int -create_anonymous_file (off_t size) -{ - static const char template[] = "/wayland-test-client-shared-XXXXXX"; - const char *path; - char *name; - int fd; - int ret; - - path = getenv ("XDG_RUNTIME_DIR"); - if (!path) - { - errno = ENOENT; - return -1; - } - - name = malloc (strlen (path) + sizeof (template)); - if (!name) - return -1; - - strcpy (name, path); - strcat (name, template); - - fd = create_tmpfile_cloexec (name); - - free (name); - - if (fd < 0) - return -1; - - do - ret = posix_fallocate (fd, 0, size); - while (ret == EINTR); - - if (ret != 0) - { - close (fd); - errno = ret; - return -1; - } - - return fd; -} diff --git a/src/tests/wayland-test-clients/wayland-test-client-utils.h b/src/tests/wayland-test-clients/wayland-test-client-utils.h deleted file mode 100644 index a8dcb5321..000000000 --- a/src/tests/wayland-test-clients/wayland-test-client-utils.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef WAYLAND_TEST_CLIENT_UTILS_H -#define WAYLAND_TEST_CLIENT_UTILS_H - -#include - -int create_anonymous_file (off_t size); - -#endif /* WAYLAND_TEST_CLIENT_UTILS_H */ diff --git a/src/tests/wayland-test-clients/xdg-apply-limits.c b/src/tests/wayland-test-clients/xdg-apply-limits.c deleted file mode 100644 index aa5ab6e70..000000000 --- a/src/tests/wayland-test-clients/xdg-apply-limits.c +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Copyright (C) 2021 Christian Rauch - * - * 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 . - */ - -#include "config.h" - -#include -#include -#include -#include - -#include "wayland-test-client-utils.h" - -#include "test-driver-client-protocol.h" -#include "xdg-shell-client-protocol.h" - -typedef enum _State -{ - STATE_INIT = 0, - STATE_WAIT_FOR_CONFIGURE_1, - STATE_WAIT_FOR_FRAME_1, - STATE_WAIT_FOR_ACTOR_DESTROYED, - STATE_WAIT_FOR_CONFIGURE_2, - STATE_WAIT_FOR_FRAME_2 -} State; - -static struct wl_display *display; -static struct wl_registry *registry; -static struct wl_compositor *compositor; -static struct wl_subcompositor *subcompositor; -static struct xdg_wm_base *xdg_wm_base; -static struct wl_shm *shm; -static struct test_driver *test_driver; - -static struct wl_surface *surface; -static struct xdg_surface *xdg_surface; -static struct xdg_toplevel *xdg_toplevel; - -static struct wl_surface *subsurface_surface; -static struct wl_subsurface *subsurface; - -static struct wl_callback *frame_callback; - -static gboolean running; - -static State state; - -static void -init_surface (void) -{ - xdg_toplevel_set_title (xdg_toplevel, "toplevel-limits-test"); - wl_surface_commit (surface); -} - -static void -actor_destroyed (void *data, - struct wl_callback *callback, - uint32_t serial) -{ - g_assert_cmpint (state, ==, STATE_WAIT_FOR_ACTOR_DESTROYED); - - init_surface (); - state = STATE_WAIT_FOR_CONFIGURE_2; - - wl_callback_destroy (callback); -} - -static const struct wl_callback_listener actor_destroy_listener = { - actor_destroyed, -}; - -static void -reset_surface (void) -{ - struct wl_callback *callback; - - if (test_driver) - { - callback = test_driver_sync_actor_destroyed (test_driver, surface); - wl_callback_add_listener (callback, &actor_destroy_listener, NULL); - } - - wl_surface_attach (surface, NULL, 0, 0); - wl_surface_commit (surface); - - state = STATE_WAIT_FOR_ACTOR_DESTROYED; -} - -static void -handle_buffer_release (void *data, - struct wl_buffer *buffer) -{ - wl_buffer_destroy (buffer); -} - -static const struct wl_buffer_listener buffer_listener = { - handle_buffer_release -}; - -static gboolean -create_shm_buffer (int width, - int height, - struct wl_buffer **out_buffer, - void **out_data, - int *out_size) -{ - struct wl_shm_pool *pool; - static struct wl_buffer *buffer; - int fd, size, stride; - int bytes_per_pixel; - void *data; - - bytes_per_pixel = 4; - stride = width * bytes_per_pixel; - size = stride * height; - - fd = create_anonymous_file (size); - if (fd < 0) - { - fprintf (stderr, "Creating a buffer file for %d B failed: %m\n", - size); - return FALSE; - } - - data = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (data == MAP_FAILED) - { - fprintf (stderr, "mmap failed: %m\n"); - close (fd); - return FALSE; - } - - pool = wl_shm_create_pool (shm, fd, size); - buffer = wl_shm_pool_create_buffer (pool, 0, - width, height, - stride, - WL_SHM_FORMAT_ARGB8888); - wl_buffer_add_listener (buffer, &buffer_listener, buffer); - wl_shm_pool_destroy (pool); - close (fd); - - *out_buffer = buffer; - *out_data = data; - *out_size = size; - - return TRUE; -} - -static void -fill (void *buffer_data, - int width, - int height, - uint32_t color) -{ - uint32_t *pixels = buffer_data; - int x, y; - - for (y = 0; y < height; y++) - { - for (x = 0; x < width; x++) - pixels[y * width + x] = color; - } -} - -static void -draw (struct wl_surface *surface, - int width, - int height, - uint32_t color) -{ - struct wl_buffer *buffer; - void *buffer_data; - int size; - - if (!create_shm_buffer (width, height, - &buffer, &buffer_data, &size)) - g_error ("Failed to create shm buffer"); - - fill (buffer_data, width, height, color); - - wl_surface_attach (surface, buffer, 0, 0); -} - -static void -draw_main (void) -{ - draw (surface, 700, 500, 0xff00ff00); -} - -static void -draw_subsurface (void) -{ - draw (subsurface_surface, 500, 300, 0xff007f00); -} - -static void -handle_xdg_toplevel_configure (void *data, - struct xdg_toplevel *xdg_toplevel, - int32_t width, - int32_t height, - struct wl_array *state) -{ -} - -static void -handle_xdg_toplevel_close(void *data, - struct xdg_toplevel *xdg_toplevel) -{ - g_assert_not_reached (); -} - -static const struct xdg_toplevel_listener xdg_toplevel_listener = { - handle_xdg_toplevel_configure, - handle_xdg_toplevel_close, -}; - -static void -handle_frame_callback (void *data, - struct wl_callback *callback, - uint32_t time) -{ - switch (state) - { - case STATE_WAIT_FOR_FRAME_1: - reset_surface (); - test_driver_sync_point (test_driver, 1); - break; - case STATE_WAIT_FOR_FRAME_2: - exit (EXIT_SUCCESS); - case STATE_INIT: - g_assert_not_reached (); - case STATE_WAIT_FOR_CONFIGURE_1: - g_assert_not_reached (); - case STATE_WAIT_FOR_ACTOR_DESTROYED: - g_assert_not_reached (); - case STATE_WAIT_FOR_CONFIGURE_2: - g_assert_not_reached (); - } -} - -static const struct wl_callback_listener frame_listener = { - handle_frame_callback, -}; - -static void -handle_xdg_surface_configure (void *data, - struct xdg_surface *xdg_surface, - uint32_t serial) -{ - switch (state) - { - case STATE_INIT: - g_assert_not_reached (); - case STATE_WAIT_FOR_CONFIGURE_1: - draw_main (); - state = STATE_WAIT_FOR_FRAME_1; - break; - case STATE_WAIT_FOR_CONFIGURE_2: - draw_main (); - state = STATE_WAIT_FOR_FRAME_2; - break; - case STATE_WAIT_FOR_ACTOR_DESTROYED: - g_assert_not_reached (); - case STATE_WAIT_FOR_FRAME_1: - case STATE_WAIT_FOR_FRAME_2: - /* ignore */ - return; - } - - xdg_surface_ack_configure (xdg_surface, serial); - frame_callback = wl_surface_frame (surface); - wl_callback_add_listener (frame_callback, &frame_listener, NULL); - wl_surface_commit (surface); - wl_display_flush (display); -} - -static const struct xdg_surface_listener xdg_surface_listener = { - handle_xdg_surface_configure, -}; - -static void -handle_xdg_wm_base_ping (void *data, - struct xdg_wm_base *xdg_wm_base, - uint32_t serial) -{ - xdg_wm_base_pong (xdg_wm_base, serial); -} - -static const struct xdg_wm_base_listener xdg_wm_base_listener = { - handle_xdg_wm_base_ping, -}; - -static void -handle_registry_global (void *data, - struct wl_registry *registry, - uint32_t id, - const char *interface, - uint32_t version) -{ - if (strcmp (interface, "wl_compositor") == 0) - { - compositor = wl_registry_bind (registry, id, &wl_compositor_interface, 1); - } - else if (strcmp (interface, "wl_subcompositor") == 0) - { - subcompositor = wl_registry_bind (registry, - id, &wl_subcompositor_interface, 1); - } - else if (strcmp (interface, "xdg_wm_base") == 0) - { - xdg_wm_base = wl_registry_bind (registry, id, - &xdg_wm_base_interface, 1); - xdg_wm_base_add_listener (xdg_wm_base, &xdg_wm_base_listener, NULL); - } - else if (strcmp (interface, "wl_shm") == 0) - { - shm = wl_registry_bind (registry, - id, &wl_shm_interface, 1); - } - else if (strcmp (interface, "test_driver") == 0) - { - test_driver = wl_registry_bind (registry, id, &test_driver_interface, 1); - } -} - -static void -handle_registry_global_remove (void *data, - struct wl_registry *registry, - uint32_t name) -{ -} - -static const struct wl_registry_listener registry_listener = { - handle_registry_global, - handle_registry_global_remove -}; - -int -main (int argc, - char **argv) -{ - display = wl_display_connect (NULL); - registry = wl_display_get_registry (display); - wl_registry_add_listener (registry, ®istry_listener, NULL); - wl_display_roundtrip (display); - - if (!shm) - { - fprintf (stderr, "No wl_shm global\n"); - return EXIT_FAILURE; - } - - if (!xdg_wm_base) - { - fprintf (stderr, "No xdg_wm_base global\n"); - return EXIT_FAILURE; - } - - wl_display_roundtrip (display); - - // g_assert_nonnull (test_driver); - - surface = wl_compositor_create_surface (compositor); - xdg_surface = xdg_wm_base_get_xdg_surface (xdg_wm_base, surface); - xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); - xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); - xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); - - subsurface_surface = wl_compositor_create_surface (compositor); - subsurface = wl_subcompositor_get_subsurface (subcompositor, - subsurface_surface, - surface); - wl_subsurface_set_position (subsurface, 100, 100); - draw_subsurface (); - wl_surface_commit (subsurface_surface); - - init_surface (); - state = STATE_WAIT_FOR_CONFIGURE_1; - - /* set minimum and maximum size and commit */ - xdg_toplevel_set_min_size(xdg_toplevel, 700, 500); - xdg_toplevel_set_max_size(xdg_toplevel, 700, 500); - wl_surface_commit (surface); - - test_driver_sync_point (test_driver, 0); - - running = TRUE; - while (running) - { - if (wl_display_dispatch (display) == -1) - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; -} diff --git a/src/tests/wayland-unit-tests.c b/src/tests/wayland-unit-tests.c deleted file mode 100644 index 98c2d905a..000000000 --- a/src/tests/wayland-unit-tests.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (C) 2019 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 . - */ - -#include "config.h" - -#include "tests/wayland-unit-tests.h" - -#include - -#include "core/display-private.h" -#include "core/window-private.h" -#include "tests/meta-wayland-test-driver.h" -#include "wayland/meta-wayland.h" -#include "wayland/meta-wayland-surface.h" - -typedef struct _WaylandTestClient -{ - GSubprocess *subprocess; - char *path; - GMainLoop *main_loop; -} WaylandTestClient; - -static MetaWaylandTestDriver *test_driver; - -static char * -get_test_client_path (const char *test_client_name) -{ - return g_test_build_filename (G_TEST_BUILT, - "src", - "tests", - "wayland-test-clients", - test_client_name, - NULL); -} - -static WaylandTestClient * -wayland_test_client_new (const char *test_client_name) -{ - MetaWaylandCompositor *compositor; - const char *wayland_display_name; - g_autofree char *test_client_path = NULL; - g_autoptr (GSubprocessLauncher) launcher = NULL; - GSubprocess *subprocess; - GError *error = NULL; - WaylandTestClient *wayland_test_client; - - compositor = meta_wayland_compositor_get_default (); - wayland_display_name = meta_wayland_get_wayland_display_name (compositor); - test_client_path = get_test_client_path (test_client_name); - - launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE); - g_subprocess_launcher_setenv (launcher, - "WAYLAND_DISPLAY", wayland_display_name, - TRUE); - - subprocess = g_subprocess_launcher_spawn (launcher, - &error, - test_client_path, - NULL); - if (!subprocess) - { - g_error ("Failed to launch Wayland test client '%s': %s", - test_client_path, error->message); - } - - wayland_test_client = g_new0 (WaylandTestClient, 1); - wayland_test_client->subprocess = subprocess; - wayland_test_client->path = g_strdup (test_client_name); - wayland_test_client->main_loop = g_main_loop_new (NULL, FALSE); - - return wayland_test_client; -} - -static void -wayland_test_client_finished (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - WaylandTestClient *wayland_test_client = user_data; - GError *error = NULL; - - if (!g_subprocess_wait_finish (wayland_test_client->subprocess, - res, - &error)) - { - g_error ("Failed to wait for Wayland test client '%s': %s", - wayland_test_client->path, error->message); - } - - g_main_loop_quit (wayland_test_client->main_loop); -} - -static void -wayland_test_client_finish (WaylandTestClient *wayland_test_client) -{ - g_subprocess_wait_async (wayland_test_client->subprocess, NULL, - wayland_test_client_finished, wayland_test_client); - - g_main_loop_run (wayland_test_client->main_loop); - - g_assert_true (g_subprocess_get_successful (wayland_test_client->subprocess)); - - g_main_loop_unref (wayland_test_client->main_loop); - g_free (wayland_test_client->path); - g_object_unref (wayland_test_client->subprocess); - g_free (wayland_test_client); -} - -static MetaWindow * -find_client_window (const char *title) -{ - MetaDisplay *display = meta_get_display (); - g_autoptr (GSList) windows = NULL; - GSList *l; - - windows = meta_display_list_windows (display, META_LIST_DEFAULT); - for (l = windows; l; l = l->next) - { - MetaWindow *window = l->data; - - if (g_strcmp0 (meta_window_get_title (window), title) == 0) - return window; - } - - return NULL; -} - -static void -subsurface_remap_toplevel (void) -{ - WaylandTestClient *wayland_test_client; - - wayland_test_client = wayland_test_client_new ("subsurface-remap-toplevel"); - wayland_test_client_finish (wayland_test_client); -} - -static void -subsurface_invalid_subsurfaces (void) -{ - WaylandTestClient *wayland_test_client; - - wayland_test_client = wayland_test_client_new ("invalid-subsurfaces"); - g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, - "WL: error in client communication*"); - g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, - "WL: error in client communication*"); - wayland_test_client_finish (wayland_test_client); - g_test_assert_expected_messages (); -} - -static void -subsurface_invalid_xdg_shell_actions (void) -{ - WaylandTestClient *wayland_test_client; - - wayland_test_client = wayland_test_client_new ("invalid-xdg-shell-actions"); - g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, - "Invalid geometry * set on xdg_surface*"); - wayland_test_client_finish (wayland_test_client); - g_test_assert_expected_messages (); -} - -typedef enum _ApplyLimitState -{ - APPLY_LIMIT_STATE_INIT, - APPLY_LIMIT_STATE_RESET, - APPLY_LIMIT_STATE_FINISH, -} ApplyLimitState; - -typedef struct _ApplyLimitData -{ - GMainLoop *loop; - WaylandTestClient *wayland_test_client; - ApplyLimitState state; -} ApplyLimitData; - -static void -on_sync_point (MetaWaylandTestDriver *test_driver, - unsigned int sequence, - struct wl_client *wl_client, - ApplyLimitData *data) -{ - MetaWindow *window; - - if (sequence == 0) - g_assert (data->state == APPLY_LIMIT_STATE_INIT); - else if (sequence == 0) - g_assert (data->state == APPLY_LIMIT_STATE_RESET); - - window = find_client_window ("toplevel-limits-test"); - - if (sequence == 0) - { - g_assert_nonnull (window); - g_assert_cmpint (window->size_hints.max_width, ==, 700); - g_assert_cmpint (window->size_hints.max_height, ==, 500); - g_assert_cmpint (window->size_hints.min_width, ==, 700); - g_assert_cmpint (window->size_hints.min_height, ==, 500); - - data->state = APPLY_LIMIT_STATE_RESET; - } - else if (sequence == 1) - { - g_assert_null (window); - data->state = APPLY_LIMIT_STATE_FINISH; - g_main_loop_quit (data->loop); - } - else - { - g_assert_not_reached (); - } -} - -static void -toplevel_apply_limits (void) -{ - ApplyLimitData data = {}; - - data.loop = g_main_loop_new (NULL, FALSE); - data.wayland_test_client = wayland_test_client_new ("xdg-apply-limits"); - g_signal_connect (test_driver, "sync-point", G_CALLBACK (on_sync_point), &data); - g_main_loop_run (data.loop); - g_assert_cmpint (data.state, ==, APPLY_LIMIT_STATE_FINISH); - wayland_test_client_finish (data.wayland_test_client); - g_test_assert_expected_messages (); -} - -void -pre_run_wayland_tests (void) -{ - MetaWaylandCompositor *compositor; - - compositor = meta_wayland_compositor_get_default (); - g_assert_nonnull (compositor); - - test_driver = meta_wayland_test_driver_new (compositor); -} - -void -init_wayland_tests (void) -{ - g_test_add_func ("/wayland/subsurface/remap-toplevel", - subsurface_remap_toplevel); - g_test_add_func ("/wayland/subsurface/invalid-subsurfaces", - subsurface_invalid_subsurfaces); - g_test_add_func ("/wayland/subsurface/invalid-xdg-shell-actions", - subsurface_invalid_xdg_shell_actions); - g_test_add_func ("/wayland/toplevel/apply-limits", - toplevel_apply_limits); -} diff --git a/src/tests/wayland-unit-tests.h b/src/tests/wayland-unit-tests.h deleted file mode 100644 index b7d8d4204..000000000 --- a/src/tests/wayland-unit-tests.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2019 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 . - */ - -#ifndef WAYLAND_UNIT_TESTS_H -#define WAYLAND_UNIT_TESTS_H - -void init_wayland_tests (void); - -void pre_run_wayland_tests (void); - -#endif /* WAYLAND_UNIT_TESTS_H */ diff --git a/src/ui/frames.c b/src/ui/frames.c deleted file mode 100644 index 48b2a361c..000000000 --- a/src/ui/frames.c +++ /dev/null @@ -1,1869 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity window frame manager widget */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2003 Red Hat, Inc. - * Copyright (C) 2005, 2006 Elijah Newren - * - * 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 . - */ - -#include "config.h" - -#include -#include -#include - -#include "core/frame.h" -#include "core/window-private.h" -#include "meta/boxes.h" -#include "meta/prefs.h" -#include "meta/theme.h" -#include "meta/util.h" -#include "ui/ui.h" -#include "ui/frames.h" -#include "x11/meta-x11-window-control.h" -#include "x11/window-x11-private.h" -#include "x11/window-x11.h" - -#define DEFAULT_INNER_BUTTON_BORDER 3 - -static void meta_frames_destroy (GtkWidget *object); -static void meta_frames_finalize (GObject *object); -static void meta_frames_style_updated (GtkWidget *widget); - -static gboolean meta_frames_draw (GtkWidget *widget, - cairo_t *cr); - -static void meta_ui_frame_attach_style (MetaUIFrame *frame); - -static void meta_ui_frame_paint (MetaUIFrame *frame, - cairo_t *cr); - -static void meta_ui_frame_calc_geometry (MetaUIFrame *frame, - MetaFrameGeometry *fgeom); - -static void meta_ui_frame_update_prelit_control (MetaUIFrame *frame, - MetaFrameControl control); - -static void meta_frames_font_changed (MetaFrames *frames); -static void meta_frames_button_layout_changed (MetaFrames *frames); - - -static GdkRectangle* control_rect (MetaFrameControl control, - MetaFrameGeometry *fgeom); -static MetaFrameControl get_control (MetaUIFrame *frame, - int x, - int y); - -G_DEFINE_TYPE (MetaFrames, meta_frames, GTK_TYPE_WINDOW); - -enum -{ - META_ACTION_CLICK, - META_ACTION_RIGHT_CLICK, - META_ACTION_MIDDLE_CLICK, - META_ACTION_DOUBLE_CLICK, - META_ACTION_IGNORE -}; - -static GObject * -meta_frames_constructor (GType gtype, - guint n_properties, - GObjectConstructParam *properties) -{ - GObject *object; - GObjectClass *gobject_class; - - gobject_class = G_OBJECT_CLASS (meta_frames_parent_class); - object = gobject_class->constructor (gtype, n_properties, properties); - - g_object_set (object, - "type", GTK_WINDOW_POPUP, - NULL); - - return object; -} - -static void -meta_frames_class_init (MetaFramesClass *class) -{ - GObjectClass *gobject_class; - GtkWidgetClass *widget_class; - - gobject_class = G_OBJECT_CLASS (class); - widget_class = (GtkWidgetClass*) class; - - gobject_class->constructor = meta_frames_constructor; - gobject_class->finalize = meta_frames_finalize; - - widget_class->destroy = meta_frames_destroy; - - widget_class->style_updated = meta_frames_style_updated; - - widget_class->draw = meta_frames_draw; -} - -static gint -unsigned_long_equal (gconstpointer v1, - gconstpointer v2) -{ - return *((const gulong*) v1) == *((const gulong*) v2); -} - -static guint -unsigned_long_hash (gconstpointer v) -{ - gulong val = * (const gulong *) v; - - /* I'm not sure this works so well. */ -#if GLIB_SIZEOF_LONG > 4 - return (guint) (val ^ (val >> 32)); -#else - return val; -#endif -} - -static void -prefs_changed_callback (MetaPreference pref, - void *data) -{ - switch (pref) - { - case META_PREF_TITLEBAR_FONT: - meta_frames_font_changed (META_FRAMES (data)); - break; - case META_PREF_BUTTON_LAYOUT: - meta_frames_button_layout_changed (META_FRAMES (data)); - break; - default: - break; - } -} - -static void -invalidate_whole_window (MetaUIFrame *frame) -{ - if (!frame->is_frozen) - { - meta_window_x11_freeze_commits (frame->meta_window); - frame->is_frozen = TRUE; - } - gdk_window_invalidate_rect (frame->window, NULL, FALSE); -} - -static MetaStyleInfo * -meta_frames_get_theme_variant (MetaFrames *frames, - const gchar *variant) -{ - MetaStyleInfo *style_info; - - style_info = g_hash_table_lookup (frames->style_variants, variant); - if (style_info == NULL) - { - style_info = meta_theme_create_style_info (gtk_widget_get_screen (GTK_WIDGET (frames)), variant); - g_hash_table_insert (frames->style_variants, g_strdup (variant), style_info); - } - - return style_info; -} - -static void -update_style_contexts (MetaFrames *frames) -{ - MetaStyleInfo *style_info; - GList *variants, *variant; - GdkScreen *screen; - - screen = gtk_widget_get_screen (GTK_WIDGET (frames)); - - if (frames->normal_style) - meta_style_info_unref (frames->normal_style); - frames->normal_style = meta_theme_create_style_info (screen, NULL); - - variants = g_hash_table_get_keys (frames->style_variants); - for (variant = variants; variant; variant = variant->next) - { - style_info = meta_theme_create_style_info (screen, (char *)variant->data); - g_hash_table_insert (frames->style_variants, - g_strdup (variant->data), style_info); - } - g_list_free (variants); -} - -static void -meta_frames_init (MetaFrames *frames) -{ - frames->text_heights = g_hash_table_new (NULL, NULL); - - frames->frames = g_hash_table_new (unsigned_long_hash, unsigned_long_equal); - - frames->style_variants = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, (GDestroyNotify)meta_style_info_unref); - - update_style_contexts (frames); - - meta_prefs_add_listener (prefs_changed_callback, frames); -} - -static void -listify_func (gpointer key, gpointer value, gpointer data) -{ - GSList **listp; - - listp = data; - *listp = g_slist_prepend (*listp, value); -} - -static void -meta_frames_destroy (GtkWidget *object) -{ - GSList *winlist; - GSList *tmp; - MetaFrames *frames; - - frames = META_FRAMES (object); - - winlist = NULL; - g_hash_table_foreach (frames->frames, listify_func, &winlist); - - /* Unmanage all frames */ - for (tmp = winlist; tmp != NULL; tmp = tmp->next) - { - MetaUIFrame *frame = tmp->data; - meta_ui_frame_unmanage (frame); - } - g_slist_free (winlist); - - if (frames->normal_style) - { - meta_style_info_unref (frames->normal_style); - frames->normal_style = NULL; - } - - if (frames->style_variants) - { - g_hash_table_destroy (frames->style_variants); - frames->style_variants = NULL; - } - - GTK_WIDGET_CLASS (meta_frames_parent_class)->destroy (object); -} - -static void -meta_frames_finalize (GObject *object) -{ - MetaFrames *frames; - - frames = META_FRAMES (object); - - meta_prefs_remove_listener (prefs_changed_callback, frames); - - g_hash_table_destroy (frames->text_heights); - - g_assert (g_hash_table_size (frames->frames) == 0); - g_hash_table_destroy (frames->frames); - - G_OBJECT_CLASS (meta_frames_parent_class)->finalize (object); -} - -static void -queue_recalc_func (gpointer key, - gpointer value, - gpointer user_data) -{ - MetaUIFrame *frame = value; - MetaFrames *frames = user_data; - - invalidate_whole_window (frame); - meta_x11_wm_queue_frame_resize (frames->x11_display, - frame->xwindow); - - g_clear_object (&frame->text_layout); -} - -static void -meta_frames_font_changed (MetaFrames *frames) -{ - if (g_hash_table_size (frames->text_heights) > 0) - { - g_hash_table_destroy (frames->text_heights); - frames->text_heights = g_hash_table_new (NULL, NULL); - } - - /* Queue a draw/resize on all frames */ - g_hash_table_foreach (frames->frames, - queue_recalc_func, frames); - -} - -static void -queue_draw_func (gpointer key, gpointer value, gpointer data) -{ - MetaUIFrame *frame = value; - invalidate_whole_window (frame); -} - -static void -meta_frames_button_layout_changed (MetaFrames *frames) -{ - g_hash_table_foreach (frames->frames, - queue_draw_func, frames); -} - -static void -reattach_style_func (gpointer key, gpointer value, gpointer data) -{ - MetaUIFrame *frame = value; - meta_ui_frame_attach_style (frame); -} - -static void -meta_frames_style_updated (GtkWidget *widget) -{ - MetaFrames *frames; - - frames = META_FRAMES (widget); - - meta_frames_font_changed (frames); - - update_style_contexts (frames); - - g_hash_table_foreach (frames->frames, reattach_style_func, NULL); - - meta_display_queue_retheme_all_windows (meta_get_display ()); - - GTK_WIDGET_CLASS (meta_frames_parent_class)->style_updated (widget); -} - -static void -meta_ui_frame_ensure_layout (MetaUIFrame *frame, - MetaFrameType type) -{ - MetaFrames *frames = frame->frames; - GtkWidget *widget; - MetaFrameLayout *layout; - - widget = GTK_WIDGET (frames); - - g_return_if_fail (gtk_widget_get_realized (widget)); - - layout = meta_theme_get_frame_layout (meta_theme_get_default (), type); - - if (layout != frame->cache_layout) - g_clear_object (&frame->text_layout); - - frame->cache_layout = layout; - - if (frame->text_layout == NULL) - { - gpointer key, value; - PangoFontDescription *font_desc; - int size; - - frame->text_layout = gtk_widget_create_pango_layout (widget, frame->title); - - pango_layout_set_ellipsize (frame->text_layout, PANGO_ELLIPSIZE_END); - pango_layout_set_auto_dir (frame->text_layout, FALSE); - pango_layout_set_single_paragraph_mode (frame->text_layout, TRUE); - - font_desc = meta_style_info_create_font_desc (frame->style_info); - meta_frame_layout_apply_scale (layout, font_desc); - - size = pango_font_description_get_size (font_desc); - - if (g_hash_table_lookup_extended (frames->text_heights, - GINT_TO_POINTER (size), - &key, &value)) - { - frame->text_height = GPOINTER_TO_INT (value); - } - else - { - frame->text_height = - meta_pango_font_desc_get_text_height (font_desc, - gtk_widget_get_pango_context (widget)); - - g_hash_table_replace (frames->text_heights, - GINT_TO_POINTER (size), - GINT_TO_POINTER (frame->text_height)); - } - - pango_layout_set_font_description (frame->text_layout, - font_desc); - - pango_font_description_free (font_desc); - } -} - -static void -meta_ui_frame_calc_geometry (MetaUIFrame *frame, - MetaFrameGeometry *fgeom) -{ - MetaFrameFlags flags; - MetaFrameType type; - MetaButtonLayout button_layout; - MetaWindowX11 *window_x11 = META_WINDOW_X11 (frame->meta_window); - MetaRectangle client_rect; - - flags = meta_frame_get_flags (frame->meta_window->frame); - type = meta_window_get_frame_type (frame->meta_window); - - meta_ui_frame_ensure_layout (frame, type); - - meta_prefs_get_button_layout (&button_layout); - - client_rect = meta_window_x11_get_client_rect (window_x11); - - meta_theme_calc_geometry (meta_theme_get_default (), - frame->style_info, - type, - frame->text_height, - flags, - client_rect.width, - client_rect.height, - &button_layout, - fgeom); -} - -MetaFrames* -meta_frames_new (MetaX11Display *x11_display) -{ - MetaFrames *frames; - - frames = g_object_new (META_TYPE_FRAMES, - "type", GTK_WINDOW_POPUP, - NULL); - frames->x11_display = x11_display; - - /* Put the window at an arbitrary offscreen location; the one place - * it can't be is at -100x-100, since the meta_window_new() will - * mistake it for a window created via meta_create_offscreen_window() - * and ignore it, and we need this window to get frame-synchronization - * messages so that GTK+'s style change handling works. - */ - gtk_window_move (GTK_WINDOW (frames), -200, -200); - gtk_window_resize (GTK_WINDOW (frames), 1, 1); - - return frames; -} - -static const char * -get_global_theme_variant (MetaFrames *frames) -{ - GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (frames)); - GtkSettings *settings = gtk_settings_get_for_screen (screen); - gboolean dark_theme_requested; - - g_object_get (settings, - "gtk-application-prefer-dark-theme", &dark_theme_requested, - NULL); - - if (dark_theme_requested) - return "dark"; - - return NULL; -} - -/* In order to use a style with a window it has to be attached to that - * window. Actually, the colormaps just have to match, but since GTK+ - * already takes care of making sure that its cheap to attach a style - * to multiple windows with the same colormap, we can just go ahead - * and attach separately for each window. - */ -static void -meta_ui_frame_attach_style (MetaUIFrame *frame) -{ - MetaFrames *frames = frame->frames; - const char *variant; - - if (frame->style_info != NULL) - meta_style_info_unref (frame->style_info); - - variant = frame->meta_window->gtk_theme_variant; - if (variant == NULL) - variant = get_global_theme_variant (frame->frames); - - if (variant == NULL || *variant == '\0') - frame->style_info = meta_style_info_ref (frames->normal_style); - else - frame->style_info = meta_style_info_ref (meta_frames_get_theme_variant (frames, - variant)); -} - -MetaUIFrame * -meta_frames_manage_window (MetaFrames *frames, - MetaWindow *meta_window, - Window xwindow, - GdkWindow *window) -{ - MetaUIFrame *frame; - - g_assert (window); - - frame = g_new (MetaUIFrame, 1); - - frame->frames = frames; - frame->window = window; - - gdk_window_set_user_data (frame->window, frames); - - frame->style_info = NULL; - - /* Don't set event mask here, it's in frame.c */ - - frame->xwindow = xwindow; - frame->meta_window = meta_window; - frame->cache_layout = NULL; - frame->text_layout = NULL; - frame->text_height = -1; - frame->title = NULL; - frame->prelit_control = META_FRAME_CONTROL_NONE; - frame->button_state = META_BUTTON_STATE_NORMAL; - frame->is_frozen = FALSE; - - meta_x11_wm_grab_buttons (frames->x11_display, frame->xwindow); - - g_hash_table_replace (frames->frames, &frame->xwindow, frame); - - return frame; -} - -void -meta_ui_frame_unmanage (MetaUIFrame *frame) -{ - MetaFrames *frames = frame->frames; - - /* restore the cursor */ - meta_x11_wm_set_screen_cursor (frames->x11_display, - frame->xwindow, - META_CURSOR_DEFAULT); - - gdk_window_set_user_data (frame->window, NULL); - - g_hash_table_remove (frames->frames, &frame->xwindow); - - meta_style_info_unref (frame->style_info); - - gdk_window_destroy (frame->window); - - if (frame->text_layout) - g_object_unref (G_OBJECT (frame->text_layout)); - - if (frame->is_frozen) - meta_window_x11_thaw_commits (frame->meta_window); - - g_free (frame->title); - - g_free (frame); -} - -void -meta_ui_frame_get_borders (MetaUIFrame *frame, - MetaFrameBorders *borders) -{ - MetaFrameFlags flags; - MetaFrameType type; - - flags = meta_frame_get_flags (frame->meta_window->frame); - type = meta_window_get_frame_type (frame->meta_window); - - g_return_if_fail (type < META_FRAME_TYPE_LAST); - - meta_ui_frame_ensure_layout (frame, type); - - /* We can't get the full geometry, because that depends on - * the client window size and probably we're being called - * by the core move/resize code to decide on the client - * window size - */ - meta_theme_get_frame_borders (meta_theme_get_default (), - frame->style_info, - type, - frame->text_height, - flags, - borders); -} - -/* The visible frame rectangle surrounds the visible portion of the - * frame window; it subtracts only the invisible borders from the frame - * window's size. - */ -static void -get_visible_frame_rect (MetaFrameGeometry *fgeom, - cairo_rectangle_int_t *rect) -{ - rect->x = fgeom->borders.invisible.left; - rect->y = fgeom->borders.invisible.top; - rect->width = fgeom->width - fgeom->borders.invisible.right - rect->x; - rect->height = fgeom->height - fgeom->borders.invisible.bottom - rect->y; -} - -static cairo_region_t * -get_visible_region (MetaUIFrame *frame, - MetaFrameGeometry *fgeom) -{ - cairo_region_t *corners_region; - cairo_region_t *visible_region; - cairo_rectangle_int_t rect; - cairo_rectangle_int_t frame_rect; - - corners_region = cairo_region_create (); - get_visible_frame_rect (fgeom, &frame_rect); - - if (fgeom->top_left_corner_rounded_radius != 0) - { - const int corner = fgeom->top_left_corner_rounded_radius; - const float radius = corner; - int i; - - for (i=0; itop_right_corner_rounded_radius != 0) - { - const int corner = fgeom->top_right_corner_rounded_radius; - const float radius = corner; - int i; - - for (i=0; ibottom_left_corner_rounded_radius != 0) - { - const int corner = fgeom->bottom_left_corner_rounded_radius; - const float radius = corner; - int i; - - for (i=0; ibottom_right_corner_rounded_radius != 0) - { - const int corner = fgeom->bottom_right_corner_rounded_radius; - const float radius = corner; - int i; - - for (i=0; iwindow); - old_height = gdk_window_get_height (frame->window); - - gdk_window_move_resize (frame->window, x, y, width, height); - - if (old_width != width || old_height != height) - invalidate_whole_window (frame); -} - -void -meta_ui_frame_queue_draw (MetaUIFrame *frame) -{ - invalidate_whole_window (frame); -} - -void -meta_ui_frame_set_title (MetaUIFrame *frame, - const char *title) -{ - g_free (frame->title); - frame->title = g_strdup (title); - - g_clear_object (&frame->text_layout); - - invalidate_whole_window (frame); -} - -void -meta_ui_frame_update_style (MetaUIFrame *frame) -{ - meta_ui_frame_attach_style (frame); - invalidate_whole_window (frame); -} - -static void -redraw_control (MetaUIFrame *frame, - MetaFrameControl control) -{ - MetaFrameGeometry fgeom; - GdkRectangle *rect; - - meta_ui_frame_calc_geometry (frame, &fgeom); - - rect = control_rect (control, &fgeom); - - gdk_window_invalidate_rect (frame->window, rect, FALSE); -} - -static gboolean -meta_frame_titlebar_event (MetaUIFrame *frame, - const ClutterEvent *event, - int action) -{ - MetaFrameFlags flags; - MetaX11Display *x11_display; - uint32_t evtime; - float x, y; - - g_assert (event->type == CLUTTER_BUTTON_PRESS || - event->type == CLUTTER_TOUCH_BEGIN); - - x11_display = frame->frames->x11_display; - - flags = meta_frame_get_flags (frame->meta_window->frame); - - evtime = clutter_event_get_time (event); - clutter_event_get_coords (event, &x, &y); - - switch (action) - { - case G_DESKTOP_TITLEBAR_ACTION_TOGGLE_SHADE: - { - if (flags & META_FRAME_ALLOWS_SHADE) - { - if (flags & META_FRAME_SHADED) - meta_window_unshade (frame->meta_window, evtime); - else - meta_window_shade (frame->meta_window, evtime); - } - } - break; - - case G_DESKTOP_TITLEBAR_ACTION_TOGGLE_MAXIMIZE: - { - if (flags & META_FRAME_ALLOWS_MAXIMIZE) - { - meta_x11_wm_toggle_maximize (x11_display, frame->xwindow); - } - } - break; - - case G_DESKTOP_TITLEBAR_ACTION_TOGGLE_MAXIMIZE_HORIZONTALLY: - { - if (flags & META_FRAME_ALLOWS_MAXIMIZE) - { - meta_x11_wm_toggle_maximize_horizontally (x11_display, - frame->xwindow); - } - } - break; - - case G_DESKTOP_TITLEBAR_ACTION_TOGGLE_MAXIMIZE_VERTICALLY: - { - if (flags & META_FRAME_ALLOWS_MAXIMIZE) - { - meta_x11_wm_toggle_maximize_vertically (x11_display, frame->xwindow); - } - } - break; - - case G_DESKTOP_TITLEBAR_ACTION_MINIMIZE: - { - if (flags & META_FRAME_ALLOWS_MINIMIZE) - meta_window_minimize (frame->meta_window); - } - break; - - case G_DESKTOP_TITLEBAR_ACTION_NONE: - /* Yaay, a sane user that doesn't use that other weird crap! */ - break; - - case G_DESKTOP_TITLEBAR_ACTION_LOWER: - meta_x11_wm_user_lower_and_unfocus (x11_display, - frame->xwindow, - evtime); - break; - - case G_DESKTOP_TITLEBAR_ACTION_MENU: - meta_x11_wm_show_window_menu (x11_display, - frame->xwindow, - META_WINDOW_MENU_WM, - x, y, evtime); - break; - } - - return TRUE; -} - -static gboolean -meta_frame_double_click_event (MetaUIFrame *frame, - const ClutterEvent *event) -{ - int action = meta_prefs_get_action_double_click_titlebar (); - - return meta_frame_titlebar_event (frame, event, action); -} - -static gboolean -meta_frame_middle_click_event (MetaUIFrame *frame, - ClutterButtonEvent *event) -{ - int action = meta_prefs_get_action_middle_click_titlebar(); - - return meta_frame_titlebar_event (frame, (const ClutterEvent *) event, - action); -} - -static gboolean -meta_frame_right_click_event (MetaUIFrame *frame, - ClutterButtonEvent *event) -{ - int action = meta_prefs_get_action_right_click_titlebar(); - - return meta_frame_titlebar_event (frame, (const ClutterEvent *) event, - action); -} - -static gboolean -meta_frames_try_grab_op (MetaUIFrame *frame, - MetaGrabOp op, - gdouble grab_x, - gdouble grab_y, - guint32 time) -{ - MetaFrames *frames = frame->frames; - gboolean ret; - - ret = meta_x11_wm_begin_grab_op (frames->x11_display, - frame->xwindow, - op, - FALSE, - TRUE, - frame->grab_button, - 0, - time, - grab_x, grab_y); - if (!ret) - { - frames->current_grab_op = op; - frames->grab_frame = frame; - frames->grab_x = grab_x; - frames->grab_y = grab_y; - } - else - frames->grab_touch = NULL; - - return ret; -} - -static gboolean -meta_frames_retry_grab_op (MetaFrames *frames, - guint time) -{ - MetaGrabOp op; - gboolean ret; - - if (frames->current_grab_op == META_GRAB_OP_NONE) - return TRUE; - - op = frames->current_grab_op; - frames->current_grab_op = META_GRAB_OP_NONE; - - ret = meta_x11_wm_begin_grab_op (frames->x11_display, - frames->grab_frame->xwindow, - op, - FALSE, - TRUE, - frames->grab_frame->grab_button, - 0, - time, - frames->grab_x, - frames->grab_y); - if (ret) - frames->grab_touch = NULL; - - return ret; -} - -static MetaGrabOp -grab_op_from_resize_control (MetaFrameControl control) -{ - switch (control) - { - case META_FRAME_CONTROL_RESIZE_SE: - return META_GRAB_OP_RESIZING_SE; - case META_FRAME_CONTROL_RESIZE_S: - return META_GRAB_OP_RESIZING_S; - case META_FRAME_CONTROL_RESIZE_SW: - return META_GRAB_OP_RESIZING_SW; - case META_FRAME_CONTROL_RESIZE_NE: - return META_GRAB_OP_RESIZING_NE; - case META_FRAME_CONTROL_RESIZE_N: - return META_GRAB_OP_RESIZING_N; - case META_FRAME_CONTROL_RESIZE_NW: - return META_GRAB_OP_RESIZING_NW; - case META_FRAME_CONTROL_RESIZE_E: - return META_GRAB_OP_RESIZING_E; - case META_FRAME_CONTROL_RESIZE_W: - return META_GRAB_OP_RESIZING_W; - default: - g_assert_not_reached (); - return META_GRAB_OP_NONE; - } -} - -static guint -get_action (const ClutterEvent *event) -{ - if (event->type == CLUTTER_BUTTON_PRESS || - event->type == CLUTTER_BUTTON_RELEASE) - { - switch (event->button.button) - { - case CLUTTER_BUTTON_PRIMARY: - if (clutter_event_get_click_count (event) == 2) - return META_ACTION_DOUBLE_CLICK; - else - return META_ACTION_CLICK; - case CLUTTER_BUTTON_SECONDARY: - return META_ACTION_RIGHT_CLICK; - case CLUTTER_BUTTON_MIDDLE: - return META_ACTION_MIDDLE_CLICK; - default: - meta_verbose ("No action triggered for button %u %s", - event->button.button, - (event->type == CLUTTER_BUTTON_PRESS) ? "press" : "release"); - } - } - else if (event->type == CLUTTER_TOUCH_BEGIN || - event->type == CLUTTER_TOUCH_UPDATE || - event->type == CLUTTER_TOUCH_END) - { - return META_ACTION_CLICK; - } - - return META_ACTION_IGNORE; -} - -static uint32_t -get_button_number (const ClutterEvent *event) -{ - if (event->type == CLUTTER_TOUCH_BEGIN || - event->type == CLUTTER_TOUCH_UPDATE || - event->type == CLUTTER_TOUCH_END) - return -1; - else if (event->type == CLUTTER_BUTTON_PRESS || - event->type == CLUTTER_BUTTON_RELEASE) - return clutter_event_get_button (event); - - g_assert_not_reached (); - return -1; -} - -static gboolean -meta_frame_left_click_event (MetaUIFrame *frame, - const ClutterEvent *event) -{ - MetaX11Display *x11_display = frame->frames->x11_display; - MetaFrameControl control; - guint32 evtime; - gfloat x, y; - - evtime = clutter_event_get_time (event); - clutter_event_get_coords (event, &x, &y); - control = get_control (frame, x, y); - - switch (control) - { - case META_FRAME_CONTROL_MAXIMIZE: - case META_FRAME_CONTROL_UNMAXIMIZE: - case META_FRAME_CONTROL_MINIMIZE: - case META_FRAME_CONTROL_DELETE: - case META_FRAME_CONTROL_MENU: - frame->grab_button = get_button_number (event); - frame->button_state = META_BUTTON_STATE_PRESSED; - frame->prelit_control = control; - redraw_control (frame, control); - - if (control == META_FRAME_CONTROL_MENU) - { - MetaFrameGeometry fgeom; - GdkRectangle *rect; - MetaRectangle root_rect; - int win_x, win_y; - - meta_ui_frame_calc_geometry (frame, &fgeom); - - rect = control_rect (control, &fgeom); - - gdk_window_get_position (frame->window, &win_x, &win_y); - - root_rect.x = win_x + rect->x; - root_rect.y = win_y + rect->y; - root_rect.width = rect->width; - root_rect.height = rect->height; - - /* if the compositor takes a grab for showing the menu, we will - * get a LeaveNotify event we want to ignore, to keep the pressed - * button state while the menu is open - */ - frame->maybe_ignore_leave_notify = TRUE; - meta_x11_wm_show_window_menu_for_rect (x11_display, - frame->xwindow, - META_WINDOW_MENU_WM, - &root_rect, - evtime); - } - else - { - meta_frames_try_grab_op (frame, META_GRAB_OP_FRAME_BUTTON, - x, y, evtime); - } - - return TRUE; - case META_FRAME_CONTROL_RESIZE_SE: - case META_FRAME_CONTROL_RESIZE_S: - case META_FRAME_CONTROL_RESIZE_SW: - case META_FRAME_CONTROL_RESIZE_NE: - case META_FRAME_CONTROL_RESIZE_N: - case META_FRAME_CONTROL_RESIZE_NW: - case META_FRAME_CONTROL_RESIZE_E: - case META_FRAME_CONTROL_RESIZE_W: - meta_frames_try_grab_op (frame, - grab_op_from_resize_control (control), - x, y, evtime); - - return TRUE; - case META_FRAME_CONTROL_TITLE: - { - MetaFrameFlags flags = meta_frame_get_flags (frame->meta_window->frame); - - if (flags & META_FRAME_ALLOWS_MOVE) - { - meta_frames_try_grab_op (frame, - META_GRAB_OP_MOVING, - x, y, evtime); - } - } - - return TRUE; - case META_FRAME_CONTROL_NONE: - /* We can get this for example when trying to resize window - * that cannot be resized (e. g. it is maximized and the theme - * currently used has borders for maximized windows), see #751884 */ - return FALSE; - case META_FRAME_CONTROL_CLIENT_AREA: - /* This can happen with broken gtk themes that have a larger shadow size - * in the unfocused state than in the focused one. Then when clicking - * below the titlebar area in the unfocused state would still be - * considered a click on the titlebar due to it being shifted down because - * of the shadow. This then causes the window to be focused before this - * function is called, which removes the shadow such that the same - * position is now considered to be on the client area */ - return FALSE; - default: - g_assert_not_reached (); - return FALSE; - } -} - -static gboolean -handle_press_event (MetaUIFrame *frame, - const ClutterEvent *event) -{ - MetaFrameControl control; - uint32_t evtime, action; - float x, y; - - g_assert (event->type == CLUTTER_BUTTON_PRESS || - event->type == CLUTTER_TOUCH_BEGIN); - - action = get_action (event); - if (action == META_ACTION_IGNORE) - return FALSE; - - evtime = clutter_event_get_time (event); - clutter_event_get_coords (event, &x, &y); - control = get_control (frame, x, y); - /* don't do the rest of this if on client area */ - if (control == META_FRAME_CONTROL_CLIENT_AREA) - return FALSE; /* not on the frame, just passed through from client */ - - if (action == META_ACTION_CLICK && - !(control == META_FRAME_CONTROL_MINIMIZE || - control == META_FRAME_CONTROL_DELETE || - control == META_FRAME_CONTROL_MAXIMIZE)) - { - meta_topic (META_DEBUG_FOCUS, - "Focusing window with frame 0x%lx due to button 1 press", - frame->xwindow); - meta_window_focus (frame->meta_window, evtime); - } - - /* We want to shade even if we have a GrabOp, since we'll have a move grab - * if we double click the titlebar. - */ - if (control == META_FRAME_CONTROL_TITLE && - action == META_ACTION_DOUBLE_CLICK) - { - meta_x11_wm_end_grab_op (frame->frames->x11_display, evtime); - return meta_frame_double_click_event (frame, event); - } - - if (meta_x11_wm_get_grab_op (frame->frames->x11_display) != META_GRAB_OP_NONE) - return FALSE; /* already up to something */ - - frame->grab_button = get_button_number (event); - - switch (action) - { - case META_ACTION_CLICK: - return meta_frame_left_click_event (frame, event); - case META_ACTION_MIDDLE_CLICK: - return meta_frame_middle_click_event (frame, (ClutterButtonEvent *) event); - case META_ACTION_RIGHT_CLICK: - return meta_frame_right_click_event (frame, (ClutterButtonEvent *) event); - default: - return FALSE; - } -} - -static gboolean -handle_release_event (MetaUIFrame *frame, - const ClutterEvent *event) -{ - guint32 evtime, button; - gfloat x, y; - - g_assert (event->type == CLUTTER_BUTTON_RELEASE || - event->type == CLUTTER_TOUCH_END); - - evtime = clutter_event_get_time (event); - clutter_event_get_coords (event, &x, &y); - button = get_button_number (event); - - frame->frames->current_grab_op = META_GRAB_OP_NONE; - meta_x11_wm_end_grab_op (frame->frames->x11_display, evtime); - - /* We only handle the releases we handled the presses for (things - * involving frame controls). Window ops that don't require a - * frame are handled in the Xlib part of the code, display.c/window.c - */ - if (((int) button) == frame->grab_button && - frame->button_state == META_BUTTON_STATE_PRESSED) - { - switch (frame->prelit_control) - { - case META_FRAME_CONTROL_MINIMIZE: - meta_window_minimize (frame->meta_window); - break; - case META_FRAME_CONTROL_MAXIMIZE: - /* Focus the window on the maximize */ - meta_window_focus (frame->meta_window, evtime); - if (meta_prefs_get_raise_on_click ()) - meta_window_raise (frame->meta_window); - meta_window_maximize (frame->meta_window, META_MAXIMIZE_BOTH); - break; - case META_FRAME_CONTROL_UNMAXIMIZE: - if (meta_prefs_get_raise_on_click ()) - meta_window_raise (frame->meta_window); - meta_window_unmaximize (frame->meta_window, META_MAXIMIZE_BOTH); - break; - case META_FRAME_CONTROL_DELETE: - meta_window_delete (frame->meta_window, evtime); - break; - default: - break; - } - - /* Update the prelit control regardless of what button the mouse - * was released over; needed so that the new button can become - * prelit so to let the user know that it can now be pressed. - * :) - */ - MetaFrameControl control = get_control (frame, x, y); - meta_ui_frame_update_prelit_control (frame, control); - } - - return TRUE; -} - -static void -meta_ui_frame_update_prelit_control (MetaUIFrame *frame, - MetaFrameControl control) -{ - MetaFrameControl old_control; - MetaCursor cursor; - - meta_verbose ("Updating prelit control from %u to %u", - frame->prelit_control, control); - - cursor = META_CURSOR_DEFAULT; - - switch (control) - { - case META_FRAME_CONTROL_CLIENT_AREA: - break; - case META_FRAME_CONTROL_NONE: - break; - case META_FRAME_CONTROL_TITLE: - break; - case META_FRAME_CONTROL_DELETE: - break; - case META_FRAME_CONTROL_MENU: - break; - case META_FRAME_CONTROL_MINIMIZE: - break; - case META_FRAME_CONTROL_MAXIMIZE: - break; - case META_FRAME_CONTROL_UNMAXIMIZE: - break; - case META_FRAME_CONTROL_RESIZE_SE: - cursor = META_CURSOR_SE_RESIZE; - break; - case META_FRAME_CONTROL_RESIZE_S: - cursor = META_CURSOR_SOUTH_RESIZE; - break; - case META_FRAME_CONTROL_RESIZE_SW: - cursor = META_CURSOR_SW_RESIZE; - break; - case META_FRAME_CONTROL_RESIZE_N: - cursor = META_CURSOR_NORTH_RESIZE; - break; - case META_FRAME_CONTROL_RESIZE_NE: - cursor = META_CURSOR_NE_RESIZE; - break; - case META_FRAME_CONTROL_RESIZE_NW: - cursor = META_CURSOR_NW_RESIZE; - break; - case META_FRAME_CONTROL_RESIZE_W: - cursor = META_CURSOR_WEST_RESIZE; - break; - case META_FRAME_CONTROL_RESIZE_E: - cursor = META_CURSOR_EAST_RESIZE; - break; - } - - /* set/unset the prelight cursor */ - meta_x11_wm_set_screen_cursor (frame->frames->x11_display, - frame->xwindow, - cursor); - - switch (control) - { - case META_FRAME_CONTROL_MENU: - case META_FRAME_CONTROL_MINIMIZE: - case META_FRAME_CONTROL_MAXIMIZE: - case META_FRAME_CONTROL_DELETE: - case META_FRAME_CONTROL_UNMAXIMIZE: - /* leave control set */ - break; - default: - /* Only prelight buttons */ - control = META_FRAME_CONTROL_NONE; - break; - } - - if (control == frame->prelit_control && - frame->button_state == META_BUTTON_STATE_PRELIGHT) - return; - - /* Save the old control so we can unprelight it */ - old_control = frame->prelit_control; - - frame->button_state = META_BUTTON_STATE_PRELIGHT; - frame->prelit_control = control; - - redraw_control (frame, old_control); - redraw_control (frame, control); -} - -static gboolean -handle_motion_event (MetaUIFrame *frame, - const ClutterEvent *event) -{ - MetaFrames *frames = frame->frames; - MetaFrameControl control; - ClutterModifierType modifiers; - guint32 evtime; - gfloat x, y; - - g_assert (event->type == CLUTTER_MOTION || - event->type == CLUTTER_TOUCH_UPDATE); - - modifiers = clutter_event_get_state (event); - evtime = clutter_event_get_time (event); - clutter_event_get_coords (event, &x, &y); - control = get_control (frame, x, y); - - if (frame->button_state == META_BUTTON_STATE_PRESSED) - { - /* If the user leaves the frame button, set the state - * back to normal and redraw. */ - if (frame->prelit_control != control) - { - frame->button_state = META_BUTTON_STATE_NORMAL; - redraw_control (frame, frame->prelit_control); - } - } - else - { - /* Update prelit control and cursor */ - meta_ui_frame_update_prelit_control (frame, control); - } - - if (frames->current_grab_op != META_GRAB_OP_NONE && - (event->type == CLUTTER_TOUCH_UPDATE || - (event->type == CLUTTER_MOTION && - (modifiers & CLUTTER_BUTTON1_MASK)))) - meta_frames_retry_grab_op (frames, evtime); - - return TRUE; -} - -static cairo_region_t * -get_visible_frame_border_region (MetaUIFrame *frame) -{ - cairo_rectangle_int_t area; - cairo_region_t *frame_border; - MetaFrameFlags flags; - MetaFrameType type; - MetaFrameBorders borders; - MetaRectangle buffer_rect = frame->meta_window->buffer_rect; - - flags = meta_frame_get_flags (frame->meta_window->frame); - type = meta_window_get_frame_type (frame->meta_window); - - meta_theme_get_frame_borders (meta_theme_get_default (), frame->style_info, - type, frame->text_height, flags, - &borders); - - /* Frame rect */ - area.x = 0; - area.y = 0; - area.width = buffer_rect.width; - area.height = buffer_rect.height; - - frame_border = cairo_region_create_rectangle (&area); - - /* Client rect */ - area.x += borders.total.left; - area.y += borders.total.top; - area.width -= borders.total.left + borders.total.right; - area.height -= borders.total.top + borders.total.bottom; - - /* Visible frame border */ - cairo_region_subtract_rectangle (frame_border, &area); - return frame_border; -} - -/* - * Draw the opaque and semi-opaque pixels of this frame into a mask. - * - * (0,0) in Cairo coordinates is assumed to be the top left corner of the - * invisible border. - * - * The parts of @cr's surface in the clip region are assumed to be - * initialized to fully-transparent, and the clip region is assumed to - * contain the invisible border and the visible parts of the frame, but - * not the client area. - * - * This function uses @cr to draw pixels of arbitrary color (it will - * typically be drawing in a %CAIRO_FORMAT_A8 surface, so the color is - * discarded anyway) with appropriate alpha values to reproduce this - * frame's alpha channel, as a mask to be applied to an opaque pixmap. - * - * @frame: This frame - * @frame_rect: The frame rect - * @cr: Used to draw the resulting mask - */ -void -meta_ui_frame_get_mask (MetaUIFrame *frame, - cairo_rectangle_int_t *frame_rect, - cairo_t *cr) -{ - MetaFrameBorders borders; - MetaFrameFlags flags; - cairo_surface_t *surface; - double xscale, yscale; - int scale; - - flags = meta_frame_get_flags (frame->meta_window->frame); - - meta_style_info_set_flags (frame->style_info, flags); - meta_ui_frame_get_borders (frame, &borders); - - /* See comment in meta_frame_layout_draw_with_style() for details on HiDPI handling */ - scale = meta_theme_get_window_scaling_factor (); - surface = cairo_get_target (cr); - cairo_surface_get_device_scale (surface, &xscale, &yscale); - cairo_surface_set_device_scale (surface, scale, scale); - - gtk_render_background (frame->style_info->styles[META_STYLE_ELEMENT_FRAME], cr, - borders.invisible.left / scale, - borders.invisible.top / scale, - frame_rect->width / scale, frame_rect->height / scale); - gtk_render_background (frame->style_info->styles[META_STYLE_ELEMENT_TITLEBAR], cr, - borders.invisible.left / scale, - borders.invisible.top / scale, - frame_rect->width / scale, borders.total.top / scale); - - cairo_surface_set_device_scale (surface, xscale, yscale); -} - -/* XXX -- this is disgusting. Find a better approach here. - * Use multiple widgets? */ -static MetaUIFrame * -find_frame_to_draw (MetaFrames *frames, - cairo_t *cr) -{ - GHashTableIter iter; - MetaUIFrame *frame; - - g_hash_table_iter_init (&iter, frames->frames); - while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &frame)) - if (gtk_cairo_should_draw_window (cr, frame->window)) - return frame; - - return NULL; -} - -static gboolean -meta_frames_draw (GtkWidget *widget, - cairo_t *cr) -{ - MetaUIFrame *frame; - MetaFrames *frames; - cairo_region_t *region; - - frames = META_FRAMES (widget); - - frame = find_frame_to_draw (frames, cr); - if (frame == NULL) - return FALSE; - - region = get_visible_frame_border_region (frame); - gdk_cairo_region (cr, region); - cairo_clip (cr); - - /* The target may be cleared to black or transparent, depending - * on the frame's visual; we don't want decorations to appear - * differently when the theme's decorations aren't fully opaque, - * so clear to black first - */ - cairo_paint (cr); - - meta_ui_frame_paint (frame, cr); - cairo_region_destroy (region); - - return TRUE; -} - -static void -meta_ui_frame_paint (MetaUIFrame *frame, - cairo_t *cr) -{ - MetaFrameFlags flags; - MetaFrameType type; - cairo_surface_t *mini_icon; - MetaButtonState button_states[META_BUTTON_TYPE_LAST]; - int i; - int button_type = -1; - MetaButtonLayout button_layout; - MetaWindowX11 *window_x11 = META_WINDOW_X11 (frame->meta_window); - MetaRectangle client_rect; - - for (i = 0; i < META_BUTTON_TYPE_LAST; i++) - button_states[i] = META_BUTTON_STATE_NORMAL; - - /* Set prelight state */ - switch (frame->prelit_control) - { - case META_FRAME_CONTROL_MENU: - button_type = META_BUTTON_TYPE_MENU; - break; - case META_FRAME_CONTROL_MINIMIZE: - button_type = META_BUTTON_TYPE_MINIMIZE; - break; - case META_FRAME_CONTROL_MAXIMIZE: - button_type = META_BUTTON_TYPE_MAXIMIZE; - break; - case META_FRAME_CONTROL_UNMAXIMIZE: - button_type = META_BUTTON_TYPE_MAXIMIZE; - break; - case META_FRAME_CONTROL_DELETE: - button_type = META_BUTTON_TYPE_CLOSE; - break; - default: - break; - } - - if (button_type > -1) - button_states[button_type] = frame->button_state; - - mini_icon = frame->meta_window->mini_icon; - flags = meta_frame_get_flags (frame->meta_window->frame); - type = meta_window_get_frame_type (frame->meta_window); - - meta_ui_frame_ensure_layout (frame, type); - - meta_prefs_get_button_layout (&button_layout); - - client_rect = meta_window_x11_get_client_rect (window_x11); - - meta_theme_draw_frame (meta_theme_get_default (), - frame->style_info, - cr, - type, - flags, - client_rect.width, - client_rect.height, - frame->text_layout, - frame->text_height, - &button_layout, - button_states, - mini_icon); - - if (frame->is_frozen) - { - meta_window_x11_thaw_commits (frame->meta_window); - frame->is_frozen = FALSE; - } -} - -static gboolean -handle_enter_notify_event (MetaUIFrame *frame, - ClutterCrossingEvent *event) -{ - MetaFrameControl control; - - frame->maybe_ignore_leave_notify = FALSE; - - control = get_control (frame, event->x, event->y); - meta_ui_frame_update_prelit_control (frame, control); - - return TRUE; -} - -static gboolean -handle_leave_notify_event (MetaUIFrame *frame, - ClutterCrossingEvent *event) -{ - MetaGrabOp grab_op; - - grab_op = meta_x11_wm_get_grab_op (frame->frames->x11_display); - - /* ignore the first LeaveNotify event after opening a window menu - * if it is the result of a compositor grab - */ - frame->maybe_ignore_leave_notify = frame->maybe_ignore_leave_notify && - grab_op == META_GRAB_OP_COMPOSITOR; - - if (frame->maybe_ignore_leave_notify) - return FALSE; - - meta_ui_frame_update_prelit_control (frame, META_FRAME_CONTROL_NONE); - - return TRUE; -} - -gboolean -meta_ui_frame_handle_event (MetaUIFrame *frame, - const ClutterEvent *event) -{ - if (event->type == CLUTTER_TOUCH_BEGIN || - event->type == CLUTTER_TOUCH_UPDATE || - event->type == CLUTTER_TOUCH_END) - { - ClutterEventSequence *sequence; - MetaFrames *frames = frame->frames; - - /* In X11, mutter sets up passive touch grabs which basically - * means we handle those events twice (once through the passive - * grab, and then through XISelectEvents). - * - * Receiving touch events here means we are going through the - * former, but passive grabs are exclusively for gesture - * recognition purposes. - * - * We do actually want this to happen though the regular event - * selection paths to avoid breaking internal state, which means - * we will get pointer events, because we don't select for XI_Touch*. - */ - if (!meta_is_wayland_compositor ()) - return FALSE; - - sequence = clutter_event_get_event_sequence (event); - - /* Lock onto a single touch */ - if (frames->grab_touch && frames->grab_touch != sequence) - return FALSE; - - if (event->type == CLUTTER_TOUCH_BEGIN) - frames->grab_touch = sequence; - else if (event->type == CLUTTER_TOUCH_END) - frames->grab_touch = NULL; - } - - switch (event->any.type) - { - case CLUTTER_BUTTON_PRESS: - case CLUTTER_TOUCH_BEGIN: - return handle_press_event (frame, event); - case CLUTTER_BUTTON_RELEASE: - case CLUTTER_TOUCH_END: - return handle_release_event (frame, event); - case CLUTTER_MOTION: - case CLUTTER_TOUCH_UPDATE: - return handle_motion_event (frame, event); - case CLUTTER_ENTER: - return handle_enter_notify_event (frame, (ClutterCrossingEvent *) event); - case CLUTTER_LEAVE: - return handle_leave_notify_event (frame, (ClutterCrossingEvent *) event); - default: - return FALSE; - } -} - -static GdkRectangle* -control_rect (MetaFrameControl control, - MetaFrameGeometry *fgeom) -{ - GdkRectangle *rect; - - rect = NULL; - switch (control) - { - case META_FRAME_CONTROL_TITLE: - rect = &fgeom->title_rect; - break; - case META_FRAME_CONTROL_DELETE: - rect = &fgeom->close_rect.visible; - break; - case META_FRAME_CONTROL_MENU: - rect = &fgeom->menu_rect.visible; - break; - case META_FRAME_CONTROL_MINIMIZE: - rect = &fgeom->min_rect.visible; - break; - case META_FRAME_CONTROL_MAXIMIZE: - case META_FRAME_CONTROL_UNMAXIMIZE: - rect = &fgeom->max_rect.visible; - break; - case META_FRAME_CONTROL_RESIZE_SE: - break; - case META_FRAME_CONTROL_RESIZE_S: - break; - case META_FRAME_CONTROL_RESIZE_SW: - break; - case META_FRAME_CONTROL_RESIZE_N: - break; - case META_FRAME_CONTROL_RESIZE_NE: - break; - case META_FRAME_CONTROL_RESIZE_NW: - break; - case META_FRAME_CONTROL_RESIZE_W: - break; - case META_FRAME_CONTROL_RESIZE_E: - break; - case META_FRAME_CONTROL_NONE: - break; - case META_FRAME_CONTROL_CLIENT_AREA: - break; - } - - return rect; -} - -#define TOP_RESIZE_HEIGHT 4 -#define CORNER_SIZE_MULT 2 -static MetaFrameControl -get_control (MetaUIFrame *frame, int root_x, int root_y) -{ - MetaFrameGeometry fgeom; - MetaFrameFlags flags; - MetaFrameType type; - gboolean has_vert, has_horiz; - gboolean has_north_resize; - cairo_rectangle_int_t client; - int x, y; - int win_x, win_y; - - if (meta_window_is_fullscreen (frame->meta_window)) - return META_FRAME_CONTROL_CLIENT_AREA; - - gdk_window_get_position (frame->window, &win_x, &win_y); - x = root_x - win_x; - y = root_y - win_y; - - meta_window_get_client_area_rect (frame->meta_window, &client); - if (META_POINT_IN_RECT (x, y, client)) - return META_FRAME_CONTROL_CLIENT_AREA; - - meta_ui_frame_calc_geometry (frame, &fgeom); - - if (META_POINT_IN_RECT (x, y, fgeom.close_rect.clickable)) - return META_FRAME_CONTROL_DELETE; - - if (META_POINT_IN_RECT (x, y, fgeom.min_rect.clickable)) - return META_FRAME_CONTROL_MINIMIZE; - - if (META_POINT_IN_RECT (x, y, fgeom.menu_rect.clickable)) - return META_FRAME_CONTROL_MENU; - - flags = meta_frame_get_flags (frame->meta_window->frame); - type = meta_window_get_frame_type (frame->meta_window); - - has_north_resize = (type != META_FRAME_TYPE_ATTACHED); - has_vert = (flags & META_FRAME_ALLOWS_VERTICAL_RESIZE) != 0; - has_horiz = (flags & META_FRAME_ALLOWS_HORIZONTAL_RESIZE) != 0; - - if (flags & META_FRAME_TILED_LEFT || flags & META_FRAME_TILED_RIGHT) - has_vert = has_horiz = FALSE; - - if (META_POINT_IN_RECT (x, y, fgeom.title_rect)) - { - if (has_vert && y <= TOP_RESIZE_HEIGHT && has_north_resize) - return META_FRAME_CONTROL_RESIZE_N; - else - return META_FRAME_CONTROL_TITLE; - } - - if (META_POINT_IN_RECT (x, y, fgeom.max_rect.clickable)) - { - if (flags & META_FRAME_MAXIMIZED) - return META_FRAME_CONTROL_UNMAXIMIZE; - else - return META_FRAME_CONTROL_MAXIMIZE; - } - - /* South resize always has priority over north resize, - * in case of overlap. - */ - - if (y >= (fgeom.height - fgeom.borders.total.bottom * CORNER_SIZE_MULT) && - x >= (fgeom.width - fgeom.borders.total.right * CORNER_SIZE_MULT)) - { - if (has_vert && has_horiz) - return META_FRAME_CONTROL_RESIZE_SE; - else if (has_vert) - return META_FRAME_CONTROL_RESIZE_S; - else if (has_horiz) - return META_FRAME_CONTROL_RESIZE_E; - } - else if (y >= (fgeom.height - fgeom.borders.total.bottom * CORNER_SIZE_MULT) && - x <= fgeom.borders.total.left * CORNER_SIZE_MULT) - { - if (has_vert && has_horiz) - return META_FRAME_CONTROL_RESIZE_SW; - else if (has_vert) - return META_FRAME_CONTROL_RESIZE_S; - else if (has_horiz) - return META_FRAME_CONTROL_RESIZE_W; - } - else if (y < (fgeom.borders.invisible.top * CORNER_SIZE_MULT) && - x <= (fgeom.borders.total.left * CORNER_SIZE_MULT) && has_north_resize) - { - if (has_vert && has_horiz) - return META_FRAME_CONTROL_RESIZE_NW; - else if (has_vert) - return META_FRAME_CONTROL_RESIZE_N; - else if (has_horiz) - return META_FRAME_CONTROL_RESIZE_W; - } - else if (y < (fgeom.borders.invisible.top * CORNER_SIZE_MULT) && - x >= (fgeom.width - fgeom.borders.total.right * CORNER_SIZE_MULT) && has_north_resize) - { - if (has_vert && has_horiz) - return META_FRAME_CONTROL_RESIZE_NE; - else if (has_vert) - return META_FRAME_CONTROL_RESIZE_N; - else if (has_horiz) - return META_FRAME_CONTROL_RESIZE_E; - } - else if (y < (fgeom.borders.invisible.top + TOP_RESIZE_HEIGHT)) - { - if (has_vert && has_north_resize) - return META_FRAME_CONTROL_RESIZE_N; - } - else if (y >= (fgeom.height - fgeom.borders.total.bottom)) - { - if (has_vert) - return META_FRAME_CONTROL_RESIZE_S; - } - else if (x <= fgeom.borders.total.left) - { - if (has_horiz || flags & META_FRAME_TILED_RIGHT) - return META_FRAME_CONTROL_RESIZE_W; - } - else if (x >= (fgeom.width - fgeom.borders.total.right)) - { - if (has_horiz || flags & META_FRAME_TILED_LEFT) - return META_FRAME_CONTROL_RESIZE_E; - } - - if (y >= fgeom.borders.total.top) - return META_FRAME_CONTROL_NONE; - else - return META_FRAME_CONTROL_TITLE; -} diff --git a/src/ui/frames.h b/src/ui/frames.h deleted file mode 100644 index d81be1c72..000000000 --- a/src/ui/frames.h +++ /dev/null @@ -1,148 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity window frame manager widget */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * 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 . - */ - -#ifndef META_FRAMES_H -#define META_FRAMES_H - -#include -#include - -#include "meta/common.h" -#include "meta/types.h" -#include "ui/theme-private.h" -#include "ui/ui.h" - -typedef enum -{ - META_FRAME_CONTROL_NONE, - META_FRAME_CONTROL_TITLE, - META_FRAME_CONTROL_DELETE, - META_FRAME_CONTROL_MENU, - META_FRAME_CONTROL_MINIMIZE, - META_FRAME_CONTROL_MAXIMIZE, - META_FRAME_CONTROL_UNMAXIMIZE, - META_FRAME_CONTROL_RESIZE_SE, - META_FRAME_CONTROL_RESIZE_S, - META_FRAME_CONTROL_RESIZE_SW, - META_FRAME_CONTROL_RESIZE_N, - META_FRAME_CONTROL_RESIZE_NE, - META_FRAME_CONTROL_RESIZE_NW, - META_FRAME_CONTROL_RESIZE_W, - META_FRAME_CONTROL_RESIZE_E, - META_FRAME_CONTROL_CLIENT_AREA -} MetaFrameControl; - -/* This is one widget that manages all the window frames - * as subwindows. - */ - -#define META_TYPE_FRAMES (meta_frames_get_type ()) -#define META_FRAMES(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_FRAMES, MetaFrames)) -#define META_FRAMES_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_FRAMES, MetaFramesClass)) -#define META_IS_FRAMES(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_FRAMES)) -#define META_IS_FRAMES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_FRAMES)) -#define META_FRAMES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_FRAMES, MetaFramesClass)) - -typedef struct _MetaFrames MetaFrames; -typedef struct _MetaFramesClass MetaFramesClass; - -struct _MetaUIFrame -{ - MetaFrames *frames; - MetaWindow *meta_window; - Window xwindow; - GdkWindow *window; - MetaStyleInfo *style_info; - MetaFrameLayout *cache_layout; - PangoLayout *text_layout; - int text_height; - char *title; /* NULL once we have a layout */ - guint maybe_ignore_leave_notify : 1; - - /* FIXME get rid of this, it can just be in the MetaFrames struct */ - MetaFrameControl prelit_control; - MetaButtonState button_state; - int grab_button; - - gboolean is_frozen; -}; - -struct _MetaFrames -{ - GtkWindow parent_instance; - - MetaX11Display *x11_display; - - GHashTable *text_heights; - - GHashTable *frames; - - MetaStyleInfo *normal_style; - GHashTable *style_variants; - - MetaGrabOp current_grab_op; - MetaUIFrame *grab_frame; - guint grab_button; - gdouble grab_x; - gdouble grab_y; - - ClutterEventSequence *grab_touch; -}; - -struct _MetaFramesClass -{ - GtkWindowClass parent_class; - -}; - -GType meta_frames_get_type (void) G_GNUC_CONST; - -MetaFrames * meta_frames_new (MetaX11Display *x11_display); - -MetaUIFrame * meta_frames_manage_window (MetaFrames *frames, - MetaWindow *meta_window, - Window xwindow, - GdkWindow *window); - -void meta_ui_frame_unmanage (MetaUIFrame *frame); - -void meta_ui_frame_set_title (MetaUIFrame *frame, - const char *title); - -void meta_ui_frame_update_style (MetaUIFrame *frame); - -void meta_ui_frame_get_borders (MetaUIFrame *frame, - MetaFrameBorders *borders); - -cairo_region_t * meta_ui_frame_get_bounds (MetaUIFrame *frame); - -void meta_ui_frame_get_mask (MetaUIFrame *frame, - cairo_rectangle_int_t *frame_rect, - cairo_t *cr); - -void meta_ui_frame_move_resize (MetaUIFrame *frame, - int x, int y, int width, int height); - -void meta_ui_frame_queue_draw (MetaUIFrame *frame); - -gboolean meta_ui_frame_handle_event (MetaUIFrame *frame, const ClutterEvent *event); - -#endif diff --git a/src/ui/theme-private.h b/src/ui/theme-private.h deleted file mode 100644 index 269dbe867..000000000 --- a/src/ui/theme-private.h +++ /dev/null @@ -1,281 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Metacity Theme Rendering */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * 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 . - */ - -#ifndef META_THEME_PRIVATE_H -#define META_THEME_PRIVATE_H - -#include - -#include "meta/boxes.h" -#include "meta/common.h" -#include "meta/theme.h" - -/** - * MetaStyleInfo: (skip) - * - */ -typedef struct _MetaStyleInfo MetaStyleInfo; -/** - * MetaFrameLayout: (skip) - * - */ -typedef struct _MetaFrameLayout MetaFrameLayout; -/** - * MetaButtonSpace: (skip) - * - */ -typedef struct _MetaButtonSpace MetaButtonSpace; -/** - * MetaFrameGeometry: (skip) - * - */ -typedef struct _MetaFrameGeometry MetaFrameGeometry; - -/** - * Various parameters used to calculate the geometry of a frame. - **/ -struct _MetaFrameLayout -{ - /** Invisible border required by the theme */ - GtkBorder invisible_border; - /** Border/padding of the entire frame */ - GtkBorder frame_border; - /** Border/padding of the titlebar region */ - GtkBorder titlebar_border; - /** Border/padding of titlebar buttons */ - GtkBorder button_border; - - /** Margin of title */ - GtkBorder title_margin; - /** Margin of titlebar buttons */ - GtkBorder button_margin; - - /** Min size of titlebar region */ - GtkRequisition titlebar_min_size; - /** Min size of titlebar buttons */ - GtkRequisition button_min_size; - - /** Size of images in buttons */ - guint icon_size; - - /** Space between titlebar elements */ - guint titlebar_spacing; - - /** scale factor for title text */ - double title_scale; - - /** Whether title text will be displayed */ - guint has_title : 1; - - /** Whether we should hide the buttons */ - guint hide_buttons : 1; - - /** Radius of the top left-hand corner; 0 if not rounded */ - guint top_left_corner_rounded_radius; - /** Radius of the top right-hand corner; 0 if not rounded */ - guint top_right_corner_rounded_radius; - /** Radius of the bottom left-hand corner; 0 if not rounded */ - guint bottom_left_corner_rounded_radius; - /** Radius of the bottom right-hand corner; 0 if not rounded */ - guint bottom_right_corner_rounded_radius; -}; - -/** - * The computed size of a button (really just a way of tying its - * visible and clickable areas together). - * The reason for two different rectangles here is Fitts' law & maximized - * windows; see bug #97703 for more details. - */ -struct _MetaButtonSpace -{ - /** The screen area where the button's image is drawn */ - GdkRectangle visible; - /** The screen area where the button can be activated by clicking */ - GdkRectangle clickable; -}; - -/** - * Calculated actual geometry of the frame - */ -struct _MetaFrameGeometry -{ - MetaFrameBorders borders; - - int width; - int height; - - GdkRectangle title_rect; - - GtkBorder content_border; - - /* used for a memset hack */ -#define ADDRESS_OF_BUTTON_RECTS(fgeom) (((char*)(fgeom)) + G_STRUCT_OFFSET (MetaFrameGeometry, close_rect)) -#define LENGTH_OF_BUTTON_RECTS (G_STRUCT_OFFSET (MetaFrameGeometry, menu_rect) + sizeof (MetaButtonSpace) - G_STRUCT_OFFSET (MetaFrameGeometry, close_rect)) - - /* The button rects (if changed adjust memset hack) */ - MetaButtonSpace close_rect; - MetaButtonSpace max_rect; - MetaButtonSpace min_rect; - MetaButtonSpace menu_rect; - /* End of button rects (if changed adjust memset hack) */ - - /* Saved button layout */ - MetaButtonLayout button_layout; - int n_left_buttons; - int n_right_buttons; - - /* Round corners */ - guint top_left_corner_rounded_radius; - guint top_right_corner_rounded_radius; - guint bottom_left_corner_rounded_radius; - guint bottom_right_corner_rounded_radius; -}; - -typedef enum -{ - META_BUTTON_STATE_NORMAL, - META_BUTTON_STATE_PRESSED, - META_BUTTON_STATE_PRELIGHT, - META_BUTTON_STATE_LAST -} MetaButtonState; - -typedef enum -{ - META_BUTTON_TYPE_CLOSE, - META_BUTTON_TYPE_MAXIMIZE, - META_BUTTON_TYPE_MINIMIZE, - META_BUTTON_TYPE_MENU, - META_BUTTON_TYPE_LAST -} MetaButtonType; - -typedef enum -{ - META_STYLE_ELEMENT_WINDOW, - META_STYLE_ELEMENT_FRAME, - META_STYLE_ELEMENT_TITLEBAR, - META_STYLE_ELEMENT_TITLE, - META_STYLE_ELEMENT_BUTTON, - META_STYLE_ELEMENT_IMAGE, - META_STYLE_ELEMENT_LAST -} MetaStyleElement; - -struct _MetaStyleInfo -{ - int refcount; - - GtkStyleContext *styles[META_STYLE_ELEMENT_LAST]; -}; - -/* Kinds of frame... - * - * normal -> focused / unfocused - * max -> focused / unfocused - * shaded -> focused / unfocused - * max/shaded -> focused / unfocused - * - * so 4 states with 2 sub-states each, meaning 8 total - * - * 8 window states times 7 or 8 window types. Except some - * window types never get a frame so that narrows it down a bit. - * - */ -typedef enum -{ - META_FRAME_STATE_NORMAL, - META_FRAME_STATE_MAXIMIZED, - META_FRAME_STATE_TILED_LEFT, - META_FRAME_STATE_TILED_RIGHT, - META_FRAME_STATE_SHADED, - META_FRAME_STATE_MAXIMIZED_AND_SHADED, - META_FRAME_STATE_TILED_LEFT_AND_SHADED, - META_FRAME_STATE_TILED_RIGHT_AND_SHADED, - META_FRAME_STATE_LAST -} MetaFrameState; - -typedef enum -{ - META_FRAME_FOCUS_NO, - META_FRAME_FOCUS_YES, - META_FRAME_FOCUS_LAST -} MetaFrameFocus; - -/** - * A theme. This is a singleton class which groups all settings from a theme - * together. - */ -struct _MetaTheme -{ - MetaFrameLayout *layouts[META_FRAME_TYPE_LAST]; -}; - -void meta_frame_layout_apply_scale (const MetaFrameLayout *layout, - PangoFontDescription *font_desc); - -MetaFrameLayout* meta_theme_get_frame_layout (MetaTheme *theme, - MetaFrameType type); - -MetaStyleInfo * meta_theme_create_style_info (GdkScreen *screen, - const gchar *variant); -MetaStyleInfo * meta_style_info_ref (MetaStyleInfo *style); -void meta_style_info_unref (MetaStyleInfo *style_info); - -void meta_style_info_set_flags (MetaStyleInfo *style_info, - MetaFrameFlags flags); - -PangoFontDescription * meta_style_info_create_font_desc (MetaStyleInfo *style_info); - -void meta_theme_draw_frame (MetaTheme *theme, - MetaStyleInfo *style_info, - cairo_t *cr, - MetaFrameType type, - MetaFrameFlags flags, - int client_width, - int client_height, - PangoLayout *title_layout, - int text_height, - const MetaButtonLayout *button_layout, - MetaButtonState button_states[META_BUTTON_TYPE_LAST], - cairo_surface_t *mini_icon); - -void meta_theme_get_frame_borders (MetaTheme *theme, - MetaStyleInfo *style_info, - MetaFrameType type, - int text_height, - MetaFrameFlags flags, - MetaFrameBorders *borders); - -void meta_theme_calc_geometry (MetaTheme *theme, - MetaStyleInfo *style_info, - MetaFrameType type, - int text_height, - MetaFrameFlags flags, - int client_width, - int client_height, - const MetaButtonLayout *button_layout, - MetaFrameGeometry *fgeom); - -/* random stuff */ - -int meta_pango_font_desc_get_text_height (const PangoFontDescription *font_desc, - PangoContext *context); -int meta_theme_get_window_scaling_factor (void); - -#endif /* META_THEME_PRIVATE_H */ diff --git a/src/ui/theme.c b/src/ui/theme.c deleted file mode 100644 index a4c8a0de2..000000000 --- a/src/ui/theme.c +++ /dev/null @@ -1,1397 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * 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 . - */ - -#include "config.h" - -#include "ui/theme-private.h" - -#include -#include -#include -#include -#include - -#include "core/util-private.h" -#include "meta/prefs.h" -#include "ui/frames.h" - -static void scale_border (GtkBorder *border, double factor); - -static MetaFrameLayout * -meta_frame_layout_new (void) -{ - MetaFrameLayout *layout; - - layout = g_new0 (MetaFrameLayout, 1); - - /* Spacing as hardcoded in GTK+: - * https://git.gnome.org/browse/gtk+/tree/gtk/gtkheaderbar.c?h=gtk-3-14#n53 - */ - layout->titlebar_spacing = 6; - layout->has_title = TRUE; - layout->title_scale = PANGO_SCALE_MEDIUM; - layout->icon_size = META_MINI_ICON_WIDTH; - - return layout; -} - -static void -meta_frame_layout_free (MetaFrameLayout *layout) -{ - g_return_if_fail (layout != NULL); - - g_free (layout); -} - -static void -meta_frame_layout_get_borders (const MetaFrameLayout *layout, - int text_height, - MetaFrameFlags flags, - MetaFrameType type, - MetaFrameBorders *borders) -{ - int buttons_height, content_height, draggable_borders; - int scale = meta_theme_get_window_scaling_factor (); - - meta_frame_borders_clear (borders); - - /* For a full-screen window, we don't have any borders, visible or not. */ - if (flags & META_FRAME_FULLSCREEN) - return; - - g_return_if_fail (layout != NULL); - - if (!layout->has_title) - text_height = 0; - else - text_height = layout->title_margin.top + text_height + layout->title_margin.bottom; - - buttons_height = MAX ((int)layout->icon_size, layout->button_min_size.height) + - layout->button_margin.top + layout->button_border.top + - layout->button_margin.bottom + layout->button_border.bottom; - content_height = MAX (buttons_height, text_height); - content_height = MAX (content_height, layout->titlebar_min_size.height) + - layout->titlebar_border.top + layout->titlebar_border.bottom; - - borders->visible.top = layout->frame_border.top + content_height; - borders->visible.left = layout->frame_border.left; - borders->visible.right = layout->frame_border.right; - borders->visible.bottom = layout->frame_border.bottom; - - borders->invisible = layout->invisible_border; - - draggable_borders = meta_prefs_get_draggable_border_width (); - - if (flags & META_FRAME_ALLOWS_HORIZONTAL_RESIZE) - { - borders->invisible.left = MAX (borders->invisible.left, - draggable_borders - borders->visible.left); - borders->invisible.right = MAX (borders->invisible.right, - draggable_borders - borders->visible.right); - } - - if (flags & META_FRAME_ALLOWS_VERTICAL_RESIZE) - { - borders->invisible.bottom = MAX (borders->invisible.bottom, - draggable_borders - borders->visible.bottom); - - /* borders.visible.top is the height of the *title bar*. We can't do the same - * algorithm here, titlebars are expectedly much bigger. Just subtract a couple - * pixels to get a proper feel. */ - if (type != META_FRAME_TYPE_ATTACHED) - borders->invisible.top = MAX (borders->invisible.top, draggable_borders - 2); - } - - borders->total.left = borders->invisible.left + borders->visible.left; - borders->total.right = borders->invisible.right + borders->visible.right; - borders->total.bottom = borders->invisible.bottom + borders->visible.bottom; - borders->total.top = borders->invisible.top + borders->visible.top; - - /* Scale geometry for HiDPI, see comment in meta_frame_layout_draw_with_style() */ - scale_border (&borders->visible, scale); - scale_border (&borders->invisible, scale); - scale_border (&borders->total, scale); -} - -int -meta_theme_get_window_scaling_factor (void) -{ - GdkScreen *screen; - GValue value = G_VALUE_INIT; - - g_value_init (&value, G_TYPE_INT); - - screen = gdk_screen_get_default (); - if (gdk_screen_get_setting (screen, "gdk-window-scaling-factor", &value)) - return g_value_get_int (&value); - else - return 1; -} - -void -meta_frame_layout_apply_scale (const MetaFrameLayout *layout, - PangoFontDescription *font_desc) -{ - int size = pango_font_description_get_size (font_desc); - double scale = layout->title_scale / meta_theme_get_window_scaling_factor (); - pango_font_description_set_size (font_desc, MAX (size * scale, 1)); -} - -static MetaButtonSpace* -rect_for_function (MetaFrameGeometry *fgeom, - MetaFrameFlags flags, - MetaButtonFunction function, - MetaTheme *theme) -{ - switch (function) - { - case META_BUTTON_FUNCTION_MENU: - if (flags & META_FRAME_ALLOWS_MENU) - return &fgeom->menu_rect; - else - return NULL; - case META_BUTTON_FUNCTION_MINIMIZE: - if (flags & META_FRAME_ALLOWS_MINIMIZE) - return &fgeom->min_rect; - else - return NULL; - case META_BUTTON_FUNCTION_MAXIMIZE: - if (flags & META_FRAME_ALLOWS_MAXIMIZE) - return &fgeom->max_rect; - else - return NULL; - case META_BUTTON_FUNCTION_CLOSE: - if (flags & META_FRAME_ALLOWS_DELETE) - return &fgeom->close_rect; - else - return NULL; - - case META_BUTTON_FUNCTION_LAST: - return NULL; - } - - return NULL; -} - -static gboolean -strip_button (MetaButtonSpace *func_rects[MAX_BUTTONS_PER_CORNER], - int *n_rects, - MetaButtonSpace *to_strip) -{ - int i; - - i = 0; - while (i < *n_rects) - { - if (func_rects[i] == to_strip) - { - *n_rects -= 1; - - /* shift the other rects back in the array */ - while (i < *n_rects) - { - func_rects[i] = func_rects[i+1]; - - ++i; - } - - func_rects[i] = NULL; - - return TRUE; - } - - ++i; - } - - return FALSE; /* did not strip anything */ -} - -static void -get_padding_and_border (GtkStyleContext *style, - GtkBorder *border) -{ - GtkBorder tmp; - GtkStateFlags state = gtk_style_context_get_state (style); - - gtk_style_context_get_border (style, state, border); - gtk_style_context_get_padding (style, state, &tmp); - - border->left += tmp.left; - border->top += tmp.top; - border->right += tmp.right; - border->bottom += tmp.bottom; -} - -static void -get_min_size (GtkStyleContext *style, - GtkRequisition *requisition) -{ - gtk_style_context_get (style, gtk_style_context_get_state (style), - "min-width", &requisition->width, - "min-height", &requisition->height, - NULL); -} - -static void -scale_border (GtkBorder *border, - double factor) -{ - border->left *= factor; - border->right *= factor; - border->top *= factor; - border->bottom *= factor; -} - -static void -meta_frame_layout_sync_with_style (MetaFrameLayout *layout, - MetaStyleInfo *style_info, - MetaFrameFlags flags) -{ - GtkStyleContext *style; - GtkBorder border; - GtkRequisition requisition; - GdkRectangle clip_rect; - int border_radius, max_radius; - - meta_style_info_set_flags (style_info, flags); - - style = style_info->styles[META_STYLE_ELEMENT_FRAME]; - get_padding_and_border (style, &layout->frame_border); - scale_border (&layout->frame_border, layout->title_scale); - - gtk_render_background_get_clip (style, 0, 0, 0, 0, &clip_rect); - layout->invisible_border.left = -clip_rect.x; - layout->invisible_border.right = clip_rect.width + clip_rect.x; - layout->invisible_border.top = -clip_rect.y; - layout->invisible_border.bottom = clip_rect.height + clip_rect.y; - - if (layout->hide_buttons) - layout->icon_size = 0; - - if (!layout->has_title && layout->hide_buttons) - return; /* border-only - be done */ - - style = style_info->styles[META_STYLE_ELEMENT_TITLEBAR]; - gtk_style_context_get (style, gtk_style_context_get_state (style), - "border-radius", &border_radius, - NULL); - /* GTK+ currently does not allow us to look up radii of individual - * corners; however we don't clip the client area, so with the - * current trend of using small/no visible frame borders, most - * themes should work fine with this. - */ - layout->top_left_corner_rounded_radius = border_radius; - layout->top_right_corner_rounded_radius = border_radius; - max_radius = MIN (layout->frame_border.bottom, layout->frame_border.left); - layout->bottom_left_corner_rounded_radius = MAX (border_radius, max_radius); - max_radius = MIN (layout->frame_border.bottom, layout->frame_border.right); - layout->bottom_right_corner_rounded_radius = MAX (border_radius, max_radius); - - get_min_size (style, &layout->titlebar_min_size); - get_padding_and_border (style, &layout->titlebar_border); - scale_border (&layout->titlebar_border, layout->title_scale); - - style = style_info->styles[META_STYLE_ELEMENT_TITLE]; - gtk_style_context_get_margin (style, gtk_style_context_get_state (style), - &layout->title_margin); - scale_border (&layout->title_margin, layout->title_scale); - - style = style_info->styles[META_STYLE_ELEMENT_BUTTON]; - get_min_size (style, &layout->button_min_size); - get_padding_and_border (style, &layout->button_border); - scale_border (&layout->button_border, layout->title_scale); - gtk_style_context_get_margin (style, gtk_style_context_get_state (style), - &layout->button_margin); - scale_border (&layout->button_margin, layout->title_scale); - - style = style_info->styles[META_STYLE_ELEMENT_IMAGE]; - get_min_size (style, &requisition); - get_padding_and_border (style, &border); - scale_border (&border, layout->title_scale); - - layout->button_border.left += border.left; - layout->button_border.right += border.right; - layout->button_border.top += border.top; - layout->button_border.bottom += border.bottom; - - gtk_style_context_get_margin (style, gtk_style_context_get_state (style), - &border); - layout->button_border.left += border.left; - layout->button_border.right += border.right; - layout->button_border.top += border.top; - layout->button_border.bottom += border.bottom; - - layout->button_min_size.width = MAX(layout->button_min_size.width, - requisition.width); - layout->button_min_size.height = MAX(layout->button_min_size.height, - requisition.height); -} - -static void -meta_frame_layout_calc_geometry (MetaFrameLayout *layout, - MetaStyleInfo *style_info, - int text_height, - MetaFrameFlags flags, - int client_width, - int client_height, - const MetaButtonLayout *button_layout, - MetaFrameType type, - MetaFrameGeometry *fgeom, - MetaTheme *theme) -{ - int i, n_left, n_right, n_left_spacers, n_right_spacers; - int x; - int button_y; - int title_right_edge; - int width, height; - int content_width, content_height; - int button_width, button_height; - int min_size_for_rounding; - int scale = meta_theme_get_window_scaling_factor (); - - /* the left/right rects in order; the max # of rects - * is the number of button functions - */ - MetaButtonSpace *left_func_rects[MAX_BUTTONS_PER_CORNER]; - MetaButtonSpace *right_func_rects[MAX_BUTTONS_PER_CORNER]; - gboolean left_buttons_has_spacer[MAX_BUTTONS_PER_CORNER]; - gboolean right_buttons_has_spacer[MAX_BUTTONS_PER_CORNER]; - - MetaFrameBorders borders; - - meta_frame_layout_sync_with_style (layout, style_info, flags); - - meta_frame_layout_get_borders (layout, text_height, - flags, type, - &borders); - - fgeom->borders = borders; - - /* Scale geometry for HiDPI, see comment in meta_frame_layout_draw_with_style() */ - fgeom->content_border = layout->frame_border; - fgeom->content_border.left += layout->titlebar_border.left * scale; - fgeom->content_border.right += layout->titlebar_border.right * scale; - fgeom->content_border.top += layout->titlebar_border.top * scale; - fgeom->content_border.bottom += layout->titlebar_border.bottom * scale; - - width = client_width + borders.total.left + borders.total.right; - - height = borders.total.top + borders.total.bottom; - if (!(flags & META_FRAME_SHADED)) - height += client_height; - - fgeom->width = width; - fgeom->height = height; - - content_width = width - - (fgeom->content_border.left + borders.invisible.left) - - (fgeom->content_border.right + borders.invisible.right); - content_height = borders.visible.top - fgeom->content_border.top - fgeom->content_border.bottom; - - button_width = MAX ((int)layout->icon_size, layout->button_min_size.width) + - layout->button_border.left + layout->button_border.right; - button_height = MAX ((int)layout->icon_size, layout->button_min_size.height) + - layout->button_border.top + layout->button_border.bottom; - button_width *= scale; - button_height *= scale; - - /* FIXME all this code sort of pretends that duplicate buttons - * with the same function are allowed, but that breaks the - * code in frames.c, so isn't really allowed right now. - * Would need left_close_rect, right_close_rect, etc. - */ - - /* Init all button rects to 0, lame hack */ - memset (ADDRESS_OF_BUTTON_RECTS (fgeom), '\0', - LENGTH_OF_BUTTON_RECTS); - - n_left = 0; - n_right = 0; - n_left_spacers = 0; - n_right_spacers = 0; - - if (!layout->hide_buttons) - { - /* Try to fill in rects */ - for (i = 0; i < MAX_BUTTONS_PER_CORNER && button_layout->left_buttons[i] != META_BUTTON_FUNCTION_LAST; i++) - { - left_func_rects[n_left] = rect_for_function (fgeom, flags, - button_layout->left_buttons[i], - theme); - if (left_func_rects[n_left] != NULL) - { - left_buttons_has_spacer[n_left] = button_layout->left_buttons_has_spacer[i]; - if (button_layout->left_buttons_has_spacer[i]) - ++n_left_spacers; - - ++n_left; - } - } - - for (i = 0; i < MAX_BUTTONS_PER_CORNER && button_layout->right_buttons[i] != META_BUTTON_FUNCTION_LAST; i++) - { - right_func_rects[n_right] = rect_for_function (fgeom, flags, - button_layout->right_buttons[i], - theme); - if (right_func_rects[n_right] != NULL) - { - right_buttons_has_spacer[n_right] = button_layout->right_buttons_has_spacer[i]; - if (button_layout->right_buttons_has_spacer[i]) - ++n_right_spacers; - - ++n_right; - } - } - } - - /* Be sure buttons fit */ - while (n_left > 0 || n_right > 0) - { - int space_used_by_buttons; - - space_used_by_buttons = 0; - - space_used_by_buttons += layout->button_margin.left * scale * n_left; - space_used_by_buttons += button_width * n_left; - space_used_by_buttons += layout->button_margin.right * scale * n_left; - space_used_by_buttons += (button_width * 0.75) * n_left_spacers; - space_used_by_buttons += layout->titlebar_spacing * scale * MAX (n_left - 1, 0); - - space_used_by_buttons += layout->button_margin.left * scale * n_right; - space_used_by_buttons += button_width * n_right; - space_used_by_buttons += layout->button_margin.right * scale * n_right; - space_used_by_buttons += (button_width * 0.75) * n_right_spacers; - space_used_by_buttons += layout->titlebar_spacing * scale * MAX (n_right - 1, 0); - - if (space_used_by_buttons <= content_width) - break; /* Everything fits, bail out */ - - /* First try to remove separators */ - if (n_left_spacers > 0) - { - left_buttons_has_spacer[--n_left_spacers] = FALSE; - continue; - } - else if (n_right_spacers > 0) - { - right_buttons_has_spacer[--n_right_spacers] = FALSE; - continue; - } - - /* Otherwise we need to shave out a button. Shave - * min, max, close, then menu (menu is most useful); - * prefer the default button locations. - */ - if (strip_button (left_func_rects, &n_left, &fgeom->min_rect)) - continue; - else if (strip_button (right_func_rects, &n_right, &fgeom->min_rect)) - continue; - else if (strip_button (left_func_rects, &n_left, &fgeom->max_rect)) - continue; - else if (strip_button (right_func_rects, &n_right, &fgeom->max_rect)) - continue; - else if (strip_button (left_func_rects, &n_left, &fgeom->close_rect)) - continue; - else if (strip_button (right_func_rects, &n_right, &fgeom->close_rect)) - continue; - else if (strip_button (right_func_rects, &n_right, &fgeom->menu_rect)) - continue; - else if (strip_button (left_func_rects, &n_left, &fgeom->menu_rect)) - continue; - else - { - meta_bug ("Could not find a button to strip. n_left = %d n_right = %d", - n_left, n_right); - } - } - - /* Save the button layout */ - fgeom->button_layout = *button_layout; - fgeom->n_left_buttons = n_left; - fgeom->n_right_buttons = n_right; - - /* center buttons vertically */ - button_y = fgeom->content_border.top + borders.invisible.top + - (content_height - button_height) / 2; - - /* right edge of farthest-right button */ - x = width - fgeom->content_border.right - borders.invisible.right; - - i = n_right - 1; - while (i >= 0) - { - MetaButtonSpace *rect; - - if (x < 0) /* if we go negative, leave the buttons we don't get to as 0-width */ - break; - - x -= layout->button_margin.right * scale; - - rect = right_func_rects[i]; - rect->visible.x = x - button_width; - if (right_buttons_has_spacer[i]) - rect->visible.x -= (button_width * 0.75); - - rect->visible.y = button_y; - rect->visible.width = button_width; - rect->visible.height = button_height; - - if (flags & META_FRAME_MAXIMIZED || - flags & META_FRAME_TILED_LEFT || - flags & META_FRAME_TILED_RIGHT) - { - rect->clickable.x = rect->visible.x; - rect->clickable.y = 0; - rect->clickable.width = rect->visible.width; - rect->clickable.height = button_height + button_y; - - if (i == n_right - 1) - rect->clickable.width += fgeom->content_border.right; - - } - else - memmove (&(rect->clickable), &(rect->visible), sizeof (rect->clickable)); - - x = rect->visible.x - layout->button_margin.left * scale; - - if (i > 0) - x -= layout->titlebar_spacing * scale; - - --i; - } - - /* save right edge of titlebar for later use */ - title_right_edge = x; - - /* Now x changes to be position from the left and we go through - * the left-side buttons - */ - x = fgeom->content_border.left + borders.invisible.left; - for (i = 0; i < n_left; i++) - { - MetaButtonSpace *rect; - - x += layout->button_margin.left * scale; - - rect = left_func_rects[i]; - - rect->visible.x = x; - rect->visible.y = button_y; - rect->visible.width = button_width; - rect->visible.height = button_height; - - if (flags & META_FRAME_MAXIMIZED) - { - if (i==0) - { - rect->clickable.x = 0; - rect->clickable.width = button_width + x; - } - else - { - rect->clickable.x = rect->visible.x; - rect->clickable.width = button_width; - } - - rect->clickable.y = 0; - rect->clickable.height = button_height + button_y; - } - else - memmove (&(rect->clickable), &(rect->visible), sizeof (rect->clickable)); - - x = rect->visible.x + rect->visible.width + layout->button_margin.right * scale; - if (i < n_left - 1) - x += layout->titlebar_spacing * scale; - if (left_buttons_has_spacer[i]) - x += (button_width * 0.75); - } - - /* Center vertically in the available content area */ - fgeom->title_rect.x = x; - fgeom->title_rect.y = fgeom->content_border.top + borders.invisible.top + - (content_height - text_height) / 2; - fgeom->title_rect.width = title_right_edge - fgeom->title_rect.x; - fgeom->title_rect.height = text_height; - - /* Nuke title if it won't fit */ - if (fgeom->title_rect.width < 0 || - fgeom->title_rect.height < 0) - { - fgeom->title_rect.width = 0; - fgeom->title_rect.height = 0; - } - - if (flags & META_FRAME_SHADED) - min_size_for_rounding = 0; - else - min_size_for_rounding = 5 * scale; - - fgeom->top_left_corner_rounded_radius = 0; - fgeom->top_right_corner_rounded_radius = 0; - fgeom->bottom_left_corner_rounded_radius = 0; - fgeom->bottom_right_corner_rounded_radius = 0; - - if (borders.visible.top + borders.visible.left >= min_size_for_rounding) - fgeom->top_left_corner_rounded_radius = layout->top_left_corner_rounded_radius * scale; - if (borders.visible.top + borders.visible.right >= min_size_for_rounding) - fgeom->top_right_corner_rounded_radius = layout->top_right_corner_rounded_radius * scale; - - if (borders.visible.bottom + borders.visible.left >= min_size_for_rounding) - fgeom->bottom_left_corner_rounded_radius = layout->bottom_left_corner_rounded_radius * scale; - if (borders.visible.bottom + borders.visible.right >= min_size_for_rounding) - fgeom->bottom_right_corner_rounded_radius = layout->bottom_right_corner_rounded_radius * scale; -} - -static void -get_button_rect (MetaButtonType type, - const MetaFrameGeometry *fgeom, - GdkRectangle *rect) -{ - switch (type) - { - case META_BUTTON_TYPE_CLOSE: - *rect = fgeom->close_rect.visible; - break; - - case META_BUTTON_TYPE_MAXIMIZE: - *rect = fgeom->max_rect.visible; - break; - - case META_BUTTON_TYPE_MINIMIZE: - *rect = fgeom->min_rect.visible; - break; - - case META_BUTTON_TYPE_MENU: - *rect = fgeom->menu_rect.visible; - break; - - default: - case META_BUTTON_TYPE_LAST: - g_assert_not_reached (); - break; - } -} - -static const char * -get_class_from_button_type (MetaButtonType type) -{ - switch (type) - { - case META_BUTTON_TYPE_CLOSE: - return "close"; - case META_BUTTON_TYPE_MAXIMIZE: - return "maximize"; - case META_BUTTON_TYPE_MINIMIZE: - return "minimize"; - default: - return NULL; - } -} - -static void -meta_frame_layout_draw_with_style (MetaFrameLayout *layout, - MetaStyleInfo *style_info, - cairo_t *cr, - const MetaFrameGeometry *fgeom, - PangoLayout *title_layout, - MetaFrameFlags flags, - MetaButtonState button_states[META_BUTTON_TYPE_LAST], - cairo_surface_t *mini_icon) -{ - GtkStyleContext *style; - GtkStateFlags state; - MetaButtonType button_type; - GdkRectangle visible_rect; - GdkRectangle titlebar_rect; - GdkRectangle button_rect; - const MetaFrameBorders *borders; - cairo_surface_t *frame_surface; - double xscale, yscale; - int scale; - - /* We opt out of GTK+/Clutter's HiDPI handling, so we have to do the scaling - * ourselves; the nitty-gritty is a bit confusing, so here is an overview: - * - the values in MetaFrameLayout are always as they appear in the theme, - * i.e. unscaled - * - calculated values (borders, MetaFrameGeometry) include the scale - as - * the geometry is comprised of scaled decorations and the client size - * which we must not scale, we don't have another option - * - for drawing, we scale the canvas to have GTK+ render elements (borders, - * radii, ...) at the correct scale - as a result, we have to "unscale" - * the geometry again to not apply the scaling twice - * - As per commit e36b629c GTK expects the device scale to be set and match - * the final scaling or the surface caching won't take this in account - * breaking -gtk-scaled items. - */ - scale = meta_theme_get_window_scaling_factor (); - frame_surface = cairo_get_target (cr); - cairo_surface_get_device_scale (frame_surface, &xscale, &yscale); - cairo_surface_set_device_scale (frame_surface, scale, scale); - - borders = &fgeom->borders; - - visible_rect.x = borders->invisible.left / scale; - visible_rect.y = borders->invisible.top / scale; - visible_rect.width = (fgeom->width - borders->invisible.left - borders->invisible.right) / scale; - visible_rect.height = (fgeom->height - borders->invisible.top - borders->invisible.bottom) / scale; - - meta_style_info_set_flags (style_info, flags); - - style = style_info->styles[META_STYLE_ELEMENT_FRAME]; - gtk_render_background (style, cr, - visible_rect.x, visible_rect.y, - visible_rect.width, visible_rect.height); - gtk_render_frame (style, cr, - visible_rect.x, visible_rect.y, - visible_rect.width, visible_rect.height); - - titlebar_rect.x = visible_rect.x; - titlebar_rect.y = visible_rect.y; - titlebar_rect.width = visible_rect.width; - titlebar_rect.height = borders->visible.top / scale; - - style = style_info->styles[META_STYLE_ELEMENT_TITLEBAR]; - gtk_render_background (style, cr, - titlebar_rect.x, titlebar_rect.y, - titlebar_rect.width, titlebar_rect.height); - gtk_render_frame (style, cr, - titlebar_rect.x, titlebar_rect.y, - titlebar_rect.width, titlebar_rect.height); - - if (layout->has_title && title_layout) - { - PangoRectangle logical; - int text_width, x, y; - - pango_layout_set_width (title_layout, -1); - pango_layout_get_pixel_extents (title_layout, NULL, &logical); - - text_width = MIN(fgeom->title_rect.width / scale, logical.width); - - if (text_width < logical.width) - pango_layout_set_width (title_layout, PANGO_SCALE * text_width); - - /* Center within the frame if possible */ - x = titlebar_rect.x + (titlebar_rect.width - text_width) / 2; - y = titlebar_rect.y + (titlebar_rect.height - logical.height) / 2; - - if (x < fgeom->title_rect.x / scale) - x = fgeom->title_rect.x / scale; - else if (x + text_width > (fgeom->title_rect.x + fgeom->title_rect.width) / scale) - x = (fgeom->title_rect.x + fgeom->title_rect.width) / scale - text_width; - - style = style_info->styles[META_STYLE_ELEMENT_TITLE]; - gtk_render_layout (style, cr, x, y, title_layout); - } - - style = style_info->styles[META_STYLE_ELEMENT_BUTTON]; - state = gtk_style_context_get_state (style); - for (button_type = META_BUTTON_TYPE_CLOSE; button_type < META_BUTTON_TYPE_LAST; button_type++) - { - const char *button_class = get_class_from_button_type (button_type); - if (button_class) - gtk_style_context_add_class (style, button_class); - - get_button_rect (button_type, fgeom, &button_rect); - - button_rect.x /= scale; - button_rect.y /= scale; - button_rect.width /= scale; - button_rect.height /= scale; - - if (button_states[button_type] == META_BUTTON_STATE_PRELIGHT) - gtk_style_context_set_state (style, state | GTK_STATE_PRELIGHT); - else if (button_states[button_type] == META_BUTTON_STATE_PRESSED) - gtk_style_context_set_state (style, state | GTK_STATE_ACTIVE); - else - gtk_style_context_set_state (style, state); - - cairo_save (cr); - - if (button_rect.width > 0 && button_rect.height > 0) - { - cairo_surface_t *surface = NULL; - const char *icon_name = NULL; - - gtk_render_background (style, cr, - button_rect.x, button_rect.y, - button_rect.width, button_rect.height); - gtk_render_frame (style, cr, - button_rect.x, button_rect.y, - button_rect.width, button_rect.height); - - switch (button_type) - { - case META_BUTTON_TYPE_CLOSE: - icon_name = "window-close-symbolic"; - break; - case META_BUTTON_TYPE_MAXIMIZE: - if (flags & META_FRAME_MAXIMIZED) - icon_name = "window-restore-symbolic"; - else - icon_name = "window-maximize-symbolic"; - break; - case META_BUTTON_TYPE_MINIMIZE: - icon_name = "window-minimize-symbolic"; - break; - case META_BUTTON_TYPE_MENU: - icon_name = "open-menu-symbolic"; - break; - default: - icon_name = NULL; - break; - } - - if (icon_name) - { - GtkIconTheme *theme = gtk_icon_theme_get_default (); - g_autoptr (GtkIconInfo) info = NULL; - g_autoptr (GdkPixbuf) pixbuf = NULL; - - info = gtk_icon_theme_lookup_icon_for_scale (theme, icon_name, - layout->icon_size, scale, 0); - pixbuf = gtk_icon_info_load_symbolic_for_context (info, style, NULL, NULL); - surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, scale, NULL); - } - - if (surface) - { - float width, height; - int x, y; - - width = cairo_image_surface_get_width (surface) / scale; - height = cairo_image_surface_get_height (surface) / scale; - x = button_rect.x + (button_rect.width - layout->icon_size) / 2; - y = button_rect.y + (button_rect.height - layout->icon_size) / 2; - - cairo_translate (cr, x, y); - cairo_scale (cr, - layout->icon_size / width, - layout->icon_size / height); - cairo_set_source_surface (cr, surface, 0, 0); - cairo_paint (cr); - - cairo_surface_destroy (surface); - } - } - cairo_restore (cr); - if (button_class) - gtk_style_context_remove_class (style, button_class); - gtk_style_context_set_state (style, state); - } - - cairo_surface_set_device_scale (frame_surface, xscale, yscale); -} - -/** - * meta_theme_get_default: (skip) - * - */ -MetaTheme* -meta_theme_get_default (void) -{ - static MetaTheme *theme = NULL; - int frame_type; - - if (theme) - return theme; - - theme = meta_theme_new (); - - for (frame_type = 0; frame_type < META_FRAME_TYPE_LAST; frame_type++) - { - MetaFrameLayout *layout = meta_frame_layout_new (); - - switch (frame_type) - { - case META_FRAME_TYPE_NORMAL: - case META_FRAME_TYPE_DIALOG: - case META_FRAME_TYPE_MODAL_DIALOG: - case META_FRAME_TYPE_ATTACHED: - break; - case META_FRAME_TYPE_MENU: - case META_FRAME_TYPE_UTILITY: - layout->title_scale = PANGO_SCALE_SMALL; - break; - case META_FRAME_TYPE_BORDER: - layout->has_title = FALSE; - layout->hide_buttons = TRUE; - break; - default: - g_assert_not_reached (); - } - - theme->layouts[frame_type] = layout; - } - return theme; -} - -/** - * meta_theme_new: (skip) - * - */ -MetaTheme* -meta_theme_new (void) -{ - return g_new0 (MetaTheme, 1); -} - - -void -meta_theme_free (MetaTheme *theme) -{ - int i; - - g_return_if_fail (theme != NULL); - - for (i = 0; i < META_FRAME_TYPE_LAST; i++) - if (theme->layouts[i]) - meta_frame_layout_free (theme->layouts[i]); - - g_free (theme); -} - -MetaFrameLayout* -meta_theme_get_frame_layout (MetaTheme *theme, - MetaFrameType type) -{ - g_return_val_if_fail (type < META_FRAME_TYPE_LAST, NULL); - - return theme->layouts[type]; -} - -static GtkStyleContext * -create_style_context (GType widget_type, - GtkStyleContext *parent_style, - GtkCssProvider *provider, - const char *object_name, - const char *first_class, - ...) -{ - GtkStyleContext *style; - GtkStateFlags state; - GtkWidgetPath *path; - const char *name; - va_list ap; - - style = gtk_style_context_new (); - gtk_style_context_set_scale (style, meta_theme_get_window_scaling_factor ()); - gtk_style_context_set_parent (style, parent_style); - - if (parent_style) - path = gtk_widget_path_copy (gtk_style_context_get_path (parent_style)); - else - path = gtk_widget_path_new (); - - gtk_widget_path_append_type (path, widget_type); - - if (object_name) - gtk_widget_path_iter_set_object_name (path, -1, object_name); - - state = gtk_style_context_get_state (style); - if (meta_get_locale_direction() == META_LOCALE_DIRECTION_RTL) - { - state |= GTK_STATE_FLAG_DIR_RTL; - state &= ~GTK_STATE_FLAG_DIR_LTR; - } - else - { - state |= GTK_STATE_FLAG_DIR_LTR; - state &= ~GTK_STATE_FLAG_DIR_RTL; - } - gtk_style_context_set_state (style, state); - - va_start (ap, first_class); - for (name = first_class; name; name = va_arg (ap, const char *)) - gtk_widget_path_iter_add_class (path, -1, name); - va_end (ap); - - gtk_style_context_set_path (style, path); - gtk_widget_path_unref (path); - - gtk_style_context_add_provider (style, GTK_STYLE_PROVIDER (provider), - GTK_STYLE_PROVIDER_PRIORITY_SETTINGS); - - return style; -} - -static inline GtkCssProvider * -get_css_provider_for_theme_name (const gchar *theme_name, - const gchar *variant) -{ - static GtkCssProvider *default_provider = NULL; - - if (!theme_name || *theme_name == '\0') - { - if (G_UNLIKELY (default_provider == NULL)) - default_provider = gtk_css_provider_new (); - - return default_provider; - } - - return gtk_css_provider_get_named (theme_name, variant); -} - -MetaStyleInfo * -meta_theme_create_style_info (GdkScreen *screen, - const gchar *variant) -{ - MetaStyleInfo *style_info; - GtkCssProvider *provider; - char *theme_name; - - g_object_get (gtk_settings_get_for_screen (screen), - "gtk-theme-name", &theme_name, - NULL); - - provider = get_css_provider_for_theme_name (theme_name, variant); - g_free (theme_name); - - style_info = g_new0 (MetaStyleInfo, 1); - style_info->refcount = 1; - - style_info->styles[META_STYLE_ELEMENT_WINDOW] = - create_style_context (META_TYPE_FRAMES, - NULL, - provider, - "window", - GTK_STYLE_CLASS_BACKGROUND, - "ssd", - NULL); - style_info->styles[META_STYLE_ELEMENT_FRAME] = - create_style_context (META_TYPE_FRAMES, - style_info->styles[META_STYLE_ELEMENT_WINDOW], - provider, - "decoration", - NULL); - style_info->styles[META_STYLE_ELEMENT_TITLEBAR] = - create_style_context (GTK_TYPE_HEADER_BAR, - style_info->styles[META_STYLE_ELEMENT_FRAME], - provider, - "headerbar", - GTK_STYLE_CLASS_TITLEBAR, - GTK_STYLE_CLASS_HORIZONTAL, - "default-decoration", - NULL); - style_info->styles[META_STYLE_ELEMENT_TITLE] = - create_style_context (GTK_TYPE_LABEL, - style_info->styles[META_STYLE_ELEMENT_TITLEBAR], - provider, - "label", - GTK_STYLE_CLASS_TITLE, - NULL); - style_info->styles[META_STYLE_ELEMENT_BUTTON] = - create_style_context (GTK_TYPE_BUTTON, - style_info->styles[META_STYLE_ELEMENT_TITLEBAR], - provider, - "button", - "titlebutton", - NULL); - style_info->styles[META_STYLE_ELEMENT_IMAGE] = - create_style_context (GTK_TYPE_IMAGE, - style_info->styles[META_STYLE_ELEMENT_BUTTON], - provider, - "image", - NULL); - return style_info; -} - -MetaStyleInfo * -meta_style_info_ref (MetaStyleInfo *style_info) -{ - g_return_val_if_fail (style_info != NULL, NULL); - g_return_val_if_fail (style_info->refcount > 0, NULL); - - g_atomic_int_inc ((volatile int *)&style_info->refcount); - return style_info; -} - -void -meta_style_info_unref (MetaStyleInfo *style_info) -{ - g_return_if_fail (style_info != NULL); - g_return_if_fail (style_info->refcount > 0); - - if (g_atomic_int_dec_and_test ((volatile int *)&style_info->refcount)) - { - int i; - for (i = 0; i < META_STYLE_ELEMENT_LAST; i++) - g_object_unref (style_info->styles[i]); - g_free (style_info); - } -} - -static void -add_toplevel_class (GtkStyleContext *style, - const char *class_name) -{ - if (gtk_style_context_get_parent (style)) - { - GtkWidgetPath *path; - - path = gtk_widget_path_copy (gtk_style_context_get_path (style)); - gtk_widget_path_iter_add_class (path, 0, class_name); - gtk_style_context_set_path (style, path); - gtk_widget_path_unref (path); - } - else - gtk_style_context_add_class (style, class_name); -} - -static void -remove_toplevel_class (GtkStyleContext *style, - const char *class_name) -{ - if (gtk_style_context_get_parent (style)) - { - GtkWidgetPath *path; - - path = gtk_widget_path_copy (gtk_style_context_get_path (style)); - gtk_widget_path_iter_remove_class (path, 0, class_name); - gtk_style_context_set_path (style, path); - gtk_widget_path_unref (path); - } - else - gtk_style_context_remove_class (style, class_name); -} - -void -meta_style_info_set_flags (MetaStyleInfo *style_info, - MetaFrameFlags flags) -{ - GtkStyleContext *style; - const char *class_name = NULL; - gboolean backdrop; - GtkStateFlags state; - int i; - - backdrop = !(flags & META_FRAME_HAS_FOCUS); - - if (flags & META_FRAME_MAXIMIZED) - class_name = "maximized"; - else if (flags & META_FRAME_TILED_LEFT || - flags & META_FRAME_TILED_RIGHT) - class_name = "tiled"; - - for (i = 0; i < META_STYLE_ELEMENT_LAST; i++) - { - style = style_info->styles[i]; - - state = gtk_style_context_get_state (style); - if (backdrop) - gtk_style_context_set_state (style, state | GTK_STATE_FLAG_BACKDROP); - else - gtk_style_context_set_state (style, state & ~GTK_STATE_FLAG_BACKDROP); - - remove_toplevel_class (style, "maximized"); - remove_toplevel_class (style, "tiled"); - - if (class_name) - add_toplevel_class (style, class_name); - } -} - -PangoFontDescription* -meta_style_info_create_font_desc (MetaStyleInfo *style_info) -{ - PangoFontDescription *font_desc; - const PangoFontDescription *override = meta_prefs_get_titlebar_font (); - GtkStyleContext *context = style_info->styles[META_STYLE_ELEMENT_TITLE]; - - gtk_style_context_get (context, - gtk_style_context_get_state (context), - "font", &font_desc, NULL); - - if (override) - pango_font_description_merge (font_desc, override, TRUE); - - return font_desc; -} - -void -meta_theme_draw_frame (MetaTheme *theme, - MetaStyleInfo *style_info, - cairo_t *cr, - MetaFrameType type, - MetaFrameFlags flags, - int client_width, - int client_height, - PangoLayout *title_layout, - int text_height, - const MetaButtonLayout *button_layout, - MetaButtonState button_states[META_BUTTON_TYPE_LAST], - cairo_surface_t *mini_icon) -{ - MetaFrameGeometry fgeom; - MetaFrameLayout *layout; - - g_return_if_fail (type < META_FRAME_TYPE_LAST); - - layout = theme->layouts[type]; - - /* Parser is not supposed to allow this currently */ - if (layout == NULL) - return; - - meta_frame_layout_calc_geometry (layout, - style_info, - text_height, - flags, - client_width, client_height, - button_layout, - type, - &fgeom, - theme); - - meta_frame_layout_draw_with_style (layout, - style_info, - cr, - &fgeom, - title_layout, - flags, - button_states, - mini_icon); -} - -void -meta_theme_get_frame_borders (MetaTheme *theme, - MetaStyleInfo *style_info, - MetaFrameType type, - int text_height, - MetaFrameFlags flags, - MetaFrameBorders *borders) -{ - MetaFrameLayout *layout; - - g_return_if_fail (type < META_FRAME_TYPE_LAST); - - layout = theme->layouts[type]; - - meta_frame_borders_clear (borders); - - /* Parser is not supposed to allow this currently */ - if (layout == NULL) - return; - - meta_frame_layout_sync_with_style (layout, style_info, flags); - - meta_frame_layout_get_borders (layout, - text_height, - flags, type, - borders); -} - -void -meta_theme_calc_geometry (MetaTheme *theme, - MetaStyleInfo *style_info, - MetaFrameType type, - int text_height, - MetaFrameFlags flags, - int client_width, - int client_height, - const MetaButtonLayout *button_layout, - MetaFrameGeometry *fgeom) -{ - MetaFrameLayout *layout; - - g_return_if_fail (type < META_FRAME_TYPE_LAST); - - layout = theme->layouts[type]; - - /* Parser is not supposed to allow this currently */ - if (layout == NULL) - return; - - meta_frame_layout_calc_geometry (layout, - style_info, - text_height, - flags, - client_width, client_height, - button_layout, - type, - fgeom, - theme); -} - -/** - * meta_pango_font_desc_get_text_height: - * @font_desc: the font - * @context: the context of the font - * - * Returns the height of the letters in a particular font. - * - * Returns: the height of the letters - */ -int -meta_pango_font_desc_get_text_height (const PangoFontDescription *font_desc, - PangoContext *context) -{ - PangoFontMetrics *metrics; - PangoLanguage *lang; - int retval; - - lang = pango_context_get_language (context); - metrics = pango_context_get_metrics (context, font_desc, lang); - - retval = PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) + - pango_font_metrics_get_descent (metrics)); - - pango_font_metrics_unref (metrics); - - return retval; -} - -/** - * meta_frame_type_to_string: - * @type: a #MetaFrameType - * - * Converts a frame type enum value to the name string that would - * appear in the theme definition file. - * - * Return value: the string value - */ -const char* -meta_frame_type_to_string (MetaFrameType type) -{ - switch (type) - { - case META_FRAME_TYPE_NORMAL: - return "normal"; - case META_FRAME_TYPE_DIALOG: - return "dialog"; - case META_FRAME_TYPE_MODAL_DIALOG: - return "modal_dialog"; - case META_FRAME_TYPE_UTILITY: - return "utility"; - case META_FRAME_TYPE_MENU: - return "menu"; - case META_FRAME_TYPE_BORDER: - return "border"; - case META_FRAME_TYPE_ATTACHED: - return "attached"; -#if 0 - case META_FRAME_TYPE_TOOLBAR: - return "toolbar"; -#endif - case META_FRAME_TYPE_LAST: - break; - } - - return ""; -} diff --git a/src/ui/ui.c b/src/ui/ui.c deleted file mode 100644 index 2fbaad993..000000000 --- a/src/ui/ui.c +++ /dev/null @@ -1,281 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter interface for talking to GTK+ UI module */ - -/* - * Copyright (C) 2002 Havoc Pennington - * - * 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 . - */ - -#include "config.h" - -#include -#include -#include - -#include "meta/prefs.h" -#include "meta/util.h" -#include "ui/frames.h" -#include "ui/theme-private.h" -#include "ui/ui.h" -#include "x11/meta-x11-display-private.h" -#include "x11/meta-x11-window-control.h" - -struct _MetaUI -{ - Display *xdisplay; - MetaFrames *frames; - - /* For double-click tracking */ - gint button_click_number; - Window button_click_window; - int button_click_x; - int button_click_y; - guint32 button_click_time; -}; - -MetaUI * -meta_ui_new (MetaX11Display *x11_display) -{ - MetaUI *ui; - - if (!gtk_init_check (NULL, NULL)) - meta_fatal ("Unable to initialize GTK"); - - g_assert (x11_display->gdk_display == gdk_display_get_default ()); - - ui = g_new0 (MetaUI, 1); - ui->xdisplay = x11_display->xdisplay; - - ui->frames = meta_frames_new (x11_display); - /* GTK+ needs the frame-sync protocol to work in order to properly - * handle style changes. This means that the dummy widget we create - * to get the style for title bars actually needs to be mapped - * and fully tracked as a MetaWindow. Horrible, but mostly harmless - - * the window is a 1x1 override redirect window positioned offscreen. - */ - gtk_widget_show (GTK_WIDGET (ui->frames)); - - g_object_set_data (G_OBJECT (x11_display->gdk_display), "meta-ui", ui); - - return ui; -} - -void -meta_ui_free (MetaUI *ui) -{ - GdkDisplay *gdk_display; - - gtk_widget_destroy (GTK_WIDGET (ui->frames)); - - gdk_display = gdk_x11_lookup_xdisplay (ui->xdisplay); - g_object_set_data (G_OBJECT (gdk_display), "meta-ui", NULL); - - g_free (ui); -} - -static void -set_background_none (Display *xdisplay, - Window xwindow) -{ - XSetWindowAttributes attrs; - - attrs.background_pixmap = None; - XChangeWindowAttributes (xdisplay, xwindow, - CWBackPixmap, &attrs); -} - -MetaUIFrame * -meta_ui_create_frame (MetaUI *ui, - Display *xdisplay, - MetaWindow *meta_window, - Visual *xvisual, - gint x, - gint y, - gint width, - gint height, - gulong *create_serial) -{ - GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay); - GdkScreen *screen; - GdkWindowAttr attrs; - gint attributes_mask; - GdkWindow *window; - GdkVisual *visual; - - screen = gdk_display_get_default_screen (display); - - /* Default depth/visual handles clients with weird visuals; they can - * always be children of the root depth/visual obviously, but - * e.g. DRI games can't be children of a parent that has the same - * visual as the client. - */ - if (!xvisual) - visual = gdk_screen_get_system_visual (screen); - else - { - visual = gdk_x11_screen_lookup_visual (screen, - XVisualIDFromVisual (xvisual)); - } - - attrs.title = NULL; - - attrs.event_mask = GDK_EXPOSURE_MASK; - attrs.x = x; - attrs.y = y; - attrs.wclass = GDK_INPUT_OUTPUT; - attrs.visual = visual; - attrs.window_type = GDK_WINDOW_CHILD; - attrs.cursor = NULL; - attrs.wmclass_name = NULL; - attrs.wmclass_class = NULL; - attrs.override_redirect = FALSE; - - attrs.width = width; - attrs.height = height; - - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL; - - /* We make an assumption that gdk_window_new() is going to call - * XCreateWindow as it's first operation; this seems to be true currently - * as long as you pass in a colormap. - */ - if (create_serial) - *create_serial = XNextRequest (xdisplay); - window = - gdk_window_new (gdk_screen_get_root_window(screen), - &attrs, attributes_mask); - - gdk_window_resize (window, width, height); - set_background_none (xdisplay, GDK_WINDOW_XID (window)); - - return meta_frames_manage_window (ui->frames, meta_window, GDK_WINDOW_XID (window), window); -} - -void -meta_ui_map_frame (MetaUI *ui, - Window xwindow) -{ - GdkWindow *window; - GdkDisplay *display; - - display = gdk_x11_lookup_xdisplay (ui->xdisplay); - window = gdk_x11_window_lookup_for_display (display, xwindow); - - if (window) - gdk_window_show_unraised (window); -} - -void -meta_ui_unmap_frame (MetaUI *ui, - Window xwindow) -{ - GdkWindow *window; - GdkDisplay *display; - - display = gdk_x11_lookup_xdisplay (ui->xdisplay); - window = gdk_x11_window_lookup_for_display (display, xwindow); - - if (window) - gdk_window_hide (window); -} - -gboolean -meta_ui_window_should_not_cause_focus (Display *xdisplay, - Window xwindow) -{ - GdkWindow *window; - GdkDisplay *display; - - display = gdk_x11_lookup_xdisplay (xdisplay); - window = gdk_x11_window_lookup_for_display (display, xwindow); - - /* we shouldn't cause focus if we're an override redirect - * toplevel which is not foreign - */ - if (window && gdk_window_get_window_type (window) == GDK_WINDOW_TEMP) - return TRUE; - else - return FALSE; -} - -void -meta_ui_theme_get_frame_borders (MetaUI *ui, - MetaFrameType type, - MetaFrameFlags flags, - MetaFrameBorders *borders) -{ - GdkDisplay *display; - GdkScreen *screen; - int text_height; - MetaStyleInfo *style_info = NULL; - PangoContext *context; - const PangoFontDescription *font_desc; - PangoFontDescription *free_font_desc = NULL; - - display = gdk_x11_lookup_xdisplay (ui->xdisplay); - screen = gdk_display_get_default_screen (display); - - style_info = meta_theme_create_style_info (screen, NULL); - - context = gtk_widget_get_pango_context (GTK_WIDGET (ui->frames)); - font_desc = meta_prefs_get_titlebar_font (); - - if (!font_desc) - { - free_font_desc = meta_style_info_create_font_desc (style_info); - font_desc = (const PangoFontDescription *) free_font_desc; - } - - text_height = meta_pango_font_desc_get_text_height (font_desc, context); - - meta_theme_get_frame_borders (meta_theme_get_default (), - style_info, type, text_height, flags, - borders); - - if (free_font_desc) - pango_font_description_free (free_font_desc); - - if (style_info != NULL) - meta_style_info_unref (style_info); -} - -gboolean -meta_ui_window_is_widget (MetaUI *ui, - Window xwindow) -{ - GdkDisplay *display; - GdkWindow *window; - - display = gdk_x11_lookup_xdisplay (ui->xdisplay); - window = gdk_x11_window_lookup_for_display (display, xwindow); - - if (window) - { - void *user_data = NULL; - gdk_window_get_user_data (window, &user_data); - return user_data != NULL && user_data != ui->frames; - } - else - return FALSE; -} - -gboolean -meta_ui_window_is_dummy (MetaUI *ui, - Window xwindow) -{ - GdkWindow *frames_window = gtk_widget_get_window (GTK_WIDGET (ui->frames)); - return xwindow == gdk_x11_window_get_xid (frames_window); -} diff --git a/src/ui/ui.h b/src/ui/ui.h deleted file mode 100644 index e7a00e4e6..000000000 --- a/src/ui/ui.h +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter interface for talking to GTK+ UI module */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * 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 . - */ - -#ifndef META_UI_H -#define META_UI_H - -#include -#include -#include -#include -#include - -#include "core/util-private.h" -#include "meta/types.h" - -typedef struct _MetaUI MetaUI; -typedef struct _MetaUIFrame MetaUIFrame; - -typedef gboolean (* MetaEventFunc) (XEvent *xevent, gpointer data); - -MetaUI *meta_ui_new (MetaX11Display *x11_display); -void meta_ui_free (MetaUI *ui); - -void meta_ui_theme_get_frame_borders (MetaUI *ui, - MetaFrameType type, - MetaFrameFlags flags, - MetaFrameBorders *borders); - -MetaUIFrame * meta_ui_create_frame (MetaUI *ui, - Display *xdisplay, - MetaWindow *meta_window, - Visual *xvisual, - gint x, - gint y, - gint width, - gint height, - gulong *create_serial); -void meta_ui_move_resize_frame (MetaUI *ui, - Window frame, - int x, - int y, - int width, - int height); - -/* GDK insists on tracking map/unmap */ -void meta_ui_map_frame (MetaUI *ui, - Window xwindow); -void meta_ui_unmap_frame (MetaUI *ui, - Window xwindow); - -gboolean meta_ui_window_should_not_cause_focus (Display *xdisplay, - Window xwindow); - -gboolean meta_ui_window_is_widget (MetaUI *ui, - Window xwindow); - -META_EXPORT_TEST -gboolean meta_ui_window_is_dummy (MetaUI *ui, - Window xwindow); - -#endif diff --git a/src/wayland/meta-cursor-sprite-wayland.c b/src/wayland/meta-cursor-sprite-wayland.c deleted file mode 100644 index 7c14960ff..000000000 --- a/src/wayland/meta-cursor-sprite-wayland.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2015, 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 . - * - */ - -#include "config.h" - -#include "wayland/meta-cursor-sprite-wayland.h" - -struct _MetaCursorSpriteWayland -{ - MetaCursorSprite parent; - - MetaWaylandSurface *surface; -}; - -G_DEFINE_TYPE (MetaCursorSpriteWayland, - meta_cursor_sprite_wayland, - META_TYPE_CURSOR_SPRITE) - -static void -meta_cursor_sprite_wayland_realize_texture (MetaCursorSprite *sprite) -{ -} - -static gboolean -meta_cursor_sprite_wayland_is_animated (MetaCursorSprite *sprite) -{ - return FALSE; -} - -MetaCursorSpriteWayland * -meta_cursor_sprite_wayland_new (MetaWaylandSurface *surface) -{ - MetaCursorSpriteWayland *sprite_wayland; - - sprite_wayland = g_object_new (META_TYPE_CURSOR_SPRITE_WAYLAND, NULL); - sprite_wayland->surface = surface; - - return sprite_wayland; -} - -MetaWaylandBuffer * -meta_cursor_sprite_wayland_get_buffer (MetaCursorSpriteWayland *sprite_wayland) -{ - return meta_wayland_surface_get_buffer (sprite_wayland->surface); -} - -static void -meta_cursor_sprite_wayland_init (MetaCursorSpriteWayland *sprite_wayland) -{ -} - -static void -meta_cursor_sprite_wayland_class_init (MetaCursorSpriteWaylandClass *klass) -{ - MetaCursorSpriteClass *cursor_sprite_class = META_CURSOR_SPRITE_CLASS (klass); - - cursor_sprite_class->realize_texture = - meta_cursor_sprite_wayland_realize_texture; - cursor_sprite_class->is_animated = meta_cursor_sprite_wayland_is_animated; -} diff --git a/src/wayland/meta-cursor-sprite-wayland.h b/src/wayland/meta-cursor-sprite-wayland.h deleted file mode 100644 index 107698f3f..000000000 --- a/src/wayland/meta-cursor-sprite-wayland.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2013, 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 . - * - */ - -#ifndef META_CURSOR_SPRITE_WAYLAND_H -#define META_CURSOR_SPRITE_WAYLAND_H - -#include - -#include "backends/meta-cursor.h" -#include "wayland/meta-wayland-surface.h" - -#define META_TYPE_CURSOR_SPRITE_WAYLAND meta_cursor_sprite_wayland_get_type () -G_DECLARE_FINAL_TYPE (MetaCursorSpriteWayland, meta_cursor_sprite_wayland, - META, CURSOR_SPRITE_WAYLAND, MetaCursorSprite) - -MetaCursorSpriteWayland * meta_cursor_sprite_wayland_new (MetaWaylandSurface *surface); - -MetaWaylandBuffer * meta_cursor_sprite_wayland_get_buffer (MetaCursorSpriteWayland *sprite_wayland); - -#endif /* META_CURSOR_SPRITE_WAYLAND_H */ diff --git a/src/wayland/meta-pointer-confinement-wayland.c b/src/wayland/meta-pointer-confinement-wayland.c deleted file mode 100644 index 3df6ed0ab..000000000 --- a/src/wayland/meta-pointer-confinement-wayland.c +++ /dev/null @@ -1,267 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -/** - * SECTION:meta-pointer-confinement-wayland - * @title: MetaPointerConfinementWayland - * @short_description: A #MetaPointerConstraint implementing pointer confinement - * - * A MetaPointerConfinementConstraint implements the client pointer constraint - * "pointer confinement": the cursor should not be able to "break out" of a - * certain area defined by the client requesting it. - */ - -#include "config.h" - -#include "wayland/meta-pointer-confinement-wayland.h" - -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-pointer-constraint.h" -#include "wayland/meta-wayland-pointer-constraints.h" -#include "wayland/meta-wayland-pointer.h" -#include "wayland/meta-wayland-seat.h" -#include "wayland/meta-wayland-surface.h" - -typedef struct _MetaPointerConfinementWaylandPrivate MetaPointerConfinementWaylandPrivate; - -struct _MetaPointerConfinementWaylandPrivate -{ - MetaWaylandPointerConstraint *constraint; - gboolean enabled; -}; - -enum -{ - PROP_0, - PROP_WAYLAND_POINTER_CONSTRAINT, - N_PROPS, -}; - -static GParamSpec *props[N_PROPS] = { 0 }; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaPointerConfinementWayland, - meta_pointer_confinement_wayland, - G_TYPE_OBJECT) - -static void -meta_pointer_confinement_wayland_update (MetaPointerConfinementWayland *self) -{ - MetaPointerConstraint *constraint; - - constraint = - META_POINTER_CONFINEMENT_WAYLAND_GET_CLASS (self)->create_constraint (self); - meta_backend_set_client_pointer_constraint (meta_get_backend (), constraint); - g_object_unref (constraint); -} - -static void -surface_geometry_changed (MetaWaylandSurface *surface, - MetaPointerConfinementWayland *self) -{ - meta_pointer_confinement_wayland_update (self); -} - -static void -window_position_changed (MetaWindow *window, - MetaPointerConfinementWayland *self) -{ - meta_pointer_confinement_wayland_update (self); -} - -void -meta_pointer_confinement_wayland_enable (MetaPointerConfinementWayland *confinement) -{ - MetaPointerConfinementWaylandPrivate *priv; - MetaWaylandPointerConstraint *constraint; - MetaWaylandSurface *surface; - MetaWindow *window; - - priv = meta_pointer_confinement_wayland_get_instance_private (confinement); - g_assert (!priv->enabled); - - priv->enabled = TRUE; - constraint = priv->constraint; - - surface = meta_wayland_pointer_constraint_get_surface (constraint); - g_signal_connect_object (surface, - "geometry-changed", - G_CALLBACK (surface_geometry_changed), - confinement, - 0); - - window = meta_wayland_surface_get_window (surface); - if (window) - { - g_signal_connect_object (window, - "position-changed", - G_CALLBACK (window_position_changed), - confinement, - 0); - } - - meta_pointer_confinement_wayland_update (confinement); -} - -void -meta_pointer_confinement_wayland_disable (MetaPointerConfinementWayland *confinement) -{ - MetaPointerConfinementWaylandPrivate *priv; - MetaWaylandPointerConstraint *constraint; - MetaWaylandSurface *surface; - MetaWindow *window; - - priv = meta_pointer_confinement_wayland_get_instance_private (confinement); - constraint = priv->constraint; - g_assert (priv->enabled); - - priv->enabled = FALSE; - surface = meta_wayland_pointer_constraint_get_surface (constraint); - g_signal_handlers_disconnect_by_func (surface, surface_geometry_changed, - confinement); - - window = meta_wayland_surface_get_window (surface); - if (window) - { - g_signal_handlers_disconnect_by_func (window, window_position_changed, - confinement); - } - - meta_backend_set_client_pointer_constraint (meta_get_backend (), NULL); -} - -static void -meta_pointer_confinement_wayland_init (MetaPointerConfinementWayland *confinement_wayland) -{ -} - -static void -meta_pointer_confinement_wayland_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaPointerConfinementWayland *confinement; - MetaPointerConfinementWaylandPrivate *priv; - - confinement = META_POINTER_CONFINEMENT_WAYLAND (object); - priv = meta_pointer_confinement_wayland_get_instance_private (confinement); - - switch (prop_id) - { - case PROP_WAYLAND_POINTER_CONSTRAINT: - g_value_set_object (value, priv->constraint); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_pointer_confinement_wayland_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaPointerConfinementWayland *confinement; - MetaPointerConfinementWaylandPrivate *priv; - - confinement = META_POINTER_CONFINEMENT_WAYLAND (object); - priv = meta_pointer_confinement_wayland_get_instance_private (confinement); - - switch (prop_id) - { - case PROP_WAYLAND_POINTER_CONSTRAINT: - priv->constraint = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static MetaPointerConstraint * -meta_pointer_confinement_wayland_create_constraint (MetaPointerConfinementWayland *confinement) -{ - MetaPointerConfinementWaylandPrivate *priv; - MetaPointerConstraint *constraint; - MetaWaylandSurface *surface; - cairo_region_t *region; - float dx, dy; - - priv = meta_pointer_confinement_wayland_get_instance_private (confinement); - - surface = meta_wayland_pointer_constraint_get_surface (priv->constraint); - region = - meta_wayland_pointer_constraint_calculate_effective_region (priv->constraint); - - meta_wayland_surface_get_absolute_coordinates (surface, 0, 0, &dx, &dy); - cairo_region_translate (region, dx, dy); - - constraint = meta_pointer_constraint_new (region); - cairo_region_destroy (region); - - return constraint; -} - -static void -meta_pointer_confinement_wayland_class_init (MetaPointerConfinementWaylandClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->set_property = meta_pointer_confinement_wayland_set_property; - object_class->get_property = meta_pointer_confinement_wayland_get_property; - - klass->create_constraint = meta_pointer_confinement_wayland_create_constraint; - - props[PROP_WAYLAND_POINTER_CONSTRAINT] = - g_param_spec_object ("wayland-pointer-constraint", - "Wayland pointer constraint", - "Wayland pointer constraint", - META_TYPE_WAYLAND_POINTER_CONSTRAINT, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - g_object_class_install_properties (object_class, N_PROPS, props); -} - -MetaPointerConfinementWayland * -meta_pointer_confinement_wayland_new (MetaWaylandPointerConstraint *constraint) -{ - return g_object_new (META_TYPE_POINTER_CONFINEMENT_WAYLAND, - "wayland-pointer-constraint", constraint, - NULL); -} - -MetaWaylandPointerConstraint * -meta_pointer_confinement_wayland_get_wayland_pointer_constraint (MetaPointerConfinementWayland *confinement) -{ - MetaPointerConfinementWaylandPrivate *priv; - - priv = meta_pointer_confinement_wayland_get_instance_private (confinement); - return priv->constraint; -} diff --git a/src/wayland/meta-pointer-confinement-wayland.h b/src/wayland/meta-pointer-confinement-wayland.h deleted file mode 100644 index 4f265779c..000000000 --- a/src/wayland/meta-pointer-confinement-wayland.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#ifndef META_POINTER_CONFINEMENT_WAYLAND_H -#define META_POINTER_CONFINEMENT_WAYLAND_H - -#include - -#include "backends/meta-pointer-constraint.h" -#include "wayland/meta-wayland-pointer-constraints.h" - -G_BEGIN_DECLS - -#define META_TYPE_POINTER_CONFINEMENT_WAYLAND (meta_pointer_confinement_wayland_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaPointerConfinementWayland, - meta_pointer_confinement_wayland, - META, POINTER_CONFINEMENT_WAYLAND, - GObject) - -struct _MetaPointerConfinementWaylandClass -{ - GObjectClass parent_class; - - MetaPointerConstraint * (*create_constraint) (MetaPointerConfinementWayland *confinement); -}; - -MetaPointerConfinementWayland *meta_pointer_confinement_wayland_new (MetaWaylandPointerConstraint *constraint); -MetaWaylandPointerConstraint * - meta_pointer_confinement_wayland_get_wayland_pointer_constraint (MetaPointerConfinementWayland *confinement); -void meta_pointer_confinement_wayland_enable (MetaPointerConfinementWayland *confinement); -void meta_pointer_confinement_wayland_disable (MetaPointerConfinementWayland *confinement); - -G_END_DECLS - -#endif /* META_CONFINEMENT_WAYLAND_H */ diff --git a/src/wayland/meta-pointer-lock-wayland.c b/src/wayland/meta-pointer-lock-wayland.c deleted file mode 100644 index 9e0e8bcb8..000000000 --- a/src/wayland/meta-pointer-lock-wayland.c +++ /dev/null @@ -1,104 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -/** - * SECTION:meta-pointer-lock-wayland - * @title: MetaPointerLockWayland - * @short_description: A #MetaPointerConstraint implementing pointer lock. - * - * A MetaPointerLockConstraint implements the client pointer constraint "pointer - * lock": the cursor should not make any movement. - */ - -#include "config.h" - -#include "wayland/meta-pointer-lock-wayland.h" - -#include - -#include "backends/meta-backend-private.h" -#include "compositor/meta-surface-actor-wayland.h" - -struct _MetaPointerLockWayland -{ - GObject parent; - MetaWaylandPointerConstraint *constraint; -}; - -G_DEFINE_TYPE (MetaPointerLockWayland, meta_pointer_lock_wayland, - META_TYPE_POINTER_CONFINEMENT_WAYLAND) - -static MetaPointerConstraint * -meta_pointer_lock_wayland_create_constraint (MetaPointerConfinementWayland *confinement) -{ - MetaBackend *backend = meta_get_backend (); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - ClutterSeat *seat = clutter_backend_get_default_seat (clutter_backend); - ClutterInputDevice *pointer = clutter_seat_get_pointer (seat); - MetaWaylandPointerConstraint *wayland_constraint; - MetaPointerConstraint *constraint; - MetaWaylandSurface *surface; - graphene_point_t point; - cairo_region_t *region; - float sx, sy, x, y; - - clutter_seat_query_state (seat, pointer, NULL, &point, NULL); - wayland_constraint = - meta_pointer_confinement_wayland_get_wayland_pointer_constraint (confinement); - surface = meta_wayland_pointer_constraint_get_surface (wayland_constraint); - meta_wayland_surface_get_relative_coordinates (surface, - point.x, point.y, - &sx, &sy); - - meta_wayland_surface_get_absolute_coordinates (surface, sx, sy, &x, &y); - region = cairo_region_create_rectangle (&(cairo_rectangle_int_t) { (int) x, (int) y, 1 , 1 }); - - constraint = meta_pointer_constraint_new (region); - cairo_region_destroy (region); - - return constraint; -} - -MetaPointerConfinementWayland * -meta_pointer_lock_wayland_new (MetaWaylandPointerConstraint *constraint) -{ - return g_object_new (META_TYPE_POINTER_LOCK_WAYLAND, - "wayland-pointer-constraint", constraint, - NULL); -} - -static void -meta_pointer_lock_wayland_init (MetaPointerLockWayland *lock_wayland) -{ -} - -static void -meta_pointer_lock_wayland_class_init (MetaPointerLockWaylandClass *klass) -{ - MetaPointerConfinementWaylandClass *confinement_class = - META_POINTER_CONFINEMENT_WAYLAND_CLASS (klass); - - confinement_class->create_constraint = - meta_pointer_lock_wayland_create_constraint; -} diff --git a/src/wayland/meta-pointer-lock-wayland.h b/src/wayland/meta-pointer-lock-wayland.h deleted file mode 100644 index d52aaa30d..000000000 --- a/src/wayland/meta-pointer-lock-wayland.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#ifndef META_POINTER_LOCK_WAYLAND_H -#define META_POINTER_LOCK_WAYLAND_H - -#include - -#include "wayland/meta-pointer-confinement-wayland.h" - -G_BEGIN_DECLS - -#define META_TYPE_POINTER_LOCK_WAYLAND (meta_pointer_lock_wayland_get_type ()) -G_DECLARE_FINAL_TYPE (MetaPointerLockWayland, meta_pointer_lock_wayland, - META, POINTER_LOCK_WAYLAND, MetaPointerConfinementWayland) - -MetaPointerConfinementWayland *meta_pointer_lock_wayland_new (MetaWaylandPointerConstraint *constraint); - -G_END_DECLS - -#endif /* META_LOCK_WAYLAND_H */ diff --git a/src/wayland/meta-selection-source-wayland-private.h b/src/wayland/meta-selection-source-wayland-private.h deleted file mode 100644 index 38489530a..000000000 --- a/src/wayland/meta-selection-source-wayland-private.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2018 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: Carlos Garnacho - */ - -#ifndef META_SELECTION_SOURCE_WAYLAND_H -#define META_SELECTION_SOURCE_WAYLAND_H - -#include - -#include "meta/meta-selection-source.h" -#include "wayland/meta-wayland-data-device.h" - -#define META_TYPE_SELECTION_SOURCE_WAYLAND (meta_selection_source_wayland_get_type ()) - -G_DECLARE_FINAL_TYPE (MetaSelectionSourceWayland, - meta_selection_source_wayland, - META, SELECTION_SOURCE_WAYLAND, - MetaSelectionSource) - -MetaSelectionSource * meta_selection_source_wayland_new (MetaWaylandDataSource *source); - -#endif /* META_SELECTION_SOURCE_WAYLAND_H */ diff --git a/src/wayland/meta-selection-source-wayland.c b/src/wayland/meta-selection-source-wayland.c deleted file mode 100644 index 4f6f0c33c..000000000 --- a/src/wayland/meta-selection-source-wayland.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (C) 2018 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: Carlos Garnacho - */ - -#include "config.h" - -#include -#include - -#include "wayland/meta-selection-source-wayland-private.h" - -struct _MetaSelectionSourceWayland -{ - MetaSelectionSource parent_instance; - MetaWaylandDataSource *data_source; - GList *mimetypes; -}; - -G_DEFINE_TYPE (MetaSelectionSourceWayland, meta_selection_source_wayland, - META_TYPE_SELECTION_SOURCE) - -static void -meta_selection_source_wayland_finalize (GObject *object) -{ - MetaSelectionSourceWayland *source_wayland = META_SELECTION_SOURCE_WAYLAND (object); - - g_list_free_full (source_wayland->mimetypes, g_free); - - G_OBJECT_CLASS (meta_selection_source_wayland_parent_class)->finalize (object); -} - -static void -meta_selection_source_wayland_read_async (MetaSelectionSource *source, - const gchar *mimetype, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MetaSelectionSourceWayland *source_wayland = META_SELECTION_SOURCE_WAYLAND (source); - GInputStream *stream; - GTask *task; - int pipe_fds[2]; - - if (!g_unix_open_pipe (pipe_fds, FD_CLOEXEC, NULL)) - { - g_task_report_new_error (source, callback, user_data, - meta_selection_source_wayland_read_async, - G_IO_ERROR, G_IO_ERROR_FAILED, - "Could not open pipe to read wayland selection"); - return; - } - - if (!g_unix_set_fd_nonblocking (pipe_fds[0], TRUE, NULL) || - !g_unix_set_fd_nonblocking (pipe_fds[1], TRUE, NULL)) - { - g_task_report_new_error (source, callback, user_data, - meta_selection_source_wayland_read_async, - G_IO_ERROR, G_IO_ERROR_FAILED, - "Could not make pipe nonblocking"); - close (pipe_fds[0]); - close (pipe_fds[1]); - return; - } - - task = g_task_new (source, cancellable, callback, user_data); - g_task_set_source_tag (task, meta_selection_source_wayland_read_async); - - stream = g_unix_input_stream_new (pipe_fds[0], TRUE); - meta_wayland_data_source_send (source_wayland->data_source, - mimetype, pipe_fds[1]); - close (pipe_fds[1]); - - g_task_return_pointer (task, stream, g_object_unref); - g_object_unref (task); -} - -static GInputStream * -meta_selection_source_wayland_read_finish (MetaSelectionSource *source, - GAsyncResult *result, - GError **error) -{ - g_return_val_if_fail (g_task_is_valid (result, source), FALSE); - g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == - meta_selection_source_wayland_read_async, FALSE); - - return g_task_propagate_pointer (G_TASK (result), error); -} - -static GList * -meta_selection_source_wayland_get_mimetypes (MetaSelectionSource *source) -{ - MetaSelectionSourceWayland *source_wayland = META_SELECTION_SOURCE_WAYLAND (source); - - return g_list_copy_deep (source_wayland->mimetypes, - (GCopyFunc) g_strdup, NULL); -} - -static void -meta_selection_source_wayland_deactivated (MetaSelectionSource *source) -{ - MetaSelectionSourceWayland *source_wayland = - META_SELECTION_SOURCE_WAYLAND (source); - - meta_wayland_data_source_cancel (source_wayland->data_source); - META_SELECTION_SOURCE_CLASS (meta_selection_source_wayland_parent_class)->deactivated (source); -} - -static void -meta_selection_source_wayland_class_init (MetaSelectionSourceWaylandClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaSelectionSourceClass *source_class = META_SELECTION_SOURCE_CLASS (klass); - - object_class->finalize = meta_selection_source_wayland_finalize; - - source_class->deactivated = meta_selection_source_wayland_deactivated; - - source_class->read_async = meta_selection_source_wayland_read_async; - source_class->read_finish = meta_selection_source_wayland_read_finish; - source_class->get_mimetypes = meta_selection_source_wayland_get_mimetypes; -} - -static void -meta_selection_source_wayland_init (MetaSelectionSourceWayland *source) -{ -} - -static GList * -copy_string_array_to_list (struct wl_array *array) -{ - GList *l = NULL; - char **p; - - wl_array_for_each (p, array) - l = g_list_prepend (l, g_strdup (*p)); - - return l; -} - -MetaSelectionSource * -meta_selection_source_wayland_new (MetaWaylandDataSource *data_source) -{ - MetaSelectionSourceWayland *source_wayland; - struct wl_array *mimetypes; - - source_wayland = g_object_new (META_TYPE_SELECTION_SOURCE_WAYLAND, NULL); - source_wayland->data_source = data_source; - - mimetypes = meta_wayland_data_source_get_mime_types (data_source); - source_wayland->mimetypes = copy_string_array_to_list (mimetypes); - - return META_SELECTION_SOURCE (source_wayland); -} diff --git a/src/wayland/meta-wayland-activation.c b/src/wayland/meta-wayland-activation.c deleted file mode 100644 index 07bc1adaa..000000000 --- a/src/wayland/meta-wayland-activation.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (C) 2020 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: Carlos Garnacho - */ - -#include "config.h" - -#include "wayland/meta-wayland-activation.h" - -#include -#include - -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-versions.h" - -#include "xdg-activation-v1-server-protocol.h" - -typedef struct _MetaXdgActivationToken MetaXdgActivationToken; - -struct _MetaWaylandActivation -{ - MetaWaylandCompositor *compositor; - struct wl_list resource_list; - struct wl_list token_list; - GHashTable *tokens; -}; - -struct _MetaXdgActivationToken -{ - MetaWaylandSurface *surface; - MetaWaylandSeat *seat; - MetaWaylandActivation *activation; - MetaStartupSequence *sequence; - char *app_id; - char *token; - uint32_t serial; - gulong sequence_complete_id; - gboolean committed; -}; - -static void -unbind_resource (struct wl_resource *resource) -{ - wl_list_remove (wl_resource_get_link (resource)); -} - -static void -token_set_serial (struct wl_client *client, - struct wl_resource *resource, - uint32_t serial, - struct wl_resource *seat_resource) -{ - MetaXdgActivationToken *token = wl_resource_get_user_data (resource); - MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); - - token->serial = serial; - token->seat = seat; -} - -static void -token_set_app_id (struct wl_client *client, - struct wl_resource *resource, - const char *app_id) -{ - MetaXdgActivationToken *token = wl_resource_get_user_data (resource); - - g_clear_pointer (&token->app_id, g_free); - token->app_id = g_strdup (app_id); -} - -static void -token_set_surface (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *surface_resource) -{ - MetaXdgActivationToken *token = wl_resource_get_user_data (resource); - MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); - - token->surface = surface; -} - -static void -sequence_complete_cb (MetaStartupSequence *sequence, - MetaXdgActivationToken *token) -{ - MetaWaylandActivation *activation = token->activation; - MetaDisplay *display = meta_get_display (); - - meta_startup_notification_remove_sequence (display->startup_notification, - sequence); - g_hash_table_remove (activation->tokens, token->token); -} - -static char * -create_startup_token (MetaWaylandActivation *activation, - MetaDisplay *display) -{ - g_autofree char *uuid = NULL, *token = NULL; - - do - { - g_clear_pointer (&uuid, g_free); - g_clear_pointer (&token, g_free); - uuid = g_uuid_string_random (); - token = g_strdup_printf ("%s_TIME%d", uuid, - meta_display_get_current_time (display)); - } - while (g_hash_table_contains (activation->tokens, token)); - - return g_steal_pointer (&token); -} - -static void -token_commit (struct wl_client *client, - struct wl_resource *resource) -{ - MetaXdgActivationToken *token = wl_resource_get_user_data (resource); - MetaWaylandActivation *activation = token->activation; - MetaDisplay *display = meta_get_display (); - uint32_t timestamp; - - if (token->committed) - { - wl_resource_post_error (resource, - XDG_ACTIVATION_TOKEN_V1_ERROR_ALREADY_USED, - "Activation token was already used"); - return; - } - - timestamp = meta_display_get_current_time_roundtrip (display); - - token->committed = TRUE; - token->token = create_startup_token (activation, display); - token->sequence = g_object_new (META_TYPE_STARTUP_SEQUENCE, - "id", token->token, - "application-id", token->app_id, - "timestamp", timestamp, - NULL); - - token->sequence_complete_id = - g_signal_connect (token->sequence, - "complete", - G_CALLBACK (sequence_complete_cb), - token); - - meta_startup_notification_add_sequence (display->startup_notification, - token->sequence); - - xdg_activation_token_v1_send_done (resource, token->token); - g_hash_table_insert (activation->tokens, token->token, token); -} - -static void -token_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static const struct xdg_activation_token_v1_interface token_interface = { - token_set_serial, - token_set_app_id, - token_set_surface, - token_commit, - token_destroy, -}; - -static void -meta_xdg_activation_token_free (MetaXdgActivationToken *token) -{ - if (token->sequence) - { - g_clear_signal_handler (&token->sequence_complete_id, - token->sequence); - g_clear_object (&token->sequence); - } - - g_free (token->app_id); - g_free (token->token); - g_free (token); -} - -static void -meta_wayland_activation_token_create_new_resource (MetaWaylandActivation *activation, - struct wl_client *client, - struct wl_resource *activation_resource, - uint32_t id) -{ - MetaXdgActivationToken *token; - struct wl_resource *token_resource; - - token = g_new0 (MetaXdgActivationToken, 1); - token->activation = activation; - - token_resource = - wl_resource_create (client, &xdg_activation_token_v1_interface, - wl_resource_get_version (activation_resource), - id); - wl_resource_set_implementation (token_resource, &token_interface, - token, unbind_resource); - wl_resource_set_user_data (token_resource, token); - wl_list_insert (&activation->token_list, - wl_resource_get_link (token_resource)); -} - -static void -activation_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -activation_get_activation_token (struct wl_client *client, - struct wl_resource *resource, - uint32_t id) -{ - MetaWaylandActivation *activation = wl_resource_get_user_data (resource); - - meta_wayland_activation_token_create_new_resource (activation, - client, - resource, - id); -} - -static void -activation_activate (struct wl_client *client, - struct wl_resource *resource, - const char *token_str, - struct wl_resource *surface_resource) -{ - MetaWaylandActivation *activation = wl_resource_get_user_data (resource); - MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); - MetaXdgActivationToken *token; - MetaWindow *window; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - token = g_hash_table_lookup (activation->tokens, token_str); - if (!token) - return; - - if (meta_wayland_seat_get_grab_info (token->seat, - token->surface, - token->serial, - FALSE, NULL, NULL)) - { - uint32_t timestamp; - int32_t workspace_idx; - - workspace_idx = meta_startup_sequence_get_workspace (token->sequence); - timestamp = meta_startup_sequence_get_timestamp (token->sequence); - - if (workspace_idx >= 0) - meta_window_change_workspace_by_index (window, workspace_idx, TRUE); - - meta_window_activate_full (window, timestamp, - META_CLIENT_TYPE_APPLICATION, NULL); - } - else - { - meta_window_set_demands_attention (window); - } - - meta_startup_sequence_complete (token->sequence); -} - -static const struct xdg_activation_v1_interface activation_interface = { - activation_destroy, - activation_get_activation_token, - activation_activate, -}; - -static void -bind_activation (struct wl_client *client, - void *data, - uint32_t version, - uint32_t id) -{ - MetaWaylandCompositor *compositor = data; - MetaWaylandActivation *activation = compositor->activation; - struct wl_resource *resource; - - resource = wl_resource_create (client, &xdg_activation_v1_interface, - MIN (version, META_XDG_ACTIVATION_V1_VERSION), - id); - wl_resource_set_implementation (resource, &activation_interface, - activation, unbind_resource); - wl_resource_set_user_data (resource, activation); - wl_list_insert (&activation->resource_list, - wl_resource_get_link (resource)); -} - -void -meta_wayland_activation_init (MetaWaylandCompositor *compositor) -{ - MetaWaylandActivation *activation; - - activation = g_new0 (MetaWaylandActivation, 1); - activation->compositor = compositor; - wl_list_init (&activation->resource_list); - wl_list_init (&activation->token_list); - - activation->tokens = - g_hash_table_new_full (g_str_hash, g_str_equal, - NULL, - (GDestroyNotify) meta_xdg_activation_token_free); - - wl_global_create (compositor->wayland_display, - &xdg_activation_v1_interface, - META_XDG_ACTIVATION_V1_VERSION, - compositor, bind_activation); - - compositor->activation = activation; -} diff --git a/src/wayland/meta-wayland-activation.h b/src/wayland/meta-wayland-activation.h deleted file mode 100644 index 8fcc0fa42..000000000 --- a/src/wayland/meta-wayland-activation.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2020 Red Hat - * - * 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 . - * - * Author: Carlos Garnacho - */ - -#ifndef META_WAYLAND_ACTIVATION_H -#define META_WAYLAND_ACTIVATION_H - -#include -#include - -#include "wayland/meta-wayland-types.h" - -void meta_wayland_activation_init (MetaWaylandCompositor *compositor); - -#endif /* META_WAYLAND_ACTIVATION_H */ diff --git a/src/wayland/meta-wayland-actor-surface.c b/src/wayland/meta-wayland-actor-surface.c deleted file mode 100644 index bdebe6b2b..000000000 --- a/src/wayland/meta-wayland-actor-surface.c +++ /dev/null @@ -1,460 +0,0 @@ -/* - * Copyright (C) 2012,2013 Intel Corporation - * Copyright (C) 2013-2017 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "wayland/meta-wayland-actor-surface.h" - -#include "backends/meta-backend-private.h" -#include "backends/meta-logical-monitor.h" -#include "compositor/meta-surface-actor-wayland.h" -#include "compositor/meta-window-actor-wayland.h" -#include "compositor/region-utils.h" -#include "wayland/meta-wayland-buffer.h" -#include "wayland/meta-wayland-surface.h" -#include "wayland/meta-window-wayland.h" -#include "wayland/meta-xwayland-surface.h" - -typedef struct _MetaWaylandActorSurfacePrivate MetaWaylandActorSurfacePrivate; - -struct _MetaWaylandActorSurfacePrivate -{ - MetaSurfaceActor *actor; - - gulong actor_destroyed_handler_id; - - struct wl_list frame_callback_list; -}; - -G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaWaylandActorSurface, - meta_wayland_actor_surface, - META_TYPE_WAYLAND_SURFACE_ROLE) - -static void -meta_wayland_actor_surface_constructed (GObject *object) -{ - G_OBJECT_CLASS (meta_wayland_actor_surface_parent_class)->constructed (object); - - meta_wayland_actor_surface_reset_actor (META_WAYLAND_ACTOR_SURFACE (object)); -} - -static void -clear_surface_actor (MetaWaylandActorSurface *actor_surface) -{ - MetaWaylandActorSurfacePrivate *priv = - meta_wayland_actor_surface_get_instance_private (actor_surface); - MetaWaylandSurfaceRole *surface_role = - META_WAYLAND_SURFACE_ROLE (actor_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - - if (!priv->actor) - return; - - g_clear_signal_handler (&priv->actor_destroyed_handler_id, priv->actor); - g_signal_handlers_disconnect_by_func (priv->actor, - meta_wayland_surface_notify_geometry_changed, - surface); - g_signal_handlers_disconnect_by_func (priv->actor, - meta_wayland_surface_update_outputs, - surface); - g_clear_object (&priv->actor); -} - -static void -meta_wayland_actor_surface_dispose (GObject *object) -{ - MetaWaylandActorSurface *actor_surface = META_WAYLAND_ACTOR_SURFACE (object); - MetaWaylandActorSurfacePrivate *priv = - meta_wayland_actor_surface_get_instance_private (actor_surface); - MetaWaylandFrameCallback *cb, *next; - - if (priv->actor) - { - clutter_actor_set_reactive (CLUTTER_ACTOR (priv->actor), FALSE); - clear_surface_actor (actor_surface); - } - - wl_list_for_each_safe (cb, next, &priv->frame_callback_list, link) - wl_resource_destroy (cb->resource); - - G_OBJECT_CLASS (meta_wayland_actor_surface_parent_class)->dispose (object); -} - -static void -meta_wayland_actor_surface_assigned (MetaWaylandSurfaceRole *surface_role) -{ - MetaWaylandActorSurfacePrivate *priv = - meta_wayland_actor_surface_get_instance_private (META_WAYLAND_ACTOR_SURFACE (surface_role)); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - - if (wl_list_empty (&surface->unassigned.pending_frame_callback_list)) - return; - - wl_list_insert_list (priv->frame_callback_list.prev, - &surface->unassigned.pending_frame_callback_list); - wl_list_init (&surface->unassigned.pending_frame_callback_list); - - meta_wayland_compositor_add_frame_callback_surface (surface->compositor, - surface); -} - -void -meta_wayland_actor_surface_queue_frame_callbacks (MetaWaylandActorSurface *actor_surface, - MetaWaylandSurfaceState *pending) -{ - MetaWaylandActorSurfacePrivate *priv = - meta_wayland_actor_surface_get_instance_private (actor_surface); - MetaWaylandSurfaceRole *surface_role = - META_WAYLAND_SURFACE_ROLE (actor_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - - if (wl_list_empty (&pending->frame_callback_list)) - return; - - wl_list_insert_list (priv->frame_callback_list.prev, - &pending->frame_callback_list); - wl_list_init (&pending->frame_callback_list); - - meta_wayland_compositor_add_frame_callback_surface (surface->compositor, - surface); -} - -void -meta_wayland_actor_surface_emit_frame_callbacks (MetaWaylandActorSurface *actor_surface, - uint32_t timestamp_ms) -{ - MetaWaylandActorSurfacePrivate *priv = - meta_wayland_actor_surface_get_instance_private (actor_surface); - - while (!wl_list_empty (&priv->frame_callback_list)) - { - MetaWaylandFrameCallback *callback = - wl_container_of (priv->frame_callback_list.next, callback, link); - - wl_callback_send_done (callback->resource, timestamp_ms); - wl_resource_destroy (callback->resource); - } -} - -double -meta_wayland_actor_surface_get_geometry_scale (MetaWaylandActorSurface *actor_surface) -{ - MetaWaylandActorSurfaceClass *actor_surface_class = - META_WAYLAND_ACTOR_SURFACE_GET_CLASS (actor_surface); - - return actor_surface_class->get_geometry_scale (actor_surface); -} - -static void -meta_wayland_actor_surface_real_sync_actor_state (MetaWaylandActorSurface *actor_surface) -{ - MetaWaylandActorSurfacePrivate *priv = - meta_wayland_actor_surface_get_instance_private (actor_surface); - MetaWaylandSurfaceRole *surface_role = - META_WAYLAND_SURFACE_ROLE (actor_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaSurfaceActor *surface_actor; - MetaShapedTexture *stex; - MetaWaylandBuffer *buffer; - cairo_rectangle_int_t surface_rect; - MetaWaylandSurface *subsurface_surface; - - surface_actor = priv->actor; - stex = meta_surface_actor_get_texture (surface_actor); - - buffer = surface->buffer_ref->buffer; - if (buffer) - { - CoglSnippet *snippet; - gboolean is_y_inverted; - - snippet = meta_wayland_buffer_create_snippet (buffer); - is_y_inverted = meta_wayland_buffer_is_y_inverted (buffer); - - meta_shaped_texture_set_texture (stex, surface->texture); - meta_shaped_texture_set_snippet (stex, snippet); - meta_shaped_texture_set_is_y_inverted (stex, is_y_inverted); - meta_shaped_texture_set_buffer_scale (stex, surface->scale); - cogl_clear_object (&snippet); - } - else - { - meta_shaped_texture_set_texture (stex, NULL); - } - - surface_rect = (cairo_rectangle_int_t) { - .width = meta_wayland_surface_get_width (surface), - .height = meta_wayland_surface_get_height (surface), - }; - - if (surface->input_region) - { - cairo_region_t *input_region; - - input_region = cairo_region_copy (surface->input_region); - cairo_region_intersect_rectangle (input_region, &surface_rect); - meta_surface_actor_set_input_region (surface_actor, input_region); - cairo_region_destroy (input_region); - } - else - { - meta_surface_actor_set_input_region (surface_actor, NULL); - } - - if (!META_IS_XWAYLAND_SURFACE (surface_role)) - { - if (!meta_shaped_texture_has_alpha (stex)) - { - cairo_region_t *opaque_region; - - opaque_region = cairo_region_create_rectangle (&surface_rect); - meta_surface_actor_set_opaque_region (surface_actor, opaque_region); - cairo_region_destroy (opaque_region); - } - else if (surface->opaque_region) - { - cairo_region_t *opaque_region; - - opaque_region = cairo_region_copy (surface->opaque_region); - cairo_region_intersect_rectangle (opaque_region, &surface_rect); - meta_surface_actor_set_opaque_region (surface_actor, opaque_region); - cairo_region_destroy (opaque_region); - } - else - { - meta_surface_actor_set_opaque_region (surface_actor, NULL); - } - } - - meta_surface_actor_set_transform (surface_actor, surface->buffer_transform); - - if (surface->viewport.has_src_rect) - { - meta_surface_actor_set_viewport_src_rect (surface_actor, - &surface->viewport.src_rect); - } - else - { - meta_surface_actor_reset_viewport_src_rect (surface_actor); - } - - if (surface->viewport.has_dst_size) - { - meta_surface_actor_set_viewport_dst_size (surface_actor, - surface->viewport.dst_width, - surface->viewport.dst_height); - } - else - { - meta_surface_actor_reset_viewport_dst_size (surface_actor); - } - - meta_shaped_texture_ensure_size_valid (stex); - - META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface) - { - MetaWaylandActorSurface *actor_surface; - - actor_surface = META_WAYLAND_ACTOR_SURFACE (subsurface_surface->role); - meta_wayland_actor_surface_sync_actor_state (actor_surface); - } -} - -void -meta_wayland_actor_surface_sync_actor_state (MetaWaylandActorSurface *actor_surface) -{ - MetaWaylandActorSurfaceClass *actor_surface_class = - META_WAYLAND_ACTOR_SURFACE_GET_CLASS (actor_surface); - - actor_surface_class->sync_actor_state (actor_surface); -} - -static void -meta_wayland_actor_surface_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending) -{ - MetaWaylandActorSurface *actor_surface = - META_WAYLAND_ACTOR_SURFACE (surface_role); - MetaWaylandActorSurfacePrivate *priv = - meta_wayland_actor_surface_get_instance_private (actor_surface); - - if (!wl_list_empty (&pending->frame_callback_list) && - priv->actor && - clutter_actor_is_mapped (CLUTTER_ACTOR (priv->actor)) && - !meta_surface_actor_is_obscured (priv->actor)) - { - ClutterActor *stage = - clutter_actor_get_stage (CLUTTER_ACTOR (priv->actor)); - - clutter_stage_schedule_update (CLUTTER_STAGE (stage)); - } - - meta_wayland_actor_surface_queue_frame_callbacks (actor_surface, pending); - - meta_wayland_actor_surface_sync_actor_state (actor_surface); -} - -static gboolean -meta_wayland_actor_surface_is_on_logical_monitor (MetaWaylandSurfaceRole *surface_role, - MetaLogicalMonitor *logical_monitor) -{ - MetaWaylandActorSurfacePrivate *priv = - meta_wayland_actor_surface_get_instance_private (META_WAYLAND_ACTOR_SURFACE (surface_role)); - ClutterActor *actor = CLUTTER_ACTOR (priv->actor); - float x, y, width, height; - cairo_rectangle_int_t actor_rect; - cairo_region_t *region; - MetaRectangle logical_monitor_layout; - gboolean is_on_monitor; - - if (!clutter_actor_is_mapped (actor) && - !clutter_actor_has_mapped_clones (actor)) - return FALSE; - - clutter_actor_get_transformed_position (actor, &x, &y); - clutter_actor_get_transformed_size (actor, &width, &height); - - actor_rect.x = (int) roundf (x); - actor_rect.y = (int) roundf (y); - actor_rect.width = (int) roundf (x + width) - actor_rect.x; - actor_rect.height = (int) roundf (y + height) - actor_rect.y; - - /* Calculate the scaled surface actor region. */ - region = cairo_region_create_rectangle (&actor_rect); - - logical_monitor_layout = meta_logical_monitor_get_layout (logical_monitor); - - cairo_region_intersect_rectangle (region, - &((cairo_rectangle_int_t) { - .x = logical_monitor_layout.x, - .y = logical_monitor_layout.y, - .width = logical_monitor_layout.width, - .height = logical_monitor_layout.height, - })); - - is_on_monitor = !cairo_region_is_empty (region); - cairo_region_destroy (region); - - return is_on_monitor; -} - -static void -meta_wayland_actor_surface_get_relative_coordinates (MetaWaylandSurfaceRole *surface_role, - float abs_x, - float abs_y, - float *out_sx, - float *out_sy) -{ - MetaWaylandActorSurface *actor_surface = - META_WAYLAND_ACTOR_SURFACE (surface_role); - MetaWaylandActorSurfacePrivate *priv = - meta_wayland_actor_surface_get_instance_private (actor_surface); - - clutter_actor_transform_stage_point (CLUTTER_ACTOR (priv->actor), - abs_x, abs_y, - out_sx, out_sy); -} - -static void -meta_wayland_actor_surface_init (MetaWaylandActorSurface *actor_surface) -{ - MetaWaylandActorSurfacePrivate *priv = - meta_wayland_actor_surface_get_instance_private (actor_surface); - - wl_list_init (&priv->frame_callback_list); -} - -static void -meta_wayland_actor_surface_class_init (MetaWaylandActorSurfaceClass *klass) -{ - MetaWaylandSurfaceRoleClass *surface_role_class = - META_WAYLAND_SURFACE_ROLE_CLASS (klass); - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->constructed = meta_wayland_actor_surface_constructed; - object_class->dispose = meta_wayland_actor_surface_dispose; - - surface_role_class->assigned = meta_wayland_actor_surface_assigned; - surface_role_class->apply_state = meta_wayland_actor_surface_apply_state; - surface_role_class->is_on_logical_monitor = - meta_wayland_actor_surface_is_on_logical_monitor; - surface_role_class->get_relative_coordinates = - meta_wayland_actor_surface_get_relative_coordinates; - - klass->sync_actor_state = meta_wayland_actor_surface_real_sync_actor_state; -} - -MetaSurfaceActor * -meta_wayland_actor_surface_get_actor (MetaWaylandActorSurface *actor_surface) -{ - MetaWaylandActorSurfacePrivate *priv = - meta_wayland_actor_surface_get_instance_private (actor_surface); - - return priv->actor; -} - -static void -on_actor_destroyed (ClutterActor *actor, - MetaWaylandActorSurface *actor_surface) -{ - clear_surface_actor (actor_surface); -} - -void -meta_wayland_actor_surface_reset_actor (MetaWaylandActorSurface *actor_surface) -{ - MetaWaylandActorSurfacePrivate *priv = - meta_wayland_actor_surface_get_instance_private (actor_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (META_WAYLAND_SURFACE_ROLE (actor_surface)); - MetaWaylandSurface *subsurface_surface; - - META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface) - { - MetaWaylandActorSurface *actor_surface; - - actor_surface = META_WAYLAND_ACTOR_SURFACE (subsurface_surface->role); - meta_wayland_actor_surface_reset_actor (actor_surface); - meta_wayland_actor_surface_sync_actor_state (actor_surface); - } - - clear_surface_actor (actor_surface); - - priv->actor = g_object_ref_sink (meta_surface_actor_wayland_new (surface)); - priv->actor_destroyed_handler_id = - g_signal_connect (priv->actor, "destroy", - G_CALLBACK (on_actor_destroyed), - actor_surface); - - g_signal_connect_swapped (priv->actor, "notify::allocation", - G_CALLBACK (meta_wayland_surface_notify_geometry_changed), - surface); - g_signal_connect_swapped (priv->actor, "notify::mapped", - G_CALLBACK (meta_wayland_surface_update_outputs), - surface); - g_signal_connect_swapped (priv->actor, "stage-views-changed", - G_CALLBACK (meta_wayland_surface_update_outputs), - surface); -} diff --git a/src/wayland/meta-wayland-actor-surface.h b/src/wayland/meta-wayland-actor-surface.h deleted file mode 100644 index bd0cca275..000000000 --- a/src/wayland/meta-wayland-actor-surface.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2012,2013 Intel Corporation - * Copyright (C) 2013-2017 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_WAYLAND_ACTOR_SURFACE_H -#define META_WAYLAND_ACTOR_SURFACE_H - -#include "wayland/meta-wayland-surface.h" - -#define META_TYPE_WAYLAND_ACTOR_SURFACE (meta_wayland_actor_surface_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaWaylandActorSurface, - meta_wayland_actor_surface, - META, WAYLAND_ACTOR_SURFACE, - MetaWaylandSurfaceRole) - -struct _MetaWaylandActorSurfaceClass -{ - MetaWaylandSurfaceRoleClass parent_class; - - double (* get_geometry_scale) (MetaWaylandActorSurface *actor_surface); - void (* sync_actor_state) (MetaWaylandActorSurface *actor_surface); -}; - -void meta_wayland_actor_surface_sync_actor_state (MetaWaylandActorSurface *actor_surface); -double meta_wayland_actor_surface_get_geometry_scale (MetaWaylandActorSurface *actor_surface); - -META_EXPORT_TEST -MetaSurfaceActor * meta_wayland_actor_surface_get_actor (MetaWaylandActorSurface *actor_surface); - -void meta_wayland_actor_surface_reset_actor (MetaWaylandActorSurface *actor_surface); - -void meta_wayland_actor_surface_queue_frame_callbacks (MetaWaylandActorSurface *actor_surface, - MetaWaylandSurfaceState *pending); - -void meta_wayland_actor_surface_emit_frame_callbacks (MetaWaylandActorSurface *actor_surface, - uint32_t timestamp_ms); - -#endif /* META_WAYLAND_ACTOR_SURFACE_H */ diff --git a/src/wayland/meta-wayland-buffer.c b/src/wayland/meta-wayland-buffer.c deleted file mode 100644 index 2b6fe6b6e..000000000 --- a/src/wayland/meta-wayland-buffer.c +++ /dev/null @@ -1,852 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Endless Mobile - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -/** - * SECTION:meta-wayland-buffer - * @title: MetaWaylandBuffer - * @short_description: A wrapper for wayland buffers - * - * #MetaWaylandBuffer is a general wrapper around wl_buffer, the basic way of - * passing rendered data from Wayland clients to the compositor. Note that a - * buffer can be backed by several types of memory, as specified by - * #MetaWaylandBufferType. - */ - -/** - * MetaWaylandBufferType: - * @META_WAYLAND_BUFFER_TYPE_UNKNOWN: Unknown type. - * @META_WAYLAND_BUFFER_TYPE_SHM: wl_buffer backed by shared memory - * @META_WAYLAND_BUFFER_TYPE_EGL_IMAGE: wl_buffer backed by an EGLImage - * @META_WAYLAND_BUFFER_TYPE_EGL_STREAM: wl_buffer backed by an EGLStream (NVIDIA-specific) - * @META_WAYLAND_BUFFER_TYPE_DMA_BUF: wl_buffer backed by a Linux DMA-BUF - * - * Specifies the backing memory for a #MetaWaylandBuffer. Depending on the type - * of buffer, this will lead to different handling for the compositor. For - * example, a shared-memory buffer will still need to be uploaded to the GPU. - */ - -#include "config.h" - -#include "wayland/meta-wayland-buffer.h" - -#include - -#include "backends/meta-backend-private.h" -#include "clutter/clutter.h" -#include "cogl/cogl-egl.h" -#include "meta/util.h" -#include "wayland/meta-wayland-dma-buf.h" -#include "wayland/meta-wayland-private.h" - -#ifdef HAVE_NATIVE_BACKEND -#include "backends/native/meta-drm-buffer-gbm.h" -#include "backends/native/meta-kms-utils.h" -#include "backends/native/meta-onscreen-native.h" -#include "backends/native/meta-renderer-native.h" -#endif - -#ifndef DRM_FORMAT_MOD_INVALID -#define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1) -#endif - -enum -{ - RESOURCE_DESTROYED, - - LAST_SIGNAL -}; - -guint signals[LAST_SIGNAL]; - -G_DEFINE_TYPE (MetaWaylandBuffer, meta_wayland_buffer, G_TYPE_OBJECT); - -static void -meta_wayland_buffer_destroy_handler (struct wl_listener *listener, - void *data) -{ - MetaWaylandBuffer *buffer = - wl_container_of (listener, buffer, destroy_listener); - - buffer->resource = NULL; - g_signal_emit (buffer, signals[RESOURCE_DESTROYED], 0); - g_object_unref (buffer); -} - -MetaWaylandBuffer * -meta_wayland_buffer_from_resource (struct wl_resource *resource) -{ - MetaWaylandBuffer *buffer; - struct wl_listener *listener; - - listener = - wl_resource_get_destroy_listener (resource, - meta_wayland_buffer_destroy_handler); - - if (listener) - { - buffer = wl_container_of (listener, buffer, destroy_listener); - } - else - { - buffer = g_object_new (META_TYPE_WAYLAND_BUFFER, NULL); - - buffer->resource = resource; - buffer->destroy_listener.notify = meta_wayland_buffer_destroy_handler; - wl_resource_add_destroy_listener (resource, &buffer->destroy_listener); - } - - return buffer; -} - -struct wl_resource * -meta_wayland_buffer_get_resource (MetaWaylandBuffer *buffer) -{ - return buffer->resource; -} - -gboolean -meta_wayland_buffer_is_realized (MetaWaylandBuffer *buffer) -{ - return buffer->type != META_WAYLAND_BUFFER_TYPE_UNKNOWN; -} - -gboolean -meta_wayland_buffer_realize (MetaWaylandBuffer *buffer) -{ - EGLint format; - MetaBackend *backend = meta_get_backend (); - MetaEgl *egl = meta_backend_get_egl (backend); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); - EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context); -#ifdef HAVE_WAYLAND_EGLSTREAM - MetaWaylandEglStream *stream; -#endif - MetaWaylandDmaBufBuffer *dma_buf; - - if (wl_shm_buffer_get (buffer->resource) != NULL) - { - buffer->type = META_WAYLAND_BUFFER_TYPE_SHM; - return TRUE; - } - -#ifdef HAVE_WAYLAND_EGLSTREAM - stream = meta_wayland_egl_stream_new (buffer, NULL); - if (stream) - { - CoglTexture2D *texture; - - texture = meta_wayland_egl_stream_create_texture (stream, NULL); - if (!texture) - return FALSE; - - buffer->egl_stream.stream = stream; - buffer->type = META_WAYLAND_BUFFER_TYPE_EGL_STREAM; - buffer->egl_stream.texture = COGL_TEXTURE (texture); - buffer->is_y_inverted = meta_wayland_egl_stream_is_y_inverted (stream); - - return TRUE; - } -#endif /* HAVE_WAYLAND_EGLSTREAM */ - - if (meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource, - EGL_TEXTURE_FORMAT, &format, - NULL)) - { - buffer->type = META_WAYLAND_BUFFER_TYPE_EGL_IMAGE; - return TRUE; - } - - dma_buf = meta_wayland_dma_buf_from_buffer (buffer); - if (dma_buf) - { - buffer->dma_buf.dma_buf = dma_buf; - buffer->type = META_WAYLAND_BUFFER_TYPE_DMA_BUF; - return TRUE; - } - - return FALSE; -} - -static gboolean -shm_format_to_cogl_pixel_format (enum wl_shm_format shm_format, - CoglPixelFormat *format_out, - CoglTextureComponents *components_out) -{ - CoglPixelFormat format; - CoglTextureComponents components = COGL_TEXTURE_COMPONENTS_RGBA; - - switch (shm_format) - { -#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_RGB565: - format = COGL_PIXEL_FORMAT_RGB_565; - components = COGL_TEXTURE_COMPONENTS_RGB; - break; - 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; - case WL_SHM_FORMAT_XRGB2101010: - components = COGL_TEXTURE_COMPONENTS_RGB; - G_GNUC_FALLTHROUGH; - case WL_SHM_FORMAT_ARGB2101010: - format = COGL_PIXEL_FORMAT_ARGB_2101010_PRE; - break; - case WL_SHM_FORMAT_XBGR2101010: - components = COGL_TEXTURE_COMPONENTS_RGB; - G_GNUC_FALLTHROUGH; - case WL_SHM_FORMAT_ABGR2101010: - format = COGL_PIXEL_FORMAT_ABGR_2101010_PRE; - break; - case WL_SHM_FORMAT_XRGB16161616F: - components = COGL_TEXTURE_COMPONENTS_RGB; - G_GNUC_FALLTHROUGH; - case WL_SHM_FORMAT_ARGB16161616F: - format = COGL_PIXEL_FORMAT_BGRA_FP_16161616_PRE; - break; - case WL_SHM_FORMAT_XBGR16161616F: - components = COGL_TEXTURE_COMPONENTS_RGB; - G_GNUC_FALLTHROUGH; - case WL_SHM_FORMAT_ABGR16161616F: - format = COGL_PIXEL_FORMAT_RGBA_FP_16161616_PRE; - break; -#endif - default: - return FALSE; - } - - if (format_out) - *format_out = format; - if (components_out) - *components_out = components; - - return TRUE; -} - -static gboolean -shm_buffer_get_cogl_pixel_format (struct wl_shm_buffer *shm_buffer, - CoglPixelFormat *format_out, - CoglTextureComponents *components_out) -{ - MetaBackend *backend = meta_get_backend (); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = - clutter_backend_get_cogl_context (clutter_backend); - CoglPixelFormat cogl_format; - CoglTextureComponents cogl_components; - - if (!shm_format_to_cogl_pixel_format (wl_shm_buffer_get_format (shm_buffer), - &cogl_format, - &cogl_components)) - return FALSE; - - if (!cogl_context_format_supports_upload (cogl_context, cogl_format)) - return FALSE; - - if (format_out) - *format_out = cogl_format; - if (components_out) - *components_out = cogl_components; - - return TRUE; -} - -static const char * -shm_format_to_string (MetaDrmFormatBuf *format_buf, - uint32_t shm_format) -{ - const char *result; - - switch (shm_format) - { - case WL_SHM_FORMAT_ARGB8888: - result = "ARGB8888"; - break; - case WL_SHM_FORMAT_XRGB8888: - result = "XRGB8888"; - break; - default: - result = meta_drm_format_to_string (format_buf, shm_format); - break; - } - - return result; -} - -static gboolean -shm_buffer_attach (MetaWaylandBuffer *buffer, - CoglTexture **texture, - GError **error) -{ - MetaBackend *backend = meta_get_backend (); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); - struct wl_shm_buffer *shm_buffer; - int stride, width, height; - CoglPixelFormat format; - CoglTextureComponents components; - CoglBitmap *bitmap; - CoglTexture *new_texture; - MetaDrmFormatBuf format_buf; - - shm_buffer = wl_shm_buffer_get (buffer->resource); - stride = wl_shm_buffer_get_stride (shm_buffer); - width = wl_shm_buffer_get_width (shm_buffer); - height = wl_shm_buffer_get_height (shm_buffer); - if (!shm_buffer_get_cogl_pixel_format (shm_buffer, &format, &components)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Invalid shm pixel format"); - return FALSE; - } - - meta_topic (META_DEBUG_WAYLAND, - "[wl-shm] wl_buffer@%u wl_shm_format %s -> CoglPixelFormat %s", - wl_resource_get_id (meta_wayland_buffer_get_resource (buffer)), - shm_format_to_string (&format_buf, - wl_shm_buffer_get_format (shm_buffer)), - cogl_pixel_format_to_string (format)); - - if (*texture && - cogl_texture_get_width (*texture) == width && - cogl_texture_get_height (*texture) == height && - cogl_texture_get_components (*texture) == components && - _cogl_texture_get_format (*texture) == format) - { - buffer->is_y_inverted = TRUE; - return TRUE; - } - - cogl_clear_object (texture); - - wl_shm_buffer_begin_access (shm_buffer); - - bitmap = cogl_bitmap_new_for_data (cogl_context, - width, height, - format, - stride, - wl_shm_buffer_get_data (shm_buffer)); - - new_texture = COGL_TEXTURE (cogl_texture_2d_new_from_bitmap (bitmap)); - cogl_texture_set_components (new_texture, components); - - if (!cogl_texture_allocate (new_texture, error)) - { - g_clear_pointer (&new_texture, cogl_object_unref); - if (g_error_matches (*error, COGL_TEXTURE_ERROR, COGL_TEXTURE_ERROR_SIZE)) - { - CoglTexture2DSliced *texture_sliced; - - g_clear_error (error); - - texture_sliced = - cogl_texture_2d_sliced_new_from_bitmap (bitmap, - COGL_TEXTURE_MAX_WASTE); - new_texture = COGL_TEXTURE (texture_sliced); - cogl_texture_set_components (new_texture, components); - - if (!cogl_texture_allocate (new_texture, error)) - g_clear_pointer (&new_texture, cogl_object_unref); - } - } - - cogl_object_unref (bitmap); - - wl_shm_buffer_end_access (shm_buffer); - - if (!new_texture) - return FALSE; - - *texture = new_texture; - buffer->is_y_inverted = TRUE; - - return TRUE; -} - -static gboolean -egl_image_buffer_attach (MetaWaylandBuffer *buffer, - CoglTexture **texture, - GError **error) -{ - MetaBackend *backend = meta_get_backend (); - MetaEgl *egl = meta_backend_get_egl (backend); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); - EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context); - int format, width, height, y_inverted; - CoglPixelFormat cogl_format; - EGLImageKHR egl_image; - CoglEglImageFlags flags; - CoglTexture2D *texture_2d; - - if (buffer->egl_image.texture) - { - cogl_clear_object (texture); - *texture = cogl_object_ref (buffer->egl_image.texture); - return TRUE; - } - - if (!meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource, - EGL_TEXTURE_FORMAT, &format, - error)) - return FALSE; - - if (!meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource, - EGL_WIDTH, &width, - error)) - return FALSE; - - if (!meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource, - EGL_HEIGHT, &height, - error)) - return FALSE; - - if (!meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource, - EGL_WAYLAND_Y_INVERTED_WL, &y_inverted, - NULL)) - y_inverted = EGL_TRUE; - - switch (format) - { - case EGL_TEXTURE_RGB: - cogl_format = COGL_PIXEL_FORMAT_RGB_888; - break; - case EGL_TEXTURE_RGBA: - cogl_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE; - break; - default: - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Unsupported buffer format %d", format); - return FALSE; - } - - /* The WL_bind_wayland_display spec states that EGL_NO_CONTEXT is to be used - * in conjunction with the EGL_WAYLAND_BUFFER_WL target. */ - egl_image = meta_egl_create_image (egl, egl_display, EGL_NO_CONTEXT, - EGL_WAYLAND_BUFFER_WL, buffer->resource, - NULL, - error); - if (egl_image == EGL_NO_IMAGE_KHR) - return FALSE; - - flags = COGL_EGL_IMAGE_FLAG_NONE; - texture_2d = cogl_egl_texture_2d_new_from_image (cogl_context, - width, height, - cogl_format, - egl_image, - flags, - error); - - meta_egl_destroy_image (egl, egl_display, egl_image, NULL); - - if (!texture_2d) - return FALSE; - - buffer->egl_image.texture = COGL_TEXTURE (texture_2d); - buffer->is_y_inverted = !!y_inverted; - - cogl_clear_object (texture); - *texture = cogl_object_ref (buffer->egl_image.texture); - - return TRUE; -} - -#ifdef HAVE_WAYLAND_EGLSTREAM -static gboolean -egl_stream_buffer_attach (MetaWaylandBuffer *buffer, - CoglTexture **texture, - GError **error) -{ - MetaWaylandEglStream *stream = buffer->egl_stream.stream; - - g_assert (stream); - - if (!meta_wayland_egl_stream_attach (stream, error)) - return FALSE; - - cogl_clear_object (texture); - *texture = cogl_object_ref (buffer->egl_stream.texture); - - return TRUE; -} -#endif /* HAVE_WAYLAND_EGLSTREAM */ - -/** - * meta_wayland_buffer_attach: - * @buffer: a pointer to a #MetaWaylandBuffer - * @texture: (inout) (transfer full): a #CoglTexture representing the surface - * content - * @error: return location for error or %NULL - * - * This function should be passed a pointer to the texture used to draw the - * surface content. The texture will either be replaced by a new texture, or - * stay the same, in which case, it may later be updated with new content when - * processing damage. The new texture might be newly created, or it may be a - * reference to an already existing one. - * - * If replaced, the old texture will have its reference count decreased by one, - * potentially freeing it. When a new texture is set, the caller (i.e. the - * surface) will be the owner of one reference count. It must free it, either - * using g_object_unref() or have it updated again using - * meta_wayland_buffer_attach(), which also might free it, as described above. - */ -gboolean -meta_wayland_buffer_attach (MetaWaylandBuffer *buffer, - CoglTexture **texture, - GError **error) -{ - g_return_val_if_fail (buffer->resource, FALSE); - - COGL_TRACE_BEGIN_SCOPED (MetaWaylandBufferAttach, "WaylandBuffer (attach)"); - - if (!meta_wayland_buffer_is_realized (buffer)) - { - /* The buffer should have been realized at surface commit time */ - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Unknown buffer type"); - return FALSE; - } - - switch (buffer->type) - { - case META_WAYLAND_BUFFER_TYPE_SHM: - return shm_buffer_attach (buffer, texture, error); - case META_WAYLAND_BUFFER_TYPE_EGL_IMAGE: - return egl_image_buffer_attach (buffer, texture, error); -#ifdef HAVE_WAYLAND_EGLSTREAM - case META_WAYLAND_BUFFER_TYPE_EGL_STREAM: - return egl_stream_buffer_attach (buffer, texture, error); -#endif - case META_WAYLAND_BUFFER_TYPE_DMA_BUF: - return meta_wayland_dma_buf_buffer_attach (buffer, - texture, - error); - case META_WAYLAND_BUFFER_TYPE_UNKNOWN: - g_assert_not_reached (); - return FALSE; - } - - g_assert_not_reached (); - return FALSE; -} - -/** - * meta_wayland_buffer_create_snippet: - * @buffer: A #MetaWaylandBuffer object - * - * If needed, this method creates a #CoglSnippet to make sure the buffer can be - * dealt with appropriately in a #CoglPipeline that renders it. - * - * Returns: (transfer full) (nullable): A new #CoglSnippet, or %NULL. - */ -CoglSnippet * -meta_wayland_buffer_create_snippet (MetaWaylandBuffer *buffer) -{ -#ifdef HAVE_WAYLAND_EGLSTREAM - if (!buffer->egl_stream.stream) - return NULL; - - return meta_wayland_egl_stream_create_snippet (buffer->egl_stream.stream); -#else - return NULL; -#endif /* HAVE_WAYLAND_EGLSTREAM */ -} - -gboolean -meta_wayland_buffer_is_y_inverted (MetaWaylandBuffer *buffer) -{ - return buffer->is_y_inverted; -} - -static gboolean -process_shm_buffer_damage (MetaWaylandBuffer *buffer, - CoglTexture *texture, - cairo_region_t *region, - GError **error) -{ - struct wl_shm_buffer *shm_buffer; - int i, n_rectangles; - gboolean set_texture_failed = FALSE; - CoglPixelFormat format; - - n_rectangles = cairo_region_num_rectangles (region); - - shm_buffer = wl_shm_buffer_get (buffer->resource); - - shm_buffer_get_cogl_pixel_format (shm_buffer, &format, NULL); - g_return_val_if_fail (cogl_pixel_format_get_n_planes (format) == 1, FALSE); - - wl_shm_buffer_begin_access (shm_buffer); - - for (i = 0; i < n_rectangles; i++) - { - const uint8_t *data = wl_shm_buffer_get_data (shm_buffer); - int32_t stride = wl_shm_buffer_get_stride (shm_buffer); - cairo_rectangle_int_t rect; - int bpp; - - bpp = cogl_pixel_format_get_bytes_per_pixel (format, 0); - cairo_region_get_rectangle (region, i, &rect); - - if (!_cogl_texture_set_region (texture, - rect.width, rect.height, - format, - stride, - data + rect.x * bpp + rect.y * stride, - rect.x, rect.y, - 0, - error)) - { - set_texture_failed = TRUE; - break; - } - } - - wl_shm_buffer_end_access (shm_buffer); - - return !set_texture_failed; -} - -void -meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer, - CoglTexture *texture, - cairo_region_t *region) -{ - gboolean res = FALSE; - GError *error = NULL; - - g_return_if_fail (buffer->resource); - - switch (buffer->type) - { - case META_WAYLAND_BUFFER_TYPE_SHM: - res = process_shm_buffer_damage (buffer, texture, region, &error); - break; - case META_WAYLAND_BUFFER_TYPE_EGL_IMAGE: -#ifdef HAVE_WAYLAND_EGLSTREAM - case META_WAYLAND_BUFFER_TYPE_EGL_STREAM: -#endif - case META_WAYLAND_BUFFER_TYPE_DMA_BUF: - res = TRUE; - break; - case META_WAYLAND_BUFFER_TYPE_UNKNOWN: - g_set_error (&error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Unknown buffer type"); - res = FALSE; - break; - } - - if (!res) - { - g_warning ("Failed to process Wayland buffer damage: %s", error->message); - g_error_free (error); - } -} - -static CoglScanout * -try_acquire_egl_image_scanout (MetaWaylandBuffer *buffer, - CoglOnscreen *onscreen) -{ -#ifdef HAVE_NATIVE_BACKEND - MetaBackend *backend = meta_get_backend (); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer); - MetaGpuKms *gpu_kms; - MetaDeviceFile *device_file; - struct gbm_device *gbm_device; - struct gbm_bo *gbm_bo; - uint32_t drm_format; - uint64_t drm_modifier; - uint32_t stride; - MetaDrmBufferGbm *fb; - g_autoptr (GError) error = NULL; - - gpu_kms = meta_renderer_native_get_primary_gpu (renderer_native); - device_file = meta_renderer_native_get_primary_device_file (renderer_native); - gbm_device = meta_gbm_device_from_gpu (gpu_kms); - - gbm_bo = gbm_bo_import (gbm_device, - GBM_BO_IMPORT_WL_BUFFER, buffer->resource, - GBM_BO_USE_SCANOUT); - if (!gbm_bo) - return NULL; - - drm_format = gbm_bo_get_format (gbm_bo); - drm_modifier = gbm_bo_get_modifier (gbm_bo); - stride = gbm_bo_get_stride (gbm_bo); - if (!meta_onscreen_native_is_buffer_scanout_compatible (onscreen, - drm_format, - drm_modifier, - stride)) - { - gbm_bo_destroy (gbm_bo); - return NULL; - } - - fb = meta_drm_buffer_gbm_new_take (device_file, - gbm_bo, - drm_modifier != DRM_FORMAT_MOD_INVALID, - &error); - if (!fb) - { - g_debug ("Failed to create scanout buffer: %s", error->message); - gbm_bo_destroy (gbm_bo); - return NULL; - } - - return COGL_SCANOUT (fb); -#else - return NULL; -#endif -} - -CoglScanout * -meta_wayland_buffer_try_acquire_scanout (MetaWaylandBuffer *buffer, - CoglOnscreen *onscreen) -{ - switch (buffer->type) - { - case META_WAYLAND_BUFFER_TYPE_SHM: - return NULL; - case META_WAYLAND_BUFFER_TYPE_EGL_IMAGE: - return try_acquire_egl_image_scanout (buffer, onscreen); -#ifdef HAVE_WAYLAND_EGLSTREAM - case META_WAYLAND_BUFFER_TYPE_EGL_STREAM: - return NULL; -#endif - case META_WAYLAND_BUFFER_TYPE_DMA_BUF: - { - MetaWaylandDmaBufBuffer *dma_buf; - - dma_buf = meta_wayland_dma_buf_from_buffer (buffer); - if (!dma_buf) - return NULL; - - return meta_wayland_dma_buf_try_acquire_scanout (dma_buf, onscreen); - } - case META_WAYLAND_BUFFER_TYPE_UNKNOWN: - g_warn_if_reached (); - return NULL; - } - - g_assert_not_reached (); - return NULL; -} - -static void -meta_wayland_buffer_finalize (GObject *object) -{ - MetaWaylandBuffer *buffer = META_WAYLAND_BUFFER (object); - - g_clear_pointer (&buffer->egl_image.texture, cogl_object_unref); -#ifdef HAVE_WAYLAND_EGLSTREAM - g_clear_pointer (&buffer->egl_stream.texture, cogl_object_unref); - g_clear_object (&buffer->egl_stream.stream); -#endif - g_clear_pointer (&buffer->dma_buf.texture, cogl_object_unref); - g_clear_object (&buffer->dma_buf.dma_buf); - - G_OBJECT_CLASS (meta_wayland_buffer_parent_class)->finalize (object); -} - -static void -meta_wayland_buffer_init (MetaWaylandBuffer *buffer) -{ -} - -static void -meta_wayland_buffer_class_init (MetaWaylandBufferClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_wayland_buffer_finalize; - - /** - * MetaWaylandBuffer::resource-destroyed: - * - * Called when the underlying wl_resource was destroyed. - */ - signals[RESOURCE_DESTROYED] = g_signal_new ("resource-destroyed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); -} - -void -meta_wayland_init_shm (MetaWaylandCompositor *compositor) -{ - MetaBackend *backend = meta_get_backend (); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = - clutter_backend_get_cogl_context (clutter_backend); - - static const enum wl_shm_format shm_formats[] = { -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - WL_SHM_FORMAT_RGB565, - WL_SHM_FORMAT_ARGB2101010, - WL_SHM_FORMAT_XRGB2101010, - WL_SHM_FORMAT_ABGR2101010, - WL_SHM_FORMAT_XBGR2101010, - WL_SHM_FORMAT_ARGB16161616F, - WL_SHM_FORMAT_XRGB16161616F, - WL_SHM_FORMAT_ABGR16161616F, - WL_SHM_FORMAT_XBGR16161616F, -#endif - }; - int i; - - wl_display_init_shm (compositor->wayland_display); - - for (i = 0; i < G_N_ELEMENTS (shm_formats); i++) - { - CoglPixelFormat cogl_format; - - if (!shm_format_to_cogl_pixel_format (shm_formats[i], - &cogl_format, - NULL)) - continue; - - if (!cogl_context_format_supports_upload (cogl_context, cogl_format)) - continue; - - wl_display_add_shm_format (compositor->wayland_display, shm_formats[i]); - } -} diff --git a/src/wayland/meta-wayland-buffer.h b/src/wayland/meta-wayland-buffer.h deleted file mode 100644 index e00406ba2..000000000 --- a/src/wayland/meta-wayland-buffer.h +++ /dev/null @@ -1,96 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Endless Mobile - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -#ifndef META_WAYLAND_BUFFER_H -#define META_WAYLAND_BUFFER_H - -#include -#include - -#include "cogl/cogl.h" -#include "wayland/meta-wayland-types.h" -#include "wayland/meta-wayland-egl-stream.h" -#include "wayland/meta-wayland-dma-buf.h" - -typedef enum _MetaWaylandBufferType -{ - META_WAYLAND_BUFFER_TYPE_UNKNOWN, - META_WAYLAND_BUFFER_TYPE_SHM, - META_WAYLAND_BUFFER_TYPE_EGL_IMAGE, -#ifdef HAVE_WAYLAND_EGLSTREAM - META_WAYLAND_BUFFER_TYPE_EGL_STREAM, -#endif - META_WAYLAND_BUFFER_TYPE_DMA_BUF, -} MetaWaylandBufferType; - -struct _MetaWaylandBuffer -{ - GObject parent; - - struct wl_resource *resource; - struct wl_listener destroy_listener; - - gboolean is_y_inverted; - - MetaWaylandBufferType type; - - struct { - CoglTexture *texture; - } egl_image; - -#ifdef HAVE_WAYLAND_EGLSTREAM - struct { - MetaWaylandEglStream *stream; - CoglTexture *texture; - } egl_stream; -#endif - - struct { - MetaWaylandDmaBufBuffer *dma_buf; - CoglTexture *texture; - } dma_buf; -}; - -#define META_TYPE_WAYLAND_BUFFER (meta_wayland_buffer_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandBuffer, meta_wayland_buffer, - META, WAYLAND_BUFFER, GObject); - -MetaWaylandBuffer * meta_wayland_buffer_from_resource (struct wl_resource *resource); -struct wl_resource * meta_wayland_buffer_get_resource (MetaWaylandBuffer *buffer); -gboolean meta_wayland_buffer_is_realized (MetaWaylandBuffer *buffer); -gboolean meta_wayland_buffer_realize (MetaWaylandBuffer *buffer); -gboolean meta_wayland_buffer_attach (MetaWaylandBuffer *buffer, - CoglTexture **texture, - GError **error); -CoglSnippet * meta_wayland_buffer_create_snippet (MetaWaylandBuffer *buffer); -gboolean meta_wayland_buffer_is_y_inverted (MetaWaylandBuffer *buffer); -void meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer, - CoglTexture *texture, - cairo_region_t *region); -CoglScanout * meta_wayland_buffer_try_acquire_scanout (MetaWaylandBuffer *buffer, - CoglOnscreen *onscreen); - -void meta_wayland_init_shm (MetaWaylandCompositor *compositor); - -#endif /* META_WAYLAND_BUFFER_H */ diff --git a/src/wayland/meta-wayland-client.c b/src/wayland/meta-wayland-client.c deleted file mode 100644 index dfae1eda6..000000000 --- a/src/wayland/meta-wayland-client.c +++ /dev/null @@ -1,335 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright 2019 Sergio Costas (rastersoft@gmail.com) - * - * 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. - */ - -/** - * SECTION: meta-wayland-client - * @title MetaWaylandClient - * @include: gio/gsubprocess.h - * A class that allows to launch a trusted client and detect if an specific - * Wayland window belongs to it. - */ - -#include "config.h" - -#include "meta/meta-wayland-client.h" - -#include -#include -#include -#include -#include - -#include "core/window-private.h" -#include "meta/util.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-types.h" - -struct _MetaWaylandClient -{ - GObject parent_instance; - - GSubprocessLauncher *launcher; - GSubprocess *subprocess; - GCancellable *died_cancellable; - gboolean process_running; - gboolean process_launched; - struct wl_client *wayland_client; -}; - -G_DEFINE_TYPE (MetaWaylandClient, meta_wayland_client, G_TYPE_OBJECT) - -static void -meta_wayland_client_dispose (GObject *object) -{ - MetaWaylandClient *client = META_WAYLAND_CLIENT (object); - - g_cancellable_cancel (client->died_cancellable); - g_clear_object (&client->died_cancellable); - g_clear_object (&client->launcher); - g_clear_object (&client->subprocess); - - G_OBJECT_CLASS (meta_wayland_client_parent_class)->dispose (object); -} - -static void -meta_wayland_client_class_init (MetaWaylandClientClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = meta_wayland_client_dispose; -} - -static void -meta_wayland_client_init (MetaWaylandClient *client) -{ -} - -static void -process_died (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - MetaWaylandClient *client = META_WAYLAND_CLIENT (user_data); - - client->process_running = FALSE; -} - -/** - * meta_wayland_client_new: - * @launcher: (not nullable): a GSubprocessLauncher to use to launch the subprocess - * @error: (nullable): Error - * - * Creates a new #MetaWaylandClient. The GSubprocesslauncher passed is - * stored internally and will be used to launch the subprocess. - * - * Returns: A #MetaWaylandClient or %NULL if %error is set. Free with - * g_object_unref(). - */ -MetaWaylandClient * -meta_wayland_client_new (GSubprocessLauncher *launcher, - GError **error) -{ - MetaWaylandClient *client; - - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - if (!meta_is_wayland_compositor ()) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_NOT_SUPPORTED, - "MetaWaylandClient can be used only with Wayland."); - return NULL; - } - - if (launcher == NULL) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_INVALID_ARGUMENT, - "Invalid launcher."); - return NULL; - } - - client = g_object_new (META_TYPE_WAYLAND_CLIENT, NULL); - client->launcher = g_object_ref (launcher); - return client; -} - -/** - * meta_wayland_client_spawnv: - * @client: a #MetaWaylandClient - * @display: (not nullable): the current MetaDisplay - * @argv: (array zero-terminated=1) (element-type filename): Command line arguments - * @error: (nullable): Error - * - * Creates a #GSubprocess given a provided array of arguments, launching a new - * process with the binary specified in the first element of argv, and with the - * rest of elements as parameters. It also sets up a new Wayland socket and sets - * the environment variable WAYLAND_SOCKET to make the new process to use it. - * - * Returns: (transfer full): A new #GSubprocess, or %NULL on error (and @error - * will be set) - **/ -GSubprocess * -meta_wayland_client_spawnv (MetaWaylandClient *client, - MetaDisplay *display, - const char * const *argv, - GError **error) -{ - int client_fd[2]; - GSubprocess *subprocess; - struct wl_client *wayland_client; - MetaWaylandCompositor *compositor; - - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - g_return_val_if_fail (argv != NULL && - argv[0] != NULL && - argv[0][0] != '\0', - NULL); - - if (client->process_launched) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_FAILED, - "This object already has spawned a subprocess."); - return NULL; - } - - if (client->launcher == NULL) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_NOT_INITIALIZED, - "MetaWaylandClient must be created using meta_wayland_client_new()."); - return NULL; - } - - if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, client_fd) < 0) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_FAILED, - "Failed to create a socket pair for the wayland client."); - return NULL; - } - - compositor = meta_wayland_compositor_get_default (); - g_subprocess_launcher_take_fd (client->launcher, client_fd[1], 3); - g_subprocess_launcher_setenv (client->launcher, "WAYLAND_SOCKET", "3", TRUE); - wayland_client = wl_client_create (compositor->wayland_display, client_fd[0]); - subprocess = g_subprocess_launcher_spawnv (client->launcher, argv, error); - g_clear_object (&client->launcher); - client->process_launched = TRUE; - - if (subprocess == NULL) - return NULL; - - client->subprocess = subprocess; - client->wayland_client = wayland_client; - client->process_running = TRUE; - client->died_cancellable = g_cancellable_new (); - g_subprocess_wait_async (client->subprocess, - client->died_cancellable, - process_died, - client); - - return g_object_ref (client->subprocess); -} - -/** - * meta_wayland_client_spawn: - * @client: a #MetaWaylandClient - * @display: (not nullable): the current MetaDisplay - * @error: (nullable): Error - * @argv0: Command line arguments - * @...: Continued arguments, %NULL terminated - * - * Creates a #GSubprocess given a provided varargs list of arguments. It also - * sets up a new Wayland socket and sets the environment variable WAYLAND_SOCKET - * to make the new process to use it. - * - * Returns: (transfer full): A new #GSubprocess, or %NULL on error (and @error - * will be set) - **/ -GSubprocess * -meta_wayland_client_spawn (MetaWaylandClient *client, - MetaDisplay *display, - GError **error, - const char *argv0, - ...) -{ - g_autoptr (GPtrArray) args = NULL; - GSubprocess *result; - const char *arg; - va_list ap; - - g_return_val_if_fail (argv0 != NULL && argv0[0] != '\0', NULL); - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - args = g_ptr_array_new_with_free_func (g_free); - - va_start (ap, argv0); - g_ptr_array_add (args, (char *) argv0); - while ((arg = va_arg (ap, const char *))) - g_ptr_array_add (args, (char *) arg); - - g_ptr_array_add (args, NULL); - va_end (ap); - - result = meta_wayland_client_spawnv (client, - display, - (const char * const *) args->pdata, - error); - - return result; -} - -/** - * meta_wayland_client_owns_wayland_window - * @client: a #MetaWaylandClient - * @window: (not nullable): a MetaWindow - * - * Checks whether @window belongs to the process launched from @client or not. - * This only works under Wayland. If the window is an X11 window, an exception - * will be triggered. - * - * Returns: TRUE if the window was created by this process; FALSE if not. - */ -gboolean -meta_wayland_client_owns_window (MetaWaylandClient *client, - MetaWindow *window) -{ - MetaWaylandSurface *surface; - - g_return_val_if_fail (meta_is_wayland_compositor (), FALSE); - g_return_val_if_fail (client->subprocess != NULL, FALSE); - g_return_val_if_fail (client->process_running, FALSE); - - surface = window->surface; - if (surface == NULL) - return FALSE; - - return wl_resource_get_client (surface->resource) == client->wayland_client; -} - -/** - * meta_wayland_client_skip_from_window_list - * @client: a #MetaWaylandClient - * @window: (not nullable): a MetaWindow - * - * Hides this window from any window list, like taskbars, pagers... - */ -void -meta_wayland_client_hide_from_window_list (MetaWaylandClient *client, - MetaWindow *window) -{ - if (!meta_wayland_client_owns_window (client, window)) - return; - - if (!window->skip_from_window_list) - { - window->skip_from_window_list = TRUE; - meta_window_recalc_features (window); - } -} - -/** - * meta_wayland_client_show_in_window_list - * @client: a #MetaWaylandClient - * @window: (not nullable): a MetaWindow - * - * Shows again this window in window lists, like taskbars, pagers... - */ -void -meta_wayland_client_show_in_window_list (MetaWaylandClient *client, - MetaWindow *window) -{ - if (!meta_wayland_client_owns_window (client, window)) - return; - - if (window->skip_from_window_list) - { - window->skip_from_window_list = FALSE; - meta_window_recalc_features (window); - } -} diff --git a/src/wayland/meta-wayland-cursor-surface.c b/src/wayland/meta-wayland-cursor-surface.c deleted file mode 100644 index d1f521818..000000000 --- a/src/wayland/meta-wayland-cursor-surface.c +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2015 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include "config.h" - -#include "wayland/meta-wayland-cursor-surface.h" - -#include "backends/meta-backend-private.h" -#include "backends/meta-logical-monitor.h" -#include "cogl/cogl-wayland-server.h" -#include "cogl/cogl.h" -#include "core/boxes-private.h" -#include "wayland/meta-cursor-sprite-wayland.h" -#include "wayland/meta-wayland-buffer.h" -#include "wayland/meta-wayland-presentation-time-private.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-xwayland.h" - -typedef struct _MetaWaylandCursorSurfacePrivate MetaWaylandCursorSurfacePrivate; - -struct _MetaWaylandCursorSurfacePrivate -{ - int hot_x; - int hot_y; - MetaCursorSpriteWayland *cursor_sprite; - MetaCursorRenderer *cursor_renderer; - MetaWaylandBuffer *buffer; - struct wl_list frame_callbacks; - gulong cursor_painted_handler_id; -}; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandCursorSurface, - meta_wayland_cursor_surface, - META_TYPE_WAYLAND_SURFACE_ROLE) - -static void -update_cursor_sprite_texture (MetaWaylandCursorSurface *cursor_surface) -{ - MetaWaylandCursorSurfacePrivate *priv = - meta_wayland_cursor_surface_get_instance_private (cursor_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (META_WAYLAND_SURFACE_ROLE (cursor_surface)); - MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (priv->cursor_sprite); - CoglTexture *texture; - - if (!priv->cursor_renderer) - return; - - texture = meta_wayland_surface_get_texture (surface); - if (texture) - { - meta_cursor_sprite_set_texture (cursor_sprite, - texture, - priv->hot_x * surface->scale, - priv->hot_y * surface->scale); - } - else - { - meta_cursor_sprite_set_texture (cursor_sprite, NULL, 0, 0); - } - - meta_cursor_renderer_force_update (priv->cursor_renderer); -} - -static void -cursor_sprite_prepare_at (MetaCursorSprite *cursor_sprite, - float best_scale, - int x, - int y, - MetaWaylandCursorSurface *cursor_surface) -{ - MetaWaylandSurfaceRole *role = META_WAYLAND_SURFACE_ROLE (cursor_surface); - MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (role); - - if (!meta_xwayland_is_xwayland_surface (surface)) - { - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaLogicalMonitor *logical_monitor; - - logical_monitor = - meta_monitor_manager_get_logical_monitor_at (monitor_manager, x, y); - if (logical_monitor) - { - float texture_scale; - - if (meta_is_stage_views_scaled ()) - texture_scale = 1.0 / surface->scale; - else - texture_scale = (meta_logical_monitor_get_scale (logical_monitor) / - surface->scale); - - meta_cursor_sprite_set_texture_scale (cursor_sprite, texture_scale); - } - } - meta_wayland_surface_update_outputs (surface); -} - -static void -meta_wayland_cursor_surface_assigned (MetaWaylandSurfaceRole *surface_role) -{ - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWaylandCursorSurface *cursor_surface = - META_WAYLAND_CURSOR_SURFACE (surface_role); - MetaWaylandCursorSurfacePrivate *priv = - meta_wayland_cursor_surface_get_instance_private (cursor_surface); - - wl_list_insert_list (&priv->frame_callbacks, - &surface->unassigned.pending_frame_callback_list); - wl_list_init (&surface->unassigned.pending_frame_callback_list); -} - -static void -meta_wayland_cursor_surface_pre_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending) -{ - MetaWaylandCursorSurface *cursor_surface = - META_WAYLAND_CURSOR_SURFACE (surface_role); - MetaWaylandCursorSurfacePrivate *priv = - meta_wayland_cursor_surface_get_instance_private (cursor_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - - if (pending->newly_attached && priv->buffer) - { - meta_wayland_surface_unref_buffer_use_count (surface); - g_clear_object (&priv->buffer); - } -} - -static void -meta_wayland_cursor_surface_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending) -{ - MetaWaylandCursorSurface *cursor_surface = - META_WAYLAND_CURSOR_SURFACE (surface_role); - MetaWaylandCursorSurfacePrivate *priv = - meta_wayland_cursor_surface_get_instance_private (cursor_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface); - - if (pending->newly_attached) - { - g_set_object (&priv->buffer, buffer); - if (priv->buffer) - meta_wayland_surface_ref_buffer_use_count (surface); - } - - wl_list_insert_list (&priv->frame_callbacks, - &pending->frame_callback_list); - wl_list_init (&pending->frame_callback_list); - - if (pending->newly_attached && - ((!cairo_region_is_empty (pending->surface_damage) || - !cairo_region_is_empty (pending->buffer_damage)) || - !priv->buffer)) - update_cursor_sprite_texture (META_WAYLAND_CURSOR_SURFACE (surface_role)); -} - -static gboolean -meta_wayland_cursor_surface_is_on_logical_monitor (MetaWaylandSurfaceRole *role, - MetaLogicalMonitor *logical_monitor) -{ - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (role); - MetaWaylandCursorSurface *cursor_surface = - META_WAYLAND_CURSOR_SURFACE (surface->role); - MetaWaylandCursorSurfacePrivate *priv = - meta_wayland_cursor_surface_get_instance_private (cursor_surface); - ClutterInputDevice *device; - graphene_point_t point; - graphene_rect_t logical_monitor_rect; - - if (!priv->cursor_renderer) - return FALSE; - - logical_monitor_rect = - meta_rectangle_to_graphene_rect (&logical_monitor->rect); - - device = meta_cursor_renderer_get_input_device (priv->cursor_renderer); - clutter_seat_query_state (clutter_input_device_get_seat (device), - device, NULL, &point, NULL); - - return graphene_rect_contains_point (&logical_monitor_rect, &point); -} - -static void -meta_wayland_cursor_surface_dispose (GObject *object) -{ - MetaWaylandCursorSurface *cursor_surface = - META_WAYLAND_CURSOR_SURFACE (object); - MetaWaylandCursorSurfacePrivate *priv = - meta_wayland_cursor_surface_get_instance_private (cursor_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (META_WAYLAND_SURFACE_ROLE (object)); - MetaWaylandFrameCallback *cb, *next; - - wl_list_for_each_safe (cb, next, &priv->frame_callbacks, link) - wl_resource_destroy (cb->resource); - - g_signal_handlers_disconnect_by_func (priv->cursor_sprite, - cursor_sprite_prepare_at, cursor_surface); - - g_clear_object (&priv->cursor_renderer); - g_clear_object (&priv->cursor_sprite); - - if (priv->buffer) - { - meta_wayland_surface_unref_buffer_use_count (surface); - g_clear_object (&priv->buffer); - } - - G_OBJECT_CLASS (meta_wayland_cursor_surface_parent_class)->dispose (object); -} - -static void -meta_wayland_cursor_surface_constructed (GObject *object) -{ - MetaWaylandCursorSurface *cursor_surface = - META_WAYLAND_CURSOR_SURFACE (object); - MetaWaylandCursorSurfacePrivate *priv = - meta_wayland_cursor_surface_get_instance_private (cursor_surface); - MetaWaylandSurfaceRole *surface_role = - META_WAYLAND_SURFACE_ROLE (cursor_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWaylandBuffer *buffer; - - buffer = meta_wayland_surface_get_buffer (surface); - - g_warn_if_fail (!buffer || buffer->resource); - - if (buffer && buffer->resource) - { - g_set_object (&priv->buffer, buffer); - meta_wayland_surface_ref_buffer_use_count (surface); - } - - priv->cursor_sprite = meta_cursor_sprite_wayland_new (surface); - g_signal_connect_object (priv->cursor_sprite, - "prepare-at", - G_CALLBACK (cursor_sprite_prepare_at), - cursor_surface, - 0); -} - -static void -meta_wayland_cursor_surface_init (MetaWaylandCursorSurface *role) -{ - MetaWaylandCursorSurfacePrivate *priv = - meta_wayland_cursor_surface_get_instance_private (role); - - wl_list_init (&priv->frame_callbacks); -} - -static void -meta_wayland_cursor_surface_class_init (MetaWaylandCursorSurfaceClass *klass) -{ - MetaWaylandSurfaceRoleClass *surface_role_class = - META_WAYLAND_SURFACE_ROLE_CLASS (klass); - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - surface_role_class->assigned = meta_wayland_cursor_surface_assigned; - surface_role_class->pre_apply_state = - meta_wayland_cursor_surface_pre_apply_state; - surface_role_class->apply_state = meta_wayland_cursor_surface_apply_state; - surface_role_class->is_on_logical_monitor = - meta_wayland_cursor_surface_is_on_logical_monitor; - - object_class->constructed = meta_wayland_cursor_surface_constructed; - object_class->dispose = meta_wayland_cursor_surface_dispose; -} - -MetaCursorSprite * -meta_wayland_cursor_surface_get_sprite (MetaWaylandCursorSurface *cursor_surface) -{ - MetaWaylandCursorSurfacePrivate *priv = - meta_wayland_cursor_surface_get_instance_private (cursor_surface); - - return META_CURSOR_SPRITE (priv->cursor_sprite); -} - -void -meta_wayland_cursor_surface_set_hotspot (MetaWaylandCursorSurface *cursor_surface, - int hotspot_x, - int hotspot_y) -{ - MetaWaylandCursorSurfacePrivate *priv = - meta_wayland_cursor_surface_get_instance_private (cursor_surface); - - if (priv->hot_x == hotspot_x && - priv->hot_y == hotspot_y) - return; - - priv->hot_x = hotspot_x; - priv->hot_y = hotspot_y; - update_cursor_sprite_texture (cursor_surface); -} - -void -meta_wayland_cursor_surface_get_hotspot (MetaWaylandCursorSurface *cursor_surface, - int *hotspot_x, - int *hotspot_y) -{ - MetaWaylandCursorSurfacePrivate *priv = - meta_wayland_cursor_surface_get_instance_private (cursor_surface); - - if (hotspot_x) - *hotspot_x = priv->hot_x; - if (hotspot_y) - *hotspot_y = priv->hot_y; -} - -static void -on_cursor_painted (MetaCursorRenderer *renderer, - MetaCursorSprite *displayed_sprite, - ClutterStageView *stage_view, - MetaWaylandCursorSurface *cursor_surface) -{ - MetaWaylandCursorSurfacePrivate *priv = - meta_wayland_cursor_surface_get_instance_private (cursor_surface); - guint32 time = (guint32) (g_get_monotonic_time () / 1000); - MetaBackend *backend = meta_get_backend (); - MetaContext *context = meta_backend_get_context (backend); - MetaWaylandCompositor *compositor = - meta_context_get_wayland_compositor (context); - - if (displayed_sprite != META_CURSOR_SPRITE (priv->cursor_sprite)) - return; - - while (!wl_list_empty (&priv->frame_callbacks)) - { - MetaWaylandFrameCallback *callback = - wl_container_of (priv->frame_callbacks.next, callback, link); - - wl_callback_send_done (callback->resource, time); - wl_resource_destroy (callback->resource); - } - - meta_wayland_presentation_time_cursor_painted (&compositor->presentation_time, - stage_view, - cursor_surface); -} - -void -meta_wayland_cursor_surface_set_renderer (MetaWaylandCursorSurface *cursor_surface, - MetaCursorRenderer *renderer) -{ - MetaWaylandCursorSurfacePrivate *priv = - meta_wayland_cursor_surface_get_instance_private (cursor_surface); - - if (priv->cursor_renderer == renderer) - return; - - if (priv->cursor_renderer) - { - g_clear_signal_handler (&priv->cursor_painted_handler_id, - priv->cursor_renderer); - g_object_unref (priv->cursor_renderer); - } - if (renderer) - { - priv->cursor_painted_handler_id = - g_signal_connect_object (renderer, "cursor-painted", - G_CALLBACK (on_cursor_painted), cursor_surface, 0); - g_object_ref (renderer); - } - - priv->cursor_renderer = renderer; - update_cursor_sprite_texture (cursor_surface); -} - -MetaCursorRenderer * -meta_wayland_cursor_surface_get_renderer (MetaWaylandCursorSurface *cursor_surface) -{ - MetaWaylandCursorSurfacePrivate *priv = - meta_wayland_cursor_surface_get_instance_private (cursor_surface); - - return priv->cursor_renderer; -} diff --git a/src/wayland/meta-wayland-cursor-surface.h b/src/wayland/meta-wayland-cursor-surface.h deleted file mode 100644 index 05b344f04..000000000 --- a/src/wayland/meta-wayland-cursor-surface.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2015 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_WAYLAND_CURSOR_SURFACE_H -#define META_WAYLAND_CURSOR_SURFACE_H - -#include "backends/meta-cursor-renderer.h" -#include "wayland/meta-wayland-surface.h" - -struct _MetaWaylandCursorSurfaceClass -{ - MetaWaylandSurfaceRoleClass parent_class; -}; - -#define META_TYPE_WAYLAND_CURSOR_SURFACE (meta_wayland_cursor_surface_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaWaylandCursorSurface, - meta_wayland_cursor_surface, - META, WAYLAND_CURSOR_SURFACE, - MetaWaylandSurfaceRole); - -MetaCursorSprite * meta_wayland_cursor_surface_get_sprite (MetaWaylandCursorSurface *cursor_surface); - -void meta_wayland_cursor_surface_set_hotspot (MetaWaylandCursorSurface *cursor_surface, - int hotspot_x, - int hotspot_y); -void meta_wayland_cursor_surface_get_hotspot (MetaWaylandCursorSurface *cursor_surface, - int *hotspot_x, - int *hotspot_y); -void meta_wayland_cursor_surface_set_renderer (MetaWaylandCursorSurface *cursor_surface, - MetaCursorRenderer *renderer); -MetaCursorRenderer * meta_wayland_cursor_surface_get_renderer (MetaWaylandCursorSurface *cursor_surface); - - -#endif /* META_WAYLAND_CURSOR_SURFACE_H */ diff --git a/src/wayland/meta-wayland-data-device-primary-legacy.c b/src/wayland/meta-wayland-data-device-primary-legacy.c deleted file mode 100644 index 684247e04..000000000 --- a/src/wayland/meta-wayland-data-device-primary-legacy.c +++ /dev/null @@ -1,359 +0,0 @@ -/* - * Copyright © 2011 Kristian Høgsberg - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -/* The file is based on src/data-device.c from Weston */ - -#include "config.h" - -#include "wayland/meta-wayland-data-device-primary-legacy.h" - -#include "compositor/meta-dnd-actor-private.h" -#include "meta/meta-selection-source-memory.h" -#include "wayland/meta-selection-source-wayland-private.h" -#include "wayland/meta-wayland-data-offer-primary-legacy.h" -#include "wayland/meta-wayland-data-source-primary-legacy.h" -#include "wayland/meta-wayland-dnd-surface.h" -#include "wayland/meta-wayland-pointer.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-seat.h" - -#include "gtk-primary-selection-server-protocol.h" - -static struct wl_resource * create_and_send_primary_offer (MetaWaylandDataDevicePrimaryLegacy *data_device, - struct wl_resource *target); - -static void -move_resources (struct wl_list *destination, - struct wl_list *source) -{ - wl_list_insert_list (destination, source); - wl_list_init (source); -} - -static void -move_resources_for_client (struct wl_list *destination, - struct wl_list *source, - struct wl_client *client) -{ - struct wl_resource *resource, *tmp; - wl_resource_for_each_safe (resource, tmp, source) - { - if (wl_resource_get_client (resource) == client) - { - wl_list_remove (wl_resource_get_link (resource)); - wl_list_insert (destination, wl_resource_get_link (resource)); - } - } -} - -static void -unbind_resource (struct wl_resource *resource) -{ - wl_list_remove (wl_resource_get_link (resource)); -} - -static void -default_destructor (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -set_selection_source (MetaWaylandDataDevicePrimaryLegacy *data_device, - MetaSelectionSource *selection_source) - -{ - MetaDisplay *display = meta_get_display (); - - meta_selection_set_owner (meta_display_get_selection (display), - META_SELECTION_PRIMARY, - selection_source); - g_set_object (&data_device->owner, selection_source); -} - -static void -unset_selection_source (MetaWaylandDataDevicePrimaryLegacy *data_device) -{ - MetaDisplay *display = meta_get_display (); - - if (!data_device->owner) - return; - - meta_selection_unset_owner (meta_display_get_selection (display), - META_SELECTION_PRIMARY, - data_device->owner); - g_clear_object (&data_device->owner); -} - -static void -primary_source_destroyed (gpointer data, - GObject *object_was_here) -{ - MetaWaylandDataDevicePrimaryLegacy *data_device = data; - - data_device->data_source = NULL; - unset_selection_source (data_device); -} - -static void -meta_wayland_data_device_primary_legacy_set_selection (MetaWaylandDataDevicePrimaryLegacy *data_device, - MetaWaylandDataSource *source, - uint32_t serial) -{ - MetaWaylandSeat *seat = wl_container_of (data_device, seat, primary_legacy_data_device); - MetaSelectionSource *selection_source; - - g_assert (!source || META_IS_WAYLAND_DATA_SOURCE_PRIMARY_LEGACY (source)); - - if (data_device->data_source && - data_device->serial - serial < UINT32_MAX / 2) - return; - - if (data_device->data_source) - { - g_object_weak_unref (G_OBJECT (data_device->data_source), - primary_source_destroyed, - data_device); - } - - data_device->data_source = source; - data_device->serial = serial; - - if (source) - { - meta_wayland_data_source_set_seat (source, seat); - g_object_weak_ref (G_OBJECT (source), - primary_source_destroyed, - data_device); - - selection_source = meta_selection_source_wayland_new (source); - } - else - { - selection_source = g_object_new (META_TYPE_SELECTION_SOURCE_MEMORY, NULL); - } - - set_selection_source (data_device, selection_source); - g_object_unref (selection_source); -} - -static void -primary_device_set_selection (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *source_resource, - uint32_t serial) -{ - MetaWaylandDataDevicePrimaryLegacy *data_device = wl_resource_get_user_data (resource); - MetaWaylandSeat *seat = wl_container_of (data_device, seat, primary_legacy_data_device); - MetaWaylandDataSource *source = NULL; - - if (source_resource) - source = wl_resource_get_user_data (source_resource); - - if (wl_resource_get_client (resource) != - meta_wayland_keyboard_get_focus_client (seat->keyboard)) - { - if (source) - meta_wayland_data_source_cancel (source); - return; - } - - meta_wayland_data_device_primary_legacy_set_selection (data_device, source, serial); -} - -static const struct gtk_primary_selection_device_interface primary_device_interface = { - primary_device_set_selection, - default_destructor, -}; - -static void -owner_changed_cb (MetaSelection *selection, - MetaSelectionType selection_type, - MetaSelectionSource *new_owner, - MetaWaylandDataDevicePrimaryLegacy *data_device) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaWaylandSeat *seat = compositor->seat; - struct wl_resource *data_device_resource; - struct wl_client *focus_client; - - focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard); - if (!focus_client) - return; - - if (selection_type == META_SELECTION_PRIMARY) - { - wl_resource_for_each (data_device_resource, &data_device->focus_resource_list) - { - struct wl_resource *offer = NULL; - - if (new_owner) - { - offer = create_and_send_primary_offer (data_device, - data_device_resource); - } - - gtk_primary_selection_device_send_selection (data_device_resource, - offer); - } - } -} - -static void -ensure_owners_changed_handler_connected (MetaWaylandDataDevicePrimaryLegacy *data_device) -{ - if (data_device->selection_owner_signal_id != 0) - return; - - data_device->selection_owner_signal_id = - g_signal_connect (meta_display_get_selection (meta_get_display ()), - "owner-changed", - G_CALLBACK (owner_changed_cb), data_device); -} - -static void -primary_device_manager_create_source (struct wl_client *client, - struct wl_resource *manager_resource, - guint32 id) -{ - struct wl_resource *source_resource; - - source_resource = - wl_resource_create (client, >k_primary_selection_source_interface, - wl_resource_get_version (manager_resource), - id); - meta_wayland_data_source_primary_legacy_new (source_resource); -} - -static void -primary_device_manager_get_device (struct wl_client *client, - struct wl_resource *manager_resource, - guint32 id, - struct wl_resource *seat_resource) -{ - MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); - struct wl_resource *cr; - - cr = wl_resource_create (client, >k_primary_selection_device_interface, - wl_resource_get_version (manager_resource), id); - wl_resource_set_implementation (cr, &primary_device_interface, - &seat->primary_legacy_data_device, unbind_resource); - wl_list_insert (&seat->primary_legacy_data_device.resource_list, - wl_resource_get_link (cr)); - - ensure_owners_changed_handler_connected (&seat->primary_legacy_data_device); -} - -static const struct gtk_primary_selection_device_manager_interface primary_manager_interface = { - primary_device_manager_create_source, - primary_device_manager_get_device, - default_destructor, -}; - -static void -bind_primary_manager (struct wl_client *client, - void *data, - uint32_t version, - uint32_t id) -{ - struct wl_resource *resource; - - resource = wl_resource_create (client, >k_primary_selection_device_manager_interface, - version, id); - wl_resource_set_implementation (resource, &primary_manager_interface, NULL, NULL); -} - -void -meta_wayland_data_device_primary_legacy_manager_init (MetaWaylandCompositor *compositor) -{ - if (wl_global_create (compositor->wayland_display, - >k_primary_selection_device_manager_interface, - META_GTK_PRIMARY_SELECTION_VERSION, - NULL, bind_primary_manager) == NULL) - g_error ("Could not create data_device"); -} - -void -meta_wayland_data_device_primary_legacy_init (MetaWaylandDataDevicePrimaryLegacy *data_device) -{ - wl_list_init (&data_device->resource_list); - wl_list_init (&data_device->focus_resource_list); -} - -static struct wl_resource * -create_and_send_primary_offer (MetaWaylandDataDevicePrimaryLegacy *data_device, - struct wl_resource *target) -{ - MetaWaylandDataOffer *offer; - MetaDisplay *display = meta_get_display (); - struct wl_resource *resource; - GList *mimetypes, *l; - - mimetypes = meta_selection_get_mimetypes (meta_display_get_selection (display), - META_SELECTION_PRIMARY); - if (!mimetypes) - return NULL; - - offer = meta_wayland_data_offer_primary_legacy_new (target); - resource = meta_wayland_data_offer_get_resource (offer); - - gtk_primary_selection_device_send_data_offer (target, resource); - - for (l = mimetypes; l; l = l->next) - gtk_primary_selection_offer_send_offer (resource, l->data); - - g_list_free_full (mimetypes, g_free); - - return resource; -} - -void -meta_wayland_data_device_primary_legacy_set_keyboard_focus (MetaWaylandDataDevicePrimaryLegacy *data_device) -{ - MetaWaylandSeat *seat = wl_container_of (data_device, seat, primary_legacy_data_device); - struct wl_client *focus_client; - struct wl_resource *data_device_resource; - - focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard); - - if (focus_client == data_device->focus_client) - return; - - data_device->focus_client = focus_client; - move_resources (&data_device->resource_list, - &data_device->focus_resource_list); - - if (!focus_client) - return; - - move_resources_for_client (&data_device->focus_resource_list, - &data_device->resource_list, - focus_client); - - wl_resource_for_each (data_device_resource, &data_device->focus_resource_list) - { - struct wl_resource *offer; - offer = create_and_send_primary_offer (data_device, data_device_resource); - gtk_primary_selection_device_send_selection (data_device_resource, offer); - } -} diff --git a/src/wayland/meta-wayland-data-device-primary-legacy.h b/src/wayland/meta-wayland-data-device-primary-legacy.h deleted file mode 100644 index c1b4d6e99..000000000 --- a/src/wayland/meta-wayland-data-device-primary-legacy.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * 2020 Red Hat Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#ifndef META_WAYLAND_DATA_DEVICE_PRIMARY_LEGACY_H -#define META_WAYLAND_DATA_DEVICE_PRIMARY_LEGACY_H - -#include -#include - -#include "clutter/clutter.h" -#include "meta/meta-selection-source.h" -#include "wayland/meta-wayland-data-offer.h" -#include "wayland/meta-wayland-data-source.h" -#include "wayland/meta-wayland-types.h" - -struct _MetaWaylandDataDevicePrimaryLegacy -{ - uint32_t serial; - MetaWaylandDataSource *data_source; - struct wl_list resource_list; - struct wl_list focus_resource_list; - struct wl_client *focus_client; - - guint selection_owner_signal_id; - - MetaSelectionSource *owner; -}; - -void meta_wayland_data_device_primary_legacy_manager_init (MetaWaylandCompositor *compositor); - -void meta_wayland_data_device_primary_legacy_init (MetaWaylandDataDevicePrimaryLegacy *data_device); - -void meta_wayland_data_device_primary_legacy_set_keyboard_focus (MetaWaylandDataDevicePrimaryLegacy *data_device); - -#endif /* META_WAYLAND_DATA_DEVICE_PRIMARY_LEGACY_H */ diff --git a/src/wayland/meta-wayland-data-device-primary.c b/src/wayland/meta-wayland-data-device-primary.c deleted file mode 100644 index 9592e8f77..000000000 --- a/src/wayland/meta-wayland-data-device-primary.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright © 2011 Kristian Høgsberg - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -/* The file is based on src/data-device.c from Weston */ - -#include "config.h" - -#include "wayland/meta-wayland-data-device-primary.h" - -#include "compositor/meta-dnd-actor-private.h" -#include "meta/meta-selection-source-memory.h" -#include "wayland/meta-selection-source-wayland-private.h" -#include "wayland/meta-wayland-data-offer-primary.h" -#include "wayland/meta-wayland-data-source-primary.h" -#include "wayland/meta-wayland-dnd-surface.h" -#include "wayland/meta-wayland-pointer.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-seat.h" - -#include "primary-selection-unstable-v1-server-protocol.h" - -static struct wl_resource * create_and_send_primary_offer (MetaWaylandDataDevicePrimary *data_device, - struct wl_resource *target); - -static void -move_resources (struct wl_list *destination, - struct wl_list *source) -{ - wl_list_insert_list (destination, source); - wl_list_init (source); -} - -static void -move_resources_for_client (struct wl_list *destination, - struct wl_list *source, - struct wl_client *client) -{ - struct wl_resource *resource, *tmp; - wl_resource_for_each_safe (resource, tmp, source) - { - if (wl_resource_get_client (resource) == client) - { - wl_list_remove (wl_resource_get_link (resource)); - wl_list_insert (destination, wl_resource_get_link (resource)); - } - } -} - -static void -unbind_resource (struct wl_resource *resource) -{ - wl_list_remove (wl_resource_get_link (resource)); -} - -static void -default_destructor (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -set_selection_source (MetaWaylandDataDevicePrimary *data_device, - MetaSelectionSource *selection_source) - -{ - MetaDisplay *display = meta_get_display (); - - meta_selection_set_owner (meta_display_get_selection (display), - META_SELECTION_PRIMARY, - selection_source); - g_set_object (&data_device->owner, selection_source); -} - -static void -unset_selection_source (MetaWaylandDataDevicePrimary *data_device) -{ - MetaDisplay *display = meta_get_display (); - - if (!data_device->owner) - return; - - meta_selection_unset_owner (meta_display_get_selection (display), - META_SELECTION_PRIMARY, - data_device->owner); - g_clear_object (&data_device->owner); -} - -static void -primary_source_destroyed (gpointer data, - GObject *object_was_here) -{ - MetaWaylandDataDevicePrimary *data_device = data; - - data_device->data_source = NULL; - unset_selection_source (data_device); -} - -static void -meta_wayland_data_device_primary_set_selection (MetaWaylandDataDevicePrimary *data_device, - MetaWaylandDataSource *source, - uint32_t serial) -{ - MetaWaylandSeat *seat = wl_container_of (data_device, seat, primary_data_device); - MetaSelectionSource *selection_source; - - g_assert (!source || META_IS_WAYLAND_DATA_SOURCE_PRIMARY (source)); - - if (data_device->data_source && - data_device->serial - serial < UINT32_MAX / 2) - return; - - if (data_device->data_source) - { - g_object_weak_unref (G_OBJECT (data_device->data_source), - primary_source_destroyed, - data_device); - } - - data_device->data_source = source; - data_device->serial = serial; - - if (source) - { - meta_wayland_data_source_set_seat (source, seat); - g_object_weak_ref (G_OBJECT (source), - primary_source_destroyed, - data_device); - - selection_source = meta_selection_source_wayland_new (source); - } - else - { - selection_source = g_object_new (META_TYPE_SELECTION_SOURCE_MEMORY, NULL); - } - - set_selection_source (data_device, selection_source); - g_object_unref (selection_source); -} - -static void -primary_device_set_selection (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *source_resource, - uint32_t serial) -{ - MetaWaylandDataDevicePrimary *data_device = wl_resource_get_user_data (resource); - MetaWaylandSeat *seat = wl_container_of (data_device, seat, primary_data_device); - MetaWaylandDataSource *source = NULL; - - if (source_resource) - source = wl_resource_get_user_data (source_resource); - - if (wl_resource_get_client (resource) != - meta_wayland_keyboard_get_focus_client (seat->keyboard)) - { - if (source) - meta_wayland_data_source_cancel (source); - return; - } - - meta_wayland_data_device_primary_set_selection (data_device, source, serial); -} - -static const struct zwp_primary_selection_device_v1_interface primary_device_interface = { - primary_device_set_selection, - default_destructor, -}; - -static void -owner_changed_cb (MetaSelection *selection, - MetaSelectionType selection_type, - MetaSelectionSource *new_owner, - MetaWaylandDataDevicePrimary *data_device) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaWaylandSeat *seat = compositor->seat; - struct wl_resource *data_device_resource; - struct wl_client *focus_client; - - focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard); - if (!focus_client) - return; - - if (selection_type == META_SELECTION_PRIMARY) - { - wl_resource_for_each (data_device_resource, &data_device->focus_resource_list) - { - struct wl_resource *offer = NULL; - - if (new_owner) - { - offer = create_and_send_primary_offer (data_device, - data_device_resource); - } - - zwp_primary_selection_device_v1_send_selection (data_device_resource, - offer); - } - } -} - -static void -ensure_owners_changed_handler_connected (MetaWaylandDataDevicePrimary *data_device) -{ - if (data_device->selection_owner_signal_id != 0) - return; - - data_device->selection_owner_signal_id = - g_signal_connect (meta_display_get_selection (meta_get_display ()), - "owner-changed", - G_CALLBACK (owner_changed_cb), data_device); -} - -static void -primary_device_manager_create_source (struct wl_client *client, - struct wl_resource *manager_resource, - guint32 id) -{ - struct wl_resource *source_resource; - - source_resource = - wl_resource_create (client, &zwp_primary_selection_source_v1_interface, - wl_resource_get_version (manager_resource), - id); - meta_wayland_data_source_primary_new (source_resource); -} - -static void -primary_device_manager_get_device (struct wl_client *client, - struct wl_resource *manager_resource, - guint32 id, - struct wl_resource *seat_resource) -{ - MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); - struct wl_resource *cr; - - cr = wl_resource_create (client, &zwp_primary_selection_device_v1_interface, - wl_resource_get_version (manager_resource), id); - wl_resource_set_implementation (cr, &primary_device_interface, - &seat->primary_data_device, unbind_resource); - wl_list_insert (&seat->primary_data_device.resource_list, wl_resource_get_link (cr)); - - ensure_owners_changed_handler_connected (&seat->primary_data_device); -} - -static const struct zwp_primary_selection_device_manager_v1_interface primary_manager_interface = { - primary_device_manager_create_source, - primary_device_manager_get_device, - default_destructor, -}; - -static void -bind_primary_manager (struct wl_client *client, - void *data, - uint32_t version, - uint32_t id) -{ - struct wl_resource *resource; - - resource = wl_resource_create (client, &zwp_primary_selection_device_manager_v1_interface, - version, id); - wl_resource_set_implementation (resource, &primary_manager_interface, NULL, NULL); -} - -void -meta_wayland_data_device_primary_manager_init (MetaWaylandCompositor *compositor) -{ - if (wl_global_create (compositor->wayland_display, - &zwp_primary_selection_device_manager_v1_interface, - META_ZWP_PRIMARY_SELECTION_V1_VERSION, - NULL, bind_primary_manager) == NULL) - g_error ("Could not create data_device"); -} - -void -meta_wayland_data_device_primary_init (MetaWaylandDataDevicePrimary *data_device) -{ - wl_list_init (&data_device->resource_list); - wl_list_init (&data_device->focus_resource_list); -} - -static struct wl_resource * -create_and_send_primary_offer (MetaWaylandDataDevicePrimary *data_device, - struct wl_resource *target) -{ - MetaWaylandDataOffer *offer; - MetaDisplay *display = meta_get_display (); - struct wl_resource *resource; - GList *mimetypes, *l; - - mimetypes = meta_selection_get_mimetypes (meta_display_get_selection (display), - META_SELECTION_PRIMARY); - if (!mimetypes) - return NULL; - - offer = meta_wayland_data_offer_primary_new (target); - resource = meta_wayland_data_offer_get_resource (offer); - - zwp_primary_selection_device_v1_send_data_offer (target, resource); - - for (l = mimetypes; l; l = l->next) - zwp_primary_selection_offer_v1_send_offer (resource, l->data); - - g_list_free_full (mimetypes, g_free); - - return resource; -} - -void -meta_wayland_data_device_primary_set_keyboard_focus (MetaWaylandDataDevicePrimary *data_device) -{ - MetaWaylandSeat *seat = wl_container_of (data_device, seat, primary_data_device); - struct wl_client *focus_client; - struct wl_resource *data_device_resource; - - focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard); - - if (focus_client == data_device->focus_client) - return; - - data_device->focus_client = focus_client; - move_resources (&data_device->resource_list, - &data_device->focus_resource_list); - - if (!focus_client) - return; - - move_resources_for_client (&data_device->focus_resource_list, - &data_device->resource_list, - focus_client); - - wl_resource_for_each (data_device_resource, &data_device->focus_resource_list) - { - struct wl_resource *offer; - offer = create_and_send_primary_offer (data_device, data_device_resource); - zwp_primary_selection_device_v1_send_selection (data_device_resource, offer); - } -} diff --git a/src/wayland/meta-wayland-data-device-primary.h b/src/wayland/meta-wayland-data-device-primary.h deleted file mode 100644 index 77fcbf97e..000000000 --- a/src/wayland/meta-wayland-data-device-primary.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * 2020 Red Hat Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#ifndef META_WAYLAND_DATA_DEVICE_PRIMARY_H -#define META_WAYLAND_DATA_DEVICE_PRIMARY_H - -#include -#include - -#include "clutter/clutter.h" -#include "meta/meta-selection-source.h" -#include "wayland/meta-wayland-data-offer.h" -#include "wayland/meta-wayland-data-source.h" -#include "wayland/meta-wayland-types.h" - -struct _MetaWaylandDataDevicePrimary -{ - uint32_t serial; - MetaWaylandDataSource *data_source; - struct wl_list resource_list; - struct wl_list focus_resource_list; - struct wl_client *focus_client; - - guint selection_owner_signal_id; - - MetaSelectionSource *owner; -}; - -void meta_wayland_data_device_primary_manager_init (MetaWaylandCompositor *compositor); - -void meta_wayland_data_device_primary_init (MetaWaylandDataDevicePrimary *data_device); - -void meta_wayland_data_device_primary_set_keyboard_focus (MetaWaylandDataDevicePrimary *data_device); - -#endif /* META_WAYLAND_DATA_DEVICE_PRIMARY_H */ diff --git a/src/wayland/meta-wayland-data-device.c b/src/wayland/meta-wayland-data-device.c deleted file mode 100644 index 2f3c154a1..000000000 --- a/src/wayland/meta-wayland-data-device.c +++ /dev/null @@ -1,1147 +0,0 @@ -/* - * Copyright © 2011 Kristian Høgsberg - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -/* The file is based on src/data-device.c from Weston */ - -#include "config.h" - -#include "wayland/meta-wayland-data-device.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "compositor/meta-dnd-actor-private.h" -#include "meta/meta-selection-source-memory.h" -#include "wayland/meta-selection-source-wayland-private.h" -#include "wayland/meta-wayland-dnd-surface.h" -#include "wayland/meta-wayland-pointer.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-seat.h" - -#define ROOTWINDOW_DROP_MIME "application/x-rootwindow-drop" - -static void unset_selection_source (MetaWaylandDataDevice *data_device, - MetaSelectionType selection_type); - -static void -drag_grab_data_source_destroyed (gpointer data, GObject *where_the_object_was); - -static struct wl_resource * create_and_send_clipboard_offer (MetaWaylandDataDevice *data_device, - struct wl_resource *target); - -static void -move_resources (struct wl_list *destination, - struct wl_list *source) -{ - wl_list_insert_list (destination, source); - wl_list_init (source); -} - -static void -move_resources_for_client (struct wl_list *destination, - struct wl_list *source, - struct wl_client *client) -{ - struct wl_resource *resource, *tmp; - wl_resource_for_each_safe (resource, tmp, source) - { - if (wl_resource_get_client (resource) == client) - { - wl_list_remove (wl_resource_get_link (resource)); - wl_list_insert (destination, wl_resource_get_link (resource)); - } - } -} - -static void -unbind_resource (struct wl_resource *resource) -{ - wl_list_remove (wl_resource_get_link (resource)); -} - -static void -default_destructor (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static struct wl_resource * -create_and_send_dnd_offer (MetaWaylandDataSource *source, - struct wl_resource *target) -{ - MetaWaylandDataOffer *offer; - struct wl_array *mime_types; - struct wl_resource *resource; - char **p; - - offer = meta_wayland_data_offer_new (META_SELECTION_DND, source, target); - resource = meta_wayland_data_offer_get_resource (offer); - - wl_data_device_send_data_offer (target, resource); - - mime_types = meta_wayland_data_source_get_mime_types (source); - - wl_array_for_each (p, mime_types) - wl_data_offer_send_offer (resource, *p); - - meta_wayland_data_offer_update_action (offer); - meta_wayland_data_source_set_current_offer (source, offer); - - return resource; -} - -struct _MetaWaylandDragGrab { - MetaWaylandPointerGrab generic; - - MetaWaylandKeyboardGrab keyboard_grab; - - MetaWaylandSeat *seat; - struct wl_client *drag_client; - - MetaWaylandSurface *drag_focus; - gulong drag_focus_destroy_handler_id; - struct wl_resource *drag_focus_data_device; - struct wl_listener drag_focus_listener; - - MetaWaylandSurface *drag_surface; - struct wl_listener drag_icon_listener; - - MetaWaylandDataSource *drag_data_source; - - ClutterActor *feedback_actor; - - MetaWaylandSurface *drag_origin; - struct wl_listener drag_origin_listener; - - int drag_start_x, drag_start_y; - ClutterModifierType buttons; - - guint need_initial_focus : 1; -}; - -static void -set_selection_source (MetaWaylandDataDevice *data_device, - MetaSelectionType selection_type, - MetaSelectionSource *selection_source) - -{ - MetaDisplay *display = meta_get_display (); - - meta_selection_set_owner (meta_display_get_selection (display), - selection_type, selection_source); - g_set_object (&data_device->owners[selection_type], selection_source); -} - -static void -unset_selection_source (MetaWaylandDataDevice *data_device, - MetaSelectionType selection_type) -{ - MetaDisplay *display = meta_get_display (); - - if (!data_device->owners[selection_type]) - return; - - meta_selection_unset_owner (meta_display_get_selection (display), - selection_type, - data_device->owners[selection_type]); - g_clear_object (&data_device->owners[selection_type]); -} - -static void -destroy_drag_focus (struct wl_listener *listener, void *data) -{ - MetaWaylandDragGrab *grab = wl_container_of (listener, grab, drag_focus_listener); - - grab->drag_focus_data_device = NULL; - - g_clear_signal_handler (&grab->drag_focus_destroy_handler_id, - grab->drag_focus); - grab->drag_focus = NULL; -} - -static void -on_drag_focus_destroyed (MetaWaylandSurface *surface, - MetaWaylandDragGrab *grab) -{ - meta_wayland_surface_drag_dest_focus_out (grab->drag_focus); - grab->drag_focus = NULL; -} - -static void -meta_wayland_drag_grab_set_source (MetaWaylandDragGrab *drag_grab, - MetaWaylandDataSource *source) -{ - if (drag_grab->drag_data_source) - g_object_weak_unref (G_OBJECT (drag_grab->drag_data_source), - drag_grab_data_source_destroyed, - drag_grab); - - drag_grab->drag_data_source = source; - - if (source) - g_object_weak_ref (G_OBJECT (source), - drag_grab_data_source_destroyed, - drag_grab); -} - -static void -meta_wayland_drag_source_fake_acceptance (MetaWaylandDataSource *source, - const gchar *mimetype) -{ - uint32_t actions, user_action, action = 0; - - meta_wayland_data_source_get_actions (source, &actions); - user_action = meta_wayland_data_source_get_user_action (source); - - /* Pick a suitable action */ - if ((user_action & actions) != 0) - action = user_action; - else if (actions != 0) - action = 1 << (ffs (actions) - 1); - - /* Bail out if there is none, source didn't cooperate */ - if (action == 0) - return; - - meta_wayland_data_source_target (source, mimetype); - meta_wayland_data_source_set_current_action (source, action); - meta_wayland_data_source_set_has_target (source, TRUE); -} - -void -meta_wayland_drag_grab_set_focus (MetaWaylandDragGrab *drag_grab, - MetaWaylandSurface *surface) -{ - MetaWaylandSeat *seat = drag_grab->seat; - MetaWaylandDataSource *source = drag_grab->drag_data_source; - struct wl_client *client; - struct wl_resource *data_device_resource, *offer = NULL; - - if (!drag_grab->need_initial_focus && - drag_grab->drag_focus == surface) - return; - - drag_grab->need_initial_focus = FALSE; - - if (drag_grab->drag_focus) - { - meta_wayland_surface_drag_dest_focus_out (drag_grab->drag_focus); - g_clear_signal_handler (&drag_grab->drag_focus_destroy_handler_id, - drag_grab->drag_focus); - drag_grab->drag_focus = NULL; - } - - if (source) - meta_wayland_data_source_set_current_offer (source, NULL); - - if (!surface && source && - meta_wayland_data_source_has_mime_type (source, ROOTWINDOW_DROP_MIME)) - meta_wayland_drag_source_fake_acceptance (source, ROOTWINDOW_DROP_MIME); - else if (source) - meta_wayland_data_source_target (source, NULL); - - if (!surface) - return; - - if (!source && - wl_resource_get_client (surface->resource) != drag_grab->drag_client) - return; - - client = wl_resource_get_client (surface->resource); - - data_device_resource = wl_resource_find_for_client (&seat->data_device.resource_list, client); - if (!data_device_resource) - { - data_device_resource = - wl_resource_find_for_client (&seat->data_device.focus_resource_list, - client); - } - - if (source && data_device_resource) - offer = create_and_send_dnd_offer (source, data_device_resource); - - drag_grab->drag_focus = surface; - drag_grab->drag_focus_destroy_handler_id = - g_signal_connect (surface, "destroy", - G_CALLBACK (on_drag_focus_destroyed), - drag_grab); - drag_grab->drag_focus_data_device = data_device_resource; - - meta_wayland_surface_drag_dest_focus_in (drag_grab->drag_focus, - offer ? wl_resource_get_user_data (offer) : NULL); -} - -MetaWaylandSurface * -meta_wayland_drag_grab_get_focus (MetaWaylandDragGrab *drag_grab) -{ - return drag_grab->drag_focus; -} - -void -meta_wayland_drag_grab_update_feedback_actor (MetaWaylandDragGrab *drag_grab, - ClutterEvent *event) -{ - meta_feedback_actor_update (META_FEEDBACK_ACTOR (drag_grab->feedback_actor), - event); -} - -static void -drag_grab_focus (MetaWaylandPointerGrab *grab, - MetaWaylandSurface *surface) -{ - MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab; - - meta_wayland_drag_grab_set_focus (drag_grab, surface); -} - -static void -data_source_update_user_dnd_action (MetaWaylandDataSource *source, - ClutterModifierType modifiers) -{ - enum wl_data_device_manager_dnd_action user_dnd_action = 0; - - if (modifiers & CLUTTER_SHIFT_MASK) - user_dnd_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE; - else if (modifiers & CLUTTER_CONTROL_MASK) - user_dnd_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY; - else if (modifiers & (CLUTTER_MOD1_MASK | CLUTTER_BUTTON2_MASK)) - user_dnd_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK; - - meta_wayland_data_source_set_user_action (source, user_dnd_action); -} - -static void -drag_grab_motion (MetaWaylandPointerGrab *grab, - const ClutterEvent *event) -{ - MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab; - - if (drag_grab->drag_focus) - meta_wayland_surface_drag_dest_motion (drag_grab->drag_focus, event); - - if (drag_grab->drag_surface) - meta_feedback_actor_update (META_FEEDBACK_ACTOR (drag_grab->feedback_actor), - event); -} - -static void -data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab) -{ - meta_wayland_drag_grab_set_source (drag_grab, NULL); - meta_wayland_drag_grab_set_focus (drag_grab, NULL); - - if (drag_grab->drag_origin) - { - drag_grab->drag_origin = NULL; - wl_list_remove (&drag_grab->drag_origin_listener.link); - } - - if (drag_grab->drag_surface) - { - drag_grab->drag_surface = NULL; - wl_list_remove (&drag_grab->drag_icon_listener.link); - } - - if (drag_grab->feedback_actor) - { - clutter_actor_remove_all_children (drag_grab->feedback_actor); - clutter_actor_destroy (drag_grab->feedback_actor); - } - - drag_grab->seat->data_device.current_grab = NULL; - - /* There might be other grabs created in result to DnD actions like popups - * on "ask" actions, we must not reset those, only our own. - */ - if (drag_grab->generic.pointer->grab == (MetaWaylandPointerGrab *) drag_grab) - { - meta_wayland_pointer_end_grab (drag_grab->generic.pointer); - meta_wayland_keyboard_end_grab (drag_grab->keyboard_grab.keyboard); - meta_display_sync_wayland_input_focus (meta_get_display ()); - } - - g_free (drag_grab); -} - -static gboolean -on_fake_read_hup (GIOChannel *channel, - GIOCondition condition, - gpointer data) -{ - MetaWaylandDataSource *source = data; - - meta_wayland_data_source_notify_finish (source); - g_io_channel_shutdown (channel, FALSE, NULL); - g_io_channel_unref (channel); - - return G_SOURCE_REMOVE; -} - -static void -meta_wayland_data_source_fake_read (MetaWaylandDataSource *source, - const gchar *mimetype) -{ - GIOChannel *channel; - int p[2]; - - if (!g_unix_open_pipe (p, FD_CLOEXEC, NULL)) - { - meta_wayland_data_source_notify_finish (source); - return; - } - - if (!g_unix_set_fd_nonblocking (p[0], TRUE, NULL) || - !g_unix_set_fd_nonblocking (p[1], TRUE, NULL)) - { - meta_wayland_data_source_notify_finish (source); - close (p[0]); - close (p[1]); - return; - } - - meta_wayland_data_source_send (source, mimetype, p[1]); - close (p[1]); - channel = g_io_channel_unix_new (p[0]); - g_io_channel_set_close_on_unref (channel, TRUE); - g_io_add_watch (channel, G_IO_HUP, on_fake_read_hup, source); -} - -static void -drag_grab_button (MetaWaylandPointerGrab *grab, - const ClutterEvent *event) -{ - MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab; - MetaWaylandSeat *seat = drag_grab->seat; - ClutterEventType event_type = clutter_event_type (event); - - if (drag_grab->generic.pointer->grab_button == clutter_event_get_button (event) && - event_type == CLUTTER_BUTTON_RELEASE) - { - MetaWaylandDataSource *source = drag_grab->drag_data_source; - gboolean success; - - if (drag_grab->drag_focus && source && - meta_wayland_data_source_has_target (source) && - meta_wayland_data_source_get_current_action (source)) - { - meta_wayland_surface_drag_dest_drop (drag_grab->drag_focus); - meta_wayland_data_source_notify_drop_performed (source); - - meta_wayland_data_source_update_in_ask (source); - success = TRUE; - } - else if (!drag_grab->drag_focus && source && - meta_wayland_data_source_has_target (source) && - meta_wayland_data_source_get_current_action (source) && - meta_wayland_data_source_has_mime_type (source, ROOTWINDOW_DROP_MIME)) - { - /* Perform a fake read, that will lead to notify_finish() being called */ - meta_wayland_data_source_fake_read (source, ROOTWINDOW_DROP_MIME); - success = TRUE; - } - else - { - if (source) - meta_wayland_data_source_set_current_offer (source, NULL); - meta_wayland_data_device_set_dnd_source (&seat->data_device, NULL); - unset_selection_source (&seat->data_device, META_SELECTION_DND); - success = FALSE; - } - - /* Finish drag and let actor self-destruct */ - meta_dnd_actor_drag_finish (META_DND_ACTOR (drag_grab->feedback_actor), success); - drag_grab->feedback_actor = NULL; - } - - if (seat->pointer->button_count == 0 && - event_type == CLUTTER_BUTTON_RELEASE) - data_device_end_drag_grab (drag_grab); -} - -static const MetaWaylandPointerGrabInterface drag_grab_interface = { - drag_grab_focus, - drag_grab_motion, - drag_grab_button, -}; - -static gboolean -keyboard_drag_grab_key (MetaWaylandKeyboardGrab *grab, - const ClutterEvent *event) -{ - if (event->key.keyval == CLUTTER_KEY_Escape) - { - MetaWaylandDragGrab *drag_grab; - - drag_grab = wl_container_of (grab, drag_grab, keyboard_grab); - meta_wayland_data_source_cancel (drag_grab->drag_data_source); - meta_wayland_data_source_set_current_offer (drag_grab->drag_data_source, NULL); - meta_dnd_actor_drag_finish (META_DND_ACTOR (drag_grab->feedback_actor), FALSE); - drag_grab->feedback_actor = NULL; - data_device_end_drag_grab (drag_grab); - - return TRUE; - } - - return FALSE; -} - -static void -keyboard_drag_grab_modifiers (MetaWaylandKeyboardGrab *grab, - ClutterModifierType modifiers) -{ - MetaWaylandDragGrab *drag_grab; - - drag_grab = wl_container_of (grab, drag_grab, keyboard_grab); - - /* The modifiers here just contain keyboard modifiers, mix it with the - * mouse button modifiers we got when starting the drag operation. - */ - modifiers |= drag_grab->buttons; - - if (drag_grab->drag_data_source) - { - data_source_update_user_dnd_action (drag_grab->drag_data_source, modifiers); - - if (drag_grab->drag_focus) - meta_wayland_surface_drag_dest_update (drag_grab->drag_focus); - } -} - -static const MetaWaylandKeyboardGrabInterface keyboard_drag_grab_interface = { - keyboard_drag_grab_key, - keyboard_drag_grab_modifiers -}; - -static void -destroy_data_device_origin (struct wl_listener *listener, void *data) -{ - MetaWaylandDragGrab *drag_grab = - wl_container_of (listener, drag_grab, drag_origin_listener); - - drag_grab->drag_origin = NULL; - meta_wayland_data_device_set_dnd_source (&drag_grab->seat->data_device, NULL); - unset_selection_source (&drag_grab->seat->data_device, META_SELECTION_DND); - meta_wayland_data_source_set_current_offer (drag_grab->drag_data_source, NULL); - data_device_end_drag_grab (drag_grab); -} - -static void -drag_grab_data_source_destroyed (gpointer data, GObject *where_the_object_was) -{ - MetaWaylandDragGrab *drag_grab = data; - - drag_grab->drag_data_source = NULL; - data_device_end_drag_grab (drag_grab); -} - -static void -destroy_data_device_icon (struct wl_listener *listener, void *data) -{ - MetaWaylandDragGrab *drag_grab = - wl_container_of (listener, drag_grab, drag_icon_listener); - - drag_grab->drag_surface = NULL; - - if (drag_grab->feedback_actor) - clutter_actor_remove_all_children (drag_grab->feedback_actor); -} - -void -meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data_device, - struct wl_client *client, - const MetaWaylandPointerGrabInterface *funcs, - MetaWaylandSurface *surface, - MetaWaylandDataSource *source, - MetaWaylandSurface *icon_surface) -{ - MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device); - MetaWaylandDragGrab *drag_grab; - graphene_point_t pos, surface_pos; - ClutterModifierType modifiers; - MetaSurfaceActor *surface_actor; - - data_device->current_grab = drag_grab = g_new0 (MetaWaylandDragGrab, 1); - - drag_grab->generic.interface = funcs; - drag_grab->generic.pointer = seat->pointer; - - drag_grab->keyboard_grab.interface = &keyboard_drag_grab_interface; - drag_grab->keyboard_grab.keyboard = seat->keyboard; - - drag_grab->drag_client = client; - drag_grab->seat = seat; - - drag_grab->drag_origin = surface; - drag_grab->drag_origin_listener.notify = destroy_data_device_origin; - wl_resource_add_destroy_listener (surface->resource, - &drag_grab->drag_origin_listener); - - surface_actor = meta_wayland_surface_get_actor (surface); - - clutter_actor_transform_stage_point (CLUTTER_ACTOR (surface_actor), - seat->pointer->grab_x, - seat->pointer->grab_y, - &surface_pos.x, &surface_pos.y); - drag_grab->drag_start_x = surface_pos.x; - drag_grab->drag_start_y = surface_pos.y; - - drag_grab->need_initial_focus = TRUE; - - clutter_seat_query_state (clutter_input_device_get_seat (seat->pointer->device), - seat->pointer->device, NULL, NULL, &modifiers); - drag_grab->buttons = modifiers & - (CLUTTER_BUTTON1_MASK | CLUTTER_BUTTON2_MASK | CLUTTER_BUTTON3_MASK | - CLUTTER_BUTTON4_MASK | CLUTTER_BUTTON5_MASK); - - meta_wayland_drag_grab_set_source (drag_grab, source); - meta_wayland_data_device_set_dnd_source (data_device, - drag_grab->drag_data_source); - data_source_update_user_dnd_action (source, modifiers); - - if (icon_surface) - { - ClutterActor *drag_surface_actor; - - drag_grab->drag_surface = icon_surface; - - drag_grab->drag_icon_listener.notify = destroy_data_device_icon; - wl_resource_add_destroy_listener (icon_surface->resource, - &drag_grab->drag_icon_listener); - - drag_surface_actor = CLUTTER_ACTOR (meta_wayland_surface_get_actor (drag_grab->drag_surface)); - - drag_grab->feedback_actor = meta_dnd_actor_new (CLUTTER_ACTOR (surface_actor), - drag_grab->drag_start_x, - drag_grab->drag_start_y); - meta_feedback_actor_set_anchor (META_FEEDBACK_ACTOR (drag_grab->feedback_actor), - 0, 0); - clutter_actor_add_child (drag_grab->feedback_actor, drag_surface_actor); - - clutter_seat_query_state (clutter_input_device_get_seat (seat->pointer->device), - seat->pointer->device, NULL, &pos, NULL); - meta_feedback_actor_set_position (META_FEEDBACK_ACTOR (drag_grab->feedback_actor), - pos.x, pos.y); - } - - meta_wayland_pointer_start_grab (seat->pointer, - (MetaWaylandPointerGrab*) drag_grab); - meta_wayland_data_source_set_seat (source, seat); -} - -void -meta_wayland_data_device_end_drag (MetaWaylandDataDevice *data_device) -{ - if (data_device->current_grab) - data_device_end_drag_grab (data_device->current_grab); -} - -static void -data_device_start_drag (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *source_resource, - struct wl_resource *origin_resource, - struct wl_resource *icon_resource, guint32 serial) -{ - MetaWaylandDataDevice *data_device = wl_resource_get_user_data (resource); - MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device); - MetaWaylandSurface *surface = NULL, *icon_surface = NULL; - MetaWaylandDataSource *drag_source = NULL; - MetaSelectionSource *selection_source; - - if (origin_resource) - surface = wl_resource_get_user_data (origin_resource); - - if (!surface) - return; - - if (seat->pointer->button_count == 0 || - seat->pointer->grab_serial != serial || - !seat->pointer->focus_surface || - seat->pointer->focus_surface != surface) - return; - - /* FIXME: Check that the data source type array isn't empty. */ - - if (data_device->current_grab || - seat->pointer->grab != &seat->pointer->default_grab) - return; - - if (icon_resource) - icon_surface = wl_resource_get_user_data (icon_resource); - if (source_resource) - drag_source = wl_resource_get_user_data (source_resource); - - if (icon_resource && - !meta_wayland_surface_assign_role (icon_surface, - META_TYPE_WAYLAND_SURFACE_ROLE_DND, - NULL)) - { - wl_resource_post_error (resource, WL_DATA_DEVICE_ERROR_ROLE, - "wl_surface@%d already has a different role", - wl_resource_get_id (icon_resource)); - return; - } - - selection_source = meta_selection_source_wayland_new (drag_source); - set_selection_source (data_device, META_SELECTION_DND, - selection_source); - g_object_unref (selection_source); - - meta_wayland_pointer_set_focus (seat->pointer, NULL); - meta_wayland_data_device_start_drag (data_device, client, - &drag_grab_interface, - surface, drag_source, icon_surface); - - if (meta_wayland_seat_has_keyboard (seat)) - meta_wayland_keyboard_start_grab (seat->keyboard, - &seat->data_device.current_grab->keyboard_grab); -} - -static void -selection_data_source_destroyed (gpointer data, GObject *object_was_here) -{ - MetaWaylandDataDevice *data_device = data; - - data_device->selection_data_source = NULL; - unset_selection_source (data_device, META_SELECTION_CLIPBOARD); -} - -static void -meta_wayland_drag_dest_focus_in (MetaWaylandDataDevice *data_device, - MetaWaylandSurface *surface, - MetaWaylandDataOffer *offer) -{ - MetaWaylandDragGrab *grab = data_device->current_grab; - MetaWaylandDataSource *source; - struct wl_display *display; - struct wl_client *client; - struct wl_resource *resource; - uint32_t source_actions; - wl_fixed_t sx, sy; - - if (!grab->drag_focus_data_device) - return; - - client = wl_resource_get_client (surface->resource); - display = wl_client_get_display (client); - - grab->drag_focus_listener.notify = destroy_drag_focus; - wl_resource_add_destroy_listener (grab->drag_focus_data_device, - &grab->drag_focus_listener); - - resource = meta_wayland_data_offer_get_resource (offer); - - if (wl_resource_get_version (resource) >= - WL_DATA_OFFER_SOURCE_ACTIONS_SINCE_VERSION) - { - source = meta_wayland_data_offer_get_source (offer); - meta_wayland_data_source_get_actions (source, &source_actions); - wl_data_offer_send_source_actions (resource, source_actions); - } - - meta_wayland_pointer_get_relative_coordinates (grab->generic.pointer, - surface, &sx, &sy); - wl_data_device_send_enter (grab->drag_focus_data_device, - wl_display_next_serial (display), - surface->resource, sx, sy, resource); -} - -static void -meta_wayland_drag_dest_focus_out (MetaWaylandDataDevice *data_device, - MetaWaylandSurface *surface) -{ - MetaWaylandDragGrab *grab = data_device->current_grab; - - if (!grab->drag_focus_data_device) - return; - - wl_data_device_send_leave (grab->drag_focus_data_device); - wl_list_remove (&grab->drag_focus_listener.link); - grab->drag_focus_data_device = NULL; -} - -static void -meta_wayland_drag_dest_motion (MetaWaylandDataDevice *data_device, - MetaWaylandSurface *surface, - const ClutterEvent *event) -{ - MetaWaylandDragGrab *grab = data_device->current_grab; - wl_fixed_t sx, sy; - - if (!grab->drag_focus_data_device) - return; - - meta_wayland_pointer_get_relative_coordinates (grab->generic.pointer, - grab->drag_focus, - &sx, &sy); - wl_data_device_send_motion (grab->drag_focus_data_device, - clutter_event_get_time (event), - sx, sy); -} - -static void -meta_wayland_drag_dest_drop (MetaWaylandDataDevice *data_device, - MetaWaylandSurface *surface) -{ - MetaWaylandDragGrab *grab = data_device->current_grab; - - if (!grab->drag_focus_data_device) - return; - - wl_data_device_send_drop (grab->drag_focus_data_device); -} - -static void -meta_wayland_drag_dest_update (MetaWaylandDataDevice *data_device, - MetaWaylandSurface *surface) -{ -} - -static const MetaWaylandDragDestFuncs meta_wayland_drag_dest_funcs = { - meta_wayland_drag_dest_focus_in, - meta_wayland_drag_dest_focus_out, - meta_wayland_drag_dest_motion, - meta_wayland_drag_dest_drop, - meta_wayland_drag_dest_update -}; - -const MetaWaylandDragDestFuncs * -meta_wayland_data_device_get_drag_dest_funcs (void) -{ - return &meta_wayland_drag_dest_funcs; -} - -static void -dnd_data_source_destroyed (gpointer data, - GObject *object_was_here) -{ - MetaWaylandDataDevice *data_device = data; - - data_device->dnd_data_source = NULL; - unset_selection_source (data_device, META_SELECTION_DND); -} - -void -meta_wayland_data_device_set_dnd_source (MetaWaylandDataDevice *data_device, - MetaWaylandDataSource *source) -{ - if (data_device->dnd_data_source == source) - return; - - if (data_device->dnd_data_source) - { - g_object_weak_unref (G_OBJECT (data_device->dnd_data_source), - dnd_data_source_destroyed, - data_device); - } - - data_device->dnd_data_source = source; - - if (source) - { - g_object_weak_ref (G_OBJECT (source), - dnd_data_source_destroyed, - data_device); - } -} - -void -meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device, - MetaWaylandDataSource *source, - guint32 serial) -{ - MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device); - MetaSelectionSource *selection_source; - - if (data_device->selection_data_source && - data_device->selection_serial - serial < UINT32_MAX / 2) - return; - - if (data_device->selection_data_source) - { - g_object_weak_unref (G_OBJECT (data_device->selection_data_source), - selection_data_source_destroyed, - data_device); - data_device->selection_data_source = NULL; - } - - data_device->selection_data_source = source; - data_device->selection_serial = serial; - - if (source) - { - meta_wayland_data_source_set_seat (source, seat); - g_object_weak_ref (G_OBJECT (source), - selection_data_source_destroyed, - data_device); - - selection_source = meta_selection_source_wayland_new (source); - } - else - { - selection_source = g_object_new (META_TYPE_SELECTION_SOURCE_MEMORY, NULL); - } - - set_selection_source (data_device, META_SELECTION_CLIPBOARD, - selection_source); - g_object_unref (selection_source); -} - -static void -data_device_set_selection (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *source_resource, - guint32 serial) -{ - MetaWaylandDataDevice *data_device = wl_resource_get_user_data (resource); - MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device); - MetaWaylandDataSource *source; - - if (source_resource) - source = wl_resource_get_user_data (source_resource); - else - source = NULL; - - if (source) - { - if (meta_wayland_data_source_get_actions (source, NULL)) - { - wl_resource_post_error(source_resource, - WL_DATA_SOURCE_ERROR_INVALID_SOURCE, - "cannot set drag-and-drop source as selection"); - return; - } - } - - if (wl_resource_get_client (resource) != - meta_wayland_keyboard_get_focus_client (seat->keyboard)) - { - if (source) - meta_wayland_data_source_cancel (source); - return; - } - - /* FIXME: Store serial and check against incoming serial here. */ - meta_wayland_data_device_set_selection (data_device, source, serial); -} - -static const struct wl_data_device_interface data_device_interface = { - data_device_start_drag, - data_device_set_selection, - default_destructor, -}; - -static void -create_data_source (struct wl_client *client, - struct wl_resource *resource, guint32 id) -{ - struct wl_resource *source_resource; - - source_resource = wl_resource_create (client, &wl_data_source_interface, - wl_resource_get_version (resource), id); - meta_wayland_data_source_new (source_resource); -} - -static void -owner_changed_cb (MetaSelection *selection, - MetaSelectionType selection_type, - MetaSelectionSource *new_owner, - MetaWaylandDataDevice *data_device) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaWaylandSeat *seat = compositor->seat; - struct wl_resource *data_device_resource; - struct wl_client *focus_client; - - focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard); - if (!focus_client) - return; - - if (selection_type == META_SELECTION_CLIPBOARD) - { - wl_resource_for_each (data_device_resource, &data_device->focus_resource_list) - { - struct wl_resource *offer = NULL; - - if (new_owner) - { - offer = create_and_send_clipboard_offer (data_device, - data_device_resource); - } - - wl_data_device_send_selection (data_device_resource, offer); - } - } -} - -static void -ensure_owners_changed_handler_connected (MetaWaylandDataDevice *data_device) -{ - if (data_device->selection_owner_signal_id != 0) - return; - - data_device->selection_owner_signal_id = - g_signal_connect (meta_display_get_selection (meta_get_display ()), - "owner-changed", - G_CALLBACK (owner_changed_cb), data_device); -} - -static void -get_data_device (struct wl_client *client, - struct wl_resource *manager_resource, - guint32 id, struct wl_resource *seat_resource) -{ - MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); - struct wl_resource *cr; - struct wl_resource *data_device_resource; - - cr = wl_resource_create (client, &wl_data_device_interface, wl_resource_get_version (manager_resource), id); - wl_resource_set_implementation (cr, &data_device_interface, &seat->data_device, unbind_resource); - - data_device_resource = - wl_resource_find_for_client (&seat->data_device.resource_list, client); - if (data_device_resource) - { - wl_list_remove (wl_resource_get_link (data_device_resource)); - wl_list_init (wl_resource_get_link (data_device_resource)); - } - - wl_list_insert (&seat->data_device.resource_list, wl_resource_get_link (cr)); - - ensure_owners_changed_handler_connected (&seat->data_device); -} - -static const struct wl_data_device_manager_interface manager_interface = { - create_data_source, - get_data_device -}; - -static void -bind_manager (struct wl_client *client, - void *data, guint32 version, guint32 id) -{ - struct wl_resource *resource; - resource = wl_resource_create (client, &wl_data_device_manager_interface, version, id); - wl_resource_set_implementation (resource, &manager_interface, NULL, NULL); -} - -void -meta_wayland_data_device_manager_init (MetaWaylandCompositor *compositor) -{ - if (wl_global_create (compositor->wayland_display, - &wl_data_device_manager_interface, - META_WL_DATA_DEVICE_MANAGER_VERSION, - NULL, bind_manager) == NULL) - g_error ("Could not create data_device"); -} - -void -meta_wayland_data_device_init (MetaWaylandDataDevice *data_device) -{ - wl_list_init (&data_device->resource_list); - wl_list_init (&data_device->focus_resource_list); -} - -static struct wl_resource * -create_and_send_clipboard_offer (MetaWaylandDataDevice *data_device, - struct wl_resource *target) -{ - MetaWaylandDataOffer *offer; - MetaDisplay *display = meta_get_display (); - struct wl_resource *resource; - GList *mimetypes, *l; - - mimetypes = meta_selection_get_mimetypes (meta_display_get_selection (display), - META_SELECTION_CLIPBOARD); - if (!mimetypes) - return NULL; - - offer = meta_wayland_data_offer_new (META_SELECTION_CLIPBOARD, NULL, target); - resource = meta_wayland_data_offer_get_resource (offer); - - wl_data_device_send_data_offer (target, resource); - - for (l = mimetypes; l; l = l->next) - wl_data_offer_send_offer (resource, l->data); - - g_list_free_full (mimetypes, g_free); - - return resource; -} - -void -meta_wayland_data_device_set_keyboard_focus (MetaWaylandDataDevice *data_device) -{ - MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device); - struct wl_client *focus_client; - struct wl_resource *data_device_resource; - - focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard); - - if (focus_client == data_device->focus_client) - return; - - data_device->focus_client = focus_client; - move_resources (&data_device->resource_list, - &data_device->focus_resource_list); - - if (!focus_client) - return; - - move_resources_for_client (&data_device->focus_resource_list, - &data_device->resource_list, - focus_client); - - wl_resource_for_each (data_device_resource, &data_device->focus_resource_list) - { - struct wl_resource *offer; - - offer = create_and_send_clipboard_offer (data_device, data_device_resource); - wl_data_device_send_selection (data_device_resource, offer); - } -} - -gboolean -meta_wayland_data_device_is_dnd_surface (MetaWaylandDataDevice *data_device, - MetaWaylandSurface *surface) -{ - return data_device->current_grab && - data_device->current_grab->drag_surface == surface; -} - -MetaWaylandDragGrab * -meta_wayland_data_device_get_current_grab (MetaWaylandDataDevice *data_device) -{ - return data_device->current_grab; -} - -void -meta_wayland_data_device_unset_dnd_selection (MetaWaylandDataDevice *data_device) -{ - unset_selection_source (data_device, META_SELECTION_DND); -} diff --git a/src/wayland/meta-wayland-data-device.h b/src/wayland/meta-wayland-data-device.h deleted file mode 100644 index 840893389..000000000 --- a/src/wayland/meta-wayland-data-device.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#ifndef META_WAYLAND_DATA_DEVICE_H -#define META_WAYLAND_DATA_DEVICE_H - -#include -#include - -#include "clutter/clutter.h" -#include "meta/meta-selection-source.h" -#include "wayland/meta-wayland-data-offer.h" -#include "wayland/meta-wayland-data-source.h" -#include "wayland/meta-wayland-types.h" - -typedef struct _MetaWaylandDragGrab MetaWaylandDragGrab; -typedef struct _MetaWaylandDataSourceFuncs MetaWaylandDataSourceFuncs; - -struct _MetaWaylandDataDevice -{ - uint32_t selection_serial; - MetaWaylandDataSource *selection_data_source; - MetaWaylandDataSource *dnd_data_source; - struct wl_list resource_list; - struct wl_list focus_resource_list; - MetaWaylandDragGrab *current_grab; - struct wl_client *focus_client; - - guint selection_owner_signal_id; - - MetaSelectionSource *owners[META_N_SELECTION_TYPES]; -}; - -void meta_wayland_data_device_manager_init (MetaWaylandCompositor *compositor); - -void meta_wayland_data_device_init (MetaWaylandDataDevice *data_device); - -void meta_wayland_data_device_set_keyboard_focus (MetaWaylandDataDevice *data_device); - -gboolean meta_wayland_data_device_is_dnd_surface (MetaWaylandDataDevice *data_device, - MetaWaylandSurface *surface); - -MetaWaylandDragGrab * - meta_wayland_data_device_get_current_grab (MetaWaylandDataDevice *data_device); - -void meta_wayland_data_device_set_dnd_source (MetaWaylandDataDevice *data_device, - MetaWaylandDataSource *source); -void meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device, - MetaWaylandDataSource *source, - guint32 serial); -void meta_wayland_data_device_unset_dnd_selection (MetaWaylandDataDevice *data_device); - -const MetaWaylandDragDestFuncs * - meta_wayland_data_device_get_drag_dest_funcs (void); - -void meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data_device, - struct wl_client *client, - const MetaWaylandPointerGrabInterface *funcs, - MetaWaylandSurface *surface, - MetaWaylandDataSource *source, - MetaWaylandSurface *icon_surface); - -void meta_wayland_data_device_end_drag (MetaWaylandDataDevice *data_device); - -void meta_wayland_drag_grab_set_focus (MetaWaylandDragGrab *drag_grab, - MetaWaylandSurface *surface); -MetaWaylandSurface * - meta_wayland_drag_grab_get_focus (MetaWaylandDragGrab *drag_grab); -void meta_wayland_drag_grab_update_feedback_actor (MetaWaylandDragGrab *drag_grab, - ClutterEvent *event); - -#endif /* META_WAYLAND_DATA_DEVICE_H */ diff --git a/src/wayland/meta-wayland-data-offer-primary-legacy.c b/src/wayland/meta-wayland-data-offer-primary-legacy.c deleted file mode 100644 index 0d5a98743..000000000 --- a/src/wayland/meta-wayland-data-offer-primary-legacy.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright © 2011 Kristian Høgsberg - * 2020 Red Hat Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#include "config.h" - -#include "meta-wayland-data-offer-primary-legacy.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "core/display-private.h" -#include "gtk-primary-selection-server-protocol.h" -#include "wayland/meta-wayland-data-offer.h" - -static void -transfer_cb (MetaSelection *selection, - GAsyncResult *res, - GOutputStream *stream) -{ - GError *error = NULL; - - if (!meta_selection_transfer_finish (selection, res, &error)) - { - g_warning ("Could not fetch selection data: %s", error->message); - g_error_free (error); - } - - g_output_stream_close (stream, NULL, NULL); - g_object_unref (stream); -} - -static void -primary_offer_receive (struct wl_client *client, - struct wl_resource *resource, - const char *mime_type, - int32_t fd) -{ - MetaDisplay *display = meta_get_display (); - GOutputStream *stream; - GList *mime_types; - gboolean found; - - mime_types = meta_selection_get_mimetypes (meta_display_get_selection (display), - META_SELECTION_PRIMARY); - found = g_list_find_custom (mime_types, mime_type, (GCompareFunc) g_strcmp0) != NULL; - g_list_free_full (mime_types, g_free); - - if (!found) - { - close (fd); - return; - } - - stream = g_unix_output_stream_new (fd, TRUE); - meta_selection_transfer_async (meta_display_get_selection (display), - META_SELECTION_PRIMARY, - mime_type, - -1, - stream, - NULL, - (GAsyncReadyCallback) transfer_cb, - stream); -} - -static void -primary_offer_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static const struct gtk_primary_selection_offer_interface primary_offer_interface = { - primary_offer_receive, - primary_offer_destroy, -}; - -static void -destroy_primary_offer (struct wl_resource *resource) -{ - MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource); - - if (offer->source) - { - if (offer == meta_wayland_data_source_get_current_offer (offer->source)) - { - meta_wayland_data_source_cancel (offer->source); - meta_wayland_data_source_set_current_offer (offer->source, NULL); - } - - g_object_remove_weak_pointer (G_OBJECT (offer->source), - (gpointer *)&offer->source); - offer->source = NULL; - } - - meta_display_sync_wayland_input_focus (meta_get_display ()); - g_free (offer); -} - -MetaWaylandDataOffer * -meta_wayland_data_offer_primary_legacy_new (struct wl_resource *target) -{ - MetaWaylandDataOffer *offer; - - offer = g_new0 (MetaWaylandDataOffer, 1); - offer->selection_type = META_SELECTION_PRIMARY; - offer->resource = wl_resource_create (wl_resource_get_client (target), - >k_primary_selection_offer_interface, - wl_resource_get_version (target), 0); - wl_resource_set_implementation (offer->resource, - &primary_offer_interface, - offer, - destroy_primary_offer); - return offer; -} diff --git a/src/wayland/meta-wayland-data-offer-primary-legacy.h b/src/wayland/meta-wayland-data-offer-primary-legacy.h deleted file mode 100644 index 96a32c34e..000000000 --- a/src/wayland/meta-wayland-data-offer-primary-legacy.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright © 2011 Kristian Høgsberg - * 2020 Red Hat Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#ifndef META_WAYLAND_DATA_OFFER_PRIMARY_LEGACY_H -#define META_WAYLAND_DATA_OFFER_PRIMARY_LEGACY_H - -#include "meta-wayland-data-offer.h" - -MetaWaylandDataOffer * meta_wayland_data_offer_primary_legacy_new (struct wl_resource *target); - -#endif /* META_WAYLAND_DATA_OFFER_PRIMARY_LEGACY_H */ diff --git a/src/wayland/meta-wayland-data-offer-primary.c b/src/wayland/meta-wayland-data-offer-primary.c deleted file mode 100644 index a5c8a6d5a..000000000 --- a/src/wayland/meta-wayland-data-offer-primary.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright © 2011 Kristian Høgsberg - * 2020 Red Hat Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#include "config.h" - -#include "meta-wayland-data-offer-primary.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "core/display-private.h" -#include "primary-selection-unstable-v1-server-protocol.h" -#include "wayland/meta-wayland-data-offer.h" - -static void -transfer_cb (MetaSelection *selection, - GAsyncResult *res, - GOutputStream *stream) -{ - GError *error = NULL; - - if (!meta_selection_transfer_finish (selection, res, &error)) - { - g_warning ("Could not fetch selection data: %s", error->message); - g_error_free (error); - } - - g_output_stream_close (stream, NULL, NULL); - g_object_unref (stream); -} - -static void -primary_offer_receive (struct wl_client *client, - struct wl_resource *resource, - const char *mime_type, - int32_t fd) -{ - MetaDisplay *display = meta_get_display (); - GOutputStream *stream; - GList *mime_types; - gboolean found; - - mime_types = meta_selection_get_mimetypes (meta_display_get_selection (display), - META_SELECTION_PRIMARY); - found = g_list_find_custom (mime_types, mime_type, (GCompareFunc) g_strcmp0) != NULL; - g_list_free_full (mime_types, g_free); - - if (!found) - { - close (fd); - return; - } - - stream = g_unix_output_stream_new (fd, TRUE); - meta_selection_transfer_async (meta_display_get_selection (display), - META_SELECTION_PRIMARY, - mime_type, - -1, - stream, - NULL, - (GAsyncReadyCallback) transfer_cb, - stream); -} - -static void -primary_offer_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static const struct zwp_primary_selection_offer_v1_interface primary_offer_interface = { - primary_offer_receive, - primary_offer_destroy, -}; - -static void -destroy_primary_offer (struct wl_resource *resource) -{ - MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource); - - if (offer->source) - { - if (offer == meta_wayland_data_source_get_current_offer (offer->source)) - { - meta_wayland_data_source_cancel (offer->source); - meta_wayland_data_source_set_current_offer (offer->source, NULL); - } - - g_object_remove_weak_pointer (G_OBJECT (offer->source), - (gpointer *)&offer->source); - offer->source = NULL; - } - - meta_display_sync_wayland_input_focus (meta_get_display ()); - g_free (offer); -} - -MetaWaylandDataOffer * -meta_wayland_data_offer_primary_new (struct wl_resource *target) -{ - MetaWaylandDataOffer *offer; - - offer = g_new0 (MetaWaylandDataOffer, 1); - offer->selection_type = META_SELECTION_PRIMARY; - offer->resource = wl_resource_create (wl_resource_get_client (target), - &zwp_primary_selection_offer_v1_interface, - wl_resource_get_version (target), 0); - wl_resource_set_implementation (offer->resource, - &primary_offer_interface, - offer, - destroy_primary_offer); - return offer; -} diff --git a/src/wayland/meta-wayland-data-offer-primary.h b/src/wayland/meta-wayland-data-offer-primary.h deleted file mode 100644 index cf59fb5c7..000000000 --- a/src/wayland/meta-wayland-data-offer-primary.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright © 2011 Kristian Høgsberg - * 2020 Red Hat Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#ifndef META_WAYLAND_DATA_OFFER_PRIMARY_H -#define META_WAYLAND_DATA_OFFER_PRIMARY_H - -#include "meta-wayland-data-offer.h" - -MetaWaylandDataOffer * meta_wayland_data_offer_primary_new (struct wl_resource *target); - -#endif /* META_WAYLAND_DATA_OFFER_PRIMARY_H */ diff --git a/src/wayland/meta-wayland-data-offer.c b/src/wayland/meta-wayland-data-offer.c deleted file mode 100644 index c686aee6f..000000000 --- a/src/wayland/meta-wayland-data-offer.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright © 2011 Kristian Høgsberg - * 2020 Red Hat Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "meta/meta-selection.h" -#include "wayland/meta-wayland-data-device.h" -#include "wayland/meta-wayland-private.h" - -#include "meta-wayland-data-offer.h" - -#define ALL_ACTIONS (WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | \ - WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE | \ - WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK) - -static void -data_offer_accept (struct wl_client *client, - struct wl_resource *resource, - guint32 serial, - const char *mime_type) -{ - MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource); - - /* FIXME: Check that client is currently focused by the input - * device that is currently dragging this data source. Should - * this be a wl_data_device request? */ - - if (offer->source) - { - meta_wayland_data_source_target (offer->source, mime_type); - meta_wayland_data_source_set_has_target (offer->source, - mime_type != NULL); - } - - offer->accepted = mime_type != NULL; -} - -static void -transfer_cb (MetaSelection *selection, - GAsyncResult *res, - GOutputStream *stream) -{ - GError *error = NULL; - - if (!meta_selection_transfer_finish (selection, res, &error)) - { - g_warning ("Could not fetch selection data: %s", error->message); - g_error_free (error); - } - - g_output_stream_close (stream, NULL, NULL); - g_object_unref (stream); -} - -static void -data_offer_receive (struct wl_client *client, struct wl_resource *resource, - const char *mime_type, int32_t fd) -{ - MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource); - MetaDisplay *display = meta_get_display (); - MetaSelectionType selection_type; - GList *mime_types; - gboolean found; - - selection_type = offer->selection_type; - mime_types = meta_selection_get_mimetypes (meta_display_get_selection (display), - selection_type); - found = g_list_find_custom (mime_types, mime_type, (GCompareFunc) g_strcmp0) != NULL; - g_list_free_full (mime_types, g_free); - - if (found) - { - GOutputStream *stream; - - stream = g_unix_output_stream_new (fd, TRUE); - meta_selection_transfer_async (meta_display_get_selection (display), - selection_type, - mime_type, - -1, - stream, - NULL, - (GAsyncReadyCallback) transfer_cb, - stream); - } - else - { - close (fd); - } -} - -static void -data_offer_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -data_offer_finish (struct wl_client *client, - struct wl_resource *resource) -{ - MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource); - enum wl_data_device_manager_dnd_action current_action; - - if (!offer->source || - offer != meta_wayland_data_source_get_current_offer (offer->source)) - return; - - if (!offer->accepted || !offer->action_sent) - { - wl_resource_post_error (offer->resource, - WL_DATA_OFFER_ERROR_INVALID_FINISH, - "premature finish request"); - return; - } - - current_action = meta_wayland_data_source_get_current_action (offer->source); - - if (current_action == WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE || - current_action == WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK) - { - wl_resource_post_error (offer->resource, - WL_DATA_OFFER_ERROR_INVALID_OFFER, - "offer finished with an invalid action"); - return; - } - - meta_wayland_data_source_notify_finish (offer->source); -} - -static void -data_offer_set_actions (struct wl_client *client, - struct wl_resource *resource, - uint32_t dnd_actions, - uint32_t preferred_action) -{ - MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource); - - if (dnd_actions & ~(ALL_ACTIONS)) - { - wl_resource_post_error (offer->resource, - WL_DATA_OFFER_ERROR_INVALID_ACTION_MASK, - "invalid actions mask %x", dnd_actions); - return; - } - - if (preferred_action && - (!(preferred_action & dnd_actions) || - __builtin_popcount (preferred_action) > 1)) - { - wl_resource_post_error (offer->resource, - WL_DATA_OFFER_ERROR_INVALID_ACTION, - "invalid action %x", preferred_action); - return; - } - - offer->dnd_actions = dnd_actions; - offer->preferred_dnd_action = preferred_action; - - meta_wayland_data_offer_update_action (offer); -} - -static const struct wl_data_offer_interface data_offer_interface = { - data_offer_accept, - data_offer_receive, - data_offer_destroy, - data_offer_finish, - data_offer_set_actions, -}; - -static void -destroy_data_offer (struct wl_resource *resource) -{ - MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource); - MetaWaylandSeat *seat; - - if (offer->source) - { - seat = meta_wayland_data_source_get_seat (offer->source); - - if (offer == meta_wayland_data_source_get_current_offer (offer->source)) - { - if (seat->data_device.dnd_data_source == offer->source) - { - if (wl_resource_get_version (offer->resource) < - WL_DATA_OFFER_ACTION_SINCE_VERSION) - meta_wayland_data_source_notify_finish (offer->source); - else if (meta_wayland_data_source_get_drop_performed (offer->source)) - meta_wayland_data_source_cancel (offer->source); - } - else - { - meta_wayland_data_source_set_current_offer (offer->source, NULL); - meta_wayland_data_source_set_has_target (offer->source, FALSE); - } - } - - g_object_remove_weak_pointer (G_OBJECT (offer->source), - (gpointer *)&offer->source); - offer->source = NULL; - } - - meta_display_sync_wayland_input_focus (meta_get_display ()); - g_free (offer); -} - -MetaWaylandDataOffer * -meta_wayland_data_offer_new (MetaSelectionType selection_type, - MetaWaylandDataSource *source, - struct wl_resource *target) -{ - MetaWaylandDataOffer *offer; - - offer = g_new0 (MetaWaylandDataOffer, 1); - offer->selection_type = selection_type; - offer->resource = wl_resource_create (wl_resource_get_client (target), - &wl_data_offer_interface, - wl_resource_get_version (target), 0); - wl_resource_set_implementation (offer->resource, - &data_offer_interface, - offer, - destroy_data_offer); - if (source) - { - offer->source = source; - g_object_add_weak_pointer (G_OBJECT (source), (gpointer *)&offer->source); - } - - return offer; -} - -static enum wl_data_device_manager_dnd_action -data_offer_choose_action (MetaWaylandDataOffer *offer) -{ - MetaWaylandDataSource *source = offer->source; - uint32_t actions, user_action, available_actions; - - if (wl_resource_get_version (offer->resource) < - WL_DATA_OFFER_ACTION_SINCE_VERSION) - return WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY; - - meta_wayland_data_source_get_actions (source, &actions); - user_action = meta_wayland_data_source_get_user_action (source); - - available_actions = actions & offer->dnd_actions; - - if (!available_actions) - return WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE; - - /* If the user is forcing an action, go for it */ - if ((user_action & available_actions) != 0) - return user_action; - - /* If the dest side has a preferred DnD action, use it */ - if ((offer->preferred_dnd_action & available_actions) != 0) - return offer->preferred_dnd_action; - - /* Use the first found action, in bit order */ - return 1 << (ffs (available_actions) - 1); -} - -void -meta_wayland_data_offer_update_action (MetaWaylandDataOffer *offer) -{ - enum wl_data_device_manager_dnd_action current_action, action; - MetaWaylandDataSource *source; - - if (!offer->source) - return; - - source = offer->source; - current_action = meta_wayland_data_source_get_current_action (source); - action = data_offer_choose_action (offer); - - if (current_action == action) - return; - - meta_wayland_data_source_set_current_action (source, action); - - if (!meta_wayland_data_source_get_in_ask (source) && - wl_resource_get_version (offer->resource) >= - WL_DATA_OFFER_ACTION_SINCE_VERSION) - { - wl_data_offer_send_action (offer->resource, action); - offer->action_sent = TRUE; - } -} - -struct wl_resource * -meta_wayland_data_offer_get_resource (MetaWaylandDataOffer *offer) -{ - return offer->resource; -} - -MetaWaylandDataSource * -meta_wayland_data_offer_get_source (MetaWaylandDataOffer *offer) -{ - return offer->source; -} diff --git a/src/wayland/meta-wayland-data-offer.h b/src/wayland/meta-wayland-data-offer.h deleted file mode 100644 index 811aa0935..000000000 --- a/src/wayland/meta-wayland-data-offer.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright © 2011 Kristian Høgsberg - * 2020 Red Hat Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#ifndef META_WAYLAND_DATA_OFFER_H -#define META_WAYLAND_DATA_OFFER_H - -#include "meta/meta-selection.h" -#include "wayland/meta-wayland-data-source.h" - -struct _MetaWaylandDataOffer -{ - struct wl_resource *resource; - MetaWaylandDataSource *source; - struct wl_listener source_destroy_listener; - gboolean accepted; - gboolean action_sent; - uint32_t dnd_actions; - enum wl_data_device_manager_dnd_action preferred_dnd_action; - MetaSelectionType selection_type; -}; - -MetaWaylandDataOffer * meta_wayland_data_offer_new (MetaSelectionType selection_type, - MetaWaylandDataSource *source, - struct wl_resource *resource); - -void meta_wayland_data_offer_update_action (MetaWaylandDataOffer *offer); - -struct wl_resource * meta_wayland_data_offer_get_resource (MetaWaylandDataOffer *offer); -MetaWaylandDataSource * meta_wayland_data_offer_get_source (MetaWaylandDataOffer *offer); - -#endif /* META_WAYLAND_DATA_OFFER_H */ diff --git a/src/wayland/meta-wayland-data-source-primary-legacy.c b/src/wayland/meta-wayland-data-source-primary-legacy.c deleted file mode 100644 index a7a1788ae..000000000 --- a/src/wayland/meta-wayland-data-source-primary-legacy.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright © 2011 Kristian Høgsberg - * 2020 Red Hat Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#include "config.h" - -#include - -#include "gtk-primary-selection-server-protocol.h" -#include "wayland/meta-wayland-data-source-primary-legacy.h" - -typedef struct _MetaWaylandDataSourcePrimaryLegacy -{ - MetaWaylandDataSource parent; -} MetaWaylandDataSourcePrimaryLegacy; - -G_DEFINE_TYPE (MetaWaylandDataSourcePrimaryLegacy, meta_wayland_data_source_primary_legacy, - META_TYPE_WAYLAND_DATA_SOURCE); - -static void -primary_source_offer (struct wl_client *client, - struct wl_resource *resource, - const char *type) -{ - MetaWaylandDataSource *source = wl_resource_get_user_data (resource); - - if (!meta_wayland_data_source_add_mime_type (source, type)) - wl_resource_post_no_memory (resource); -} - -static void -primary_source_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static struct gtk_primary_selection_source_interface primary_source_interface = { - primary_source_offer, - primary_source_destroy, -}; - -static void -destroy_primary_source (struct wl_resource *resource) -{ - MetaWaylandDataSource *source = wl_resource_get_user_data (resource); - - meta_wayland_data_source_set_resource (source, NULL); - g_object_unref (source); -} - -static void -meta_wayland_data_source_primary_legacy_send (MetaWaylandDataSource *source, - const gchar *mime_type, - gint fd) -{ - struct wl_resource *resource = meta_wayland_data_source_get_resource (source); - - gtk_primary_selection_source_send_send (resource, mime_type, fd); - close (fd); -} - -static void -meta_wayland_data_source_primary_legacy_cancel (MetaWaylandDataSource *source) -{ - struct wl_resource *resource = meta_wayland_data_source_get_resource (source); - - if (resource) - gtk_primary_selection_source_send_cancelled (resource); -} - -static void -meta_wayland_data_source_primary_legacy_init (MetaWaylandDataSourcePrimaryLegacy *source_primary) -{ -} - -static void -meta_wayland_data_source_primary_legacy_class_init (MetaWaylandDataSourcePrimaryLegacyClass *klass) -{ - MetaWaylandDataSourceClass *data_source_class = - META_WAYLAND_DATA_SOURCE_CLASS (klass); - - data_source_class->send = meta_wayland_data_source_primary_legacy_send; - data_source_class->cancel = meta_wayland_data_source_primary_legacy_cancel; -} - -MetaWaylandDataSource * -meta_wayland_data_source_primary_legacy_new (struct wl_resource *resource) -{ - MetaWaylandDataSource *source_primary = - g_object_new (META_TYPE_WAYLAND_DATA_SOURCE_PRIMARY_LEGACY, NULL); - - meta_wayland_data_source_set_resource (source_primary, resource); - wl_resource_set_implementation (resource, &primary_source_interface, - source_primary, destroy_primary_source); - - return source_primary; -} diff --git a/src/wayland/meta-wayland-data-source-primary-legacy.h b/src/wayland/meta-wayland-data-source-primary-legacy.h deleted file mode 100644 index 2904807c8..000000000 --- a/src/wayland/meta-wayland-data-source-primary-legacy.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright © 2011 Kristian Høgsberg - * 2020 Red Hat Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#ifndef META_WAYLAND_DATA_SOURCE_PRIMARY_LEGACY_H -#define META_WAYLAND_DATA_SOURCE_PRIMARY_LEGACY_H - -#include "meta-wayland-data-source.h" - -#define META_TYPE_WAYLAND_DATA_SOURCE_PRIMARY_LEGACY (meta_wayland_data_source_primary_legacy_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandDataSourcePrimaryLegacy, - meta_wayland_data_source_primary_legacy, - META, WAYLAND_DATA_SOURCE_PRIMARY_LEGACY, - MetaWaylandDataSource); - -MetaWaylandDataSource * meta_wayland_data_source_primary_legacy_new (struct wl_resource *resource); - -#endif /* META_WAYLAND_DATA_SOURCE_PRIMARY_LEGACY_H */ diff --git a/src/wayland/meta-wayland-data-source-primary.c b/src/wayland/meta-wayland-data-source-primary.c deleted file mode 100644 index 0229c840a..000000000 --- a/src/wayland/meta-wayland-data-source-primary.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright © 2011 Kristian Høgsberg - * 2020 Red Hat Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#include "config.h" - -#include - -#include "primary-selection-unstable-v1-server-protocol.h" -#include "wayland/meta-wayland-data-source-primary.h" - -typedef struct _MetaWaylandDataSourcePrimary -{ - MetaWaylandDataSource parent; -} MetaWaylandDataSourcePrimary; - -G_DEFINE_TYPE (MetaWaylandDataSourcePrimary, meta_wayland_data_source_primary, - META_TYPE_WAYLAND_DATA_SOURCE); - -static void -primary_source_offer (struct wl_client *client, - struct wl_resource *resource, - const char *type) -{ - MetaWaylandDataSource *source = wl_resource_get_user_data (resource); - - if (!meta_wayland_data_source_add_mime_type (source, type)) - wl_resource_post_no_memory (resource); -} - -static void -primary_source_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static struct zwp_primary_selection_source_v1_interface primary_source_interface = { - primary_source_offer, - primary_source_destroy, -}; - -static void -destroy_primary_source (struct wl_resource *resource) -{ - MetaWaylandDataSource *source = wl_resource_get_user_data (resource); - - meta_wayland_data_source_set_resource (source, NULL); - g_object_unref (source); -} - -static void -meta_wayland_data_source_primary_send (MetaWaylandDataSource *source, - const gchar *mime_type, - gint fd) -{ - struct wl_resource *resource = meta_wayland_data_source_get_resource (source); - - zwp_primary_selection_source_v1_send_send (resource, mime_type, fd); - close (fd); -} - -static void -meta_wayland_data_source_primary_cancel (MetaWaylandDataSource *source) -{ - struct wl_resource *resource = meta_wayland_data_source_get_resource (source); - - if (resource) - zwp_primary_selection_source_v1_send_cancelled (resource); -} - -static void -meta_wayland_data_source_primary_init (MetaWaylandDataSourcePrimary *source_primary) -{ -} - -static void -meta_wayland_data_source_primary_class_init (MetaWaylandDataSourcePrimaryClass *klass) -{ - MetaWaylandDataSourceClass *data_source_class = - META_WAYLAND_DATA_SOURCE_CLASS (klass); - - data_source_class->send = meta_wayland_data_source_primary_send; - data_source_class->cancel = meta_wayland_data_source_primary_cancel; -} - -MetaWaylandDataSource * -meta_wayland_data_source_primary_new (struct wl_resource *resource) -{ - MetaWaylandDataSource *source_primary = - g_object_new (META_TYPE_WAYLAND_DATA_SOURCE_PRIMARY, NULL); - - meta_wayland_data_source_set_resource (source_primary, resource); - wl_resource_set_implementation (resource, &primary_source_interface, - source_primary, destroy_primary_source); - - return source_primary; -} diff --git a/src/wayland/meta-wayland-data-source-primary.h b/src/wayland/meta-wayland-data-source-primary.h deleted file mode 100644 index 78ab55c19..000000000 --- a/src/wayland/meta-wayland-data-source-primary.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright © 2011 Kristian Høgsberg - * 2020 Red Hat Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#ifndef META_WAYLAND_DATA_SOURCE_PRIMARY_H -#define META_WAYLAND_DATA_SOURCE_PRIMARY_H - -#include "meta-wayland-data-source.h" - -#define META_TYPE_WAYLAND_DATA_SOURCE_PRIMARY (meta_wayland_data_source_primary_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandDataSourcePrimary, - meta_wayland_data_source_primary, - META, WAYLAND_DATA_SOURCE_PRIMARY, - MetaWaylandDataSource); - -MetaWaylandDataSource * meta_wayland_data_source_primary_new (struct wl_resource *resource); - -#endif /* META_WAYLAND_DATA_SOURCE_PRIMARY_H */ diff --git a/src/wayland/meta-wayland-data-source.c b/src/wayland/meta-wayland-data-source.c deleted file mode 100644 index 93aa3fdc8..000000000 --- a/src/wayland/meta-wayland-data-source.c +++ /dev/null @@ -1,523 +0,0 @@ -/* - * Copyright © 2011 Kristian Høgsberg - * 2020 Red Hat Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#include "config.h" - -#include - -#include "wayland/meta-wayland-data-source.h" -#include "wayland/meta-wayland-private.h" - -#define ALL_ACTIONS (WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | \ - WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE | \ - WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK) - -typedef struct _MetaWaylandDataSourcePrivate -{ - struct wl_resource *resource; - MetaWaylandDataOffer *offer; - struct wl_array mime_types; - gboolean has_target; - uint32_t dnd_actions; - enum wl_data_device_manager_dnd_action user_dnd_action; - enum wl_data_device_manager_dnd_action current_dnd_action; - MetaWaylandSeat *seat; - guint actions_set : 1; - guint in_ask : 1; - guint drop_performed : 1; -} MetaWaylandDataSourcePrivate; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandDataSource, meta_wayland_data_source, - G_TYPE_OBJECT); - -static void -meta_wayland_data_source_real_send (MetaWaylandDataSource *source, - const gchar *mime_type, - gint fd) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - wl_data_source_send_send (priv->resource, mime_type, fd); - close (fd); -} - -static void -meta_wayland_data_source_real_target (MetaWaylandDataSource *source, - const gchar *mime_type) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - wl_data_source_send_target (priv->resource, mime_type); -} - -static void -meta_wayland_data_source_real_cancel (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - if (!priv->resource) - return; - - wl_data_source_send_cancelled (priv->resource); -} - -static void -meta_wayland_data_source_real_action (MetaWaylandDataSource *source, - enum wl_data_device_manager_dnd_action action) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - if (wl_resource_get_version (priv->resource) >= - WL_DATA_SOURCE_ACTION_SINCE_VERSION) - wl_data_source_send_action (priv->resource, action); -} - -static void -meta_wayland_data_source_real_drop_performed (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - if (wl_resource_get_version (priv->resource) >= - WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION) - { - priv->drop_performed = TRUE; - wl_data_source_send_dnd_drop_performed (priv->resource); - } -} - -static void -meta_wayland_data_source_real_drag_finished (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - enum wl_data_device_manager_dnd_action action; - - if (meta_wayland_data_source_get_in_ask (source)) - { - action = meta_wayland_data_source_get_current_action (source); - meta_wayland_data_source_real_action (source, action); - } - - if (wl_resource_get_version (priv->resource) >= - WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION) - wl_data_source_send_dnd_finished (priv->resource); -} - -static void -meta_wayland_data_source_finalize (GObject *object) -{ - MetaWaylandDataSource *source = META_WAYLAND_DATA_SOURCE (object); - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - char **pos; - - wl_array_for_each (pos, &priv->mime_types) - g_free (*pos); - wl_array_release (&priv->mime_types); - - G_OBJECT_CLASS (meta_wayland_data_source_parent_class)->finalize (object); -} - -static void -meta_wayland_data_source_init (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - wl_array_init (&priv->mime_types); - priv->current_dnd_action = -1; - priv->drop_performed = FALSE; -} - -static void -meta_wayland_data_source_class_init (MetaWaylandDataSourceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_wayland_data_source_finalize; - - klass->send = meta_wayland_data_source_real_send; - klass->target = meta_wayland_data_source_real_target; - klass->cancel = meta_wayland_data_source_real_cancel; - klass->action = meta_wayland_data_source_real_action; - klass->drop_performed = meta_wayland_data_source_real_drop_performed; - klass->drag_finished = meta_wayland_data_source_real_drag_finished; -} - - -static void -data_source_offer (struct wl_client *client, - struct wl_resource *resource, const char *type) -{ - MetaWaylandDataSource *source = wl_resource_get_user_data (resource); - - if (!meta_wayland_data_source_add_mime_type (source, type)) - wl_resource_post_no_memory (resource); -} - -static void -data_source_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -data_source_set_actions (struct wl_client *client, - struct wl_resource *resource, - uint32_t dnd_actions) -{ - MetaWaylandDataSource *source = wl_resource_get_user_data (resource); - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - if (priv->actions_set) - { - wl_resource_post_error (priv->resource, - WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK, - "cannot set actions more than once"); - return; - } - - if (dnd_actions & ~(ALL_ACTIONS)) - { - wl_resource_post_error (priv->resource, - WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK, - "invalid actions mask %x", dnd_actions); - return; - } - - if (meta_wayland_data_source_get_seat (source)) - { - wl_resource_post_error (priv->resource, - WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK, - "invalid action change after " - "wl_data_device.start_drag"); - return; - } - - meta_wayland_data_source_set_actions (source, dnd_actions); -} - -static struct wl_data_source_interface data_source_interface = { - data_source_offer, - data_source_destroy, - data_source_set_actions -}; - -static void -destroy_data_source (struct wl_resource *resource) -{ - MetaWaylandDataSource *source = wl_resource_get_user_data (resource); - - meta_wayland_data_source_set_resource (source, NULL); - g_object_unref (source); -} - -MetaWaylandDataSource * -meta_wayland_data_source_new (struct wl_resource *resource) -{ - MetaWaylandDataSource *source = - g_object_new (META_TYPE_WAYLAND_DATA_SOURCE, NULL); - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - meta_wayland_data_source_set_resource (source, resource); - wl_resource_set_implementation (resource, &data_source_interface, - source, destroy_data_source); - - if (wl_resource_get_version (resource) < WL_DATA_SOURCE_ACTION_SINCE_VERSION) - { - priv->dnd_actions = priv->user_dnd_action = - WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY; - } - - return source; -} - -struct wl_resource * -meta_wayland_data_source_get_resource (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - return priv->resource; -} - -void -meta_wayland_data_source_set_resource (MetaWaylandDataSource *source, - struct wl_resource *resource) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - priv->resource = resource; -} - -gboolean -meta_wayland_data_source_get_in_ask (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - return priv->in_ask; -} - -void -meta_wayland_data_source_update_in_ask (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - priv->in_ask = - priv->current_dnd_action == WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK; -} - -void -meta_wayland_data_source_target (MetaWaylandDataSource *source, - const char *mime_type) -{ - if (META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->target) - META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->target (source, mime_type); -} - -void -meta_wayland_data_source_send (MetaWaylandDataSource *source, - const char *mime_type, - int fd) -{ - META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->send (source, mime_type, fd); -} - -gboolean -meta_wayland_data_source_has_target (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - return priv->has_target; -} - -void -meta_wayland_data_source_set_seat (MetaWaylandDataSource *source, - MetaWaylandSeat *seat) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - priv->seat = seat; -} - -MetaWaylandSeat * -meta_wayland_data_source_get_seat (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - return priv->seat; -} - -void -meta_wayland_data_source_set_has_target (MetaWaylandDataSource *source, - gboolean has_target) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - priv->has_target = has_target; -} - -struct wl_array * -meta_wayland_data_source_get_mime_types (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private ((MetaWaylandDataSource *)source); - - return &priv->mime_types; -} - -void -meta_wayland_data_source_cancel (MetaWaylandDataSource *source) -{ - META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->cancel (source); -} - -gboolean -meta_wayland_data_source_get_actions (MetaWaylandDataSource *source, - uint32_t *dnd_actions) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - if (dnd_actions) - *dnd_actions = priv->dnd_actions; - - return priv->actions_set; -} - -enum wl_data_device_manager_dnd_action -meta_wayland_data_source_get_user_action (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - if (!priv->seat) - return WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE; - - return priv->user_dnd_action; -} - -enum wl_data_device_manager_dnd_action -meta_wayland_data_source_get_current_action (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - return priv->current_dnd_action; -} - -void -meta_wayland_data_source_set_current_offer (MetaWaylandDataSource *source, - MetaWaylandDataOffer *offer) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - priv->offer = offer; -} - -MetaWaylandDataOffer * -meta_wayland_data_source_get_current_offer (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - return priv->offer; -} - -void -meta_wayland_data_source_set_current_action (MetaWaylandDataSource *source, - enum wl_data_device_manager_dnd_action action) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - if (priv->current_dnd_action == action) - return; - - priv->current_dnd_action = action; - - if (!meta_wayland_data_source_get_in_ask (source)) - META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->action (source, action); -} - -void -meta_wayland_data_source_set_actions (MetaWaylandDataSource *source, - uint32_t dnd_actions) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - priv->dnd_actions = dnd_actions; - priv->actions_set = TRUE; -} - -void -meta_wayland_data_source_set_user_action (MetaWaylandDataSource *source, - uint32_t action) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - MetaWaylandDataOffer *offer; - - if (priv->user_dnd_action == action) - return; - - priv->user_dnd_action = action; - offer = meta_wayland_data_source_get_current_offer (source); - - if (offer) - meta_wayland_data_offer_update_action (offer); -} - -gboolean -meta_wayland_data_source_get_drop_performed (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - - return priv->drop_performed; -} - -void -meta_wayland_data_source_notify_drop_performed (MetaWaylandDataSource *source) -{ - META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->drop_performed (source); -} - -void -meta_wayland_data_source_notify_finish (MetaWaylandDataSource *source) -{ - META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->drag_finished (source); -} - -gboolean -meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source, - const char *mime_type) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - char **pos; - - pos = wl_array_add (&priv->mime_types, sizeof (*pos)); - - if (pos) - { - *pos = g_strdup (mime_type); - return *pos != NULL; - } - - return FALSE; -} - -gboolean -meta_wayland_data_source_has_mime_type (MetaWaylandDataSource *source, - const char *mime_type) -{ - MetaWaylandDataSourcePrivate *priv = - meta_wayland_data_source_get_instance_private (source); - char **p; - - wl_array_for_each (p, &priv->mime_types) - { - if (g_strcmp0 (mime_type, *p) == 0) - return TRUE; - } - - return FALSE; -} diff --git a/src/wayland/meta-wayland-data-source.h b/src/wayland/meta-wayland-data-source.h deleted file mode 100644 index 900329b10..000000000 --- a/src/wayland/meta-wayland-data-source.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright © 2011 Kristian Høgsberg - * 2020 Red Hat Inc. - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#ifndef META_WAYLAND_DATA_SOURCE_H -#define META_WAYLAND_DATA_SOURCE_H - -#include -#include - -#include "wayland/meta-wayland-types.h" - -#define META_TYPE_WAYLAND_DATA_SOURCE (meta_wayland_data_source_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaWaylandDataSource, - meta_wayland_data_source, - META, WAYLAND_DATA_SOURCE, - GObject) - -typedef struct _MetaWaylandDataSourceClass MetaWaylandDataSourceClass; - -struct _MetaWaylandDataSourceClass -{ - GObjectClass parent_class; - - void (* send) (MetaWaylandDataSource *source, - const gchar *mime_type, - gint fd); - void (* target) (MetaWaylandDataSource *source, - const gchar *mime_type); - void (* cancel) (MetaWaylandDataSource *source); - - void (* action) (MetaWaylandDataSource *source, - uint32_t action); - void (* drop_performed) (MetaWaylandDataSource *source); - void (* drag_finished) (MetaWaylandDataSource *source); -}; - -MetaWaylandDataSource * meta_wayland_data_source_new (struct wl_resource *resource); - -struct wl_resource * meta_wayland_data_source_get_resource (MetaWaylandDataSource *source); -void meta_wayland_data_source_set_resource (MetaWaylandDataSource *source, - struct wl_resource *resource); - -gboolean meta_wayland_data_source_get_in_ask (MetaWaylandDataSource *source); -void meta_wayland_data_source_update_in_ask (MetaWaylandDataSource *source); - -void meta_wayland_data_source_target (MetaWaylandDataSource *source, - const char *mime_type); -void meta_wayland_data_source_send (MetaWaylandDataSource *source, - const char *mime_type, - int fd); -void meta_wayland_data_source_cancel (MetaWaylandDataSource *source); - -gboolean meta_wayland_data_source_has_target (MetaWaylandDataSource *source); - -void meta_wayland_data_source_set_seat (MetaWaylandDataSource *source, - MetaWaylandSeat *seat); -MetaWaylandSeat * meta_wayland_data_source_get_seat (MetaWaylandDataSource *source); - -void meta_wayland_data_source_set_has_target (MetaWaylandDataSource *source, - gboolean has_target); -struct wl_array * meta_wayland_data_source_get_mime_types (MetaWaylandDataSource *source); -gboolean meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source, - const gchar *mime_type); -gboolean meta_wayland_data_source_has_mime_type (MetaWaylandDataSource *source, - const char *mime_type); - -gboolean meta_wayland_data_source_get_actions (MetaWaylandDataSource *source, - uint32_t *dnd_actions); -void meta_wayland_data_source_set_actions (MetaWaylandDataSource *source, - uint32_t dnd_actions); - -enum wl_data_device_manager_dnd_action - meta_wayland_data_source_get_current_action (MetaWaylandDataSource *source); -void meta_wayland_data_source_set_current_action (MetaWaylandDataSource *source, - enum wl_data_device_manager_dnd_action action); - -enum wl_data_device_manager_dnd_action - meta_wayland_data_source_get_user_action (MetaWaylandDataSource *source); -void meta_wayland_data_source_set_user_action (MetaWaylandDataSource *source, - uint32_t action); - -MetaWaylandDataOffer * - meta_wayland_data_source_get_current_offer (MetaWaylandDataSource *source); -void meta_wayland_data_source_set_current_offer (MetaWaylandDataSource *source, - MetaWaylandDataOffer *offer); - -gboolean meta_wayland_data_source_get_drop_performed (MetaWaylandDataSource *source); - -void meta_wayland_data_source_notify_drop_performed (MetaWaylandDataSource *source); -void meta_wayland_data_source_notify_finish (MetaWaylandDataSource *source); - -#endif /* META_WAYLAND_DATA_SOURCE_H */ diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c deleted file mode 100644 index 3fc431201..000000000 --- a/src/wayland/meta-wayland-dma-buf.c +++ /dev/null @@ -1,784 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 Red Hat Inc. - * Copyright (C) 2017 Intel Corporation - * Copyright (C) 2018,2019 DisplayLink (UK) Ltd. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - * Daniel Stone - */ - -/** - * SECTION:meta-wayland-dma-buf - * @title: MetaWaylandDmaBuf - * @short_description: Handles passing DMA-BUFs in Wayland - * - * The MetaWaylandDmaBuf namespace contains several objects and functions to - * handle DMA-BUF buffers that are passed through from clients in Wayland (e.g. - * using the linux_dmabuf_unstable_v1 protocol). - */ - -#include "config.h" - -#include "wayland/meta-wayland-dma-buf.h" - -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-egl-ext.h" -#include "backends/meta-egl.h" -#include "cogl/cogl-egl.h" -#include "cogl/cogl.h" -#include "meta/meta-backend.h" -#include "wayland/meta-wayland-buffer.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-versions.h" - -#ifdef HAVE_NATIVE_BACKEND -#include "backends/native/meta-drm-buffer-gbm.h" -#include "backends/native/meta-kms-utils.h" -#include "backends/native/meta-onscreen-native.h" -#include "backends/native/meta-renderer-native.h" -#endif - -#include "linux-dmabuf-unstable-v1-server-protocol.h" - -#ifndef DRM_FORMAT_MOD_INVALID -#define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1) -#endif - -#define META_WAYLAND_DMA_BUF_MAX_FDS 4 - -struct _MetaWaylandDmaBufBuffer -{ - GObject parent; - - int width; - int height; - uint32_t drm_format; - uint64_t drm_modifier; - bool is_y_inverted; - int fds[META_WAYLAND_DMA_BUF_MAX_FDS]; - uint32_t offsets[META_WAYLAND_DMA_BUF_MAX_FDS]; - uint32_t strides[META_WAYLAND_DMA_BUF_MAX_FDS]; -}; - -G_DEFINE_TYPE (MetaWaylandDmaBufBuffer, meta_wayland_dma_buf_buffer, G_TYPE_OBJECT); - -static gboolean -meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer, - GError **error) -{ - MetaBackend *backend = meta_get_backend (); - MetaEgl *egl = meta_backend_get_egl (backend); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); - EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context); - MetaWaylandDmaBufBuffer *dma_buf = buffer->dma_buf.dma_buf; - uint32_t n_planes; - uint64_t modifiers[META_WAYLAND_DMA_BUF_MAX_FDS]; - CoglPixelFormat cogl_format; - EGLImageKHR egl_image; - CoglEglImageFlags flags; - CoglTexture2D *texture; - MetaDrmFormatBuf format_buf; - - if (buffer->dma_buf.texture) - return TRUE; - - switch (dma_buf->drm_format) - { - /* - * NOTE: The cogl_format here is only used for texture color channel - * swizzling as compared to COGL_PIXEL_FORMAT_ARGB. It is *not* used - * for accessing the buffer memory. EGL will access the buffer - * memory according to the DRM fourcc code. Cogl will not mmap - * and access the buffer memory at all. - */ - case DRM_FORMAT_XRGB8888: - cogl_format = COGL_PIXEL_FORMAT_RGB_888; - break; - case DRM_FORMAT_ARGB8888: - cogl_format = COGL_PIXEL_FORMAT_ARGB_8888_PRE; - break; - case DRM_FORMAT_XRGB2101010: - cogl_format = COGL_PIXEL_FORMAT_ARGB_2101010; - break; - case DRM_FORMAT_ARGB2101010: - cogl_format = COGL_PIXEL_FORMAT_ARGB_2101010_PRE; - break; - case DRM_FORMAT_ABGR2101010: - cogl_format = COGL_PIXEL_FORMAT_ABGR_2101010_PRE; - break; - case DRM_FORMAT_RGB565: - cogl_format = COGL_PIXEL_FORMAT_RGB_565; - break; - case DRM_FORMAT_XBGR16161616F: - case DRM_FORMAT_ABGR16161616F: - cogl_format = COGL_PIXEL_FORMAT_ABGR_FP_16161616_PRE; - break; - case DRM_FORMAT_XRGB16161616F: - case DRM_FORMAT_ARGB16161616F: - cogl_format = COGL_PIXEL_FORMAT_ARGB_FP_16161616_PRE; - break; - default: - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Unsupported buffer format %d", dma_buf->drm_format); - return FALSE; - } - - meta_topic (META_DEBUG_WAYLAND, - "[dma-buf] wl_buffer@%u DRM format %s -> CoglPixelFormat %s", - wl_resource_get_id (meta_wayland_buffer_get_resource (buffer)), - meta_drm_format_to_string (&format_buf, dma_buf->drm_format), - cogl_pixel_format_to_string (cogl_format)); - - for (n_planes = 0; n_planes < META_WAYLAND_DMA_BUF_MAX_FDS; n_planes++) - { - if (dma_buf->fds[n_planes] < 0) - break; - - modifiers[n_planes] = dma_buf->drm_modifier; - } - - egl_image = meta_egl_create_dmabuf_image (egl, - egl_display, - dma_buf->width, - dma_buf->height, - dma_buf->drm_format, - n_planes, - dma_buf->fds, - dma_buf->strides, - dma_buf->offsets, - modifiers, - error); - if (egl_image == EGL_NO_IMAGE_KHR) - return FALSE; - - flags = COGL_EGL_IMAGE_FLAG_NO_GET_DATA; - texture = cogl_egl_texture_2d_new_from_image (cogl_context, - dma_buf->width, - dma_buf->height, - cogl_format, - egl_image, - flags, - error); - - meta_egl_destroy_image (egl, egl_display, egl_image, NULL); - - if (!texture) - return FALSE; - - buffer->dma_buf.texture = COGL_TEXTURE (texture); - buffer->is_y_inverted = dma_buf->is_y_inverted; - - return TRUE; -} - -gboolean -meta_wayland_dma_buf_buffer_attach (MetaWaylandBuffer *buffer, - CoglTexture **texture, - GError **error) -{ - if (!meta_wayland_dma_buf_realize_texture (buffer, error)) - return FALSE; - - cogl_clear_object (texture); - *texture = cogl_object_ref (buffer->dma_buf.texture); - return TRUE; -} - -#ifdef HAVE_NATIVE_BACKEND -static struct gbm_bo * -import_scanout_gbm_bo (MetaWaylandDmaBufBuffer *dma_buf, - MetaGpuKms *gpu_kms, - int n_planes, - gboolean *use_modifier) -{ - struct gbm_device *gbm_device; - - gbm_device = meta_gbm_device_from_gpu (gpu_kms); - - if (dma_buf->drm_modifier != DRM_FORMAT_MOD_INVALID || - n_planes > 1 || - dma_buf->offsets[0] > 0) - { - struct gbm_import_fd_modifier_data import_with_modifier; - - import_with_modifier = (struct gbm_import_fd_modifier_data) { - .width = dma_buf->width, - .height = dma_buf->height, - .format = dma_buf->drm_format, - .num_fds = n_planes, - .modifier = dma_buf->drm_modifier, - }; - memcpy (import_with_modifier.fds, - dma_buf->fds, - sizeof (dma_buf->fds)); - memcpy (import_with_modifier.strides, - dma_buf->strides, - sizeof (import_with_modifier.strides)); - memcpy (import_with_modifier.offsets, - dma_buf->offsets, - sizeof (import_with_modifier.offsets)); - - *use_modifier = TRUE; - return gbm_bo_import (gbm_device, GBM_BO_IMPORT_FD_MODIFIER, - &import_with_modifier, - GBM_BO_USE_SCANOUT); - } - else - { - struct gbm_import_fd_data import_legacy; - - import_legacy = (struct gbm_import_fd_data) { - .width = dma_buf->width, - .height = dma_buf->height, - .format = dma_buf->drm_format, - .stride = dma_buf->strides[0], - .fd = dma_buf->fds[0], - }; - - *use_modifier = FALSE; - return gbm_bo_import (gbm_device, GBM_BO_IMPORT_FD, - &import_legacy, - GBM_BO_USE_SCANOUT); - } -} -#endif - -CoglScanout * -meta_wayland_dma_buf_try_acquire_scanout (MetaWaylandDmaBufBuffer *dma_buf, - CoglOnscreen *onscreen) -{ -#ifdef HAVE_NATIVE_BACKEND - MetaBackend *backend = meta_get_backend (); - MetaRenderer *renderer = meta_backend_get_renderer (backend); - MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer); - MetaDeviceFile *device_file; - MetaGpuKms *gpu_kms; - int n_planes; - uint32_t drm_format; - uint64_t drm_modifier; - uint32_t stride; - struct gbm_bo *gbm_bo; - gboolean use_modifier; - g_autoptr (GError) error = NULL; - MetaDrmBufferGbm *fb; - - for (n_planes = 0; n_planes < META_WAYLAND_DMA_BUF_MAX_FDS; n_planes++) - { - if (dma_buf->fds[n_planes] < 0) - break; - } - - drm_format = dma_buf->drm_format; - drm_modifier = dma_buf->drm_modifier; - stride = dma_buf->strides[0]; - if (!meta_onscreen_native_is_buffer_scanout_compatible (onscreen, - drm_format, - drm_modifier, - stride)) - return NULL; - - device_file = meta_renderer_native_get_primary_device_file (renderer_native); - gpu_kms = meta_renderer_native_get_primary_gpu (renderer_native); - gbm_bo = import_scanout_gbm_bo (dma_buf, gpu_kms, n_planes, &use_modifier); - if (!gbm_bo) - { - g_debug ("Failed to import scanout gbm_bo: %s", g_strerror (errno)); - return NULL; - } - - fb = meta_drm_buffer_gbm_new_take (device_file, - gbm_bo, - use_modifier, - &error); - if (!fb) - { - g_debug ("Failed to create scanout buffer: %s", error->message); - gbm_bo_destroy (gbm_bo); - return NULL; - } - - return COGL_SCANOUT (fb); -#else - return NULL; -#endif -} - -static void -buffer_params_add (struct wl_client *client, - struct wl_resource *resource, - int32_t fd, - uint32_t plane_idx, - uint32_t offset, - uint32_t stride, - uint32_t drm_modifier_hi, - uint32_t drm_modifier_lo) -{ - MetaWaylandDmaBufBuffer *dma_buf; - uint64_t drm_modifier; - - drm_modifier = ((uint64_t) drm_modifier_hi) << 32; - drm_modifier |= ((uint64_t) drm_modifier_lo) & 0xffffffff; - - dma_buf = wl_resource_get_user_data (resource); - if (!dma_buf) - { - wl_resource_post_error (resource, - ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED, - "params already used"); - return; - } - - if (plane_idx >= META_WAYLAND_DMA_BUF_MAX_FDS) - { - wl_resource_post_error (resource, - ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_IDX, - "out-of-bounds plane index %d", - plane_idx); - return; - } - - if (dma_buf->fds[plane_idx] != -1) - { - wl_resource_post_error (resource, - ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_SET, - "plane index %d already set", - plane_idx); - return; - } - - if (dma_buf->drm_modifier != DRM_FORMAT_MOD_INVALID && - dma_buf->drm_modifier != drm_modifier) - { - wl_resource_post_error (resource, - ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_WL_BUFFER, - "mismatching modifier between planes"); - return; - } - - dma_buf->drm_modifier = drm_modifier; - dma_buf->fds[plane_idx] = fd; - dma_buf->offsets[plane_idx] = offset; - dma_buf->strides[plane_idx] = stride; -} - -static void -buffer_params_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -buffer_params_destructor (struct wl_resource *resource) -{ - MetaWaylandDmaBufBuffer *dma_buf; - - /* The user-data for our MetaWaylandBuffer is only valid in between adding - * FDs and creating the buffer; once it is created, we free it out into - * the wild, where the ref is considered transferred to the wl_buffer. */ - dma_buf = wl_resource_get_user_data (resource); - if (dma_buf) - g_object_unref (dma_buf); -} - -static void -buffer_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static const struct wl_buffer_interface dma_buf_buffer_impl = -{ - buffer_destroy, -}; - -/** - * meta_wayland_dma_buf_from_buffer: - * @buffer: A #MetaWaylandBuffer object - * - * Fetches the associated #MetaWaylandDmaBufBuffer from the wayland buffer. - * This does not *create* a new object, as this happens in the create_params - * request of linux_dmabuf_unstable_v1. - * - * Returns: (transfer none): The corresponding #MetaWaylandDmaBufBuffer (or - * %NULL if it wasn't a dma_buf-based wayland buffer) - */ -MetaWaylandDmaBufBuffer * -meta_wayland_dma_buf_from_buffer (MetaWaylandBuffer *buffer) -{ - if (!buffer->resource) - return NULL; - - if (wl_resource_instance_of (buffer->resource, &wl_buffer_interface, - &dma_buf_buffer_impl)) - return wl_resource_get_user_data (buffer->resource); - - return NULL; -} - -static void -buffer_params_create_common (struct wl_client *client, - struct wl_resource *params_resource, - uint32_t buffer_id, - int32_t width, - int32_t height, - uint32_t drm_format, - uint32_t flags) -{ - MetaWaylandDmaBufBuffer *dma_buf; - MetaWaylandBuffer *buffer; - struct wl_resource *buffer_resource; - GError *error = NULL; - - dma_buf = wl_resource_get_user_data (params_resource); - if (!dma_buf) - { - wl_resource_post_error (params_resource, - ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED, - "params already used"); - return; - } - - /* Calling the 'create' method is the point of no return: after that point, - * the params object cannot be used. This method must either transfer the - * ownership of the MetaWaylandDmaBufBuffer to a MetaWaylandBuffer, or - * destroy it. */ - wl_resource_set_user_data (params_resource, NULL); - - if (dma_buf->fds[0] == -1) - { - wl_resource_post_error (params_resource, - ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, - "no planes added to params"); - g_object_unref (dma_buf); - return; - } - - if ((dma_buf->fds[3] >= 0 || dma_buf->fds[2] >= 0) && - (dma_buf->fds[2] == -1 || dma_buf->fds[1] == -1)) - { - wl_resource_post_error (params_resource, - ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, - "gap in planes added to params"); - g_object_unref (dma_buf); - return; - } - - dma_buf->width = width; - dma_buf->height = height; - dma_buf->drm_format = drm_format; - dma_buf->is_y_inverted = !(flags & ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT); - - if (flags & ~ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT) - { - wl_resource_post_error (params_resource, - ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_WL_BUFFER, - "unknown flags 0x%x supplied", flags); - g_object_unref (dma_buf); - return; - } - - /* Create a new MetaWaylandBuffer wrapping our dmabuf, and immediately try - * to realize it, so we can give the client success/fail feedback for the - * import. */ - buffer_resource = - wl_resource_create (client, &wl_buffer_interface, 1, buffer_id); - wl_resource_set_implementation (buffer_resource, &dma_buf_buffer_impl, - dma_buf, NULL); - buffer = meta_wayland_buffer_from_resource (buffer_resource); - - meta_wayland_buffer_realize (buffer); - if (!meta_wayland_dma_buf_realize_texture (buffer, &error)) - { - if (buffer_id == 0) - { - zwp_linux_buffer_params_v1_send_failed (params_resource); - } - else - { - wl_resource_post_error (params_resource, - ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_WL_BUFFER, - "failed to import supplied dmabufs: %s", - error ? error->message : "unknown error"); - } - - /* will unref the MetaWaylandBuffer */ - wl_resource_destroy (buffer->resource); - return; - } - - /* If buffer_id is 0, we are using the non-immediate interface, so - * need to send a success event with our buffer. */ - if (buffer_id == 0) - zwp_linux_buffer_params_v1_send_created (params_resource, - buffer->resource); -} - -static void -buffer_params_create (struct wl_client *client, - struct wl_resource *params_resource, - int32_t width, - int32_t height, - uint32_t format, - uint32_t flags) -{ - buffer_params_create_common (client, params_resource, 0, width, height, - format, flags); -} - -static void -buffer_params_create_immed (struct wl_client *client, - struct wl_resource *params_resource, - uint32_t buffer_id, - int32_t width, - int32_t height, - uint32_t format, - uint32_t flags) -{ - buffer_params_create_common (client, params_resource, buffer_id, width, - height, format, flags); -} - -static const struct zwp_linux_buffer_params_v1_interface buffer_params_implementation = -{ - buffer_params_destroy, - buffer_params_add, - buffer_params_create, - buffer_params_create_immed, -}; - -static void -dma_buf_handle_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -dma_buf_handle_create_buffer_params (struct wl_client *client, - struct wl_resource *dma_buf_resource, - uint32_t params_id) -{ - struct wl_resource *params_resource; - MetaWaylandDmaBufBuffer *dma_buf; - - dma_buf = g_object_new (META_TYPE_WAYLAND_DMA_BUF_BUFFER, NULL); - - params_resource = - wl_resource_create (client, - &zwp_linux_buffer_params_v1_interface, - wl_resource_get_version (dma_buf_resource), - params_id); - wl_resource_set_implementation (params_resource, - &buffer_params_implementation, - dma_buf, - buffer_params_destructor); -} - -static const struct zwp_linux_dmabuf_v1_interface dma_buf_implementation = -{ - dma_buf_handle_destroy, - dma_buf_handle_create_buffer_params, -}; - -static gboolean -should_send_modifiers (MetaBackend *backend) -{ - MetaSettings *settings = meta_backend_get_settings (backend); - -#ifdef HAVE_NATIVE_BACKEND - if (META_IS_BACKEND_NATIVE (backend)) - { - MetaRenderer *renderer = meta_backend_get_renderer (backend); - MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer); - return meta_renderer_native_use_modifiers (renderer_native); - } -#endif - - return meta_settings_is_experimental_feature_enabled ( - settings, META_EXPERIMENTAL_FEATURE_KMS_MODIFIERS); -} - -static void -send_modifiers (struct wl_resource *resource, - uint32_t format) -{ - MetaBackend *backend = meta_get_backend (); - MetaEgl *egl = meta_backend_get_egl (backend); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); - EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context); - EGLint num_modifiers; - EGLuint64KHR *modifiers; - GError *error = NULL; - gboolean ret; - int i; - - zwp_linux_dmabuf_v1_send_format (resource, format); - - /* The modifier event was only added in v3; v1 and v2 only have the format - * event. */ - if (wl_resource_get_version (resource) < ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION) - return; - - if (!should_send_modifiers (backend)) - { - zwp_linux_dmabuf_v1_send_modifier (resource, format, - DRM_FORMAT_MOD_INVALID >> 32, - DRM_FORMAT_MOD_INVALID & 0xffffffff); - return; - } - - /* First query the number of available modifiers, then allocate an array, - * then fill the array. */ - ret = meta_egl_query_dma_buf_modifiers (egl, egl_display, format, 0, NULL, - NULL, &num_modifiers, NULL); - if (!ret) - return; - - if (num_modifiers == 0) - { - zwp_linux_dmabuf_v1_send_modifier (resource, format, - DRM_FORMAT_MOD_INVALID >> 32, - DRM_FORMAT_MOD_INVALID & 0xffffffff); - return; - } - - modifiers = g_new0 (uint64_t, num_modifiers); - ret = meta_egl_query_dma_buf_modifiers (egl, egl_display, format, - num_modifiers, modifiers, NULL, - &num_modifiers, &error); - if (!ret) - { - g_warning ("Failed to query modifiers for format 0x%" PRIu32 ": %s", - format, error ? error->message : "unknown error"); - g_free (modifiers); - return; - } - - for (i = 0; i < num_modifiers; i++) - { - zwp_linux_dmabuf_v1_send_modifier (resource, format, - modifiers[i] >> 32, - modifiers[i] & 0xffffffff); - } - - g_free (modifiers); -} - -static void -dma_buf_bind (struct wl_client *client, - void *data, - uint32_t version, - uint32_t id) -{ - MetaWaylandCompositor *compositor = data; - struct wl_resource *resource; - - resource = wl_resource_create (client, &zwp_linux_dmabuf_v1_interface, - version, id); - wl_resource_set_implementation (resource, &dma_buf_implementation, - compositor, NULL); - send_modifiers (resource, DRM_FORMAT_ARGB8888); - send_modifiers (resource, DRM_FORMAT_XRGB8888); - send_modifiers (resource, DRM_FORMAT_ARGB2101010); - send_modifiers (resource, DRM_FORMAT_ABGR2101010); - send_modifiers (resource, DRM_FORMAT_XRGB2101010); - send_modifiers (resource, DRM_FORMAT_RGB565); - send_modifiers (resource, DRM_FORMAT_ABGR16161616F); - send_modifiers (resource, DRM_FORMAT_XBGR16161616F); - send_modifiers (resource, DRM_FORMAT_XRGB16161616F); - send_modifiers (resource, DRM_FORMAT_ARGB16161616F); -} - -/** - * meta_wayland_dma_buf_init: - * @compositor: The #MetaWaylandCompositor - * - * Creates the global Wayland object that exposes the linux-dmabuf protocol. - * - * Returns: Whether the initialization was successful. If this is %FALSE, - * clients won't be able to use the linux-dmabuf protocol to pass buffers. - */ -gboolean -meta_wayland_dma_buf_init (MetaWaylandCompositor *compositor) -{ - MetaBackend *backend = meta_get_backend (); - MetaEgl *egl = meta_backend_get_egl (backend); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); - EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context); - - g_assert (backend && egl && clutter_backend && cogl_context && egl_display); - - if (!meta_egl_has_extensions (egl, egl_display, NULL, - "EGL_EXT_image_dma_buf_import_modifiers", - NULL)) - return FALSE; - - if (!wl_global_create (compositor->wayland_display, - &zwp_linux_dmabuf_v1_interface, - META_ZWP_LINUX_DMABUF_V1_VERSION, - compositor, - dma_buf_bind)) - return FALSE; - - return TRUE; -} - -static void -meta_wayland_dma_buf_buffer_finalize (GObject *object) -{ - MetaWaylandDmaBufBuffer *dma_buf = META_WAYLAND_DMA_BUF_BUFFER (object); - int i; - - for (i = 0; i < META_WAYLAND_DMA_BUF_MAX_FDS; i++) - { - if (dma_buf->fds[i] != -1) - close (dma_buf->fds[i]); - } - - G_OBJECT_CLASS (meta_wayland_dma_buf_buffer_parent_class)->finalize (object); -} - -static void -meta_wayland_dma_buf_buffer_init (MetaWaylandDmaBufBuffer *dma_buf) -{ - int i; - - dma_buf->drm_modifier = DRM_FORMAT_MOD_INVALID; - - for (i = 0; i < META_WAYLAND_DMA_BUF_MAX_FDS; i++) - dma_buf->fds[i] = -1; -} - -static void -meta_wayland_dma_buf_buffer_class_init (MetaWaylandDmaBufBufferClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_wayland_dma_buf_buffer_finalize; -} diff --git a/src/wayland/meta-wayland-dma-buf.h b/src/wayland/meta-wayland-dma-buf.h deleted file mode 100644 index cdc65aeb5..000000000 --- a/src/wayland/meta-wayland-dma-buf.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 Red Hat Inc. - * Copyright (C) 2017 Intel Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - * Daniel Stone - */ - -#ifndef META_WAYLAND_DMA_BUF_H -#define META_WAYLAND_DMA_BUF_H - -#include -#include - -#include "cogl/cogl.h" -#include "wayland/meta-wayland-types.h" - -#define META_TYPE_WAYLAND_DMA_BUF_BUFFER (meta_wayland_dma_buf_buffer_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandDmaBufBuffer, meta_wayland_dma_buf_buffer, - META, WAYLAND_DMA_BUF_BUFFER, GObject); - -typedef struct _MetaWaylandDmaBufBuffer MetaWaylandDmaBufBuffer; - -gboolean meta_wayland_dma_buf_init (MetaWaylandCompositor *compositor); - -gboolean -meta_wayland_dma_buf_buffer_attach (MetaWaylandBuffer *buffer, - CoglTexture **texture, - GError **error); - -MetaWaylandDmaBufBuffer * -meta_wayland_dma_buf_from_buffer (MetaWaylandBuffer *buffer); - -CoglScanout * -meta_wayland_dma_buf_try_acquire_scanout (MetaWaylandDmaBufBuffer *dma_buf, - CoglOnscreen *onscreen); - -#endif /* META_WAYLAND_DMA_BUF_H */ diff --git a/src/wayland/meta-wayland-dnd-surface.c b/src/wayland/meta-wayland-dnd-surface.c deleted file mode 100644 index 047de6e2b..000000000 --- a/src/wayland/meta-wayland-dnd-surface.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (C) 2015-2019 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include "config.h" - -#include "wayland/meta-wayland-dnd-surface.h" - -#include "backends/meta-logical-monitor.h" -#include "compositor/meta-feedback-actor-private.h" -#include "wayland/meta-wayland.h" - -struct _MetaWaylandSurfaceRoleDND -{ - MetaWaylandActorSurface parent; - int32_t pending_offset_x; - int32_t pending_offset_y; -}; - -G_DEFINE_TYPE (MetaWaylandSurfaceRoleDND, - meta_wayland_surface_role_dnd, - META_TYPE_WAYLAND_ACTOR_SURFACE) - -static void -dnd_surface_assigned (MetaWaylandSurfaceRole *surface_role) -{ - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - - if (wl_list_empty (&surface->unassigned.pending_frame_callback_list)) - return; - - meta_wayland_compositor_add_frame_callback_surface (surface->compositor, - surface); -} - -static void -dnd_surface_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending) -{ - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWaylandSurfaceRoleDND *surface_role_dnd = - META_WAYLAND_SURFACE_ROLE_DND (surface_role); - MetaWaylandSurfaceRoleClass *surface_role_class = - META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_surface_role_dnd_parent_class); - - meta_wayland_compositor_add_frame_callback_surface (surface->compositor, - surface); - - surface_role_dnd->pending_offset_x = pending->dx; - surface_role_dnd->pending_offset_y = pending->dy; - - surface_role_class->apply_state (surface_role, pending); -} - -static MetaLogicalMonitor * -dnd_surface_find_logical_monitor (MetaWaylandActorSurface *actor_surface) -{ - MetaBackend *backend = meta_get_backend (); - MetaCursorTracker *cursor_tracker = - meta_backend_get_cursor_tracker (backend); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - graphene_point_t point; - - meta_cursor_tracker_get_pointer (cursor_tracker, &point, NULL); - return meta_monitor_manager_get_logical_monitor_at (monitor_manager, - point.x, point.y); -} - -static double -dnd_subsurface_get_geometry_scale (MetaWaylandActorSurface *actor_surface) -{ - if (meta_is_stage_views_scaled ()) - { - return 1; - } - else - { - MetaLogicalMonitor *logical_monitor; - - logical_monitor = dnd_surface_find_logical_monitor (actor_surface); - return meta_logical_monitor_get_scale (logical_monitor); - } -} - -static void -dnd_subsurface_sync_actor_state (MetaWaylandActorSurface *actor_surface) -{ - MetaSurfaceActor *surface_actor = - meta_wayland_actor_surface_get_actor (actor_surface); - MetaFeedbackActor *feedback_actor = - META_FEEDBACK_ACTOR (clutter_actor_get_parent (CLUTTER_ACTOR (surface_actor))); - MetaWaylandSurfaceRole *surface_role = - META_WAYLAND_SURFACE_ROLE (actor_surface); - MetaWaylandSurfaceRoleDND *surface_role_dnd = - META_WAYLAND_SURFACE_ROLE_DND (surface_role); - MetaWaylandActorSurfaceClass *actor_surface_class = - META_WAYLAND_ACTOR_SURFACE_CLASS (meta_wayland_surface_role_dnd_parent_class); - int geometry_scale; - float anchor_x; - float anchor_y; - - g_return_if_fail (META_IS_FEEDBACK_ACTOR (feedback_actor)); - - geometry_scale = - meta_wayland_actor_surface_get_geometry_scale (actor_surface); - meta_feedback_actor_set_geometry_scale (feedback_actor, geometry_scale); - - meta_feedback_actor_get_anchor (feedback_actor, &anchor_x, &anchor_y); - anchor_x -= surface_role_dnd->pending_offset_x; - anchor_y -= surface_role_dnd->pending_offset_y; - meta_feedback_actor_set_anchor (feedback_actor, anchor_x, anchor_y); - - actor_surface_class->sync_actor_state (actor_surface); -} - -static void -meta_wayland_surface_role_dnd_init (MetaWaylandSurfaceRoleDND *role) -{ -} - -static void -meta_wayland_surface_role_dnd_class_init (MetaWaylandSurfaceRoleDNDClass *klass) -{ - MetaWaylandSurfaceRoleClass *surface_role_class = - META_WAYLAND_SURFACE_ROLE_CLASS (klass); - MetaWaylandActorSurfaceClass *actor_surface_class = - META_WAYLAND_ACTOR_SURFACE_CLASS (klass); - - surface_role_class->assigned = dnd_surface_assigned; - surface_role_class->apply_state = dnd_surface_apply_state; - - actor_surface_class->get_geometry_scale = dnd_subsurface_get_geometry_scale; - actor_surface_class->sync_actor_state = dnd_subsurface_sync_actor_state; -} diff --git a/src/wayland/meta-wayland-dnd-surface.h b/src/wayland/meta-wayland-dnd-surface.h deleted file mode 100644 index 45cf689ee..000000000 --- a/src/wayland/meta-wayland-dnd-surface.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2015-2019 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_WAYLAND_DND_SURFACE_H -#define META_WAYLAND_DND_SURFACE_H - -#include "wayland/meta-wayland-actor-surface.h" - -#define META_TYPE_WAYLAND_SURFACE_ROLE_DND (meta_wayland_surface_role_dnd_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandSurfaceRoleDND, - meta_wayland_surface_role_dnd, - META, WAYLAND_SURFACE_ROLE_DND, - MetaWaylandActorSurface) - -#endif /* META_WAYLAND_DND_SURFACE_H */ diff --git a/src/wayland/meta-wayland-egl-stream.c b/src/wayland/meta-wayland-egl-stream.c deleted file mode 100644 index 3a2e1e56a..000000000 --- a/src/wayland/meta-wayland-egl-stream.c +++ /dev/null @@ -1,367 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#include "config.h" - -#include "wayland/meta-wayland-egl-stream.h" - -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-egl-ext.h" -#include "backends/meta-egl.h" -#include "cogl/cogl-egl.h" -#include "meta/meta-backend.h" -#include "wayland/meta-wayland-buffer.h" -#include "wayland/meta-wayland-private.h" - -#include "wayland-eglstream-controller-server-protocol.h" - -static struct wl_interface *wl_eglstream_controller_interface_ptr = NULL; - -static void -attach_eglstream_consumer (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *wl_surface, - struct wl_resource *wl_eglstream) -{ - MetaWaylandBuffer *buffer = meta_wayland_buffer_from_resource (wl_eglstream); - - if (!meta_wayland_buffer_is_realized (buffer)) - meta_wayland_buffer_realize (buffer); -} - -static const struct wl_eglstream_controller_interface -meta_eglstream_controller_interface = { - attach_eglstream_consumer -}; - -static void -bind_eglstream_controller (struct wl_client *client, - void *data, - uint32_t version, - uint32_t id) -{ - struct wl_resource *resource; - - g_assert (wl_eglstream_controller_interface_ptr != NULL); - - resource = wl_resource_create (client, - wl_eglstream_controller_interface_ptr, - version, - id); - - if (resource == NULL) - { - wl_client_post_no_memory(client); - return; - } - - wl_resource_set_implementation (resource, - &meta_eglstream_controller_interface, - data, - NULL); -} - -gboolean -meta_wayland_eglstream_controller_init (MetaWaylandCompositor *compositor) -{ - /* - * wl_eglstream_controller_interface is provided by - * libnvidia-egl-wayland.so.1 - * - * Since it might not be available on the - * system, dynamically load it at runtime and resolve the needed - * symbols. If available, it should be found under any of the search - * directories of dlopen() - * - * Failure to initialize wl_eglstream_controller is non-fatal - */ - - void *lib = dlopen ("libnvidia-egl-wayland.so.1", RTLD_NOW | RTLD_LAZY); - if (!lib) - goto fail; - - wl_eglstream_controller_interface_ptr = - dlsym (lib, "wl_eglstream_controller_interface"); - - if (!wl_eglstream_controller_interface_ptr) - goto fail; - - if (wl_global_create (compositor->wayland_display, - wl_eglstream_controller_interface_ptr, 1, - NULL, - bind_eglstream_controller) == NULL) - goto fail; - - g_debug ("WL: loaded libnvidia-egl-wayland.so.1:wl_eglstream_controller."); - - return TRUE; - -fail: - if (lib) - dlclose(lib); - - g_debug ("WL: Unable to initialize wl_eglstream_controller."); - - return FALSE; -} - -struct _MetaWaylandEglStream -{ - GObject parent; - - EGLStreamKHR egl_stream; - MetaWaylandBuffer *buffer; - CoglTexture2D *texture; - gboolean is_y_inverted; - CoglSnippet *snippet; -}; - -G_DEFINE_TYPE (MetaWaylandEglStream, meta_wayland_egl_stream, - G_TYPE_OBJECT) - -MetaWaylandEglStream * -meta_wayland_egl_stream_new (MetaWaylandBuffer *buffer, - GError **error) -{ - MetaBackend *backend = meta_get_backend (); - MetaEgl *egl = meta_backend_get_egl (backend); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); - EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context); - EGLAttrib stream_attribs[] = { - EGL_WAYLAND_EGLSTREAM_WL, (EGLAttrib) buffer->resource, - EGL_NONE - }; - EGLStreamKHR egl_stream; - MetaWaylandEglStream *stream; - - egl_stream = meta_egl_create_stream_attrib (egl, egl_display, stream_attribs, - error); - if (egl_stream == EGL_NO_STREAM_KHR) - { - g_set_error (error, G_IO_ERROR, - G_IO_ERROR_FAILED, - "Failed to create stream from wl_buffer resource"); - return NULL; - } - - stream = g_object_new (META_TYPE_WAYLAND_EGL_STREAM, NULL); - stream->egl_stream = egl_stream; - stream->buffer = buffer; - - return stream; -} - -static void -stream_texture_destroyed (gpointer data) -{ - MetaWaylandEglStream *stream = data; - - stream->texture = NULL; - - g_object_unref (stream); -} - -static gboolean -alloc_egl_stream_texture (CoglTexture2D *texture, - gpointer user_data, - GError **error) -{ - MetaBackend *backend = meta_get_backend (); - MetaEgl *egl = meta_backend_get_egl (backend); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); - EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context); - MetaWaylandEglStream *stream = user_data; - - return meta_egl_stream_consumer_gl_texture_external (egl, egl_display, - stream->egl_stream, - error); -} - -CoglTexture2D * -meta_wayland_egl_stream_create_texture (MetaWaylandEglStream *stream, - GError **error) -{ - MetaBackend *backend = meta_get_backend (); - MetaEgl *egl = meta_backend_get_egl (backend); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); - EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context); - CoglTexture2D *texture; - int width, height; - int y_inverted; - - if (!meta_egl_query_wayland_buffer (egl, egl_display, - stream->buffer->resource, - EGL_WIDTH, &width, - error)) - return NULL; - - if (!meta_egl_query_wayland_buffer (egl, egl_display, - stream->buffer->resource, - EGL_HEIGHT, &height, - error)) - return NULL; - - if (!meta_egl_query_wayland_buffer (egl, egl_display, - stream->buffer->resource, - EGL_WAYLAND_Y_INVERTED_WL, &y_inverted, - NULL)) - y_inverted = EGL_TRUE; - - texture = - cogl_texture_2d_new_from_egl_image_external (cogl_context, - width, height, - alloc_egl_stream_texture, - g_object_ref (stream), - stream_texture_destroyed, - error); - if (!texture) - { - g_object_unref (stream); - return NULL; - } - - if (!cogl_texture_allocate (COGL_TEXTURE (texture), error)) - { - cogl_object_unref (texture); - return NULL; - } - - stream->texture = texture; - stream->is_y_inverted = !!y_inverted; - - return texture; -} - -gboolean -meta_wayland_egl_stream_attach (MetaWaylandEglStream *stream, - GError **error) -{ - MetaBackend *backend = meta_get_backend (); - MetaEgl *egl = meta_backend_get_egl (backend); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); - EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context); - EGLint stream_state; - - if (!meta_egl_query_stream (egl, egl_display, stream->egl_stream, - EGL_STREAM_STATE_KHR, &stream_state, - error)) - return FALSE; - - if (stream_state == EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR) - { - if (!meta_egl_stream_consumer_acquire (egl, egl_display, - stream->egl_stream, - error)) - return FALSE; - } - - return TRUE; -} - -gboolean -meta_wayland_egl_stream_is_y_inverted (MetaWaylandEglStream *stream) -{ - return stream->is_y_inverted; -} - -CoglSnippet * -meta_wayland_egl_stream_create_snippet (MetaWaylandEglStream *stream) -{ - if (!stream->snippet) - { - CoglSnippet *snippet; - - snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_LOOKUP, - "uniform samplerExternalOES tex_external;", - NULL); - cogl_snippet_set_replace (snippet, - "cogl_texel = texture2D (tex_external,\n" - " cogl_tex_coord.xy);"); - stream->snippet = snippet; - } - - return cogl_object_ref (stream->snippet); -} - -gboolean -meta_wayland_is_egl_stream_buffer (MetaWaylandBuffer *buffer) -{ - MetaBackend *backend = meta_get_backend (); - MetaEgl *egl = meta_backend_get_egl (backend); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); - EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context); - int stream_fd; - - if (!meta_egl_has_extensions (egl, egl_display, NULL, - "EGL_KHR_stream_consumer_gltexture", - "EGL_KHR_stream_cross_process_fd", - NULL)) - return FALSE; - - if (!meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource, - EGL_WAYLAND_BUFFER_WL, &stream_fd, - NULL)) - return FALSE; - - return TRUE; -} - -static void -meta_wayland_egl_stream_finalize (GObject *object) -{ - MetaWaylandEglStream *stream = META_WAYLAND_EGL_STREAM (object); - MetaBackend *backend = meta_get_backend (); - MetaEgl *egl = meta_backend_get_egl (backend); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); - EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context); - - g_assert (!stream->texture); - - meta_egl_destroy_stream (egl, egl_display, stream->egl_stream, NULL); - - cogl_clear_object (&stream->snippet); - - G_OBJECT_CLASS (meta_wayland_egl_stream_parent_class)->finalize (object); -} - -static void -meta_wayland_egl_stream_init (MetaWaylandEglStream *stream) -{ -} - -static void -meta_wayland_egl_stream_class_init (MetaWaylandEglStreamClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_wayland_egl_stream_finalize; -} diff --git a/src/wayland/meta-wayland-egl-stream.h b/src/wayland/meta-wayland-egl-stream.h deleted file mode 100644 index b8a6b1968..000000000 --- a/src/wayland/meta-wayland-egl-stream.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#ifndef META_WAYLAND_EGL_STREAM_H -#define META_WAYLAND_EGL_STREAM_H - -#include -#include - -#include "cogl/cogl.h" -#include "wayland/meta-wayland-types.h" - -gboolean meta_wayland_eglstream_controller_init (MetaWaylandCompositor *compositor); - -#define META_TYPE_WAYLAND_EGL_STREAM (meta_wayland_egl_stream_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandEglStream, meta_wayland_egl_stream, - META, WAYLAND_EGL_STREAM, GObject); - -gboolean meta_wayland_is_egl_stream_buffer (MetaWaylandBuffer *buffer); - -MetaWaylandEglStream * meta_wayland_egl_stream_new (MetaWaylandBuffer *buffer, - GError **error); - -gboolean meta_wayland_egl_stream_attach (MetaWaylandEglStream *stream, - GError **error); - -CoglTexture2D * meta_wayland_egl_stream_create_texture (MetaWaylandEglStream *stream, - GError **error); -CoglSnippet * meta_wayland_egl_stream_create_snippet (MetaWaylandEglStream *stream); - -gboolean meta_wayland_egl_stream_is_y_inverted (MetaWaylandEglStream *stream); - -#endif /* META_WAYLAND_EGL_STREAM_H */ diff --git a/src/wayland/meta-wayland-gtk-shell.c b/src/wayland/meta-wayland-gtk-shell.c deleted file mode 100644 index 12e1b0e4a..000000000 --- a/src/wayland/meta-wayland-gtk-shell.c +++ /dev/null @@ -1,565 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2012,2013 Intel Corporation - * 2013-2016 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include "config.h" - -#include "wayland/meta-wayland-gtk-shell.h" - -#include "core/bell.h" -#include "core/window-private.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-surface.h" -#include "wayland/meta-wayland-versions.h" -#include "wayland/meta-window-wayland.h" - -#include "gtk-shell-server-protocol.h" - -static GQuark quark_gtk_surface_data = 0; - -typedef struct _MetaWaylandGtkSurface -{ - struct wl_resource *resource; - MetaWaylandSurface *surface; - gboolean is_modal; - gulong configure_handler_id; -} MetaWaylandGtkSurface; - -struct _MetaWaylandGtkShell -{ - GObject parent; - - GList *shell_resources; - uint32_t capabilities; -}; - -G_DEFINE_TYPE (MetaWaylandGtkShell, meta_wayland_gtk_shell, G_TYPE_OBJECT) - -static void -gtk_surface_destructor (struct wl_resource *resource) -{ - MetaWaylandGtkSurface *gtk_surface = wl_resource_get_user_data (resource); - - if (gtk_surface->surface) - { - g_object_steal_qdata (G_OBJECT (gtk_surface->surface), - quark_gtk_surface_data); - g_clear_signal_handler (>k_surface->configure_handler_id, - gtk_surface->surface); - } - - g_free (gtk_surface); -} - -static void -gtk_surface_set_dbus_properties (struct wl_client *client, - struct wl_resource *resource, - const char *application_id, - const char *app_menu_path, - const char *menubar_path, - const char *window_object_path, - const char *application_object_path, - const char *unique_bus_name) -{ - MetaWaylandGtkSurface *gtk_surface = wl_resource_get_user_data (resource); - MetaWaylandSurface *surface = gtk_surface->surface; - MetaWindow *window; - - if (!surface) - return; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - meta_window_set_gtk_dbus_properties (window, - application_id, - unique_bus_name, - app_menu_path, - menubar_path, - application_object_path, - window_object_path); -} - -static void -gtk_surface_set_modal (struct wl_client *client, - struct wl_resource *resource) -{ - MetaWaylandGtkSurface *gtk_surface = wl_resource_get_user_data (resource); - MetaWaylandSurface *surface = gtk_surface->surface; - MetaWindow *window; - - if (!surface) - return; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - if (gtk_surface->is_modal) - return; - - gtk_surface->is_modal = TRUE; - meta_window_set_type (window, META_WINDOW_MODAL_DIALOG); -} - -static void -gtk_surface_unset_modal (struct wl_client *client, - struct wl_resource *resource) -{ - MetaWaylandGtkSurface *gtk_surface = wl_resource_get_user_data (resource); - MetaWaylandSurface *surface = gtk_surface->surface; - MetaWindow *window; - - if (!surface) - return; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - if (!gtk_surface->is_modal) - return; - - gtk_surface->is_modal = FALSE; - meta_window_set_type (window, META_WINDOW_NORMAL); -} - -static void -gtk_surface_present (struct wl_client *client, - struct wl_resource *resource, - uint32_t timestamp) -{ - MetaWaylandGtkSurface *gtk_surface = wl_resource_get_user_data (resource); - MetaWaylandSurface *surface = gtk_surface->surface; - MetaWindow *window; - - if (!surface) - return; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - meta_window_activate_full (window, timestamp, - META_CLIENT_TYPE_APPLICATION, NULL); -} - -static void -gtk_surface_request_focus (struct wl_client *client, - struct wl_resource *resource, - const char *startup_id) -{ - MetaWaylandGtkSurface *gtk_surface = wl_resource_get_user_data (resource); - MetaWaylandSurface *surface = gtk_surface->surface; - MetaDisplay *display = meta_get_display (); - MetaStartupSequence *sequence = NULL; - MetaWindow *window; - - if (!surface) - return; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - if (startup_id) - sequence = meta_startup_notification_lookup_sequence (display->startup_notification, - startup_id); - - if (sequence) - { - uint32_t timestamp; - int32_t workspace_idx; - - workspace_idx = meta_startup_sequence_get_workspace (sequence); - timestamp = meta_startup_sequence_get_timestamp (sequence); - - meta_startup_sequence_complete (sequence); - meta_startup_notification_remove_sequence (display->startup_notification, - sequence); - if (workspace_idx >= 0) - meta_window_change_workspace_by_index (window, workspace_idx, TRUE); - - meta_window_activate_full (window, timestamp, - META_CLIENT_TYPE_APPLICATION, NULL); - } - else - { - meta_window_set_demands_attention (window); - } -} - -static void -gtk_surface_release (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static const struct gtk_surface1_interface meta_wayland_gtk_surface_interface = { - gtk_surface_set_dbus_properties, - gtk_surface_set_modal, - gtk_surface_unset_modal, - gtk_surface_present, - gtk_surface_request_focus, - gtk_surface_release -}; - -static void -gtk_surface_surface_destroyed (MetaWaylandGtkSurface *gtk_surface) -{ - gtk_surface->surface = NULL; -} - -static void -fill_edge_states (struct wl_array *states, - MetaWindow *window) -{ - uint32_t *s; - - if (window->edge_constraints.top != META_EDGE_CONSTRAINT_MONITOR) - { - s = wl_array_add (states, sizeof *s); - *s = GTK_SURFACE1_EDGE_CONSTRAINT_RESIZABLE_TOP; - } - - if (window->edge_constraints.right != META_EDGE_CONSTRAINT_MONITOR) - { - s = wl_array_add (states, sizeof *s); - *s = GTK_SURFACE1_EDGE_CONSTRAINT_RESIZABLE_RIGHT; - } - - if (window->edge_constraints.bottom != META_EDGE_CONSTRAINT_MONITOR) - { - s = wl_array_add (states, sizeof *s); - *s = GTK_SURFACE1_EDGE_CONSTRAINT_RESIZABLE_BOTTOM; - } - - if (window->edge_constraints.left != META_EDGE_CONSTRAINT_MONITOR) - { - s = wl_array_add (states, sizeof *s); - *s = GTK_SURFACE1_EDGE_CONSTRAINT_RESIZABLE_LEFT; - } -} - -static void -send_configure_edges (MetaWaylandGtkSurface *gtk_surface, - MetaWindow *window) -{ - struct wl_array edge_states; - - wl_array_init (&edge_states); - fill_edge_states (&edge_states, window); - - gtk_surface1_send_configure_edges (gtk_surface->resource, &edge_states); - - wl_array_release (&edge_states); -} - -static void -add_state_value (struct wl_array *states, - enum gtk_surface1_state state) -{ - uint32_t *s; - - s = wl_array_add (states, sizeof *s); - *s = state; -} - -static void -fill_states (struct wl_array *states, - MetaWindow *window, - struct wl_resource *resource) -{ - int version; - - version = wl_resource_get_version (resource); - - if (version < GTK_SURFACE1_CONFIGURE_EDGES_SINCE_VERSION && - (window->tile_mode == META_TILE_LEFT || - window->tile_mode == META_TILE_RIGHT)) - add_state_value (states, GTK_SURFACE1_STATE_TILED); - - if (version >= GTK_SURFACE1_STATE_TILED_TOP_SINCE_VERSION && - window->edge_constraints.top != META_EDGE_CONSTRAINT_NONE) - add_state_value (states, GTK_SURFACE1_STATE_TILED_TOP); - - if (version >= GTK_SURFACE1_STATE_TILED_RIGHT_SINCE_VERSION && - window->edge_constraints.right != META_EDGE_CONSTRAINT_NONE) - add_state_value (states, GTK_SURFACE1_STATE_TILED_RIGHT); - - if (version >= GTK_SURFACE1_STATE_TILED_BOTTOM_SINCE_VERSION && - window->edge_constraints.bottom != META_EDGE_CONSTRAINT_NONE) - add_state_value (states, GTK_SURFACE1_STATE_TILED_BOTTOM); - - if (version >= GTK_SURFACE1_STATE_TILED_LEFT_SINCE_VERSION && - window->edge_constraints.left != META_EDGE_CONSTRAINT_NONE) - add_state_value (states, GTK_SURFACE1_STATE_TILED_LEFT); -} - -static void -send_configure (MetaWaylandGtkSurface *gtk_surface, - MetaWindow *window) -{ - struct wl_array states; - - wl_array_init (&states); - fill_states (&states, window, gtk_surface->resource); - - gtk_surface1_send_configure (gtk_surface->resource, &states); - - wl_array_release (&states); -} - -static void -on_configure (MetaWaylandSurface *surface, - MetaWaylandGtkSurface *gtk_surface) -{ - MetaWindow *window; - - window = meta_wayland_surface_get_window (surface); - send_configure (gtk_surface, window); - - if (wl_resource_get_version (gtk_surface->resource) >= - GTK_SURFACE1_CONFIGURE_EDGES_SINCE_VERSION) - send_configure_edges (gtk_surface, window); -} - -static void -gtk_shell_get_gtk_surface (struct wl_client *client, - struct wl_resource *resource, - guint32 id, - struct wl_resource *surface_resource) -{ - MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); - MetaWaylandGtkSurface *gtk_surface; - - gtk_surface = g_object_get_qdata (G_OBJECT (surface), quark_gtk_surface_data); - if (gtk_surface) - { - wl_resource_post_error (surface_resource, - WL_DISPLAY_ERROR_INVALID_OBJECT, - "gtk_shell::get_gtk_surface already requested"); - return; - } - - gtk_surface = g_new0 (MetaWaylandGtkSurface, 1); - gtk_surface->surface = surface; - gtk_surface->resource = wl_resource_create (client, - >k_surface1_interface, - wl_resource_get_version (resource), - id); - wl_resource_set_implementation (gtk_surface->resource, - &meta_wayland_gtk_surface_interface, - gtk_surface, gtk_surface_destructor); - - gtk_surface->configure_handler_id = g_signal_connect (surface, - "configure", - G_CALLBACK (on_configure), - gtk_surface); - - g_object_set_qdata_full (G_OBJECT (surface), - quark_gtk_surface_data, - gtk_surface, - (GDestroyNotify) gtk_surface_surface_destroyed); -} - -static void -gtk_shell_set_startup_id (struct wl_client *client, - struct wl_resource *resource, - const char *startup_id) -{ - MetaStartupSequence *sequence; - MetaDisplay *display; - - display = meta_get_display (); - - sequence = meta_startup_notification_lookup_sequence (display->startup_notification, - startup_id); - if (sequence) - meta_startup_sequence_complete (sequence); -} - -static void -gtk_shell_system_bell (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *gtk_surface_resource) -{ - MetaDisplay *display = meta_get_display (); - - if (gtk_surface_resource) - { - MetaWaylandGtkSurface *gtk_surface = - wl_resource_get_user_data (gtk_surface_resource); - MetaWaylandSurface *surface = gtk_surface->surface; - MetaWindow *window; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - meta_bell_notify (display, window); - } - else - { - meta_bell_notify (display, NULL); - } -} - -static void -gtk_shell_notify_launch (struct wl_client *client, - struct wl_resource *resource, - const char *startup_id) -{ - MetaDisplay *display = meta_get_display (); - MetaStartupSequence *sequence; - uint32_t timestamp; - - sequence = meta_startup_notification_lookup_sequence (display->startup_notification, - startup_id); - if (sequence) - { - g_warning ("Naughty client notified launch with duplicate startup_id '%s'", - startup_id); - return; - } - - timestamp = meta_display_get_current_time_roundtrip (display); - sequence = g_object_new (META_TYPE_STARTUP_SEQUENCE, - "id", startup_id, - "timestamp", timestamp, - NULL); - - meta_startup_notification_add_sequence (display->startup_notification, - sequence); - g_object_unref (sequence); -} - -static const struct gtk_shell1_interface meta_wayland_gtk_shell_interface = { - gtk_shell_get_gtk_surface, - gtk_shell_set_startup_id, - gtk_shell_system_bell, - gtk_shell_notify_launch, -}; - -static void -gtk_shell_destructor (struct wl_resource *resource) -{ - MetaWaylandGtkShell *gtk_shell = wl_resource_get_user_data (resource); - - gtk_shell->shell_resources = g_list_remove (gtk_shell->shell_resources, - resource); -} - -static void -bind_gtk_shell (struct wl_client *client, - void *data, - guint32 version, - guint32 id) -{ - MetaWaylandGtkShell *gtk_shell = data; - struct wl_resource *resource; - - resource = wl_resource_create (client, >k_shell1_interface, version, id); - wl_resource_set_implementation (resource, &meta_wayland_gtk_shell_interface, - data, gtk_shell_destructor); - - gtk_shell->shell_resources = g_list_prepend (gtk_shell->shell_resources, - resource); - - gtk_shell1_send_capabilities (resource, gtk_shell->capabilities); -} - -static void -meta_wayland_gtk_shell_init (MetaWaylandGtkShell *gtk_shell) -{ -} - -static void -meta_wayland_gtk_shell_class_init (MetaWaylandGtkShellClass *klass) -{ - quark_gtk_surface_data = - g_quark_from_static_string ("-meta-wayland-gtk-shell-surface-data"); -} - -static uint32_t -calculate_capabilities (void) -{ - uint32_t capabilities = 0; - - if (!meta_prefs_get_show_fallback_app_menu ()) - capabilities = GTK_SHELL1_CAPABILITY_GLOBAL_APP_MENU; - - return capabilities; -} - -static void -prefs_changed (MetaPreference pref, - gpointer user_data) -{ - MetaWaylandGtkShell *gtk_shell = user_data; - uint32_t new_capabilities; - GList *l; - - if (pref != META_PREF_BUTTON_LAYOUT) - return; - - new_capabilities = calculate_capabilities (); - if (gtk_shell->capabilities == new_capabilities) - return; - gtk_shell->capabilities = new_capabilities; - - for (l = gtk_shell->shell_resources; l; l = l->next) - { - struct wl_resource *resource = l->data; - - gtk_shell1_send_capabilities (resource, gtk_shell->capabilities); - } -} - -static MetaWaylandGtkShell * -meta_wayland_gtk_shell_new (MetaWaylandCompositor *compositor) -{ - MetaWaylandGtkShell *gtk_shell; - - gtk_shell = g_object_new (META_TYPE_WAYLAND_GTK_SHELL, NULL); - - if (wl_global_create (compositor->wayland_display, - >k_shell1_interface, - META_GTK_SHELL1_VERSION, - gtk_shell, bind_gtk_shell) == NULL) - g_error ("Failed to register a global gtk-shell object"); - - gtk_shell->capabilities = calculate_capabilities (); - - meta_prefs_add_listener (prefs_changed, gtk_shell); - - return gtk_shell; -} - -void -meta_wayland_init_gtk_shell (MetaWaylandCompositor *compositor) -{ - g_object_set_data_full (G_OBJECT (compositor), "-meta-wayland-gtk-shell", - meta_wayland_gtk_shell_new (compositor), - g_object_unref); -} diff --git a/src/wayland/meta-wayland-gtk-shell.h b/src/wayland/meta-wayland-gtk-shell.h deleted file mode 100644 index 347c1f398..000000000 --- a/src/wayland/meta-wayland-gtk-shell.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2016 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_WAYLAND_GTK_SHELL_H -#define META_WAYLAND_GTK_SHELL_H - -#include "wayland/meta-wayland.h" - -#define META_TYPE_WAYLAND_GTK_SHELL (meta_wayland_gtk_shell_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandGtkShell, meta_wayland_gtk_shell, - META, WAYLAND_GTK_SHELL, GObject) - -void meta_wayland_init_gtk_shell (MetaWaylandCompositor *compositor); - -#endif /* META_WAYLAND_GTK_SHELL_H */ diff --git a/src/wayland/meta-wayland-inhibit-shortcuts-dialog.c b/src/wayland/meta-wayland-inhibit-shortcuts-dialog.c deleted file mode 100644 index 818098460..000000000 --- a/src/wayland/meta-wayland-inhibit-shortcuts-dialog.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (C) 2017 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, see . - */ - -#include "config.h" - -#include "compositor/compositor-private.h" -#include "core/window-private.h" -#include "wayland/meta-wayland-inhibit-shortcuts-dialog.h" -#include "wayland/meta-wayland.h" -#include "wayland/meta-window-wayland.h" - -static GQuark quark_surface_inhibit_shortcuts_data = 0; - -typedef struct _InhibitShortcutsData -{ - MetaWaylandSurface *surface; - MetaWaylandSeat *seat; - MetaInhibitShortcutsDialog *dialog; - gulong response_handler_id; - gboolean has_last_response; - gboolean request_canceled; - MetaInhibitShortcutsDialogResponse last_response; -} InhibitShortcutsData; - -static InhibitShortcutsData * -surface_inhibit_shortcuts_data_get (MetaWaylandSurface *surface) -{ - return g_object_get_qdata (G_OBJECT (surface), - quark_surface_inhibit_shortcuts_data); -} - -static void -surface_inhibit_shortcuts_data_set (MetaWaylandSurface *surface, - InhibitShortcutsData *data) -{ - g_object_set_qdata (G_OBJECT (surface), - quark_surface_inhibit_shortcuts_data, - data); -} - -static void -surface_inhibit_shortcuts_data_destroy_dialog (InhibitShortcutsData *data) -{ - g_clear_signal_handler (&data->response_handler_id, data->dialog); - meta_inhibit_shortcuts_dialog_hide (data->dialog); - g_clear_object (&data->dialog); -} - -static void -surface_inhibit_shortcuts_data_free (InhibitShortcutsData *data) -{ - if (data->dialog) - surface_inhibit_shortcuts_data_destroy_dialog (data); - g_free (data); -} - -static void -on_surface_destroyed (MetaWaylandSurface *surface, - InhibitShortcutsData *data) -{ - surface_inhibit_shortcuts_data_free (data); - g_object_set_qdata (G_OBJECT (surface), - quark_surface_inhibit_shortcuts_data, - NULL); -} - -static void -inhibit_shortcuts_dialog_response_apply (InhibitShortcutsData *data) -{ - if (data->last_response == META_INHIBIT_SHORTCUTS_DIALOG_RESPONSE_ALLOW) - meta_wayland_surface_inhibit_shortcuts (data->surface, data->seat); - else if (meta_wayland_surface_is_shortcuts_inhibited (data->surface, data->seat)) - meta_wayland_surface_restore_shortcuts (data->surface, data->seat); -} - -static void -inhibit_shortcuts_dialog_response_cb (MetaInhibitShortcutsDialog *dialog, - MetaInhibitShortcutsDialogResponse response, - InhibitShortcutsData *data) -{ - data->last_response = response; - data->has_last_response = TRUE; - - /* If the request was canceled, we don't need to apply the choice made */ - if (!data->request_canceled) - inhibit_shortcuts_dialog_response_apply (data); - - meta_inhibit_shortcuts_dialog_hide (data->dialog); - surface_inhibit_shortcuts_data_destroy_dialog (data); -} - -static InhibitShortcutsData * -meta_wayland_surface_ensure_inhibit_shortcuts_dialog (MetaWaylandSurface *surface, - MetaWaylandSeat *seat) -{ - InhibitShortcutsData *data; - MetaWindow *window; - MetaDisplay *display; - MetaInhibitShortcutsDialog *dialog; - - data = surface_inhibit_shortcuts_data_get (surface); - if (data) - return data; - - data = g_new0 (InhibitShortcutsData, 1); - surface_inhibit_shortcuts_data_set (surface, data); - g_signal_connect (surface, "destroy", - G_CALLBACK (on_surface_destroyed), - data); - - window = meta_wayland_surface_get_toplevel_window (surface); - display = window->display; - dialog = - meta_compositor_create_inhibit_shortcuts_dialog (display->compositor, - window); - - data->surface = surface; - data->seat = seat; - data->dialog = dialog; - data->response_handler_id = - g_signal_connect (dialog, "response", - G_CALLBACK (inhibit_shortcuts_dialog_response_cb), - data); - - return data; -} - -void -meta_wayland_surface_show_inhibit_shortcuts_dialog (MetaWaylandSurface *surface, - MetaWaylandSeat *seat) -{ - InhibitShortcutsData *data; - - g_return_if_fail (META_IS_WAYLAND_SURFACE (surface)); - - data = surface_inhibit_shortcuts_data_get (surface); - if (data && data->has_last_response) - { - /* The dialog was shown before for this surface but is not showing - * anymore, reuse the last user response. - */ - inhibit_shortcuts_dialog_response_apply (data); - return; - } - - data = meta_wayland_surface_ensure_inhibit_shortcuts_dialog (surface, seat); - /* This is a new request */ - data->request_canceled = FALSE; - - meta_inhibit_shortcuts_dialog_show (data->dialog); -} - -void -meta_wayland_surface_cancel_inhibit_shortcuts_dialog (MetaWaylandSurface *surface) -{ - InhibitShortcutsData *data; - - g_return_if_fail (META_IS_WAYLAND_SURFACE (surface)); - - /* The closure notify will take care of actually hiding the dialog */ - data = surface_inhibit_shortcuts_data_get (surface); - g_return_if_fail (data); - - /* Keep the dialog on screen, but mark the request as canceled */ - data->request_canceled = TRUE; -} - -void -meta_wayland_surface_inhibit_shortcuts_dialog_init (void) -{ - quark_surface_inhibit_shortcuts_data = - g_quark_from_static_string ("-meta-wayland-surface-inhibit-shortcuts-data"); -} diff --git a/src/wayland/meta-wayland-inhibit-shortcuts-dialog.h b/src/wayland/meta-wayland-inhibit-shortcuts-dialog.h deleted file mode 100644 index 7f3501565..000000000 --- a/src/wayland/meta-wayland-inhibit-shortcuts-dialog.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2017 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, see . - * - */ - -#ifndef META_WAYLAND_INHIBIT_SHORTCUTS_DIALOG_H -#define META_WAYLAND_INHIBIT_SHORTCUTS_DIALOG_H - -#include "wayland/meta-wayland-private.h" - -void meta_wayland_surface_show_inhibit_shortcuts_dialog (MetaWaylandSurface *surface, - MetaWaylandSeat *seat); - -void meta_wayland_surface_cancel_inhibit_shortcuts_dialog (MetaWaylandSurface *surface); - -void meta_wayland_surface_inhibit_shortcuts_dialog_init (void); - -#endif /* META_WAYLAND_INHIBIT_SHORTCUTS_DIALOG_H */ diff --git a/src/wayland/meta-wayland-inhibit-shortcuts.c b/src/wayland/meta-wayland-inhibit-shortcuts.c deleted file mode 100644 index 68e90eec2..000000000 --- a/src/wayland/meta-wayland-inhibit-shortcuts.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (C) 2017 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Olivier Fourdan - */ - -#include "config.h" - -#include - -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-versions.h" -#include "wayland/meta-wayland-inhibit-shortcuts.h" -#include "wayland/meta-wayland-inhibit-shortcuts-dialog.h" - -#include "keyboard-shortcuts-inhibit-unstable-v1-server-protocol.h" - -struct _MetaWaylandKeyboardShotscutsInhibit -{ - MetaWaylandSurface *surface; - MetaWaylandSeat *seat; - gulong inhibit_shortcut_handler; - gulong restore_shortcut_handler; - gulong surface_destroyed_handler; - struct wl_resource *resource; -}; - -static void -zwp_keyboard_shortcuts_inhibit_destructor (struct wl_resource *resource) -{ - MetaWaylandKeyboardShotscutsInhibit *shortcut_inhibit; - - shortcut_inhibit = wl_resource_get_user_data (resource); - if (shortcut_inhibit->surface) - { - meta_wayland_surface_cancel_inhibit_shortcuts_dialog (shortcut_inhibit->surface); - - g_clear_signal_handler (&shortcut_inhibit->surface_destroyed_handler, - shortcut_inhibit->surface); - - g_clear_signal_handler (&shortcut_inhibit->inhibit_shortcut_handler, - shortcut_inhibit->surface); - - g_clear_signal_handler (&shortcut_inhibit->restore_shortcut_handler, - shortcut_inhibit->surface); - - meta_wayland_surface_restore_shortcuts (shortcut_inhibit->surface, - shortcut_inhibit->seat); - } - g_free (shortcut_inhibit); -} - -static void -zwp_keyboard_shortcuts_inhibit_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static const struct zwp_keyboard_shortcuts_inhibit_manager_v1_interface - meta_keyboard_shortcuts_inhibit_interface = { - zwp_keyboard_shortcuts_inhibit_destroy, - }; - -static void -surface_destroyed_cb (MetaWaylandSurface *surface, - MetaWaylandKeyboardShotscutsInhibit *shortcut_inhibit) -{ - shortcut_inhibit->surface = NULL; - shortcut_inhibit->seat = NULL; -} - -static void -shortcuts_inhibited_cb (MetaWaylandSurface *surface, - MetaWaylandKeyboardShotscutsInhibit *shortcut_inhibit) -{ - zwp_keyboard_shortcuts_inhibitor_v1_send_active (shortcut_inhibit->resource); -} - -static void -shortcuts_restored_cb (MetaWaylandSurface *surface, - MetaWaylandKeyboardShotscutsInhibit *shortcut_inhibit) -{ - zwp_keyboard_shortcuts_inhibitor_v1_send_inactive (shortcut_inhibit->resource); -} - -static void -zwp_keyboard_shortcuts_inhibit_manager_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -zwp_keyboard_shortcuts_inhibit_manager_inhibit_shortcuts (struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *surface_resource, - struct wl_resource *seat_resource) -{ - MetaWaylandKeyboardShotscutsInhibit *shortcut_inhibit; - MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); - MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); - struct wl_resource *keyboard_shortcuts_inhibit_resource; - - keyboard_shortcuts_inhibit_resource = - wl_resource_create (client, - &zwp_keyboard_shortcuts_inhibitor_v1_interface, - META_ZWP_KEYBOARD_SHORTCUTS_INHIBIT_V1_VERSION, - id); - - shortcut_inhibit = g_new0 (MetaWaylandKeyboardShotscutsInhibit, 1); - shortcut_inhibit->surface = surface; - shortcut_inhibit->seat = seat; - shortcut_inhibit->resource = keyboard_shortcuts_inhibit_resource; - - shortcut_inhibit->inhibit_shortcut_handler = - g_signal_connect (surface, "shortcuts-inhibited", - G_CALLBACK (shortcuts_inhibited_cb), - shortcut_inhibit); - shortcut_inhibit->restore_shortcut_handler = - g_signal_connect (surface, "shortcuts-restored", - G_CALLBACK (shortcuts_restored_cb), - shortcut_inhibit); - shortcut_inhibit->surface_destroyed_handler = - g_signal_connect (surface, "destroy", - G_CALLBACK (surface_destroyed_cb), - shortcut_inhibit); - - /* Cannot grant shortcuts to a surface without any window */ - if (meta_wayland_surface_get_toplevel_window (surface)) - meta_wayland_surface_show_inhibit_shortcuts_dialog (surface, seat); - - wl_resource_set_implementation (keyboard_shortcuts_inhibit_resource, - &meta_keyboard_shortcuts_inhibit_interface, - shortcut_inhibit, - zwp_keyboard_shortcuts_inhibit_destructor); -} - -static const struct zwp_keyboard_shortcuts_inhibit_manager_v1_interface - meta_keyboard_shortcuts_inhibit_manager_interface = { - zwp_keyboard_shortcuts_inhibit_manager_destroy, - zwp_keyboard_shortcuts_inhibit_manager_inhibit_shortcuts, - }; - -static void -bind_keyboard_shortcuts_inhibit (struct wl_client *client, - void *data, - uint32_t version, - uint32_t id) -{ - struct wl_resource *resource; - - resource = wl_resource_create (client, - &zwp_keyboard_shortcuts_inhibit_manager_v1_interface, - META_ZWP_KEYBOARD_SHORTCUTS_INHIBIT_V1_VERSION, - id); - - wl_resource_set_implementation (resource, - &meta_keyboard_shortcuts_inhibit_manager_interface, - NULL, NULL); -} - -gboolean -meta_wayland_keyboard_shortcuts_inhibit_init (MetaWaylandCompositor *compositor) -{ - return (wl_global_create (compositor->wayland_display, - &zwp_keyboard_shortcuts_inhibit_manager_v1_interface, - META_ZWP_KEYBOARD_SHORTCUTS_INHIBIT_V1_VERSION, - NULL, - bind_keyboard_shortcuts_inhibit) != NULL); -} diff --git a/src/wayland/meta-wayland-inhibit-shortcuts.h b/src/wayland/meta-wayland-inhibit-shortcuts.h deleted file mode 100644 index 52b2240c4..000000000 --- a/src/wayland/meta-wayland-inhibit-shortcuts.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2017 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Olivier Fourdan - */ - -#ifndef META_WAYLAND_INHIBIT_SHORTCUTS_H -#define META_WAYLAND_INHIBIT_SHORTCUTS_H - -#include - -#include "meta/window.h" -#include "wayland/meta-wayland-types.h" - -#define META_TYPE_WAYLAND_KEYBOARD_SHORTCUTS_INHIBIT (meta_wayland_keyboard_shortcuts_inhibit_resource_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandKeyboardShotscutsInhibit, - meta_wayland_keyboard_shortcuts_inhibit_resource, - META, WAYLAND_KEYBOARD_SHORTCUTS_INHIBIT, - GObject); - -gboolean meta_wayland_keyboard_shortcuts_inhibit_init (MetaWaylandCompositor *compositor); - -#endif /* META_WAYLAND_INHIBIT_SHORTCUTS_H */ diff --git a/src/wayland/meta-wayland-input-device.c b/src/wayland/meta-wayland-input-device.c deleted file mode 100644 index b82f204cf..000000000 --- a/src/wayland/meta-wayland-input-device.c +++ /dev/null @@ -1,129 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#include "config.h" - -#include "wayland/meta-wayland-input-device.h" - -#include - -#include "wayland/meta-wayland-seat.h" - -enum -{ - PROP_0, - - PROP_SEAT -}; - -typedef struct _MetaWaylandInputDevicePrivate -{ - MetaWaylandSeat *seat; -} MetaWaylandInputDevicePrivate; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandInputDevice, - meta_wayland_input_device, - G_TYPE_OBJECT) - -MetaWaylandSeat * -meta_wayland_input_device_get_seat (MetaWaylandInputDevice *input_device) -{ - MetaWaylandInputDevicePrivate *priv = - meta_wayland_input_device_get_instance_private (input_device); - - return priv->seat; -} - -uint32_t -meta_wayland_input_device_next_serial (MetaWaylandInputDevice *input_device) -{ - MetaWaylandSeat *seat = meta_wayland_input_device_get_seat (input_device); - - return wl_display_next_serial (seat->wl_display); -} - -static void -meta_wayland_input_device_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaWaylandInputDevice *input_device = META_WAYLAND_INPUT_DEVICE (object); - MetaWaylandInputDevicePrivate *priv = - meta_wayland_input_device_get_instance_private (input_device); - - switch (prop_id) - { - case PROP_SEAT: - priv->seat = g_value_get_pointer (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_wayland_input_device_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaWaylandInputDevice *input_device = META_WAYLAND_INPUT_DEVICE (object); - MetaWaylandInputDevicePrivate *priv = - meta_wayland_input_device_get_instance_private (input_device); - - switch (prop_id) - { - case PROP_SEAT: - g_value_set_pointer (value, priv->seat); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_wayland_input_device_init (MetaWaylandInputDevice *input_device) -{ -} - -static void -meta_wayland_input_device_class_init (MetaWaylandInputDeviceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GParamSpec *pspec; - - object_class->set_property = meta_wayland_input_device_set_property; - object_class->get_property = meta_wayland_input_device_get_property; - - pspec = g_param_spec_pointer ("seat", - "MetaWaylandSeat", - "The seat", - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS | - G_PARAM_CONSTRUCT_ONLY); - g_object_class_install_property (object_class, PROP_SEAT, pspec); -} diff --git a/src/wayland/meta-wayland-input-device.h b/src/wayland/meta-wayland-input-device.h deleted file mode 100644 index c6a6c3d38..000000000 --- a/src/wayland/meta-wayland-input-device.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2016 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#ifndef META_WAYLAND_INPUT_DEVICE_H -#define META_WAYLAND_INPUT_DEVICE_H - -#include -#include - -#include "wayland/meta-wayland-types.h" - -#define META_TYPE_WAYLAND_INPUT_DEVICE (meta_wayland_input_device_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaWaylandInputDevice, - meta_wayland_input_device, - META, WAYLAND_INPUT_DEVICE, - GObject) - -struct _MetaWaylandInputDeviceClass -{ - GObjectClass parent_class; -}; - -MetaWaylandSeat * meta_wayland_input_device_get_seat (MetaWaylandInputDevice *input_device); - -uint32_t meta_wayland_input_device_next_serial (MetaWaylandInputDevice *input_device); - -#endif /* META_WAYLAND_INPUT_DEVICE_H */ diff --git a/src/wayland/meta-wayland-keyboard.c b/src/wayland/meta-wayland-keyboard.c deleted file mode 100644 index 836939c9d..000000000 --- a/src/wayland/meta-wayland-keyboard.c +++ /dev/null @@ -1,873 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2013 Intel Corporation - * - * 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. - */ - -/* - * Copyright © 2010-2011 Intel Corporation - * Copyright © 2008-2011 Kristian Høgsberg - * Copyright © 2012 Collabora, Ltd. - * - * Permission to use, copy, modify, distribute, and sell this software and - * its documentation for any purpose is hereby granted without fee, provided - * that the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of the copyright holders not be used in - * advertising or publicity pertaining to distribution of the software - * without specific, written prior permission. The copyright holders make - * no representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF - * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* The file is based on src/input.c from Weston */ - -#include "config.h" - -#include -#include -#include -#include -#include - -#include "backends/meta-backend-private.h" -#include "core/display-private.h" -#include "core/meta-anonymous-file.h" -#include "wayland/meta-wayland-private.h" - -#define GSD_KEYBOARD_SCHEMA "org.gnome.settings-daemon.peripherals.keyboard" - -G_DEFINE_TYPE (MetaWaylandKeyboard, meta_wayland_keyboard, - META_TYPE_WAYLAND_INPUT_DEVICE) - -static void meta_wayland_keyboard_update_xkb_state (MetaWaylandKeyboard *keyboard); -static void notify_modifiers (MetaWaylandKeyboard *keyboard); - -static void -unbind_resource (struct wl_resource *resource) -{ - wl_list_remove (wl_resource_get_link (resource)); -} - -static void -send_keymap (MetaWaylandKeyboard *keyboard, - struct wl_resource *resource) -{ - MetaWaylandXkbInfo *xkb_info = &keyboard->xkb_info; - int fd; - size_t size; - MetaAnonymousFileMapmode mapmode; - - if (wl_resource_get_version (resource) < 7) - mapmode = META_ANONYMOUS_FILE_MAPMODE_SHARED; - else - mapmode = META_ANONYMOUS_FILE_MAPMODE_PRIVATE; - - fd = meta_anonymous_file_open_fd (xkb_info->keymap_rofile, mapmode); - size = meta_anonymous_file_size (xkb_info->keymap_rofile); - - if (fd == -1) - { - g_warning ("Creating a keymap file failed: %s", strerror (errno)); - return; - } - - wl_keyboard_send_keymap (resource, - WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, - fd, size); - - meta_anonymous_file_close_fd (fd); -} - -static void -inform_clients_of_new_keymap (MetaWaylandKeyboard *keyboard) -{ - struct wl_resource *keyboard_resource; - - wl_resource_for_each (keyboard_resource, &keyboard->resource_list) - send_keymap (keyboard, keyboard_resource); - wl_resource_for_each (keyboard_resource, &keyboard->focus_resource_list) - send_keymap (keyboard, keyboard_resource); -} - -static void -meta_wayland_keyboard_take_keymap (MetaWaylandKeyboard *keyboard, - struct xkb_keymap *keymap) -{ - MetaWaylandXkbInfo *xkb_info = &keyboard->xkb_info; - char *keymap_string; - size_t keymap_size; - - if (keymap == NULL) - { - g_warning ("Attempting to set null keymap (compilation probably failed)"); - return; - } - - xkb_keymap_unref (xkb_info->keymap); - xkb_info->keymap = xkb_keymap_ref (keymap); - - meta_wayland_keyboard_update_xkb_state (keyboard); - - keymap_string = - xkb_keymap_get_as_string (xkb_info->keymap, XKB_KEYMAP_FORMAT_TEXT_V1); - if (!keymap_string) - { - g_warning ("Failed to get string version of keymap"); - return; - } - keymap_size = strlen (keymap_string) + 1; - - g_clear_pointer (&xkb_info->keymap_rofile, meta_anonymous_file_free); - xkb_info->keymap_rofile = - meta_anonymous_file_new (keymap_size, (const uint8_t *) keymap_string); - - free (keymap_string); - - if (!xkb_info->keymap_rofile) - { - g_warning ("Failed to create anonymous file for keymap"); - return; - } - - inform_clients_of_new_keymap (keyboard); - - notify_modifiers (keyboard); -} - -static xkb_mod_mask_t -kbd_a11y_apply_mask (MetaWaylandKeyboard *keyboard) -{ - xkb_mod_mask_t latched, locked, depressed, group; - xkb_mod_mask_t update_mask = 0; - - depressed = xkb_state_serialize_mods(keyboard->xkb_info.state, XKB_STATE_DEPRESSED); - latched = xkb_state_serialize_mods (keyboard->xkb_info.state, XKB_STATE_MODS_LATCHED); - locked = xkb_state_serialize_mods (keyboard->xkb_info.state, XKB_STATE_MODS_LOCKED); - group = xkb_state_serialize_layout (keyboard->xkb_info.state, XKB_STATE_LAYOUT_EFFECTIVE); - - if ((latched & keyboard->kbd_a11y_latched_mods) != keyboard->kbd_a11y_latched_mods) - update_mask |= XKB_STATE_MODS_LATCHED; - - if ((locked & keyboard->kbd_a11y_locked_mods) != keyboard->kbd_a11y_locked_mods) - update_mask |= XKB_STATE_MODS_LOCKED; - - if (update_mask) - { - latched |= keyboard->kbd_a11y_latched_mods; - locked |= keyboard->kbd_a11y_locked_mods; - xkb_state_update_mask (keyboard->xkb_info.state, depressed, latched, locked, 0, 0, group); - } - - return update_mask; -} - -static void -on_keymap_changed (MetaBackend *backend, - gpointer data) -{ - MetaWaylandKeyboard *keyboard = data; - - meta_wayland_keyboard_take_keymap (keyboard, meta_backend_get_keymap (backend)); -} - -static void -on_keymap_layout_group_changed (MetaBackend *backend, - guint idx, - gpointer data) -{ - MetaWaylandKeyboard *keyboard = data; - xkb_mod_mask_t depressed_mods; - xkb_mod_mask_t latched_mods; - xkb_mod_mask_t locked_mods; - struct xkb_state *state; - - state = keyboard->xkb_info.state; - - depressed_mods = xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED); - latched_mods = xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED); - locked_mods = xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED); - - xkb_state_update_mask (state, depressed_mods, latched_mods, locked_mods, 0, 0, idx); - kbd_a11y_apply_mask (keyboard); - - notify_modifiers (keyboard); -} - -static void -keyboard_handle_focus_surface_destroy (struct wl_listener *listener, void *data) -{ - MetaWaylandKeyboard *keyboard = wl_container_of (listener, keyboard, - focus_surface_listener); - - meta_wayland_keyboard_set_focus (keyboard, NULL); -} - -static gboolean -meta_wayland_keyboard_broadcast_key (MetaWaylandKeyboard *keyboard, - uint32_t time, - uint32_t key, - uint32_t state) -{ - struct wl_resource *resource; - - if (!wl_list_empty (&keyboard->focus_resource_list)) - { - MetaWaylandInputDevice *input_device = - META_WAYLAND_INPUT_DEVICE (keyboard); - uint32_t serial; - - serial = meta_wayland_input_device_next_serial (input_device); - - if (state) - { - keyboard->key_down_serial = serial; - keyboard->key_down_keycode = key; - } - else - { - keyboard->key_up_serial = serial; - keyboard->key_up_keycode = key; - } - - wl_resource_for_each (resource, &keyboard->focus_resource_list) - wl_keyboard_send_key (resource, serial, time, key, state); - } - - /* Eat the key events if we have a focused surface. */ - return (keyboard->focus_surface != NULL); -} - -static gboolean -notify_key (MetaWaylandKeyboard *keyboard, - const ClutterEvent *event) -{ - return keyboard->grab->interface->key (keyboard->grab, event); -} - -static xkb_mod_mask_t -add_vmod (xkb_mod_mask_t mask, - xkb_mod_mask_t mod, - xkb_mod_mask_t vmod, - xkb_mod_mask_t *added) -{ - if ((mask & mod) && !(mod & *added)) - { - mask |= vmod; - *added |= mod; - } - return mask; -} - -static xkb_mod_mask_t -add_virtual_mods (xkb_mod_mask_t mask) -{ - MetaKeyBindingManager *keys = &(meta_get_display ()->key_binding_manager); - xkb_mod_mask_t added; - guint i; - /* Order is important here: if multiple vmods share the same real - modifier we only want to add the first. */ - struct { - xkb_mod_mask_t mod; - xkb_mod_mask_t vmod; - } mods[] = { - { keys->super_mask, keys->virtual_super_mask }, - { keys->hyper_mask, keys->virtual_hyper_mask }, - { keys->meta_mask, keys->virtual_meta_mask }, - }; - - added = 0; - for (i = 0; i < G_N_ELEMENTS (mods); ++i) - mask = add_vmod (mask, mods[i].mod, mods[i].vmod, &added); - - return mask; -} - -static void -keyboard_send_modifiers (MetaWaylandKeyboard *keyboard, - struct wl_resource *resource, - uint32_t serial) -{ - struct xkb_state *state = keyboard->xkb_info.state; - xkb_mod_mask_t depressed, latched, locked; - - depressed = add_virtual_mods (xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED)); - latched = add_virtual_mods (xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED)); - locked = add_virtual_mods (xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED)); - - wl_keyboard_send_modifiers (resource, serial, depressed, latched, locked, - xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE)); -} - -static void -meta_wayland_keyboard_broadcast_modifiers (MetaWaylandKeyboard *keyboard) -{ - struct wl_resource *resource; - - if (!wl_list_empty (&keyboard->focus_resource_list)) - { - MetaWaylandInputDevice *input_device = - META_WAYLAND_INPUT_DEVICE (keyboard); - uint32_t serial; - - serial = meta_wayland_input_device_next_serial (input_device); - - wl_resource_for_each (resource, &keyboard->focus_resource_list) - keyboard_send_modifiers (keyboard, resource, serial); - } -} - -static void -notify_modifiers (MetaWaylandKeyboard *keyboard) -{ - struct xkb_state *state; - - state = keyboard->xkb_info.state; - keyboard->grab->interface->modifiers (keyboard->grab, - xkb_state_serialize_mods (state, XKB_STATE_MODS_EFFECTIVE)); -} - -static void -meta_wayland_keyboard_update_xkb_state (MetaWaylandKeyboard *keyboard) -{ - MetaWaylandXkbInfo *xkb_info = &keyboard->xkb_info; - xkb_mod_mask_t latched, locked, numlock; - MetaBackend *backend = meta_get_backend (); - xkb_layout_index_t layout_idx; - ClutterKeymap *keymap; - ClutterSeat *seat; - - /* Preserve latched/locked modifiers state */ - if (xkb_info->state) - { - latched = xkb_state_serialize_mods (xkb_info->state, XKB_STATE_MODS_LATCHED); - locked = xkb_state_serialize_mods (xkb_info->state, XKB_STATE_MODS_LOCKED); - xkb_state_unref (xkb_info->state); - } - else - { - latched = locked = 0; - } - - seat = clutter_backend_get_default_seat (clutter_get_default_backend ()); - keymap = clutter_seat_get_keymap (seat); - numlock = (1 << xkb_keymap_mod_get_index (xkb_info->keymap, "Mod2")); - - if (clutter_keymap_get_num_lock_state (keymap)) - locked |= numlock; - else - locked &= ~numlock; - - xkb_info->state = xkb_state_new (xkb_info->keymap); - - layout_idx = meta_backend_get_keymap_layout_group (backend); - xkb_state_update_mask (xkb_info->state, 0, latched, locked, 0, 0, layout_idx); - - kbd_a11y_apply_mask (keyboard); -} - -static void -on_kbd_a11y_mask_changed (ClutterSeat *seat, - xkb_mod_mask_t new_latched_mods, - xkb_mod_mask_t new_locked_mods, - MetaWaylandKeyboard *keyboard) -{ - xkb_mod_mask_t latched, locked, depressed, group; - - if (keyboard->xkb_info.state == NULL) - return; - - depressed = xkb_state_serialize_mods(keyboard->xkb_info.state, XKB_STATE_DEPRESSED); - latched = xkb_state_serialize_mods (keyboard->xkb_info.state, XKB_STATE_MODS_LATCHED); - locked = xkb_state_serialize_mods (keyboard->xkb_info.state, XKB_STATE_MODS_LOCKED); - group = xkb_state_serialize_layout (keyboard->xkb_info.state, XKB_STATE_LAYOUT_EFFECTIVE); - - /* Clear previous masks */ - latched &= ~keyboard->kbd_a11y_latched_mods; - locked &= ~keyboard->kbd_a11y_locked_mods; - xkb_state_update_mask (keyboard->xkb_info.state, depressed, latched, locked, 0, 0, group); - - /* Apply new masks */ - keyboard->kbd_a11y_latched_mods = new_latched_mods; - keyboard->kbd_a11y_locked_mods = new_locked_mods; - kbd_a11y_apply_mask (keyboard); - - notify_modifiers (keyboard); -} - -static void -notify_key_repeat_for_resource (MetaWaylandKeyboard *keyboard, - struct wl_resource *keyboard_resource) -{ - if (wl_resource_get_version (keyboard_resource) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) - { - gboolean repeat; - unsigned int delay, rate; - - repeat = g_settings_get_boolean (keyboard->settings, "repeat"); - - if (repeat) - { - unsigned int interval; - interval = g_settings_get_uint (keyboard->settings, "repeat-interval"); - /* Our setting is in the milliseconds between keys. "rate" is the number - * of keys per second. */ - if (interval > 0) - rate = (1000 / interval); - else - rate = 0; - - delay = g_settings_get_uint (keyboard->settings, "delay"); - } - else - { - rate = 0; - delay = 0; - } - - wl_keyboard_send_repeat_info (keyboard_resource, rate, delay); - } -} - -static void -notify_key_repeat (MetaWaylandKeyboard *keyboard) -{ - struct wl_resource *keyboard_resource; - - wl_resource_for_each (keyboard_resource, &keyboard->resource_list) - { - notify_key_repeat_for_resource (keyboard, keyboard_resource); - } - - wl_resource_for_each (keyboard_resource, &keyboard->focus_resource_list) - { - notify_key_repeat_for_resource (keyboard, keyboard_resource); - } -} - -static void -settings_changed (GSettings *settings, - const char *key, - gpointer data) -{ - MetaWaylandKeyboard *keyboard = data; - - notify_key_repeat (keyboard); -} - -static gboolean -default_grab_key (MetaWaylandKeyboardGrab *grab, - const ClutterEvent *event) -{ - MetaWaylandKeyboard *keyboard = grab->keyboard; - gboolean is_press = event->type == CLUTTER_KEY_PRESS; - guint32 code = 0; - - /* Ignore autorepeat events, as autorepeat in Wayland is done on the client - * side. */ - if (event->key.flags & CLUTTER_EVENT_FLAG_REPEATED) - return FALSE; - - code = clutter_event_get_event_code (event); - - return meta_wayland_keyboard_broadcast_key (keyboard, event->key.time, - code, is_press); -} - -static void -default_grab_modifiers (MetaWaylandKeyboardGrab *grab, - ClutterModifierType modifiers) -{ - meta_wayland_keyboard_broadcast_modifiers (grab->keyboard); -} - -static const MetaWaylandKeyboardGrabInterface default_keyboard_grab_interface = { - default_grab_key, - default_grab_modifiers -}; - -void -meta_wayland_keyboard_enable (MetaWaylandKeyboard *keyboard) -{ - MetaBackend *backend = meta_get_backend (); - ClutterBackend *clutter_backend = clutter_get_default_backend (); - - keyboard->settings = g_settings_new ("org.gnome.desktop.peripherals.keyboard"); - g_signal_connect (keyboard->settings, "changed", - G_CALLBACK (settings_changed), keyboard); - - g_signal_connect (backend, "keymap-changed", - G_CALLBACK (on_keymap_changed), keyboard); - g_signal_connect (backend, "keymap-layout-group-changed", - G_CALLBACK (on_keymap_layout_group_changed), keyboard); - - g_signal_connect (clutter_backend_get_default_seat (clutter_backend), - "kbd-a11y-mods-state-changed", - G_CALLBACK (on_kbd_a11y_mask_changed), keyboard); - - meta_wayland_keyboard_take_keymap (keyboard, meta_backend_get_keymap (backend)); -} - -static void -meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info) -{ - g_clear_pointer (&xkb_info->keymap, xkb_keymap_unref); - g_clear_pointer (&xkb_info->state, xkb_state_unref); - g_clear_pointer (&xkb_info->keymap_rofile, meta_anonymous_file_free); -} - -void -meta_wayland_keyboard_disable (MetaWaylandKeyboard *keyboard) -{ - MetaBackend *backend = meta_get_backend (); - - g_signal_handlers_disconnect_by_func (backend, on_keymap_changed, keyboard); - g_signal_handlers_disconnect_by_func (backend, on_keymap_layout_group_changed, keyboard); - - meta_wayland_keyboard_end_grab (keyboard); - meta_wayland_keyboard_set_focus (keyboard, NULL); - - wl_list_remove (&keyboard->resource_list); - wl_list_init (&keyboard->resource_list); - wl_list_remove (&keyboard->focus_resource_list); - wl_list_init (&keyboard->focus_resource_list); - - g_clear_object (&keyboard->settings); -} - -void -meta_wayland_keyboard_update (MetaWaylandKeyboard *keyboard, - const ClutterKeyEvent *event) -{ - gboolean is_press = event->type == CLUTTER_KEY_PRESS; - - /* Only handle real, non-synthetic, events here. The IM is free to reemit - * key events (incl. modifiers), handling those additionally will result - * in doubly-pressed keys. - */ - if ((event->flags & - (CLUTTER_EVENT_FLAG_SYNTHETIC | CLUTTER_EVENT_FLAG_INPUT_METHOD)) != 0) - return; - - /* If we get a key event but still have pending modifier state - * changes from a previous event that didn't get cleared, we need to - * send that state right away so that the new key event can be - * interpreted by clients correctly modified. */ - if (keyboard->mods_changed) - notify_modifiers (keyboard); - - keyboard->mods_changed = xkb_state_update_key (keyboard->xkb_info.state, - event->hardware_keycode, - is_press ? XKB_KEY_DOWN : XKB_KEY_UP); - keyboard->mods_changed |= kbd_a11y_apply_mask (keyboard); -} - -gboolean -meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard, - const ClutterKeyEvent *event) -{ -#ifdef WITH_VERBOSE_MODE - gboolean is_press = event->type == CLUTTER_KEY_PRESS; -#endif - gboolean handled; - - /* Synthetic key events are for autorepeat. Ignore those, as - * autorepeat in Wayland is done on the client side. */ - if ((event->flags & CLUTTER_EVENT_FLAG_SYNTHETIC) && - !(event->flags & CLUTTER_EVENT_FLAG_INPUT_METHOD)) - return FALSE; - - meta_verbose ("Handling key %s event code %d", - is_press ? "press" : "release", - event->hardware_keycode); - - handled = notify_key (keyboard, (const ClutterEvent *) event); - - if (handled) - meta_verbose ("Sent event to wayland client"); - else - meta_verbose ("No wayland surface is focused, continuing normal operation"); - - if (keyboard->mods_changed != 0) - { - notify_modifiers (keyboard); - keyboard->mods_changed = 0; - } - - return handled; -} - -void -meta_wayland_keyboard_update_key_state (MetaWaylandKeyboard *keyboard, - char *key_vector, - int key_vector_len, - int offset) -{ - gboolean mods_changed = FALSE; - - int i; - for (i = offset; i < key_vector_len * 8; i++) - { - gboolean set = (key_vector[i/8] & (1 << (i % 8))) != 0; - - /* The 'offset' parameter allows the caller to have the indices - * into key_vector to either be X-style (base 8) or evdev (base 0), or - * something else (unlikely). We subtract 'offset' to convert to evdev - * style, then add 8 to convert the "evdev" style keycode back to - * the X-style that xkbcommon expects. - */ - mods_changed |= xkb_state_update_key (keyboard->xkb_info.state, - i - offset + 8, - set ? XKB_KEY_DOWN : XKB_KEY_UP); - } - - mods_changed |= kbd_a11y_apply_mask (keyboard); - if (mods_changed) - notify_modifiers (keyboard); -} - -static void -move_resources (struct wl_list *destination, struct wl_list *source) -{ - wl_list_insert_list (destination, source); - wl_list_init (source); -} - -static void -move_resources_for_client (struct wl_list *destination, - struct wl_list *source, - struct wl_client *client) -{ - struct wl_resource *resource, *tmp; - wl_resource_for_each_safe (resource, tmp, source) - { - if (wl_resource_get_client (resource) == client) - { - wl_list_remove (wl_resource_get_link (resource)); - wl_list_insert (destination, wl_resource_get_link (resource)); - } - } -} - -static void -broadcast_focus (MetaWaylandKeyboard *keyboard, - struct wl_resource *resource) -{ - struct wl_array fake_keys; - - /* We never want to send pressed keys to wayland clients on - * enter. The protocol says that we should send them, presumably so - * that clients can trigger their own key repeat routine in case - * they are given focus and a key is physically pressed. - * - * Unfortunately this causes some clients, in particular Xwayland, - * to register key events that they really shouldn't handle, - * e.g. on an Alt+Tab keybinding, where Alt is released before Tab, - * clients would see Tab being pressed on enter followed by a key - * release event for Tab, meaning that Tab would be processed by - * the client when it really shouldn't. - * - * Since the use case for the pressed keys array on enter seems weak - * to us, we'll just fake that there are no pressed keys instead - * which should be spec compliant even if it might not be true. - */ - wl_array_init (&fake_keys); - - keyboard_send_modifiers (keyboard, resource, keyboard->focus_serial); - wl_keyboard_send_enter (resource, keyboard->focus_serial, - keyboard->focus_surface->resource, - &fake_keys); -} - -void -meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard, - MetaWaylandSurface *surface) -{ - MetaWaylandInputDevice *input_device = META_WAYLAND_INPUT_DEVICE (keyboard); - - if (keyboard->focus_surface == surface) - return; - - if (keyboard->focus_surface != NULL) - { - if (!wl_list_empty (&keyboard->focus_resource_list)) - { - struct wl_resource *resource; - uint32_t serial; - - serial = meta_wayland_input_device_next_serial (input_device); - - wl_resource_for_each (resource, &keyboard->focus_resource_list) - { - wl_keyboard_send_leave (resource, serial, - keyboard->focus_surface->resource); - } - - move_resources (&keyboard->resource_list, - &keyboard->focus_resource_list); - } - - wl_list_remove (&keyboard->focus_surface_listener.link); - keyboard->focus_surface = NULL; - } - - if (surface != NULL) - { - struct wl_resource *focus_surface_resource; - - keyboard->focus_surface = surface; - focus_surface_resource = keyboard->focus_surface->resource; - wl_resource_add_destroy_listener (focus_surface_resource, - &keyboard->focus_surface_listener); - - move_resources_for_client (&keyboard->focus_resource_list, - &keyboard->resource_list, - wl_resource_get_client (focus_surface_resource)); - - /* Make sure a11y masks are applied before braodcasting modifiers */ - kbd_a11y_apply_mask (keyboard); - - if (!wl_list_empty (&keyboard->focus_resource_list)) - { - struct wl_resource *resource; - - keyboard->focus_serial = - meta_wayland_input_device_next_serial (input_device); - - wl_resource_for_each (resource, &keyboard->focus_resource_list) - { - broadcast_focus (keyboard, resource); - } - } - } -} - -struct wl_client * -meta_wayland_keyboard_get_focus_client (MetaWaylandKeyboard *keyboard) -{ - if (keyboard->focus_surface) - return wl_resource_get_client (keyboard->focus_surface->resource); - else - return NULL; -} - -static void -keyboard_release (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static const struct wl_keyboard_interface keyboard_interface = { - keyboard_release, -}; - -void -meta_wayland_keyboard_create_new_resource (MetaWaylandKeyboard *keyboard, - struct wl_client *client, - struct wl_resource *seat_resource, - uint32_t id) -{ - struct wl_resource *resource; - - resource = wl_resource_create (client, &wl_keyboard_interface, - wl_resource_get_version (seat_resource), id); - wl_resource_set_implementation (resource, &keyboard_interface, - keyboard, unbind_resource); - - send_keymap (keyboard, resource); - - notify_key_repeat_for_resource (keyboard, resource); - - if (keyboard->focus_surface && - wl_resource_get_client (keyboard->focus_surface->resource) == client) - { - wl_list_insert (&keyboard->focus_resource_list, - wl_resource_get_link (resource)); - broadcast_focus (keyboard, resource); - } - else - { - wl_list_insert (&keyboard->resource_list, - wl_resource_get_link (resource)); - } -} - -gboolean -meta_wayland_keyboard_can_popup (MetaWaylandKeyboard *keyboard, - uint32_t serial) -{ - return (keyboard->key_down_serial == serial || - ((keyboard->key_down_keycode == keyboard->key_up_keycode) && - keyboard->key_up_serial == serial)); -} - -void -meta_wayland_keyboard_start_grab (MetaWaylandKeyboard *keyboard, - MetaWaylandKeyboardGrab *grab) -{ - meta_wayland_keyboard_set_focus (keyboard, NULL); - keyboard->grab = grab; - grab->keyboard = keyboard; -} - -void -meta_wayland_keyboard_end_grab (MetaWaylandKeyboard *keyboard) -{ - keyboard->grab = &keyboard->default_grab; -} - -static void -meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard) -{ - wl_list_init (&keyboard->resource_list); - wl_list_init (&keyboard->focus_resource_list); - - keyboard->default_grab.interface = &default_keyboard_grab_interface; - keyboard->default_grab.keyboard = keyboard; - keyboard->grab = &keyboard->default_grab; - - keyboard->focus_surface_listener.notify = - keyboard_handle_focus_surface_destroy; -} - -static void -meta_wayland_keyboard_finalize (GObject *object) -{ - MetaWaylandKeyboard *keyboard = META_WAYLAND_KEYBOARD (object); - - meta_wayland_xkb_info_destroy (&keyboard->xkb_info); - - G_OBJECT_CLASS (meta_wayland_keyboard_parent_class)->finalize (object); -} - -static void -meta_wayland_keyboard_class_init (MetaWaylandKeyboardClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_wayland_keyboard_finalize; -} diff --git a/src/wayland/meta-wayland-keyboard.h b/src/wayland/meta-wayland-keyboard.h deleted file mode 100644 index ac57d7677..000000000 --- a/src/wayland/meta-wayland-keyboard.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2013 Intel Corporation - * - * 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. - */ - -/* - * Copyright © 2008-2011 Kristian Høgsberg - * Copyright © 2012 Collabora, Ltd. - * - * Permission to use, copy, modify, distribute, and sell this software and - * its documentation for any purpose is hereby granted without fee, provided - * that the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of the copyright holders not be used in - * advertising or publicity pertaining to distribution of the software - * without specific, written prior permission. The copyright holders make - * no representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF - * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef META_WAYLAND_KEYBOARD_H -#define META_WAYLAND_KEYBOARD_H - -#include -#include - -#include "clutter/clutter.h" -#include "core/meta-anonymous-file.h" -#include "wayland/meta-wayland-types.h" - -#define META_TYPE_WAYLAND_KEYBOARD (meta_wayland_keyboard_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandKeyboard, meta_wayland_keyboard, - META, WAYLAND_KEYBOARD, - MetaWaylandInputDevice) - -struct _MetaWaylandKeyboardGrabInterface -{ - gboolean (*key) (MetaWaylandKeyboardGrab *grab, - const ClutterEvent *event); - void (*modifiers) (MetaWaylandKeyboardGrab *grab, - ClutterModifierType modifiers); -}; - -struct _MetaWaylandKeyboardGrab -{ - const MetaWaylandKeyboardGrabInterface *interface; - MetaWaylandKeyboard *keyboard; -}; - -typedef struct -{ - struct xkb_keymap *keymap; - struct xkb_state *state; - MetaAnonymousFile *keymap_rofile; -} MetaWaylandXkbInfo; - -struct _MetaWaylandKeyboard -{ - MetaWaylandInputDevice parent; - - struct wl_list resource_list; - struct wl_list focus_resource_list; - - MetaWaylandSurface *focus_surface; - struct wl_listener focus_surface_listener; - uint32_t focus_serial; - - uint32_t key_down_keycode; - uint32_t key_down_serial; - - uint32_t key_up_keycode; - uint32_t key_up_serial; - - MetaWaylandXkbInfo xkb_info; - enum xkb_state_component mods_changed; - xkb_mod_mask_t kbd_a11y_latched_mods; - xkb_mod_mask_t kbd_a11y_locked_mods; - - MetaWaylandKeyboardGrab *grab; - MetaWaylandKeyboardGrab default_grab; - - GSettings *settings; -}; - -void meta_wayland_keyboard_enable (MetaWaylandKeyboard *keyboard); - -void meta_wayland_keyboard_disable (MetaWaylandKeyboard *keyboard); - -void meta_wayland_keyboard_update (MetaWaylandKeyboard *keyboard, - const ClutterKeyEvent *event); - -gboolean meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard, - const ClutterKeyEvent *event); -void meta_wayland_keyboard_update_key_state (MetaWaylandKeyboard *compositor, - char *key_vector, - int key_vector_len, - int offset); - -void meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard, - MetaWaylandSurface *surface); - -struct wl_client * meta_wayland_keyboard_get_focus_client (MetaWaylandKeyboard *keyboard); - -void meta_wayland_keyboard_create_new_resource (MetaWaylandKeyboard *keyboard, - struct wl_client *client, - struct wl_resource *seat_resource, - uint32_t id); - -gboolean meta_wayland_keyboard_can_popup (MetaWaylandKeyboard *keyboard, - uint32_t serial); - -void meta_wayland_keyboard_start_grab (MetaWaylandKeyboard *keyboard, - MetaWaylandKeyboardGrab *grab); -void meta_wayland_keyboard_end_grab (MetaWaylandKeyboard *keyboard); - -#endif /* META_WAYLAND_KEYBOARD_H */ diff --git a/src/wayland/meta-wayland-legacy-xdg-shell.c b/src/wayland/meta-wayland-legacy-xdg-shell.c deleted file mode 100644 index 3c1ed8e93..000000000 --- a/src/wayland/meta-wayland-legacy-xdg-shell.c +++ /dev/null @@ -1,2105 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2012-2013 Intel Corporation - * Copyright (C) 2013-2015 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "wayland/meta-wayland-legacy-xdg-shell.h" - -#include "backends/meta-logical-monitor.h" -#include "core/window-private.h" -#include "wayland/meta-wayland-outputs.h" -#include "wayland/meta-wayland-popup.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-seat.h" -#include "wayland/meta-wayland-shell-surface.h" -#include "wayland/meta-wayland-surface.h" -#include "wayland/meta-wayland-versions.h" -#include "wayland/meta-wayland-window-configuration.h" -#include "wayland/meta-wayland.h" -#include "wayland/meta-window-wayland.h" - -#include "xdg-shell-unstable-v6-server-protocol.h" - -enum -{ - ZXDG_SURFACE_V6_PROP_0, - - ZXDG_SURFACE_V6_PROP_SHELL_CLIENT, - ZXDG_SURFACE_V6_PROP_RESOURCE, -}; - -typedef struct _MetaWaylandZxdgShellV6Client -{ - struct wl_resource *resource; - GList *surfaces; - GList *surface_constructors; -} MetaWaylandZxdgShellV6Client; - -typedef struct _MetaWaylandZxdgPositionerV6 -{ - MetaRectangle anchor_rect; - int32_t width; - int32_t height; - uint32_t gravity; - uint32_t anchor; - uint32_t constraint_adjustment; - int32_t offset_x; - int32_t offset_y; -} MetaWaylandZxdgPositionerV6; - -typedef struct _MetaWaylandZxdgSurfaceV6Constructor -{ - MetaWaylandSurface *surface; - struct wl_resource *resource; - MetaWaylandZxdgShellV6Client *shell_client; -} MetaWaylandZxdgSurfaceV6Constructor; - -typedef struct _MetaWaylandZxdgSurfaceV6Private -{ - struct wl_resource *resource; - MetaWaylandZxdgShellV6Client *shell_client; - MetaRectangle geometry; - - guint configure_sent : 1; - guint first_buffer_attached : 1; - guint has_set_geometry : 1; -} MetaWaylandZxdgSurfaceV6Private; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandZxdgSurfaceV6, - meta_wayland_zxdg_surface_v6, - META_TYPE_WAYLAND_SHELL_SURFACE); - -struct _MetaWaylandZxdgToplevelV6 -{ - MetaWaylandZxdgSurfaceV6 parent; - - struct wl_resource *resource; -}; - -G_DEFINE_TYPE (MetaWaylandZxdgToplevelV6, - meta_wayland_zxdg_toplevel_v6, - META_TYPE_WAYLAND_ZXDG_SURFACE_V6); - -struct _MetaWaylandZxdgPopupV6 -{ - MetaWaylandZxdgSurfaceV6 parent; - - struct wl_resource *resource; - - MetaWaylandSurface *parent_surface; - struct wl_listener parent_destroy_listener; - - MetaWaylandPopup *popup; - - struct { - MetaWaylandSurface *parent_surface; - - /* - * The coordinates/dimensions in the placement rule are in logical pixel - * coordinate space, i.e. not scaled given what monitor the popup is on. - */ - MetaPlacementRule placement_rule; - - MetaWaylandSeat *grab_seat; - uint32_t grab_serial; - } setup; -}; - -static void -popup_surface_iface_init (MetaWaylandPopupSurfaceInterface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaWaylandZxdgPopupV6, - meta_wayland_zxdg_popup_v6, - META_TYPE_WAYLAND_ZXDG_SURFACE_V6, - G_IMPLEMENT_INTERFACE (META_TYPE_WAYLAND_POPUP_SURFACE, - popup_surface_iface_init)); - -static MetaPlacementRule -meta_wayland_zxdg_positioner_v6_to_placement (MetaWaylandZxdgPositionerV6 *xdg_positioner); - -static struct wl_resource * -meta_wayland_zxdg_surface_v6_get_shell_resource (MetaWaylandZxdgSurfaceV6 *xdg_surface); - -static MetaRectangle -meta_wayland_zxdg_surface_v6_get_window_geometry (MetaWaylandZxdgSurfaceV6 *xdg_surface); - -static void -meta_wayland_zxdg_surface_v6_send_configure (MetaWaylandZxdgSurfaceV6 *xdg_surface, - MetaWaylandWindowConfiguration *configuration); - -static MetaWaylandSurface * -surface_from_xdg_surface_resource (struct wl_resource *resource) -{ - MetaWaylandSurfaceRole *surface_role = wl_resource_get_user_data (resource); - - return meta_wayland_surface_role_get_surface (surface_role); -} - -static MetaWaylandSurface * -surface_from_xdg_toplevel_resource (struct wl_resource *resource) -{ - return surface_from_xdg_surface_resource (resource); -} - -static void -zxdg_toplevel_v6_destructor (struct wl_resource *resource) -{ - MetaWaylandZxdgToplevelV6 *xdg_toplevel = - wl_resource_get_user_data (resource); - MetaWaylandShellSurface *shell_surface = - META_WAYLAND_SHELL_SURFACE (xdg_toplevel); - - meta_wayland_shell_surface_destroy_window (shell_surface); - xdg_toplevel->resource = NULL; -} - -static void -zxdg_toplevel_v6_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -zxdg_toplevel_v6_set_parent (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *parent_resource) -{ - MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource); - MetaWindow *transient_for = NULL; - MetaWindow *window; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - if (parent_resource) - { - MetaWaylandSurface *parent_surface = - surface_from_xdg_surface_resource (parent_resource); - - transient_for = meta_wayland_surface_get_window (parent_surface); - } - - meta_window_set_transient_for (window, transient_for); -} - -static void -zxdg_toplevel_v6_set_title (struct wl_client *client, - struct wl_resource *resource, - const char *title) -{ - MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource); - MetaWindow *window; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - if (!g_utf8_validate (title, -1, NULL)) - title = ""; - - meta_window_set_title (window, title); -} - -static void -zxdg_toplevel_v6_set_app_id (struct wl_client *client, - struct wl_resource *resource, - const char *app_id) -{ - MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource); - MetaWindow *window; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - if (!g_utf8_validate (app_id, -1, NULL)) - app_id = ""; - - meta_window_set_wm_class (window, app_id, app_id); -} - -static void -zxdg_toplevel_v6_show_window_menu (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *seat_resource, - uint32_t serial, - int32_t x, - int32_t y) -{ - MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); - MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource); - MetaWindow *window; - int monitor_scale; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - if (!meta_wayland_seat_get_grab_info (seat, surface, serial, FALSE, NULL, NULL)) - return; - - monitor_scale = meta_window_wayland_get_geometry_scale (window); - meta_window_show_menu (window, META_WINDOW_MENU_WM, - window->buffer_rect.x + (x * monitor_scale), - window->buffer_rect.y + (y * monitor_scale)); -} - -static void -zxdg_toplevel_v6_move (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *seat_resource, - uint32_t serial) -{ - MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); - MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource); - MetaWindow *window; - gfloat x, y; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - if (!meta_wayland_seat_get_grab_info (seat, surface, serial, TRUE, &x, &y)) - return; - - meta_wayland_surface_begin_grab_op (surface, seat, META_GRAB_OP_MOVING, x, y); -} - -static MetaGrabOp -grab_op_for_xdg_toplevel_resize_edge (int edge) -{ - MetaGrabOp op = META_GRAB_OP_WINDOW_BASE; - - if (edge & ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP) - op |= META_GRAB_OP_WINDOW_DIR_NORTH; - if (edge & ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM) - op |= META_GRAB_OP_WINDOW_DIR_SOUTH; - if (edge & ZXDG_TOPLEVEL_V6_RESIZE_EDGE_LEFT) - op |= META_GRAB_OP_WINDOW_DIR_WEST; - if (edge & ZXDG_TOPLEVEL_V6_RESIZE_EDGE_RIGHT) - op |= META_GRAB_OP_WINDOW_DIR_EAST; - - if (op == META_GRAB_OP_WINDOW_BASE) - { - g_warning ("invalid edge: %d", edge); - return META_GRAB_OP_NONE; - } - - return op; -} - -static void -zxdg_toplevel_v6_resize (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *seat_resource, - uint32_t serial, - uint32_t edges) -{ - MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); - MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource); - MetaWindow *window; - gfloat x, y; - MetaGrabOp grab_op; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - if (!meta_wayland_seat_get_grab_info (seat, surface, serial, TRUE, &x, &y)) - return; - - grab_op = grab_op_for_xdg_toplevel_resize_edge (edges); - meta_wayland_surface_begin_grab_op (surface, seat, grab_op, x, y); -} - -static void -zxdg_toplevel_v6_set_max_size (struct wl_client *client, - struct wl_resource *resource, - int32_t width, - int32_t height) -{ - MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource); - MetaWaylandSurfaceState *pending; - MetaWindow *window; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - if (width < 0 || height < 0) - { - wl_resource_post_error (resource, - ZXDG_SHELL_V6_ERROR_INVALID_SURFACE_STATE, - "invalid negative max size requested %i x %i", - width, height); - return; - } - - pending = meta_wayland_surface_get_pending_state (surface); - pending->has_new_max_size = TRUE; - pending->new_max_width = width; - pending->new_max_height = height; -} - -static void -zxdg_toplevel_v6_set_min_size (struct wl_client *client, - struct wl_resource *resource, - int32_t width, - int32_t height) -{ - MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource); - MetaWaylandSurfaceState *pending; - MetaWindow *window; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - if (width < 0 || height < 0) - { - wl_resource_post_error (resource, - ZXDG_SHELL_V6_ERROR_INVALID_SURFACE_STATE, - "invalid negative min size requested %i x %i", - width, height); - return; - } - - pending = meta_wayland_surface_get_pending_state (surface); - pending->has_new_min_size = TRUE; - pending->new_min_width = width; - pending->new_min_height = height; -} - -static void -zxdg_toplevel_v6_set_maximized (struct wl_client *client, - struct wl_resource *resource) -{ - MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource); - MetaWindow *window; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - if (!window->has_maximize_func) - return; - - meta_window_force_placement (window, TRUE); - meta_window_maximize (window, META_MAXIMIZE_BOTH); -} - -static void -zxdg_toplevel_v6_unset_maximized (struct wl_client *client, - struct wl_resource *resource) -{ - MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource); - MetaWindow *window; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - meta_window_unmaximize (window, META_MAXIMIZE_BOTH); -} - -static void -zxdg_toplevel_v6_set_fullscreen (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *output_resource) -{ - MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource); - MetaWindow *window; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - if (output_resource) - { - MetaWaylandOutput *output = wl_resource_get_user_data (output_resource); - if (output && output->logical_monitor) - meta_window_move_to_monitor (window, output->logical_monitor->number); - } - - meta_window_make_fullscreen (window); -} - -static void -zxdg_toplevel_v6_unset_fullscreen (struct wl_client *client, - struct wl_resource *resource) -{ - MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource); - MetaWindow *window; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - meta_window_unmake_fullscreen (window); -} - -static void -zxdg_toplevel_v6_set_minimized (struct wl_client *client, - struct wl_resource *resource) -{ - MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource); - MetaWindow *window; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - meta_window_minimize (window); -} - -static const struct zxdg_toplevel_v6_interface meta_wayland_zxdg_toplevel_v6_interface = { - zxdg_toplevel_v6_destroy, - zxdg_toplevel_v6_set_parent, - zxdg_toplevel_v6_set_title, - zxdg_toplevel_v6_set_app_id, - zxdg_toplevel_v6_show_window_menu, - zxdg_toplevel_v6_move, - zxdg_toplevel_v6_resize, - zxdg_toplevel_v6_set_max_size, - zxdg_toplevel_v6_set_min_size, - zxdg_toplevel_v6_set_maximized, - zxdg_toplevel_v6_unset_maximized, - zxdg_toplevel_v6_set_fullscreen, - zxdg_toplevel_v6_unset_fullscreen, - zxdg_toplevel_v6_set_minimized, -}; - -static void -zxdg_popup_v6_destructor (struct wl_resource *resource) -{ - MetaWaylandZxdgPopupV6 *xdg_popup = - META_WAYLAND_ZXDG_POPUP_V6 (wl_resource_get_user_data (resource)); - - if (xdg_popup->parent_surface) - { - wl_list_remove (&xdg_popup->parent_destroy_listener.link); - xdg_popup->parent_surface = NULL; - } - - if (xdg_popup->popup) - meta_wayland_popup_dismiss (xdg_popup->popup); - - xdg_popup->resource = NULL; -} - -static void -zxdg_popup_v6_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -zxdg_popup_v6_grab (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *seat_resource, - uint32_t serial) -{ - MetaWaylandZxdgPopupV6 *xdg_popup = - META_WAYLAND_ZXDG_POPUP_V6 (wl_resource_get_user_data (resource)); - MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); - MetaWaylandSurface *parent_surface; - - parent_surface = xdg_popup->setup.parent_surface; - if (!parent_surface) - { - wl_resource_post_error (resource, - ZXDG_POPUP_V6_ERROR_INVALID_GRAB, - "tried to grab after popup was mapped"); - return; - } - - xdg_popup->setup.grab_seat = seat; - xdg_popup->setup.grab_serial = serial; -} - -static const struct zxdg_popup_v6_interface meta_wayland_zxdg_popup_v6_interface = { - zxdg_popup_v6_destroy, - zxdg_popup_v6_grab, -}; - -static void -handle_popup_parent_destroyed (struct wl_listener *listener, - void *data) -{ - MetaWaylandZxdgPopupV6 *xdg_popup = - wl_container_of (listener, xdg_popup, parent_destroy_listener); - MetaWaylandZxdgSurfaceV6 *xdg_surface = - META_WAYLAND_ZXDG_SURFACE_V6 (xdg_popup); - struct wl_resource *xdg_shell_resource = - meta_wayland_zxdg_surface_v6_get_shell_resource (xdg_surface); - MetaWaylandShellSurface *shell_surface = - META_WAYLAND_SHELL_SURFACE (xdg_popup); - - wl_resource_post_error (xdg_shell_resource, - ZXDG_SHELL_V6_ERROR_NOT_THE_TOPMOST_POPUP, - "destroyed popup not top most popup"); - xdg_popup->parent_surface = NULL; - - meta_wayland_shell_surface_destroy_window (shell_surface); -} - -static void -add_state_value (struct wl_array *states, - enum zxdg_toplevel_v6_state state) -{ - uint32_t *s; - - s = wl_array_add (states, sizeof *s); - *s = state; -} - -static void -fill_states (struct wl_array *states, - MetaWindow *window) -{ - if (META_WINDOW_MAXIMIZED (window)) - add_state_value (states, ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED); - if (meta_window_is_fullscreen (window)) - add_state_value (states, ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN); - if (meta_grab_op_is_resizing (window->display->grab_op)) - add_state_value (states, ZXDG_TOPLEVEL_V6_STATE_RESIZING); - if (meta_window_appears_focused (window)) - add_state_value (states, ZXDG_TOPLEVEL_V6_STATE_ACTIVATED); -} - -static void -meta_wayland_zxdg_toplevel_v6_send_configure (MetaWaylandZxdgToplevelV6 *xdg_toplevel, - MetaWaylandWindowConfiguration *configuration) -{ - MetaWaylandZxdgSurfaceV6 *xdg_surface = - META_WAYLAND_ZXDG_SURFACE_V6 (xdg_toplevel); - MetaWaylandSurfaceRole *surface_role = - META_WAYLAND_SURFACE_ROLE (xdg_toplevel); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWindow *window; - struct wl_array states; - - window = meta_wayland_surface_get_window (surface); - - wl_array_init (&states); - fill_states (&states, window); - - zxdg_toplevel_v6_send_configure (xdg_toplevel->resource, - configuration->width / configuration->scale, - configuration->height / configuration->scale, - &states); - wl_array_release (&states); - - meta_wayland_zxdg_surface_v6_send_configure (xdg_surface, configuration); -} - -static gboolean -is_new_size_hints_valid (MetaWindow *window, - MetaWaylandSurfaceState *pending) -{ - int new_min_width, new_min_height; - int new_max_width, new_max_height; - - if (pending->has_new_min_size) - { - new_min_width = pending->new_min_width; - new_min_height = pending->new_min_height; - } - else - { - meta_window_wayland_get_min_size (window, &new_min_width, &new_min_height); - } - - if (pending->has_new_max_size) - { - new_max_width = pending->new_max_width; - new_max_height = pending->new_max_height; - } - else - { - meta_window_wayland_get_max_size (window, &new_max_width, &new_max_height); - } - /* Zero means unlimited */ - return ((new_max_width == 0 || new_min_width <= new_max_width) && - (new_max_height == 0 || new_min_height <= new_max_height)); -} - -static void -meta_wayland_zxdg_toplevel_v6_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending) -{ - MetaWaylandZxdgToplevelV6 *xdg_toplevel = - META_WAYLAND_ZXDG_TOPLEVEL_V6 (surface_role); - MetaWaylandZxdgSurfaceV6 *xdg_surface = - META_WAYLAND_ZXDG_SURFACE_V6 (xdg_toplevel); - MetaWaylandZxdgSurfaceV6Private *xdg_surface_priv = - meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface); - MetaWaylandActorSurface *actor_surface = - META_WAYLAND_ACTOR_SURFACE (xdg_surface); - MetaWaylandSurfaceRoleClass *surface_role_class; - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWindow *window; - - window = meta_wayland_surface_get_window (surface); - if (!window) - { - meta_wayland_actor_surface_queue_frame_callbacks (actor_surface, pending); - return; - } - - surface_role_class = - META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_zxdg_toplevel_v6_parent_class); - surface_role_class->apply_state (surface_role, pending); - - if (!xdg_surface_priv->configure_sent) - { - MetaWaylandWindowConfiguration *configuration; - - configuration = meta_wayland_window_configuration_new_empty (); - meta_wayland_zxdg_toplevel_v6_send_configure (xdg_toplevel, - configuration); - meta_wayland_window_configuration_free (configuration); - return; - } -} - -static void -meta_wayland_zxdg_toplevel_v6_post_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending) -{ - MetaWaylandZxdgToplevelV6 *xdg_toplevel = - META_WAYLAND_ZXDG_TOPLEVEL_V6 (surface_role); - MetaWaylandZxdgSurfaceV6 *xdg_surface = - META_WAYLAND_ZXDG_SURFACE_V6 (xdg_toplevel); - MetaWaylandZxdgSurfaceV6Private *xdg_surface_priv = - meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface); - MetaWaylandSurfaceRoleClass *surface_role_class; - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWindow *window; - MetaRectangle old_geometry; - gboolean geometry_changed; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - old_geometry = xdg_surface_priv->geometry; - - surface_role_class = - META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_zxdg_toplevel_v6_parent_class); - surface_role_class->post_apply_state (surface_role, pending); - - geometry_changed = !meta_rectangle_equal (&old_geometry, &xdg_surface_priv->geometry); - - if (geometry_changed || pending->has_acked_configure_serial) - { - MetaRectangle window_geometry; - - window_geometry = - meta_wayland_zxdg_surface_v6_get_window_geometry (xdg_surface); - meta_window_wayland_finish_move_resize (window, window_geometry, pending); - } - else if (pending->dx != 0 || pending->dy != 0) - { - g_warning ("XXX: Attach-initiated move without a new geometry. " - "This is unimplemented right now."); - } - - /* When we get to this point, we ought to have valid size hints */ - if (pending->has_new_min_size || pending->has_new_max_size) - { - if (is_new_size_hints_valid (window, pending)) - { - if (pending->has_new_min_size) - meta_window_wayland_set_min_size (window, - pending->new_min_width, - pending->new_min_height); - - if (pending->has_new_max_size) - meta_window_wayland_set_max_size (window, - pending->new_max_width, - pending->new_max_height); - - meta_window_recalc_features (window); - } - else - { - wl_resource_post_error (surface->resource, - ZXDG_SHELL_V6_ERROR_INVALID_SURFACE_STATE, - "Invalid min/max size"); - } - } -} - -static MetaWaylandSurface * -meta_wayland_zxdg_toplevel_v6_get_toplevel (MetaWaylandSurfaceRole *surface_role) -{ - return meta_wayland_surface_role_get_surface (surface_role); -} - -static void -meta_wayland_zxdg_toplevel_v6_configure (MetaWaylandShellSurface *shell_surface, - MetaWaylandWindowConfiguration *configuration) -{ - MetaWaylandZxdgToplevelV6 *xdg_toplevel = - META_WAYLAND_ZXDG_TOPLEVEL_V6 (shell_surface); - MetaWaylandZxdgSurfaceV6 *xdg_surface = - META_WAYLAND_ZXDG_SURFACE_V6 (xdg_toplevel); - MetaWaylandZxdgSurfaceV6Private *xdg_surface_priv = - meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface); - - if (!xdg_surface_priv->resource) - return; - - if (!xdg_toplevel->resource) - return; - - meta_wayland_zxdg_toplevel_v6_send_configure (xdg_toplevel, configuration); -} - -static void -meta_wayland_zxdg_toplevel_v6_managed (MetaWaylandShellSurface *shell_surface, - MetaWindow *window) -{ -} - -static void -meta_wayland_zxdg_toplevel_v6_close (MetaWaylandShellSurface *shell_surface) -{ - MetaWaylandZxdgToplevelV6 *xdg_toplevel = - META_WAYLAND_ZXDG_TOPLEVEL_V6 (shell_surface); - - zxdg_toplevel_v6_send_close (xdg_toplevel->resource); -} - -static void -meta_wayland_zxdg_toplevel_v6_shell_client_destroyed (MetaWaylandZxdgSurfaceV6 *xdg_surface) -{ - MetaWaylandZxdgToplevelV6 *xdg_toplevel = - META_WAYLAND_ZXDG_TOPLEVEL_V6 (xdg_surface); - struct wl_resource *xdg_shell_resource = - meta_wayland_zxdg_surface_v6_get_shell_resource (xdg_surface); - MetaWaylandZxdgSurfaceV6Class *xdg_surface_class = - META_WAYLAND_ZXDG_SURFACE_V6_CLASS (meta_wayland_zxdg_toplevel_v6_parent_class); - - xdg_surface_class->shell_client_destroyed (xdg_surface); - - if (xdg_toplevel->resource) - { - wl_resource_post_error (xdg_shell_resource, - ZXDG_SHELL_V6_ERROR_DEFUNCT_SURFACES, - "xdg_shell of xdg_toplevel@%d was destroyed", - wl_resource_get_id (xdg_toplevel->resource)); - - wl_resource_destroy (xdg_toplevel->resource); - } -} - -static void -meta_wayland_zxdg_toplevel_v6_finalize (GObject *object) -{ - MetaWaylandZxdgToplevelV6 *xdg_toplevel = - META_WAYLAND_ZXDG_TOPLEVEL_V6 (object); - - g_clear_pointer (&xdg_toplevel->resource, wl_resource_destroy); - - G_OBJECT_CLASS (meta_wayland_zxdg_toplevel_v6_parent_class)->finalize (object); -} - -static void -meta_wayland_zxdg_toplevel_v6_init (MetaWaylandZxdgToplevelV6 *role) -{ -} - -static void -meta_wayland_zxdg_toplevel_v6_class_init (MetaWaylandZxdgToplevelV6Class *klass) -{ - GObjectClass *object_class; - MetaWaylandSurfaceRoleClass *surface_role_class; - MetaWaylandShellSurfaceClass *shell_surface_class; - MetaWaylandZxdgSurfaceV6Class *xdg_surface_class; - - object_class = G_OBJECT_CLASS (klass); - object_class->finalize = meta_wayland_zxdg_toplevel_v6_finalize; - - surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass); - surface_role_class->apply_state = meta_wayland_zxdg_toplevel_v6_apply_state; - surface_role_class->post_apply_state = - meta_wayland_zxdg_toplevel_v6_post_apply_state; - surface_role_class->get_toplevel = meta_wayland_zxdg_toplevel_v6_get_toplevel; - - shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass); - shell_surface_class->configure = meta_wayland_zxdg_toplevel_v6_configure; - shell_surface_class->managed = meta_wayland_zxdg_toplevel_v6_managed; - shell_surface_class->close = meta_wayland_zxdg_toplevel_v6_close; - - xdg_surface_class = META_WAYLAND_ZXDG_SURFACE_V6_CLASS (klass); - xdg_surface_class->shell_client_destroyed = - meta_wayland_zxdg_toplevel_v6_shell_client_destroyed; -} - -static void -scale_placement_rule (MetaPlacementRule *placement_rule, - MetaWaylandSurface *surface) -{ - MetaWindow *window; - int geometry_scale; - - window = meta_wayland_surface_get_window (surface); - geometry_scale = meta_window_wayland_get_geometry_scale (window); - - placement_rule->anchor_rect.x *= geometry_scale; - placement_rule->anchor_rect.y *= geometry_scale; - placement_rule->anchor_rect.width *= geometry_scale; - placement_rule->anchor_rect.height *= geometry_scale; - placement_rule->offset_x *= geometry_scale; - placement_rule->offset_y *= geometry_scale; - placement_rule->width *= geometry_scale; - placement_rule->height *= geometry_scale; -} - -static void -finish_popup_setup (MetaWaylandZxdgPopupV6 *xdg_popup) -{ - MetaWaylandZxdgSurfaceV6 *xdg_surface = - META_WAYLAND_ZXDG_SURFACE_V6 (xdg_popup); - MetaWaylandShellSurface *shell_surface = - META_WAYLAND_SHELL_SURFACE (xdg_popup); - MetaWaylandSurfaceRole *surface_role = META_WAYLAND_SURFACE_ROLE (xdg_popup); - struct wl_resource *xdg_shell_resource = - meta_wayland_zxdg_surface_v6_get_shell_resource (xdg_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWaylandSurface *parent_surface; - MetaPlacementRule scaled_placement_rule; - MetaWaylandSeat *seat; - uint32_t serial; - MetaDisplay *display = meta_get_display (); - MetaWindow *window; - - parent_surface = xdg_popup->setup.parent_surface; - seat = xdg_popup->setup.grab_seat; - serial = xdg_popup->setup.grab_serial; - - xdg_popup->setup.parent_surface = NULL; - xdg_popup->setup.grab_seat = NULL; - - if (!meta_wayland_surface_get_window (parent_surface)) - { - zxdg_popup_v6_send_popup_done (xdg_popup->resource); - return; - } - - if (seat) - { - MetaWaylandSurface *top_popup; - - if (!meta_wayland_seat_can_popup (seat, serial)) - { - zxdg_popup_v6_send_popup_done (xdg_popup->resource); - return; - } - - top_popup = meta_wayland_pointer_get_top_popup (seat->pointer); - if (top_popup && parent_surface != top_popup) - { - wl_resource_post_error (xdg_shell_resource, - ZXDG_SHELL_V6_ERROR_NOT_THE_TOPMOST_POPUP, - "parent not top most surface"); - return; - } - } - - xdg_popup->parent_surface = parent_surface; - xdg_popup->parent_destroy_listener.notify = handle_popup_parent_destroyed; - wl_resource_add_destroy_listener (parent_surface->resource, - &xdg_popup->parent_destroy_listener); - - window = meta_window_wayland_new (display, surface); - meta_wayland_shell_surface_set_window (shell_surface, window); - - scaled_placement_rule = xdg_popup->setup.placement_rule; - scale_placement_rule (&scaled_placement_rule, surface); - meta_window_place_with_placement_rule (window, &scaled_placement_rule); - - if (seat) - { - MetaWaylandPopupSurface *popup_surface; - MetaWaylandPopup *popup; - - meta_window_focus (window, meta_display_get_current_time (display)); - popup_surface = META_WAYLAND_POPUP_SURFACE (surface->role); - popup = meta_wayland_pointer_start_popup_grab (seat->pointer, - popup_surface); - if (popup == NULL) - { - zxdg_popup_v6_send_popup_done (xdg_popup->resource); - meta_wayland_shell_surface_destroy_window (shell_surface); - return; - } - - xdg_popup->popup = popup; - } - else - { - /* The keyboard focus semantics for non-grabbing zxdg_shell_v6 popups - * is pretty undefined. Same applies for subsurfaces, but in practice, - * subsurfaces never receive keyboard focus, so it makes sense to - * do the same for non-grabbing popups. - * - * See https://bugzilla.gnome.org/show_bug.cgi?id=771694#c24 - */ - window->input = FALSE; - } -} - -static void -meta_wayland_zxdg_popup_v6_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending) -{ - MetaWaylandZxdgPopupV6 *xdg_popup = META_WAYLAND_ZXDG_POPUP_V6 (surface_role); - MetaWaylandSurfaceRoleClass *surface_role_class; - - if (xdg_popup->setup.parent_surface) - finish_popup_setup (xdg_popup); - - surface_role_class = - META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_zxdg_popup_v6_parent_class); - surface_role_class->apply_state (surface_role, pending); -} - -static void -meta_wayland_zxdg_popup_v6_post_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending) -{ - MetaWaylandZxdgSurfaceV6 *xdg_surface = - META_WAYLAND_ZXDG_SURFACE_V6 (surface_role); - MetaWaylandSurfaceRoleClass *surface_role_class; - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWindow *window; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - surface_role_class = - META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_zxdg_popup_v6_parent_class); - surface_role_class->post_apply_state (surface_role, pending); - - if (!surface->buffer_ref->buffer) - return; - - if (pending->has_acked_configure_serial) - { - MetaRectangle window_geometry; - - window_geometry = - meta_wayland_zxdg_surface_v6_get_window_geometry (xdg_surface); - meta_window_wayland_finish_move_resize (window, - window_geometry, - pending); - } -} - -static MetaWaylandSurface * -meta_wayland_zxdg_popup_v6_get_toplevel (MetaWaylandSurfaceRole *surface_role) -{ - MetaWaylandZxdgPopupV6 *xdg_popup = META_WAYLAND_ZXDG_POPUP_V6 (surface_role); - - if (xdg_popup->parent_surface) - return meta_wayland_surface_get_toplevel (xdg_popup->parent_surface); - else - return NULL; -} - -static void -meta_wayland_zxdg_popup_v6_configure (MetaWaylandShellSurface *shell_surface, - MetaWaylandWindowConfiguration *configuration) -{ - MetaWaylandZxdgPopupV6 *xdg_popup = - META_WAYLAND_ZXDG_POPUP_V6 (shell_surface); - MetaWaylandZxdgSurfaceV6 *xdg_surface = - META_WAYLAND_ZXDG_SURFACE_V6 (xdg_popup); - MetaWindow *parent_window = - meta_wayland_surface_get_window (xdg_popup->parent_surface); - int geometry_scale; - int x, y; - - /* If the parent surface was destroyed, its window will be destroyed - * before the popup receives the parent-destroy signal. This means that - * the popup may potentially get temporary focus until itself is destroyed. - * If this happen, don't try to configure the xdg_popup surface. - * - * FIXME: Could maybe add a signal that is emitted before the window is - * created so that we can avoid incorrect intermediate foci. - */ - if (!parent_window) - return; - - geometry_scale = meta_window_wayland_get_geometry_scale (parent_window); - x = configuration->rel_x / geometry_scale; - y = configuration->rel_y / geometry_scale; - - zxdg_popup_v6_send_configure (xdg_popup->resource, - x, y, - configuration->width / configuration->scale, - configuration->height / configuration->scale); - meta_wayland_zxdg_surface_v6_send_configure (xdg_surface, configuration); -} - -static void -meta_wayland_zxdg_popup_v6_managed (MetaWaylandShellSurface *shell_surface, - MetaWindow *window) -{ - MetaWaylandZxdgPopupV6 *xdg_popup = - META_WAYLAND_ZXDG_POPUP_V6 (shell_surface); - MetaWaylandSurface *parent = xdg_popup->parent_surface; - - g_assert (parent); - - meta_window_set_transient_for (window, - meta_wayland_surface_get_window (parent)); - meta_window_set_type (window, META_WINDOW_DROPDOWN_MENU); -} - -static void -meta_wayland_zxdg_popup_v6_shell_client_destroyed (MetaWaylandZxdgSurfaceV6 *xdg_surface) -{ - MetaWaylandZxdgPopupV6 *xdg_popup = META_WAYLAND_ZXDG_POPUP_V6 (xdg_surface); - struct wl_resource *xdg_shell_resource = - meta_wayland_zxdg_surface_v6_get_shell_resource (xdg_surface); - MetaWaylandZxdgSurfaceV6Class *xdg_surface_class = - META_WAYLAND_ZXDG_SURFACE_V6_CLASS (meta_wayland_zxdg_popup_v6_parent_class); - - xdg_surface_class->shell_client_destroyed (xdg_surface); - - if (xdg_popup->resource) - { - wl_resource_post_error (xdg_shell_resource, - ZXDG_SHELL_V6_ERROR_DEFUNCT_SURFACES, - "xdg_shell of xdg_popup@%d was destroyed", - wl_resource_get_id (xdg_popup->resource)); - - wl_resource_destroy (xdg_popup->resource); - } -} - -static void -meta_wayland_zxdg_popup_v6_done (MetaWaylandPopupSurface *popup_surface) -{ - MetaWaylandZxdgPopupV6 *xdg_popup = META_WAYLAND_ZXDG_POPUP_V6 (popup_surface); - - zxdg_popup_v6_send_popup_done (xdg_popup->resource); -} - -static void -meta_wayland_zxdg_popup_v6_dismiss (MetaWaylandPopupSurface *popup_surface) -{ - MetaWaylandZxdgPopupV6 *xdg_popup = - META_WAYLAND_ZXDG_POPUP_V6 (popup_surface); - MetaWaylandZxdgSurfaceV6 *xdg_surface = - META_WAYLAND_ZXDG_SURFACE_V6 (xdg_popup); - struct wl_resource *xdg_shell_resource = - meta_wayland_zxdg_surface_v6_get_shell_resource (xdg_surface); - MetaWaylandShellSurface *shell_surface = - META_WAYLAND_SHELL_SURFACE (xdg_popup); - MetaWaylandSurfaceRole *surface_role = META_WAYLAND_SURFACE_ROLE (xdg_popup); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWaylandSurface *top_popup; - - top_popup = meta_wayland_popup_get_top_popup (xdg_popup->popup); - if (surface != top_popup) - { - wl_resource_post_error (xdg_shell_resource, - ZXDG_SHELL_V6_ERROR_NOT_THE_TOPMOST_POPUP, - "destroyed popup not top most popup"); - } - - xdg_popup->popup = NULL; - - meta_wayland_shell_surface_destroy_window (shell_surface); -} - -static MetaWaylandSurface * -meta_wayland_zxdg_popup_v6_get_surface (MetaWaylandPopupSurface *popup_surface) -{ - MetaWaylandSurfaceRole *surface_role = - META_WAYLAND_SURFACE_ROLE (popup_surface); - - return meta_wayland_surface_role_get_surface (surface_role); -} - -static void -popup_surface_iface_init (MetaWaylandPopupSurfaceInterface *iface) -{ - iface->done = meta_wayland_zxdg_popup_v6_done; - iface->dismiss = meta_wayland_zxdg_popup_v6_dismiss; - iface->get_surface = meta_wayland_zxdg_popup_v6_get_surface; -} - -static void -meta_wayland_zxdg_popup_v6_role_finalize (GObject *object) -{ - MetaWaylandZxdgPopupV6 *xdg_popup = META_WAYLAND_ZXDG_POPUP_V6 (object); - - g_clear_pointer (&xdg_popup->resource, wl_resource_destroy); - - G_OBJECT_CLASS (meta_wayland_zxdg_popup_v6_parent_class)->finalize (object); -} - -static void -meta_wayland_zxdg_popup_v6_init (MetaWaylandZxdgPopupV6 *role) -{ -} - -static void -meta_wayland_zxdg_popup_v6_class_init (MetaWaylandZxdgPopupV6Class *klass) -{ - GObjectClass *object_class; - MetaWaylandSurfaceRoleClass *surface_role_class; - MetaWaylandShellSurfaceClass *shell_surface_class; - MetaWaylandZxdgSurfaceV6Class *xdg_surface_class; - - object_class = G_OBJECT_CLASS (klass); - object_class->finalize = meta_wayland_zxdg_popup_v6_role_finalize; - - surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass); - surface_role_class->apply_state = meta_wayland_zxdg_popup_v6_apply_state; - surface_role_class->post_apply_state = - meta_wayland_zxdg_popup_v6_post_apply_state; - surface_role_class->get_toplevel = meta_wayland_zxdg_popup_v6_get_toplevel; - - shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass); - shell_surface_class->configure = meta_wayland_zxdg_popup_v6_configure; - shell_surface_class->managed = meta_wayland_zxdg_popup_v6_managed; - - xdg_surface_class = META_WAYLAND_ZXDG_SURFACE_V6_CLASS (klass); - xdg_surface_class->shell_client_destroyed = - meta_wayland_zxdg_popup_v6_shell_client_destroyed; -} - -static struct wl_resource * -meta_wayland_zxdg_surface_v6_get_shell_resource (MetaWaylandZxdgSurfaceV6 *xdg_surface) -{ - MetaWaylandZxdgSurfaceV6Private *priv = - meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface); - - return priv->shell_client->resource; -} - -static MetaRectangle -meta_wayland_zxdg_surface_v6_get_window_geometry (MetaWaylandZxdgSurfaceV6 *xdg_surface) -{ - MetaWaylandZxdgSurfaceV6Private *priv = - meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface); - - return priv->geometry; -} - -static gboolean -meta_wayland_zxdg_surface_v6_is_assigned (MetaWaylandZxdgSurfaceV6 *xdg_surface) -{ - MetaWaylandZxdgSurfaceV6Private *priv = - meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface); - - return priv->resource != NULL; -} - -static void -meta_wayland_zxdg_surface_v6_send_configure (MetaWaylandZxdgSurfaceV6 *xdg_surface, - MetaWaylandWindowConfiguration *configuration) -{ - MetaWaylandZxdgSurfaceV6Private *priv = - meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface); - - zxdg_surface_v6_send_configure (priv->resource, configuration->serial); - - priv->configure_sent = TRUE; -} - -static void -zxdg_surface_v6_destructor (struct wl_resource *resource) -{ - MetaWaylandZxdgSurfaceV6 *xdg_surface = wl_resource_get_user_data (resource); - MetaWaylandZxdgSurfaceV6Private *priv = - meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface); - - priv->shell_client->surfaces = g_list_remove (priv->shell_client->surfaces, - xdg_surface); - - priv->resource = NULL; - priv->first_buffer_attached = FALSE; -} - -static void -zxdg_surface_v6_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -zxdg_surface_v6_get_toplevel (struct wl_client *client, - struct wl_resource *resource, - uint32_t id) -{ - MetaWaylandZxdgSurfaceV6 *xdg_surface = wl_resource_get_user_data (resource); - MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource); - struct wl_resource *xdg_shell_resource = - meta_wayland_zxdg_surface_v6_get_shell_resource (xdg_surface); - - wl_resource_post_error (xdg_shell_resource, ZXDG_SHELL_V6_ERROR_ROLE, - "wl_surface@%d already has a role assigned", - wl_resource_get_id (surface->resource)); -} - -static void -zxdg_surface_v6_get_popup (struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *parent_resource, - struct wl_resource *positioner_resource) -{ - MetaWaylandZxdgSurfaceV6 *xdg_surface = wl_resource_get_user_data (resource); - MetaWaylandZxdgSurfaceV6Private *priv = - meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface); - MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource); - - wl_resource_post_error (priv->shell_client->resource, - ZXDG_SHELL_V6_ERROR_ROLE, - "wl_surface@%d already has a role assigned", - wl_resource_get_id (surface->resource)); -} - -static void -zxdg_surface_v6_set_window_geometry (struct wl_client *client, - struct wl_resource *resource, - int32_t x, - int32_t y, - int32_t width, - int32_t height) -{ - MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource); - MetaWaylandSurfaceState *pending; - - if (width == 0 || height == 0) - { - g_warning ("Invalid geometry %dx%d+%d+%d set on xdg_surface@%d. Ignoring for " - "now, but this will result in client termination in the future.", - width, height, x, y, - wl_resource_get_id (resource)); - return; - } - - pending = meta_wayland_surface_get_pending_state (surface); - pending->has_new_geometry = TRUE; - pending->new_geometry.x = x; - pending->new_geometry.y = y; - pending->new_geometry.width = width; - pending->new_geometry.height = height; -} - -static void -zxdg_surface_v6_ack_configure (struct wl_client *client, - struct wl_resource *resource, - uint32_t serial) -{ - MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource); - MetaWaylandSurfaceState *pending; - - pending = meta_wayland_surface_get_pending_state (surface); - pending->has_acked_configure_serial = TRUE; - pending->acked_configure_serial = serial; -} - -static const struct zxdg_surface_v6_interface meta_wayland_zxdg_surface_v6_interface = { - zxdg_surface_v6_destroy, - zxdg_surface_v6_get_toplevel, - zxdg_surface_v6_get_popup, - zxdg_surface_v6_set_window_geometry, - zxdg_surface_v6_ack_configure, -}; - -static void -meta_wayland_zxdg_surface_v6_finalize (GObject *object) -{ - MetaWaylandZxdgSurfaceV6 *xdg_surface = META_WAYLAND_ZXDG_SURFACE_V6 (object); - MetaWaylandZxdgSurfaceV6Private *priv = - meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface); - - g_clear_pointer (&priv->resource, wl_resource_destroy); - - G_OBJECT_CLASS (meta_wayland_zxdg_surface_v6_parent_class)->finalize (object); -} - -static void -meta_wayland_zxdg_surface_v6_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending) -{ - MetaWaylandZxdgSurfaceV6 *xdg_surface = - META_WAYLAND_ZXDG_SURFACE_V6 (surface_role); - MetaWaylandZxdgSurfaceV6Private *priv = - meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWindow *window = meta_wayland_surface_get_window (surface); - MetaWaylandSurfaceRoleClass *surface_role_class; - - surface_role_class = - META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_zxdg_surface_v6_parent_class); - surface_role_class->apply_state (surface_role, pending); - - /* Ignore commits when unassigned. */ - if (!priv->resource) - return; - - if (!surface->buffer_ref->buffer && priv->first_buffer_attached) - { - /* XDG surfaces can't commit NULL buffers */ - wl_resource_post_error (surface->resource, - WL_DISPLAY_ERROR_INVALID_OBJECT, - "Cannot commit a NULL buffer to an xdg_surface"); - return; - } - - if (surface->buffer_ref->buffer && !priv->configure_sent) - { - wl_resource_post_error (surface->resource, - ZXDG_SURFACE_V6_ERROR_UNCONFIGURED_BUFFER, - "buffer committed to unconfigured xdg_surface"); - return; - } - - if (!window) - return; - - if (surface->buffer_ref->buffer) - priv->first_buffer_attached = TRUE; -} - -static void -meta_wayland_zxdg_surface_v6_post_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending) -{ - MetaWaylandZxdgSurfaceV6 *xdg_surface = - META_WAYLAND_ZXDG_SURFACE_V6 (surface_role); - MetaWaylandZxdgSurfaceV6Private *priv = - meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface); - MetaWaylandShellSurface *shell_surface = - META_WAYLAND_SHELL_SURFACE (xdg_surface); - - if (pending->has_new_geometry) - { - meta_wayland_shell_surface_determine_geometry (shell_surface, - &pending->new_geometry, - &priv->geometry); - priv->has_set_geometry = TRUE; - } - else if (!priv->has_set_geometry) - { - MetaRectangle new_geometry = { 0 }; - - /* If the surface has never set any geometry, calculate - * a default one unioning the surface and all subsurfaces together. */ - - meta_wayland_shell_surface_calculate_geometry (shell_surface, - &new_geometry); - if (!meta_rectangle_equal (&new_geometry, &priv->geometry)) - { - pending->has_new_geometry = TRUE; - priv->geometry = new_geometry; - } - } -} - -static void -meta_wayland_zxdg_surface_v6_assigned (MetaWaylandSurfaceRole *surface_role) -{ - MetaWaylandZxdgSurfaceV6 *xdg_surface = - META_WAYLAND_ZXDG_SURFACE_V6 (surface_role); - MetaWaylandZxdgSurfaceV6Private *priv = - meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - struct wl_resource *xdg_shell_resource = - meta_wayland_zxdg_surface_v6_get_shell_resource (xdg_surface); - MetaWaylandSurfaceRoleClass *surface_role_class; - - priv->configure_sent = FALSE; - priv->first_buffer_attached = FALSE; - - if (surface->buffer_ref->buffer) - { - wl_resource_post_error (xdg_shell_resource, - ZXDG_SHELL_V6_ERROR_INVALID_SURFACE_STATE, - "wl_surface@%d already has a buffer committed", - wl_resource_get_id (surface->resource)); - return; - } - - surface_role_class = - META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_zxdg_surface_v6_parent_class); - surface_role_class->assigned (surface_role); -} - -static void -meta_wayland_zxdg_surface_v6_ping (MetaWaylandShellSurface *shell_surface, - uint32_t serial) -{ - MetaWaylandZxdgSurfaceV6 *xdg_surface = - META_WAYLAND_ZXDG_SURFACE_V6 (shell_surface); - MetaWaylandZxdgSurfaceV6Private *priv = - meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface); - - zxdg_shell_v6_send_ping (priv->shell_client->resource, serial); -} - -static void -meta_wayland_zxdg_surface_v6_real_shell_client_destroyed (MetaWaylandZxdgSurfaceV6 *xdg_surface) -{ - MetaWaylandZxdgSurfaceV6Private *priv = - meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface); - - if (priv->resource) - { - wl_resource_post_error (priv->shell_client->resource, - ZXDG_SHELL_V6_ERROR_DEFUNCT_SURFACES, - "xdg_shell of xdg_surface@%d was destroyed", - wl_resource_get_id (priv->resource)); - - wl_resource_destroy (priv->resource); - } -} - -static void -meta_wayland_zxdg_surface_v6_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaWaylandZxdgSurfaceV6 *xdg_surface = META_WAYLAND_ZXDG_SURFACE_V6 (object); - MetaWaylandZxdgSurfaceV6Private *priv = - meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface); - - switch (prop_id) - { - case ZXDG_SURFACE_V6_PROP_SHELL_CLIENT: - priv->shell_client = g_value_get_pointer (value); - break; - - case ZXDG_SURFACE_V6_PROP_RESOURCE: - priv->resource = g_value_get_pointer (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_wayland_zxdg_surface_v6_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaWaylandZxdgSurfaceV6 *xdg_surface = META_WAYLAND_ZXDG_SURFACE_V6 (object); - MetaWaylandZxdgSurfaceV6Private *priv = - meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface); - - switch (prop_id) - { - case ZXDG_SURFACE_V6_PROP_SHELL_CLIENT: - g_value_set_pointer (value, priv->shell_client); - break; - - case ZXDG_SURFACE_V6_PROP_RESOURCE: - g_value_set_pointer (value, priv->resource); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_wayland_zxdg_surface_v6_init (MetaWaylandZxdgSurfaceV6 *xdg_surface) -{ -} - -static void -meta_wayland_zxdg_surface_v6_class_init (MetaWaylandZxdgSurfaceV6Class *klass) -{ - GObjectClass *object_class; - MetaWaylandSurfaceRoleClass *surface_role_class; - MetaWaylandShellSurfaceClass *shell_surface_class; - GParamSpec *pspec; - - object_class = G_OBJECT_CLASS (klass); - object_class->finalize = meta_wayland_zxdg_surface_v6_finalize; - object_class->set_property = meta_wayland_zxdg_surface_v6_set_property; - object_class->get_property = meta_wayland_zxdg_surface_v6_get_property; - - surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass); - surface_role_class->apply_state = meta_wayland_zxdg_surface_v6_apply_state; - surface_role_class->post_apply_state = - meta_wayland_zxdg_surface_v6_post_apply_state; - surface_role_class->assigned = meta_wayland_zxdg_surface_v6_assigned; - - shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass); - shell_surface_class->ping = meta_wayland_zxdg_surface_v6_ping; - - klass->shell_client_destroyed = - meta_wayland_zxdg_surface_v6_real_shell_client_destroyed; - - pspec = g_param_spec_pointer ("shell-client", - "MetaWaylandZxdgShellV6Client", - "The shell client instance", - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, - ZXDG_SURFACE_V6_PROP_SHELL_CLIENT, - pspec); - pspec = g_param_spec_pointer ("xdg-surface-resource", - "xdg_surface wl_resource", - "The xdg_surface wl_resource instance", - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, - ZXDG_SURFACE_V6_PROP_RESOURCE, - pspec); -} - -static void -meta_wayland_zxdg_surface_v6_shell_client_destroyed (MetaWaylandZxdgSurfaceV6 *xdg_surface) -{ - MetaWaylandZxdgSurfaceV6Class *xdg_surface_class = - META_WAYLAND_ZXDG_SURFACE_V6_GET_CLASS (xdg_surface); - - xdg_surface_class->shell_client_destroyed (xdg_surface); -} - -static void -meta_wayland_zxdg_surface_v6_constructor_finalize (MetaWaylandZxdgSurfaceV6Constructor *constructor, - MetaWaylandZxdgSurfaceV6 *xdg_surface) -{ - MetaWaylandZxdgShellV6Client *shell_client = constructor->shell_client; - - shell_client->surface_constructors = - g_list_remove (shell_client->surface_constructors, constructor); - shell_client->surfaces = g_list_append (shell_client->surfaces, xdg_surface); - - wl_resource_set_implementation (constructor->resource, - &meta_wayland_zxdg_surface_v6_interface, - xdg_surface, - zxdg_surface_v6_destructor); - - g_free (constructor); -} - -static void -zxdg_surface_v6_constructor_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_post_error (resource, - ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED, - "xdg_surface destroyed before constructed"); - wl_resource_destroy (resource); -} - -static void -zxdg_surface_v6_constructor_get_toplevel (struct wl_client *client, - struct wl_resource *resource, - uint32_t id) -{ - MetaWaylandZxdgSurfaceV6Constructor *constructor = - wl_resource_get_user_data (resource); - MetaWaylandZxdgShellV6Client *shell_client = constructor->shell_client; - struct wl_resource *xdg_surface_resource = constructor->resource; - MetaWaylandSurface *surface = constructor->surface; - MetaWaylandZxdgToplevelV6 *xdg_toplevel; - MetaWaylandZxdgSurfaceV6 *xdg_surface; - MetaWaylandShellSurface *shell_surface; - MetaWindow *window; - - if (!meta_wayland_surface_assign_role (surface, - META_TYPE_WAYLAND_ZXDG_TOPLEVEL_V6, - "shell-client", shell_client, - "xdg-surface-resource", xdg_surface_resource, - NULL)) - { - wl_resource_post_error (resource, ZXDG_SHELL_V6_ERROR_ROLE, - "wl_surface@%d already has a different role", - wl_resource_get_id (surface->resource)); - return; - } - - xdg_toplevel = META_WAYLAND_ZXDG_TOPLEVEL_V6 (surface->role); - xdg_toplevel->resource = wl_resource_create (client, - &zxdg_toplevel_v6_interface, - wl_resource_get_version (resource), - id); - wl_resource_set_implementation (xdg_toplevel->resource, - &meta_wayland_zxdg_toplevel_v6_interface, - xdg_toplevel, - zxdg_toplevel_v6_destructor); - - xdg_surface = META_WAYLAND_ZXDG_SURFACE_V6 (xdg_toplevel); - meta_wayland_zxdg_surface_v6_constructor_finalize (constructor, xdg_surface); - - window = meta_window_wayland_new (meta_get_display (), surface); - shell_surface = META_WAYLAND_SHELL_SURFACE (xdg_surface); - meta_wayland_shell_surface_set_window (shell_surface, window); -} - -static void -zxdg_surface_v6_constructor_get_popup (struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *parent_resource, - struct wl_resource *positioner_resource) -{ - MetaWaylandZxdgSurfaceV6Constructor *constructor = - wl_resource_get_user_data (resource); - MetaWaylandZxdgShellV6Client *shell_client = constructor->shell_client; - MetaWaylandSurface *surface = constructor->surface; - struct wl_resource *xdg_shell_resource = constructor->shell_client->resource; - struct wl_resource *xdg_surface_resource = constructor->resource; - MetaWaylandSurface *parent_surface = - surface_from_xdg_surface_resource (parent_resource); - MetaWaylandZxdgPositionerV6 *xdg_positioner; - MetaWaylandZxdgPopupV6 *xdg_popup; - MetaWaylandZxdgSurfaceV6 *xdg_surface; - - if (!meta_wayland_surface_assign_role (surface, - META_TYPE_WAYLAND_ZXDG_POPUP_V6, - "shell-client", shell_client, - "xdg-surface-resource", xdg_surface_resource, - NULL)) - { - wl_resource_post_error (xdg_shell_resource, ZXDG_SHELL_V6_ERROR_ROLE, - "wl_surface@%d already has a different role", - wl_resource_get_id (surface->resource)); - return; - } - - if (!META_IS_WAYLAND_ZXDG_SURFACE_V6 (parent_surface->role)) - { - wl_resource_post_error (xdg_shell_resource, - ZXDG_SHELL_V6_ERROR_INVALID_POPUP_PARENT, - "Invalid popup parent role"); - return; - } - - xdg_popup = META_WAYLAND_ZXDG_POPUP_V6 (surface->role); - - xdg_popup->resource = wl_resource_create (client, - &zxdg_popup_v6_interface, - wl_resource_get_version (resource), - id); - wl_resource_set_implementation (xdg_popup->resource, - &meta_wayland_zxdg_popup_v6_interface, - xdg_popup, - zxdg_popup_v6_destructor); - - xdg_surface = META_WAYLAND_ZXDG_SURFACE_V6 (xdg_popup); - meta_wayland_zxdg_surface_v6_constructor_finalize (constructor, xdg_surface); - - xdg_positioner = wl_resource_get_user_data (positioner_resource); - xdg_popup->setup.placement_rule = - meta_wayland_zxdg_positioner_v6_to_placement (xdg_positioner); - xdg_popup->setup.parent_surface = parent_surface; -} - -static void -zxdg_surface_v6_constructor_set_window_geometry (struct wl_client *client, - struct wl_resource *resource, - int32_t x, - int32_t y, - int32_t width, - int32_t height) -{ - wl_resource_post_error (resource, - ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED, - "xdg_surface::set_window_geometry called before constructed"); -} - -static void -zxdg_surface_v6_constructor_ack_configure (struct wl_client *client, - struct wl_resource *resource, - uint32_t serial) -{ - wl_resource_post_error (resource, - ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED, - "xdg_surface::ack_configure called before constructed"); -} - -static const struct zxdg_surface_v6_interface meta_wayland_zxdg_surface_v6_constructor_interface = { - zxdg_surface_v6_constructor_destroy, - zxdg_surface_v6_constructor_get_toplevel, - zxdg_surface_v6_constructor_get_popup, - zxdg_surface_v6_constructor_set_window_geometry, - zxdg_surface_v6_constructor_ack_configure, -}; - -static void -zxdg_surface_v6_constructor_destructor (struct wl_resource *resource) -{ - MetaWaylandZxdgSurfaceV6Constructor *constructor = - wl_resource_get_user_data (resource); - - constructor->shell_client->surface_constructors = - g_list_remove (constructor->shell_client->surface_constructors, - constructor); - - g_free (constructor); -} - -static MetaPlacementRule -meta_wayland_zxdg_positioner_v6_to_placement (MetaWaylandZxdgPositionerV6 *xdg_positioner) -{ - return (MetaPlacementRule) { - .anchor_rect = xdg_positioner->anchor_rect, - .gravity = xdg_positioner->gravity, - .anchor = xdg_positioner->anchor, - .constraint_adjustment = xdg_positioner->constraint_adjustment, - .offset_x = xdg_positioner->offset_x, - .offset_y = xdg_positioner->offset_y, - .width = xdg_positioner->width, - .height = xdg_positioner->height, - }; -} - -static void -zxdg_positioner_v6_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -zxdg_positioner_v6_set_size (struct wl_client *client, - struct wl_resource *resource, - int32_t width, - int32_t height) -{ - MetaWaylandZxdgPositionerV6 *positioner = wl_resource_get_user_data (resource); - - if (width <= 0 || height <= 0) - { - wl_resource_post_error (resource, ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT, - "Invalid size"); - return; - } - - positioner->width = width; - positioner->height = height; -} - -static void -zxdg_positioner_v6_set_anchor_rect (struct wl_client *client, - struct wl_resource *resource, - int32_t x, - int32_t y, - int32_t width, - int32_t height) -{ - MetaWaylandZxdgPositionerV6 *positioner = wl_resource_get_user_data (resource); - - if (width <= 0 || height <= 0) - { - wl_resource_post_error (resource, ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT, - "Invalid anchor rectangle size"); - return; - } - - positioner->anchor_rect = (MetaRectangle) { - .x = x, - .y = y, - .width = width, - .height = height, - }; -} - -static void -zxdg_positioner_v6_set_anchor (struct wl_client *client, - struct wl_resource *resource, - uint32_t anchor) -{ - MetaWaylandZxdgPositionerV6 *positioner = wl_resource_get_user_data (resource); - - if ((anchor & ZXDG_POSITIONER_V6_ANCHOR_LEFT && - anchor & ZXDG_POSITIONER_V6_ANCHOR_RIGHT) || - (anchor & ZXDG_POSITIONER_V6_ANCHOR_TOP && - anchor & ZXDG_POSITIONER_V6_ANCHOR_BOTTOM)) - { - wl_resource_post_error (resource, ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT, - "Invalid anchor"); - return; - } - - positioner->anchor = anchor; -} - -static void -zxdg_positioner_v6_set_gravity (struct wl_client *client, - struct wl_resource *resource, - uint32_t gravity) -{ - MetaWaylandZxdgPositionerV6 *positioner = wl_resource_get_user_data (resource); - - if ((gravity & ZXDG_POSITIONER_V6_GRAVITY_LEFT && - gravity & ZXDG_POSITIONER_V6_GRAVITY_RIGHT) || - (gravity & ZXDG_POSITIONER_V6_GRAVITY_TOP && - gravity & ZXDG_POSITIONER_V6_GRAVITY_BOTTOM)) - { - wl_resource_post_error (resource, ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT, - "Invalid gravity"); - return; - } - - positioner->gravity = gravity; -} - -static void -zxdg_positioner_v6_set_constraint_adjustment (struct wl_client *client, - struct wl_resource *resource, - uint32_t constraint_adjustment) -{ - MetaWaylandZxdgPositionerV6 *positioner = wl_resource_get_user_data (resource); - uint32_t all_adjustments = (ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_X | - ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_X | - ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_SLIDE_Y | - ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_FLIP_Y | - ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_X | - ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_RESIZE_Y); - - if ((constraint_adjustment & ~all_adjustments) != 0) - { - wl_resource_post_error (resource, ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT, - "Invalid constraint action"); - return; - } - - positioner->constraint_adjustment = constraint_adjustment; -} - -static void -zxdg_positioner_v6_set_offset (struct wl_client *client, - struct wl_resource *resource, - int32_t x, - int32_t y) -{ - MetaWaylandZxdgPositionerV6 *positioner = wl_resource_get_user_data (resource); - - positioner->offset_x = x; - positioner->offset_y = y; -} - -static const struct zxdg_positioner_v6_interface meta_wayland_zxdg_positioner_v6_interface = { - zxdg_positioner_v6_destroy, - zxdg_positioner_v6_set_size, - zxdg_positioner_v6_set_anchor_rect, - zxdg_positioner_v6_set_anchor, - zxdg_positioner_v6_set_gravity, - zxdg_positioner_v6_set_constraint_adjustment, - zxdg_positioner_v6_set_offset, -}; - -static void -zxdg_positioner_v6_destructor (struct wl_resource *resource) -{ - MetaWaylandZxdgPositionerV6 *positioner = wl_resource_get_user_data (resource); - - g_free (positioner); -} - -static void -zxdg_shell_v6_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - MetaWaylandZxdgShellV6Client *shell_client = wl_resource_get_user_data (resource); - - if (shell_client->surfaces || shell_client->surface_constructors) - wl_resource_post_error (resource, ZXDG_SHELL_V6_ERROR_DEFUNCT_SURFACES, - "xdg_shell destroyed before its surfaces"); - - wl_resource_destroy (resource); -} - -static void -zxdg_shell_v6_create_positioner (struct wl_client *client, - struct wl_resource *resource, - uint32_t id) -{ - MetaWaylandZxdgPositionerV6 *positioner; - struct wl_resource *positioner_resource; - - positioner = g_new0 (MetaWaylandZxdgPositionerV6, 1); - positioner_resource = wl_resource_create (client, - &zxdg_positioner_v6_interface, - wl_resource_get_version (resource), - id); - wl_resource_set_implementation (positioner_resource, - &meta_wayland_zxdg_positioner_v6_interface, - positioner, - zxdg_positioner_v6_destructor); -} - -static void -zxdg_shell_v6_get_xdg_surface (struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *surface_resource) -{ - MetaWaylandZxdgShellV6Client *shell_client = wl_resource_get_user_data (resource); - MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); - MetaWaylandZxdgSurfaceV6 *xdg_surface = NULL; - MetaWaylandZxdgSurfaceV6Constructor *constructor; - - if (surface->role && !META_IS_WAYLAND_ZXDG_SURFACE_V6 (surface->role)) - { - wl_resource_post_error (resource, ZXDG_SHELL_V6_ERROR_ROLE, - "wl_surface@%d already has a different role", - wl_resource_get_id (surface->resource)); - return; - } - - if (surface->role) - xdg_surface = META_WAYLAND_ZXDG_SURFACE_V6 (surface->role); - if (xdg_surface && meta_wayland_zxdg_surface_v6_is_assigned (xdg_surface)) - { - wl_resource_post_error (surface_resource, - WL_DISPLAY_ERROR_INVALID_OBJECT, - "zxdg_shell_v6::get_xdg_surface already requested"); - return; - } - - if (surface->buffer_ref->buffer) - { - wl_resource_post_error (resource, - ZXDG_SHELL_V6_ERROR_INVALID_SURFACE_STATE, - "wl_surface@%d already has a buffer committed", - wl_resource_get_id (surface->resource)); - return; - } - - constructor = g_new0 (MetaWaylandZxdgSurfaceV6Constructor, 1); - constructor->surface = surface; - constructor->shell_client = shell_client; - constructor->resource = wl_resource_create (client, - &zxdg_surface_v6_interface, - wl_resource_get_version (resource), - id); - wl_resource_set_implementation (constructor->resource, - &meta_wayland_zxdg_surface_v6_constructor_interface, - constructor, - zxdg_surface_v6_constructor_destructor); - - shell_client->surface_constructors = - g_list_append (shell_client->surface_constructors, constructor); -} - -static void -zxdg_shell_v6_pong (struct wl_client *client, - struct wl_resource *resource, - uint32_t serial) -{ - MetaDisplay *display = meta_get_display (); - - meta_display_pong_for_serial (display, serial); -} - -static const struct zxdg_shell_v6_interface meta_wayland_zxdg_shell_v6_interface = { - zxdg_shell_v6_destroy, - zxdg_shell_v6_create_positioner, - zxdg_shell_v6_get_xdg_surface, - zxdg_shell_v6_pong, -}; - -static void -meta_wayland_zxdg_shell_v6_client_destroy (MetaWaylandZxdgShellV6Client *shell_client) -{ - while (shell_client->surface_constructors) - { - MetaWaylandZxdgSurfaceV6Constructor *constructor = - g_list_first (shell_client->surface_constructors)->data; - - wl_resource_destroy (constructor->resource); - } - g_list_free (shell_client->surface_constructors); - - while (shell_client->surfaces) - { - MetaWaylandZxdgSurfaceV6 *xdg_surface = - g_list_first (shell_client->surfaces)->data; - - meta_wayland_zxdg_surface_v6_shell_client_destroyed (xdg_surface); - } - g_list_free (shell_client->surfaces); - - g_free (shell_client); -} - -static void -zxdg_shell_v6_destructor (struct wl_resource *resource) -{ - MetaWaylandZxdgShellV6Client *shell_client = wl_resource_get_user_data (resource); - - meta_wayland_zxdg_shell_v6_client_destroy (shell_client); -} - -static void -bind_zxdg_shell_v6 (struct wl_client *client, - void *data, - guint32 version, - guint32 id) -{ - MetaWaylandZxdgShellV6Client *shell_client; - - shell_client = g_new0 (MetaWaylandZxdgShellV6Client, 1); - - shell_client->resource = wl_resource_create (client, - &zxdg_shell_v6_interface, - version, id); - wl_resource_set_implementation (shell_client->resource, - &meta_wayland_zxdg_shell_v6_interface, - shell_client, zxdg_shell_v6_destructor); -} - -void -meta_wayland_legacy_xdg_shell_init (MetaWaylandCompositor *compositor) -{ - if (wl_global_create (compositor->wayland_display, - &zxdg_shell_v6_interface, - META_ZXDG_SHELL_V6_VERSION, - compositor, bind_zxdg_shell_v6) == NULL) - g_error ("Failed to register a global xdg-shell object"); -} diff --git a/src/wayland/meta-wayland-legacy-xdg-shell.h b/src/wayland/meta-wayland-legacy-xdg-shell.h deleted file mode 100644 index 8a07dfb29..000000000 --- a/src/wayland/meta-wayland-legacy-xdg-shell.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2013-2015 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_WAYLAND_LEGACY_XDG_SHELL_H -#define META_WAYLAND_LEGACY_XDG_SHELL_H - -#include "wayland/meta-wayland-shell-surface.h" -#include "wayland/meta-wayland-surface.h" - -#define META_TYPE_WAYLAND_ZXDG_SURFACE_V6 (meta_wayland_zxdg_surface_v6_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaWaylandZxdgSurfaceV6, - meta_wayland_zxdg_surface_v6, - META, WAYLAND_ZXDG_SURFACE_V6, - MetaWaylandShellSurface) - -struct _MetaWaylandZxdgSurfaceV6Class -{ - MetaWaylandShellSurfaceClass parent_class; - - void (*shell_client_destroyed) (MetaWaylandZxdgSurfaceV6 *xdg_surface); -}; - -#define META_TYPE_WAYLAND_ZXDG_TOPLEVEL_V6 (meta_wayland_zxdg_toplevel_v6_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandZxdgToplevelV6, - meta_wayland_zxdg_toplevel_v6, - META, WAYLAND_ZXDG_TOPLEVEL_V6, - MetaWaylandZxdgSurfaceV6); - -#define META_TYPE_WAYLAND_ZXDG_POPUP_V6 (meta_wayland_zxdg_popup_v6_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandZxdgPopupV6, - meta_wayland_zxdg_popup_v6, - META, WAYLAND_ZXDG_POPUP_V6, - MetaWaylandZxdgSurfaceV6); - -void meta_wayland_legacy_xdg_shell_init (MetaWaylandCompositor *compositor); - -#endif /* META_WAYLAND_LEGACY_XDG_SHELL_H */ diff --git a/src/wayland/meta-wayland-outputs.c b/src/wayland/meta-wayland-outputs.c deleted file mode 100644 index 6c766ea51..000000000 --- a/src/wayland/meta-wayland-outputs.c +++ /dev/null @@ -1,750 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -#include "config.h" - -#include "wayland/meta-wayland-outputs.h" - -#include - -#include "backends/meta-logical-monitor.h" -#include "backends/meta-monitor.h" -#include "backends/meta-monitor-manager-private.h" -#include "wayland/meta-wayland-private.h" - -#include "xdg-output-unstable-v1-server-protocol.h" - -/* Wayland protocol headers list new additions, not deprecations */ -#define NO_XDG_OUTPUT_DONE_SINCE_VERSION 3 - -enum -{ - OUTPUT_DESTROYED, - OUTPUT_BOUND, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL]; - -G_DEFINE_TYPE (MetaWaylandOutput, meta_wayland_output, G_TYPE_OBJECT) - -static void -send_xdg_output_events (struct wl_resource *resource, - MetaWaylandOutput *wayland_output, - MetaLogicalMonitor *logical_monitor, - gboolean need_all_events, - gboolean *pending_done_event); - -static void -output_resource_destroy (struct wl_resource *res) -{ - MetaWaylandOutput *wayland_output; - - wayland_output = wl_resource_get_user_data (res); - if (!wayland_output) - return; - - wayland_output->resources = g_list_remove (wayland_output->resources, res); -} - -static MetaMonitor * -pick_main_monitor (MetaLogicalMonitor *logical_monitor) -{ - GList *monitors; - - monitors = meta_logical_monitor_get_monitors (logical_monitor); - return g_list_first (monitors)->data; -} - -static enum wl_output_subpixel -cogl_subpixel_order_to_wl_output_subpixel (CoglSubpixelOrder subpixel_order) -{ - switch (subpixel_order) - { - case COGL_SUBPIXEL_ORDER_UNKNOWN: - return WL_OUTPUT_SUBPIXEL_UNKNOWN; - case COGL_SUBPIXEL_ORDER_NONE: - return WL_OUTPUT_SUBPIXEL_NONE; - case COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB: - return WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB; - case COGL_SUBPIXEL_ORDER_HORIZONTAL_BGR: - return WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR; - case COGL_SUBPIXEL_ORDER_VERTICAL_RGB: - return WL_OUTPUT_SUBPIXEL_VERTICAL_RGB; - case COGL_SUBPIXEL_ORDER_VERTICAL_BGR: - return WL_OUTPUT_SUBPIXEL_VERTICAL_BGR; - } - - g_assert_not_reached (); - return WL_OUTPUT_SUBPIXEL_UNKNOWN; -} - -static enum wl_output_subpixel -calculate_suitable_subpixel_order (MetaLogicalMonitor *logical_monitor) -{ - GList *monitors; - GList *l; - MetaMonitor *first_monitor; - CoglSubpixelOrder subpixel_order; - - monitors = meta_logical_monitor_get_monitors (logical_monitor); - first_monitor = monitors->data; - subpixel_order = meta_monitor_get_subpixel_order (first_monitor); - - for (l = monitors->next; l; l = l->next) - { - MetaMonitor *monitor = l->data; - - if (meta_monitor_get_subpixel_order (monitor) != subpixel_order) - { - subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN; - break; - } - } - - return cogl_subpixel_order_to_wl_output_subpixel (subpixel_order); -} - -static int -calculate_wayland_output_scale (MetaLogicalMonitor *logical_monitor) -{ - float scale; - - scale = meta_logical_monitor_get_scale (logical_monitor); - return ceilf (scale); -} - -static void -get_rotated_physical_dimensions (MetaMonitor *monitor, - int *width_mm, - int *height_mm) -{ - int monitor_width_mm, monitor_height_mm; - MetaLogicalMonitor *logical_monitor; - - meta_monitor_get_physical_dimensions (monitor, - &monitor_width_mm, - &monitor_height_mm); - logical_monitor = meta_monitor_get_logical_monitor (monitor); - - if (meta_monitor_transform_is_rotated (logical_monitor->transform)) - { - *width_mm = monitor_height_mm; - *height_mm = monitor_width_mm; - } - else - { - *width_mm = monitor_width_mm; - *height_mm = monitor_height_mm; - } -} - -static gboolean -is_different_rotation (MetaLogicalMonitor *a, - MetaLogicalMonitor *b) -{ - return (meta_monitor_transform_is_rotated (a->transform) != - meta_monitor_transform_is_rotated (b->transform)); -} - -static void -get_native_output_mode_resolution (MetaLogicalMonitor *logical_monitor, - MetaMonitorMode *mode, - int *mode_width, - int *mode_height) -{ - MetaMonitorTransform transform; - - transform = meta_logical_monitor_get_transform (logical_monitor); - if (meta_monitor_transform_is_rotated (transform)) - meta_monitor_mode_get_resolution (mode, mode_height, mode_width); - else - meta_monitor_mode_get_resolution (mode, mode_width, mode_height); -} - -static void -send_output_events (struct wl_resource *resource, - MetaWaylandOutput *wayland_output, - MetaLogicalMonitor *logical_monitor, - gboolean need_all_events, - gboolean *pending_done_event) -{ - int version = wl_resource_get_version (resource); - MetaMonitor *monitor; - MetaMonitorMode *current_mode; - MetaMonitorMode *preferred_mode; - guint mode_flags = WL_OUTPUT_MODE_CURRENT; - MetaLogicalMonitor *old_logical_monitor; - guint old_mode_flags; - gint old_scale; - float old_refresh_rate; - float refresh_rate; - int new_width, new_height; - - old_logical_monitor = wayland_output->logical_monitor; - old_mode_flags = wayland_output->mode_flags; - old_scale = wayland_output->scale; - old_refresh_rate = wayland_output->refresh_rate; - - monitor = pick_main_monitor (logical_monitor); - - current_mode = meta_monitor_get_current_mode (monitor); - refresh_rate = meta_monitor_mode_get_refresh_rate (current_mode); - - gboolean need_done = FALSE; - - if (need_all_events || - old_logical_monitor->rect.x != logical_monitor->rect.x || - old_logical_monitor->rect.y != logical_monitor->rect.y || - is_different_rotation (old_logical_monitor, logical_monitor)) - { - int width_mm, height_mm; - const char *vendor; - const char *product; - uint32_t transform; - enum wl_output_subpixel subpixel_order; - - /* - * While the wl_output carries information specific to a single monitor, - * it is actually referring to a region of the compositor's screen region - * (logical monitor), which may consist of multiple monitors (clones). - * Arbitrarily use whatever monitor is the first in the logical monitor - * and use that for these details. - */ - get_rotated_physical_dimensions (monitor, &width_mm, &height_mm); - vendor = meta_monitor_get_vendor (monitor); - product = meta_monitor_get_product (monitor); - - subpixel_order = calculate_suitable_subpixel_order (logical_monitor); - - /* - * TODO: When we support wl_surface.set_buffer_transform, pass along - * the correct transform here instead of always pretending its 'normal'. - * The reason for this is to try stopping clients from setting any buffer - * transform other than 'normal'. - */ - transform = WL_OUTPUT_TRANSFORM_NORMAL; - - wl_output_send_geometry (resource, - logical_monitor->rect.x, - logical_monitor->rect.y, - width_mm, - height_mm, - subpixel_order, - vendor, - product, - transform); - need_done = TRUE; - } - - preferred_mode = meta_monitor_get_preferred_mode (monitor); - if (current_mode == preferred_mode) - mode_flags |= WL_OUTPUT_MODE_PREFERRED; - - get_native_output_mode_resolution (logical_monitor, - current_mode, - &new_width, - &new_height); - if (need_all_events || - wayland_output->mode_width != new_width || - wayland_output->mode_height != new_height || - old_refresh_rate != refresh_rate || - old_mode_flags != mode_flags) - { - wl_output_send_mode (resource, - mode_flags, - new_width, - new_height, - (int32_t) (refresh_rate * 1000)); - need_done = TRUE; - } - - if (version >= WL_OUTPUT_SCALE_SINCE_VERSION) - { - int scale; - - scale = calculate_wayland_output_scale (logical_monitor); - if (need_all_events || - old_scale != scale) - { - wl_output_send_scale (resource, scale); - need_done = TRUE; - } - } - - if (need_all_events && version >= WL_OUTPUT_DONE_SINCE_VERSION) - { - wl_output_send_done (resource); - need_done = FALSE; - } - - if (pending_done_event && need_done) - *pending_done_event = TRUE; -} - -static void -bind_output (struct wl_client *client, - void *data, - guint32 version, - guint32 id) -{ - MetaWaylandOutput *wayland_output = data; - MetaLogicalMonitor *logical_monitor = wayland_output->logical_monitor; - struct wl_resource *resource; -#ifdef WITH_VERBOSE_MODE - MetaMonitor *monitor; -#endif - - resource = wl_resource_create (client, &wl_output_interface, version, id); - wayland_output->resources = g_list_prepend (wayland_output->resources, resource); - - wl_resource_set_user_data (resource, wayland_output); - wl_resource_set_destructor (resource, output_resource_destroy); - - if (!logical_monitor) - return; - -#ifdef WITH_VERBOSE_MODE - monitor = pick_main_monitor (logical_monitor); - - meta_verbose ("Binding monitor %p/%s (%u, %u, %u, %u) x %f", - logical_monitor, - meta_monitor_get_product (monitor), - logical_monitor->rect.x, logical_monitor->rect.y, - wayland_output->mode_width, - wayland_output->mode_height, - wayland_output->refresh_rate); -#endif - - send_output_events (resource, wayland_output, logical_monitor, TRUE, NULL); - - g_signal_emit (wayland_output, signals[OUTPUT_BOUND], 0, resource); -} - -static void -meta_wayland_output_set_logical_monitor (MetaWaylandOutput *wayland_output, - MetaLogicalMonitor *logical_monitor) -{ - MetaMonitor *monitor; - MetaMonitorMode *current_mode; - MetaMonitorMode *preferred_mode; - - wayland_output->logical_monitor = logical_monitor; - wayland_output->mode_flags = WL_OUTPUT_MODE_CURRENT; - - monitor = pick_main_monitor (logical_monitor); - current_mode = meta_monitor_get_current_mode (monitor); - preferred_mode = meta_monitor_get_preferred_mode (monitor); - - if (current_mode == preferred_mode) - wayland_output->mode_flags |= WL_OUTPUT_MODE_PREFERRED; - wayland_output->scale = calculate_wayland_output_scale (logical_monitor); - wayland_output->refresh_rate = meta_monitor_mode_get_refresh_rate (current_mode); - - wayland_output->winsys_id = logical_monitor->winsys_id; - get_native_output_mode_resolution (logical_monitor, - current_mode, - &wayland_output->mode_width, - &wayland_output->mode_height); -} - -static void -wayland_output_update_for_output (MetaWaylandOutput *wayland_output, - MetaLogicalMonitor *logical_monitor) -{ - GList *iter; - gboolean pending_done_event; - - pending_done_event = FALSE; - for (iter = wayland_output->resources; iter; iter = iter->next) - { - struct wl_resource *resource = iter->data; - send_output_events (resource, wayland_output, logical_monitor, FALSE, &pending_done_event); - } - - for (iter = wayland_output->xdg_output_resources; iter; iter = iter->next) - { - struct wl_resource *xdg_output = iter->data; - send_xdg_output_events (xdg_output, wayland_output, logical_monitor, FALSE, &pending_done_event); - } - - /* Send the "done" events if needed */ - if (pending_done_event) - { - for (iter = wayland_output->resources; iter; iter = iter->next) - { - struct wl_resource *resource = iter->data; - if (wl_resource_get_version (resource) >= WL_OUTPUT_DONE_SINCE_VERSION) - wl_output_send_done (resource); - } - - for (iter = wayland_output->xdg_output_resources; iter; iter = iter->next) - { - struct wl_resource *xdg_output = iter->data; - if (wl_resource_get_version (xdg_output) < NO_XDG_OUTPUT_DONE_SINCE_VERSION) - zxdg_output_v1_send_done (xdg_output); - } - } - /* It's very important that we change the output pointer here, as - the old structure is about to be freed by MetaMonitorManager */ - meta_wayland_output_set_logical_monitor (wayland_output, logical_monitor); -} - -static MetaWaylandOutput * -meta_wayland_output_new (MetaWaylandCompositor *compositor, - MetaLogicalMonitor *logical_monitor) -{ - MetaWaylandOutput *wayland_output; - - wayland_output = g_object_new (META_TYPE_WAYLAND_OUTPUT, NULL); - wayland_output->global = wl_global_create (compositor->wayland_display, - &wl_output_interface, - META_WL_OUTPUT_VERSION, - wayland_output, bind_output); - meta_wayland_compositor_flush_clients (compositor); - meta_wayland_output_set_logical_monitor (wayland_output, logical_monitor); - - return wayland_output; -} - -static void -make_output_resources_inert (MetaWaylandOutput *wayland_output) -{ - GList *l; - - for (l = wayland_output->resources; l; l = l->next) - { - struct wl_resource *output_resource = l->data; - - wl_resource_set_user_data (output_resource, NULL); - } - g_list_free (wayland_output->resources); - wayland_output->resources = NULL; - - for (l = wayland_output->xdg_output_resources; l; l = l->next) - { - struct wl_resource *xdg_output_resource = l->data; - - wl_resource_set_user_data (xdg_output_resource, NULL); - } - g_list_free (wayland_output->xdg_output_resources); - wayland_output->xdg_output_resources = NULL; -} - -static void -make_output_inert (gpointer key, - gpointer value, - gpointer data) -{ - MetaWaylandOutput *wayland_output = value; - - g_signal_emit (wayland_output, signals[OUTPUT_DESTROYED], 0); - - wayland_output->logical_monitor = NULL; - make_output_resources_inert (wayland_output); -} - -static gboolean -delayed_destroy_outputs (gpointer data) -{ - g_hash_table_destroy (data); - return G_SOURCE_REMOVE; -} - -static GHashTable * -meta_wayland_compositor_update_outputs (MetaWaylandCompositor *compositor, - MetaMonitorManager *monitor_manager) -{ - GHashTable *new_table; - GList *logical_monitors, *l; - - logical_monitors = - meta_monitor_manager_get_logical_monitors (monitor_manager); - new_table = g_hash_table_new_full (g_int64_hash, g_int64_equal, NULL, - g_object_unref); - - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - MetaWaylandOutput *wayland_output = NULL; - - if (logical_monitor->winsys_id == 0) - continue; - - wayland_output = g_hash_table_lookup (compositor->outputs, - &logical_monitor->winsys_id); - - if (wayland_output) - { - g_hash_table_steal (compositor->outputs, - &logical_monitor->winsys_id); - } - else - { - wayland_output = meta_wayland_output_new (compositor, logical_monitor); - } - - wayland_output_update_for_output (wayland_output, logical_monitor); - g_hash_table_insert (new_table, - &wayland_output->winsys_id, - wayland_output); - } - - g_hash_table_foreach (compositor->outputs, make_output_inert, NULL); - g_timeout_add_seconds (10, delayed_destroy_outputs, compositor->outputs); - - return new_table; -} - -static void -on_monitors_changed (MetaMonitorManager *monitors, - MetaWaylandCompositor *compositor) -{ - compositor->outputs = meta_wayland_compositor_update_outputs (compositor, monitors); -} - -static void -meta_wayland_output_init (MetaWaylandOutput *wayland_output) -{ -} - -static void -meta_wayland_output_finalize (GObject *object) -{ - MetaWaylandOutput *wayland_output = META_WAYLAND_OUTPUT (object); - - wl_global_destroy (wayland_output->global); - - /* Make sure the wl_output destructor doesn't try to access MetaWaylandOutput - * after we have freed it. - */ - make_output_resources_inert (wayland_output); - - G_OBJECT_CLASS (meta_wayland_output_parent_class)->finalize (object); -} - -static void -meta_wayland_output_class_init (MetaWaylandOutputClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_wayland_output_finalize; - - signals[OUTPUT_DESTROYED] = g_signal_new ("output-destroyed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); - - signals[OUTPUT_BOUND] = g_signal_new ("output-bound", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 1, - G_TYPE_POINTER); -} - -static void -meta_xdg_output_destructor (struct wl_resource *resource) -{ - MetaWaylandOutput *wayland_output; - - wayland_output = wl_resource_get_user_data (resource); - if (!wayland_output) - return; - - wayland_output->xdg_output_resources = - g_list_remove (wayland_output->xdg_output_resources, resource); -} - -static void -meta_xdg_output_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static const struct zxdg_output_v1_interface - meta_xdg_output_interface = { - meta_xdg_output_destroy, - }; - -static void -send_xdg_output_events (struct wl_resource *resource, - MetaWaylandOutput *wayland_output, - MetaLogicalMonitor *logical_monitor, - gboolean need_all_events, - gboolean *pending_done_event) -{ - MetaRectangle new_layout; - MetaRectangle old_layout; - MetaLogicalMonitor *old_logical_monitor; - MetaMonitor *monitor; - gboolean need_done; - int version; - - need_done = FALSE; - old_logical_monitor = wayland_output->logical_monitor; - old_layout = meta_logical_monitor_get_layout (old_logical_monitor); - new_layout = meta_logical_monitor_get_layout (logical_monitor); - - if (need_all_events || - old_layout.x != new_layout.x || - old_layout.y != new_layout.y) - { - zxdg_output_v1_send_logical_position (resource, - new_layout.x, - new_layout.y); - need_done = TRUE; - } - - if (need_all_events || - old_layout.width != new_layout.width || - old_layout.height != new_layout.height) - { - zxdg_output_v1_send_logical_size (resource, - new_layout.width, - new_layout.height); - need_done = TRUE; - } - - version = wl_resource_get_version (resource); - monitor = pick_main_monitor (logical_monitor); - - if (need_all_events && version >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) - { - const char *name; - - name = meta_monitor_get_connector (monitor); - zxdg_output_v1_send_name (resource, name); - } - - if (need_all_events && version >= ZXDG_OUTPUT_V1_DESCRIPTION_SINCE_VERSION) - { - const char *description; - - description = meta_monitor_get_display_name (monitor); - zxdg_output_v1_send_description (resource, description); - } - - if (pending_done_event && need_done) - *pending_done_event = TRUE; -} - -static void -meta_xdg_output_manager_get_xdg_output (struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *output) -{ - struct wl_resource *xdg_output_resource; - MetaWaylandOutput *wayland_output; - int xdg_output_version; - int wl_output_version; - - xdg_output_resource = wl_resource_create (client, - &zxdg_output_v1_interface, - wl_resource_get_version (resource), - id); - - wayland_output = wl_resource_get_user_data (output); - if (!wayland_output) - return; - - wl_resource_set_implementation (xdg_output_resource, - &meta_xdg_output_interface, - wayland_output, meta_xdg_output_destructor); - - wayland_output->xdg_output_resources = - g_list_prepend (wayland_output->xdg_output_resources, xdg_output_resource); - - if (!wayland_output->logical_monitor) - return; - - send_xdg_output_events (xdg_output_resource, - wayland_output, - wayland_output->logical_monitor, - TRUE, NULL); - - xdg_output_version = wl_resource_get_version (xdg_output_resource); - wl_output_version = wl_resource_get_version (output); - - if (xdg_output_version < NO_XDG_OUTPUT_DONE_SINCE_VERSION) - zxdg_output_v1_send_done (xdg_output_resource); - else if (wl_output_version >= WL_OUTPUT_DONE_SINCE_VERSION) - wl_output_send_done (output); -} - -static void -meta_xdg_output_manager_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static const struct zxdg_output_manager_v1_interface - meta_xdg_output_manager_interface = { - meta_xdg_output_manager_destroy, - meta_xdg_output_manager_get_xdg_output, - }; - -static void -bind_xdg_output_manager (struct wl_client *client, - void *data, - uint32_t version, - uint32_t id) -{ - struct wl_resource *resource; - - resource = wl_resource_create (client, - &zxdg_output_manager_v1_interface, - version, id); - - wl_resource_set_implementation (resource, - &meta_xdg_output_manager_interface, - NULL, NULL); -} - -void -meta_wayland_outputs_init (MetaWaylandCompositor *compositor) -{ - MetaMonitorManager *monitors; - - monitors = meta_monitor_manager_get (); - g_signal_connect (monitors, "monitors-changed-internal", - G_CALLBACK (on_monitors_changed), compositor); - - compositor->outputs = g_hash_table_new_full (g_int64_hash, g_int64_equal, NULL, - g_object_unref); - compositor->outputs = meta_wayland_compositor_update_outputs (compositor, monitors); - - wl_global_create (compositor->wayland_display, - &zxdg_output_manager_v1_interface, - META_ZXDG_OUTPUT_V1_VERSION, - NULL, - bind_xdg_output_manager); -} diff --git a/src/wayland/meta-wayland-outputs.h b/src/wayland/meta-wayland-outputs.h deleted file mode 100644 index 381febcdb..000000000 --- a/src/wayland/meta-wayland-outputs.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -#ifndef META_WAYLAND_OUTPUTS_H -#define META_WAYLAND_OUTPUTS_H - -#include "backends/meta-monitor-manager-private.h" -#include "wayland/meta-wayland-private.h" - -#define META_TYPE_WAYLAND_OUTPUT (meta_wayland_output_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandOutput, meta_wayland_output, - META, WAYLAND_OUTPUT, GObject) - -struct _MetaWaylandOutput -{ - GObject parent; - - struct wl_global *global; - MetaLogicalMonitor *logical_monitor; - guint mode_flags; - float refresh_rate; - gint scale; - int mode_width; - int mode_height; - - GList *resources; - GList *xdg_output_resources; - - uint64_t winsys_id; -}; - -void meta_wayland_outputs_init (MetaWaylandCompositor *compositor); - -#endif /* META_WAYLAND_OUTPUTS_H */ diff --git a/src/wayland/meta-wayland-pointer-constraints.c b/src/wayland/meta-wayland-pointer-constraints.c deleted file mode 100644 index 965b95dda..000000000 --- a/src/wayland/meta-wayland-pointer-constraints.c +++ /dev/null @@ -1,1201 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#include "config.h" - -#include "wayland/meta-wayland-pointer-constraints.h" - -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-pointer-constraint.h" -#include "core/frame.h" -#include "core/window-private.h" -#include "meta/meta-backend.h" -#include "wayland/meta-pointer-confinement-wayland.h" -#include "wayland/meta-pointer-lock-wayland.h" -#include "wayland/meta-wayland-pointer.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-region.h" -#include "wayland/meta-wayland-seat.h" -#include "wayland/meta-wayland-surface.h" -#include "wayland/meta-xwayland.h" - -#include "pointer-constraints-unstable-v1-server-protocol.h" - -static GQuark quark_pending_constraint_state = 0; -static GQuark quark_surface_pointer_constraints_data = 0; - -struct _MetaWaylandPointerConstraint -{ - GObject parent; - - MetaWaylandSurface *surface; - gboolean is_enabled; - cairo_region_t *region; - struct wl_resource *resource; - MetaWaylandPointerGrab grab; - MetaWaylandSeat *seat; - enum zwp_pointer_constraints_v1_lifetime lifetime; - gulong pointer_focus_surface_handler_id; - - gboolean hint_set; - wl_fixed_t x_hint; - wl_fixed_t y_hint; - - MetaPointerConfinementWayland *confinement; -}; - -typedef struct _MetaWaylandSurfacePointerConstraintsData -{ - MetaWaylandSurface *surface; - - GList *pointer_constraints; - - MetaWindow *window; - gulong window_associated_handler_id; - - gulong appears_changed_handler_id; - gulong raised_handler_id; -} MetaWaylandSurfacePointerConstraintsData; - -typedef struct -{ - MetaWaylandPointerConstraint *constraint; - cairo_region_t *region; - gulong applied_handler_id; -} MetaWaylandPendingConstraintState; - -typedef struct -{ - GList *pending_constraint_states; -} MetaWaylandPendingConstraintStateContainer; - -G_DEFINE_TYPE (MetaWaylandPointerConstraint, meta_wayland_pointer_constraint, - G_TYPE_OBJECT); - -static const struct zwp_locked_pointer_v1_interface locked_pointer_interface; -static const struct zwp_confined_pointer_v1_interface confined_pointer_interface; -static const MetaWaylandPointerGrabInterface locked_pointer_grab_interface; -static const MetaWaylandPointerGrabInterface confined_pointer_grab_interface; - -static void -meta_wayland_pointer_constraint_destroy (MetaWaylandPointerConstraint *constraint); - -static void -meta_wayland_pointer_constraint_maybe_enable (MetaWaylandPointerConstraint *constraint); - -static void -meta_wayland_pointer_constraint_maybe_enable_for_window (MetaWindow *window); - -static void -meta_wayland_pointer_constraint_maybe_remove_for_seat (MetaWaylandSeat *seat, - MetaWindow *window); - -static MetaWaylandSurfacePointerConstraintsData * -get_surface_constraints_data (MetaWaylandSurface *surface) -{ - return g_object_get_qdata (G_OBJECT (surface), - quark_surface_pointer_constraints_data); -} - -static void -appears_focused_changed (MetaWindow *window, - GParamSpec *pspec, - gpointer user_data) -{ - MetaWaylandCompositor *wayland_compositor; - - wayland_compositor = meta_wayland_compositor_get_default (); - meta_wayland_pointer_constraint_maybe_remove_for_seat (wayland_compositor->seat, - window); - - meta_wayland_pointer_constraint_maybe_enable_for_window (window); -} - -static void -window_raised (MetaWindow *window) -{ - meta_wayland_pointer_constraint_maybe_enable_for_window (window); -} - -static void -connect_window (MetaWaylandSurfacePointerConstraintsData *data, - MetaWindow *window) -{ - data->window = window; - g_object_add_weak_pointer (G_OBJECT (data->window), - (gpointer *) &data->window); - data->appears_changed_handler_id = - g_signal_connect (data->window, "notify::appears-focused", - G_CALLBACK (appears_focused_changed), NULL); - data->raised_handler_id = - g_signal_connect (data->window, "raised", - G_CALLBACK (window_raised), NULL); -} - -static void -window_associated (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfacePointerConstraintsData *data) -{ - MetaWaylandSurface *surface = data->surface; - MetaWindow *window; - - window = meta_wayland_surface_get_window (surface); - connect_window (data, window); - g_clear_signal_handler (&data->window_associated_handler_id, surface); - - meta_wayland_pointer_constraint_maybe_enable_for_window (window); -} - -static MetaWaylandSurfacePointerConstraintsData * -surface_constraint_data_new (MetaWaylandSurface *surface) -{ - MetaWaylandSurfacePointerConstraintsData *data; - MetaWindow *window; - - data = g_new0 (MetaWaylandSurfacePointerConstraintsData, 1); - - data->surface = surface; - - window = meta_wayland_surface_get_window (surface); - if (window) - { - connect_window (data, window); - } - else if (meta_xwayland_is_xwayland_surface (surface)) - { - data->window_associated_handler_id = - g_signal_connect (surface->role, "window-associated", - G_CALLBACK (window_associated), - data); - } - else - { - /* TODO: Support constraints on non-toplevel windows, such as subsurfaces. - */ - g_warn_if_reached (); - } - - return data; -} -static void -surface_constraint_data_free (MetaWaylandSurfacePointerConstraintsData *data) -{ - if (data->window) - { - g_clear_signal_handler (&data->appears_changed_handler_id, data->window); - g_clear_signal_handler (&data->raised_handler_id, data->window); - g_object_remove_weak_pointer (G_OBJECT (data->window), - (gpointer *) &data->window); - } - else - { - g_clear_signal_handler (&data->window_associated_handler_id, - data->surface->role); - } - - g_list_free_full (data->pointer_constraints, - (GDestroyNotify) meta_wayland_pointer_constraint_destroy); - g_free (data); -} - -static void -constrained_surface_destroyed (MetaWaylandSurface *surface, - MetaWaylandSurfacePointerConstraintsData *data) -{ - surface_constraint_data_free (data); -} - -static MetaWaylandSurfacePointerConstraintsData * -ensure_surface_constraints_data (MetaWaylandSurface *surface) -{ - MetaWaylandSurfacePointerConstraintsData *data; - - data = get_surface_constraints_data (surface); - if (!data) - { - data = surface_constraint_data_new (surface); - g_object_set_qdata (G_OBJECT (surface), - quark_surface_pointer_constraints_data, - data); - g_signal_connect (surface, "destroy", - G_CALLBACK (constrained_surface_destroyed), data); - } - - return data; -} - -static void -surface_add_pointer_constraint (MetaWaylandSurface *surface, - MetaWaylandPointerConstraint *constraint) -{ - MetaWaylandSurfacePointerConstraintsData *data; - - data = ensure_surface_constraints_data (surface); - data->pointer_constraints = g_list_append (data->pointer_constraints, - constraint); -} - -static void -surface_remove_pointer_constraints (MetaWaylandSurface *surface, - MetaWaylandPointerConstraint *constraint) -{ - MetaWaylandSurfacePointerConstraintsData *data; - - data = get_surface_constraints_data (surface); - data->pointer_constraints = - g_list_remove (data->pointer_constraints, constraint); - - if (!data->pointer_constraints) - { - g_object_set_qdata (G_OBJECT (surface), - quark_surface_pointer_constraints_data, - NULL); - } -} - -static void -pointer_focus_surface_changed (MetaWaylandPointer *pointer, - MetaWaylandPointerConstraint *constraint) -{ - MetaWindow *window; - - window = meta_wayland_surface_get_window (constraint->surface); - if (window) - { - MetaWaylandSeat *seat = meta_wayland_pointer_get_seat (pointer); - - meta_wayland_pointer_constraint_maybe_remove_for_seat (seat, window); - } - - meta_wayland_pointer_constraint_maybe_enable (constraint); -} - -static MetaWaylandPointerConstraint * -meta_wayland_pointer_constraint_new (MetaWaylandSurface *surface, - MetaWaylandSeat *seat, - MetaWaylandRegion *region, - enum zwp_pointer_constraints_v1_lifetime lifetime, - struct wl_resource *resource, - const MetaWaylandPointerGrabInterface *grab_interface) -{ - MetaWaylandPointerConstraint *constraint; - - constraint = g_object_new (META_TYPE_WAYLAND_POINTER_CONSTRAINT, NULL); - if (!constraint) - return NULL; - - constraint->surface = surface; - constraint->seat = seat; - constraint->lifetime = lifetime; - constraint->resource = resource; - constraint->grab.interface = grab_interface; - - if (region) - { - constraint->region = - cairo_region_copy (meta_wayland_region_peek_cairo_region (region)); - } - else - { - constraint->region = NULL; - } - - constraint->pointer_focus_surface_handler_id = - g_signal_connect (seat->pointer, "focus-surface-changed", - G_CALLBACK (pointer_focus_surface_changed), - constraint); - - return constraint; -} - -static gboolean -meta_wayland_pointer_constraint_is_enabled (MetaWaylandPointerConstraint *constraint) -{ - return constraint->is_enabled; -} - -static void -meta_wayland_pointer_constraint_notify_activated (MetaWaylandPointerConstraint *constraint) -{ - struct wl_resource *resource = constraint->resource; - - if (wl_resource_instance_of (resource, - &zwp_locked_pointer_v1_interface, - &locked_pointer_interface)) - { - zwp_locked_pointer_v1_send_locked (resource); - } - else if (wl_resource_instance_of (resource, - &zwp_confined_pointer_v1_interface, - &confined_pointer_interface)) - { - zwp_confined_pointer_v1_send_confined (resource); - } -} - -static void -meta_wayland_pointer_constraint_notify_deactivated (MetaWaylandPointerConstraint *constraint) -{ - struct wl_resource *resource = constraint->resource; - - if (wl_resource_instance_of (resource, - &zwp_locked_pointer_v1_interface, - &locked_pointer_interface)) - zwp_locked_pointer_v1_send_unlocked (resource); - else if (wl_resource_instance_of (resource, - &zwp_confined_pointer_v1_interface, - &confined_pointer_interface)) - zwp_confined_pointer_v1_send_unconfined (resource); -} - -static MetaPointerConfinementWayland * -meta_wayland_pointer_constraint_create_pointer_constraint (MetaWaylandPointerConstraint *constraint) -{ - struct wl_resource *resource = constraint->resource; - - if (wl_resource_instance_of (resource, - &zwp_locked_pointer_v1_interface, - &locked_pointer_interface)) - { - return meta_pointer_lock_wayland_new (constraint); - } - else if (wl_resource_instance_of (resource, - &zwp_confined_pointer_v1_interface, - &confined_pointer_interface)) - { - return meta_pointer_confinement_wayland_new (constraint); - } - g_assert_not_reached (); - return NULL; -} - -static void -meta_wayland_pointer_constraint_enable (MetaWaylandPointerConstraint *constraint) -{ - g_assert (!constraint->is_enabled); - - constraint->is_enabled = TRUE; - meta_wayland_pointer_constraint_notify_activated (constraint); - meta_wayland_pointer_start_grab (constraint->seat->pointer, - &constraint->grab); - - constraint->confinement = - meta_wayland_pointer_constraint_create_pointer_constraint (constraint); - meta_pointer_confinement_wayland_enable (constraint->confinement); - g_object_add_weak_pointer (G_OBJECT (constraint->confinement), - (gpointer *) &constraint->confinement); -} - -static void -meta_wayland_pointer_constraint_disable (MetaWaylandPointerConstraint *constraint) -{ - constraint->is_enabled = FALSE; - - if (constraint->confinement) - { - meta_pointer_confinement_wayland_disable (constraint->confinement); - g_object_unref (constraint->confinement); - } - - meta_wayland_pointer_constraint_notify_deactivated (constraint); - meta_wayland_pointer_end_grab (constraint->grab.pointer); -} - -void -meta_wayland_pointer_constraint_destroy (MetaWaylandPointerConstraint *constraint) -{ - if (meta_wayland_pointer_constraint_is_enabled (constraint)) - meta_wayland_pointer_constraint_disable (constraint); - - wl_resource_set_user_data (constraint->resource, NULL); - g_clear_pointer (&constraint->region, cairo_region_destroy); - g_object_unref (constraint); -} - -static gboolean -is_within_constraint_region (MetaWaylandPointerConstraint *constraint, - wl_fixed_t sx, - wl_fixed_t sy) -{ - cairo_region_t *region; - gboolean is_within; - - region = meta_wayland_pointer_constraint_calculate_effective_region (constraint); - is_within = cairo_region_contains_point (region, - wl_fixed_to_int (sx), - wl_fixed_to_int (sy)); - cairo_region_destroy (region); - - return is_within; -} - -static gboolean -should_constraint_be_enabled (MetaWaylandPointerConstraint *constraint) -{ - MetaWindow *window; - - window = meta_wayland_surface_get_window (constraint->surface); - if (!window) - { - /* - * Locks from Xwayland may come before we have had the opportunity to - * associate the X11 Window with the wl_surface. - */ - g_warn_if_fail (meta_xwayland_is_xwayland_surface (constraint->surface)); - return FALSE; - } - - if (window->unmanaging) - return FALSE; - - if (constraint->seat->pointer->focus_surface != constraint->surface) - return FALSE; - - if (meta_xwayland_is_xwayland_surface (constraint->surface)) - { - MetaDisplay *display = meta_get_display (); - - /* - * We need to handle Xwayland surfaces differently in order to allow - * Xwayland to be able to lock the pointer. For example, we cannot require - * the locked window to "appear focused" because the surface Xwayland - * locks might not be able to appear focused (for example it may be a - * override redirect window). - * - * Since we don't have any way to know what focused window an override - * redirect is associated with, nor have a way to know if the override - * redirect window even shares the same connection as a focused window, - * we simply can only really restrict it to enable the lock if any - * Xwayland window appears focused. - */ - - if (display->focus_window && - display->focus_window->client_type != META_WINDOW_CLIENT_TYPE_X11) - return FALSE; - } - else - { - if (!meta_window_appears_focused (window)) - return FALSE; - } - - return TRUE; -} - -static void -meta_wayland_pointer_constraint_maybe_enable (MetaWaylandPointerConstraint *constraint) -{ - wl_fixed_t sx, sy; - - if (constraint->is_enabled) - return; - - if (!should_constraint_be_enabled (constraint)) - return; - - meta_wayland_pointer_get_relative_coordinates (constraint->seat->pointer, - constraint->surface, - &sx, &sy); - if (!is_within_constraint_region (constraint, sx, sy)) - return; - - meta_wayland_pointer_constraint_enable (constraint); -} - -static void -meta_wayland_pointer_constraint_remove (MetaWaylandPointerConstraint *constraint) -{ - MetaWaylandSurface *surface = constraint->surface; - - surface_remove_pointer_constraints (surface, constraint); - meta_wayland_pointer_constraint_destroy (constraint); -} - -static void -meta_wayland_pointer_constraint_deactivate (MetaWaylandPointerConstraint *constraint) -{ - switch (constraint->lifetime) - { - case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT: - meta_wayland_pointer_constraint_remove (constraint); - break; - - case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT: - meta_wayland_pointer_constraint_disable (constraint); - break; - - default: - g_assert_not_reached (); - } -} - -void -meta_wayland_pointer_constraint_maybe_remove_for_seat (MetaWaylandSeat *seat, - MetaWindow *window) -{ - MetaWaylandPointer *pointer = seat->pointer; - MetaWaylandPointerConstraint *constraint; - - if ((pointer->grab->interface != &confined_pointer_grab_interface && - pointer->grab->interface != &locked_pointer_grab_interface)) - return; - - constraint = wl_container_of (pointer->grab, constraint, grab); - - if (should_constraint_be_enabled (constraint)) - return; - - meta_wayland_pointer_constraint_deactivate (constraint); -} - -static void -meta_wayland_pointer_constraint_maybe_enable_for_window (MetaWindow *window) -{ - MetaWaylandSurface *surface = window->surface; - MetaWaylandSurfacePointerConstraintsData *surface_data; - GList *l; - - if (!surface) - { - g_warn_if_fail (window->client_type == META_WINDOW_CLIENT_TYPE_X11); - return; - } - - surface_data = get_surface_constraints_data (surface); - if (!surface_data) - return; - - for (l = surface_data->pointer_constraints; l; l = l->next) - { - MetaWaylandPointerConstraint *constraint = l->data; - - meta_wayland_pointer_constraint_maybe_enable (constraint); - } -} - -MetaWaylandSeat * -meta_wayland_pointer_constraint_get_seat (MetaWaylandPointerConstraint *constraint) -{ - return constraint->seat; -} - -cairo_region_t * -meta_wayland_pointer_constraint_calculate_effective_region (MetaWaylandPointerConstraint *constraint) -{ - cairo_region_t *region; - MetaWindow *window; - - region = meta_wayland_surface_calculate_input_region (constraint->surface); - if (constraint->region) - cairo_region_intersect (region, constraint->region); - - window = meta_wayland_surface_get_window (constraint->surface); - if (window && window->frame) - { - MetaFrame *frame = window->frame; - int actual_width, actual_height; - - g_assert (meta_xwayland_is_xwayland_surface (constraint->surface)); - - actual_width = window->buffer_rect.width - (frame->child_x + - frame->right_width); - actual_height = window->buffer_rect.height - (frame->child_y + - frame->bottom_height); - if (actual_width > 0 && actual_height > 0) - { - cairo_region_intersect_rectangle (region, &(cairo_rectangle_int_t) { - .x = frame->child_x, - .y = frame->child_y, - .width = actual_width, - .height = actual_height - }); - } - } - - return region; -} - -MetaWaylandSurface * -meta_wayland_pointer_constraint_get_surface (MetaWaylandPointerConstraint *constraint) -{ - return constraint->surface; -} - -static void -pointer_constraint_resource_destroyed (struct wl_resource *resource) -{ - MetaWaylandPointerConstraint *constraint = - wl_resource_get_user_data (resource); - - if (!constraint) - return; - - meta_wayland_pointer_constraint_remove (constraint); -} - -static void -pending_constraint_state_free (MetaWaylandPendingConstraintState *constraint_pending) -{ - g_clear_pointer (&constraint_pending->region, cairo_region_destroy); - if (constraint_pending->constraint) - g_object_remove_weak_pointer (G_OBJECT (constraint_pending->constraint), - (gpointer *) &constraint_pending->constraint); -} - -static MetaWaylandPendingConstraintStateContainer * -get_pending_constraint_state_container (MetaWaylandSurfaceState *pending) -{ - return g_object_get_qdata (G_OBJECT (pending), - quark_pending_constraint_state); -} - -static MetaWaylandPendingConstraintState * -get_pending_constraint_state (MetaWaylandPointerConstraint *constraint) -{ - MetaWaylandSurfaceState *pending; - MetaWaylandPendingConstraintStateContainer *container; - GList *l; - - pending = meta_wayland_surface_get_pending_state (constraint->surface); - container = get_pending_constraint_state_container (pending); - for (l = container->pending_constraint_states; l; l = l->next) - { - MetaWaylandPendingConstraintState *constraint_pending = l->data; - - if (constraint_pending->constraint == constraint) - return constraint_pending; - } - - return NULL; -} - -static void -pending_constraint_state_container_free (MetaWaylandPendingConstraintStateContainer *container) -{ - g_list_free_full (container->pending_constraint_states, - (GDestroyNotify) pending_constraint_state_free); - g_free (container); -} - -static MetaWaylandPendingConstraintStateContainer * -ensure_pending_constraint_state_container (MetaWaylandSurfaceState *pending) -{ - MetaWaylandPendingConstraintStateContainer *container; - - container = get_pending_constraint_state_container (pending); - if (!container) - { - container = g_new0 (MetaWaylandPendingConstraintStateContainer, 1); - g_object_set_qdata_full (G_OBJECT (pending), - quark_pending_constraint_state, - container, - (GDestroyNotify) pending_constraint_state_container_free); - - } - - return container; -} - -static void -remove_pending_constraint_state (MetaWaylandPointerConstraint *constraint, - MetaWaylandSurfaceState *pending) -{ - MetaWaylandPendingConstraintStateContainer *container; - GList *l; - - container = get_pending_constraint_state_container (pending); - for (l = container->pending_constraint_states; l; l = l->next) - { - MetaWaylandPendingConstraintState *constraint_pending = l->data; - if (constraint_pending->constraint != constraint) - continue; - - pending_constraint_state_free (l->data); - container->pending_constraint_states = - g_list_remove_link (container->pending_constraint_states, l); - break; - } -} - -static void -pending_constraint_state_applied (MetaWaylandSurfaceState *pending, - MetaWaylandPendingConstraintState *constraint_pending) -{ - MetaWaylandPointerConstraint *constraint = constraint_pending->constraint; - - if (!constraint) - return; - - g_clear_pointer (&constraint->region, cairo_region_destroy); - if (constraint_pending->region) - { - constraint->region = constraint_pending->region; - constraint_pending->region = NULL; - } - else - { - constraint->region = NULL; - } - - g_clear_signal_handler (&constraint_pending->applied_handler_id, pending); - remove_pending_constraint_state (constraint, pending); - - /* The pointer is potentially warped by the actor paint signal callback if - * the new region proved it necessary. - */ -} - -static MetaWaylandPendingConstraintState * -ensure_pending_constraint_state (MetaWaylandPointerConstraint *constraint) -{ - MetaWaylandSurfaceState *pending; - MetaWaylandPendingConstraintStateContainer *container; - MetaWaylandPendingConstraintState *constraint_pending; - - pending = meta_wayland_surface_get_pending_state (constraint->surface); - container = ensure_pending_constraint_state_container (pending); - constraint_pending = get_pending_constraint_state (constraint); - if (!constraint_pending) - { - constraint_pending = g_new0 (MetaWaylandPendingConstraintState, 1); - constraint_pending->constraint = constraint; - constraint_pending->applied_handler_id = - g_signal_connect (pending, "applied", - G_CALLBACK (pending_constraint_state_applied), - constraint_pending); - g_object_add_weak_pointer (G_OBJECT (constraint), - (gpointer *) &constraint_pending->constraint); - - container->pending_constraint_states = - g_list_append (container->pending_constraint_states, - constraint_pending); - } - - return constraint_pending; -} - -static void -meta_wayland_pointer_constraint_set_pending_region (MetaWaylandPointerConstraint *constraint, - MetaWaylandRegion *region) -{ - MetaWaylandPendingConstraintState *constraint_pending; - - constraint_pending = ensure_pending_constraint_state (constraint); - - g_clear_pointer (&constraint_pending->region, cairo_region_destroy); - if (region) - { - constraint_pending->region = - cairo_region_copy (meta_wayland_region_peek_cairo_region (region)); - } -} - -static MetaWaylandPointerConstraint * -get_pointer_constraint_for_seat (MetaWaylandSurface *surface, - MetaWaylandSeat *seat) -{ - MetaWaylandSurfacePointerConstraintsData *surface_data; - GList *l; - - surface_data = get_surface_constraints_data (surface); - if (!surface_data) - return NULL; - - for (l = surface_data->pointer_constraints; l; l = l->next) - { - MetaWaylandPointerConstraint *constraint = l->data; - - if (seat == constraint->seat) - return constraint; - } - - return NULL; -} - -static void -init_pointer_constraint (struct wl_resource *resource, - uint32_t id, - MetaWaylandSurface *surface, - MetaWaylandSeat *seat, - MetaWaylandRegion *region, - enum zwp_pointer_constraints_v1_lifetime lifetime, - const struct wl_interface *interface, - const void *implementation, - const MetaWaylandPointerGrabInterface *grab_interface) -{ - struct wl_client *client = wl_resource_get_client (resource); - struct wl_resource *cr; - MetaWaylandPointerConstraint *constraint; - - if (get_pointer_constraint_for_seat (surface, seat)) - { - wl_resource_post_error (resource, - WL_DISPLAY_ERROR_INVALID_OBJECT, - "the pointer was already requested to be " - "locked or confined on that surface"); - return; - } - - cr = wl_resource_create (client, interface, - wl_resource_get_version (resource), - id); - if (cr == NULL) - { - wl_client_post_no_memory (client); - return; - } - - switch (lifetime) - { - case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT: - case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT: - break; - - default: - wl_resource_post_error (resource, - WL_DISPLAY_ERROR_INVALID_OBJECT, - "Invalid constraint lifetime"); - return; - } - - constraint = meta_wayland_pointer_constraint_new (surface, seat, - region, - lifetime, - cr, grab_interface); - if (constraint == NULL) - { - wl_client_post_no_memory (client); - return; - } - - surface_add_pointer_constraint (surface, constraint); - - wl_resource_set_implementation (cr, implementation, constraint, - pointer_constraint_resource_destroyed); - - meta_wayland_pointer_constraint_maybe_enable (constraint); -} - -static void -locked_pointer_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - MetaWaylandPointerConstraint *constraint = - wl_resource_get_user_data (resource); - gboolean warp_pointer = FALSE; - int warp_x, warp_y; - - if (constraint && constraint->is_enabled && constraint->hint_set && - is_within_constraint_region (constraint, - constraint->x_hint, - constraint->y_hint)) - { - float sx, sy; - float x, y; - - sx = (float)wl_fixed_to_double (constraint->x_hint); - sy = (float)wl_fixed_to_double (constraint->y_hint); - meta_wayland_surface_get_absolute_coordinates (constraint->surface, - sx, sy, - &x, &y); - warp_pointer = TRUE; - warp_x = (int) x; - warp_y = (int) y; - } - wl_resource_destroy (resource); - - if (warp_pointer) - { - ClutterSeat *seat; - - seat = clutter_backend_get_default_seat (clutter_get_default_backend ()); - clutter_seat_warp_pointer (seat, warp_x, warp_y); - } -} - -static void -locked_pointer_set_cursor_position_hint (struct wl_client *client, - struct wl_resource *resource, - wl_fixed_t surface_x, - wl_fixed_t surface_y) -{ - MetaWaylandPointerConstraint *constraint = - wl_resource_get_user_data (resource); - - /* Ignore a set cursor hint that was already sent after the constraint - * was cancelled. */ - if (!constraint || !constraint->resource || constraint->resource != resource) - return; - - constraint->hint_set = TRUE; - constraint->x_hint = surface_x; - constraint->y_hint = surface_y; -} - -static void -locked_pointer_set_region (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *region_resource) -{ - MetaWaylandPointerConstraint *constraint = - wl_resource_get_user_data (resource); - MetaWaylandRegion *region = - region_resource ? wl_resource_get_user_data (region_resource) : NULL; - - if (!constraint) - return; - - meta_wayland_pointer_constraint_set_pending_region (constraint, region); -} - -static const struct zwp_locked_pointer_v1_interface locked_pointer_interface = { - locked_pointer_destroy, - locked_pointer_set_cursor_position_hint, - locked_pointer_set_region, -}; - -static void -locked_pointer_grab_pointer_focus (MetaWaylandPointerGrab *grab, - MetaWaylandSurface *surface) -{ -} - -static void -locked_pointer_grab_pointer_motion (MetaWaylandPointerGrab *grab, - const ClutterEvent *event) -{ - meta_wayland_pointer_send_relative_motion (grab->pointer, event); - meta_wayland_pointer_broadcast_frame (grab->pointer); -} - -static void -locked_pointer_grab_pointer_button (MetaWaylandPointerGrab *grab, - const ClutterEvent *event) -{ - meta_wayland_pointer_send_button (grab->pointer, event); -} - -static void -locked_pointer_grab_pointer_cancel (MetaWaylandPointerGrab *grab) -{ - MetaWaylandPointerConstraint *constraint = - wl_container_of (grab, constraint, grab); - - meta_wayland_pointer_constraint_deactivate (constraint); -} - -static const MetaWaylandPointerGrabInterface locked_pointer_grab_interface = { - locked_pointer_grab_pointer_focus, - locked_pointer_grab_pointer_motion, - locked_pointer_grab_pointer_button, - locked_pointer_grab_pointer_cancel, -}; - -static void -pointer_constraints_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -pointer_constraints_lock_pointer (struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *surface_resource, - struct wl_resource *pointer_resource, - struct wl_resource *region_resource, - uint32_t lifetime) -{ - MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); - MetaWaylandPointer *pointer = wl_resource_get_user_data (pointer_resource); - MetaWaylandSeat *seat = meta_wayland_pointer_get_seat (pointer); - MetaWaylandRegion *region = - region_resource ? wl_resource_get_user_data (region_resource) : NULL; - - init_pointer_constraint (resource, id, surface, seat, region, lifetime, - &zwp_locked_pointer_v1_interface, - &locked_pointer_interface, - &locked_pointer_grab_interface); -} - -static void -confined_pointer_grab_pointer_focus (MetaWaylandPointerGrab *grab, - MetaWaylandSurface *surface) -{ -} - -static void -confined_pointer_grab_pointer_motion (MetaWaylandPointerGrab *grab, - const ClutterEvent *event) -{ - MetaWaylandPointerConstraint *constraint = - wl_container_of (grab, constraint, grab); - MetaWaylandPointer *pointer = grab->pointer; - - g_assert (pointer->focus_surface); - g_assert (pointer->focus_surface == constraint->surface); - - meta_wayland_pointer_send_motion (pointer, event); -} - -static void -confined_pointer_grab_pointer_button (MetaWaylandPointerGrab *grab, - const ClutterEvent *event) -{ - meta_wayland_pointer_send_button (grab->pointer, event); -} - -static void -confined_pointer_grab_pointer_cancel (MetaWaylandPointerGrab *grab) -{ - MetaWaylandPointerConstraint *constraint = - wl_container_of (grab, constraint, grab); - - meta_wayland_pointer_constraint_deactivate (constraint); -} - -static const MetaWaylandPointerGrabInterface confined_pointer_grab_interface = { - confined_pointer_grab_pointer_focus, - confined_pointer_grab_pointer_motion, - confined_pointer_grab_pointer_button, - confined_pointer_grab_pointer_cancel, -}; - -static void -confined_pointer_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -confined_pointer_set_region (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *region_resource) -{ - MetaWaylandPointerConstraint *constraint = - wl_resource_get_user_data (resource); - MetaWaylandRegion *region = - region_resource ? wl_resource_get_user_data (region_resource) : NULL; - - if (!constraint) - return; - - meta_wayland_pointer_constraint_set_pending_region (constraint, region); -} - -static const struct zwp_confined_pointer_v1_interface confined_pointer_interface = { - confined_pointer_destroy, - confined_pointer_set_region, -}; - -static void -pointer_constraints_confine_pointer (struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *surface_resource, - struct wl_resource *pointer_resource, - struct wl_resource *region_resource, - uint32_t lifetime) -{ - MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); - MetaWaylandPointer *pointer = wl_resource_get_user_data (pointer_resource); - MetaWaylandSeat *seat = meta_wayland_pointer_get_seat (pointer); - MetaWaylandRegion *region = - region_resource ? wl_resource_get_user_data (region_resource) : NULL; - - init_pointer_constraint (resource, id, surface, seat, region, lifetime, - &zwp_confined_pointer_v1_interface, - &confined_pointer_interface, - &confined_pointer_grab_interface); - -} - -static const struct zwp_pointer_constraints_v1_interface pointer_constraints = { - pointer_constraints_destroy, - pointer_constraints_lock_pointer, - pointer_constraints_confine_pointer, -}; - -static void -bind_pointer_constraints (struct wl_client *client, - void *data, - uint32_t version, - uint32_t id) -{ - MetaWaylandCompositor *compositor = data; - struct wl_resource *resource; - - resource = wl_resource_create (client, - &zwp_pointer_constraints_v1_interface, - 1, id); - - wl_resource_set_implementation (resource, - &pointer_constraints, - compositor, - NULL); -} - -static void -meta_wayland_pointer_constraint_finalize (GObject *object) -{ - MetaWaylandPointerConstraint *constraint = - META_WAYLAND_POINTER_CONSTRAINT (object); - - g_clear_signal_handler (&constraint->pointer_focus_surface_handler_id, - constraint->seat->pointer); - - G_OBJECT_CLASS (meta_wayland_pointer_constraint_parent_class)->finalize (object); -} - -void -meta_wayland_pointer_constraints_init (MetaWaylandCompositor *compositor) -{ - if (!wl_global_create (compositor->wayland_display, - &zwp_pointer_constraints_v1_interface, 1, - compositor, bind_pointer_constraints)) - g_error ("Could not create wp_pointer_constraints global"); -} - -static void -meta_wayland_pointer_constraint_init (MetaWaylandPointerConstraint *constraint) -{ -} - -static void -meta_wayland_pointer_constraint_class_init (MetaWaylandPointerConstraintClass *klass) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - object_class->finalize = meta_wayland_pointer_constraint_finalize; - - quark_pending_constraint_state = - g_quark_from_static_string ("-meta-wayland-pointer-constraint-pending_state"); - quark_surface_pointer_constraints_data = - g_quark_from_static_string ("-meta-wayland-surface-constraints-data"); -} diff --git a/src/wayland/meta-wayland-pointer-constraints.h b/src/wayland/meta-wayland-pointer-constraints.h deleted file mode 100644 index dee7568de..000000000 --- a/src/wayland/meta-wayland-pointer-constraints.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#ifndef META_WAYLAND_POINTER_CONSTRAINTS_H -#define META_WAYLAND_POINTER_CONSTRAINTS_H - -#include - -#include "meta/window.h" -#include "wayland/meta-wayland-types.h" - -#define META_TYPE_WAYLAND_POINTER_CONSTRAINT (meta_wayland_pointer_constraint_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandPointerConstraint, - meta_wayland_pointer_constraint, - META, WAYLAND_POINTER_CONSTRAINT, - GObject); - -void meta_wayland_pointer_constraints_init (MetaWaylandCompositor *compositor); - -MetaWaylandSeat * meta_wayland_pointer_constraint_get_seat (MetaWaylandPointerConstraint *constraint); - -cairo_region_t * meta_wayland_pointer_constraint_calculate_effective_region (MetaWaylandPointerConstraint *constraint); - -MetaWaylandSurface * meta_wayland_pointer_constraint_get_surface (MetaWaylandPointerConstraint *constraint); - -#endif /* META_WAYLAND_POINTER_CONSTRAINTS_H */ diff --git a/src/wayland/meta-wayland-pointer-gesture-pinch.c b/src/wayland/meta-wayland-pointer-gesture-pinch.c deleted file mode 100644 index f7b37ff27..000000000 --- a/src/wayland/meta-wayland-pointer-gesture-pinch.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2015 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: Carlos Garnacho - */ - -#include "config.h" - -#include "wayland/meta-wayland-pointer-gesture-pinch.h" - -#include - -#include "wayland/meta-wayland-pointer.h" -#include "wayland/meta-wayland-seat.h" -#include "wayland/meta-wayland-surface.h" - -#include "pointer-gestures-unstable-v1-server-protocol.h" - -static void -handle_pinch_begin (MetaWaylandPointer *pointer, - const ClutterEvent *event) -{ - MetaWaylandPointerClient *pointer_client; - MetaWaylandSeat *seat; - struct wl_resource *resource; - uint32_t serial, fingers; - - pointer_client = pointer->focus_client; - seat = meta_wayland_pointer_get_seat (pointer); - serial = wl_display_next_serial (seat->wl_display); - fingers = clutter_event_get_touchpad_gesture_finger_count (event); - - wl_resource_for_each (resource, &pointer_client->pinch_gesture_resources) - { - zwp_pointer_gesture_pinch_v1_send_begin (resource, serial, - clutter_event_get_time (event), - pointer->focus_surface->resource, - fingers); - } -} - -static void -handle_pinch_update (MetaWaylandPointer *pointer, - const ClutterEvent *event) -{ - MetaWaylandPointerClient *pointer_client; - struct wl_resource *resource; - gdouble dx, dy, scale, rotation; - - pointer_client = pointer->focus_client; - clutter_event_get_gesture_motion_delta (event, &dx, &dy); - rotation = clutter_event_get_gesture_pinch_angle_delta (event); - scale = clutter_event_get_gesture_pinch_scale (event); - - wl_resource_for_each (resource, &pointer_client->pinch_gesture_resources) - { - zwp_pointer_gesture_pinch_v1_send_update (resource, - clutter_event_get_time (event), - wl_fixed_from_double (dx), - wl_fixed_from_double (dy), - wl_fixed_from_double (scale), - wl_fixed_from_double (rotation)); - } -} - -static void -handle_pinch_end (MetaWaylandPointer *pointer, - const ClutterEvent *event) -{ - MetaWaylandPointerClient *pointer_client; - MetaWaylandSeat *seat; - struct wl_resource *resource; - gboolean cancelled = FALSE; - uint32_t serial; - - pointer_client = pointer->focus_client; - seat = meta_wayland_pointer_get_seat (pointer); - serial = wl_display_next_serial (seat->wl_display); - - if (event->touchpad_pinch.phase == CLUTTER_TOUCHPAD_GESTURE_PHASE_CANCEL) - cancelled = TRUE; - - wl_resource_for_each (resource, &pointer_client->pinch_gesture_resources) - { - zwp_pointer_gesture_pinch_v1_send_end (resource, serial, - clutter_event_get_time (event), - cancelled); - } -} - -gboolean -meta_wayland_pointer_gesture_pinch_handle_event (MetaWaylandPointer *pointer, - const ClutterEvent *event) -{ - if (event->type != CLUTTER_TOUCHPAD_PINCH) - return FALSE; - - if (!pointer->focus_client) - return FALSE; - - switch (event->touchpad_pinch.phase) - { - case CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN: - handle_pinch_begin (pointer, event); - break; - case CLUTTER_TOUCHPAD_GESTURE_PHASE_UPDATE: - handle_pinch_update (pointer, event); - break; - case CLUTTER_TOUCHPAD_GESTURE_PHASE_END: - case CLUTTER_TOUCHPAD_GESTURE_PHASE_CANCEL: - handle_pinch_end (pointer, event); - break; - default: - return FALSE; - } - - return TRUE; -} - -static void -pointer_gesture_pinch_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static const struct zwp_pointer_gesture_pinch_v1_interface pointer_gesture_pinch_interface = { - pointer_gesture_pinch_destroy -}; - -void -meta_wayland_pointer_gesture_pinch_create_new_resource (MetaWaylandPointer *pointer, - struct wl_client *client, - struct wl_resource *gestures_resource, - uint32_t id) -{ - MetaWaylandPointerClient *pointer_client; - struct wl_resource *res; - - pointer_client = meta_wayland_pointer_get_pointer_client (pointer, client); - g_return_if_fail (pointer_client != NULL); - - res = wl_resource_create (client, &zwp_pointer_gesture_pinch_v1_interface, - wl_resource_get_version (gestures_resource), id); - wl_resource_set_implementation (res, &pointer_gesture_pinch_interface, pointer, - meta_wayland_pointer_unbind_pointer_client_resource); - wl_list_insert (&pointer_client->pinch_gesture_resources, - wl_resource_get_link (res)); -} diff --git a/src/wayland/meta-wayland-pointer-gesture-pinch.h b/src/wayland/meta-wayland-pointer-gesture-pinch.h deleted file mode 100644 index 9ea3733f7..000000000 --- a/src/wayland/meta-wayland-pointer-gesture-pinch.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2015 Red Hat - * - * 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 . - * - * Author: Carlos Garnacho - */ - -#ifndef META_WAYLAND_POINTER_GESTURE_PINCH_H -#define META_WAYLAND_POINTER_GESTURE_PINCH_H - -#include -#include - -#include "clutter/clutter.h" -#include "wayland/meta-wayland-types.h" - -gboolean meta_wayland_pointer_gesture_pinch_handle_event (MetaWaylandPointer *pointer, - const ClutterEvent *event); - -void meta_wayland_pointer_gesture_pinch_create_new_resource (MetaWaylandPointer *pointer, - struct wl_client *client, - struct wl_resource *gestures_resource, - uint32_t id); - -#endif /* META_WAYLAND_POINTER_GESTURE_PINCH_H */ diff --git a/src/wayland/meta-wayland-pointer-gesture-swipe.c b/src/wayland/meta-wayland-pointer-gesture-swipe.c deleted file mode 100644 index d95e84941..000000000 --- a/src/wayland/meta-wayland-pointer-gesture-swipe.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2015 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: Carlos Garnacho - */ - -#include "config.h" - -#include "wayland/meta-wayland-pointer-gesture-swipe.h" - -#include - -#include "wayland/meta-wayland-pointer.h" -#include "wayland/meta-wayland-seat.h" -#include "wayland/meta-wayland-surface.h" - -#include "pointer-gestures-unstable-v1-server-protocol.h" - -static void -handle_swipe_begin (MetaWaylandPointer *pointer, - const ClutterEvent *event) -{ - MetaWaylandPointerClient *pointer_client; - MetaWaylandSeat *seat; - struct wl_resource *resource; - uint32_t serial, fingers; - - pointer_client = pointer->focus_client; - seat = meta_wayland_pointer_get_seat (pointer); - serial = wl_display_next_serial (seat->wl_display); - fingers = clutter_event_get_touchpad_gesture_finger_count (event); - - wl_resource_for_each (resource, &pointer_client->swipe_gesture_resources) - { - zwp_pointer_gesture_swipe_v1_send_begin (resource, serial, - clutter_event_get_time (event), - pointer->focus_surface->resource, - fingers); - } -} - -static void -handle_swipe_update (MetaWaylandPointer *pointer, - const ClutterEvent *event) -{ - MetaWaylandPointerClient *pointer_client; - struct wl_resource *resource; - gdouble dx, dy; - - pointer_client = pointer->focus_client; - clutter_event_get_gesture_motion_delta (event, &dx, &dy); - - wl_resource_for_each (resource, &pointer_client->swipe_gesture_resources) - { - zwp_pointer_gesture_swipe_v1_send_update (resource, - clutter_event_get_time (event), - wl_fixed_from_double (dx), - wl_fixed_from_double (dy)); - } -} - -static void -handle_swipe_end (MetaWaylandPointer *pointer, - const ClutterEvent *event) -{ - MetaWaylandPointerClient *pointer_client; - MetaWaylandSeat *seat; - struct wl_resource *resource; - gboolean cancelled = FALSE; - uint32_t serial; - - pointer_client = pointer->focus_client; - seat = meta_wayland_pointer_get_seat (pointer); - serial = wl_display_next_serial (seat->wl_display); - - if (event->touchpad_swipe.phase == CLUTTER_TOUCHPAD_GESTURE_PHASE_CANCEL) - cancelled = TRUE; - - wl_resource_for_each (resource, &pointer_client->swipe_gesture_resources) - { - zwp_pointer_gesture_swipe_v1_send_end (resource, serial, - clutter_event_get_time (event), - cancelled); - } -} - -gboolean -meta_wayland_pointer_gesture_swipe_handle_event (MetaWaylandPointer *pointer, - const ClutterEvent *event) -{ - if (event->type != CLUTTER_TOUCHPAD_SWIPE) - return FALSE; - - if (!pointer->focus_client) - return FALSE; - - switch (event->touchpad_swipe.phase) - { - case CLUTTER_TOUCHPAD_GESTURE_PHASE_BEGIN: - handle_swipe_begin (pointer, event); - break; - case CLUTTER_TOUCHPAD_GESTURE_PHASE_UPDATE: - handle_swipe_update (pointer, event); - break; - case CLUTTER_TOUCHPAD_GESTURE_PHASE_END: - case CLUTTER_TOUCHPAD_GESTURE_PHASE_CANCEL: - handle_swipe_end (pointer, event); - break; - default: - return FALSE; - } - - return TRUE; -} - -static void -pointer_gesture_swipe_release (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static const struct zwp_pointer_gesture_swipe_v1_interface pointer_gesture_swipe_interface = { - pointer_gesture_swipe_release -}; - -void -meta_wayland_pointer_gesture_swipe_create_new_resource (MetaWaylandPointer *pointer, - struct wl_client *client, - struct wl_resource *pointer_resource, - uint32_t id) -{ - MetaWaylandPointerClient *pointer_client; - struct wl_resource *res; - - pointer_client = meta_wayland_pointer_get_pointer_client (pointer, client); - g_return_if_fail (pointer_client != NULL); - - res = wl_resource_create (client, &zwp_pointer_gesture_swipe_v1_interface, - wl_resource_get_version (pointer_resource), id); - wl_resource_set_implementation (res, &pointer_gesture_swipe_interface, pointer, - meta_wayland_pointer_unbind_pointer_client_resource); - wl_list_insert (&pointer_client->swipe_gesture_resources, - wl_resource_get_link (res)); -} diff --git a/src/wayland/meta-wayland-pointer-gesture-swipe.h b/src/wayland/meta-wayland-pointer-gesture-swipe.h deleted file mode 100644 index ed53fc4b2..000000000 --- a/src/wayland/meta-wayland-pointer-gesture-swipe.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2015 Red Hat - * - * 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 . - * - * Author: Carlos Garnacho - */ - -#ifndef META_WAYLAND_POINTER_GESTURE_SWIPE_H -#define META_WAYLAND_POINTER_GESTURE_SWIPE_H - -#include -#include - -#include "clutter/clutter.h" -#include "wayland/meta-wayland-types.h" - -gboolean meta_wayland_pointer_gesture_swipe_handle_event (MetaWaylandPointer *pointer, - const ClutterEvent *event); - -void meta_wayland_pointer_gesture_swipe_create_new_resource (MetaWaylandPointer *pointer, - struct wl_client *client, - struct wl_resource *pointer_resource, - uint32_t id); - -#endif /* META_WAYLAND_POINTER_GESTURE_SWIPE_H */ diff --git a/src/wayland/meta-wayland-pointer-gestures.c b/src/wayland/meta-wayland-pointer-gestures.c deleted file mode 100644 index 7222a8a8c..000000000 --- a/src/wayland/meta-wayland-pointer-gestures.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2015 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: Carlos Garnacho - */ - -#include "config.h" - -#include "wayland/meta-wayland-pointer-gestures.h" - -#include - -#include "wayland/meta-wayland-versions.h" -#include "wayland/meta-wayland-private.h" - -#include "pointer-gestures-unstable-v1-server-protocol.h" - -static void -gestures_get_swipe (struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *pointer_resource) -{ - MetaWaylandPointer *pointer = wl_resource_get_user_data (pointer_resource); - - meta_wayland_pointer_gesture_swipe_create_new_resource (pointer, client, resource, id); -} - -static void -gestures_get_pinch (struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *pointer_resource) -{ - MetaWaylandPointer *pointer = wl_resource_get_user_data (pointer_resource); - - meta_wayland_pointer_gesture_pinch_create_new_resource (pointer, client, resource, id); -} - -static const struct zwp_pointer_gestures_v1_interface pointer_gestures_interface = { - gestures_get_swipe, - gestures_get_pinch -}; - -static void -bind_pointer_gestures (struct wl_client *client, - void *data, - guint32 version, - guint32 id) -{ - struct wl_resource *resource; - - resource = wl_resource_create (client, &zwp_pointer_gestures_v1_interface, - version, id); - wl_resource_set_implementation (resource, &pointer_gestures_interface, - NULL, NULL); -} - -void -meta_wayland_pointer_gestures_init (MetaWaylandCompositor *compositor) -{ - wl_global_create (compositor->wayland_display, - &zwp_pointer_gestures_v1_interface, - META_ZWP_POINTER_GESTURES_V1_VERSION, - NULL, bind_pointer_gestures); -} diff --git a/src/wayland/meta-wayland-pointer-gestures.h b/src/wayland/meta-wayland-pointer-gestures.h deleted file mode 100644 index 48792da12..000000000 --- a/src/wayland/meta-wayland-pointer-gestures.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2015 Red Hat - * - * 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 . - * - * Author: Carlos Garnacho - */ - -#ifndef META_WAYLAND_POINTER_GESTURES_H -#define META_WAYLAND_POINTER_GESTURES_H - -#include -#include - -#include "wayland/meta-wayland-types.h" - -void meta_wayland_pointer_gestures_init (MetaWaylandCompositor *compositor); - -#endif /* META_WAYLAND_POINTER_GESTURES_H */ diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c deleted file mode 100644 index 3132abfd2..000000000 --- a/src/wayland/meta-wayland-pointer.c +++ /dev/null @@ -1,1370 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2013 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 . - */ - -/* - * Copyright © 2008 Kristian Høgsberg - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -/* The file is based on src/input.c from Weston */ - -#include "config.h" - -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-cursor-renderer.h" -#include "backends/meta-cursor-tracker-private.h" -#include "backends/meta-cursor.h" -#include "clutter/clutter.h" -#include "cogl/cogl-wayland-server.h" -#include "cogl/cogl.h" -#include "compositor/meta-surface-actor-wayland.h" -#include "meta/meta-cursor-tracker.h" -#include "wayland/meta-wayland-buffer.h" -#include "wayland/meta-wayland-cursor-surface.h" -#include "wayland/meta-wayland-pointer.h" -#include "wayland/meta-wayland-popup.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-seat.h" -#include "wayland/meta-wayland-surface.h" -#include "wayland/meta-xwayland.h" - -#ifdef HAVE_NATIVE_BACKEND -#include "backends/native/meta-backend-native.h" -#endif - -#include "relative-pointer-unstable-v1-server-protocol.h" - -#define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int (10) - -enum -{ - FOCUS_SURFACE_CHANGED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL]; - -G_DEFINE_TYPE (MetaWaylandPointer, meta_wayland_pointer, - META_TYPE_WAYLAND_INPUT_DEVICE) - -static void -meta_wayland_pointer_set_current (MetaWaylandPointer *pointer, - MetaWaylandSurface *surface); - -static void -meta_wayland_pointer_reset_grab (MetaWaylandPointer *pointer); - -static void -meta_wayland_pointer_cancel_grab (MetaWaylandPointer *pointer); - -static MetaWaylandPointerClient * -meta_wayland_pointer_client_new (void) -{ - MetaWaylandPointerClient *pointer_client; - - pointer_client = g_new0 (MetaWaylandPointerClient, 1); - wl_list_init (&pointer_client->pointer_resources); - wl_list_init (&pointer_client->swipe_gesture_resources); - wl_list_init (&pointer_client->pinch_gesture_resources); - wl_list_init (&pointer_client->relative_pointer_resources); - - return pointer_client; -} - -static void -meta_wayland_pointer_client_free (MetaWaylandPointerClient *pointer_client) -{ - struct wl_resource *resource, *next; - - /* Since we make every wl_pointer resource defunct when we stop advertising - * the pointer capability on the wl_seat, we need to make sure all the - * resources in the pointer client instance gets removed. - */ - wl_resource_for_each_safe (resource, next, &pointer_client->pointer_resources) - { - wl_list_remove (wl_resource_get_link (resource)); - wl_list_init (wl_resource_get_link (resource)); - wl_resource_set_user_data (resource, NULL); - } - wl_resource_for_each_safe (resource, next, &pointer_client->swipe_gesture_resources) - { - wl_list_remove (wl_resource_get_link (resource)); - wl_list_init (wl_resource_get_link (resource)); - wl_resource_set_user_data (resource, NULL); - } - wl_resource_for_each_safe (resource, next, &pointer_client->pinch_gesture_resources) - { - wl_list_remove (wl_resource_get_link (resource)); - wl_list_init (wl_resource_get_link (resource)); - wl_resource_set_user_data (resource, NULL); - } - wl_resource_for_each_safe (resource, next, &pointer_client->relative_pointer_resources) - { - wl_list_remove (wl_resource_get_link (resource)); - wl_list_init (wl_resource_get_link (resource)); - wl_resource_set_user_data (resource, NULL); - } - - g_free (pointer_client); -} - -static gboolean -meta_wayland_pointer_client_is_empty (MetaWaylandPointerClient *pointer_client) -{ - return (wl_list_empty (&pointer_client->pointer_resources) && - wl_list_empty (&pointer_client->swipe_gesture_resources) && - wl_list_empty (&pointer_client->pinch_gesture_resources) && - wl_list_empty (&pointer_client->relative_pointer_resources)); -} - -MetaWaylandPointerClient * -meta_wayland_pointer_get_pointer_client (MetaWaylandPointer *pointer, - struct wl_client *client) -{ - if (!pointer->pointer_clients) - return NULL; - return g_hash_table_lookup (pointer->pointer_clients, client); -} - -static MetaWaylandPointerClient * -meta_wayland_pointer_ensure_pointer_client (MetaWaylandPointer *pointer, - struct wl_client *client) -{ - MetaWaylandPointerClient *pointer_client; - - pointer_client = meta_wayland_pointer_get_pointer_client (pointer, client); - if (pointer_client) - return pointer_client; - - pointer_client = meta_wayland_pointer_client_new (); - g_hash_table_insert (pointer->pointer_clients, client, pointer_client); - - if (!pointer->focus_client && - pointer->focus_surface && - wl_resource_get_client (pointer->focus_surface->resource) == client) - pointer->focus_client = pointer_client; - - return pointer_client; -} - -static void -meta_wayland_pointer_cleanup_pointer_client (MetaWaylandPointer *pointer, - MetaWaylandPointerClient *pointer_client, - struct wl_client *client) -{ - if (meta_wayland_pointer_client_is_empty (pointer_client)) - { - if (pointer->focus_client == pointer_client) - pointer->focus_client = NULL; - g_hash_table_remove (pointer->pointer_clients, client); - } -} - -void -meta_wayland_pointer_unbind_pointer_client_resource (struct wl_resource *resource) -{ - MetaWaylandPointer *pointer = wl_resource_get_user_data (resource); - MetaWaylandPointerClient *pointer_client; - struct wl_client *client = wl_resource_get_client (resource); - - pointer = wl_resource_get_user_data (resource); - if (!pointer) - return; - - wl_list_remove (wl_resource_get_link (resource)); - - pointer_client = meta_wayland_pointer_get_pointer_client (pointer, client); - if (!pointer_client) - { - /* This happens if all pointer devices were unplugged and no new resources - * were created by the client. - * - * If this is a resource that was previously made defunct, pointer_client - * be non-NULL but it is harmless since the below cleanup call will be - * prevented from removing the pointer client because of valid resources. - */ - return; - } - - meta_wayland_pointer_cleanup_pointer_client (pointer, - pointer_client, - client); -} - -static void -sync_focus_surface (MetaWaylandPointer *pointer) -{ - MetaDisplay *display = meta_get_display (); - MetaBackend *backend = meta_get_backend (); - MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); - ClutterBackend *clutter_backend = clutter_get_default_backend (); - ClutterSeat *clutter_seat = clutter_backend_get_default_seat (clutter_backend); - - if (!meta_cursor_tracker_get_pointer_visible (cursor_tracker) && - !clutter_seat_is_unfocus_inhibited (clutter_seat)) - { - meta_wayland_pointer_set_focus (pointer, NULL); - return; - } - - switch (display->event_route) - { - case META_EVENT_ROUTE_WINDOW_OP: - case META_EVENT_ROUTE_COMPOSITOR_GRAB: - case META_EVENT_ROUTE_FRAME_BUTTON: - /* The compositor has a grab, so remove our focus... */ - meta_wayland_pointer_set_focus (pointer, NULL); - break; - - case META_EVENT_ROUTE_NORMAL: - case META_EVENT_ROUTE_WAYLAND_POPUP: - { - const MetaWaylandPointerGrabInterface *interface = pointer->grab->interface; - interface->focus (pointer->grab, pointer->current); - } - break; - - default: - g_assert_not_reached (); - } - -} - -static void -meta_wayland_pointer_send_frame (MetaWaylandPointer *pointer, - struct wl_resource *resource) -{ - if (wl_resource_get_version (resource) >= WL_POINTER_AXIS_SOURCE_SINCE_VERSION) - wl_pointer_send_frame (resource); -} - -void -meta_wayland_pointer_broadcast_frame (MetaWaylandPointer *pointer) -{ - struct wl_resource *resource; - - if (!pointer->focus_client) - return; - - wl_resource_for_each (resource, &pointer->focus_client->pointer_resources) - { - meta_wayland_pointer_send_frame (pointer, resource); - } -} - -void -meta_wayland_pointer_send_relative_motion (MetaWaylandPointer *pointer, - const ClutterEvent *event) -{ - struct wl_resource *resource; - double dx, dy; - double dx_unaccel, dy_unaccel; - uint64_t time_us; - uint32_t time_us_hi; - uint32_t time_us_lo; - wl_fixed_t dxf, dyf; - wl_fixed_t dx_unaccelf, dy_unaccelf; - - if (!pointer->focus_client) - return; - - if (!clutter_event_get_relative_motion (event, - &dx, &dy, - &dx_unaccel, &dy_unaccel)) - return; - - time_us = clutter_event_get_time_us (event); - if (time_us == 0) - time_us = clutter_event_get_time (event) * 1000ULL; - time_us_hi = (uint32_t) (time_us >> 32); - time_us_lo = (uint32_t) time_us; - dxf = wl_fixed_from_double (dx); - dyf = wl_fixed_from_double (dy); - dx_unaccelf = wl_fixed_from_double (dx_unaccel); - dy_unaccelf = wl_fixed_from_double (dy_unaccel); - - wl_resource_for_each (resource, - &pointer->focus_client->relative_pointer_resources) - { - zwp_relative_pointer_v1_send_relative_motion (resource, - time_us_hi, - time_us_lo, - dxf, - dyf, - dx_unaccelf, - dy_unaccelf); - } -} - -void -meta_wayland_pointer_send_motion (MetaWaylandPointer *pointer, - const ClutterEvent *event) -{ - struct wl_resource *resource; - uint32_t time; - float sx, sy; - - if (!pointer->focus_client) - return; - - time = clutter_event_get_time (event); - meta_wayland_surface_get_relative_coordinates (pointer->focus_surface, - event->motion.x, - event->motion.y, - &sx, &sy); - - wl_resource_for_each (resource, &pointer->focus_client->pointer_resources) - { - wl_pointer_send_motion (resource, time, - wl_fixed_from_double (sx), - wl_fixed_from_double (sy)); - } - - meta_wayland_pointer_send_relative_motion (pointer, event); - - meta_wayland_pointer_broadcast_frame (pointer); -} - -void -meta_wayland_pointer_send_button (MetaWaylandPointer *pointer, - const ClutterEvent *event) -{ - struct wl_resource *resource; - ClutterEventType event_type; - - event_type = clutter_event_type (event); - - if (pointer->focus_client && - !wl_list_empty (&pointer->focus_client->pointer_resources)) - { - MetaWaylandInputDevice *input_device = - META_WAYLAND_INPUT_DEVICE (pointer); - uint32_t time; - uint32_t button; - uint32_t serial; - - button = clutter_event_get_event_code (event); - time = clutter_event_get_time (event); - serial = meta_wayland_input_device_next_serial (input_device); - - wl_resource_for_each (resource, &pointer->focus_client->pointer_resources) - { - wl_pointer_send_button (resource, serial, - time, button, - event_type == CLUTTER_BUTTON_PRESS ? 1 : 0); - } - - meta_wayland_pointer_broadcast_frame (pointer); - } - - if (pointer->button_count == 0 && event_type == CLUTTER_BUTTON_RELEASE) - sync_focus_surface (pointer); -} - -static void -default_grab_focus (MetaWaylandPointerGrab *grab, - MetaWaylandSurface *surface) -{ - MetaWaylandPointer *pointer = grab->pointer; - MetaWaylandSeat *seat = meta_wayland_pointer_get_seat (pointer); - MetaDisplay *display = meta_get_display (); - MetaBackend *backend = meta_get_backend (); - MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); - ClutterBackend *clutter_backend = clutter_get_default_backend (); - ClutterSeat *clutter_seat = clutter_backend_get_default_seat (clutter_backend); - - if (!meta_wayland_seat_has_pointer (seat)) - return; - - if (!meta_cursor_tracker_get_pointer_visible (cursor_tracker) && - !clutter_seat_is_unfocus_inhibited (clutter_seat)) - return; - - if (pointer->button_count > 0) - return; - - switch (display->event_route) - { - case META_EVENT_ROUTE_WINDOW_OP: - case META_EVENT_ROUTE_COMPOSITOR_GRAB: - case META_EVENT_ROUTE_FRAME_BUTTON: - return; - break; - - case META_EVENT_ROUTE_NORMAL: - case META_EVENT_ROUTE_WAYLAND_POPUP: - break; - } - - meta_wayland_pointer_set_focus (pointer, surface); -} - -static void -default_grab_motion (MetaWaylandPointerGrab *grab, - const ClutterEvent *event) -{ - MetaWaylandPointer *pointer = grab->pointer; - - meta_wayland_pointer_send_motion (pointer, event); -} - -static void -default_grab_button (MetaWaylandPointerGrab *grab, - const ClutterEvent *event) -{ - MetaWaylandPointer *pointer = grab->pointer; - - meta_wayland_pointer_send_button (pointer, event); -} - -static const MetaWaylandPointerGrabInterface default_pointer_grab_interface = { - default_grab_focus, - default_grab_motion, - default_grab_button -}; - -static void -meta_wayland_pointer_on_cursor_changed (MetaCursorTracker *cursor_tracker, - MetaWaylandPointer *pointer) -{ - if (pointer->cursor_surface) - meta_wayland_surface_update_outputs (pointer->cursor_surface); -} - -void -meta_wayland_pointer_enable (MetaWaylandPointer *pointer) -{ - MetaBackend *backend = meta_get_backend (); - MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); - ClutterSeat *clutter_seat; - - pointer->pointer_clients = - g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) meta_wayland_pointer_client_free); - - pointer->cursor_surface = NULL; - - clutter_seat = clutter_backend_get_default_seat (clutter_get_default_backend ()); - pointer->device = clutter_seat_get_pointer (clutter_seat); - - g_signal_connect (cursor_tracker, - "cursor-changed", - G_CALLBACK (meta_wayland_pointer_on_cursor_changed), - pointer); - - g_signal_connect_swapped (cursor_tracker, - "visibility-changed", - G_CALLBACK (sync_focus_surface), - pointer); - - g_signal_connect_swapped (clutter_seat, - "is-unfocus-inhibited-changed", - G_CALLBACK (sync_focus_surface), - pointer); -} - -void -meta_wayland_pointer_disable (MetaWaylandPointer *pointer) -{ - MetaBackend *backend = meta_get_backend (); - MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); - ClutterBackend *clutter_backend = clutter_get_default_backend (); - ClutterSeat *clutter_seat = clutter_backend_get_default_seat (clutter_backend); - - g_signal_handlers_disconnect_by_func (cursor_tracker, - (gpointer) meta_wayland_pointer_on_cursor_changed, - pointer); - - g_signal_handlers_disconnect_by_func (cursor_tracker, - sync_focus_surface, - pointer); - - g_signal_handlers_disconnect_by_func (clutter_seat, - sync_focus_surface, - pointer); - - if (pointer->cursor_surface) - { - g_clear_signal_handler (&pointer->cursor_surface_destroy_id, - pointer->cursor_surface); - } - - meta_wayland_pointer_cancel_grab (pointer); - meta_wayland_pointer_reset_grab (pointer); - meta_wayland_pointer_set_focus (pointer, NULL); - meta_wayland_pointer_set_current (pointer, NULL); - - g_clear_pointer (&pointer->pointer_clients, g_hash_table_unref); - pointer->cursor_surface = NULL; -} - -static int -count_buttons (const ClutterEvent *event) -{ - static gint maskmap[5] = - { - CLUTTER_BUTTON1_MASK, CLUTTER_BUTTON2_MASK, CLUTTER_BUTTON3_MASK, - CLUTTER_BUTTON4_MASK, CLUTTER_BUTTON5_MASK - }; - ClutterModifierType mod_mask; - int i, count; - - mod_mask = clutter_event_get_state (event); - count = 0; - for (i = 0; i < 5; i++) - { - if (mod_mask & maskmap[i]) - count++; - } - - return count; -} - -static void -current_surface_destroyed (MetaWaylandSurface *surface, - MetaWaylandPointer *pointer) -{ - meta_wayland_pointer_set_current (pointer, NULL); -} - -static void -meta_wayland_pointer_set_current (MetaWaylandPointer *pointer, - MetaWaylandSurface *surface) -{ - if (pointer->current) - { - g_clear_signal_handler (&pointer->current_surface_destroyed_handler_id, - pointer->current); - pointer->current = NULL; - } - - if (surface) - { - pointer->current = surface; - pointer->current_surface_destroyed_handler_id = - g_signal_connect (surface, "destroy", - G_CALLBACK (current_surface_destroyed), - pointer); - } -} - -static void -repick_for_event (MetaWaylandPointer *pointer, - const ClutterEvent *for_event) -{ - ClutterActor *actor; - MetaWaylandSurface *surface; - - if (clutter_event_type (for_event) == CLUTTER_LEAVE) - actor = clutter_event_get_related (for_event); - else - actor = clutter_event_get_source (for_event); - - if (META_IS_SURFACE_ACTOR_WAYLAND (actor)) - { - MetaSurfaceActorWayland *actor_wayland = - META_SURFACE_ACTOR_WAYLAND (actor); - - surface = meta_surface_actor_wayland_get_surface (actor_wayland); - } - else - { - surface = NULL; - } - - meta_wayland_pointer_set_current (pointer, surface); - - sync_focus_surface (pointer); - meta_wayland_pointer_update_cursor_surface (pointer); -} - -void -meta_wayland_pointer_update (MetaWaylandPointer *pointer, - const ClutterEvent *event) -{ - if ((event->type == CLUTTER_MOTION || - event->type == CLUTTER_ENTER || - event->type == CLUTTER_LEAVE) && - !clutter_event_get_event_sequence (event)) - repick_for_event (pointer, event); - - if (event->type == CLUTTER_MOTION || - event->type == CLUTTER_BUTTON_PRESS || - event->type == CLUTTER_BUTTON_RELEASE) - { - pointer->button_count = count_buttons (event); - } -} - -static void -notify_motion (MetaWaylandPointer *pointer, - const ClutterEvent *event) -{ - pointer->grab->interface->motion (pointer->grab, event); -} - -static void -handle_motion_event (MetaWaylandPointer *pointer, - const ClutterEvent *event) -{ - notify_motion (pointer, event); -} - -static void -handle_button_event (MetaWaylandPointer *pointer, - const ClutterEvent *event) -{ - gboolean implicit_grab; - - implicit_grab = (event->type == CLUTTER_BUTTON_PRESS) && (pointer->button_count == 1); - if (implicit_grab) - { - pointer->grab_button = clutter_event_get_button (event); - pointer->grab_time = clutter_event_get_time (event); - clutter_event_get_coords (event, &pointer->grab_x, &pointer->grab_y); - } - - pointer->grab->interface->button (pointer->grab, event); - - if (implicit_grab) - { - MetaWaylandSeat *seat = meta_wayland_pointer_get_seat (pointer); - - pointer->grab_serial = wl_display_get_serial (seat->wl_display); - } -} - -static void -handle_scroll_event (MetaWaylandPointer *pointer, - const ClutterEvent *event) -{ - struct wl_resource *resource; - wl_fixed_t x_value = 0, y_value = 0; - int x_discrete = 0, y_discrete = 0; - enum wl_pointer_axis_source source = -1; - - if (clutter_event_is_pointer_emulated (event)) - return; - - switch (event->scroll.scroll_source) - { - case CLUTTER_SCROLL_SOURCE_WHEEL: - source = WL_POINTER_AXIS_SOURCE_WHEEL; - break; - case CLUTTER_SCROLL_SOURCE_FINGER: - source = WL_POINTER_AXIS_SOURCE_FINGER; - break; - case CLUTTER_SCROLL_SOURCE_CONTINUOUS: - source = WL_POINTER_AXIS_SOURCE_CONTINUOUS; - break; - default: - source = WL_POINTER_AXIS_SOURCE_WHEEL; - break; - } - - switch (clutter_event_get_scroll_direction (event)) - { - case CLUTTER_SCROLL_UP: - y_value = -DEFAULT_AXIS_STEP_DISTANCE; - y_discrete = -1; - break; - - case CLUTTER_SCROLL_DOWN: - y_value = DEFAULT_AXIS_STEP_DISTANCE; - y_discrete = 1; - break; - - case CLUTTER_SCROLL_LEFT: - x_value = -DEFAULT_AXIS_STEP_DISTANCE; - x_discrete = -1; - break; - - case CLUTTER_SCROLL_RIGHT: - x_value = DEFAULT_AXIS_STEP_DISTANCE; - x_discrete = 1; - break; - - case CLUTTER_SCROLL_SMOOTH: - { - double dx, dy; - /* Clutter smooth scroll events are in discrete steps (1 step = 1.0 long - * vector along one axis). To convert to smooth scroll events that are - * in pointer motion event space, multiply the vector with the 10. */ - const double factor = 10.0; - clutter_event_get_scroll_delta (event, &dx, &dy); - x_value = wl_fixed_from_double (dx) * factor; - y_value = wl_fixed_from_double (dy) * factor; - } - break; - - default: - return; - } - - if (pointer->focus_client) - { - wl_resource_for_each (resource, &pointer->focus_client->pointer_resources) - { - if (wl_resource_get_version (resource) >= WL_POINTER_AXIS_SOURCE_SINCE_VERSION) - wl_pointer_send_axis_source (resource, source); - - /* X axis */ - if (x_discrete != 0 && - wl_resource_get_version (resource) >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION) - wl_pointer_send_axis_discrete (resource, - WL_POINTER_AXIS_HORIZONTAL_SCROLL, - x_discrete); - - if (x_value) - wl_pointer_send_axis (resource, clutter_event_get_time (event), - WL_POINTER_AXIS_HORIZONTAL_SCROLL, x_value); - - if ((event->scroll.finish_flags & CLUTTER_SCROLL_FINISHED_HORIZONTAL) && - wl_resource_get_version (resource) >= WL_POINTER_AXIS_STOP_SINCE_VERSION) - wl_pointer_send_axis_stop (resource, - clutter_event_get_time (event), - WL_POINTER_AXIS_HORIZONTAL_SCROLL); - /* Y axis */ - if (y_discrete != 0 && - wl_resource_get_version (resource) >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION) - wl_pointer_send_axis_discrete (resource, - WL_POINTER_AXIS_VERTICAL_SCROLL, - y_discrete); - - if (y_value) - wl_pointer_send_axis (resource, clutter_event_get_time (event), - WL_POINTER_AXIS_VERTICAL_SCROLL, y_value); - - if ((event->scroll.finish_flags & CLUTTER_SCROLL_FINISHED_VERTICAL) && - wl_resource_get_version (resource) >= WL_POINTER_AXIS_STOP_SINCE_VERSION) - wl_pointer_send_axis_stop (resource, - clutter_event_get_time (event), - WL_POINTER_AXIS_VERTICAL_SCROLL); - } - - meta_wayland_pointer_broadcast_frame (pointer); - } -} - -gboolean -meta_wayland_pointer_handle_event (MetaWaylandPointer *pointer, - const ClutterEvent *event) -{ - switch (event->type) - { - case CLUTTER_MOTION: - handle_motion_event (pointer, event); - break; - - case CLUTTER_BUTTON_PRESS: - case CLUTTER_BUTTON_RELEASE: - handle_button_event (pointer, event); - break; - - case CLUTTER_SCROLL: - handle_scroll_event (pointer, event); - break; - - case CLUTTER_TOUCHPAD_SWIPE: - meta_wayland_pointer_gesture_swipe_handle_event (pointer, event); - break; - - case CLUTTER_TOUCHPAD_PINCH: - meta_wayland_pointer_gesture_pinch_handle_event (pointer, event); - break; - - default: - break; - } - - return FALSE; -} - -static void -meta_wayland_pointer_send_enter (MetaWaylandPointer *pointer, - struct wl_resource *pointer_resource, - uint32_t serial, - MetaWaylandSurface *surface) -{ - wl_fixed_t sx, sy; - - meta_wayland_pointer_get_relative_coordinates (pointer, surface, &sx, &sy); - wl_pointer_send_enter (pointer_resource, - serial, - surface->resource, - sx, sy); -} - -static void -meta_wayland_pointer_send_leave (MetaWaylandPointer *pointer, - struct wl_resource *pointer_resource, - uint32_t serial, - MetaWaylandSurface *surface) -{ - wl_pointer_send_leave (pointer_resource, serial, surface->resource); -} - -static void -meta_wayland_pointer_broadcast_enter (MetaWaylandPointer *pointer, - uint32_t serial, - MetaWaylandSurface *surface) -{ - struct wl_resource *pointer_resource; - - wl_resource_for_each (pointer_resource, - &pointer->focus_client->pointer_resources) - meta_wayland_pointer_send_enter (pointer, pointer_resource, - serial, surface); - - meta_wayland_pointer_broadcast_frame (pointer); -} - -static void -meta_wayland_pointer_broadcast_leave (MetaWaylandPointer *pointer, - uint32_t serial, - MetaWaylandSurface *surface) -{ - struct wl_resource *pointer_resource; - - wl_resource_for_each (pointer_resource, - &pointer->focus_client->pointer_resources) - meta_wayland_pointer_send_leave (pointer, pointer_resource, - serial, surface); - - meta_wayland_pointer_broadcast_frame (pointer); -} - -static void -focus_surface_destroyed (MetaWaylandSurface *surface, - MetaWaylandPointer *pointer) -{ - meta_wayland_pointer_set_focus (pointer, NULL); -} - -void -meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer, - MetaWaylandSurface *surface) -{ - MetaWaylandInputDevice *input_device = META_WAYLAND_INPUT_DEVICE (pointer); - MetaBackend *backend = meta_get_backend (); - MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); - ClutterBackend *clutter_backend = clutter_get_default_backend (); - ClutterSeat *clutter_seat = clutter_backend_get_default_seat (clutter_backend); - - g_return_if_fail (meta_cursor_tracker_get_pointer_visible (cursor_tracker) || - clutter_seat_is_unfocus_inhibited (clutter_seat) || - surface == NULL); - - if (pointer->focus_surface == surface) - return; - - if (pointer->focus_surface != NULL) - { - uint32_t serial; - - serial = meta_wayland_input_device_next_serial (input_device); - - if (pointer->focus_client) - { - meta_wayland_pointer_broadcast_leave (pointer, - serial, - pointer->focus_surface); - pointer->focus_client = NULL; - } - - g_clear_signal_handler (&pointer->focus_surface_destroyed_handler_id, - pointer->focus_surface); - pointer->focus_surface = NULL; - } - - if (surface != NULL) - { - ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend)); - struct wl_client *client = wl_resource_get_client (surface->resource); - graphene_point_t pos; - MetaWindow *focus_window; - - pointer->focus_surface = surface; - - pointer->focus_surface_destroyed_handler_id = - g_signal_connect_after (pointer->focus_surface, "destroy", - G_CALLBACK (focus_surface_destroyed), - pointer); - - clutter_stage_get_device_coords (stage, pointer->device, NULL, &pos); - - focus_window = meta_wayland_surface_get_window (pointer->focus_surface); - if (focus_window) - meta_window_handle_enter (focus_window, - /* XXX -- can we reliably get a timestamp for setting focus? */ - clutter_get_current_event_time (), - pos.x, pos.y); - - pointer->focus_client = - meta_wayland_pointer_get_pointer_client (pointer, client); - if (pointer->focus_client) - { - pointer->focus_serial = - meta_wayland_input_device_next_serial (input_device); - meta_wayland_pointer_broadcast_enter (pointer, - pointer->focus_serial, - pointer->focus_surface); - } - } - - meta_wayland_pointer_update_cursor_surface (pointer); - - g_signal_emit (pointer, signals[FOCUS_SURFACE_CHANGED], 0); -} - -void -meta_wayland_pointer_start_grab (MetaWaylandPointer *pointer, - MetaWaylandPointerGrab *grab) -{ - const MetaWaylandPointerGrabInterface *interface; - - meta_wayland_pointer_cancel_grab (pointer); - - pointer->grab = grab; - interface = pointer->grab->interface; - grab->pointer = pointer; - - interface->focus (pointer->grab, pointer->current); -} - -static void -meta_wayland_pointer_reset_grab (MetaWaylandPointer *pointer) -{ - pointer->grab = &pointer->default_grab; -} - -void -meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer) -{ - const MetaWaylandPointerGrabInterface *interface; - - pointer->grab = &pointer->default_grab; - interface = pointer->grab->interface; - interface->focus (pointer->grab, pointer->current); - - meta_wayland_pointer_update_cursor_surface (pointer); -} - -static void -meta_wayland_pointer_cancel_grab (MetaWaylandPointer *pointer) -{ - if (pointer->grab->interface->cancel) - pointer->grab->interface->cancel (pointer->grab); -} - -void -meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer) -{ - MetaWaylandPopupGrab *popup_grab = (MetaWaylandPopupGrab*)pointer->grab; - - meta_wayland_popup_grab_destroy (popup_grab); -} - -MetaWaylandPopup * -meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer, - MetaWaylandPopupSurface *popup_surface) -{ - MetaWaylandPopupGrab *grab; - - if (pointer->grab != &pointer->default_grab && - !meta_wayland_pointer_grab_is_popup_grab (pointer->grab)) - return NULL; - - if (pointer->grab == &pointer->default_grab) - grab = meta_wayland_popup_grab_create (pointer, popup_surface); - else - grab = (MetaWaylandPopupGrab*)pointer->grab; - - return meta_wayland_popup_create (popup_surface, grab); -} - -void -meta_wayland_pointer_get_relative_coordinates (MetaWaylandPointer *pointer, - MetaWaylandSurface *surface, - wl_fixed_t *sx, - wl_fixed_t *sy) -{ - MetaBackend *backend = meta_get_backend (); - ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend)); - float xf = 0.0f, yf = 0.0f; - graphene_point_t pos; - - clutter_stage_get_device_coords (stage, pointer->device, NULL, &pos); - meta_wayland_surface_get_relative_coordinates (surface, pos.x, pos.y, &xf, &yf); - - *sx = wl_fixed_from_double (xf); - *sy = wl_fixed_from_double (yf); -} - -void -meta_wayland_pointer_update_cursor_surface (MetaWaylandPointer *pointer) -{ - MetaBackend *backend = meta_get_backend (); - MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); - - if (pointer->current) - { - MetaCursorSprite *cursor_sprite = NULL; - - if (pointer->cursor_surface) - { - MetaWaylandCursorSurface *cursor_surface = - META_WAYLAND_CURSOR_SURFACE (pointer->cursor_surface->role); - - cursor_sprite = meta_wayland_cursor_surface_get_sprite (cursor_surface); - } - - meta_cursor_tracker_set_window_cursor (cursor_tracker, cursor_sprite); - } - else - { - meta_cursor_tracker_unset_window_cursor (cursor_tracker); - } -} - -static void -ensure_update_cursor_surface (MetaWaylandPointer *pointer, - MetaWaylandSurface *surface) -{ - if (pointer->cursor_surface != surface) - return; - - pointer->cursor_surface = NULL; - meta_wayland_pointer_update_cursor_surface (pointer); -} - -static void -meta_wayland_pointer_set_cursor_surface (MetaWaylandPointer *pointer, - MetaWaylandSurface *cursor_surface) -{ - MetaWaylandSurface *prev_cursor_surface; - - prev_cursor_surface = pointer->cursor_surface; - - if (prev_cursor_surface == cursor_surface) - return; - - pointer->cursor_surface = cursor_surface; - - if (prev_cursor_surface) - { - meta_wayland_surface_update_outputs (prev_cursor_surface); - g_clear_signal_handler (&pointer->cursor_surface_destroy_id, - prev_cursor_surface); - } - - if (cursor_surface) - { - pointer->cursor_surface_destroy_id = - g_signal_connect_swapped (cursor_surface, "destroy", - G_CALLBACK (ensure_update_cursor_surface), - pointer); - } - - meta_wayland_pointer_update_cursor_surface (pointer); -} - -static void -pointer_set_cursor (struct wl_client *client, - struct wl_resource *resource, - uint32_t serial, - struct wl_resource *surface_resource, - int32_t hot_x, int32_t hot_y) -{ - MetaWaylandPointer *pointer; - MetaWaylandSurface *surface; - - pointer = wl_resource_get_user_data (resource); - if (!pointer) - return; - - surface = (surface_resource ? wl_resource_get_user_data (surface_resource) : NULL); - - if (pointer->focus_surface == NULL) - return; - if (wl_resource_get_client (pointer->focus_surface->resource) != client) - return; - if (pointer->focus_serial - serial > G_MAXUINT32 / 2) - return; - - if (surface && - !meta_wayland_surface_assign_role (surface, - META_TYPE_WAYLAND_CURSOR_SURFACE, - NULL)) - { - wl_resource_post_error (resource, WL_POINTER_ERROR_ROLE, - "wl_surface@%d already has a different role", - wl_resource_get_id (surface_resource)); - return; - } - - if (surface) - { - ClutterBackend *clutter_backend = clutter_get_default_backend (); - ClutterSeat *clutter_seat = - clutter_backend_get_default_seat (clutter_backend); - ClutterInputDevice *device = clutter_seat_get_pointer (clutter_seat); - MetaCursorRenderer *cursor_renderer = - meta_backend_get_cursor_renderer_for_device (meta_get_backend (), - device); - MetaWaylandCursorSurface *cursor_surface; - - cursor_surface = META_WAYLAND_CURSOR_SURFACE (surface->role); - meta_wayland_cursor_surface_set_renderer (cursor_surface, - cursor_renderer); - meta_wayland_cursor_surface_set_hotspot (cursor_surface, - hot_x, hot_y); - } - - meta_wayland_pointer_set_cursor_surface (pointer, surface); -} - -static void -pointer_release (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static const struct wl_pointer_interface pointer_interface = { - pointer_set_cursor, - pointer_release, -}; - -void -meta_wayland_pointer_create_new_resource (MetaWaylandPointer *pointer, - struct wl_client *client, - struct wl_resource *seat_resource, - uint32_t id) -{ - struct wl_resource *resource; - MetaWaylandPointerClient *pointer_client; - - resource = wl_resource_create (client, &wl_pointer_interface, - wl_resource_get_version (seat_resource), id); - wl_resource_set_implementation (resource, &pointer_interface, pointer, - meta_wayland_pointer_unbind_pointer_client_resource); - - pointer_client = meta_wayland_pointer_ensure_pointer_client (pointer, client); - - wl_list_insert (&pointer_client->pointer_resources, - wl_resource_get_link (resource)); - - if (pointer->focus_client == pointer_client) - { - meta_wayland_pointer_send_enter (pointer, resource, - pointer->focus_serial, - pointer->focus_surface); - meta_wayland_pointer_send_frame (pointer, resource); - } -} - -static gboolean -pointer_can_grab_surface (MetaWaylandPointer *pointer, - MetaWaylandSurface *surface) -{ - MetaWaylandSurface *subsurface; - - if (pointer->focus_surface == surface) - return TRUE; - - META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface) - { - if (pointer_can_grab_surface (pointer, subsurface)) - return TRUE; - } - - return FALSE; -} - -gboolean -meta_wayland_pointer_can_grab_surface (MetaWaylandPointer *pointer, - MetaWaylandSurface *surface, - uint32_t serial) -{ - return (pointer->grab_serial == serial && - pointer_can_grab_surface (pointer, surface)); -} - -gboolean -meta_wayland_pointer_can_popup (MetaWaylandPointer *pointer, uint32_t serial) -{ - return pointer->grab_serial == serial; -} - -MetaWaylandSurface * -meta_wayland_pointer_get_top_popup (MetaWaylandPointer *pointer) -{ - MetaWaylandPopupGrab *grab; - - if (!meta_wayland_pointer_grab_is_popup_grab (pointer->grab)) - return NULL; - - grab = (MetaWaylandPopupGrab*)pointer->grab; - return meta_wayland_popup_grab_get_top_popup(grab); -} - -static void -relative_pointer_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static const struct zwp_relative_pointer_v1_interface relative_pointer_interface = { - relative_pointer_destroy -}; - -static void -relative_pointer_manager_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -relative_pointer_manager_get_relative_pointer (struct wl_client *client, - struct wl_resource *manager_resource, - uint32_t id, - struct wl_resource *pointer_resource) -{ - MetaWaylandPointer *pointer = wl_resource_get_user_data (pointer_resource); - struct wl_resource *resource; - MetaWaylandPointerClient *pointer_client; - - resource = wl_resource_create (client, &zwp_relative_pointer_v1_interface, - wl_resource_get_version (manager_resource), - id); - if (!resource) - { - wl_client_post_no_memory (client); - return; - } - - wl_resource_set_implementation (resource, &relative_pointer_interface, - pointer, - meta_wayland_pointer_unbind_pointer_client_resource); - - pointer_client = meta_wayland_pointer_ensure_pointer_client (pointer, client); - - wl_list_insert (&pointer_client->relative_pointer_resources, - wl_resource_get_link (resource)); -} - -static const struct zwp_relative_pointer_manager_v1_interface relative_pointer_manager = { - relative_pointer_manager_destroy, - relative_pointer_manager_get_relative_pointer, -}; - -static void -bind_relative_pointer_manager (struct wl_client *client, - void *data, - uint32_t version, - uint32_t id) -{ - MetaWaylandCompositor *compositor = data; - struct wl_resource *resource; - - resource = wl_resource_create (client, - &zwp_relative_pointer_manager_v1_interface, - 1, id); - - if (version != 1) - wl_resource_post_error (resource, - WL_DISPLAY_ERROR_INVALID_OBJECT, - "bound invalid version %u of " - "wp_relative_pointer_manager", - version); - - wl_resource_set_implementation (resource, &relative_pointer_manager, - compositor, - NULL); -} - -void -meta_wayland_relative_pointer_init (MetaWaylandCompositor *compositor) -{ - /* Relative pointer events are currently only supported by the native backend - * so lets just advertise the extension when the native backend is used. - */ -#ifdef HAVE_NATIVE_BACKEND - if (!META_IS_BACKEND_NATIVE (meta_get_backend ())) - return; -#else - return; -#endif - - if (!wl_global_create (compositor->wayland_display, - &zwp_relative_pointer_manager_v1_interface, 1, - compositor, bind_relative_pointer_manager)) - g_error ("Could not create relative pointer manager global"); -} - -MetaWaylandSeat * -meta_wayland_pointer_get_seat (MetaWaylandPointer *pointer) -{ - MetaWaylandInputDevice *input_device = META_WAYLAND_INPUT_DEVICE (pointer); - - return meta_wayland_input_device_get_seat (input_device); -} - -static void -meta_wayland_pointer_init (MetaWaylandPointer *pointer) -{ - pointer->default_grab.interface = &default_pointer_grab_interface; - pointer->default_grab.pointer = pointer; - pointer->grab = &pointer->default_grab; -} - -static void -meta_wayland_pointer_class_init (MetaWaylandPointerClass *klass) -{ - signals[FOCUS_SURFACE_CHANGED] = g_signal_new ("focus-surface-changed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); -} diff --git a/src/wayland/meta-wayland-pointer.h b/src/wayland/meta-wayland-pointer.h deleted file mode 100644 index 5eda5276f..000000000 --- a/src/wayland/meta-wayland-pointer.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2013 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 . - */ - -#ifndef META_WAYLAND_POINTER_H -#define META_WAYLAND_POINTER_H - -#include -#include - -#include "meta/meta-cursor-tracker.h" -#include "wayland/meta-wayland-pointer-constraints.h" -#include "wayland/meta-wayland-pointer-gesture-pinch.h" -#include "wayland/meta-wayland-pointer-gesture-swipe.h" -#include "wayland/meta-wayland-seat.h" -#include "wayland/meta-wayland-surface.h" -#include "wayland/meta-wayland-types.h" - -#define META_TYPE_WAYLAND_POINTER (meta_wayland_pointer_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandPointer, meta_wayland_pointer, - META, WAYLAND_POINTER, - MetaWaylandInputDevice) - -struct _MetaWaylandPointerGrabInterface -{ - void (*focus) (MetaWaylandPointerGrab *grab, - MetaWaylandSurface *surface); - void (*motion) (MetaWaylandPointerGrab *grab, - const ClutterEvent *event); - void (*button) (MetaWaylandPointerGrab *grab, - const ClutterEvent *event); - void (*cancel) (MetaWaylandPointerGrab *grab); -}; - -struct _MetaWaylandPointerGrab -{ - const MetaWaylandPointerGrabInterface *interface; - MetaWaylandPointer *pointer; -}; - -struct _MetaWaylandPointerClient -{ - struct wl_list pointer_resources; - struct wl_list swipe_gesture_resources; - struct wl_list pinch_gesture_resources; - struct wl_list relative_pointer_resources; -}; - -struct _MetaWaylandPointer -{ - MetaWaylandInputDevice parent; - - MetaWaylandPointerClient *focus_client; - GHashTable *pointer_clients; - - MetaWaylandSurface *focus_surface; - gulong focus_surface_destroyed_handler_id; - guint32 focus_serial; - guint32 click_serial; - - MetaWaylandSurface *cursor_surface; - gulong cursor_surface_destroy_id; - - MetaWaylandPointerGrab *grab; - MetaWaylandPointerGrab default_grab; - guint32 grab_button; - guint32 grab_serial; - guint32 grab_time; - float grab_x, grab_y; - - ClutterInputDevice *device; - MetaWaylandSurface *current; - gulong current_surface_destroyed_handler_id; - - guint32 button_count; -}; - -void meta_wayland_pointer_enable (MetaWaylandPointer *pointer); - -void meta_wayland_pointer_disable (MetaWaylandPointer *pointer); - -void meta_wayland_pointer_update (MetaWaylandPointer *pointer, - const ClutterEvent *event); - -gboolean meta_wayland_pointer_handle_event (MetaWaylandPointer *pointer, - const ClutterEvent *event); - -void meta_wayland_pointer_send_motion (MetaWaylandPointer *pointer, - const ClutterEvent *event); - -void meta_wayland_pointer_send_relative_motion (MetaWaylandPointer *pointer, - const ClutterEvent *event); - -void meta_wayland_pointer_send_button (MetaWaylandPointer *pointer, - const ClutterEvent *event); - -void meta_wayland_pointer_broadcast_frame (MetaWaylandPointer *pointer); - -void meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer, - MetaWaylandSurface *surface); - -void meta_wayland_pointer_start_grab (MetaWaylandPointer *pointer, - MetaWaylandPointerGrab *grab); - -void meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer); - -MetaWaylandPopup *meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer, - MetaWaylandPopupSurface *popup_surface); - -void meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer); - -void meta_wayland_pointer_get_relative_coordinates (MetaWaylandPointer *pointer, - MetaWaylandSurface *surface, - wl_fixed_t *x, - wl_fixed_t *y); - -void meta_wayland_pointer_create_new_resource (MetaWaylandPointer *pointer, - struct wl_client *client, - struct wl_resource *seat_resource, - uint32_t id); - -gboolean meta_wayland_pointer_can_grab_surface (MetaWaylandPointer *pointer, - MetaWaylandSurface *surface, - uint32_t serial); - -gboolean meta_wayland_pointer_can_popup (MetaWaylandPointer *pointer, - uint32_t serial); - -MetaWaylandSurface *meta_wayland_pointer_get_top_popup (MetaWaylandPointer *pointer); - -MetaWaylandPointerClient * meta_wayland_pointer_get_pointer_client (MetaWaylandPointer *pointer, - struct wl_client *client); -void meta_wayland_pointer_unbind_pointer_client_resource (struct wl_resource *resource); - -void meta_wayland_relative_pointer_init (MetaWaylandCompositor *compositor); - -MetaWaylandSeat *meta_wayland_pointer_get_seat (MetaWaylandPointer *pointer); - -void meta_wayland_surface_cursor_update (MetaWaylandSurface *cursor_surface); - -void meta_wayland_pointer_update_cursor_surface (MetaWaylandPointer *pointer); - -#endif /* META_WAYLAND_POINTER_H */ diff --git a/src/wayland/meta-wayland-popup.c b/src/wayland/meta-wayland-popup.c deleted file mode 100644 index 995d5f967..000000000 --- a/src/wayland/meta-wayland-popup.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2013 Intel Corporation - * Copyright (C) 2015 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 . - */ - -/* - * Copyright © 2008 Kristian Høgsberg - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that copyright - * notice and this permission notice appear in supporting documentation, and - * that the name of the copyright holders not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no representations - * about the suitability of this software for any purpose. It is provided "as - * is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE - * OF THIS SOFTWARE. - */ - -#include "config.h" - -#include "wayland/meta-wayland-popup.h" - -#include "wayland/meta-wayland-pointer.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-surface.h" - -G_DEFINE_INTERFACE (MetaWaylandPopupSurface, meta_wayland_popup_surface, - G_TYPE_OBJECT); - -struct _MetaWaylandPopupGrab -{ - MetaWaylandPointerGrab generic; - - struct wl_client *grab_client; - struct wl_list all_popups; -}; - -struct _MetaWaylandPopup -{ - MetaWaylandPopupGrab *grab; - MetaWaylandPopupSurface *popup_surface; - struct wl_list link; -}; - -static void -meta_wayland_popup_grab_begin (MetaWaylandPopupGrab *grab, - MetaWaylandSurface *surface); - -static void -meta_wayland_popup_grab_end (MetaWaylandPopupGrab *grab); - -static void -meta_wayland_popup_surface_default_init (MetaWaylandPopupSurfaceInterface *iface) -{ -} - -static void -meta_wayland_popup_surface_done (MetaWaylandPopupSurface *popup_surface) -{ - META_WAYLAND_POPUP_SURFACE_GET_IFACE (popup_surface)->done (popup_surface); -} - -static void -meta_wayland_popup_surface_dismiss (MetaWaylandPopupSurface *popup_surface) -{ - META_WAYLAND_POPUP_SURFACE_GET_IFACE (popup_surface)->dismiss (popup_surface); -} - -static MetaWaylandSurface * -meta_wayland_popup_surface_get_surface (MetaWaylandPopupSurface *popup_surface) -{ - return META_WAYLAND_POPUP_SURFACE_GET_IFACE (popup_surface)->get_surface (popup_surface); -} - -static void -popup_grab_focus (MetaWaylandPointerGrab *grab, - MetaWaylandSurface *surface) -{ - MetaWaylandPopupGrab *popup_grab = (MetaWaylandPopupGrab*)grab; - MetaWaylandSeat *seat = meta_wayland_pointer_get_seat (grab->pointer); - MetaWaylandPointer *pointer = grab->pointer; - - /* - * We rely on having a pointer grab even when the seat doesn't have - * the pointer capability. In this case, we shouldn't update any pointer focus - * since there is no such thing when the seat doesn't have the pointer - * capability. - */ - if (!meta_wayland_seat_has_pointer (seat)) - return; - - /* Popup grabs are in owner-events mode (ie, events for the same client - are reported as normal) */ - if (surface && - wl_resource_get_client (surface->resource) == popup_grab->grab_client) - meta_wayland_pointer_set_focus (grab->pointer, surface); - else if (pointer->button_count == 0) - meta_wayland_pointer_set_focus (grab->pointer, NULL); -} - -static void -popup_grab_motion (MetaWaylandPointerGrab *grab, - const ClutterEvent *event) -{ - meta_wayland_pointer_send_motion (grab->pointer, event); -} - -static void -popup_grab_button (MetaWaylandPointerGrab *grab, - const ClutterEvent *event) -{ - MetaWaylandPointer *pointer = grab->pointer; - - if (pointer->focus_surface) - meta_wayland_pointer_send_button (grab->pointer, event); - else if (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE && - pointer->button_count == 0) - meta_wayland_pointer_end_popup_grab (grab->pointer); -} - -static void -popup_grab_cancel (MetaWaylandPointerGrab *grab) -{ - meta_wayland_pointer_end_popup_grab (grab->pointer); -} - -static MetaWaylandPointerGrabInterface popup_grab_interface = { - popup_grab_focus, - popup_grab_motion, - popup_grab_button, - popup_grab_cancel -}; - -MetaWaylandPopupGrab * -meta_wayland_popup_grab_create (MetaWaylandPointer *pointer, - MetaWaylandPopupSurface *popup_surface) -{ - MetaWaylandSurface *surface = - meta_wayland_popup_surface_get_surface (popup_surface); - struct wl_client *client = wl_resource_get_client (surface->resource); - MetaWaylandPopupGrab *grab; - - grab = g_new0 (MetaWaylandPopupGrab, 1); - grab->generic.interface = &popup_grab_interface; - grab->generic.pointer = pointer; - grab->grab_client = client; - wl_list_init (&grab->all_popups); - - meta_wayland_popup_grab_begin (grab, surface); - - return grab; -} - -void -meta_wayland_popup_grab_destroy (MetaWaylandPopupGrab *grab) -{ - meta_wayland_popup_grab_end (grab); - g_free (grab); -} - -static void -meta_wayland_popup_grab_begin (MetaWaylandPopupGrab *grab, - MetaWaylandSurface *surface) -{ - MetaWaylandPointer *pointer = grab->generic.pointer; - MetaWindow *window = meta_wayland_surface_get_window (surface); - - meta_wayland_pointer_start_grab (pointer, (MetaWaylandPointerGrab*)grab); - meta_display_begin_grab_op (window->display, - window, - META_GRAB_OP_WAYLAND_POPUP, - FALSE, /* pointer_already_grabbed */ - FALSE, /* frame_action */ - 1, /* button. XXX? */ - 0, /* modmask */ - meta_display_get_current_time_roundtrip ( - window->display), - pointer->grab_x, - pointer->grab_y); -} - -void -meta_wayland_popup_grab_end (MetaWaylandPopupGrab *grab) -{ - MetaWaylandPopup *popup, *tmp; - - g_assert (grab->generic.interface == &popup_grab_interface); - - wl_list_for_each_safe (popup, tmp, &grab->all_popups, link) - { - meta_wayland_popup_surface_done (popup->popup_surface); - meta_wayland_popup_destroy (popup); - } - - { - MetaDisplay *display = meta_get_display (); - meta_display_end_grab_op (display, - meta_display_get_current_time_roundtrip (display)); - } - - meta_wayland_pointer_end_grab (grab->generic.pointer); -} - -MetaWaylandSurface * -meta_wayland_popup_grab_get_top_popup (MetaWaylandPopupGrab *grab) -{ - MetaWaylandPopup *popup; - - g_assert (!wl_list_empty (&grab->all_popups)); - popup = wl_container_of (grab->all_popups.next, popup, link); - - return meta_wayland_popup_surface_get_surface (popup->popup_surface); -} - -gboolean -meta_wayland_pointer_grab_is_popup_grab (MetaWaylandPointerGrab *grab) -{ - return grab->interface == &popup_grab_interface; -} - -void -meta_wayland_popup_destroy (MetaWaylandPopup *popup) -{ - meta_wayland_popup_surface_dismiss (popup->popup_surface); - - wl_list_remove (&popup->link); - g_free (popup); -} - -void -meta_wayland_popup_dismiss (MetaWaylandPopup *popup) -{ - MetaWaylandPopupGrab *popup_grab = popup->grab; - - meta_wayland_popup_destroy (popup); - - if (wl_list_empty (&popup_grab->all_popups)) - { - meta_wayland_pointer_end_popup_grab (popup_grab->generic.pointer); - } - else - { - MetaWaylandSurface *top_popup_surface; - MetaWaylandSeat *seat; - - top_popup_surface = meta_wayland_popup_grab_get_top_popup (popup_grab); - seat = meta_wayland_pointer_get_seat (popup_grab->generic.pointer); - - if (meta_wayland_seat_has_keyboard (seat)) - meta_wayland_keyboard_set_focus (seat->keyboard, top_popup_surface); - } -} - -MetaWaylandSurface * -meta_wayland_popup_get_top_popup (MetaWaylandPopup *popup) -{ - return meta_wayland_popup_grab_get_top_popup (popup->grab); -} - -MetaWaylandPopup * -meta_wayland_popup_create (MetaWaylandPopupSurface *popup_surface, - MetaWaylandPopupGrab *grab) -{ - MetaWaylandSurface *surface = - meta_wayland_popup_surface_get_surface (popup_surface); - MetaWaylandPopup *popup; - MetaWaylandSeat *seat; - - /* Don't allow creating popups if the grab has a different client. */ - if (grab->grab_client != wl_resource_get_client (surface->resource)) - return NULL; - - popup = g_new0 (MetaWaylandPopup, 1); - popup->grab = grab; - popup->popup_surface = popup_surface; - - wl_list_insert (&grab->all_popups, &popup->link); - - seat = meta_wayland_pointer_get_seat (grab->generic.pointer); - if (meta_wayland_seat_has_keyboard (seat)) - meta_wayland_keyboard_set_focus (seat->keyboard, surface); - - return popup; -} diff --git a/src/wayland/meta-wayland-popup.h b/src/wayland/meta-wayland-popup.h deleted file mode 100644 index 3cc90e22a..000000000 --- a/src/wayland/meta-wayland-popup.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2013 Intel Corporation - * Copyright (C) 2015 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 . - */ - -#ifndef META_WAYLAND_POPUP_H -#define META_WAYLAND_POPUP_H - -#include -#include - -#include "wayland/meta-wayland-types.h" -#include "wayland/meta-wayland-pointer.h" - -#define META_TYPE_WAYLAND_POPUP_SURFACE (meta_wayland_popup_surface_get_type ()) -G_DECLARE_INTERFACE (MetaWaylandPopupSurface, meta_wayland_popup_surface, - META, WAYLAND_POPUP_SURFACE, - GObject); - -struct _MetaWaylandPopupSurfaceInterface -{ - GTypeInterface parent_iface; - - void (*done) (MetaWaylandPopupSurface *popup_surface); - void (*dismiss) (MetaWaylandPopupSurface *popup_surface); - MetaWaylandSurface *(*get_surface) (MetaWaylandPopupSurface *popup_surface); -}; - -MetaWaylandPopupGrab *meta_wayland_popup_grab_create (MetaWaylandPointer *pointer, - MetaWaylandPopupSurface *popup_surface); - -void meta_wayland_popup_grab_destroy (MetaWaylandPopupGrab *grab); - -MetaWaylandSurface *meta_wayland_popup_grab_get_top_popup (MetaWaylandPopupGrab *grab); - -gboolean meta_wayland_pointer_grab_is_popup_grab (MetaWaylandPointerGrab *grab); - -MetaWaylandPopup *meta_wayland_popup_create (MetaWaylandPopupSurface *surface, - MetaWaylandPopupGrab *grab); - -void meta_wayland_popup_destroy (MetaWaylandPopup *popup); - -void meta_wayland_popup_dismiss (MetaWaylandPopup *popup); - -MetaWaylandSurface *meta_wayland_popup_get_top_popup (MetaWaylandPopup *popup); - -#endif /* META_WAYLAND_POPUP_H */ diff --git a/src/wayland/meta-wayland-presentation-time-private.h b/src/wayland/meta-wayland-presentation-time-private.h deleted file mode 100644 index bc3dc6a40..000000000 --- a/src/wayland/meta-wayland-presentation-time-private.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * presentation-time protocol - * - * Copyright (C) 2020 Ivan Molodetskikh - * - * 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_WAYLAND_PRESENTATION_TIME_PRIVATE_H -#define META_WAYLAND_PRESENTATION_TIME_PRIVATE_H - -#include - -#include "clutter/clutter.h" -#include "wayland/meta-wayland-cursor-surface.h" -#include "wayland/meta-wayland-types.h" - -typedef struct _MetaWaylandPresentationFeedback -{ - struct wl_list link; - struct wl_resource *resource; - - MetaWaylandSurface *surface; -} MetaWaylandPresentationFeedback; - -typedef struct _MetaWaylandPresentationTime -{ - GList *feedback_surfaces; - - /* - * A mapping from (ClutterStageView *) to a - * (MetaWaylandPresentationFeedback *) wl_list of presentation-time feedbacks - * that are scheduled to be presented. - */ - GHashTable *feedbacks; -} MetaWaylandPresentationTime; - -void meta_wayland_init_presentation_time (MetaWaylandCompositor *compositor); - -void meta_wayland_presentation_feedback_discard (MetaWaylandPresentationFeedback *feedback); - -void meta_wayland_presentation_feedback_present (MetaWaylandPresentationFeedback *feedback, - ClutterFrameInfo *frame_info, - MetaWaylandOutput *output); - -struct wl_list * meta_wayland_presentation_time_ensure_feedbacks (MetaWaylandPresentationTime *presentation_time, - ClutterStageView *stage_view); - -void meta_wayland_presentation_time_cursor_painted (MetaWaylandPresentationTime *presentation_time, - ClutterStageView *stage_view, - MetaWaylandCursorSurface *cursor_surface); - -#endif /* META_WAYLAND_PRESENTATION_TIME_PRIVATE_H */ diff --git a/src/wayland/meta-wayland-presentation-time.c b/src/wayland/meta-wayland-presentation-time.c deleted file mode 100644 index b0d8cf81c..000000000 --- a/src/wayland/meta-wayland-presentation-time.c +++ /dev/null @@ -1,417 +0,0 @@ -/* - * presentation-time protocol - * - * Copyright (C) 2020 Ivan Molodetskikh - * - * 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 "meta-wayland-presentation-time-private.h" - -#include - -#include "compositor/meta-surface-actor-wayland.h" -#include "wayland/meta-wayland-cursor-surface.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-surface.h" -#include "wayland/meta-wayland-outputs.h" -#include "wayland/meta-wayland-versions.h" - -#include "presentation-time-server-protocol.h" - -static void -wp_presentation_feedback_destructor (struct wl_resource *resource) -{ - MetaWaylandPresentationFeedback *feedback = - wl_resource_get_user_data (resource); - - wl_list_remove (&feedback->link); - g_free (feedback); -} - -static void -wp_presentation_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -wp_presentation_feedback (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *surface_resource, - uint32_t callback_id) -{ - MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); - MetaWaylandSurfaceState *pending; - MetaWaylandPresentationFeedback *feedback; - - feedback = g_new0 (MetaWaylandPresentationFeedback, 1); - wl_list_init (&feedback->link); - feedback->resource = wl_resource_create (client, - &wp_presentation_feedback_interface, - wl_resource_get_version (resource), - callback_id); - wl_resource_set_implementation (feedback->resource, - NULL, - feedback, - wp_presentation_feedback_destructor); - - if (surface == NULL) - { - g_warn_if_reached (); - meta_wayland_presentation_feedback_discard (feedback); - return; - } - - pending = meta_wayland_surface_get_pending_state (surface); - wl_list_insert (&pending->presentation_feedback_list, &feedback->link); - - feedback->surface = surface; -} - -static const struct wp_presentation_interface -meta_wayland_presentation_interface = { - wp_presentation_destroy, - wp_presentation_feedback, -}; - -static void -wp_presentation_bind (struct wl_client *client, - void *data, - uint32_t version, - uint32_t id) -{ - struct wl_resource *resource; - - resource = wl_resource_create (client, - &wp_presentation_interface, - version, - id); - wl_resource_set_implementation (resource, - &meta_wayland_presentation_interface, - NULL, - NULL); - - /* Presentation timestamps in Mutter are guaranteed to be CLOCK_MONOTONIC. */ - wp_presentation_send_clock_id (resource, CLOCK_MONOTONIC); -} - -static void -discard_non_cursor_feedbacks (struct wl_list *feedbacks) -{ - MetaWaylandPresentationFeedback *feedback, *next; - - wl_list_for_each_safe (feedback, next, feedbacks, link) - { - if (META_IS_WAYLAND_CURSOR_SURFACE (feedback->surface->role)) - continue; - - meta_wayland_presentation_feedback_discard (feedback); - } -} - -static void -on_after_paint (ClutterStage *stage, - ClutterStageView *stage_view, - MetaWaylandCompositor *compositor) -{ - struct wl_list *feedbacks; - GList *l; - - /* - * We just painted this stage view, which means that all non-cursor feedbacks - * that didn't fire (e.g. due to page flip failing) are now obsolete and - * should be discarded. - * - * Cursor feedbacks have a similar mechanism done separately, mainly because - * they are painted earlier, in prepare_frame(). This means that the feedbacks - * list currently contains stale non-cursor feedbacks and up-to-date cursor - * feedbacks. - */ - feedbacks = - meta_wayland_presentation_time_ensure_feedbacks (&compositor->presentation_time, - stage_view); - discard_non_cursor_feedbacks (feedbacks); - - l = compositor->presentation_time.feedback_surfaces; - while (l) - { - GList *l_cur = l; - MetaWaylandSurface *surface = l->data; - MetaSurfaceActor *actor; - ClutterStageView *surface_primary_view; - - l = l->next; - - actor = meta_wayland_surface_get_actor (surface); - if (!actor) - continue; - - surface_primary_view = - meta_surface_actor_wayland_get_current_primary_view (actor, stage); - if (stage_view != surface_primary_view) - continue; - - if (!wl_list_empty (&surface->presentation_time.feedback_list)) - { - /* Add feedbacks to the list to be fired on presentation. */ - wl_list_insert_list (feedbacks, - &surface->presentation_time.feedback_list); - wl_list_init (&surface->presentation_time.feedback_list); - - surface->presentation_time.needs_sequence_update = TRUE; - } - - compositor->presentation_time.feedback_surfaces = - g_list_delete_link (compositor->presentation_time.feedback_surfaces, - l_cur); - } -} - -static void -destroy_feedback_list (gpointer data) -{ - struct wl_list *feedbacks = data; - - while (!wl_list_empty (feedbacks)) - { - MetaWaylandPresentationFeedback *feedback = - wl_container_of (feedbacks->next, feedback, link); - - meta_wayland_presentation_feedback_discard (feedback); - } - - g_free (feedbacks); -} - -static void -on_monitors_changed (MetaMonitorManager *manager, - MetaWaylandCompositor *compositor) -{ - /* All ClutterStageViews were re-created, so clear our map. */ - g_hash_table_remove_all (compositor->presentation_time.feedbacks); -} - -void -meta_wayland_init_presentation_time (MetaWaylandCompositor *compositor) -{ - MetaContext *context = compositor->context; - MetaBackend *backend = meta_context_get_backend (context); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - ClutterActor *stage = meta_backend_get_stage (backend); - - compositor->presentation_time.feedbacks = - g_hash_table_new_full (NULL, NULL, NULL, destroy_feedback_list); - - g_signal_connect (monitor_manager, "monitors-changed-internal", - G_CALLBACK (on_monitors_changed), compositor); - - g_signal_connect (stage, "after-paint", - G_CALLBACK (on_after_paint), compositor); - - if (wl_global_create (compositor->wayland_display, - &wp_presentation_interface, - META_WP_PRESENTATION_VERSION, - NULL, - wp_presentation_bind) == NULL) - g_error ("Failed to register a global wp_presentation object"); -} - -void -meta_wayland_presentation_feedback_discard (MetaWaylandPresentationFeedback *feedback) -{ - wp_presentation_feedback_send_discarded (feedback->resource); - wl_resource_destroy (feedback->resource); -} - -static void -maybe_update_presentation_sequence (MetaWaylandSurface *surface, - ClutterFrameInfo *frame_info, - MetaWaylandOutput *output) -{ - unsigned int sequence_delta; - - if (!surface->presentation_time.needs_sequence_update) - return; - - surface->presentation_time.needs_sequence_update = FALSE; - - if (!(frame_info->flags & CLUTTER_FRAME_INFO_FLAG_VSYNC)) - goto invalid_sequence; - - /* Getting sequence = 0 after sequence = UINT_MAX is likely valid (32-bit - * overflow, on a 144 Hz display that's ~173 days of operation). Getting it - * otherwise is usually a driver bug. - */ - if (frame_info->sequence == 0 && - !(surface->presentation_time.is_last_output_sequence_valid && - surface->presentation_time.last_output_sequence == UINT_MAX)) - { - g_warning_once ("Invalid sequence for VSYNC frame info"); - goto invalid_sequence; - } - - if (surface->presentation_time.is_last_output_sequence_valid && - surface->presentation_time.last_output == output) - { - sequence_delta = - frame_info->sequence - surface->presentation_time.last_output_sequence; - } - else - { - /* Sequence generally has different base between different outputs, but we - * want to keep it monotonic and without sudden jumps when the surface is - * moved between outputs. This matches the Xorg behavior with regards to - * the GLX_OML_sync_control implementation. - */ - sequence_delta = 1; - } - - surface->presentation_time.sequence += sequence_delta; - surface->presentation_time.last_output = output; - surface->presentation_time.last_output_sequence = frame_info->sequence; - surface->presentation_time.is_last_output_sequence_valid = TRUE; - - return; - -invalid_sequence: - surface->presentation_time.sequence += 1; - surface->presentation_time.last_output = output; - surface->presentation_time.is_last_output_sequence_valid = FALSE; -} - -void -meta_wayland_presentation_feedback_present (MetaWaylandPresentationFeedback *feedback, - ClutterFrameInfo *frame_info, - MetaWaylandOutput *output) -{ - MetaWaylandSurface *surface = feedback->surface; - int64_t time_us = frame_info->presentation_time; - uint64_t time_s; - uint32_t tv_sec_hi, tv_sec_lo, tv_nsec; - uint32_t refresh_interval_ns; - uint32_t seq_hi, seq_lo; - uint32_t flags; - GList *l; - - if (output == NULL) - { - g_warning ("Output is NULL while sending presentation feedback"); - meta_wayland_presentation_feedback_discard (feedback); - return; - } - - time_s = us2s (time_us); - - tv_sec_hi = time_s >> 32; - tv_sec_lo = time_s; - tv_nsec = (uint32_t) us2ns (time_us - s2us (time_s)); - - refresh_interval_ns = (uint32_t) (0.5 + s2ns (1) / frame_info->refresh_rate); - - maybe_update_presentation_sequence (surface, frame_info, output); - - seq_hi = surface->presentation_time.sequence >> 32; - seq_lo = surface->presentation_time.sequence; - - flags = WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION; - - if (frame_info->flags & CLUTTER_FRAME_INFO_FLAG_HW_CLOCK) - flags |= WP_PRESENTATION_FEEDBACK_KIND_HW_CLOCK; - - if (frame_info->flags & CLUTTER_FRAME_INFO_FLAG_ZERO_COPY) - flags |= WP_PRESENTATION_FEEDBACK_KIND_ZERO_COPY; - - if (frame_info->flags & CLUTTER_FRAME_INFO_FLAG_VSYNC) - flags |= WP_PRESENTATION_FEEDBACK_KIND_VSYNC; - - for (l = output->resources; l; l = l->next) - { - struct wl_resource *output_resource = l->data; - - if (feedback->resource->client == output_resource->client) - { - wp_presentation_feedback_send_sync_output (feedback->resource, - output_resource); - } - } - - wp_presentation_feedback_send_presented (feedback->resource, - tv_sec_hi, - tv_sec_lo, - tv_nsec, - refresh_interval_ns, - seq_hi, - seq_lo, - flags); - - wl_resource_destroy (feedback->resource); -} - -struct wl_list * -meta_wayland_presentation_time_ensure_feedbacks (MetaWaylandPresentationTime *presentation_time, - ClutterStageView *stage_view) -{ - if (!g_hash_table_contains (presentation_time->feedbacks, stage_view)) - { - struct wl_list *list; - - list = g_new0 (struct wl_list, 1); - wl_list_init (list); - g_hash_table_insert (presentation_time->feedbacks, stage_view, list); - - return list; - } - - return g_hash_table_lookup (presentation_time->feedbacks, stage_view); -} - -void -meta_wayland_presentation_time_cursor_painted (MetaWaylandPresentationTime *presentation_time, - ClutterStageView *stage_view, - MetaWaylandCursorSurface *cursor_surface) -{ - struct wl_list *feedbacks; - MetaWaylandPresentationFeedback *feedback, *next; - MetaWaylandSurfaceRole *role = META_WAYLAND_SURFACE_ROLE (cursor_surface); - MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (role); - - feedbacks = - meta_wayland_presentation_time_ensure_feedbacks (presentation_time, - stage_view); - - /* Discard previous feedbacks for this cursor as now it has gone stale. */ - wl_list_for_each_safe (feedback, next, feedbacks, link) - { - if (feedback->surface->role == role) - meta_wayland_presentation_feedback_discard (feedback); - } - - /* Add new feedbacks. */ - if (!wl_list_empty (&surface->presentation_time.feedback_list)) - { - wl_list_insert_list (feedbacks, - &surface->presentation_time.feedback_list); - wl_list_init (&surface->presentation_time.feedback_list); - - surface->presentation_time.needs_sequence_update = TRUE; - } -} diff --git a/src/wayland/meta-wayland-private.h b/src/wayland/meta-wayland-private.h deleted file mode 100644 index 5272b530f..000000000 --- a/src/wayland/meta-wayland-private.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2012 Intel Corporation - * - * 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_WAYLAND_PRIVATE_H -#define META_WAYLAND_PRIVATE_H - -#include -#include - -#include "clutter/clutter.h" -#include "core/window-private.h" -#include "meta/meta-cursor-tracker.h" -#include "wayland/meta-wayland-pointer-gestures.h" -#include "wayland/meta-wayland-presentation-time-private.h" -#include "wayland/meta-wayland-seat.h" -#include "wayland/meta-wayland-surface.h" -#include "wayland/meta-wayland-tablet-manager.h" -#include "wayland/meta-wayland-versions.h" -#include "wayland/meta-wayland.h" - -typedef struct _MetaXWaylandDnd MetaXWaylandDnd; - -typedef struct -{ - struct wl_list link; - struct wl_resource *resource; - MetaWaylandSurface *surface; -} MetaWaylandFrameCallback; - -typedef struct -{ - int display_index; - char *lock_file; - int abstract_fd; - int unix_fd; - char *name; -} MetaXWaylandConnection; - -typedef struct -{ - MetaXWaylandConnection private_connection; - MetaXWaylandConnection public_connection; - - guint abstract_fd_watch_id; - guint unix_fd_watch_id; - - guint xserver_grace_period_id; - struct wl_display *wayland_display; - struct wl_client *client; - struct wl_resource *xserver_resource; - char *auth_file; - - GCancellable *xserver_died_cancellable; - GSubprocess *proc; - - GList *x11_windows; - - MetaXWaylandDnd *dnd; - - gboolean has_xrandr; - int rr_event_base; - int rr_error_base; -} MetaXWaylandManager; - -struct _MetaWaylandCompositor -{ - GObject parent; - - MetaContext *context; - - struct wl_display *wayland_display; - char *display_name; - GHashTable *outputs; - GList *frame_callback_surfaces; - - MetaXWaylandManager xwayland_manager; - - MetaWaylandSeat *seat; - MetaWaylandTabletManager *tablet_manager; - MetaWaylandActivation *activation; - - GHashTable *scheduled_surface_associations; - - MetaWaylandPresentationTime presentation_time; -}; - -#define META_TYPE_WAYLAND_COMPOSITOR (meta_wayland_compositor_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandCompositor, meta_wayland_compositor, - META, WAYLAND_COMPOSITOR, GObject) - -#endif /* META_WAYLAND_PRIVATE_H */ diff --git a/src/wayland/meta-wayland-region.c b/src/wayland/meta-wayland-region.c deleted file mode 100644 index ee4b6950f..000000000 --- a/src/wayland/meta-wayland-region.c +++ /dev/null @@ -1,105 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Endless Mobile - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -#include "config.h" - -#include "wayland/meta-wayland-region.h" - -struct _MetaWaylandRegion -{ - struct wl_resource *resource; - cairo_region_t *region; -}; - -static void -wl_region_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -wl_region_add (struct wl_client *client, - struct wl_resource *resource, - gint32 x, - gint32 y, - gint32 width, - gint32 height) -{ - MetaWaylandRegion *region = wl_resource_get_user_data (resource); - cairo_rectangle_int_t rectangle = { x, y, width, height }; - - cairo_region_union_rectangle (region->region, &rectangle); -} - -static void -wl_region_subtract (struct wl_client *client, - struct wl_resource *resource, - gint32 x, - gint32 y, - gint32 width, - gint32 height) -{ - MetaWaylandRegion *region = wl_resource_get_user_data (resource); - cairo_rectangle_int_t rectangle = { x, y, width, height }; - - cairo_region_subtract_rectangle (region->region, &rectangle); -} - -static const struct wl_region_interface meta_wayland_wl_region_interface = { - wl_region_destroy, - wl_region_add, - wl_region_subtract -}; - -static void -wl_region_destructor (struct wl_resource *resource) -{ - MetaWaylandRegion *region = wl_resource_get_user_data (resource); - - cairo_region_destroy (region->region); - g_free (region); -} - -MetaWaylandRegion * -meta_wayland_region_create (MetaWaylandCompositor *compositor, - struct wl_client *client, - struct wl_resource *compositor_resource, - guint32 id) -{ - MetaWaylandRegion *region = g_new0 (MetaWaylandRegion, 1); - - region->resource = wl_resource_create (client, &wl_region_interface, wl_resource_get_version (compositor_resource), id); - wl_resource_set_implementation (region->resource, &meta_wayland_wl_region_interface, region, wl_region_destructor); - - region->region = cairo_region_create (); - - return region; -} - -cairo_region_t * -meta_wayland_region_peek_cairo_region (MetaWaylandRegion *region) -{ - return region->region; -} diff --git a/src/wayland/meta-wayland-region.h b/src/wayland/meta-wayland-region.h deleted file mode 100644 index 201580a67..000000000 --- a/src/wayland/meta-wayland-region.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Endless Mobile - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -#ifndef META_WAYLAND_REGION_H -#define META_WAYLAND_REGION_H - -#include -#include -#include - -#include "wayland/meta-wayland-types.h" - -MetaWaylandRegion * meta_wayland_region_create (MetaWaylandCompositor *compositor, - struct wl_client *client, - struct wl_resource *compositor_resource, - guint32 id); - -cairo_region_t * meta_wayland_region_peek_cairo_region (MetaWaylandRegion *region); - -#endif /* META_WAYLAND_REGION_H */ diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c deleted file mode 100644 index abc0b4dda..000000000 --- a/src/wayland/meta-wayland-seat.c +++ /dev/null @@ -1,556 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2013 Intel Corporation - * - * 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 "wayland/meta-wayland-seat.h" - -#include "wayland/meta-wayland-data-device.h" -#include "wayland/meta-wayland-data-device-primary-legacy.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-tablet-seat.h" -#include "wayland/meta-wayland-versions.h" - -#define CAPABILITY_ENABLED(prev, cur, capability) ((cur & (capability)) && !(prev & (capability))) -#define CAPABILITY_DISABLED(prev, cur, capability) ((prev & (capability)) && !(cur & (capability))) - -static void -unbind_resource (struct wl_resource *resource) -{ - wl_list_remove (wl_resource_get_link (resource)); -} - -static void -seat_get_pointer (struct wl_client *client, - struct wl_resource *resource, - uint32_t id) -{ - MetaWaylandSeat *seat = wl_resource_get_user_data (resource); - MetaWaylandPointer *pointer = seat->pointer; - - if (meta_wayland_seat_has_pointer (seat)) - meta_wayland_pointer_create_new_resource (pointer, client, resource, id); -} - -static void -seat_get_keyboard (struct wl_client *client, - struct wl_resource *resource, - uint32_t id) -{ - MetaWaylandSeat *seat = wl_resource_get_user_data (resource); - MetaWaylandKeyboard *keyboard = seat->keyboard; - - if (meta_wayland_seat_has_keyboard (seat)) - meta_wayland_keyboard_create_new_resource (keyboard, client, resource, id); -} - -static void -seat_get_touch (struct wl_client *client, - struct wl_resource *resource, - uint32_t id) -{ - MetaWaylandSeat *seat = wl_resource_get_user_data (resource); - MetaWaylandTouch *touch = seat->touch; - - if (meta_wayland_seat_has_touch (seat)) - meta_wayland_touch_create_new_resource (touch, client, resource, id); -} - -static void -seat_release (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static const struct wl_seat_interface seat_interface = { - seat_get_pointer, - seat_get_keyboard, - seat_get_touch, - seat_release -}; - -static void -bind_seat (struct wl_client *client, - void *data, - guint32 version, - guint32 id) -{ - MetaWaylandSeat *seat = data; - struct wl_resource *resource; - - resource = wl_resource_create (client, &wl_seat_interface, version, id); - wl_resource_set_implementation (resource, &seat_interface, seat, unbind_resource); - wl_list_insert (&seat->base_resource_list, wl_resource_get_link (resource)); - - wl_seat_send_capabilities (resource, seat->capabilities); - - if (version >= WL_SEAT_NAME_SINCE_VERSION) - wl_seat_send_name (resource, "seat0"); -} - -static uint32_t -lookup_device_capabilities (ClutterSeat *seat) -{ - GList *devices, *l; - uint32_t capabilities = 0; - - devices = clutter_seat_list_devices (seat); - - for (l = devices; l; l = l->next) - { - ClutterInputDeviceType device_type; - - /* Only look for physical devices, logical devices have rather generic - * keyboard/pointer device types, which is not truly representative of - * the physical devices connected to them. - */ - if (clutter_input_device_get_device_mode (l->data) == CLUTTER_INPUT_MODE_LOGICAL) - continue; - - device_type = clutter_input_device_get_device_type (l->data); - - switch (device_type) - { - case CLUTTER_TOUCHPAD_DEVICE: - case CLUTTER_POINTER_DEVICE: - capabilities |= WL_SEAT_CAPABILITY_POINTER; - break; - case CLUTTER_KEYBOARD_DEVICE: - capabilities |= WL_SEAT_CAPABILITY_KEYBOARD; - break; - case CLUTTER_TOUCHSCREEN_DEVICE: - capabilities |= WL_SEAT_CAPABILITY_TOUCH; - break; - default: - g_debug ("Ignoring device '%s' with unhandled type %d", - clutter_input_device_get_device_name (l->data), - device_type); - break; - } - } - - g_list_free (devices); - - return capabilities; -} - -static void -meta_wayland_seat_set_capabilities (MetaWaylandSeat *seat, - uint32_t flags) -{ - struct wl_resource *resource; - uint32_t prev_flags; - - prev_flags = seat->capabilities; - - if (prev_flags == flags) - return; - - seat->capabilities = flags; - - if (CAPABILITY_ENABLED (prev_flags, flags, WL_SEAT_CAPABILITY_POINTER)) - meta_wayland_pointer_enable (seat->pointer); - else if (CAPABILITY_DISABLED (prev_flags, flags, WL_SEAT_CAPABILITY_POINTER)) - meta_wayland_pointer_disable (seat->pointer); - - if (CAPABILITY_ENABLED (prev_flags, flags, WL_SEAT_CAPABILITY_KEYBOARD)) - { - MetaDisplay *display; - - meta_wayland_keyboard_enable (seat->keyboard); - display = meta_get_display (); - - /* Post-initialization, ensure the input focus is in sync */ - if (display) - meta_display_sync_wayland_input_focus (display); - } - else if (CAPABILITY_DISABLED (prev_flags, flags, WL_SEAT_CAPABILITY_KEYBOARD)) - meta_wayland_keyboard_disable (seat->keyboard); - - if (CAPABILITY_ENABLED (prev_flags, flags, WL_SEAT_CAPABILITY_TOUCH)) - meta_wayland_touch_enable (seat->touch); - else if (CAPABILITY_DISABLED (prev_flags, flags, WL_SEAT_CAPABILITY_TOUCH)) - meta_wayland_touch_disable (seat->touch); - - /* Broadcast capability changes */ - wl_resource_for_each (resource, &seat->base_resource_list) - { - wl_seat_send_capabilities (resource, flags); - } -} - -static void -meta_wayland_seat_update_capabilities (MetaWaylandSeat *seat, - ClutterSeat *clutter_seat) -{ - uint32_t capabilities; - - capabilities = lookup_device_capabilities (clutter_seat); - meta_wayland_seat_set_capabilities (seat, capabilities); -} - -static void -meta_wayland_seat_devices_updated (ClutterSeat *clutter_seat, - ClutterInputDevice *input_device, - MetaWaylandSeat *seat) -{ - meta_wayland_seat_update_capabilities (seat, clutter_seat); -} - -static MetaWaylandSeat * -meta_wayland_seat_new (MetaWaylandCompositor *compositor, - struct wl_display *display) -{ - MetaWaylandSeat *seat = g_new0 (MetaWaylandSeat, 1); - ClutterSeat *clutter_seat; - - wl_list_init (&seat->base_resource_list); - seat->wl_display = display; - - seat->pointer = g_object_new (META_TYPE_WAYLAND_POINTER, - "seat", seat, - NULL); - seat->keyboard = g_object_new (META_TYPE_WAYLAND_KEYBOARD, - "seat", seat, - NULL); - seat->touch = g_object_new (META_TYPE_WAYLAND_TOUCH, - "seat", seat, - NULL); - - seat->text_input = meta_wayland_text_input_new (seat); - seat->gtk_text_input = meta_wayland_gtk_text_input_new (seat); - - meta_wayland_data_device_init (&seat->data_device); - meta_wayland_data_device_primary_init (&seat->primary_data_device); - meta_wayland_data_device_primary_legacy_init (&seat->primary_legacy_data_device); - - clutter_seat = clutter_backend_get_default_seat (clutter_get_default_backend ()); - meta_wayland_seat_update_capabilities (seat, clutter_seat); - g_signal_connect (clutter_seat, "device-added", - G_CALLBACK (meta_wayland_seat_devices_updated), seat); - g_signal_connect (clutter_seat, "device-removed", - G_CALLBACK (meta_wayland_seat_devices_updated), seat); - - wl_global_create (display, &wl_seat_interface, META_WL_SEAT_VERSION, seat, bind_seat); - - meta_wayland_tablet_manager_ensure_seat (compositor->tablet_manager, seat); - - return seat; -} - -void -meta_wayland_seat_init (MetaWaylandCompositor *compositor) -{ - compositor->seat = meta_wayland_seat_new (compositor, - compositor->wayland_display); -} - -void -meta_wayland_seat_free (MetaWaylandSeat *seat) -{ - ClutterSeat *clutter_seat; - - clutter_seat = clutter_backend_get_default_seat (clutter_get_default_backend ()); - g_signal_handlers_disconnect_by_data (clutter_seat, seat); - meta_wayland_seat_set_capabilities (seat, 0); - - meta_wayland_pointer_disable (seat->pointer); - g_object_unref (seat->pointer); - meta_wayland_keyboard_disable (seat->keyboard); - g_object_unref (seat->keyboard); - meta_wayland_touch_disable (seat->touch); - g_object_unref (seat->touch); - - meta_wayland_gtk_text_input_destroy (seat->gtk_text_input); - meta_wayland_text_input_destroy (seat->text_input); - - g_free (seat); -} - -static gboolean -event_is_synthesized_crossing (const ClutterEvent *event) -{ - ClutterInputDevice *device; - - if (event->type != CLUTTER_ENTER && event->type != CLUTTER_LEAVE) - return FALSE; - - device = clutter_event_get_source_device (event); - return clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_LOGICAL; -} - -static gboolean -event_from_supported_hardware_device (MetaWaylandSeat *seat, - const ClutterEvent *event) -{ - ClutterInputDevice *input_device; - ClutterInputMode input_mode; - ClutterInputDeviceType device_type; - gboolean hardware_device = FALSE; - gboolean supported_device = FALSE; - - input_device = clutter_event_get_source_device (event); - - if (input_device == NULL) - goto out; - - input_mode = clutter_input_device_get_device_mode (input_device); - - if (input_mode != CLUTTER_INPUT_MODE_PHYSICAL) - goto out; - - hardware_device = TRUE; - - device_type = clutter_input_device_get_device_type (input_device); - - switch (device_type) - { - case CLUTTER_TOUCHPAD_DEVICE: - case CLUTTER_POINTER_DEVICE: - case CLUTTER_KEYBOARD_DEVICE: - case CLUTTER_TOUCHSCREEN_DEVICE: - supported_device = TRUE; - break; - - default: - supported_device = FALSE; - break; - } - -out: - return hardware_device && supported_device; -} - -void -meta_wayland_seat_update (MetaWaylandSeat *seat, - const ClutterEvent *event) -{ - if (!(clutter_event_get_flags (event) & CLUTTER_EVENT_FLAG_INPUT_METHOD) && - !event_from_supported_hardware_device (seat, event) && - !event_is_synthesized_crossing (event)) - return; - - switch (event->type) - { - case CLUTTER_MOTION: - case CLUTTER_BUTTON_PRESS: - case CLUTTER_BUTTON_RELEASE: - case CLUTTER_SCROLL: - case CLUTTER_ENTER: - case CLUTTER_LEAVE: - if (meta_wayland_seat_has_pointer (seat)) - meta_wayland_pointer_update (seat->pointer, event); - break; - - case CLUTTER_KEY_PRESS: - case CLUTTER_KEY_RELEASE: - if (meta_wayland_seat_has_keyboard (seat)) - meta_wayland_keyboard_update (seat->keyboard, (const ClutterKeyEvent *) event); - break; - - case CLUTTER_TOUCH_BEGIN: - case CLUTTER_TOUCH_UPDATE: - case CLUTTER_TOUCH_END: - if (meta_wayland_seat_has_touch (seat)) - meta_wayland_touch_update (seat->touch, event); - break; - - default: - break; - } -} - -gboolean -meta_wayland_seat_handle_event (MetaWaylandSeat *seat, - const ClutterEvent *event) -{ - if (!(clutter_event_get_flags (event) & CLUTTER_EVENT_FLAG_INPUT_METHOD) && - !event_from_supported_hardware_device (seat, event)) - return FALSE; - - switch (event->type) - { - case CLUTTER_MOTION: - case CLUTTER_BUTTON_PRESS: - case CLUTTER_BUTTON_RELEASE: - case CLUTTER_SCROLL: - case CLUTTER_TOUCHPAD_SWIPE: - case CLUTTER_TOUCHPAD_PINCH: - if (meta_wayland_seat_has_pointer (seat)) - return meta_wayland_pointer_handle_event (seat->pointer, event); - - break; - case CLUTTER_KEY_PRESS: - case CLUTTER_KEY_RELEASE: - if (meta_wayland_text_input_handle_event (seat->text_input, event)) - return TRUE; - - if (meta_wayland_gtk_text_input_handle_event (seat->gtk_text_input, - event)) - return TRUE; - - if (meta_wayland_seat_has_keyboard (seat)) - return meta_wayland_keyboard_handle_event (seat->keyboard, - (const ClutterKeyEvent *) event); - break; - case CLUTTER_TOUCH_BEGIN: - case CLUTTER_TOUCH_UPDATE: - case CLUTTER_TOUCH_END: - if (meta_wayland_seat_has_touch (seat)) - return meta_wayland_touch_handle_event (seat->touch, event); - - break; - case CLUTTER_IM_COMMIT: - case CLUTTER_IM_DELETE: - case CLUTTER_IM_PREEDIT: - if (meta_wayland_text_input_handle_event (seat->text_input, event)) - return TRUE; - if (meta_wayland_gtk_text_input_handle_event (seat->gtk_text_input, - event)) - return TRUE; - - break; - default: - break; - } - - return FALSE; -} - -void -meta_wayland_seat_set_input_focus (MetaWaylandSeat *seat, - MetaWaylandSurface *surface) -{ - MetaWaylandTabletSeat *tablet_seat; - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - - if (meta_wayland_seat_has_keyboard (seat)) - { - meta_wayland_keyboard_set_focus (seat->keyboard, surface); - meta_wayland_data_device_set_keyboard_focus (&seat->data_device); - meta_wayland_data_device_primary_set_keyboard_focus (&seat->primary_data_device); - meta_wayland_data_device_primary_legacy_set_keyboard_focus (&seat->primary_legacy_data_device); - } - - tablet_seat = meta_wayland_tablet_manager_ensure_seat (compositor->tablet_manager, seat); - meta_wayland_tablet_seat_set_pad_focus (tablet_seat, surface); - - meta_wayland_text_input_set_focus (seat->text_input, surface); - meta_wayland_gtk_text_input_set_focus (seat->gtk_text_input, surface); -} - -gboolean -meta_wayland_seat_get_grab_info (MetaWaylandSeat *seat, - MetaWaylandSurface *surface, - uint32_t serial, - gboolean require_pressed, - gfloat *x, - gfloat *y) -{ - MetaWaylandCompositor *compositor; - MetaWaylandTabletSeat *tablet_seat; - GList *tools, *l; - - compositor = meta_wayland_compositor_get_default (); - tablet_seat = meta_wayland_tablet_manager_ensure_seat (compositor->tablet_manager, seat); - tools = g_hash_table_get_values (tablet_seat->tools); - - if (meta_wayland_seat_has_touch (seat)) - { - ClutterEventSequence *sequence; - sequence = meta_wayland_touch_find_grab_sequence (seat->touch, - surface, - serial); - if (sequence) - { - meta_wayland_touch_get_press_coords (seat->touch, sequence, x, y); - return TRUE; - } - } - - if (meta_wayland_seat_has_pointer (seat)) - { - if ((!require_pressed || seat->pointer->button_count > 0) && - meta_wayland_pointer_can_grab_surface (seat->pointer, surface, serial)) - { - if (x) - *x = seat->pointer->grab_x; - if (y) - *y = seat->pointer->grab_y; - - return TRUE; - } - } - - for (l = tools; l; l = l->next) - { - MetaWaylandTabletTool *tool = l->data; - - if ((!require_pressed || tool->button_count > 0) && - meta_wayland_tablet_tool_can_grab_surface (tool, surface, serial)) - { - if (x) - *x = tool->grab_x; - if (y) - *y = tool->grab_y; - - return TRUE; - } - } - - return FALSE; -} - -gboolean -meta_wayland_seat_can_popup (MetaWaylandSeat *seat, - uint32_t serial) -{ - MetaWaylandCompositor *compositor; - MetaWaylandTabletSeat *tablet_seat; - - compositor = meta_wayland_compositor_get_default (); - tablet_seat = - meta_wayland_tablet_manager_ensure_seat (compositor->tablet_manager, seat); - - return (meta_wayland_pointer_can_popup (seat->pointer, serial) || - meta_wayland_keyboard_can_popup (seat->keyboard, serial) || - meta_wayland_touch_can_popup (seat->touch, serial) || - meta_wayland_tablet_seat_can_popup (tablet_seat, serial)); -} - -gboolean -meta_wayland_seat_has_keyboard (MetaWaylandSeat *seat) -{ - return (seat->capabilities & WL_SEAT_CAPABILITY_KEYBOARD) != 0; -} - -gboolean -meta_wayland_seat_has_pointer (MetaWaylandSeat *seat) -{ - return (seat->capabilities & WL_SEAT_CAPABILITY_POINTER) != 0; -} - -gboolean -meta_wayland_seat_has_touch (MetaWaylandSeat *seat) -{ - return (seat->capabilities & WL_SEAT_CAPABILITY_TOUCH) != 0; -} diff --git a/src/wayland/meta-wayland-seat.h b/src/wayland/meta-wayland-seat.h deleted file mode 100644 index ae4e1076b..000000000 --- a/src/wayland/meta-wayland-seat.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2012 Intel Corporation - * - * 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_WAYLAND_SEAT_H -#define META_WAYLAND_SEAT_H - -#include - -#include "clutter/clutter.h" -#include "wayland/meta-wayland-data-device.h" -#include "wayland/meta-wayland-data-device-primary.h" -#include "wayland/meta-wayland-data-device-primary-legacy.h" -#include "wayland/meta-wayland-input-device.h" -#include "wayland/meta-wayland-keyboard.h" -#include "wayland/meta-wayland-pointer.h" -#include "wayland/meta-wayland-tablet-tool.h" -#include "wayland/meta-wayland-text-input.h" -#include "wayland/meta-wayland-text-input-legacy.h" -#include "wayland/meta-wayland-touch.h" -#include "wayland/meta-wayland-types.h" - -struct _MetaWaylandSeat -{ - struct wl_list base_resource_list; - struct wl_display *wl_display; - - MetaWaylandPointer *pointer; - MetaWaylandKeyboard *keyboard; - MetaWaylandTouch *touch; - - MetaWaylandDataDevice data_device; - MetaWaylandDataDevicePrimary primary_data_device; - MetaWaylandDataDevicePrimaryLegacy primary_legacy_data_device; - - MetaWaylandGtkTextInput *gtk_text_input; - MetaWaylandTextInput *text_input; - - guint capabilities; -}; - -void meta_wayland_seat_init (MetaWaylandCompositor *compositor); - -void meta_wayland_seat_free (MetaWaylandSeat *seat); - -void meta_wayland_seat_update (MetaWaylandSeat *seat, - const ClutterEvent *event); - -gboolean meta_wayland_seat_handle_event (MetaWaylandSeat *seat, - const ClutterEvent *event); - -void meta_wayland_seat_set_input_focus (MetaWaylandSeat *seat, - MetaWaylandSurface *surface); - -gboolean meta_wayland_seat_get_grab_info (MetaWaylandSeat *seat, - MetaWaylandSurface *surface, - uint32_t serial, - gboolean require_pressed, - gfloat *x, - gfloat *y); -gboolean meta_wayland_seat_can_popup (MetaWaylandSeat *seat, - uint32_t serial); - -gboolean meta_wayland_seat_has_keyboard (MetaWaylandSeat *seat); - -gboolean meta_wayland_seat_has_pointer (MetaWaylandSeat *seat); - -gboolean meta_wayland_seat_has_touch (MetaWaylandSeat *seat); - -#endif /* META_WAYLAND_SEAT_H */ diff --git a/src/wayland/meta-wayland-shell-surface.c b/src/wayland/meta-wayland-shell-surface.c deleted file mode 100644 index 5e052e000..000000000 --- a/src/wayland/meta-wayland-shell-surface.c +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Copyright (C) 2012,2013 Intel Corporation - * Copyright (C) 2013-2017 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "wayland/meta-wayland-shell-surface.h" - -#include "compositor/meta-surface-actor-wayland.h" -#include "compositor/meta-window-actor-private.h" -#include "compositor/meta-window-actor-wayland.h" -#include "wayland/meta-wayland-actor-surface.h" -#include "wayland/meta-wayland-buffer.h" -#include "wayland/meta-wayland-subsurface.h" -#include "wayland/meta-wayland-surface.h" -#include "wayland/meta-window-wayland.h" - -typedef struct _MetaWaylandShellSurfacePrivate -{ - MetaWindow *window; - - gulong unmanaging_handler_id; -} MetaWaylandShellSurfacePrivate; - -G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaWaylandShellSurface, - meta_wayland_shell_surface, - META_TYPE_WAYLAND_ACTOR_SURFACE) - -void -meta_wayland_shell_surface_calculate_geometry (MetaWaylandShellSurface *shell_surface, - MetaRectangle *out_geometry) -{ - MetaWaylandSurfaceRole *surface_role = - META_WAYLAND_SURFACE_ROLE (shell_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaRectangle geometry; - MetaWaylandSurface *subsurface_surface; - - geometry = (MetaRectangle) { - .width = meta_wayland_surface_get_width (surface), - .height = meta_wayland_surface_get_height (surface), - }; - - META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface) - { - MetaWaylandSubsurface *subsurface; - - subsurface = META_WAYLAND_SUBSURFACE (subsurface_surface->role); - meta_wayland_subsurface_union_geometry (subsurface, - 0, 0, - &geometry); - } - - *out_geometry = geometry; -} - -void -meta_wayland_shell_surface_determine_geometry (MetaWaylandShellSurface *shell_surface, - MetaRectangle *set_geometry, - MetaRectangle *out_geometry) -{ - MetaRectangle bounding_geometry = { 0 }; - MetaRectangle intersected_geometry = { 0 }; - - meta_wayland_shell_surface_calculate_geometry (shell_surface, - &bounding_geometry); - - meta_rectangle_intersect (set_geometry, &bounding_geometry, - &intersected_geometry); - - *out_geometry = intersected_geometry; -} - -static void -clear_window (MetaWaylandShellSurface *shell_surface) -{ - MetaWaylandShellSurfacePrivate *priv = - meta_wayland_shell_surface_get_instance_private (shell_surface); - MetaWaylandSurfaceRole *surface_role = - META_WAYLAND_SURFACE_ROLE (shell_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaSurfaceActor *surface_actor; - - if (!priv->window) - return; - - g_clear_signal_handler (&priv->unmanaging_handler_id, - priv->window); - priv->window = NULL; - - surface_actor = meta_wayland_surface_get_actor (surface); - if (surface_actor) - clutter_actor_set_reactive (CLUTTER_ACTOR (surface_actor), FALSE); - - meta_wayland_surface_notify_unmapped (surface); -} - -static void -window_unmanaging (MetaWindow *window, - MetaWaylandShellSurface *shell_surface) -{ - clear_window (shell_surface); -} - -void -meta_wayland_shell_surface_set_window (MetaWaylandShellSurface *shell_surface, - MetaWindow *window) -{ - MetaWaylandShellSurfacePrivate *priv = - meta_wayland_shell_surface_get_instance_private (shell_surface); - MetaWaylandSurfaceRole *surface_role = - META_WAYLAND_SURFACE_ROLE (shell_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaSurfaceActor *surface_actor; - - g_assert (!priv->window); - - priv->window = window; - - surface_actor = meta_wayland_surface_get_actor (surface); - if (surface_actor) - clutter_actor_set_reactive (CLUTTER_ACTOR (surface_actor), TRUE); - - priv->unmanaging_handler_id = - g_signal_connect (window, - "unmanaging", - G_CALLBACK (window_unmanaging), - shell_surface); - - meta_window_update_monitor (window, META_WINDOW_UPDATE_MONITOR_FLAGS_NONE); -} - -void -meta_wayland_shell_surface_configure (MetaWaylandShellSurface *shell_surface, - MetaWaylandWindowConfiguration *configuration) -{ - MetaWaylandShellSurfaceClass *shell_surface_class = - META_WAYLAND_SHELL_SURFACE_GET_CLASS (shell_surface); - - shell_surface_class->configure (shell_surface, configuration); -} - -void -meta_wayland_shell_surface_ping (MetaWaylandShellSurface *shell_surface, - uint32_t serial) -{ - MetaWaylandShellSurfaceClass *shell_surface_class = - META_WAYLAND_SHELL_SURFACE_GET_CLASS (shell_surface); - - shell_surface_class->ping (shell_surface, serial); -} - -void -meta_wayland_shell_surface_close (MetaWaylandShellSurface *shell_surface) -{ - MetaWaylandShellSurfaceClass *shell_surface_class = - META_WAYLAND_SHELL_SURFACE_GET_CLASS (shell_surface); - - shell_surface_class->close (shell_surface); -} - -void -meta_wayland_shell_surface_managed (MetaWaylandShellSurface *shell_surface, - MetaWindow *window) -{ - MetaWaylandShellSurfaceClass *shell_surface_class = - META_WAYLAND_SHELL_SURFACE_GET_CLASS (shell_surface); - - shell_surface_class->managed (shell_surface, window); -} - -static void -meta_wayland_shell_surface_assigned (MetaWaylandSurfaceRole *surface_role) -{ - MetaWaylandSurfaceRoleClass *surface_role_class = - META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_shell_surface_parent_class); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - - surface->dnd.funcs = meta_wayland_data_device_get_drag_dest_funcs (); - - surface_role_class->assigned (surface_role); -} - -static void -meta_wayland_shell_surface_surface_pre_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending) -{ - MetaWaylandShellSurface *shell_surface = - META_WAYLAND_SHELL_SURFACE (surface_role); - MetaWaylandShellSurfacePrivate *priv = - meta_wayland_shell_surface_get_instance_private (shell_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - - if (pending->newly_attached && - !surface->buffer_ref->buffer && - priv->window) - meta_window_queue (priv->window, META_QUEUE_CALC_SHOWING); -} - -static void -meta_wayland_shell_surface_surface_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending) -{ - MetaWaylandShellSurface *shell_surface = - META_WAYLAND_SHELL_SURFACE (surface_role); - MetaWaylandShellSurfacePrivate *priv = - meta_wayland_shell_surface_get_instance_private (shell_surface); - MetaWaylandActorSurface *actor_surface = - META_WAYLAND_ACTOR_SURFACE (surface_role); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWaylandSurfaceRoleClass *surface_role_class; - MetaWindow *window; - MetaWaylandBuffer *buffer; - double geometry_scale; - - surface_role_class = - META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_shell_surface_parent_class); - surface_role_class->apply_state (surface_role, pending); - - buffer = surface->buffer_ref->buffer; - if (!buffer) - return; - - window = priv->window; - if (!window) - return; - - geometry_scale = meta_wayland_actor_surface_get_geometry_scale (actor_surface); - - window->buffer_rect.width = - meta_wayland_surface_get_width (surface) * geometry_scale; - window->buffer_rect.height = - meta_wayland_surface_get_height (surface) * geometry_scale; -} - -static MetaWindow * -meta_wayland_shell_surface_get_window (MetaWaylandSurfaceRole *surface_role) -{ - MetaWaylandShellSurface *shell_surface = - META_WAYLAND_SHELL_SURFACE (surface_role); - MetaWaylandShellSurfacePrivate *priv = - meta_wayland_shell_surface_get_instance_private (shell_surface); - - return priv->window; -} - -static void -meta_wayland_shell_surface_notify_subsurface_state_changed (MetaWaylandSurfaceRole *surface_role) -{ - MetaWaylandShellSurface *shell_surface = - META_WAYLAND_SHELL_SURFACE (surface_role); - MetaWaylandShellSurfacePrivate *priv = - meta_wayland_shell_surface_get_instance_private (shell_surface); - MetaWindow *window; - MetaWindowActor *window_actor; - - window = priv->window; - if (!window) - return; - - window_actor = meta_window_actor_from_window (window); - meta_window_actor_wayland_rebuild_surface_tree (window_actor); -} - -static double -meta_wayland_shell_surface_get_geometry_scale (MetaWaylandActorSurface *actor_surface) -{ - MetaWaylandSurfaceRole *surface_role = - META_WAYLAND_SURFACE_ROLE (actor_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWindow *toplevel_window; - - toplevel_window = meta_wayland_surface_get_toplevel_window (surface); - if (meta_is_stage_views_scaled () || !toplevel_window) - return 1; - else - return meta_window_wayland_get_geometry_scale (toplevel_window); -} - -static void -meta_wayland_shell_surface_sync_actor_state (MetaWaylandActorSurface *actor_surface) -{ - MetaWaylandSurfaceRole *surface_role = - META_WAYLAND_SURFACE_ROLE (actor_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWaylandActorSurfaceClass *actor_surface_class = - META_WAYLAND_ACTOR_SURFACE_CLASS (meta_wayland_shell_surface_parent_class); - MetaWindow *toplevel_window; - - toplevel_window = meta_wayland_surface_get_toplevel_window (surface); - if (!toplevel_window) - return; - - actor_surface_class->sync_actor_state (actor_surface); -} - -void -meta_wayland_shell_surface_destroy_window (MetaWaylandShellSurface *shell_surface) -{ - MetaWaylandShellSurfacePrivate *priv = - meta_wayland_shell_surface_get_instance_private (shell_surface); - MetaWindow *window; - MetaDisplay *display; - uint32_t timestamp; - - window = priv->window; - if (!window) - return; - - display = meta_window_get_display (window); - timestamp = meta_display_get_current_time_roundtrip (display); - meta_window_unmanage (window, timestamp); - g_assert (!priv->window); -} - -static void -meta_wayland_shell_surface_finalize (GObject *object) -{ - MetaWaylandShellSurface *shell_surface = META_WAYLAND_SHELL_SURFACE (object); - - meta_wayland_shell_surface_destroy_window (shell_surface); - - G_OBJECT_CLASS (meta_wayland_shell_surface_parent_class)->finalize (object); -} - -static void -meta_wayland_shell_surface_init (MetaWaylandShellSurface *role) -{ -} - -static void -meta_wayland_shell_surface_class_init (MetaWaylandShellSurfaceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaWaylandSurfaceRoleClass *surface_role_class = - META_WAYLAND_SURFACE_ROLE_CLASS (klass); - MetaWaylandActorSurfaceClass *actor_surface_class = - META_WAYLAND_ACTOR_SURFACE_CLASS (klass); - - object_class->finalize = meta_wayland_shell_surface_finalize; - - surface_role_class->assigned = meta_wayland_shell_surface_assigned; - surface_role_class->pre_apply_state = - meta_wayland_shell_surface_surface_pre_apply_state; - surface_role_class->apply_state = - meta_wayland_shell_surface_surface_apply_state; - surface_role_class->notify_subsurface_state_changed = - meta_wayland_shell_surface_notify_subsurface_state_changed; - surface_role_class->get_window = meta_wayland_shell_surface_get_window; - - actor_surface_class->get_geometry_scale = - meta_wayland_shell_surface_get_geometry_scale; - actor_surface_class->sync_actor_state = - meta_wayland_shell_surface_sync_actor_state; -} diff --git a/src/wayland/meta-wayland-shell-surface.h b/src/wayland/meta-wayland-shell-surface.h deleted file mode 100644 index d1bbeef65..000000000 --- a/src/wayland/meta-wayland-shell-surface.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2012,2013 Intel Corporation - * Copyright (C) 2013-2017 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_WAYLAND_SHELL_SURFACE_H -#define META_WAYLAND_SHELL_SURFACE_H - -#include "wayland/meta-wayland-actor-surface.h" - -#define META_TYPE_WAYLAND_SHELL_SURFACE (meta_wayland_shell_surface_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaWaylandShellSurface, - meta_wayland_shell_surface, - META, WAYLAND_SHELL_SURFACE, - MetaWaylandActorSurface) - -struct _MetaWaylandShellSurfaceClass -{ - MetaWaylandActorSurfaceClass parent_class; - - void (*configure) (MetaWaylandShellSurface *shell_surface, - MetaWaylandWindowConfiguration *configuration); - void (*managed) (MetaWaylandShellSurface *shell_surface, - MetaWindow *window); - void (*ping) (MetaWaylandShellSurface *shell_surface, - uint32_t serial); - void (*close) (MetaWaylandShellSurface *shell_surface); -}; - -void meta_wayland_shell_surface_configure (MetaWaylandShellSurface *shell_surface, - MetaWaylandWindowConfiguration *configuration); - -void meta_wayland_shell_surface_ping (MetaWaylandShellSurface *shell_surface, - uint32_t serial); - -void meta_wayland_shell_surface_close (MetaWaylandShellSurface *shell_surface); - -void meta_wayland_shell_surface_managed (MetaWaylandShellSurface *shell_surface, - MetaWindow *window); - -void meta_wayland_shell_surface_calculate_geometry (MetaWaylandShellSurface *shell_surface, - MetaRectangle *out_geometry); - -void meta_wayland_shell_surface_determine_geometry (MetaWaylandShellSurface *shell_surface, - MetaRectangle *set_geometry, - MetaRectangle *out_geometry); - -void meta_wayland_shell_surface_set_window (MetaWaylandShellSurface *shell_surface, - MetaWindow *window); - -void meta_wayland_shell_surface_destroy_window (MetaWaylandShellSurface *shell_surface); - -#endif /* META_WAYLAND_SHELL_SURFACE_H */ diff --git a/src/wayland/meta-wayland-subsurface.c b/src/wayland/meta-wayland-subsurface.c deleted file mode 100644 index d7f56b66e..000000000 --- a/src/wayland/meta-wayland-subsurface.c +++ /dev/null @@ -1,612 +0,0 @@ -/* - * Copyright (C) 2012,2013 Intel Corporation - * Copyright (C) 2013-2017 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include "config.h" - -#include "wayland/meta-wayland-subsurface.h" - -#include "compositor/meta-surface-actor-wayland.h" -#include "compositor/meta-window-actor-wayland.h" -#include "wayland/meta-wayland.h" -#include "wayland/meta-wayland-actor-surface.h" -#include "wayland/meta-wayland-buffer.h" -#include "wayland/meta-wayland-surface.h" -#include "wayland/meta-window-wayland.h" - -struct _MetaWaylandSubsurface -{ - MetaWaylandActorSurface parent; -}; - -G_DEFINE_TYPE (MetaWaylandSubsurface, - meta_wayland_subsurface, - META_TYPE_WAYLAND_ACTOR_SURFACE) - -static void -transform_subsurface_position (MetaWaylandSurface *surface, - int *x, - int *y) -{ - do - { - *x += surface->sub.x; - *y += surface->sub.y; - - surface = surface->sub.parent; - } - while (surface); -} - -static gboolean -should_show (MetaWaylandSurface *surface) -{ - if (!surface->buffer_ref->buffer) - return FALSE; - else if (surface->sub.parent) - return should_show (surface->sub.parent); - else - return TRUE; -} - -static void -sync_actor_subsurface_state (MetaWaylandSurface *surface) -{ - ClutterActor *actor = CLUTTER_ACTOR (meta_wayland_surface_get_actor (surface)); - MetaWindow *toplevel_window; - int x, y; - - toplevel_window = meta_wayland_surface_get_toplevel_window (surface); - if (!toplevel_window) - return; - - if (toplevel_window->client_type == META_WINDOW_CLIENT_TYPE_X11) - return; - - x = y = 0; - transform_subsurface_position (surface, &x, &y); - - clutter_actor_set_position (actor, x, y); - clutter_actor_set_reactive (actor, TRUE); - - if (should_show (surface)) - clutter_actor_show (actor); - else - clutter_actor_hide (actor); -} - -static gboolean -is_child (MetaWaylandSurface *surface, - MetaWaylandSurface *sibling) -{ - if (surface->sub.parent == sibling) - return TRUE; - else - return FALSE; -} - -static gboolean -is_sibling (MetaWaylandSurface *surface, - MetaWaylandSurface *sibling) -{ - if (surface->sub.parent == sibling->sub.parent) - return TRUE; - else - return FALSE; -} - -static gboolean -is_surface_effectively_synchronized (MetaWaylandSurface *surface) -{ - return meta_wayland_surface_should_cache_state (surface); -} - -void -meta_wayland_subsurface_parent_state_applied (MetaWaylandSubsurface *subsurface) -{ - MetaWaylandSurfaceRole *surface_role = META_WAYLAND_SURFACE_ROLE (subsurface); - MetaWaylandActorSurface *actor_surface = - META_WAYLAND_ACTOR_SURFACE (subsurface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - - if (surface->sub.pending_pos) - { - surface->sub.x = surface->sub.pending_x; - surface->sub.y = surface->sub.pending_y; - surface->sub.pending_pos = FALSE; - } - - if (is_surface_effectively_synchronized (surface)) - meta_wayland_surface_apply_cached_state (surface); - - meta_wayland_actor_surface_sync_actor_state (actor_surface); -} - -void -meta_wayland_subsurface_union_geometry (MetaWaylandSubsurface *subsurface, - int parent_x, - int parent_y, - MetaRectangle *out_geometry) -{ - MetaWaylandSurfaceRole *surface_role = META_WAYLAND_SURFACE_ROLE (subsurface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaRectangle geometry; - MetaWaylandSurface *subsurface_surface; - - geometry = (MetaRectangle) { - .x = surface->offset_x + surface->sub.x, - .y = surface->offset_y + surface->sub.y, - .width = meta_wayland_surface_get_width (surface), - .height = meta_wayland_surface_get_height (surface), - }; - - if (surface->buffer_ref->buffer) - meta_rectangle_union (out_geometry, &geometry, out_geometry); - - META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface) - { - MetaWaylandSubsurface *subsurface; - - subsurface = META_WAYLAND_SUBSURFACE (subsurface_surface->role); - meta_wayland_subsurface_union_geometry (subsurface, - parent_x + geometry.x, - parent_y + geometry.y, - out_geometry); - } -} - -static void -meta_wayland_subsurface_assigned (MetaWaylandSurfaceRole *surface_role) -{ - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWaylandSurfaceRoleClass *surface_role_class = - META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_subsurface_parent_class); - - surface->dnd.funcs = meta_wayland_data_device_get_drag_dest_funcs (); - - surface_role_class->assigned (surface_role); -} - -static MetaWaylandSurface * -meta_wayland_subsurface_get_toplevel (MetaWaylandSurfaceRole *surface_role) -{ - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWaylandSurface *parent = surface->sub.parent; - - if (parent) - return meta_wayland_surface_get_toplevel (parent); - else - return NULL; -} - -static gboolean -meta_wayland_subsurface_should_cache_state (MetaWaylandSurfaceRole *surface_role) -{ - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWaylandSurface *parent; - - if (surface->sub.synchronous) - return TRUE; - - parent = surface->sub.parent; - if (parent) - return meta_wayland_surface_should_cache_state (parent); - - return TRUE; -} - -static void -meta_wayland_subsurface_notify_subsurface_state_changed (MetaWaylandSurfaceRole *surface_role) -{ - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWaylandSurface *parent = surface->sub.parent; - - if (parent) - return meta_wayland_surface_notify_subsurface_state_changed (parent); -} - -static double -meta_wayland_subsurface_get_geometry_scale (MetaWaylandActorSurface *actor_surface) -{ - MetaWaylandSurfaceRole *surface_role = - META_WAYLAND_SURFACE_ROLE (actor_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWaylandSurface *parent = surface->sub.parent; - - if (parent) - { - MetaWaylandActorSurface *parent_actor; - - parent_actor = META_WAYLAND_ACTOR_SURFACE (surface->sub.parent->role); - return meta_wayland_actor_surface_get_geometry_scale (parent_actor); - } - else - { - return 1; - } -} - -static void -meta_wayland_subsurface_sync_actor_state (MetaWaylandActorSurface *actor_surface) -{ - MetaWaylandSurfaceRole *surface_role = - META_WAYLAND_SURFACE_ROLE (actor_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWaylandActorSurfaceClass *actor_surface_class = - META_WAYLAND_ACTOR_SURFACE_CLASS (meta_wayland_subsurface_parent_class); - MetaWaylandSurface *toplevel_surface; - - toplevel_surface = meta_wayland_surface_get_toplevel (surface); - if (toplevel_surface && meta_wayland_surface_get_window (toplevel_surface)) - actor_surface_class->sync_actor_state (actor_surface); - - sync_actor_subsurface_state (surface); -} - -static void -meta_wayland_subsurface_init (MetaWaylandSubsurface *role) -{ -} - -static void -meta_wayland_subsurface_class_init (MetaWaylandSubsurfaceClass *klass) -{ - MetaWaylandSurfaceRoleClass *surface_role_class = - META_WAYLAND_SURFACE_ROLE_CLASS (klass); - MetaWaylandActorSurfaceClass *actor_surface_class = - META_WAYLAND_ACTOR_SURFACE_CLASS (klass); - - surface_role_class->assigned = meta_wayland_subsurface_assigned; - surface_role_class->get_toplevel = meta_wayland_subsurface_get_toplevel; - surface_role_class->should_cache_state = meta_wayland_subsurface_should_cache_state; - surface_role_class->notify_subsurface_state_changed = - meta_wayland_subsurface_notify_subsurface_state_changed; - - actor_surface_class->get_geometry_scale = - meta_wayland_subsurface_get_geometry_scale; - actor_surface_class->sync_actor_state = - meta_wayland_subsurface_sync_actor_state; -} - -static void -unparent_actor (MetaWaylandSurface *surface) -{ - ClutterActor *actor; - ClutterActor *parent_actor; - - actor = CLUTTER_ACTOR (meta_wayland_surface_get_actor (surface)); - if (!actor) - return; - - parent_actor = clutter_actor_get_parent (actor); - clutter_actor_remove_child (parent_actor, actor); -} - -static void -wl_subsurface_destructor (struct wl_resource *resource) -{ - MetaWaylandSurface *surface = wl_resource_get_user_data (resource); - - g_node_unlink (surface->subsurface_branch_node); - unparent_actor (surface); - - if (surface->sub.parent) - { - wl_list_remove (&surface->sub.parent_destroy_listener.link); - surface->sub.parent = NULL; - } - - surface->wl_subsurface = NULL; -} - -static void -wl_subsurface_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -wl_subsurface_set_position (struct wl_client *client, - struct wl_resource *resource, - int32_t x, - int32_t y) -{ - MetaWaylandSurface *surface = wl_resource_get_user_data (resource); - - surface->sub.pending_x = x; - surface->sub.pending_y = y; - surface->sub.pending_pos = TRUE; -} - -static gboolean -is_valid_sibling (MetaWaylandSurface *surface, - MetaWaylandSurface *sibling) -{ - if (is_child (surface, sibling)) - return TRUE; - if (is_sibling (surface, sibling)) - return TRUE; - return FALSE; -} - -static void -subsurface_handle_pending_subsurface_destroyed (struct wl_listener *listener, - void *data) -{ - MetaWaylandSubsurfacePlacementOp *op = - wl_container_of (listener, op, subsurface_destroy_listener); - - op->surface = NULL; -} - -static void -subsurface_handle_pending_sibling_destroyed (struct wl_listener *listener, - void *data) -{ - MetaWaylandSubsurfacePlacementOp *op = - wl_container_of (listener, op, sibling_destroy_listener); - - op->sibling = NULL; -} - -void -meta_wayland_subsurface_placement_op_free (MetaWaylandSubsurfacePlacementOp *op) -{ - if (op->surface) - wl_list_remove (&op->subsurface_destroy_listener.link); - if (op->sibling) - wl_list_remove (&op->sibling_destroy_listener.link); - g_free (op); -} - -static void -queue_subsurface_placement (MetaWaylandSurface *surface, - MetaWaylandSurface *sibling, - MetaWaylandSubsurfacePlacement placement) -{ - MetaWaylandSurface *parent = surface->sub.parent; - MetaWaylandSubsurfacePlacementOp *op = - g_new0 (MetaWaylandSubsurfacePlacementOp, 1); - - op->placement = placement; - op->surface = surface; - op->sibling = sibling; - op->subsurface_destroy_listener.notify = - subsurface_handle_pending_subsurface_destroyed; - op->sibling_destroy_listener.notify = - subsurface_handle_pending_sibling_destroyed; - wl_resource_add_destroy_listener (surface->wl_subsurface, - &op->subsurface_destroy_listener); - wl_resource_add_destroy_listener (sibling->resource, - &op->sibling_destroy_listener); - - parent->pending_state->subsurface_placement_ops = - g_slist_append (parent->pending_state->subsurface_placement_ops, op); -} - -static void -wl_subsurface_place_above (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *sibling_resource) -{ - MetaWaylandSurface *surface = wl_resource_get_user_data (resource); - MetaWaylandSurface *sibling = wl_resource_get_user_data (sibling_resource); - - if (!is_valid_sibling (surface, sibling)) - { - wl_resource_post_error (resource, WL_SUBSURFACE_ERROR_BAD_SURFACE, - "wl_subsurface::place_above: wl_surface@%d is " - "not a valid parent or sibling", - wl_resource_get_id (sibling->resource)); - return; - } - - queue_subsurface_placement (surface, - sibling, - META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE); -} - -static void -wl_subsurface_place_below (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *sibling_resource) -{ - MetaWaylandSurface *surface = wl_resource_get_user_data (resource); - MetaWaylandSurface *sibling = wl_resource_get_user_data (sibling_resource); - - if (!is_valid_sibling (surface, sibling)) - { - wl_resource_post_error (resource, WL_SUBSURFACE_ERROR_BAD_SURFACE, - "wl_subsurface::place_below: wl_surface@%d is " - "not a valid parent or sibling", - wl_resource_get_id (sibling->resource)); - return; - } - - queue_subsurface_placement (surface, - sibling, - META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW); -} - -static void -wl_subsurface_set_sync (struct wl_client *client, - struct wl_resource *resource) -{ - MetaWaylandSurface *surface = wl_resource_get_user_data (resource); - - surface->sub.synchronous = TRUE; -} - -static void -wl_subsurface_set_desync (struct wl_client *client, - struct wl_resource *resource) -{ - MetaWaylandSurface *surface = wl_resource_get_user_data (resource); - gboolean was_effectively_synchronized; - - was_effectively_synchronized = is_surface_effectively_synchronized (surface); - surface->sub.synchronous = FALSE; - - if (was_effectively_synchronized && - !is_surface_effectively_synchronized (surface)) - meta_wayland_surface_apply_cached_state (surface); -} - -static const struct wl_subsurface_interface meta_wayland_wl_subsurface_interface = { - wl_subsurface_destroy, - wl_subsurface_set_position, - wl_subsurface_place_above, - wl_subsurface_place_below, - wl_subsurface_set_sync, - wl_subsurface_set_desync, -}; - -static void -wl_subcompositor_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -surface_handle_parent_surface_destroyed (struct wl_listener *listener, - void *data) -{ - MetaWaylandSurface *surface = wl_container_of (listener, - surface, - sub.parent_destroy_listener); - - surface->sub.parent = NULL; -} - -static gboolean -is_same_or_ancestor (MetaWaylandSurface *surface, - MetaWaylandSurface *other_surface) -{ - if (surface == other_surface) - return TRUE; - if (other_surface->sub.parent) - return is_same_or_ancestor (surface, other_surface->sub.parent); - return FALSE; -} - -static void -wl_subcompositor_get_subsurface (struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *surface_resource, - struct wl_resource *parent_resource) -{ - MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); - MetaWaylandSurface *parent = wl_resource_get_user_data (parent_resource); - MetaWindow *toplevel_window; - - if (surface->wl_subsurface) - { - wl_resource_post_error (surface_resource, - WL_DISPLAY_ERROR_INVALID_OBJECT, - "wl_subcompositor::get_subsurface already requested"); - return; - } - - if (is_same_or_ancestor (surface, parent)) - { - wl_resource_post_error (resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE, - "Circular relationship between wl_surface@%d " - "and parent surface wl_surface@%d", - wl_resource_get_id (surface->resource), - wl_resource_get_id (parent->resource)); - return; - } - - if (!meta_wayland_surface_assign_role (surface, - META_TYPE_WAYLAND_SUBSURFACE, - NULL)) - { - wl_resource_post_error (resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE, - "wl_surface@%d already has a different role", - wl_resource_get_id (surface->resource)); - return; - } - - toplevel_window = meta_wayland_surface_get_toplevel_window (parent); - if (toplevel_window && - toplevel_window->client_type == META_WINDOW_CLIENT_TYPE_X11) - g_warning ("XWayland subsurfaces not currently supported"); - - surface->wl_subsurface = - wl_resource_create (client, - &wl_subsurface_interface, - wl_resource_get_version (resource), - id); - wl_resource_set_implementation (surface->wl_subsurface, - &meta_wayland_wl_subsurface_interface, - surface, - wl_subsurface_destructor); - - surface->sub.synchronous = TRUE; - surface->sub.parent = parent; - surface->sub.parent_destroy_listener.notify = - surface_handle_parent_surface_destroyed; - wl_resource_add_destroy_listener (parent->resource, - &surface->sub.parent_destroy_listener); - - g_node_append (parent->subsurface_branch_node, - surface->subsurface_branch_node); - - meta_wayland_surface_notify_subsurface_state_changed (parent); -} - -static const struct wl_subcompositor_interface meta_wayland_subcompositor_interface = { - wl_subcompositor_destroy, - wl_subcompositor_get_subsurface, -}; - -static void -bind_subcompositor (struct wl_client *client, - void *data, - uint32_t version, - uint32_t id) -{ - struct wl_resource *resource; - - resource = wl_resource_create (client, &wl_subcompositor_interface, - version, id); - wl_resource_set_implementation (resource, &meta_wayland_subcompositor_interface, - data, NULL); -} - -void -meta_wayland_subsurfaces_init (MetaWaylandCompositor *compositor) -{ - if (wl_global_create (compositor->wayland_display, - &wl_subcompositor_interface, - META_WL_SUBCOMPOSITOR_VERSION, - compositor, bind_subcompositor) == NULL) - g_error ("Failed to register a global wl-subcompositor object"); -} diff --git a/src/wayland/meta-wayland-subsurface.h b/src/wayland/meta-wayland-subsurface.h deleted file mode 100644 index 45dbf8626..000000000 --- a/src/wayland/meta-wayland-subsurface.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2012,2013 Intel Corporation - * Copyright (C) 2013-2017 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_WAYLAND_SUBSURFACE_H -#define META_WAYLAND_SUBSURFACE_H - -#include "wayland/meta-wayland-actor-surface.h" - -#define META_TYPE_WAYLAND_SUBSURFACE (meta_wayland_subsurface_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandSubsurface, - meta_wayland_subsurface, - META, WAYLAND_SUBSURFACE, - MetaWaylandActorSurface) - -typedef enum -{ - META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE, - META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW -} MetaWaylandSubsurfacePlacement; - -typedef struct -{ - MetaWaylandSubsurfacePlacement placement; - MetaWaylandSurface *surface; - MetaWaylandSurface *sibling; - struct wl_listener subsurface_destroy_listener; - struct wl_listener sibling_destroy_listener; -} MetaWaylandSubsurfacePlacementOp; - -void meta_wayland_subsurface_parent_state_applied (MetaWaylandSubsurface *subsurface); - -void meta_wayland_subsurface_union_geometry (MetaWaylandSubsurface *subsurface, - int parent_x, - int parent_y, - MetaRectangle *out_geometry); - -void meta_wayland_subsurface_placement_op_free (MetaWaylandSubsurfacePlacementOp *op); - -void meta_wayland_subsurfaces_init (MetaWaylandCompositor *compositor); - -#endif /* META_WAYLAND_SUBSURFACE_H */ diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c deleted file mode 100644 index 64e7de8db..000000000 --- a/src/wayland/meta-wayland-surface.c +++ /dev/null @@ -1,2133 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2012,2013 Intel Corporation - * Copyright (C) 2013-2017 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include "config.h" - -#include "wayland/meta-wayland-surface.h" - -#include -#include - -#include "backends/meta-cursor-tracker-private.h" -#include "clutter/clutter.h" -#include "cogl/cogl-wayland-server.h" -#include "cogl/cogl.h" -#include "compositor/meta-surface-actor-wayland.h" -#include "compositor/meta-surface-actor.h" -#include "compositor/meta-window-actor-private.h" -#include "compositor/region-utils.h" -#include "core/display-private.h" -#include "core/window-private.h" -#include "wayland/meta-wayland-actor-surface.h" -#include "wayland/meta-wayland-buffer.h" -#include "wayland/meta-wayland-data-device.h" -#include "wayland/meta-wayland-gtk-shell.h" -#include "wayland/meta-wayland-keyboard.h" -#include "wayland/meta-wayland-legacy-xdg-shell.h" -#include "wayland/meta-wayland-outputs.h" -#include "wayland/meta-wayland-pointer.h" -#include "wayland/meta-wayland-presentation-time-private.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-region.h" -#include "wayland/meta-wayland-seat.h" -#include "wayland/meta-wayland-subsurface.h" -#include "wayland/meta-wayland-viewporter.h" -#include "wayland/meta-wayland-wl-shell.h" -#include "wayland/meta-wayland-xdg-shell.h" -#include "wayland/meta-window-wayland.h" -#include "wayland/meta-xwayland-private.h" -#include "wayland/meta-xwayland-private.h" - -enum -{ - SURFACE_STATE_SIGNAL_APPLIED, - - SURFACE_STATE_SIGNAL_N_SIGNALS -}; - -enum -{ - SURFACE_ROLE_PROP_0, - - SURFACE_ROLE_PROP_SURFACE, -}; - -static guint surface_state_signals[SURFACE_STATE_SIGNAL_N_SIGNALS]; - -typedef struct _MetaWaylandSurfaceRolePrivate -{ - MetaWaylandSurface *surface; -} MetaWaylandSurfaceRolePrivate; - -G_DEFINE_TYPE (MetaWaylandSurface, meta_wayland_surface, G_TYPE_OBJECT); - -G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaWaylandSurfaceRole, - meta_wayland_surface_role, - G_TYPE_OBJECT) - -G_DEFINE_TYPE (MetaWaylandSurfaceState, - meta_wayland_surface_state, - G_TYPE_OBJECT) - -enum -{ - SURFACE_DESTROY, - SURFACE_UNMAPPED, - SURFACE_CONFIGURE, - SURFACE_SHORTCUTS_INHIBITED, - SURFACE_SHORTCUTS_RESTORED, - SURFACE_GEOMETRY_CHANGED, - SURFACE_PRE_STATE_APPLIED, - N_SURFACE_SIGNALS -}; - -guint surface_signals[N_SURFACE_SIGNALS] = { 0 }; - -static void -meta_wayland_surface_role_assigned (MetaWaylandSurfaceRole *surface_role); - -static void -meta_wayland_surface_role_pre_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending); - -static void -meta_wayland_surface_role_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending); - -static void -meta_wayland_surface_role_post_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending); - -static gboolean -meta_wayland_surface_role_is_on_logical_monitor (MetaWaylandSurfaceRole *surface_role, - MetaLogicalMonitor *logical_monitor); - -static MetaWaylandSurface * -meta_wayland_surface_role_get_toplevel (MetaWaylandSurfaceRole *surface_role); - -static void -set_surface_is_on_output (MetaWaylandSurface *surface, - MetaWaylandOutput *wayland_output, - gboolean is_on_output); - -static MetaWaylandBufferRef * -meta_wayland_buffer_ref_new (void) -{ - MetaWaylandBufferRef *buffer_ref; - - buffer_ref = g_new0 (MetaWaylandBufferRef, 1); - g_ref_count_init (&buffer_ref->ref_count); - - return buffer_ref; -} - -static MetaWaylandBufferRef * -meta_wayland_buffer_ref_ref (MetaWaylandBufferRef *buffer_ref) -{ - g_ref_count_inc (&buffer_ref->ref_count); - return buffer_ref; -} - -static void -meta_wayland_buffer_ref_unref (MetaWaylandBufferRef *buffer_ref) -{ - if (g_ref_count_dec (&buffer_ref->ref_count)) - { - g_warn_if_fail (buffer_ref->use_count == 0); - g_clear_object (&buffer_ref->buffer); - g_free (buffer_ref); - } -} - -static void -meta_wayland_buffer_ref_inc_use_count (MetaWaylandBufferRef *buffer_ref) -{ - g_return_if_fail (buffer_ref->buffer); - g_warn_if_fail (buffer_ref->buffer->resource); - - buffer_ref->use_count++; -} - -static void -meta_wayland_buffer_ref_dec_use_count (MetaWaylandBufferRef *buffer_ref) -{ - MetaWaylandBuffer *buffer = buffer_ref->buffer; - - g_return_if_fail (buffer_ref->use_count > 0); - g_return_if_fail (buffer); - - buffer_ref->use_count--; - - if (buffer_ref->use_count == 0 && buffer->resource) - wl_buffer_send_release (buffer->resource); -} - -static void -role_assignment_valist_to_properties (GType role_type, - const char *first_property_name, - va_list var_args, - GArray *names, - GArray *values) -{ - GObjectClass *object_class; - const char *property_name = first_property_name; - - object_class = g_type_class_ref (role_type); - - while (property_name) - { - GValue value = G_VALUE_INIT; - GParamSpec *pspec; - GType ptype; - gchar *error = NULL; - - pspec = g_object_class_find_property (object_class, - property_name); - g_assert (pspec); - - ptype = G_PARAM_SPEC_VALUE_TYPE (pspec); - G_VALUE_COLLECT_INIT (&value, ptype, var_args, 0, &error); - g_assert (!error); - - g_array_append_val (names, property_name); - g_array_append_val (values, value); - - property_name = va_arg (var_args, const char *); - } - - g_type_class_unref (object_class); -} - -gboolean -meta_wayland_surface_assign_role (MetaWaylandSurface *surface, - GType role_type, - const char *first_property_name, - ...) -{ - va_list var_args; - - if (!surface->role) - { - if (first_property_name) - { - GArray *names; - GArray *values; - const char *surface_prop_name; - GValue surface_value = G_VALUE_INIT; - GObject *role_object; - - names = g_array_new (FALSE, FALSE, sizeof (const char *)); - values = g_array_new (FALSE, FALSE, sizeof (GValue)); - g_array_set_clear_func (values, (GDestroyNotify) g_value_unset); - - va_start (var_args, first_property_name); - role_assignment_valist_to_properties (role_type, - first_property_name, - var_args, - names, - values); - va_end (var_args); - - surface_prop_name = "surface"; - g_value_init (&surface_value, META_TYPE_WAYLAND_SURFACE); - g_value_set_object (&surface_value, surface); - g_array_append_val (names, surface_prop_name); - g_array_append_val (values, surface_value); - - role_object = - g_object_new_with_properties (role_type, - values->len, - (const char **) names->data, - (const GValue *) values->data); - surface->role = META_WAYLAND_SURFACE_ROLE (role_object); - - g_array_free (names, TRUE); - g_array_free (values, TRUE); - } - else - { - surface->role = g_object_new (role_type, "surface", surface, NULL); - } - - meta_wayland_surface_role_assigned (surface->role); - - /* Release the use count held on behalf of the just assigned role. */ - if (surface->unassigned.buffer) - { - meta_wayland_surface_unref_buffer_use_count (surface); - g_clear_object (&surface->unassigned.buffer); - } - - return TRUE; - } - else if (G_OBJECT_TYPE (surface->role) != role_type) - { - return FALSE; - } - else - { - va_start (var_args, first_property_name); - g_object_set_valist (G_OBJECT (surface->role), - first_property_name, var_args); - va_end (var_args); - - meta_wayland_surface_role_assigned (surface->role); - - return TRUE; - } -} - -static int -get_buffer_width (MetaWaylandSurface *surface) -{ - MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface); - - if (buffer) - return cogl_texture_get_width (surface->texture); - else - return 0; -} - -static int -get_buffer_height (MetaWaylandSurface *surface) -{ - MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface); - - if (buffer) - return cogl_texture_get_height (surface->texture); - else - return 0; -} - -static void -surface_process_damage (MetaWaylandSurface *surface, - cairo_region_t *surface_region, - cairo_region_t *buffer_region) -{ - MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface); - cairo_rectangle_int_t surface_rect; - cairo_rectangle_int_t buffer_rect; - cairo_region_t *scaled_region; - cairo_region_t *transformed_region; - cairo_region_t *viewport_region; - graphene_rect_t src_rect; - MetaSurfaceActor *actor; - - /* If the client destroyed the buffer it attached before committing, but - * still posted damage, or posted damage without any buffer, don't try to - * process it on the non-existing buffer. - */ - if (!buffer) - return; - - buffer_rect = (cairo_rectangle_int_t) { - .width = get_buffer_width (surface), - .height = get_buffer_height (surface), - }; - - /* Intersect the damage region with the surface region before scaling in - * order to avoid integer overflow when scaling a damage region is too large - * (for example INT32_MAX which mesa passes). */ - surface_rect = (cairo_rectangle_int_t) { - .width = meta_wayland_surface_get_width (surface), - .height = meta_wayland_surface_get_height (surface), - }; - cairo_region_intersect_rectangle (surface_region, &surface_rect); - - /* The damage region must be in the same coordinate space as the buffer, - * i.e. scaled with surface->scale. */ - scaled_region = meta_region_scale (surface_region, surface->scale); - if (surface->viewport.has_src_rect) - { - src_rect = (graphene_rect_t) { - .origin.x = surface->viewport.src_rect.origin.x * surface->scale, - .origin.y = surface->viewport.src_rect.origin.y * surface->scale, - .size.width = surface->viewport.src_rect.size.width * surface->scale, - .size.height = surface->viewport.src_rect.size.height * surface->scale - }; - } - else - { - src_rect = (graphene_rect_t) { - .size.width = surface_rect.width * surface->scale, - .size.height = surface_rect.height * surface->scale, - }; - } - viewport_region = meta_region_crop_and_scale (scaled_region, - &src_rect, - surface_rect.width * - surface->scale, - surface_rect.height * - surface->scale); - transformed_region = meta_region_transform (viewport_region, - surface->buffer_transform, - buffer_rect.width, - buffer_rect.height); - - /* Now add the scaled, cropped and transformed damage region to the - * buffer damage. Buffer damage is already in the correct coordinate space. */ - cairo_region_union (buffer_region, transformed_region); - - cairo_region_intersect_rectangle (buffer_region, &buffer_rect); - - meta_wayland_buffer_process_damage (buffer, surface->texture, buffer_region); - - actor = meta_wayland_surface_get_actor (surface); - if (actor) - { - int i, n_rectangles; - - n_rectangles = cairo_region_num_rectangles (buffer_region); - for (i = 0; i < n_rectangles; i++) - { - cairo_rectangle_int_t rect; - cairo_region_get_rectangle (buffer_region, i, &rect); - - meta_surface_actor_process_damage (actor, - rect.x, rect.y, - rect.width, rect.height); - } - } - - cairo_region_destroy (viewport_region); - cairo_region_destroy (scaled_region); - cairo_region_destroy (transformed_region); -} - -MetaWaylandBuffer * -meta_wayland_surface_get_buffer (MetaWaylandSurface *surface) -{ - return surface->buffer_ref->buffer; -} - -void -meta_wayland_surface_ref_buffer_use_count (MetaWaylandSurface *surface) -{ - meta_wayland_buffer_ref_inc_use_count (surface->buffer_ref); -} - -void -meta_wayland_surface_unref_buffer_use_count (MetaWaylandSurface *surface) -{ - meta_wayland_buffer_ref_dec_use_count (surface->buffer_ref); -} - -static void -pending_buffer_resource_destroyed (MetaWaylandBuffer *buffer, - MetaWaylandSurfaceState *pending) -{ - g_clear_signal_handler (&pending->buffer_destroy_handler_id, buffer); - pending->buffer = NULL; -} - -static void -meta_wayland_surface_state_set_default (MetaWaylandSurfaceState *state) -{ - state->newly_attached = FALSE; - state->buffer = NULL; - state->buffer_destroy_handler_id = 0; - state->dx = 0; - state->dy = 0; - state->scale = 0; - - state->input_region = NULL; - state->input_region_set = FALSE; - state->opaque_region = NULL; - state->opaque_region_set = FALSE; - - state->surface_damage = cairo_region_create (); - state->buffer_damage = cairo_region_create (); - wl_list_init (&state->frame_callback_list); - - state->has_new_geometry = FALSE; - state->has_acked_configure_serial = FALSE; - state->has_new_min_size = FALSE; - state->has_new_max_size = FALSE; - - state->has_new_buffer_transform = FALSE; - state->has_new_viewport_src_rect = FALSE; - state->has_new_viewport_dst_size = FALSE; - - state->subsurface_placement_ops = NULL; - - wl_list_init (&state->presentation_feedback_list); -} - -static void -meta_wayland_surface_state_discard_presentation_feedback (MetaWaylandSurfaceState *state) -{ - while (!wl_list_empty (&state->presentation_feedback_list)) - { - MetaWaylandPresentationFeedback *feedback = - wl_container_of (state->presentation_feedback_list.next, feedback, link); - - meta_wayland_presentation_feedback_discard (feedback); - } -} - -static void -meta_wayland_surface_state_clear (MetaWaylandSurfaceState *state) -{ - MetaWaylandFrameCallback *cb, *next; - - g_clear_pointer (&state->surface_damage, cairo_region_destroy); - g_clear_pointer (&state->buffer_damage, cairo_region_destroy); - g_clear_pointer (&state->input_region, cairo_region_destroy); - g_clear_pointer (&state->opaque_region, cairo_region_destroy); - - if (state->buffer) - g_clear_signal_handler (&state->buffer_destroy_handler_id, state->buffer); - - wl_list_for_each_safe (cb, next, &state->frame_callback_list, link) - wl_resource_destroy (cb->resource); - - if (state->subsurface_placement_ops) - { - g_slist_free_full ( - state->subsurface_placement_ops, - (GDestroyNotify) meta_wayland_subsurface_placement_op_free); - } - - meta_wayland_surface_state_discard_presentation_feedback (state); -} - -static void -meta_wayland_surface_state_reset (MetaWaylandSurfaceState *state) -{ - meta_wayland_surface_state_clear (state); - meta_wayland_surface_state_set_default (state); -} - -static void -meta_wayland_surface_state_merge_into (MetaWaylandSurfaceState *from, - MetaWaylandSurfaceState *to) -{ - if (from->newly_attached) - { - if (to->buffer) - g_clear_signal_handler (&to->buffer_destroy_handler_id, to->buffer); - - to->newly_attached = TRUE; - to->buffer = from->buffer; - to->dx = from->dx; - to->dy = from->dy; - } - - wl_list_insert_list (&to->frame_callback_list, &from->frame_callback_list); - wl_list_init (&from->frame_callback_list); - - cairo_region_union (to->surface_damage, from->surface_damage); - cairo_region_union (to->buffer_damage, from->buffer_damage); - - if (from->input_region_set) - { - if (to->input_region) - cairo_region_union (to->input_region, from->input_region); - else - to->input_region = cairo_region_reference (from->input_region); - - to->input_region_set = TRUE; - } - - if (from->opaque_region_set) - { - if (to->opaque_region) - cairo_region_union (to->opaque_region, from->opaque_region); - else - to->opaque_region = cairo_region_reference (from->opaque_region); - - to->opaque_region_set = TRUE; - } - - if (from->has_new_geometry) - { - to->new_geometry = from->new_geometry; - to->has_new_geometry = TRUE; - } - - if (from->has_acked_configure_serial) - { - to->acked_configure_serial = from->acked_configure_serial; - to->has_acked_configure_serial = TRUE; - } - - if (from->has_new_min_size) - { - to->new_min_width = from->new_min_width; - to->new_min_height = from->new_min_height; - to->has_new_min_size = TRUE; - } - - if (from->has_new_max_size) - { - to->new_max_width = from->new_max_width; - to->new_max_height = from->new_max_height; - to->has_new_max_size = TRUE; - } - - if (from->scale > 0) - to->scale = from->scale; - - if (from->has_new_buffer_transform) - { - to->buffer_transform = from->buffer_transform; - to->has_new_buffer_transform = TRUE; - } - - if (from->has_new_viewport_src_rect) - { - to->viewport_src_rect.origin.x = from->viewport_src_rect.origin.x; - to->viewport_src_rect.origin.y = from->viewport_src_rect.origin.y; - to->viewport_src_rect.size.width = from->viewport_src_rect.size.width; - to->viewport_src_rect.size.height = from->viewport_src_rect.size.height; - to->has_new_viewport_src_rect = TRUE; - } - - if (from->has_new_viewport_dst_size) - { - to->viewport_dst_width = from->viewport_dst_width; - to->viewport_dst_height = from->viewport_dst_height; - to->has_new_viewport_dst_size = TRUE; - } - - if (to->buffer && to->buffer_destroy_handler_id == 0) - { - to->buffer_destroy_handler_id = - g_signal_connect (to->buffer, "resource-destroyed", - G_CALLBACK (pending_buffer_resource_destroyed), - to); - } - - if (from->subsurface_placement_ops != NULL) - { - if (to->subsurface_placement_ops != NULL) - { - to->subsurface_placement_ops = - g_slist_concat (to->subsurface_placement_ops, - from->subsurface_placement_ops); - } - else - { - to->subsurface_placement_ops = from->subsurface_placement_ops; - } - - from->subsurface_placement_ops = NULL; - } - - wl_list_insert_list (&to->presentation_feedback_list, - &from->presentation_feedback_list); - wl_list_init (&from->presentation_feedback_list); - - meta_wayland_surface_state_reset (from); -} - -static void -meta_wayland_surface_state_finalize (GObject *object) -{ - MetaWaylandSurfaceState *state = META_WAYLAND_SURFACE_STATE (object); - - meta_wayland_surface_state_clear (state); - - G_OBJECT_CLASS (meta_wayland_surface_state_parent_class)->finalize (object); -} - -static void -meta_wayland_surface_state_init (MetaWaylandSurfaceState *state) -{ - meta_wayland_surface_state_set_default (state); -} - -static void -meta_wayland_surface_state_class_init (MetaWaylandSurfaceStateClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_wayland_surface_state_finalize; - - surface_state_signals[SURFACE_STATE_SIGNAL_APPLIED] = - g_signal_new ("applied", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 0); -} - -static void -meta_wayland_surface_discard_presentation_feedback (MetaWaylandSurface *surface) -{ - while (!wl_list_empty (&surface->presentation_time.feedback_list)) - { - MetaWaylandPresentationFeedback *feedback = - wl_container_of (surface->presentation_time.feedback_list.next, - feedback, link); - - meta_wayland_presentation_feedback_discard (feedback); - } -} - -static void -meta_wayland_surface_apply_state (MetaWaylandSurface *surface, - MetaWaylandSurfaceState *state) -{ - MetaWaylandSurface *subsurface_surface; - gboolean had_damage = FALSE; - - g_signal_emit (surface, surface_signals[SURFACE_PRE_STATE_APPLIED], 0); - - if (surface->role) - { - meta_wayland_surface_role_pre_apply_state (surface->role, state); - } - else - { - if (state->newly_attached && surface->unassigned.buffer) - { - meta_wayland_surface_unref_buffer_use_count (surface); - g_clear_object (&surface->unassigned.buffer); - } - } - - if (state->newly_attached) - { - /* Always release any previously held buffer. If the buffer held is same - * as the newly attached buffer, we still need to release it here, because - * wl_surface.attach+commit and wl_buffer.release on the attached buffer - * is symmetric. - */ - if (surface->buffer_held) - meta_wayland_surface_unref_buffer_use_count (surface); - - if (surface->buffer_ref->use_count > 0) - { - meta_wayland_buffer_ref_unref (surface->buffer_ref); - surface->buffer_ref = meta_wayland_buffer_ref_new (); - } - - g_set_object (&surface->buffer_ref->buffer, state->buffer); - - if (state->buffer) - meta_wayland_surface_ref_buffer_use_count (surface); - - if (state->buffer) - { - GError *error = NULL; - - if (!meta_wayland_buffer_attach (state->buffer, - &surface->texture, - &error)) - { - g_warning ("Could not import pending buffer: %s", error->message); - wl_resource_post_error (surface->resource, WL_DISPLAY_ERROR_NO_MEMORY, - "Failed to attach buffer to surface %i: %s", - wl_resource_get_id (surface->resource), - error->message); - g_error_free (error); - goto cleanup; - } - } - else - { - cogl_clear_object (&surface->texture); - } - - /* If the newly attached buffer is going to be accessed directly without - * making a copy, such as an EGL buffer, mark it as in-use don't release - * it until is replaced by a subsequent wl_surface.commit or when the - * wl_surface is destroyed. - */ - surface->buffer_held = (state->buffer && - !wl_shm_buffer_get (state->buffer->resource)); - } - - if (state->scale > 0) - surface->scale = state->scale; - - if (state->has_new_buffer_transform) - surface->buffer_transform = state->buffer_transform; - - if (state->has_new_viewport_src_rect) - { - surface->viewport.src_rect.origin.x = state->viewport_src_rect.origin.x; - surface->viewport.src_rect.origin.y = state->viewport_src_rect.origin.y; - surface->viewport.src_rect.size.width = state->viewport_src_rect.size.width; - surface->viewport.src_rect.size.height = state->viewport_src_rect.size.height; - surface->viewport.has_src_rect = surface->viewport.src_rect.size.width > 0; - } - - if (state->has_new_viewport_dst_size) - { - surface->viewport.dst_width = state->viewport_dst_width; - surface->viewport.dst_height = state->viewport_dst_height; - surface->viewport.has_dst_size = surface->viewport.dst_width > 0; - } - - if (!cairo_region_is_empty (state->surface_damage) || - !cairo_region_is_empty (state->buffer_damage)) - { - surface_process_damage (surface, - state->surface_damage, - state->buffer_damage); - had_damage = TRUE; - } - - surface->offset_x += state->dx; - surface->offset_y += state->dy; - - if (state->opaque_region_set) - { - if (surface->opaque_region) - cairo_region_destroy (surface->opaque_region); - if (state->opaque_region) - surface->opaque_region = cairo_region_reference (state->opaque_region); - else - surface->opaque_region = NULL; - } - - if (state->input_region_set) - { - if (surface->input_region) - cairo_region_destroy (surface->input_region); - if (state->input_region) - surface->input_region = cairo_region_reference (state->input_region); - else - surface->input_region = NULL; - } - - /* - * A new commit indicates a new content update, so any previous - * content update did not go on screen and needs to be discarded. - */ - meta_wayland_surface_discard_presentation_feedback (surface); - - wl_list_insert_list (&surface->presentation_time.feedback_list, - &state->presentation_feedback_list); - wl_list_init (&state->presentation_feedback_list); - - if (!wl_list_empty (&surface->presentation_time.feedback_list)) - meta_wayland_compositor_add_presentation_feedback_surface (surface->compositor, - surface); - - if (surface->role) - { - meta_wayland_surface_role_apply_state (surface->role, state); - g_assert (wl_list_empty (&state->frame_callback_list)); - } - else - { - wl_list_insert_list (surface->unassigned.pending_frame_callback_list.prev, - &state->frame_callback_list); - wl_list_init (&state->frame_callback_list); - - if (state->newly_attached) - { - /* The need to keep the wl_buffer from being released depends on what - * role the surface is given. That means we need to also keep a use - * count for wl_buffer's that are used by unassigned wl_surface's. - */ - g_set_object (&surface->unassigned.buffer, - surface->buffer_ref->buffer); - if (surface->unassigned.buffer) - meta_wayland_surface_ref_buffer_use_count (surface); - } - } - - if (state->subsurface_placement_ops) - { - GSList *l; - - for (l = state->subsurface_placement_ops; l; l = l->next) - { - MetaWaylandSubsurfacePlacementOp *op = l->data; - GNode *sibling_node; - - if (!op->surface || !op->sibling) - continue; - - if (op->sibling == surface) - sibling_node = surface->subsurface_leaf_node; - else - sibling_node = op->sibling->subsurface_branch_node; - - g_node_unlink (op->surface->subsurface_branch_node); - - switch (op->placement) - { - case META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE: - g_node_insert_after (surface->subsurface_branch_node, - sibling_node, - op->surface->subsurface_branch_node); - break; - case META_WAYLAND_SUBSURFACE_PLACEMENT_BELOW: - g_node_insert_before (surface->subsurface_branch_node, - sibling_node, - op->surface->subsurface_branch_node); - break; - } - } - - meta_wayland_surface_notify_subsurface_state_changed (surface); - } - -cleanup: - /* If we have a buffer that we are not using, decrease the use count so it may - * be released if no-one else has a use-reference to it. - */ - if (state->newly_attached && - !surface->buffer_held && surface->buffer_ref->buffer) - meta_wayland_surface_unref_buffer_use_count (surface); - - g_signal_emit (state, - surface_state_signals[SURFACE_STATE_SIGNAL_APPLIED], - 0); - - META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface) - { - MetaWaylandSubsurface *subsurface; - - subsurface = META_WAYLAND_SUBSURFACE (subsurface_surface->role); - meta_wayland_subsurface_parent_state_applied (subsurface); - } - - if (had_damage) - { - MetaWindow *toplevel_window; - - toplevel_window = meta_wayland_surface_get_toplevel_window (surface); - if (toplevel_window) - { - MetaWindowActor *toplevel_window_actor; - - toplevel_window_actor = - meta_window_actor_from_window (toplevel_window); - if (toplevel_window_actor) - meta_window_actor_notify_damaged (toplevel_window_actor); - } - } - - if (surface->role) - meta_wayland_surface_role_post_apply_state (surface->role, state); - - meta_wayland_surface_state_reset (state); -} - -void -meta_wayland_surface_apply_cached_state (MetaWaylandSurface *surface) -{ - if (!surface->cached_state) - return; - - meta_wayland_surface_apply_state (surface, surface->cached_state); -} - -MetaWaylandSurfaceState * -meta_wayland_surface_get_pending_state (MetaWaylandSurface *surface) -{ - return surface->pending_state; -} - -MetaWaylandSurfaceState * -meta_wayland_surface_ensure_cached_state (MetaWaylandSurface *surface) -{ - if (!surface->cached_state) - surface->cached_state = g_object_new (META_TYPE_WAYLAND_SURFACE_STATE, - NULL); - return surface->cached_state; -} - -static void -meta_wayland_surface_commit (MetaWaylandSurface *surface) -{ - MetaWaylandSurfaceState *pending = surface->pending_state; - - COGL_TRACE_BEGIN_SCOPED (MetaWaylandSurfaceCommit, - "WaylandSurface (commit)"); - - if (pending->buffer && - !meta_wayland_buffer_is_realized (pending->buffer)) - meta_wayland_buffer_realize (pending->buffer); - - /* - * If this is a sub-surface and it is in effective synchronous mode, only - * cache the pending surface state until either one of the following two - * scenarios happens: - * 1) Its parent surface gets its state applied. - * 2) Its mode changes from synchronized to desynchronized and its parent - * surface is in effective desynchronized mode. - */ - if (meta_wayland_surface_should_cache_state (surface)) - { - MetaWaylandSurfaceState *cached_state; - - cached_state = meta_wayland_surface_ensure_cached_state (surface); - - /* - * A new commit indicates a new content update, so any previous - * cached content update did not go on screen and needs to be discarded. - */ - meta_wayland_surface_state_discard_presentation_feedback (cached_state); - - meta_wayland_surface_state_merge_into (pending, cached_state); - } - else - { - meta_wayland_surface_apply_state (surface, surface->pending_state); - } -} - -static void -wl_surface_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -wl_surface_attach (struct wl_client *client, - struct wl_resource *surface_resource, - struct wl_resource *buffer_resource, - gint32 dx, gint32 dy) -{ - MetaWaylandSurface *surface = - wl_resource_get_user_data (surface_resource); - MetaWaylandSurfaceState *pending = surface->pending_state; - MetaWaylandBuffer *buffer; - - /* X11 unmanaged window */ - if (!surface) - return; - - if (buffer_resource) - buffer = meta_wayland_buffer_from_resource (buffer_resource); - else - buffer = NULL; - - if (surface->pending_state->buffer) - { - g_clear_signal_handler (&pending->buffer_destroy_handler_id, - pending->buffer); - } - - pending->newly_attached = TRUE; - pending->buffer = buffer; - pending->dx = dx; - pending->dy = dy; - - if (buffer) - { - pending->buffer_destroy_handler_id = - g_signal_connect (buffer, "resource-destroyed", - G_CALLBACK (pending_buffer_resource_destroyed), - pending); - } -} - -static void -wl_surface_damage (struct wl_client *client, - struct wl_resource *surface_resource, - int32_t x, - int32_t y, - int32_t width, - int32_t height) -{ - MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); - MetaWaylandSurfaceState *pending = surface->pending_state; - cairo_rectangle_int_t rectangle; - - /* X11 unmanaged window */ - if (!surface) - return; - - rectangle = (cairo_rectangle_int_t) { - .x = x, - .y = y, - .width = width, - .height = height - }; - cairo_region_union_rectangle (pending->surface_damage, &rectangle); -} - -static void -destroy_frame_callback (struct wl_resource *callback_resource) -{ - MetaWaylandFrameCallback *callback = - wl_resource_get_user_data (callback_resource); - - wl_list_remove (&callback->link); - g_free (callback); -} - -static void -wl_surface_frame (struct wl_client *client, - struct wl_resource *surface_resource, - guint32 callback_id) -{ - MetaWaylandFrameCallback *callback; - MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); - MetaWaylandSurfaceState *pending = surface->pending_state; - - /* X11 unmanaged window */ - if (!surface) - return; - - callback = g_new0 (MetaWaylandFrameCallback, 1); - callback->surface = surface; - callback->resource = wl_resource_create (client, - &wl_callback_interface, - META_WL_CALLBACK_VERSION, - callback_id); - wl_resource_set_implementation (callback->resource, NULL, callback, - destroy_frame_callback); - - wl_list_insert (pending->frame_callback_list.prev, &callback->link); -} - -static void -wl_surface_set_opaque_region (struct wl_client *client, - struct wl_resource *surface_resource, - struct wl_resource *region_resource) -{ - MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); - MetaWaylandSurfaceState *pending = surface->pending_state; - - /* X11 unmanaged window */ - if (!surface) - return; - - g_clear_pointer (&pending->opaque_region, cairo_region_destroy); - if (region_resource) - { - MetaWaylandRegion *region = wl_resource_get_user_data (region_resource); - cairo_region_t *cr_region = meta_wayland_region_peek_cairo_region (region); - pending->opaque_region = cairo_region_copy (cr_region); - } - pending->opaque_region_set = TRUE; -} - -static void -wl_surface_set_input_region (struct wl_client *client, - struct wl_resource *surface_resource, - struct wl_resource *region_resource) -{ - MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); - MetaWaylandSurfaceState *pending = surface->pending_state; - - /* X11 unmanaged window */ - if (!surface) - return; - - g_clear_pointer (&pending->input_region, cairo_region_destroy); - if (region_resource) - { - MetaWaylandRegion *region = wl_resource_get_user_data (region_resource); - cairo_region_t *cr_region = meta_wayland_region_peek_cairo_region (region); - pending->input_region = cairo_region_copy (cr_region); - } - pending->input_region_set = TRUE; -} - -static void -wl_surface_commit (struct wl_client *client, - struct wl_resource *resource) -{ - MetaWaylandSurface *surface = wl_resource_get_user_data (resource); - - /* X11 unmanaged window */ - if (!surface) - return; - - meta_wayland_surface_commit (surface); -} - -static MetaMonitorTransform -transform_from_wl_output_transform (int32_t transform_value) -{ - enum wl_output_transform transform = transform_value; - - switch (transform) - { - case WL_OUTPUT_TRANSFORM_NORMAL: - return META_MONITOR_TRANSFORM_NORMAL; - case WL_OUTPUT_TRANSFORM_90: - return META_MONITOR_TRANSFORM_90; - case WL_OUTPUT_TRANSFORM_180: - return META_MONITOR_TRANSFORM_180; - case WL_OUTPUT_TRANSFORM_270: - return META_MONITOR_TRANSFORM_270; - case WL_OUTPUT_TRANSFORM_FLIPPED: - return META_MONITOR_TRANSFORM_FLIPPED; - case WL_OUTPUT_TRANSFORM_FLIPPED_90: - return META_MONITOR_TRANSFORM_FLIPPED_90; - case WL_OUTPUT_TRANSFORM_FLIPPED_180: - return META_MONITOR_TRANSFORM_FLIPPED_180; - case WL_OUTPUT_TRANSFORM_FLIPPED_270: - return META_MONITOR_TRANSFORM_FLIPPED_270; - default: - return -1; - } -} - -static void -wl_surface_set_buffer_transform (struct wl_client *client, - struct wl_resource *resource, - int32_t transform) -{ - MetaWaylandSurface *surface = wl_resource_get_user_data (resource); - MetaWaylandSurfaceState *pending = surface->pending_state; - MetaMonitorTransform buffer_transform; - - buffer_transform = transform_from_wl_output_transform (transform); - - if (buffer_transform == -1) - { - wl_resource_post_error (resource, - WL_SURFACE_ERROR_INVALID_TRANSFORM, - "Trying to set invalid buffer_transform of %d", - transform); - return; - } - - pending->buffer_transform = buffer_transform; - pending->has_new_buffer_transform = TRUE; -} - -static void -wl_surface_set_buffer_scale (struct wl_client *client, - struct wl_resource *resource, - int scale) -{ - MetaWaylandSurface *surface = wl_resource_get_user_data (resource); - MetaWaylandSurfaceState *pending = surface->pending_state; - - if (scale <= 0) - { - wl_resource_post_error (resource, - WL_SURFACE_ERROR_INVALID_SCALE, - "Trying to set invalid buffer_scale of %d", - scale); - return; - } - - pending->scale = scale; -} - -static void -wl_surface_damage_buffer (struct wl_client *client, - struct wl_resource *surface_resource, - int32_t x, - int32_t y, - int32_t width, - int32_t height) -{ - MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); - MetaWaylandSurfaceState *pending = surface->pending_state; - cairo_rectangle_int_t rectangle; - - /* X11 unmanaged window */ - if (!surface) - return; - - rectangle = (cairo_rectangle_int_t) { - .x = x, - .y = y, - .width = width, - .height = height - }; - cairo_region_union_rectangle (pending->buffer_damage, &rectangle); -} - -static const struct wl_surface_interface meta_wayland_wl_surface_interface = { - wl_surface_destroy, - wl_surface_attach, - wl_surface_damage, - wl_surface_frame, - wl_surface_set_opaque_region, - wl_surface_set_input_region, - wl_surface_commit, - wl_surface_set_buffer_transform, - wl_surface_set_buffer_scale, - wl_surface_damage_buffer, -}; - -static void -handle_output_destroyed (MetaWaylandOutput *wayland_output, - MetaWaylandSurface *surface) -{ - set_surface_is_on_output (surface, wayland_output, FALSE); -} - -static void -handle_output_bound (MetaWaylandOutput *wayland_output, - struct wl_resource *output_resource, - MetaWaylandSurface *surface) -{ - if (wl_resource_get_client (output_resource) == - wl_resource_get_client (surface->resource)) - wl_surface_send_enter (surface->resource, output_resource); -} - -static void -surface_entered_output (MetaWaylandSurface *surface, - MetaWaylandOutput *wayland_output) -{ - GList *iter; - struct wl_resource *resource; - - g_signal_connect (wayland_output, "output-destroyed", - G_CALLBACK (handle_output_destroyed), - surface); - - for (iter = wayland_output->resources; iter != NULL; iter = iter->next) - { - resource = iter->data; - - if (wl_resource_get_client (resource) != - wl_resource_get_client (surface->resource)) - continue; - - wl_surface_send_enter (surface->resource, resource); - } - - g_signal_connect (wayland_output, "output-bound", - G_CALLBACK (handle_output_bound), - surface); -} - -static void -surface_left_output (MetaWaylandSurface *surface, - MetaWaylandOutput *wayland_output) -{ - GList *iter; - struct wl_resource *resource; - - g_signal_handlers_disconnect_by_func (wayland_output, - G_CALLBACK (handle_output_destroyed), - surface); - - g_signal_handlers_disconnect_by_func (wayland_output, - G_CALLBACK (handle_output_bound), - surface); - - for (iter = wayland_output->resources; iter != NULL; iter = iter->next) - { - resource = iter->data; - - if (wl_resource_get_client (resource) != - wl_resource_get_client (surface->resource)) - continue; - - wl_surface_send_leave (surface->resource, resource); - } -} - -static void -set_surface_is_on_output (MetaWaylandSurface *surface, - MetaWaylandOutput *wayland_output, - gboolean is_on_output) -{ - gboolean was_on_output; - - was_on_output = g_hash_table_contains (surface->outputs, wayland_output); - - if (!was_on_output && is_on_output) - { - g_hash_table_add (surface->outputs, wayland_output); - surface_entered_output (surface, wayland_output); - } - else if (was_on_output && !is_on_output) - { - g_hash_table_remove (surface->outputs, wayland_output); - surface_left_output (surface, wayland_output); - } -} - -static void -update_surface_output_state (gpointer key, gpointer value, gpointer user_data) -{ - MetaWaylandOutput *wayland_output = value; - MetaWaylandSurface *surface = user_data; - MetaLogicalMonitor *logical_monitor; - gboolean is_on_logical_monitor; - - g_assert (surface->role); - - logical_monitor = wayland_output->logical_monitor; - if (!logical_monitor) - { - set_surface_is_on_output (surface, wayland_output, FALSE); - return; - } - - is_on_logical_monitor = - meta_wayland_surface_role_is_on_logical_monitor (surface->role, - logical_monitor); - set_surface_is_on_output (surface, wayland_output, is_on_logical_monitor); -} - -static void -surface_output_disconnect_signals (gpointer key, - gpointer value, - gpointer user_data) -{ - MetaWaylandOutput *wayland_output = key; - MetaWaylandSurface *surface = user_data; - - g_signal_handlers_disconnect_by_func (wayland_output, - G_CALLBACK (handle_output_destroyed), - surface); - - g_signal_handlers_disconnect_by_func (wayland_output, - G_CALLBACK (handle_output_bound), - surface); -} - -void -meta_wayland_surface_update_outputs (MetaWaylandSurface *surface) -{ - if (!surface->compositor) - return; - - g_hash_table_foreach (surface->compositor->outputs, - update_surface_output_state, - surface); -} - -void -meta_wayland_surface_notify_unmapped (MetaWaylandSurface *surface) -{ - g_signal_emit (surface, surface_signals[SURFACE_UNMAPPED], 0); -} - -static void -unlink_note (GNode *node, - gpointer data) -{ - g_node_unlink (node); -} - -static void -wl_surface_destructor (struct wl_resource *resource) -{ - MetaWaylandSurface *surface = wl_resource_get_user_data (resource); - MetaWaylandCompositor *compositor = surface->compositor; - MetaWaylandFrameCallback *cb, *next; - - g_signal_emit (surface, surface_signals[SURFACE_DESTROY], 0); - - g_clear_object (&surface->role); - - if (surface->unassigned.buffer) - { - meta_wayland_surface_unref_buffer_use_count (surface); - g_clear_object (&surface->unassigned.buffer); - } - - if (surface->buffer_held) - meta_wayland_surface_unref_buffer_use_count (surface); - g_clear_pointer (&surface->texture, cogl_object_unref); - g_clear_pointer (&surface->buffer_ref, meta_wayland_buffer_ref_unref); - - g_clear_object (&surface->cached_state); - g_clear_object (&surface->pending_state); - - if (surface->opaque_region) - cairo_region_destroy (surface->opaque_region); - if (surface->input_region) - cairo_region_destroy (surface->input_region); - - meta_wayland_compositor_remove_frame_callback_surface (compositor, surface); - meta_wayland_compositor_remove_presentation_feedback_surface (compositor, - surface); - - g_hash_table_foreach (surface->outputs, - surface_output_disconnect_signals, - surface); - g_hash_table_destroy (surface->outputs); - - wl_list_for_each_safe (cb, next, - &surface->unassigned.pending_frame_callback_list, - link) - wl_resource_destroy (cb->resource); - - meta_wayland_surface_discard_presentation_feedback (surface); - - if (surface->resource) - wl_resource_set_user_data (surface->resource, NULL); - - if (surface->wl_subsurface) - wl_resource_destroy (surface->wl_subsurface); - - if (surface->subsurface_branch_node) - { - g_node_children_foreach (surface->subsurface_branch_node, - G_TRAVERSE_NON_LEAVES, - unlink_note, - NULL); - g_clear_pointer (&surface->subsurface_branch_node, g_node_destroy); - } - - g_hash_table_destroy (surface->shortcut_inhibited_seats); - - g_object_unref (surface); -} - -MetaWaylandSurface * -meta_wayland_surface_create (MetaWaylandCompositor *compositor, - struct wl_client *client, - struct wl_resource *compositor_resource, - guint32 id) -{ - MetaWaylandSurface *surface = g_object_new (META_TYPE_WAYLAND_SURFACE, NULL); - int surface_version; - - surface->compositor = compositor; - surface->scale = 1; - - surface_version = wl_resource_get_version (compositor_resource); - surface->resource = wl_resource_create (client, - &wl_surface_interface, - surface_version, - id); - wl_resource_set_implementation (surface->resource, - &meta_wayland_wl_surface_interface, - surface, - wl_surface_destructor); - - wl_list_init (&surface->unassigned.pending_frame_callback_list); - - surface->outputs = g_hash_table_new (NULL, NULL); - surface->shortcut_inhibited_seats = g_hash_table_new (NULL, NULL); - - wl_list_init (&surface->presentation_time.feedback_list); - - meta_wayland_compositor_notify_surface_id (compositor, id, surface); - - return surface; -} - -gboolean -meta_wayland_surface_begin_grab_op (MetaWaylandSurface *surface, - MetaWaylandSeat *seat, - MetaGrabOp grab_op, - gfloat x, - gfloat y) -{ - MetaWindow *window = meta_wayland_surface_get_window (surface); - - if (grab_op == META_GRAB_OP_NONE) - return FALSE; - - /* This is an input driven operation so we set frame_action to - constrain it in the same way as it would be if the window was - being moved/resized via a SSD event. */ - return meta_display_begin_grab_op (window->display, - window, - grab_op, - TRUE, /* pointer_already_grabbed */ - TRUE, /* frame_action */ - 1, /* button. XXX? */ - 0, /* modmask */ - meta_display_get_current_time_roundtrip (window->display), - x, y); -} - -/** - * meta_wayland_shell_init: - * @compositor: The #MetaWaylandCompositor object - * - * Initializes the Wayland interfaces providing features that deal with - * desktop-specific conundrums, like XDG shell, wl_shell (deprecated), etc. - */ -void -meta_wayland_shell_init (MetaWaylandCompositor *compositor) -{ - meta_wayland_xdg_shell_init (compositor); - meta_wayland_legacy_xdg_shell_init (compositor); - meta_wayland_wl_shell_init (compositor); - meta_wayland_init_gtk_shell (compositor); - meta_wayland_init_viewporter (compositor); -} - -void -meta_wayland_surface_configure_notify (MetaWaylandSurface *surface, - MetaWaylandWindowConfiguration *configuration) -{ - MetaWaylandShellSurface *shell_surface = - META_WAYLAND_SHELL_SURFACE (surface->role); - - g_signal_emit (surface, surface_signals[SURFACE_CONFIGURE], 0); - - meta_wayland_shell_surface_configure (shell_surface, configuration); -} - -void -meta_wayland_surface_ping (MetaWaylandSurface *surface, - guint32 serial) -{ - MetaWaylandShellSurface *shell_surface = - META_WAYLAND_SHELL_SURFACE (surface->role); - - meta_wayland_shell_surface_ping (shell_surface, serial); -} - -void -meta_wayland_surface_delete (MetaWaylandSurface *surface) -{ - MetaWaylandShellSurface *shell_surface = - META_WAYLAND_SHELL_SURFACE (surface->role); - - meta_wayland_shell_surface_close (shell_surface); -} - -void -meta_wayland_surface_window_managed (MetaWaylandSurface *surface, - MetaWindow *window) -{ - MetaWaylandShellSurface *shell_surface = - META_WAYLAND_SHELL_SURFACE (surface->role); - - meta_wayland_shell_surface_managed (shell_surface, window); -} - -void -meta_wayland_surface_drag_dest_focus_in (MetaWaylandSurface *surface, - MetaWaylandDataOffer *offer) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaWaylandDataDevice *data_device = &compositor->seat->data_device; - - surface->dnd.funcs->focus_in (data_device, surface, offer); -} - -void -meta_wayland_surface_drag_dest_motion (MetaWaylandSurface *surface, - const ClutterEvent *event) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaWaylandDataDevice *data_device = &compositor->seat->data_device; - - surface->dnd.funcs->motion (data_device, surface, event); -} - -void -meta_wayland_surface_drag_dest_focus_out (MetaWaylandSurface *surface) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaWaylandDataDevice *data_device = &compositor->seat->data_device; - - surface->dnd.funcs->focus_out (data_device, surface); -} - -void -meta_wayland_surface_drag_dest_drop (MetaWaylandSurface *surface) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaWaylandDataDevice *data_device = &compositor->seat->data_device; - - surface->dnd.funcs->drop (data_device, surface); -} - -void -meta_wayland_surface_drag_dest_update (MetaWaylandSurface *surface) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaWaylandDataDevice *data_device = &compositor->seat->data_device; - - surface->dnd.funcs->update (data_device, surface); -} - -MetaWaylandSurface * -meta_wayland_surface_get_toplevel (MetaWaylandSurface *surface) -{ - if (surface->role) - return meta_wayland_surface_role_get_toplevel (surface->role); - else - return NULL; -} - -MetaWindow * -meta_wayland_surface_get_toplevel_window (MetaWaylandSurface *surface) -{ - MetaWaylandSurface *toplevel; - - toplevel = meta_wayland_surface_get_toplevel (surface); - if (toplevel) - return meta_wayland_surface_get_window (toplevel); - else - return NULL; -} - -void -meta_wayland_surface_get_relative_coordinates (MetaWaylandSurface *surface, - float abs_x, - float abs_y, - float *sx, - float *sy) -{ - MetaWaylandSurfaceRoleClass *surface_role_class = - META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface->role); - - surface_role_class->get_relative_coordinates (surface->role, - abs_x, abs_y, - sx, sy); -} - -void -meta_wayland_surface_get_absolute_coordinates (MetaWaylandSurface *surface, - float sx, - float sy, - float *x, - float *y) -{ - ClutterActor *actor = - CLUTTER_ACTOR (meta_wayland_surface_get_actor (surface)); - graphene_point3d_t sv = { - .x = sx, - .y = sy, - }; - graphene_point3d_t v = { 0 }; - - clutter_actor_apply_relative_transform_to_point (actor, NULL, &sv, &v); - - *x = v.x; - *y = v.y; -} - -static void -meta_wayland_surface_init (MetaWaylandSurface *surface) -{ - surface->pending_state = g_object_new (META_TYPE_WAYLAND_SURFACE_STATE, NULL); - - surface->buffer_ref = meta_wayland_buffer_ref_new (); - - surface->subsurface_branch_node = g_node_new (surface); - surface->subsurface_leaf_node = - g_node_prepend_data (surface->subsurface_branch_node, surface); -} - -static void -meta_wayland_surface_class_init (MetaWaylandSurfaceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - surface_signals[SURFACE_DESTROY] = - g_signal_new ("destroy", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - surface_signals[SURFACE_UNMAPPED] = - g_signal_new ("unmapped", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - surface_signals[SURFACE_CONFIGURE] = - g_signal_new ("configure", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - surface_signals[SURFACE_SHORTCUTS_INHIBITED] = - g_signal_new ("shortcuts-inhibited", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - surface_signals[SURFACE_SHORTCUTS_RESTORED] = - g_signal_new ("shortcuts-restored", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - surface_signals[SURFACE_GEOMETRY_CHANGED] = - g_signal_new ("geometry-changed", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - surface_signals[SURFACE_PRE_STATE_APPLIED] = - g_signal_new ("pre-state-applied", - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); -} - -static void -meta_wayland_surface_role_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaWaylandSurfaceRole *surface_role = META_WAYLAND_SURFACE_ROLE (object); - MetaWaylandSurfaceRolePrivate *priv = - meta_wayland_surface_role_get_instance_private (surface_role); - - switch (prop_id) - { - case SURFACE_ROLE_PROP_SURFACE: - priv->surface = g_value_get_object (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_wayland_surface_role_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaWaylandSurfaceRole *surface_role = META_WAYLAND_SURFACE_ROLE (object); - MetaWaylandSurfaceRolePrivate *priv = - meta_wayland_surface_role_get_instance_private (surface_role); - - switch (prop_id) - { - case SURFACE_ROLE_PROP_SURFACE: - g_value_set_object (value, priv->surface); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_wayland_surface_role_init (MetaWaylandSurfaceRole *role) -{ -} - -static void -meta_wayland_surface_role_class_init (MetaWaylandSurfaceRoleClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->set_property = meta_wayland_surface_role_set_property; - object_class->get_property = meta_wayland_surface_role_get_property; - - g_object_class_install_property (object_class, - SURFACE_ROLE_PROP_SURFACE, - g_param_spec_object ("surface", - "MetaWaylandSurface", - "The MetaWaylandSurface instance", - META_TYPE_WAYLAND_SURFACE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); -} - -static void -meta_wayland_surface_role_assigned (MetaWaylandSurfaceRole *surface_role) -{ - META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role)->assigned (surface_role); -} - -static void -meta_wayland_surface_role_pre_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending) -{ - MetaWaylandSurfaceRoleClass *klass; - - klass = META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role); - if (klass->pre_apply_state) - klass->pre_apply_state (surface_role, pending); -} - -static void -meta_wayland_surface_role_post_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending) -{ - MetaWaylandSurfaceRoleClass *klass; - - klass = META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role); - if (klass->post_apply_state) - klass->post_apply_state (surface_role, pending); -} - -static void -meta_wayland_surface_role_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending) -{ - META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role)->apply_state (surface_role, - pending); -} - -static gboolean -meta_wayland_surface_role_is_on_logical_monitor (MetaWaylandSurfaceRole *surface_role, - MetaLogicalMonitor *logical_monitor) -{ - MetaWaylandSurfaceRoleClass *klass; - - klass = META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role); - if (klass->is_on_logical_monitor) - return klass->is_on_logical_monitor (surface_role, logical_monitor); - else - return FALSE; -} - -static MetaWaylandSurface * -meta_wayland_surface_role_get_toplevel (MetaWaylandSurfaceRole *surface_role) -{ - MetaWaylandSurfaceRoleClass *klass; - - klass = META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role); - if (klass->get_toplevel) - return klass->get_toplevel (surface_role); - else - return NULL; -} - -static MetaWindow * -meta_wayland_surface_role_get_window (MetaWaylandSurfaceRole *surface_role) -{ - MetaWaylandSurfaceRoleClass *klass; - - klass = META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role); - - if (klass->get_window) - return klass->get_window (surface_role); - else - return NULL; -} - -MetaWindow * -meta_wayland_surface_get_window (MetaWaylandSurface *surface) -{ - if (!surface->role) - return NULL; - - return meta_wayland_surface_role_get_window (surface->role); -} - -static gboolean -meta_wayland_surface_role_should_cache_state (MetaWaylandSurfaceRole *surface_role) -{ - MetaWaylandSurfaceRoleClass *klass; - - klass = META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role); - if (klass->should_cache_state) - return klass->should_cache_state (surface_role); - else - return FALSE; -} - -gboolean -meta_wayland_surface_should_cache_state (MetaWaylandSurface *surface) -{ - if (!surface->role) - return FALSE; - - return meta_wayland_surface_role_should_cache_state (surface->role); -} - -static void -meta_wayland_surface_role_notify_subsurface_state_changed (MetaWaylandSurfaceRole *surface_role) -{ - MetaWaylandSurfaceRoleClass *klass; - - klass = META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role); - g_return_if_fail (klass->notify_subsurface_state_changed); - - klass->notify_subsurface_state_changed (surface_role); -} - -void -meta_wayland_surface_notify_subsurface_state_changed (MetaWaylandSurface *surface) -{ - if (surface->role) - meta_wayland_surface_role_notify_subsurface_state_changed (surface->role); -} - -MetaWaylandSurface * -meta_wayland_surface_role_get_surface (MetaWaylandSurfaceRole *role) -{ - MetaWaylandSurfaceRolePrivate *priv = - meta_wayland_surface_role_get_instance_private (role); - - return priv->surface; -} - -cairo_region_t * -meta_wayland_surface_calculate_input_region (MetaWaylandSurface *surface) -{ - cairo_region_t *region; - cairo_rectangle_int_t buffer_rect; - - if (!surface->buffer_ref->buffer) - return NULL; - - buffer_rect = (cairo_rectangle_int_t) { - .width = meta_wayland_surface_get_width (surface), - .height = meta_wayland_surface_get_height (surface), - }; - region = cairo_region_create_rectangle (&buffer_rect); - - if (surface->input_region) - cairo_region_intersect (region, surface->input_region); - - return region; -} - -void -meta_wayland_surface_inhibit_shortcuts (MetaWaylandSurface *surface, - MetaWaylandSeat *seat) -{ - g_hash_table_add (surface->shortcut_inhibited_seats, seat); - g_signal_emit (surface, surface_signals[SURFACE_SHORTCUTS_INHIBITED], 0); -} - -void -meta_wayland_surface_restore_shortcuts (MetaWaylandSurface *surface, - MetaWaylandSeat *seat) -{ - g_signal_emit (surface, surface_signals[SURFACE_SHORTCUTS_RESTORED], 0); - g_hash_table_remove (surface->shortcut_inhibited_seats, seat); -} - -gboolean -meta_wayland_surface_is_shortcuts_inhibited (MetaWaylandSurface *surface, - MetaWaylandSeat *seat) -{ - if (surface->shortcut_inhibited_seats == NULL) - return FALSE; - - return g_hash_table_contains (surface->shortcut_inhibited_seats, seat); -} - -CoglTexture * -meta_wayland_surface_get_texture (MetaWaylandSurface *surface) -{ - return surface->texture; -} - -MetaSurfaceActor * -meta_wayland_surface_get_actor (MetaWaylandSurface *surface) -{ - if (!surface->role || !META_IS_WAYLAND_ACTOR_SURFACE (surface->role)) - return NULL; - - return meta_wayland_actor_surface_get_actor (META_WAYLAND_ACTOR_SURFACE (surface->role)); -} - -void -meta_wayland_surface_notify_geometry_changed (MetaWaylandSurface *surface) -{ - g_signal_emit (surface, surface_signals[SURFACE_GEOMETRY_CHANGED], 0); -} - -int -meta_wayland_surface_get_width (MetaWaylandSurface *surface) -{ - if (surface->viewport.has_dst_size) - { - return surface->viewport.dst_width; - } - else if (surface->viewport.has_src_rect) - { - return ceilf (surface->viewport.src_rect.size.width); - } - else - { - int width; - - if (meta_monitor_transform_is_rotated (surface->buffer_transform)) - width = get_buffer_height (surface); - else - width = get_buffer_width (surface); - - return width / surface->scale; - } -} - -int -meta_wayland_surface_get_height (MetaWaylandSurface *surface) -{ - if (surface->viewport.has_dst_size) - { - return surface->viewport.dst_height; - } - else if (surface->viewport.has_src_rect) - { - return ceilf (surface->viewport.src_rect.size.height); - } - else - { - int height; - - if (meta_monitor_transform_is_rotated (surface->buffer_transform)) - height = get_buffer_width (surface); - else - height = get_buffer_height (surface); - - return height / surface->scale; - } -} - -static void -scanout_destroyed (gpointer data, - GObject *where_the_object_was) -{ - MetaWaylandBufferRef *buffer_ref = data; - - meta_wayland_buffer_ref_dec_use_count (buffer_ref); - meta_wayland_buffer_ref_unref (buffer_ref); -} - -CoglScanout * -meta_wayland_surface_try_acquire_scanout (MetaWaylandSurface *surface, - CoglOnscreen *onscreen) -{ - CoglScanout *scanout; - MetaWaylandBufferRef *buffer_ref; - - if (!surface->buffer_ref->buffer) - return NULL; - - if (surface->buffer_ref->use_count == 0) - return NULL; - - scanout = meta_wayland_buffer_try_acquire_scanout (surface->buffer_ref->buffer, - onscreen); - if (!scanout) - return NULL; - - buffer_ref = meta_wayland_buffer_ref_ref (surface->buffer_ref); - meta_wayland_buffer_ref_inc_use_count (buffer_ref); - g_object_weak_ref (G_OBJECT (scanout), scanout_destroyed, buffer_ref); - - return scanout; -} diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h deleted file mode 100644 index f0153b23b..000000000 --- a/src/wayland/meta-wayland-surface.h +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Copyright (C) 2013 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_WAYLAND_SURFACE_H -#define META_WAYLAND_SURFACE_H - -#include -#include -#include -#include - -#include "backends/meta-monitor-manager-private.h" -#include "clutter/clutter.h" -#include "compositor/meta-shaped-texture-private.h" -#include "compositor/meta-surface-actor.h" -#include "meta/meta-cursor-tracker.h" -#include "wayland/meta-wayland-pointer-constraints.h" -#include "wayland/meta-wayland-types.h" - -#define META_TYPE_WAYLAND_SURFACE (meta_wayland_surface_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandSurface, - meta_wayland_surface, - META, WAYLAND_SURFACE, - GObject); - -#define META_TYPE_WAYLAND_SURFACE_ROLE (meta_wayland_surface_role_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaWaylandSurfaceRole, meta_wayland_surface_role, - META, WAYLAND_SURFACE_ROLE, GObject); - -#define META_TYPE_WAYLAND_SURFACE_STATE (meta_wayland_surface_state_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandSurfaceState, - meta_wayland_surface_state, - META, WAYLAND_SURFACE_STATE, - GObject) - -struct _MetaWaylandSurfaceRoleClass -{ - GObjectClass parent_class; - - void (*assigned) (MetaWaylandSurfaceRole *surface_role); - void (*pre_apply_state) (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending); - void (*apply_state) (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending); - void (*post_apply_state) (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending); - gboolean (*is_on_logical_monitor) (MetaWaylandSurfaceRole *surface_role, - MetaLogicalMonitor *logical_monitor); - MetaWaylandSurface * (*get_toplevel) (MetaWaylandSurfaceRole *surface_role); - gboolean (*should_cache_state) (MetaWaylandSurfaceRole *surface_role); - void (*notify_subsurface_state_changed) (MetaWaylandSurfaceRole *surface_role); - void (*get_relative_coordinates) (MetaWaylandSurfaceRole *surface_role, - float abs_x, - float abs_y, - float *out_sx, - float *out_sy); - MetaWindow * (*get_window) (MetaWaylandSurfaceRole *surface_role); -}; - -struct _MetaWaylandSurfaceState -{ - GObject parent; - - /* wl_surface.attach */ - gboolean newly_attached; - MetaWaylandBuffer *buffer; - gulong buffer_destroy_handler_id; - int32_t dx; - int32_t dy; - - int scale; - - /* wl_surface.damage */ - cairo_region_t *surface_damage; - /* wl_surface.damage_buffer */ - cairo_region_t *buffer_damage; - - cairo_region_t *input_region; - gboolean input_region_set; - cairo_region_t *opaque_region; - gboolean opaque_region_set; - - /* wl_surface.frame */ - struct wl_list frame_callback_list; - - MetaRectangle new_geometry; - gboolean has_new_geometry; - - gboolean has_acked_configure_serial; - uint32_t acked_configure_serial; - - /* pending min/max size in window geometry coordinates */ - gboolean has_new_min_size; - int new_min_width; - int new_min_height; - gboolean has_new_max_size; - int new_max_width; - int new_max_height; - - gboolean has_new_buffer_transform; - MetaMonitorTransform buffer_transform; - gboolean has_new_viewport_src_rect; - graphene_rect_t viewport_src_rect; - gboolean has_new_viewport_dst_size; - int viewport_dst_width; - int viewport_dst_height; - - GSList *subsurface_placement_ops; - - /* presentation-time */ - struct wl_list presentation_feedback_list; -}; - -struct _MetaWaylandDragDestFuncs -{ - void (* focus_in) (MetaWaylandDataDevice *data_device, - MetaWaylandSurface *surface, - MetaWaylandDataOffer *offer); - void (* focus_out) (MetaWaylandDataDevice *data_device, - MetaWaylandSurface *surface); - void (* motion) (MetaWaylandDataDevice *data_device, - MetaWaylandSurface *surface, - const ClutterEvent *event); - void (* drop) (MetaWaylandDataDevice *data_device, - MetaWaylandSurface *surface); - void (* update) (MetaWaylandDataDevice *data_device, - MetaWaylandSurface *surface); -}; - -typedef struct _MetaWaylandBufferRef -{ - grefcount ref_count; - MetaWaylandBuffer *buffer; - unsigned int use_count; -} MetaWaylandBufferRef; - -struct _MetaWaylandSurface -{ - GObject parent; - - /* Generic stuff */ - struct wl_resource *resource; - MetaWaylandCompositor *compositor; - MetaWaylandSurfaceRole *role; - cairo_region_t *input_region; - cairo_region_t *opaque_region; - int scale; - int32_t offset_x, offset_y; - GNode *subsurface_branch_node; - GNode *subsurface_leaf_node; - GHashTable *outputs; - MetaMonitorTransform buffer_transform; - - CoglTexture *texture; - - /* Buffer reference state. */ - MetaWaylandBufferRef *buffer_ref; - - /* Buffer renderer state. */ - gboolean buffer_held; - - /* Intermediate state for when no role has been assigned. */ - struct { - struct wl_list pending_frame_callback_list; - MetaWaylandBuffer *buffer; - } unassigned; - - struct { - const MetaWaylandDragDestFuncs *funcs; - } dnd; - - /* All the pending state that wl_surface.commit will apply. */ - MetaWaylandSurfaceState *pending_state; - /* State cached due to inter-surface synchronization such. */ - MetaWaylandSurfaceState *cached_state; - - /* Extension resources. */ - struct wl_resource *wl_subsurface; - - /* wl_subsurface stuff. */ - struct { - MetaWaylandSurface *parent; - struct wl_listener parent_destroy_listener; - - int x; - int y; - - /* When the surface is synchronous, its state will be applied - * when the parent is committed. This is done by moving the - * "real" pending state below to here when this surface is - * committed and in synchronous mode. - * - * When the parent surface is committed, we apply the pending - * state here. - */ - gboolean synchronous; - - int32_t pending_x; - int32_t pending_y; - gboolean pending_pos; - } sub; - - /* wp_viewport */ - struct { - struct wl_resource *resource; - gulong destroy_handler_id; - - gboolean has_src_rect; - graphene_rect_t src_rect; - - gboolean has_dst_size; - int dst_width; - int dst_height; - } viewport; - - /* table of seats for which shortcuts are inhibited */ - GHashTable *shortcut_inhibited_seats; - - /* presentation-time */ - struct { - struct wl_list feedback_list; - MetaWaylandOutput *last_output; - unsigned int last_output_sequence; - gboolean is_last_output_sequence_valid; - gboolean needs_sequence_update; - - /* - * Sequence has an undefined base, but is guaranteed to monotonically - * increase. DRM only gives us a 32-bit sequence, so we compute our own - * delta to update our own 64-bit sequence. - */ - uint64_t sequence; - } presentation_time; -}; - -void meta_wayland_shell_init (MetaWaylandCompositor *compositor); - -MetaWaylandSurface *meta_wayland_surface_create (MetaWaylandCompositor *compositor, - struct wl_client *client, - struct wl_resource *compositor_resource, - guint32 id); - -MetaWaylandSurfaceState * - meta_wayland_surface_get_pending_state (MetaWaylandSurface *surface); - -MetaWaylandSurfaceState * - meta_wayland_surface_ensure_cached_state (MetaWaylandSurface *surface); - -void meta_wayland_surface_apply_cached_state (MetaWaylandSurface *surface); - -gboolean meta_wayland_surface_is_effectively_synchronized (MetaWaylandSurface *surface); - -gboolean meta_wayland_surface_assign_role (MetaWaylandSurface *surface, - GType role_type, - const char *first_property_name, - ...); - -MetaWaylandBuffer *meta_wayland_surface_get_buffer (MetaWaylandSurface *surface); - -void meta_wayland_surface_ref_buffer_use_count (MetaWaylandSurface *surface); - -void meta_wayland_surface_unref_buffer_use_count (MetaWaylandSurface *surface); - -void meta_wayland_surface_set_window (MetaWaylandSurface *surface, - MetaWindow *window); - -void meta_wayland_surface_configure_notify (MetaWaylandSurface *surface, - MetaWaylandWindowConfiguration *configuration); - -void meta_wayland_surface_ping (MetaWaylandSurface *surface, - guint32 serial); -void meta_wayland_surface_delete (MetaWaylandSurface *surface); - -/* Drag dest functions */ -void meta_wayland_surface_drag_dest_focus_in (MetaWaylandSurface *surface, - MetaWaylandDataOffer *offer); -void meta_wayland_surface_drag_dest_motion (MetaWaylandSurface *surface, - const ClutterEvent *event); -void meta_wayland_surface_drag_dest_focus_out (MetaWaylandSurface *surface); -void meta_wayland_surface_drag_dest_drop (MetaWaylandSurface *surface); -void meta_wayland_surface_drag_dest_update (MetaWaylandSurface *surface); - -void meta_wayland_surface_update_outputs (MetaWaylandSurface *surface); - -MetaWaylandSurface *meta_wayland_surface_get_toplevel (MetaWaylandSurface *surface); - -MetaWindow * meta_wayland_surface_get_window (MetaWaylandSurface *surface); - -gboolean meta_wayland_surface_should_cache_state (MetaWaylandSurface *surface); - -MetaWindow * meta_wayland_surface_get_toplevel_window (MetaWaylandSurface *surface); - -void meta_wayland_surface_queue_pending_frame_callbacks (MetaWaylandSurface *surface); - -void meta_wayland_surface_queue_pending_state_frame_callbacks (MetaWaylandSurface *surface, - MetaWaylandSurfaceState *pending); - -void meta_wayland_surface_get_relative_coordinates (MetaWaylandSurface *surface, - float abs_x, - float abs_y, - float *sx, - float *sy); - -void meta_wayland_surface_get_absolute_coordinates (MetaWaylandSurface *surface, - float sx, - float sy, - float *x, - float *y); - -MetaWaylandSurface * meta_wayland_surface_role_get_surface (MetaWaylandSurfaceRole *role); - -cairo_region_t * meta_wayland_surface_calculate_input_region (MetaWaylandSurface *surface); - - -gboolean meta_wayland_surface_begin_grab_op (MetaWaylandSurface *surface, - MetaWaylandSeat *seat, - MetaGrabOp grab_op, - gfloat x, - gfloat y); - -void meta_wayland_surface_window_managed (MetaWaylandSurface *surface, - MetaWindow *window); - -void meta_wayland_surface_inhibit_shortcuts (MetaWaylandSurface *surface, - MetaWaylandSeat *seat); - -void meta_wayland_surface_restore_shortcuts (MetaWaylandSurface *surface, - MetaWaylandSeat *seat); - -gboolean meta_wayland_surface_is_shortcuts_inhibited (MetaWaylandSurface *surface, - MetaWaylandSeat *seat); - -CoglTexture * meta_wayland_surface_get_texture (MetaWaylandSurface *surface); - -MetaSurfaceActor * meta_wayland_surface_get_actor (MetaWaylandSurface *surface); - -void meta_wayland_surface_notify_geometry_changed (MetaWaylandSurface *surface); - -void meta_wayland_surface_notify_subsurface_state_changed (MetaWaylandSurface *surface); - -void meta_wayland_surface_notify_unmapped (MetaWaylandSurface *surface); - -int meta_wayland_surface_get_width (MetaWaylandSurface *surface); -int meta_wayland_surface_get_height (MetaWaylandSurface *surface); - -CoglScanout * meta_wayland_surface_try_acquire_scanout (MetaWaylandSurface *surface, - CoglOnscreen *onscreen); - -static inline GNode * -meta_get_next_subsurface_sibling (GNode *n) -{ - GNode *next; - - if (!n) - return NULL; - - next = g_node_next_sibling (n); - if (!next) - return NULL; - if (!G_NODE_IS_LEAF (next)) - return next; - else - return meta_get_next_subsurface_sibling (next); -} - -static inline GNode * -meta_get_first_subsurface_node (MetaWaylandSurface *surface) -{ - GNode *n; - - n = g_node_first_child (surface->subsurface_branch_node); - if (!G_NODE_IS_LEAF (n)) - return n; - else - return meta_get_next_subsurface_sibling (n); -} - -#define META_WAYLAND_SURFACE_FOREACH_SUBSURFACE(surface, subsurface) \ - for (GNode *G_PASTE(__n, __LINE__) = meta_get_first_subsurface_node ((surface)); \ - (subsurface = (G_PASTE (__n, __LINE__) ? G_PASTE (__n, __LINE__)->data : NULL)); \ - G_PASTE (__n, __LINE__) = meta_get_next_subsurface_sibling (G_PASTE (__n, __LINE__))) - -#endif diff --git a/src/wayland/meta-wayland-tablet-cursor-surface.c b/src/wayland/meta-wayland-tablet-cursor-surface.c deleted file mode 100644 index 421b7c20a..000000000 --- a/src/wayland/meta-wayland-tablet-cursor-surface.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2016 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include "config.h" - -#include "wayland/meta-wayland-tablet-cursor-surface.h" - -struct _MetaWaylandTabletCursorSurface -{ - MetaWaylandCursorSurface parent; -}; - -G_DEFINE_TYPE (MetaWaylandTabletCursorSurface, - meta_wayland_tablet_cursor_surface, - META_TYPE_WAYLAND_CURSOR_SURFACE) - -static void -meta_wayland_tablet_cursor_surface_init (MetaWaylandTabletCursorSurface *role) -{ -} - -static void -meta_wayland_tablet_cursor_surface_class_init (MetaWaylandTabletCursorSurfaceClass *klass) -{ -} diff --git a/src/wayland/meta-wayland-tablet-cursor-surface.h b/src/wayland/meta-wayland-tablet-cursor-surface.h deleted file mode 100644 index df41e832e..000000000 --- a/src/wayland/meta-wayland-tablet-cursor-surface.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2016 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_WAYLAND_TABLET_CURSOR_SURFACE_H -#define META_WAYLAND_TABLET_CURSOR_SURFACE_H - -#include "wayland/meta-wayland-cursor-surface.h" - -#define META_TYPE_WAYLAND_TABLET_CURSOR_SURFACE (meta_wayland_tablet_cursor_surface_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandTabletCursorSurface, - meta_wayland_tablet_cursor_surface, - META, WAYLAND_TABLET_CURSOR_SURFACE, - MetaWaylandCursorSurface) - -#endif /* META_WAYLAND_TABLET_CURSOR_SURFACE_H */ diff --git a/src/wayland/meta-wayland-tablet-manager.c b/src/wayland/meta-wayland-tablet-manager.c deleted file mode 100644 index a729c7b89..000000000 --- a/src/wayland/meta-wayland-tablet-manager.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2015 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: Carlos Garnacho - */ - -#include "config.h" - -#include - -#include - -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-tablet-manager.h" -#include "wayland/meta-wayland-tablet-seat.h" -#include "wayland/meta-wayland-tablet-tool.h" - -#include "tablet-unstable-v2-server-protocol.h" - -static void -unbind_resource (struct wl_resource *resource) -{ - wl_list_remove (wl_resource_get_link (resource)); -} - -static gboolean -is_tablet_device (ClutterInputDevice *device) -{ - ClutterInputDeviceType device_type; - - if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_LOGICAL) - return FALSE; - - device_type = clutter_input_device_get_device_type (device); - - return (device_type == CLUTTER_TABLET_DEVICE || - device_type == CLUTTER_PEN_DEVICE || - device_type == CLUTTER_ERASER_DEVICE || - device_type == CLUTTER_CURSOR_DEVICE || - device_type == CLUTTER_PAD_DEVICE); -} - -static void -tablet_manager_get_tablet_seat (struct wl_client *client, - struct wl_resource *resource, - guint32 id, - struct wl_resource *seat_resource) -{ - MetaWaylandTabletManager *tablet_manager = wl_resource_get_user_data (resource); - MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); - MetaWaylandTabletSeat *tablet_seat; - - tablet_seat = meta_wayland_tablet_manager_ensure_seat (tablet_manager, seat); - meta_wayland_tablet_seat_create_new_resource (tablet_seat, client, - resource, id); -} - -static void -tablet_manager_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static const struct zwp_tablet_manager_v2_interface tablet_manager_interface = { - tablet_manager_get_tablet_seat, - tablet_manager_destroy -}; - -static void -bind_tablet_manager (struct wl_client *client, - void *data, - uint32_t version, - uint32_t id) -{ - MetaWaylandCompositor *compositor = data; - MetaWaylandTabletManager *tablet_manager = compositor->tablet_manager; - struct wl_resource *resource; - - resource = wl_resource_create (client, &zwp_tablet_manager_v2_interface, - MIN (version, 1), id); - wl_resource_set_implementation (resource, &tablet_manager_interface, - tablet_manager, unbind_resource); - wl_resource_set_user_data (resource, tablet_manager); - wl_list_insert (&tablet_manager->resource_list, - wl_resource_get_link (resource)); -} - -static MetaWaylandTabletManager * -meta_wayland_tablet_manager_new (MetaWaylandCompositor *compositor) -{ - MetaWaylandTabletManager *tablet_manager; - - tablet_manager = g_new0 (MetaWaylandTabletManager, 1); - tablet_manager->compositor = compositor; - tablet_manager->wl_display = compositor->wayland_display; - tablet_manager->seats = g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) meta_wayland_tablet_seat_free); - wl_list_init (&tablet_manager->resource_list); - - wl_global_create (tablet_manager->wl_display, - &zwp_tablet_manager_v2_interface, 1, - compositor, bind_tablet_manager); - - return tablet_manager; -} - -void -meta_wayland_tablet_manager_init (MetaWaylandCompositor *compositor) -{ - compositor->tablet_manager = meta_wayland_tablet_manager_new (compositor); -} - -void -meta_wayland_tablet_manager_free (MetaWaylandTabletManager *tablet_manager) -{ - g_hash_table_destroy (tablet_manager->seats); - g_free (tablet_manager); -} - -static MetaWaylandTabletSeat * -meta_wayland_tablet_manager_lookup_seat (MetaWaylandTabletManager *manager, - ClutterInputDevice *device) -{ - MetaWaylandTabletSeat *tablet_seat; - MetaWaylandSeat *seat; - GHashTableIter iter; - - if (!device || !is_tablet_device (device)) - return NULL; - - g_hash_table_iter_init (&iter, manager->seats); - - while (g_hash_table_iter_next (&iter, (gpointer*) &seat, (gpointer*) &tablet_seat)) - { - if (meta_wayland_tablet_seat_lookup_tablet (tablet_seat, device) || - meta_wayland_tablet_seat_lookup_pad (tablet_seat, device)) - return tablet_seat; - } - - return NULL; -} - -gboolean -meta_wayland_tablet_manager_consumes_event (MetaWaylandTabletManager *manager, - const ClutterEvent *event) -{ - ClutterInputDevice *device = clutter_event_get_source_device (event); - - return meta_wayland_tablet_manager_lookup_seat (manager, device) != NULL; -} - -void -meta_wayland_tablet_manager_update (MetaWaylandTabletManager *manager, - const ClutterEvent *event) -{ - ClutterInputDevice *device = clutter_event_get_source_device (event); - MetaWaylandTabletSeat *tablet_seat; - - tablet_seat = meta_wayland_tablet_manager_lookup_seat (manager, device); - - if (!tablet_seat) - return; - - switch (event->type) - { - case CLUTTER_PROXIMITY_IN: - case CLUTTER_PROXIMITY_OUT: - case CLUTTER_BUTTON_PRESS: - case CLUTTER_BUTTON_RELEASE: - case CLUTTER_MOTION: - case CLUTTER_PAD_BUTTON_PRESS: - case CLUTTER_PAD_BUTTON_RELEASE: - case CLUTTER_PAD_RING: - case CLUTTER_PAD_STRIP: - meta_wayland_tablet_seat_update (tablet_seat, event); - break; - default: - break; - } -} - -gboolean -meta_wayland_tablet_manager_handle_event (MetaWaylandTabletManager *manager, - const ClutterEvent *event) -{ - ClutterInputDevice *device = clutter_event_get_source_device (event); - MetaWaylandTabletSeat *tablet_seat; - - tablet_seat = meta_wayland_tablet_manager_lookup_seat (manager, device); - - if (!tablet_seat) - return CLUTTER_EVENT_PROPAGATE; - - switch (event->type) - { - case CLUTTER_PROXIMITY_IN: - case CLUTTER_PROXIMITY_OUT: - case CLUTTER_BUTTON_PRESS: - case CLUTTER_BUTTON_RELEASE: - case CLUTTER_MOTION: - case CLUTTER_PAD_BUTTON_PRESS: - case CLUTTER_PAD_BUTTON_RELEASE: - case CLUTTER_PAD_RING: - case CLUTTER_PAD_STRIP: - return meta_wayland_tablet_seat_handle_event (tablet_seat, event); - default: - return CLUTTER_EVENT_PROPAGATE; - } -} - -MetaWaylandTabletSeat * -meta_wayland_tablet_manager_ensure_seat (MetaWaylandTabletManager *manager, - MetaWaylandSeat *seat) -{ - MetaWaylandTabletSeat *tablet_seat; - - tablet_seat = g_hash_table_lookup (manager->seats, seat); - - if (!tablet_seat) - { - tablet_seat = meta_wayland_tablet_seat_new (manager, seat); - g_hash_table_insert (manager->seats, seat, tablet_seat); - } - - return tablet_seat; -} diff --git a/src/wayland/meta-wayland-tablet-manager.h b/src/wayland/meta-wayland-tablet-manager.h deleted file mode 100644 index 83f9d3d0f..000000000 --- a/src/wayland/meta-wayland-tablet-manager.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2015 Red Hat - * - * 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 . - * - * Author: Carlos Garnacho - */ - -#ifndef META_WAYLAND_TABLET_MANAGER_H -#define META_WAYLAND_TABLET_MANAGER_H - -#include -#include - -#include "wayland/meta-wayland-types.h" - -struct _MetaWaylandTabletManager -{ - MetaWaylandCompositor *compositor; - struct wl_display *wl_display; - struct wl_list resource_list; - - GHashTable *seats; -}; - -void meta_wayland_tablet_manager_init (MetaWaylandCompositor *compositor); -void meta_wayland_tablet_manager_free (MetaWaylandTabletManager *tablet_manager); - -gboolean meta_wayland_tablet_manager_consumes_event (MetaWaylandTabletManager *manager, - const ClutterEvent *event); -void meta_wayland_tablet_manager_update (MetaWaylandTabletManager *manager, - const ClutterEvent *event); -gboolean meta_wayland_tablet_manager_handle_event (MetaWaylandTabletManager *manager, - const ClutterEvent *event); - -MetaWaylandTabletSeat * - meta_wayland_tablet_manager_ensure_seat (MetaWaylandTabletManager *manager, - MetaWaylandSeat *seat); - -#endif /* META_WAYLAND_TABLET_MANAGER_H */ diff --git a/src/wayland/meta-wayland-tablet-pad-group.c b/src/wayland/meta-wayland-tablet-pad-group.c deleted file mode 100644 index 281651588..000000000 --- a/src/wayland/meta-wayland-tablet-pad-group.c +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2016 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: Carlos Garnacho - */ - -#include "config.h" - -#include - -#include "compositor/meta-surface-actor-wayland.h" -#include "wayland/meta-wayland-tablet-pad-group.h" -#include "wayland/meta-wayland-tablet-pad-ring.h" -#include "wayland/meta-wayland-tablet-pad-strip.h" -#include "wayland/meta-wayland-tablet-pad.h" -#include "wayland/meta-wayland-tablet-seat.h" - -#include "tablet-unstable-v2-server-protocol.h" - -static void -unbind_resource (struct wl_resource *resource) -{ - wl_list_remove (wl_resource_get_link (resource)); -} - -MetaWaylandTabletPadGroup * -meta_wayland_tablet_pad_group_new (MetaWaylandTabletPad *pad) -{ - MetaWaylandTabletPadGroup *group; - - group = g_new0 (MetaWaylandTabletPadGroup, 1); - wl_list_init (&group->resource_list); - wl_list_init (&group->focus_resource_list); - group->pad = pad; - - return group; -} - -void -meta_wayland_tablet_pad_group_free (MetaWaylandTabletPadGroup *group) -{ - struct wl_resource *resource, *next; - - wl_resource_for_each_safe (resource, next, &group->resource_list) - { - wl_list_remove (wl_resource_get_link (resource)); - wl_list_init (wl_resource_get_link (resource)); - } - - g_list_free (group->rings); - g_list_free (group->strips); - - g_free (group); -} - -static void -tablet_pad_group_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static const struct zwp_tablet_pad_group_v2_interface group_interface = { - tablet_pad_group_destroy -}; - -struct wl_resource * -meta_wayland_tablet_pad_group_create_new_resource (MetaWaylandTabletPadGroup *group, - struct wl_client *client, - struct wl_resource *pad_resource, - uint32_t id) -{ - struct wl_resource *resource; - - resource = wl_resource_create (client, &zwp_tablet_pad_group_v2_interface, - wl_resource_get_version (pad_resource), id); - wl_resource_set_implementation (resource, &group_interface, - group, unbind_resource); - wl_resource_set_user_data (resource, group); - wl_list_insert (&group->resource_list, wl_resource_get_link (resource)); - - return resource; -} - -struct wl_resource * -meta_wayland_tablet_pad_group_lookup_resource (MetaWaylandTabletPadGroup *group, - struct wl_client *client) -{ - struct wl_resource *resource; - - resource = wl_resource_find_for_client (&group->resource_list, client); - - if (!resource) - resource = wl_resource_find_for_client (&group->focus_resource_list, client); - - return resource; -} - -gboolean -meta_wayland_tablet_pad_group_has_button (MetaWaylandTabletPadGroup *group, - guint button) -{ - int n_group = g_list_index (group->pad->groups, group); - - if (clutter_input_device_get_pad_feature_group (group->pad->device, - CLUTTER_PAD_FEATURE_BUTTON, - button) == n_group) - return TRUE; - - return FALSE; -} - -static void -meta_wayland_tablet_pad_group_send_buttons (MetaWaylandTabletPadGroup *group, - struct wl_resource *resource) -{ - struct wl_array buttons; - guint i; - - wl_array_init (&buttons); - - for (i = 0; i < group->pad->n_buttons; i++) - { - uint32_t *pos; - - if (!meta_wayland_tablet_pad_group_has_button (group, i)) - continue; - - pos = wl_array_add (&buttons, sizeof (*pos)); - *pos = i; - } - - zwp_tablet_pad_group_v2_send_buttons (resource, &buttons); - wl_array_release (&buttons); -} - -void -meta_wayland_tablet_pad_group_notify (MetaWaylandTabletPadGroup *group, - struct wl_resource *resource) -{ - struct wl_client *client = wl_resource_get_client (resource); - struct wl_array buttons; - guint n_group, n_modes; - GList *l; - - wl_array_init (&buttons); - - /* Buttons */ - meta_wayland_tablet_pad_group_send_buttons (group, resource); - - /* Rings */ - for (l = group->rings; l; l = l->next) - { - MetaWaylandTabletPadRing *ring = l->data; - struct wl_resource *ring_resource; - - ring_resource = meta_wayland_tablet_pad_ring_create_new_resource (ring, - client, - resource, - 0); - zwp_tablet_pad_group_v2_send_ring (resource, ring_resource); - } - - /* Strips */ - for (l = group->strips; l; l = l->next) - { - MetaWaylandTabletPadStrip *strip = l->data; - struct wl_resource *strip_resource; - - strip_resource = meta_wayland_tablet_pad_strip_create_new_resource (strip, - client, - resource, - 0); - zwp_tablet_pad_group_v2_send_strip (resource, strip_resource); - } - - n_group = g_list_index (group->pad->groups, group); - n_modes = clutter_input_device_get_group_n_modes (group->pad->device, - n_group); - - zwp_tablet_pad_group_v2_send_modes (resource, n_modes); - zwp_tablet_pad_group_v2_send_done (resource); -} - -void -meta_wayland_tablet_pad_group_update (MetaWaylandTabletPadGroup *group, - const ClutterEvent *event) -{ - switch (event->type) - { - case CLUTTER_PAD_BUTTON_PRESS: - case CLUTTER_PAD_BUTTON_RELEASE: - if (meta_wayland_tablet_pad_group_is_mode_switch_button (group, event->pad_button.button)) - group->current_mode = event->pad_button.mode; - break; - default: - break; - } -} - -static gboolean -handle_pad_ring_event (MetaWaylandTabletPadGroup *group, - const ClutterEvent *event) -{ - MetaWaylandTabletPadRing *ring; - - if (event->type != CLUTTER_PAD_RING) - return FALSE; - - ring = g_list_nth_data (group->rings, event->pad_ring.ring_number); - - if (!ring) - return FALSE; - - return meta_wayland_tablet_pad_ring_handle_event (ring, event); -} - -static gboolean -handle_pad_strip_event (MetaWaylandTabletPadGroup *group, - const ClutterEvent *event) -{ - MetaWaylandTabletPadStrip *strip; - - if (event->type != CLUTTER_PAD_STRIP) - return FALSE; - - strip = g_list_nth_data (group->strips, event->pad_strip.strip_number); - - if (!strip) - return FALSE; - - return meta_wayland_tablet_pad_strip_handle_event (strip, event); -} - -static void -broadcast_group_mode (MetaWaylandTabletPadGroup *group, - uint32_t time) -{ - struct wl_display *display = group->pad->tablet_seat->seat->wl_display; - struct wl_resource *resource; - - group->mode_switch_serial = wl_display_next_serial (display); - - wl_resource_for_each (resource, &group->focus_resource_list) - { - zwp_tablet_pad_group_v2_send_mode_switch (resource, time, - group->mode_switch_serial, - group->current_mode); - } -} - -static void -broadcast_group_buttons (MetaWaylandTabletPadGroup *group) -{ - struct wl_resource *resource; - - wl_resource_for_each (resource, &group->focus_resource_list) - { - meta_wayland_tablet_pad_group_send_buttons (group, resource); - } -} - -gboolean -meta_wayland_tablet_pad_group_handle_event (MetaWaylandTabletPadGroup *group, - const ClutterEvent *event) -{ - switch (clutter_event_type (event)) - { - case CLUTTER_PAD_BUTTON_PRESS: - case CLUTTER_PAD_BUTTON_RELEASE: - if (meta_wayland_tablet_pad_group_is_mode_switch_button (group, event->pad_button.button)) - { - if (event->type == CLUTTER_PAD_BUTTON_PRESS) - broadcast_group_mode (group, clutter_event_get_time (event)); - return TRUE; - } - else - { - return FALSE; - } - break; - case CLUTTER_PAD_RING: - return handle_pad_ring_event (group, event); - case CLUTTER_PAD_STRIP: - return handle_pad_strip_event (group, event); - default: - return FALSE; - } -} - -static void -meta_wayland_tablet_pad_group_update_rings_focus (MetaWaylandTabletPadGroup *group) -{ - GList *l; - - for (l = group->rings; l; l = l->next) - meta_wayland_tablet_pad_ring_sync_focus (l->data); -} - -static void -meta_wayland_tablet_pad_group_update_strips_focus (MetaWaylandTabletPadGroup *group) -{ - GList *l; - - for (l = group->strips; l; l = l->next) - meta_wayland_tablet_pad_strip_sync_focus (l->data); -} - -static void -move_resources (struct wl_list *destination, struct wl_list *source) -{ - wl_list_insert_list (destination, source); - wl_list_init (source); -} - -static void -move_resources_for_client (struct wl_list *destination, - struct wl_list *source, - struct wl_client *client) -{ - struct wl_resource *resource, *tmp; - - wl_resource_for_each_safe (resource, tmp, source) - { - if (wl_resource_get_client (resource) == client) - { - wl_list_remove (wl_resource_get_link (resource)); - wl_list_insert (destination, wl_resource_get_link (resource)); - } - } -} - -void -meta_wayland_tablet_pad_group_sync_focus (MetaWaylandTabletPadGroup *group) -{ - if (!wl_list_empty (&group->focus_resource_list)) - { - move_resources (&group->resource_list, &group->focus_resource_list); - } - - if (group->pad->focus_surface != NULL) - { - move_resources_for_client (&group->focus_resource_list, - &group->resource_list, - wl_resource_get_client (group->pad->focus_surface->resource)); - } - - meta_wayland_tablet_pad_group_update_rings_focus (group); - meta_wayland_tablet_pad_group_update_strips_focus (group); - - if (!wl_list_empty (&group->focus_resource_list)) - { - broadcast_group_mode (group, clutter_get_current_event_time ()); - broadcast_group_buttons (group); - } -} - -gboolean -meta_wayland_tablet_pad_group_is_mode_switch_button (MetaWaylandTabletPadGroup *group, - guint button) -{ - gint n_group = g_list_index (group->pad->groups, group); - - g_assert (n_group >= 0); - - return clutter_input_device_is_mode_switch_button (group->pad->device, - n_group, button); -} diff --git a/src/wayland/meta-wayland-tablet-pad-group.h b/src/wayland/meta-wayland-tablet-pad-group.h deleted file mode 100644 index 0df3cc1f8..000000000 --- a/src/wayland/meta-wayland-tablet-pad-group.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2016 Red Hat - * - * 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 . - * - * Author: Carlos Garnacho - */ - -#ifndef META_WAYLAND_TABLET_PAD_GROUP_H -#define META_WAYLAND_TABLET_PAD_GROUP_H - -#include -#include - -#include "clutter/clutter.h" -#include "wayland/meta-wayland-types.h" - -struct _MetaWaylandTabletPadGroup -{ - MetaWaylandTabletPad *pad; - GArray *buttons; - uint32_t n_modes; - uint32_t current_mode; - - struct wl_list resource_list; - struct wl_list focus_resource_list; - uint32_t mode_switch_serial; - - GList *strips; - GList *rings; -}; - -MetaWaylandTabletPadGroup * meta_wayland_tablet_pad_group_new (MetaWaylandTabletPad *pad); -void meta_wayland_tablet_pad_group_free (MetaWaylandTabletPadGroup *group); - -struct wl_resource * - meta_wayland_tablet_pad_group_create_new_resource (MetaWaylandTabletPadGroup *group, - struct wl_client *client, - struct wl_resource *pad_resource, - uint32_t id); -struct wl_resource * - meta_wayland_tablet_pad_group_lookup_resource (MetaWaylandTabletPadGroup *group, - struct wl_client *client); - -void meta_wayland_tablet_pad_group_notify (MetaWaylandTabletPadGroup *group, - struct wl_resource *resource); - -void meta_wayland_tablet_pad_group_update (MetaWaylandTabletPadGroup *group, - const ClutterEvent *event); -gboolean meta_wayland_tablet_pad_group_handle_event (MetaWaylandTabletPadGroup *group, - const ClutterEvent *event); - -void meta_wayland_tablet_pad_group_sync_focus (MetaWaylandTabletPadGroup *group); - -gboolean meta_wayland_tablet_pad_group_has_button (MetaWaylandTabletPadGroup *group, - guint button); -gboolean meta_wayland_tablet_pad_group_is_mode_switch_button (MetaWaylandTabletPadGroup *group, - guint button); - -#endif /* META_WAYLAND_TABLET_PAD_GROUP_H */ diff --git a/src/wayland/meta-wayland-tablet-pad-ring.c b/src/wayland/meta-wayland-tablet-pad-ring.c deleted file mode 100644 index 55e45eaa2..000000000 --- a/src/wayland/meta-wayland-tablet-pad-ring.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2016 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: Carlos Garnacho - */ - -#include "config.h" - -#include "wayland/meta-wayland-tablet-pad-ring.h" - -#include -#include - -#include "compositor/meta-surface-actor-wayland.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-tablet-pad.h" -#include "wayland/meta-wayland-tablet-pad-group.h" - -#include "tablet-unstable-v2-server-protocol.h" - -static void -unbind_resource (struct wl_resource *resource) -{ - wl_list_remove (wl_resource_get_link (resource)); -} - -MetaWaylandTabletPadRing * -meta_wayland_tablet_pad_ring_new (MetaWaylandTabletPad *pad) -{ - MetaWaylandTabletPadRing *ring; - - ring = g_new0 (MetaWaylandTabletPadRing, 1); - wl_list_init (&ring->resource_list); - wl_list_init (&ring->focus_resource_list); - ring->pad = pad; - - return ring; -} - -void -meta_wayland_tablet_pad_ring_free (MetaWaylandTabletPadRing *ring) -{ - struct wl_resource *resource, *next; - - wl_resource_for_each_safe (resource, next, &ring->resource_list) - { - wl_list_remove (wl_resource_get_link (resource)); - wl_list_init (wl_resource_get_link (resource)); - } - - g_free (ring->feedback); - g_free (ring); -} - -static void -tablet_pad_ring_set_feedback (struct wl_client *client, - struct wl_resource *resource, - const char *str, - uint32_t serial) -{ - MetaWaylandTabletPadRing *ring = wl_resource_get_user_data (resource); - - if (ring->group->mode_switch_serial != serial) - return; - - ring->feedback = g_strdup (str); -} - -static void -tablet_pad_ring_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static const struct zwp_tablet_pad_ring_v2_interface ring_interface = { - tablet_pad_ring_set_feedback, - tablet_pad_ring_destroy, -}; - -struct wl_resource * -meta_wayland_tablet_pad_ring_create_new_resource (MetaWaylandTabletPadRing *ring, - struct wl_client *client, - struct wl_resource *group_resource, - uint32_t id) -{ - struct wl_resource *resource; - - resource = wl_resource_create (client, &zwp_tablet_pad_ring_v2_interface, - wl_resource_get_version (group_resource), id); - wl_resource_set_implementation (resource, &ring_interface, - ring, unbind_resource); - wl_resource_set_user_data (resource, ring); - wl_list_insert (&ring->resource_list, wl_resource_get_link (resource)); - - return resource; -} - -gboolean -meta_wayland_tablet_pad_ring_handle_event (MetaWaylandTabletPadRing *ring, - const ClutterEvent *event) -{ - struct wl_list *focus_resources = &ring->focus_resource_list; - enum zwp_tablet_pad_ring_v2_source source; - gboolean source_known = FALSE; - struct wl_resource *resource; - - if (wl_list_empty (focus_resources)) - return FALSE; - if (event->type != CLUTTER_PAD_RING) - return FALSE; - - if (event->pad_ring.ring_source == CLUTTER_INPUT_DEVICE_PAD_SOURCE_FINGER) - { - source = ZWP_TABLET_PAD_RING_V2_SOURCE_FINGER; - source_known = TRUE; - } - - wl_resource_for_each (resource, focus_resources) - { - gdouble angle = event->pad_ring.angle; - - if (source_known) - zwp_tablet_pad_ring_v2_send_source (resource, source); - - if (angle >= 0) - zwp_tablet_pad_ring_v2_send_angle (resource, - wl_fixed_from_double (angle)); - else - zwp_tablet_pad_ring_v2_send_stop (resource); - - zwp_tablet_pad_ring_v2_send_frame (resource, - clutter_event_get_time (event)); - } - - return TRUE; -} - -static void -move_resources (struct wl_list *destination, struct wl_list *source) -{ - wl_list_insert_list (destination, source); - wl_list_init (source); -} - -static void -move_resources_for_client (struct wl_list *destination, - struct wl_list *source, - struct wl_client *client) -{ - struct wl_resource *resource, *tmp; - wl_resource_for_each_safe (resource, tmp, source) - { - if (wl_resource_get_client (resource) == client) - { - wl_list_remove (wl_resource_get_link (resource)); - wl_list_insert (destination, wl_resource_get_link (resource)); - } - } -} - -void -meta_wayland_tablet_pad_ring_sync_focus (MetaWaylandTabletPadRing *ring) -{ - g_clear_pointer (&ring->feedback, g_free); - - if (!wl_list_empty (&ring->focus_resource_list)) - { - move_resources (&ring->resource_list, &ring->focus_resource_list); - } - - if (ring->pad->focus_surface != NULL) - { - move_resources_for_client (&ring->focus_resource_list, - &ring->resource_list, - wl_resource_get_client (ring->pad->focus_surface->resource)); - } -} - -void -meta_wayland_tablet_pad_ring_set_group (MetaWaylandTabletPadRing *ring, - MetaWaylandTabletPadGroup *group) -{ - /* Group is static, can only be set once */ - g_assert (ring->group == NULL); - - ring->group = group; - group->rings = g_list_append (group->rings, ring); -} diff --git a/src/wayland/meta-wayland-tablet-pad-ring.h b/src/wayland/meta-wayland-tablet-pad-ring.h deleted file mode 100644 index 744ba2e84..000000000 --- a/src/wayland/meta-wayland-tablet-pad-ring.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2016 Red Hat - * - * 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 . - * - * Author: Carlos Garnacho - */ - -#ifndef META_WAYLAND_TABLET_PAD_RING_H -#define META_WAYLAND_TABLET_PAD_RING_H - -#include -#include - -#include "backends/meta-cursor-renderer.h" -#include "wayland/meta-wayland-types.h" - -struct _MetaWaylandTabletPadRing -{ - MetaWaylandTabletPad *pad; - MetaWaylandTabletPadGroup *group; - - struct wl_list resource_list; - struct wl_list focus_resource_list; - - gchar *feedback; -}; - -MetaWaylandTabletPadRing * meta_wayland_tablet_pad_ring_new (MetaWaylandTabletPad *pad); -void meta_wayland_tablet_pad_ring_free (MetaWaylandTabletPadRing *ring); - -void meta_wayland_tablet_pad_ring_set_group (MetaWaylandTabletPadRing *ring, - MetaWaylandTabletPadGroup *group); -struct wl_resource * - meta_wayland_tablet_pad_ring_create_new_resource (MetaWaylandTabletPadRing *ring, - struct wl_client *client, - struct wl_resource *group_resource, - uint32_t id); - -gboolean meta_wayland_tablet_pad_ring_handle_event (MetaWaylandTabletPadRing *ring, - const ClutterEvent *event); - -void meta_wayland_tablet_pad_ring_sync_focus (MetaWaylandTabletPadRing *ring); - -#endif /* META_WAYLAND_TABLET_PAD_RING_H */ - diff --git a/src/wayland/meta-wayland-tablet-pad-strip.c b/src/wayland/meta-wayland-tablet-pad-strip.c deleted file mode 100644 index b320dbf80..000000000 --- a/src/wayland/meta-wayland-tablet-pad-strip.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2016 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: Carlos Garnacho - */ - -#include "config.h" - -#include "wayland/meta-wayland-tablet-pad-strip.h" - -#include -#include - -#include "compositor/meta-surface-actor-wayland.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-tablet-pad.h" -#include "wayland/meta-wayland-tablet-pad-group.h" - -#include "tablet-unstable-v2-server-protocol.h" - -static void -unbind_resource (struct wl_resource *resource) -{ - wl_list_remove (wl_resource_get_link (resource)); -} - -MetaWaylandTabletPadStrip * -meta_wayland_tablet_pad_strip_new (MetaWaylandTabletPad *pad) -{ - MetaWaylandTabletPadStrip *strip; - - strip = g_new0 (MetaWaylandTabletPadStrip, 1); - wl_list_init (&strip->resource_list); - wl_list_init (&strip->focus_resource_list); - strip->pad = pad; - - return strip; -} - -void -meta_wayland_tablet_pad_strip_free (MetaWaylandTabletPadStrip *strip) -{ - struct wl_resource *resource, *next; - - wl_resource_for_each_safe (resource, next, &strip->resource_list) - { - wl_list_remove (wl_resource_get_link (resource)); - wl_list_init (wl_resource_get_link (resource)); - } - - g_free (strip->feedback); - g_free (strip); -} - -static void -tablet_pad_strip_set_feedback (struct wl_client *client, - struct wl_resource *resource, - const char *str, - uint32_t serial) -{ - MetaWaylandTabletPadStrip *strip = wl_resource_get_user_data (resource); - - if (strip->group->mode_switch_serial != serial) - return; - - strip->feedback = g_strdup (str); -} - -static void -tablet_pad_strip_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static const struct zwp_tablet_pad_strip_v2_interface strip_interface = { - tablet_pad_strip_set_feedback, - tablet_pad_strip_destroy, -}; - -struct wl_resource * -meta_wayland_tablet_pad_strip_create_new_resource (MetaWaylandTabletPadStrip *strip, - struct wl_client *client, - struct wl_resource *group_resource, - uint32_t id) -{ - struct wl_resource *resource; - - resource = wl_resource_create (client, &zwp_tablet_pad_strip_v2_interface, - wl_resource_get_version (group_resource), id); - wl_resource_set_implementation (resource, &strip_interface, - strip, unbind_resource); - wl_resource_set_user_data (resource, strip); - wl_list_insert (&strip->resource_list, wl_resource_get_link (resource)); - - return resource; -} - -gboolean -meta_wayland_tablet_pad_strip_handle_event (MetaWaylandTabletPadStrip *strip, - const ClutterEvent *event) -{ - struct wl_list *focus_resources = &strip->focus_resource_list; - enum zwp_tablet_pad_strip_v2_source source; - gboolean source_known = FALSE; - struct wl_resource *resource; - - if (wl_list_empty (focus_resources)) - return FALSE; - if (event->type != CLUTTER_PAD_STRIP) - return FALSE; - - if (event->pad_strip.strip_source == CLUTTER_INPUT_DEVICE_PAD_SOURCE_FINGER) - { - source = ZWP_TABLET_PAD_STRIP_V2_SOURCE_FINGER; - source_known = TRUE; - } - - wl_resource_for_each (resource, focus_resources) - { - gdouble value = event->pad_strip.value; - - if (source_known) - zwp_tablet_pad_strip_v2_send_source (resource, source); - - if (value >= 0) - zwp_tablet_pad_strip_v2_send_position (resource, (uint32_t) (value * 65535)); - else - zwp_tablet_pad_strip_v2_send_stop (resource); - - zwp_tablet_pad_strip_v2_send_frame (resource, - clutter_event_get_time (event)); - } - - return TRUE; -} - -static void -move_resources (struct wl_list *destination, struct wl_list *source) -{ - wl_list_insert_list (destination, source); - wl_list_init (source); -} - -static void -move_resources_for_client (struct wl_list *destination, - struct wl_list *source, - struct wl_client *client) -{ - struct wl_resource *resource, *tmp; - wl_resource_for_each_safe (resource, tmp, source) - { - if (wl_resource_get_client (resource) == client) - { - wl_list_remove (wl_resource_get_link (resource)); - wl_list_insert (destination, wl_resource_get_link (resource)); - } - } -} - -void -meta_wayland_tablet_pad_strip_sync_focus (MetaWaylandTabletPadStrip *strip) -{ - g_clear_pointer (&strip->feedback, g_free); - - if (!wl_list_empty (&strip->focus_resource_list)) - { - move_resources (&strip->resource_list, &strip->focus_resource_list); - } - - if (strip->pad->focus_surface != NULL) - { - move_resources_for_client (&strip->focus_resource_list, - &strip->resource_list, - wl_resource_get_client (strip->pad->focus_surface->resource)); - } -} - -void -meta_wayland_tablet_pad_strip_set_group (MetaWaylandTabletPadStrip *strip, - MetaWaylandTabletPadGroup *group) -{ - /* Group is static, can only be set once */ - g_assert (strip->group == NULL); - - strip->group = group; - group->strips = g_list_append (group->strips, strip); -} diff --git a/src/wayland/meta-wayland-tablet-pad-strip.h b/src/wayland/meta-wayland-tablet-pad-strip.h deleted file mode 100644 index 9d69de4eb..000000000 --- a/src/wayland/meta-wayland-tablet-pad-strip.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2016 Red Hat - * - * 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 . - * - * Author: Carlos Garnacho - */ - -#ifndef META_WAYLAND_TABLET_PAD_STRIP_H -#define META_WAYLAND_TABLET_PAD_STRIP_H - -#include -#include - -#include "backends/meta-cursor-renderer.h" -#include "wayland/meta-wayland-types.h" - -struct _MetaWaylandTabletPadStrip -{ - MetaWaylandTabletPad *pad; - MetaWaylandTabletPadGroup *group; - - struct wl_list resource_list; - struct wl_list focus_resource_list; - - gchar *feedback; -}; - -MetaWaylandTabletPadStrip * meta_wayland_tablet_pad_strip_new (MetaWaylandTabletPad *pad); -void meta_wayland_tablet_pad_strip_free (MetaWaylandTabletPadStrip *strip); - -void meta_wayland_tablet_pad_strip_set_group (MetaWaylandTabletPadStrip *strip, - MetaWaylandTabletPadGroup *group); - -struct wl_resource * - meta_wayland_tablet_pad_strip_create_new_resource (MetaWaylandTabletPadStrip *strip, - struct wl_client *client, - struct wl_resource *group_resource, - uint32_t id); - -gboolean meta_wayland_tablet_pad_strip_handle_event (MetaWaylandTabletPadStrip *strip, - const ClutterEvent *event); - -void meta_wayland_tablet_pad_strip_sync_focus (MetaWaylandTabletPadStrip *strip); - -#endif /* META_WAYLAND_TABLET_PAD_STRIP_H */ diff --git a/src/wayland/meta-wayland-tablet-pad.c b/src/wayland/meta-wayland-tablet-pad.c deleted file mode 100644 index c0b408c10..000000000 --- a/src/wayland/meta-wayland-tablet-pad.c +++ /dev/null @@ -1,563 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2016 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: Carlos Garnacho - */ - -#include "config.h" - -#include -#include -#include - -#include "backends/meta-input-settings-private.h" -#include "core/display-private.h" -#include "compositor/meta-surface-actor-wayland.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-tablet-pad-group.h" -#include "wayland/meta-wayland-tablet-pad-ring.h" -#include "wayland/meta-wayland-tablet-pad-strip.h" -#include "wayland/meta-wayland-tablet-pad.h" -#include "wayland/meta-wayland-tablet-seat.h" -#include "wayland/meta-wayland-tablet.h" - -#include "tablet-unstable-v2-server-protocol.h" - -static void -unbind_resource (struct wl_resource *resource) -{ - wl_list_remove (wl_resource_get_link (resource)); -} - -static void -pad_handle_focus_surface_destroy (struct wl_listener *listener, - void *data) -{ - MetaWaylandTabletPad *pad = wl_container_of (listener, pad, focus_surface_listener); - - meta_wayland_tablet_pad_set_focus (pad, NULL); -} - -static void -group_rings_strips (MetaWaylandTabletPad *pad) -{ - gint n_group, n_elem; - GList *g, *l; - - for (n_group = 0, g = pad->groups; g; g = g->next) - { - MetaWaylandTabletPadGroup *group = g->data; - - for (n_elem = 0, l = pad->rings; l; l = l->next) - { - MetaWaylandTabletPadRing *ring = l->data; - - if (clutter_input_device_get_pad_feature_group (pad->device, - CLUTTER_PAD_FEATURE_RING, - n_elem) == n_group) - meta_wayland_tablet_pad_ring_set_group (ring, group); - - n_elem++; - } - - for (n_elem = 0, l = pad->strips; l; l = l->next) - { - MetaWaylandTabletPadStrip *strip = l->data; - - if (clutter_input_device_get_pad_feature_group (pad->device, - CLUTTER_PAD_FEATURE_STRIP, - n_elem) == n_group) - meta_wayland_tablet_pad_strip_set_group (strip, group); - - n_elem++; - } - - n_group++; - } -} - -MetaWaylandTabletPad * -meta_wayland_tablet_pad_new (ClutterInputDevice *device, - MetaWaylandTabletSeat *tablet_seat) -{ - MetaWaylandTabletPad *pad; - guint n_elems, i; - - pad = g_new0 (MetaWaylandTabletPad, 1); - wl_list_init (&pad->resource_list); - wl_list_init (&pad->focus_resource_list); - pad->focus_surface_listener.notify = pad_handle_focus_surface_destroy; - pad->device = device; - pad->tablet_seat = tablet_seat; - - pad->feedback = g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) g_free); - - pad->n_buttons = clutter_input_device_get_n_buttons (device); - - n_elems = clutter_input_device_get_n_mode_groups (pad->device); - - for (i = 0; i < n_elems; i++) - { - pad->groups = g_list_prepend (pad->groups, - meta_wayland_tablet_pad_group_new (pad)); - } - - n_elems = clutter_input_device_get_n_rings (pad->device); - - for (i = 0; i < n_elems; i++) - { - MetaWaylandTabletPadRing *ring; - - ring = meta_wayland_tablet_pad_ring_new (pad); - pad->rings = g_list_prepend (pad->rings, ring); - } - - n_elems = clutter_input_device_get_n_strips (pad->device); - - for (i = 0; i < n_elems; i++) - { - MetaWaylandTabletPadStrip *strip; - - strip = meta_wayland_tablet_pad_strip_new (pad); - pad->strips = g_list_prepend (pad->strips, strip); - } - - group_rings_strips (pad); - - return pad; -} - -void -meta_wayland_tablet_pad_free (MetaWaylandTabletPad *pad) -{ - struct wl_resource *resource, *next; - - meta_wayland_tablet_pad_set_focus (pad, NULL); - - wl_resource_for_each_safe (resource, next, &pad->resource_list) - { - zwp_tablet_pad_v2_send_removed (resource); - wl_list_remove (wl_resource_get_link (resource)); - wl_list_init (wl_resource_get_link (resource)); - } - - g_list_free_full (pad->groups, - (GDestroyNotify) meta_wayland_tablet_pad_group_free); - g_list_free_full (pad->rings, - (GDestroyNotify) meta_wayland_tablet_pad_ring_free); - g_list_free_full (pad->strips, - (GDestroyNotify) meta_wayland_tablet_pad_strip_free); - - g_hash_table_destroy (pad->feedback); - - g_free (pad); -} - -static MetaWaylandTabletPadGroup * -tablet_pad_lookup_button_group (MetaWaylandTabletPad *pad, - guint button) -{ - GList *l; - - for (l = pad->groups; l; l = l->next) - { - MetaWaylandTabletPadGroup *group = l->data; - - if (meta_wayland_tablet_pad_group_has_button (group, button)) - return group; - } - - return NULL; -} - -static void -tablet_pad_set_feedback (struct wl_client *client, - struct wl_resource *resource, - uint32_t button, - const char *str, - uint32_t serial) -{ - MetaWaylandTabletPad *pad = wl_resource_get_user_data (resource); - MetaWaylandTabletPadGroup *group = tablet_pad_lookup_button_group (pad, button); - MetaPadActionMapper *mapper; - - if (!group || group->mode_switch_serial != serial) - return; - - mapper = meta_get_display ()->pad_action_mapper; - - if (meta_pad_action_mapper_is_button_grabbed (mapper, pad->device, button)) - return; - - if (meta_wayland_tablet_pad_group_is_mode_switch_button (group, button)) - return; - - g_hash_table_insert (pad->feedback, GUINT_TO_POINTER (button), g_strdup (str)); -} - -static void -tablet_pad_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static const struct zwp_tablet_pad_v2_interface pad_interface = { - tablet_pad_set_feedback, - tablet_pad_destroy, -}; - -void -meta_wayland_tablet_pad_notify (MetaWaylandTabletPad *pad, - struct wl_resource *resource) -{ - struct wl_client *client = wl_resource_get_client (resource); - const gchar *node_path; - GList *l; - - node_path = clutter_input_device_get_device_node (pad->device); - if (node_path) - zwp_tablet_pad_v2_send_path (resource, node_path); - - zwp_tablet_pad_v2_send_buttons (resource, pad->n_buttons); - - for (l = pad->groups; l; l = l->next) - { - MetaWaylandTabletPadGroup *group = l->data; - struct wl_resource *group_resource; - - group_resource = meta_wayland_tablet_pad_group_create_new_resource (group, - client, - resource, - 0); - zwp_tablet_pad_v2_send_group (resource, group_resource); - meta_wayland_tablet_pad_group_notify (group, group_resource); - } - - zwp_tablet_pad_v2_send_done (resource); -} - -struct wl_resource * -meta_wayland_tablet_pad_create_new_resource (MetaWaylandTabletPad *pad, - struct wl_client *client, - struct wl_resource *seat_resource, - uint32_t id) -{ - struct wl_resource *resource; - - resource = wl_resource_create (client, &zwp_tablet_pad_v2_interface, - wl_resource_get_version (seat_resource), id); - wl_resource_set_implementation (resource, &pad_interface, - pad, unbind_resource); - wl_resource_set_user_data (resource, pad); - wl_list_insert (&pad->resource_list, wl_resource_get_link (resource)); - - return resource; -} - -struct wl_resource * -meta_wayland_tablet_pad_lookup_resource (MetaWaylandTabletPad *pad, - struct wl_client *client) -{ - struct wl_resource *resource; - - resource = wl_resource_find_for_client (&pad->resource_list, client); - - if (!resource) - resource = wl_resource_find_for_client (&pad->focus_resource_list, client); - - return resource; -} - -static gboolean -handle_pad_button_event (MetaWaylandTabletPad *pad, - const ClutterEvent *event) -{ - enum zwp_tablet_pad_v2_button_state button_state; - struct wl_list *focus_resources = &pad->focus_resource_list; - struct wl_resource *resource; - - if (wl_list_empty (focus_resources)) - return FALSE; - - if (event->type == CLUTTER_PAD_BUTTON_PRESS) - button_state = ZWP_TABLET_PAD_V2_BUTTON_STATE_PRESSED; - else if (event->type == CLUTTER_PAD_BUTTON_RELEASE) - button_state = ZWP_TABLET_PAD_V2_BUTTON_STATE_RELEASED; - else - return FALSE; - - wl_resource_for_each (resource, focus_resources) - { - zwp_tablet_pad_v2_send_button (resource, - clutter_event_get_time (event), - event->pad_button.button, button_state); - } - - return TRUE; -} - -static gboolean -meta_wayland_tablet_pad_handle_event_action (MetaWaylandTabletPad *pad, - const ClutterEvent *event) -{ - MetaPadActionMapper *mapper; - ClutterInputDevice *device; - - device = clutter_event_get_source_device (event); - mapper = meta_get_display ()->pad_action_mapper; - - if (meta_pad_action_mapper_is_button_grabbed (mapper, device, - event->pad_button.button)) - return TRUE; - - return FALSE; -} - -gboolean -meta_wayland_tablet_pad_handle_event (MetaWaylandTabletPad *pad, - const ClutterEvent *event) -{ - MetaWaylandTabletPadGroup *group; - gboolean handled = FALSE; - guint n_group; - - n_group = clutter_event_get_mode_group (event); - group = g_list_nth_data (pad->groups, n_group); - - switch (clutter_event_type (event)) - { - case CLUTTER_PAD_BUTTON_PRESS: - case CLUTTER_PAD_BUTTON_RELEASE: - if (group) - handled |= meta_wayland_tablet_pad_group_handle_event (group, event); - - handled |= meta_wayland_tablet_pad_handle_event_action (pad, event); - - if (handled) - return TRUE; - - return handle_pad_button_event (pad, event); - case CLUTTER_PAD_RING: - case CLUTTER_PAD_STRIP: - if (group) - return meta_wayland_tablet_pad_group_handle_event (group, event); - default: - return FALSE; - } -} - -static void -move_resources (struct wl_list *destination, struct wl_list *source) -{ - wl_list_insert_list (destination, source); - wl_list_init (source); -} - -static void -move_resources_for_client (struct wl_list *destination, - struct wl_list *source, - struct wl_client *client) -{ - struct wl_resource *resource, *tmp; - - wl_resource_for_each_safe (resource, tmp, source) - { - if (wl_resource_get_client (resource) == client) - { - wl_list_remove (wl_resource_get_link (resource)); - wl_list_insert (destination, wl_resource_get_link (resource)); - } - } -} - -static void -meta_wayland_tablet_pad_update_groups_focus (MetaWaylandTabletPad *pad) -{ - GList *l; - - for (l = pad->groups; l; l = l->next) - meta_wayland_tablet_pad_group_sync_focus (l->data); -} - -static void -meta_wayland_tablet_pad_broadcast_enter (MetaWaylandTabletPad *pad, - uint32_t serial, - MetaWaylandTablet *tablet, - MetaWaylandSurface *surface) -{ - struct wl_resource *resource, *tablet_resource; - struct wl_client *client; - - client = wl_resource_get_client (pad->focus_surface->resource); - tablet_resource = meta_wayland_tablet_lookup_resource (tablet, client); - - wl_resource_for_each (resource, &pad->focus_resource_list) - { - zwp_tablet_pad_v2_send_enter (resource, serial, - tablet_resource, - surface->resource); - } -} - -static void -meta_wayland_tablet_pad_broadcast_leave (MetaWaylandTabletPad *pad, - uint32_t serial, - MetaWaylandSurface *surface) -{ - struct wl_resource *resource; - - wl_resource_for_each (resource, &pad->focus_resource_list) - { - zwp_tablet_pad_v2_send_leave (resource, serial, - surface->resource); - } -} - -void -meta_wayland_tablet_pad_set_focus (MetaWaylandTabletPad *pad, - MetaWaylandSurface *surface) -{ - MetaWaylandTablet *tablet; - - if (pad->focus_surface == surface) - return; - - g_hash_table_remove_all (pad->feedback); - - if (pad->focus_surface != NULL) - { - struct wl_client *client = wl_resource_get_client (pad->focus_surface->resource); - struct wl_list *focus_resources = &pad->focus_resource_list; - - if (!wl_list_empty (focus_resources)) - { - struct wl_display *display = wl_client_get_display (client); - uint32_t serial = wl_display_next_serial (display); - - meta_wayland_tablet_pad_broadcast_leave (pad, serial, - pad->focus_surface); - move_resources (&pad->resource_list, &pad->focus_resource_list); - } - - wl_list_remove (&pad->focus_surface_listener.link); - pad->focus_surface = NULL; - } - - tablet = meta_wayland_tablet_seat_lookup_paired_tablet (pad->tablet_seat, - pad); - - if (tablet != NULL && surface != NULL) - { - struct wl_client *client; - - pad->focus_surface = surface; - wl_resource_add_destroy_listener (pad->focus_surface->resource, - &pad->focus_surface_listener); - - client = wl_resource_get_client (pad->focus_surface->resource); - move_resources_for_client (&pad->focus_resource_list, - &pad->resource_list, client); - - if (!wl_list_empty (&pad->focus_resource_list)) - { - struct wl_display *display = wl_client_get_display (client); - - pad->focus_serial = wl_display_next_serial (display); - meta_wayland_tablet_pad_broadcast_enter (pad, pad->focus_serial, - tablet, pad->focus_surface); - } - } - - meta_wayland_tablet_pad_update_groups_focus (pad); -} - -void -meta_wayland_tablet_pad_update (MetaWaylandTabletPad *pad, - const ClutterEvent *event) -{ - MetaWaylandTabletPadGroup *group; - guint n_group; - - n_group = clutter_event_get_mode_group (event); - group = g_list_nth_data (pad->groups, n_group); - - if (group) - meta_wayland_tablet_pad_group_update (group, event); -} - -static gchar * -meta_wayland_tablet_pad_label_mode_switch_button (MetaWaylandTabletPad *pad, - guint button) -{ - MetaWaylandTabletPadGroup *group; - GList *l; - - for (l = pad->groups; l; l = l->next) - { - group = l->data; - - if (meta_wayland_tablet_pad_group_is_mode_switch_button (group, button)) - return g_strdup_printf (_("Mode Switch: Mode %d"), group->current_mode + 1); - } - - return NULL; -} - -gchar * -meta_wayland_tablet_pad_get_label (MetaWaylandTabletPad *pad, - MetaPadActionType type, - guint action) -{ - const gchar *label = NULL; - gchar *mode_label; - - switch (type) - { - case META_PAD_ACTION_BUTTON: - mode_label = meta_wayland_tablet_pad_label_mode_switch_button (pad, action); - if (mode_label) - return mode_label; - - label = g_hash_table_lookup (pad->feedback, GUINT_TO_POINTER (action)); - break; - case META_PAD_ACTION_RING: - { - MetaWaylandTabletPadRing *ring; - - ring = g_list_nth_data (pad->rings, action); - if (ring) - label = ring->feedback; - break; - } - case META_PAD_ACTION_STRIP: - { - MetaWaylandTabletPadStrip *strip; - - strip = g_list_nth_data (pad->strips, action); - if (strip) - label = strip->feedback; - break; - } - } - - return g_strdup (label); -} diff --git a/src/wayland/meta-wayland-tablet-pad.h b/src/wayland/meta-wayland-tablet-pad.h deleted file mode 100644 index 63eaa03ed..000000000 --- a/src/wayland/meta-wayland-tablet-pad.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2016 Red Hat - * - * 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 . - * - * Author: Carlos Garnacho - */ - -#ifndef META_WAYLAND_TABLET_PAD_H -#define META_WAYLAND_TABLET_PAD_H - -#include -#include - -#include "backends/meta-cursor-renderer.h" -#include "wayland/meta-wayland-types.h" - -struct _MetaWaylandTabletPad -{ - MetaWaylandTabletSeat *tablet_seat; - ClutterInputDevice *device; - - struct wl_list resource_list; - struct wl_list focus_resource_list; - - MetaWaylandSurface *focus_surface; - struct wl_listener focus_surface_listener; - uint32_t focus_serial; - - uint32_t n_buttons; - GList *groups; - GList *rings; - GList *strips; - - GHashTable *feedback; - - MetaWaylandSurface *focus; -}; - -MetaWaylandTabletPad * meta_wayland_tablet_pad_new (ClutterInputDevice *device, - MetaWaylandTabletSeat *tablet_seat); -void meta_wayland_tablet_pad_free (MetaWaylandTabletPad *pad); - -struct wl_resource * - meta_wayland_tablet_pad_create_new_resource (MetaWaylandTabletPad *pad, - struct wl_client *client, - struct wl_resource *seat_resource, - uint32_t id); -struct wl_resource * - meta_wayland_tablet_pad_lookup_resource (MetaWaylandTabletPad *pad, - struct wl_client *client); - -void meta_wayland_tablet_pad_notify (MetaWaylandTabletPad *pad, - struct wl_resource *resource); - -void meta_wayland_tablet_pad_update (MetaWaylandTabletPad *pad, - const ClutterEvent *event); -gboolean meta_wayland_tablet_pad_handle_event (MetaWaylandTabletPad *pad, - const ClutterEvent *event); - -void meta_wayland_tablet_pad_set_focus (MetaWaylandTabletPad *pad, - MetaWaylandSurface *surface); - -gchar * meta_wayland_tablet_pad_get_label (MetaWaylandTabletPad *pad, - MetaPadActionType type, - guint action); - -#endif /* META_WAYLAND_TABLET_PAD_H */ diff --git a/src/wayland/meta-wayland-tablet-seat.c b/src/wayland/meta-wayland-tablet-seat.c deleted file mode 100644 index f9b95a656..000000000 --- a/src/wayland/meta-wayland-tablet-seat.c +++ /dev/null @@ -1,571 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2015 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: Carlos Garnacho - */ - -#include "config.h" - -#include -#include - -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-tablet-pad.h" -#include "wayland/meta-wayland-tablet-seat.h" -#include "wayland/meta-wayland-tablet-tool.h" -#include "wayland/meta-wayland-tablet.h" - -#include "tablet-unstable-v2-server-protocol.h" - -static void -unbind_resource (struct wl_resource *resource) -{ - wl_list_remove (wl_resource_get_link (resource)); -} - -static void -notify_tool_added (MetaWaylandTabletSeat *tablet_seat, - struct wl_resource *client_resource, - MetaWaylandTabletTool *tool) -{ - struct wl_resource *tool_resource; - struct wl_client *client; - - client = wl_resource_get_client (client_resource); - tool_resource = meta_wayland_tablet_tool_lookup_resource (tool, client); - - if (!tool_resource) - return; - - zwp_tablet_seat_v2_send_tool_added (client_resource, tool_resource); -} - -static void -notify_tablet_added (MetaWaylandTabletSeat *tablet_seat, - struct wl_resource *client_resource, - ClutterInputDevice *device) -{ - struct wl_resource *resource; - MetaWaylandTablet *tablet; - struct wl_client *client; - - tablet = g_hash_table_lookup (tablet_seat->tablets, device); - - if (!tablet) - return; - - client = wl_resource_get_client (client_resource); - - if (meta_wayland_tablet_lookup_resource (tablet, client)) - return; - - resource = meta_wayland_tablet_create_new_resource (tablet, client, - client_resource, 0); - if (!resource) - return; - - zwp_tablet_seat_v2_send_tablet_added (client_resource, resource); - meta_wayland_tablet_notify (tablet, resource); -} - -static void -broadcast_tablet_added (MetaWaylandTabletSeat *tablet_seat, - ClutterInputDevice *device) -{ - struct wl_resource *resource; - - wl_resource_for_each (resource, &tablet_seat->resource_list) - { - notify_tablet_added (tablet_seat, resource, device); - } -} - -static void -notify_tablets (MetaWaylandTabletSeat *tablet_seat, - struct wl_resource *client_resource) -{ - ClutterInputDevice *device; - GHashTableIter iter; - - g_hash_table_iter_init (&iter, tablet_seat->tablets); - - while (g_hash_table_iter_next (&iter, (gpointer *) &device, NULL)) - notify_tablet_added (tablet_seat, client_resource, device); -} - -static void -notify_pad_added (MetaWaylandTabletSeat *tablet_seat, - struct wl_resource *tablet_seat_resource, - ClutterInputDevice *device) -{ - struct wl_resource *resource; - MetaWaylandTabletPad *pad; - struct wl_client *client; - - pad = g_hash_table_lookup (tablet_seat->pads, device); - - if (!pad) - return; - - client = wl_resource_get_client (tablet_seat_resource); - - if (meta_wayland_tablet_pad_lookup_resource (pad, client)) - return; - - resource = meta_wayland_tablet_pad_create_new_resource (pad, client, - tablet_seat_resource, - 0); - if (!resource) - return; - - zwp_tablet_seat_v2_send_pad_added (tablet_seat_resource, resource); - meta_wayland_tablet_pad_notify (pad, resource); -} - -static void -broadcast_pad_added (MetaWaylandTabletSeat *tablet_seat, - ClutterInputDevice *device) -{ - struct wl_resource *resource; - - wl_resource_for_each (resource, &tablet_seat->resource_list) - { - notify_pad_added (tablet_seat, resource, device); - } -} - -static void -notify_pads (MetaWaylandTabletSeat *tablet_seat, - struct wl_resource *tablet_seat_resource) -{ - ClutterInputDevice *device; - GHashTableIter iter; - - g_hash_table_iter_init (&iter, tablet_seat->pads); - - while (g_hash_table_iter_next (&iter, (gpointer *) &device, NULL)) - notify_pad_added (tablet_seat, tablet_seat_resource, device); -} - -static gboolean -is_tablet_device (ClutterInputDevice *device) -{ - ClutterInputDeviceType device_type; - - if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_LOGICAL) - return FALSE; - - device_type = clutter_input_device_get_device_type (device); - - return (device_type == CLUTTER_TABLET_DEVICE || - device_type == CLUTTER_PEN_DEVICE || - device_type == CLUTTER_ERASER_DEVICE || - device_type == CLUTTER_CURSOR_DEVICE); -} - -static gboolean -is_pad_device (ClutterInputDevice *device) -{ - ClutterInputDeviceType device_type; - - if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_LOGICAL) - return FALSE; - - device_type = clutter_input_device_get_device_type (device); - - return device_type == CLUTTER_PAD_DEVICE; -} - -static void -meta_wayland_tablet_seat_device_added (MetaWaylandTabletSeat *tablet_seat, - ClutterInputDevice *device) -{ - MetaWaylandSurface *pad_focus = tablet_seat->seat->keyboard->focus_surface; - - if (is_tablet_device (device)) - { - MetaWaylandTablet *tablet; - GList *pads, *l; - - tablet = meta_wayland_tablet_new (device, tablet_seat); - g_hash_table_insert (tablet_seat->tablets, device, tablet); - broadcast_tablet_added (tablet_seat, device); - - /* Because the insertion order is undefined, there might be already - * pads that are logically paired to this tablet. Look those up and - * refocus them. - */ - pads = meta_wayland_tablet_seat_lookup_paired_pads (tablet_seat, - tablet); - - for (l = pads; l; l = l->next) - meta_wayland_tablet_pad_set_focus (l->data, pad_focus); - - g_list_free (pads); - } - else if (is_pad_device (device)) - { - MetaWaylandTabletPad *pad; - - pad = meta_wayland_tablet_pad_new (device, tablet_seat); - g_hash_table_insert (tablet_seat->pads, device, pad); - broadcast_pad_added (tablet_seat, device); - - meta_wayland_tablet_pad_set_focus (pad, pad_focus); - } -} - -static void -meta_wayland_tablet_seat_device_removed (MetaWaylandTabletSeat *tablet_seat, - ClutterInputDevice *device) -{ - g_hash_table_remove (tablet_seat->tablets, device); - g_hash_table_remove (tablet_seat->pads, device); -} - -static void -tablet_seat_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static const struct zwp_tablet_seat_v2_interface tablet_seat_interface = { - tablet_seat_destroy -}; - -MetaWaylandTabletSeat * -meta_wayland_tablet_seat_new (MetaWaylandTabletManager *manager, - MetaWaylandSeat *seat) -{ - MetaWaylandTabletSeat *tablet_seat; - GList *devices, *l; - - tablet_seat = g_new0 (MetaWaylandTabletSeat, 1); - tablet_seat->manager = manager; - tablet_seat->seat = seat; - tablet_seat->clutter_seat = clutter_backend_get_default_seat (clutter_get_default_backend ()); - tablet_seat->tablets = g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) meta_wayland_tablet_free); - tablet_seat->tools = g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) meta_wayland_tablet_tool_free); - tablet_seat->pads = g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) meta_wayland_tablet_pad_free); - wl_list_init (&tablet_seat->resource_list); - - g_signal_connect_swapped (tablet_seat->clutter_seat, "device-added", - G_CALLBACK (meta_wayland_tablet_seat_device_added), - tablet_seat); - g_signal_connect_swapped (tablet_seat->clutter_seat, "device-removed", - G_CALLBACK (meta_wayland_tablet_seat_device_removed), - tablet_seat); - - devices = clutter_seat_list_devices (tablet_seat->clutter_seat); - - for (l = devices; l; l = l->next) - meta_wayland_tablet_seat_device_added (tablet_seat, l->data); - - g_list_free (devices); - - return tablet_seat; -} - -void -meta_wayland_tablet_seat_free (MetaWaylandTabletSeat *tablet_seat) -{ - struct wl_resource *resource, *next; - - wl_resource_for_each_safe (resource, next, &tablet_seat->resource_list) - { - wl_list_remove (wl_resource_get_link (resource)); - wl_list_init (wl_resource_get_link (resource)); - } - - g_signal_handlers_disconnect_by_data (tablet_seat->clutter_seat, - tablet_seat); - g_hash_table_destroy (tablet_seat->tablets); - g_hash_table_destroy (tablet_seat->tools); - g_hash_table_destroy (tablet_seat->pads); - g_free (tablet_seat); -} - -struct wl_resource * -meta_wayland_tablet_seat_create_new_resource (MetaWaylandTabletSeat *tablet_seat, - struct wl_client *client, - struct wl_resource *manager_resource, - uint32_t id) -{ - struct wl_resource *resource; - - resource = wl_resource_create (client, &zwp_tablet_seat_v2_interface, - wl_resource_get_version (manager_resource), - id); - wl_resource_set_implementation (resource, &tablet_seat_interface, - tablet_seat, unbind_resource); - wl_resource_set_user_data (resource, tablet_seat); - wl_list_insert (&tablet_seat->resource_list, wl_resource_get_link (resource)); - - /* Notify client of all available tablets/pads */ - notify_tablets (tablet_seat, resource); - notify_pads (tablet_seat, resource); - - return resource; -} - -struct wl_resource * -meta_wayland_tablet_seat_lookup_resource (MetaWaylandTabletSeat *tablet_seat, - struct wl_client *client) -{ - return wl_resource_find_for_client (&tablet_seat->resource_list, client); -} - -MetaWaylandTablet * -meta_wayland_tablet_seat_lookup_tablet (MetaWaylandTabletSeat *tablet_seat, - ClutterInputDevice *device) -{ - return g_hash_table_lookup (tablet_seat->tablets, device); -} - -MetaWaylandTabletTool * -meta_wayland_tablet_seat_lookup_tool (MetaWaylandTabletSeat *tablet_seat, - ClutterInputDeviceTool *tool) -{ - return g_hash_table_lookup (tablet_seat->tools, tool); -} - -MetaWaylandTabletPad * -meta_wayland_tablet_seat_lookup_pad (MetaWaylandTabletSeat *tablet_seat, - ClutterInputDevice *device) -{ - return g_hash_table_lookup (tablet_seat->pads, device); -} - -static MetaWaylandTabletTool * -meta_wayland_tablet_seat_ensure_tool (MetaWaylandTabletSeat *tablet_seat, - ClutterInputDevice *device, - ClutterInputDeviceTool *device_tool) -{ - MetaWaylandTabletTool *tool; - - tool = g_hash_table_lookup (tablet_seat->tools, device_tool); - - if (!tool) - { - tool = meta_wayland_tablet_tool_new (tablet_seat, device, device_tool); - g_hash_table_insert (tablet_seat->tools, device_tool, tool); - } - - return tool; -} - -void -meta_wayland_tablet_seat_update (MetaWaylandTabletSeat *tablet_seat, - const ClutterEvent *event) -{ - ClutterInputDevice *device; - ClutterInputDeviceTool *device_tool; - MetaWaylandTabletTool *tool = NULL; - MetaWaylandTabletPad *pad = NULL; - - device = clutter_event_get_source_device (event); - - switch (event->type) - { - case CLUTTER_PROXIMITY_IN: - case CLUTTER_PROXIMITY_OUT: - case CLUTTER_BUTTON_PRESS: - case CLUTTER_BUTTON_RELEASE: - case CLUTTER_MOTION: - device_tool = clutter_event_get_device_tool (event); - - if (device && device_tool) - tool = meta_wayland_tablet_seat_ensure_tool (tablet_seat, device, device_tool); - - if (!tool) - return; - - meta_wayland_tablet_tool_update (tool, event); - break; - case CLUTTER_PAD_BUTTON_PRESS: - case CLUTTER_PAD_BUTTON_RELEASE: - case CLUTTER_PAD_RING: - case CLUTTER_PAD_STRIP: - pad = g_hash_table_lookup (tablet_seat->pads, device); - if (!pad) - return; - - return meta_wayland_tablet_pad_update (pad, event); - default: - break; - } -} - -gboolean -meta_wayland_tablet_seat_handle_event (MetaWaylandTabletSeat *tablet_seat, - const ClutterEvent *event) -{ - ClutterInputDeviceTool *device_tool; - MetaWaylandTabletTool *tool = NULL; - MetaWaylandTabletPad *pad = NULL; - - switch (event->type) - { - case CLUTTER_PROXIMITY_IN: - case CLUTTER_PROXIMITY_OUT: - case CLUTTER_BUTTON_PRESS: - case CLUTTER_BUTTON_RELEASE: - case CLUTTER_MOTION: - device_tool = clutter_event_get_device_tool (event); - - if (device_tool) - tool = g_hash_table_lookup (tablet_seat->tools, device_tool); - - if (!tool) - return CLUTTER_EVENT_PROPAGATE; - - meta_wayland_tablet_tool_handle_event (tool, event); - return CLUTTER_EVENT_PROPAGATE; - case CLUTTER_PAD_BUTTON_PRESS: - case CLUTTER_PAD_BUTTON_RELEASE: - case CLUTTER_PAD_RING: - case CLUTTER_PAD_STRIP: - pad = g_hash_table_lookup (tablet_seat->pads, - clutter_event_get_source_device (event)); - if (!pad) - return CLUTTER_EVENT_PROPAGATE; - - return meta_wayland_tablet_pad_handle_event (pad, event); - default: - return CLUTTER_EVENT_STOP; - } -} - -void -meta_wayland_tablet_seat_notify_tool (MetaWaylandTabletSeat *tablet_seat, - MetaWaylandTabletTool *tool, - struct wl_client *client) -{ - struct wl_resource *resource; - - resource = wl_resource_find_for_client (&tablet_seat->resource_list, client); - - if (resource) - notify_tool_added (tablet_seat, resource, tool); -} - -static GList * -lookup_grouped_devices (ClutterInputDevice *device, - ClutterInputDeviceType type) -{ - ClutterSeat *clutter_seat; - GList *devices, *l; - GList *group = NULL; - - clutter_seat = clutter_input_device_get_seat (device); - devices = clutter_seat_list_devices (clutter_seat); - - for (l = devices; l; l = l->next) - { - if (l->data == device) - continue; - if (clutter_input_device_get_device_type (l->data) != type) - continue; - - if (!clutter_input_device_is_grouped (device, l->data)) - continue; - - group = g_list_prepend (group, l->data); - } - - g_list_free (devices); - - return group; -} - -MetaWaylandTablet * -meta_wayland_tablet_seat_lookup_paired_tablet (MetaWaylandTabletSeat *tablet_seat, - MetaWaylandTabletPad *pad) -{ - MetaWaylandTablet *tablet; - GList *devices; - - devices = lookup_grouped_devices (pad->device, CLUTTER_TABLET_DEVICE); - - if (!devices) - return NULL; - - /* We only accept one device here */ - g_warn_if_fail (!devices->next); - - tablet = meta_wayland_tablet_seat_lookup_tablet (pad->tablet_seat, - devices->data); - g_list_free (devices); - - return tablet; -} - -GList * -meta_wayland_tablet_seat_lookup_paired_pads (MetaWaylandTabletSeat *tablet_seat, - MetaWaylandTablet *tablet) -{ - GList *l, *devices, *pads = NULL; - MetaWaylandTabletPad *pad; - - devices = lookup_grouped_devices (tablet->device, CLUTTER_PAD_DEVICE); - - for (l = devices; l; l = l->next) - { - pad = meta_wayland_tablet_seat_lookup_pad (tablet_seat, l->data); - if (pad) - pads = g_list_prepend (pads, pad); - } - - return pads; -} - -void -meta_wayland_tablet_seat_set_pad_focus (MetaWaylandTabletSeat *tablet_seat, - MetaWaylandSurface *surface) -{ - MetaWaylandTabletPad *pad; - GHashTableIter iter; - - g_hash_table_iter_init (&iter, tablet_seat->pads); - - while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &pad)) - meta_wayland_tablet_pad_set_focus (pad, surface); -} - -gboolean -meta_wayland_tablet_seat_can_popup (MetaWaylandTabletSeat *tablet_seat, - uint32_t serial) -{ - MetaWaylandTabletTool *tool; - GHashTableIter iter; - - g_hash_table_iter_init (&iter, tablet_seat->tools); - while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &tool)) - { - if (meta_wayland_tablet_tool_can_popup (tool, serial)) - return TRUE; - } - - return FALSE; -} diff --git a/src/wayland/meta-wayland-tablet-seat.h b/src/wayland/meta-wayland-tablet-seat.h deleted file mode 100644 index e8b5a2439..000000000 --- a/src/wayland/meta-wayland-tablet-seat.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2015 Red Hat - * - * 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 . - * - * Author: Carlos Garnacho - */ - -#ifndef META_WAYLAND_TABLET_SEAT_H -#define META_WAYLAND_TABLET_SEAT_H - -#include -#include - -#include "wayland/meta-wayland-types.h" - -struct _MetaWaylandTabletSeat -{ - MetaWaylandTabletManager *manager; - MetaWaylandSeat *seat; - ClutterSeat *clutter_seat; - struct wl_list resource_list; - - GHashTable *tablets; - GHashTable *tools; - GHashTable *pads; -}; - -MetaWaylandTabletSeat *meta_wayland_tablet_seat_new (MetaWaylandTabletManager *tablet_manager, - MetaWaylandSeat *seat); -void meta_wayland_tablet_seat_free (MetaWaylandTabletSeat *tablet_seat); - -struct wl_resource *meta_wayland_tablet_seat_create_new_resource (MetaWaylandTabletSeat *tablet_seat, - struct wl_client *client, - struct wl_resource *seat_resource, - uint32_t id); -struct wl_resource *meta_wayland_tablet_seat_lookup_resource (MetaWaylandTabletSeat *tablet_seat, - struct wl_client *client); - -MetaWaylandTablet *meta_wayland_tablet_seat_lookup_tablet (MetaWaylandTabletSeat *tablet_seat, - ClutterInputDevice *device); - -MetaWaylandTabletTool *meta_wayland_tablet_seat_lookup_tool (MetaWaylandTabletSeat *tablet_seat, - ClutterInputDeviceTool *tool); - -MetaWaylandTabletPad *meta_wayland_tablet_seat_lookup_pad (MetaWaylandTabletSeat *tablet_seat, - ClutterInputDevice *device); - -void meta_wayland_tablet_seat_update (MetaWaylandTabletSeat *tablet_seat, - const ClutterEvent *event); -gboolean meta_wayland_tablet_seat_handle_event (MetaWaylandTabletSeat *tablet_seat, - const ClutterEvent *event); - -void meta_wayland_tablet_seat_notify_tool (MetaWaylandTabletSeat *tablet_seat, - MetaWaylandTabletTool *tool, - struct wl_client *client); - -void meta_wayland_tablet_seat_set_pad_focus (MetaWaylandTabletSeat *tablet_seat, - MetaWaylandSurface *surface); - -MetaWaylandTablet *meta_wayland_tablet_seat_lookup_paired_tablet (MetaWaylandTabletSeat *tablet_seat, - MetaWaylandTabletPad *pad); -GList *meta_wayland_tablet_seat_lookup_paired_pads (MetaWaylandTabletSeat *tablet_seat, - MetaWaylandTablet *tablet); -gboolean meta_wayland_tablet_seat_can_popup (MetaWaylandTabletSeat *tablet_seat, - uint32_t serial); - -#endif /* META_WAYLAND_TABLET_SEAT_H */ diff --git a/src/wayland/meta-wayland-tablet-tool.c b/src/wayland/meta-wayland-tablet-tool.c deleted file mode 100644 index a8de868bc..000000000 --- a/src/wayland/meta-wayland-tablet-tool.c +++ /dev/null @@ -1,912 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2015 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: Carlos Garnacho - */ - -#include "config.h" - -#include "wayland/meta-wayland-tablet-tool.h" - -#include -#include - -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-tablet-cursor-surface.h" -#include "compositor/meta-surface-actor-wayland.h" -#include "wayland/meta-wayland-tablet.h" -#include "wayland/meta-wayland-tablet-seat.h" -#include "backends/meta-input-settings-private.h" -#include "backends/meta-logical-monitor.h" - -#include "tablet-unstable-v2-server-protocol.h" - -#define TABLET_AXIS_MAX 65535 - -static void -unbind_resource (struct wl_resource *resource) -{ - wl_list_remove (wl_resource_get_link (resource)); -} - -static void -move_resources (struct wl_list *destination, - struct wl_list *source) -{ - wl_list_insert_list (destination, source); - wl_list_init (source); -} - -static void -move_resources_for_client (struct wl_list *destination, - struct wl_list *source, - struct wl_client *client) -{ - struct wl_resource *resource, *tmp; - - wl_resource_for_each_safe (resource, tmp, source) - { - if (wl_resource_get_client (resource) == client) - { - wl_list_remove (wl_resource_get_link (resource)); - wl_list_insert (destination, wl_resource_get_link (resource)); - } - } -} - -static void -meta_wayland_tablet_tool_update_cursor_surface (MetaWaylandTabletTool *tool) -{ - MetaCursorSprite *cursor = NULL; - - if (tool->cursor_renderer == NULL) - return; - - if (tool->current && tool->current_tablet) - { - if (tool->cursor_surface && - meta_wayland_surface_get_buffer (tool->cursor_surface)) - { - MetaWaylandCursorSurface *cursor_surface = - META_WAYLAND_CURSOR_SURFACE (tool->cursor_surface->role); - - cursor = meta_wayland_cursor_surface_get_sprite (cursor_surface); - } - else - cursor = NULL; - } - else if (tool->current_tablet) - cursor = META_CURSOR_SPRITE (tool->default_sprite); - else - cursor = NULL; - - meta_cursor_renderer_set_cursor (tool->cursor_renderer, cursor); -} - -static void -meta_wayland_tablet_tool_set_cursor_surface (MetaWaylandTabletTool *tool, - MetaWaylandSurface *surface) -{ - if (tool->cursor_surface == surface) - return; - - if (tool->cursor_surface) - { - MetaWaylandCursorSurface *cursor_surface; - - cursor_surface = META_WAYLAND_CURSOR_SURFACE (tool->cursor_surface->role); - meta_wayland_cursor_surface_set_renderer (cursor_surface, NULL); - - meta_wayland_surface_update_outputs (tool->cursor_surface); - wl_list_remove (&tool->cursor_surface_destroy_listener.link); - } - - tool->cursor_surface = surface; - - if (tool->cursor_surface) - { - meta_wayland_surface_update_outputs (tool->cursor_surface); - wl_resource_add_destroy_listener (tool->cursor_surface->resource, - &tool->cursor_surface_destroy_listener); - } - - meta_wayland_tablet_tool_update_cursor_surface (tool); -} - -static enum zwp_tablet_tool_v2_type -input_device_tool_get_type (ClutterInputDeviceTool *device_tool) -{ - ClutterInputDeviceToolType tool_type; - - tool_type = clutter_input_device_tool_get_tool_type (device_tool); - - switch (tool_type) - { - case CLUTTER_INPUT_DEVICE_TOOL_NONE: - case CLUTTER_INPUT_DEVICE_TOOL_PEN: - return ZWP_TABLET_TOOL_V2_TYPE_PEN; - case CLUTTER_INPUT_DEVICE_TOOL_ERASER: - return ZWP_TABLET_TOOL_V2_TYPE_ERASER; - case CLUTTER_INPUT_DEVICE_TOOL_BRUSH: - return ZWP_TABLET_TOOL_V2_TYPE_BRUSH; - case CLUTTER_INPUT_DEVICE_TOOL_PENCIL: - return ZWP_TABLET_TOOL_V2_TYPE_PENCIL; - case CLUTTER_INPUT_DEVICE_TOOL_AIRBRUSH: - return ZWP_TABLET_TOOL_V2_TYPE_AIRBRUSH; - case CLUTTER_INPUT_DEVICE_TOOL_MOUSE: - return ZWP_TABLET_TOOL_V2_TYPE_MOUSE; - case CLUTTER_INPUT_DEVICE_TOOL_LENS: - return ZWP_TABLET_TOOL_V2_TYPE_LENS; - } - - g_assert_not_reached (); - return 0; -} - -static void -meta_wayland_tablet_tool_notify_capabilities (MetaWaylandTabletTool *tool, - struct wl_resource *resource) -{ - ClutterInputAxisFlags axes; - - axes = clutter_input_device_tool_get_axes (tool->device_tool); - - if (axes & CLUTTER_INPUT_AXIS_FLAG_PRESSURE) - zwp_tablet_tool_v2_send_capability (resource, - ZWP_TABLET_TOOL_V2_CAPABILITY_PRESSURE); - if (axes & CLUTTER_INPUT_AXIS_FLAG_DISTANCE) - zwp_tablet_tool_v2_send_capability (resource, - ZWP_TABLET_TOOL_V2_CAPABILITY_DISTANCE); - if (axes & (CLUTTER_INPUT_AXIS_FLAG_XTILT | CLUTTER_INPUT_AXIS_FLAG_YTILT)) - zwp_tablet_tool_v2_send_capability (resource, - ZWP_TABLET_TOOL_V2_CAPABILITY_TILT); - if (axes & CLUTTER_INPUT_AXIS_FLAG_ROTATION) - zwp_tablet_tool_v2_send_capability (resource, - ZWP_TABLET_TOOL_V2_CAPABILITY_ROTATION); - if (axes & CLUTTER_INPUT_AXIS_FLAG_SLIDER) - zwp_tablet_tool_v2_send_capability (resource, - ZWP_TABLET_TOOL_V2_CAPABILITY_SLIDER); - if (axes & CLUTTER_INPUT_AXIS_FLAG_WHEEL) - zwp_tablet_tool_v2_send_capability (resource, - ZWP_TABLET_TOOL_V2_CAPABILITY_WHEEL); -} - -static void -meta_wayland_tablet_tool_notify_details (MetaWaylandTabletTool *tool, - struct wl_resource *resource) -{ - guint64 serial, id; - - zwp_tablet_tool_v2_send_type (resource, - input_device_tool_get_type (tool->device_tool)); - - serial = clutter_input_device_tool_get_serial (tool->device_tool); - zwp_tablet_tool_v2_send_hardware_serial (resource, (uint32_t) (serial >> 32), - (uint32_t) (serial & G_MAXUINT32)); - - id = clutter_input_device_tool_get_id (tool->device_tool); - zwp_tablet_tool_v2_send_hardware_id_wacom (resource, (uint32_t) (id >> 32), - (uint32_t) (id & G_MAXUINT32)); - - meta_wayland_tablet_tool_notify_capabilities (tool, resource); - - zwp_tablet_tool_v2_send_done (resource); -} - -static void -meta_wayland_tablet_tool_ensure_resource (MetaWaylandTabletTool *tool, - struct wl_client *client) -{ - struct wl_resource *seat_resource, *tool_resource; - - seat_resource = meta_wayland_tablet_seat_lookup_resource (tool->seat, client); - - if (seat_resource && - !meta_wayland_tablet_tool_lookup_resource (tool, client)) - { - tool_resource = meta_wayland_tablet_tool_create_new_resource (tool, client, - seat_resource, - 0); - - meta_wayland_tablet_seat_notify_tool (tool->seat, tool, client); - meta_wayland_tablet_tool_notify_details (tool, tool_resource); - } -} - -static void -broadcast_proximity_in (MetaWaylandTabletTool *tool) -{ - struct wl_resource *resource, *tablet_resource; - struct wl_client *client; - - client = wl_resource_get_client (tool->focus_surface->resource); - tablet_resource = meta_wayland_tablet_lookup_resource (tool->current_tablet, - client); - - wl_resource_for_each (resource, &tool->focus_resource_list) - { - zwp_tablet_tool_v2_send_proximity_in (resource, tool->proximity_serial, - tablet_resource, - tool->focus_surface->resource); - } -} - -static void -broadcast_proximity_out (MetaWaylandTabletTool *tool) -{ - struct wl_resource *resource; - - wl_resource_for_each (resource, &tool->focus_resource_list) - { - zwp_tablet_tool_v2_send_proximity_out (resource); - } -} - -static void -broadcast_frame (MetaWaylandTabletTool *tool, - const ClutterEvent *event) -{ - struct wl_resource *resource; - guint32 _time = event ? clutter_event_get_time (event) : CLUTTER_CURRENT_TIME; - - wl_resource_for_each (resource, &tool->focus_resource_list) - { - zwp_tablet_tool_v2_send_frame (resource, _time); - } -} - -static void -meta_wayland_tablet_tool_set_focus (MetaWaylandTabletTool *tool, - MetaWaylandSurface *surface, - const ClutterEvent *event) -{ - if (tool->focus_surface == surface) - return; - - if (tool->focus_surface != NULL) - { - struct wl_list *l; - - l = &tool->focus_resource_list; - if (!wl_list_empty (l)) - { - broadcast_proximity_out (tool); - broadcast_frame (tool, event); - move_resources (&tool->resource_list, &tool->focus_resource_list); - } - - wl_list_remove (&tool->focus_surface_destroy_listener.link); - tool->focus_surface = NULL; - } - - if (surface != NULL && tool->current_tablet) - { - struct wl_client *client; - struct wl_list *l; - - tool->focus_surface = surface; - client = wl_resource_get_client (tool->focus_surface->resource); - wl_resource_add_destroy_listener (tool->focus_surface->resource, - &tool->focus_surface_destroy_listener); - - move_resources_for_client (&tool->focus_resource_list, - &tool->resource_list, client); - meta_wayland_tablet_tool_ensure_resource (tool, client); - - l = &tool->focus_resource_list; - - if (!wl_list_empty (l)) - { - struct wl_client *client = wl_resource_get_client (tool->focus_surface->resource); - struct wl_display *display = wl_client_get_display (client); - - tool->proximity_serial = wl_display_next_serial (display); - - broadcast_proximity_in (tool); - broadcast_frame (tool, event); - } - } - - meta_wayland_tablet_tool_update_cursor_surface (tool); -} - -static void -tablet_tool_handle_focus_surface_destroy (struct wl_listener *listener, - void *data) -{ - MetaWaylandTabletTool *tool; - - tool = wl_container_of (listener, tool, focus_surface_destroy_listener); - meta_wayland_tablet_tool_set_focus (tool, NULL, NULL); -} - -static void -tablet_tool_handle_cursor_surface_destroy (struct wl_listener *listener, - void *data) -{ - MetaWaylandTabletTool *tool; - - tool = wl_container_of (listener, tool, cursor_surface_destroy_listener); - meta_wayland_tablet_tool_set_cursor_surface (tool, NULL); -} - -static void -tool_cursor_prepare_at (MetaCursorSpriteXcursor *sprite_xcursor, - float best_scale, - int x, - int y, - MetaWaylandTabletTool *tool) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaLogicalMonitor *logical_monitor; - - logical_monitor = - meta_monitor_manager_get_logical_monitor_at (monitor_manager, x, y); - - /* Reload the cursor texture if the scale has changed. */ - if (logical_monitor) - { - MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (sprite_xcursor); - float ceiled_scale; - - ceiled_scale = ceilf (logical_monitor->scale); - meta_cursor_sprite_xcursor_set_theme_scale (sprite_xcursor, - (int) ceiled_scale); - - if (meta_is_stage_views_scaled ()) - meta_cursor_sprite_set_texture_scale (cursor_sprite, - 1.0 / ceiled_scale); - else - meta_cursor_sprite_set_texture_scale (cursor_sprite, 1.0); - } -} - -MetaWaylandTabletTool * -meta_wayland_tablet_tool_new (MetaWaylandTabletSeat *seat, - ClutterInputDevice *device, - ClutterInputDeviceTool *device_tool) -{ - MetaWaylandTabletTool *tool; - - tool = g_new0 (MetaWaylandTabletTool, 1); - tool->seat = seat; - tool->device = device; - tool->device_tool = device_tool; - wl_list_init (&tool->resource_list); - wl_list_init (&tool->focus_resource_list); - - tool->focus_surface_destroy_listener.notify = tablet_tool_handle_focus_surface_destroy; - tool->cursor_surface_destroy_listener.notify = tablet_tool_handle_cursor_surface_destroy; - - tool->default_sprite = meta_cursor_sprite_xcursor_new (META_CURSOR_CROSSHAIR); - tool->prepare_at_signal_id = - g_signal_connect (tool->default_sprite, "prepare-at", - G_CALLBACK (tool_cursor_prepare_at), tool); - - return tool; -} - -void -meta_wayland_tablet_tool_free (MetaWaylandTabletTool *tool) -{ - struct wl_resource *resource, *next; - - meta_wayland_tablet_tool_set_focus (tool, NULL, NULL); - meta_wayland_tablet_tool_set_cursor_surface (tool, NULL); - g_clear_object (&tool->cursor_renderer); - - wl_resource_for_each_safe (resource, next, &tool->resource_list) - { - zwp_tablet_tool_v2_send_removed (resource); - wl_list_remove (wl_resource_get_link (resource)); - wl_list_init (wl_resource_get_link (resource)); - } - - g_clear_signal_handler (&tool->prepare_at_signal_id, tool->default_sprite); - g_object_unref (tool->default_sprite); - - g_free (tool); -} - -static void -tool_set_cursor (struct wl_client *client, - struct wl_resource *resource, - uint32_t serial, - struct wl_resource *surface_resource, - int32_t hotspot_x, - int32_t hotspot_y) -{ - MetaWaylandTabletTool *tool = wl_resource_get_user_data (resource); - MetaWaylandSurface *surface; - - surface = (surface_resource ? wl_resource_get_user_data (surface_resource) : NULL); - - if (tool->focus_surface == NULL) - return; - if (tool->cursor_renderer == NULL) - return; - if (wl_resource_get_client (tool->focus_surface->resource) != client) - return; - if (tool->proximity_serial - serial > G_MAXUINT32 / 2) - return; - - if (surface && - !meta_wayland_surface_assign_role (surface, - META_TYPE_WAYLAND_TABLET_CURSOR_SURFACE, - NULL)) - { - wl_resource_post_error (resource, WL_POINTER_ERROR_ROLE, - "wl_surface@%d already has a different role", - wl_resource_get_id (surface_resource)); - return; - } - - if (surface) - { - MetaWaylandCursorSurface *cursor_surface; - - cursor_surface = META_WAYLAND_CURSOR_SURFACE (surface->role); - meta_wayland_cursor_surface_set_renderer (cursor_surface, - tool->cursor_renderer); - meta_wayland_cursor_surface_set_hotspot (cursor_surface, - hotspot_x, hotspot_y); - } - - meta_wayland_tablet_tool_set_cursor_surface (tool, surface); -} - -static void -tool_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static const struct zwp_tablet_tool_v2_interface tool_interface = { - tool_set_cursor, - tool_destroy -}; - -struct wl_resource * -meta_wayland_tablet_tool_create_new_resource (MetaWaylandTabletTool *tool, - struct wl_client *client, - struct wl_resource *seat_resource, - uint32_t id) -{ - struct wl_resource *resource; - - resource = wl_resource_create (client, &zwp_tablet_tool_v2_interface, - wl_resource_get_version (seat_resource), id); - wl_resource_set_implementation (resource, &tool_interface, - tool, unbind_resource); - wl_resource_set_user_data (resource, tool); - - if (tool->focus_surface && - wl_resource_get_client (tool->focus_surface->resource) == client) - { - wl_list_insert (&tool->focus_resource_list, wl_resource_get_link (resource)); - } - else - { - wl_list_insert (&tool->resource_list, wl_resource_get_link (resource)); - } - - return resource; -} - -struct wl_resource * -meta_wayland_tablet_tool_lookup_resource (MetaWaylandTabletTool *tool, - struct wl_client *client) -{ - struct wl_resource *resource = NULL; - - if (!wl_list_empty (&tool->resource_list)) - resource = wl_resource_find_for_client (&tool->resource_list, client); - - if (!wl_list_empty (&tool->focus_resource_list)) - resource = wl_resource_find_for_client (&tool->focus_resource_list, client); - - return resource; -} - -static void -meta_wayland_tablet_tool_account_button (MetaWaylandTabletTool *tool, - const ClutterEvent *event) -{ - if (event->type == CLUTTER_BUTTON_PRESS) - { - tool->pressed_buttons |= 1 << (event->button.button - 1); - tool->button_count++; - } - else if (event->type == CLUTTER_BUTTON_RELEASE) - { - tool->pressed_buttons &= ~(1 << (event->button.button - 1)); - tool->button_count--; - } -} - -static void -sync_focus_surface (MetaWaylandTabletTool *tool, - const ClutterEvent *event) -{ - MetaDisplay *display = meta_get_display (); - - switch (display->event_route) - { - case META_EVENT_ROUTE_WINDOW_OP: - case META_EVENT_ROUTE_COMPOSITOR_GRAB: - case META_EVENT_ROUTE_FRAME_BUTTON: - /* The compositor has a grab, so remove our focus */ - meta_wayland_tablet_tool_set_focus (tool, NULL, event); - break; - - case META_EVENT_ROUTE_NORMAL: - case META_EVENT_ROUTE_WAYLAND_POPUP: - meta_wayland_tablet_tool_set_focus (tool, tool->current, event); - break; - - default: - g_assert_not_reached (); - } -} - -static void -repick_for_event (MetaWaylandTabletTool *tool, - const ClutterEvent *for_event) -{ - ClutterActor *actor = NULL; - - actor = clutter_event_get_source (for_event); - - if (META_IS_SURFACE_ACTOR_WAYLAND (actor)) - tool->current = meta_surface_actor_wayland_get_surface (META_SURFACE_ACTOR_WAYLAND (actor)); - else - tool->current = NULL; - - sync_focus_surface (tool, for_event); - meta_wayland_tablet_tool_update_cursor_surface (tool); -} - -static void -meta_wayland_tablet_tool_get_relative_coordinates (MetaWaylandTabletTool *tool, - const ClutterEvent *event, - MetaWaylandSurface *surface, - wl_fixed_t *sx, - wl_fixed_t *sy) -{ - float xf, yf; - - clutter_event_get_coords (event, &xf, &yf); - meta_wayland_surface_get_relative_coordinates (surface, xf, yf, &xf, &yf); - - *sx = wl_fixed_from_double (xf); - *sy = wl_fixed_from_double (yf); -} - -static void -broadcast_motion (MetaWaylandTabletTool *tool, - const ClutterEvent *event) -{ - struct wl_resource *resource; - wl_fixed_t sx, sy; - - meta_wayland_tablet_tool_get_relative_coordinates (tool, event, - tool->focus_surface, - &sx, &sy); - - wl_resource_for_each (resource, &tool->focus_resource_list) - { - zwp_tablet_tool_v2_send_motion (resource, sx, sy); - } -} - -static void -broadcast_down (MetaWaylandTabletTool *tool, - const ClutterEvent *event) -{ - struct wl_resource *resource; - - tool->down_serial = wl_display_next_serial (tool->seat->manager->wl_display); - - wl_resource_for_each (resource, &tool->focus_resource_list) - { - zwp_tablet_tool_v2_send_down (resource, tool->down_serial); - } -} - -static void -broadcast_up (MetaWaylandTabletTool *tool, - const ClutterEvent *event) -{ - struct wl_resource *resource; - - wl_resource_for_each (resource, &tool->focus_resource_list) - { - zwp_tablet_tool_v2_send_up (resource); - } -} - -static void -broadcast_button (MetaWaylandTabletTool *tool, - const ClutterEvent *event) -{ - struct wl_resource *resource; - uint32_t button; - - button = clutter_event_get_event_code (event); - tool->button_serial = wl_display_next_serial (tool->seat->manager->wl_display); - - wl_resource_for_each (resource, &tool->focus_resource_list) - { - zwp_tablet_tool_v2_send_button (resource, tool->button_serial, button, - event->type == CLUTTER_BUTTON_PRESS ? - ZWP_TABLET_TOOL_V2_BUTTON_STATE_PRESSED : - ZWP_TABLET_TOOL_V2_BUTTON_STATE_RELEASED); - } -} - -static void -broadcast_axis (MetaWaylandTabletTool *tool, - const ClutterEvent *event, - ClutterInputAxis axis) -{ - struct wl_resource *resource; - uint32_t value; - double val; - - val = event->motion.axes[axis]; - value = val * TABLET_AXIS_MAX; - - wl_resource_for_each (resource, &tool->focus_resource_list) - { - switch (axis) - { - case CLUTTER_INPUT_AXIS_PRESSURE: - zwp_tablet_tool_v2_send_pressure (resource, value); - break; - case CLUTTER_INPUT_AXIS_DISTANCE: - zwp_tablet_tool_v2_send_distance (resource, value); - break; - case CLUTTER_INPUT_AXIS_SLIDER: - zwp_tablet_tool_v2_send_slider (resource, value); - break; - default: - break; - } - } -} - -static void -broadcast_tilt (MetaWaylandTabletTool *tool, - const ClutterEvent *event) -{ - struct wl_resource *resource; - gdouble xtilt, ytilt; - - xtilt = event->motion.axes[CLUTTER_INPUT_AXIS_FLAG_XTILT]; - ytilt = event->motion.axes[CLUTTER_INPUT_AXIS_FLAG_YTILT]; - - wl_resource_for_each (resource, &tool->focus_resource_list) - { - zwp_tablet_tool_v2_send_tilt (resource, - wl_fixed_from_double (xtilt), - wl_fixed_from_double (ytilt)); - } -} - -static void -broadcast_rotation (MetaWaylandTabletTool *tool, - const ClutterEvent *event) -{ - struct wl_resource *resource; - gdouble rotation; - - rotation = event->motion.axes[CLUTTER_INPUT_AXIS_FLAG_ROTATION]; - - wl_resource_for_each (resource, &tool->focus_resource_list) - { - zwp_tablet_tool_v2_send_rotation (resource, - wl_fixed_from_double (rotation)); - } -} - -static void -broadcast_wheel (MetaWaylandTabletTool *tool, - const ClutterEvent *event) -{ - struct wl_resource *resource; - gdouble angle; - gint32 clicks = 0; - - angle = event->motion.axes[CLUTTER_INPUT_AXIS_FLAG_WHEEL]; - - /* FIXME: Perform proper angle-to-clicks accumulation elsewhere */ - if (angle > 0.01) - clicks = 1; - else if (angle < -0.01) - clicks = -1; - else - return; - - wl_resource_for_each (resource, &tool->focus_resource_list) - { - zwp_tablet_tool_v2_send_wheel (resource, - wl_fixed_from_double (angle), - clicks); - } -} - -static void -broadcast_axes (MetaWaylandTabletTool *tool, - const ClutterEvent *event) -{ - ClutterInputAxisFlags axes; - - axes = clutter_input_device_tool_get_axes (tool->device_tool); - - if (axes & CLUTTER_INPUT_AXIS_FLAG_PRESSURE) - broadcast_axis (tool, event, CLUTTER_INPUT_AXIS_PRESSURE); - if (axes & CLUTTER_INPUT_AXIS_FLAG_DISTANCE) - broadcast_axis (tool, event, CLUTTER_INPUT_AXIS_DISTANCE); - if (axes & (CLUTTER_INPUT_AXIS_FLAG_XTILT | CLUTTER_INPUT_AXIS_FLAG_YTILT)) - broadcast_tilt (tool, event); - if (axes & CLUTTER_INPUT_AXIS_FLAG_ROTATION) - broadcast_rotation (tool, event); - if (axes & CLUTTER_INPUT_AXIS_FLAG_SLIDER) - broadcast_axis (tool, event, CLUTTER_INPUT_AXIS_SLIDER); - if (axes & CLUTTER_INPUT_AXIS_FLAG_WHEEL) - broadcast_wheel (tool, event); -} - -static void -handle_motion_event (MetaWaylandTabletTool *tool, - const ClutterEvent *event) -{ - if (!tool->focus_surface) - return; - - broadcast_motion (tool, event); - broadcast_axes (tool, event); - broadcast_frame (tool, event); -} - -static void -handle_button_event (MetaWaylandTabletTool *tool, - const ClutterEvent *event) -{ - if (!tool->focus_surface) - return; - - if (event->type == CLUTTER_BUTTON_PRESS && tool->button_count == 1) - clutter_event_get_coords (event, &tool->grab_x, &tool->grab_y); - - if (event->type == CLUTTER_BUTTON_PRESS && event->button.button == 1) - broadcast_down (tool, event); - else if (event->type == CLUTTER_BUTTON_RELEASE && event->button.button == 1) - broadcast_up (tool, event); - else - broadcast_button (tool, event); - - broadcast_frame (tool, event); -} - -void -meta_wayland_tablet_tool_update (MetaWaylandTabletTool *tool, - const ClutterEvent *event) -{ - switch (event->type) - { - case CLUTTER_BUTTON_PRESS: - case CLUTTER_BUTTON_RELEASE: - meta_wayland_tablet_tool_account_button (tool, event); - break; - case CLUTTER_MOTION: - if (!tool->pressed_buttons) - repick_for_event (tool, event); - break; - case CLUTTER_PROXIMITY_IN: - if (!tool->cursor_renderer) - { - MetaCursorRenderer *renderer; - - renderer = - meta_backend_get_cursor_renderer_for_device (meta_get_backend (), - clutter_event_get_source_device (event)); - g_set_object (&tool->cursor_renderer, renderer); - } - tool->current_tablet = - meta_wayland_tablet_seat_lookup_tablet (tool->seat, - clutter_event_get_source_device (event)); - break; - case CLUTTER_PROXIMITY_OUT: - tool->current_tablet = NULL; - meta_wayland_tablet_tool_set_cursor_surface (tool, NULL); - meta_wayland_tablet_tool_update_cursor_surface (tool); - g_clear_object (&tool->cursor_renderer); - break; - default: - break; - } -} - -gboolean -meta_wayland_tablet_tool_handle_event (MetaWaylandTabletTool *tool, - const ClutterEvent *event) -{ - switch (event->type) - { - case CLUTTER_PROXIMITY_IN: - /* We don't have much info here to make anything useful out of it, - * wait until the first motion event so we have both coordinates - * and tool. - */ - break; - case CLUTTER_PROXIMITY_OUT: - meta_wayland_tablet_tool_set_focus (tool, NULL, event); - break; - case CLUTTER_MOTION: - handle_motion_event (tool, event); - break; - case CLUTTER_BUTTON_PRESS: - case CLUTTER_BUTTON_RELEASE: - handle_button_event (tool, event); - break; - default: - return CLUTTER_EVENT_PROPAGATE; - } - - return CLUTTER_EVENT_STOP; -} - -static gboolean -tablet_tool_can_grab_surface (MetaWaylandTabletTool *tool, - MetaWaylandSurface *surface) -{ - MetaWaylandSurface *subsurface; - - if (tool->focus_surface == surface) - return TRUE; - - META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface) - { - if (tablet_tool_can_grab_surface (tool, subsurface)) - return TRUE; - } - - return FALSE; -} - -gboolean -meta_wayland_tablet_tool_can_grab_surface (MetaWaylandTabletTool *tool, - MetaWaylandSurface *surface, - uint32_t serial) -{ - return ((tool->down_serial == serial || tool->button_serial == serial) && - tablet_tool_can_grab_surface (tool, surface)); -} - -gboolean -meta_wayland_tablet_tool_can_popup (MetaWaylandTabletTool *tool, - uint32_t serial) -{ - return tool->down_serial == serial || tool->button_serial == serial; -} diff --git a/src/wayland/meta-wayland-tablet-tool.h b/src/wayland/meta-wayland-tablet-tool.h deleted file mode 100644 index e9ad7db40..000000000 --- a/src/wayland/meta-wayland-tablet-tool.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2015 Red Hat - * - * 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 . - * - * Author: Carlos Garnacho - */ - -#ifndef META_WAYLAND_TABLET_TOOL_H -#define META_WAYLAND_TABLET_TOOL_H - -#include -#include - -#include "backends/meta-cursor-renderer.h" -#include "backends/meta-cursor-sprite-xcursor.h" -#include "wayland/meta-wayland-types.h" - -struct _MetaWaylandTabletTool -{ - MetaWaylandTabletSeat *seat; - ClutterInputDevice *device; - ClutterInputDeviceTool *device_tool; - struct wl_list resource_list; - struct wl_list focus_resource_list; - - MetaWaylandSurface *focus_surface; - struct wl_listener focus_surface_destroy_listener; - - MetaWaylandSurface *cursor_surface; - struct wl_listener cursor_surface_destroy_listener; - MetaCursorRenderer *cursor_renderer; - MetaCursorSpriteXcursor *default_sprite; - gulong prepare_at_signal_id; - - MetaWaylandSurface *current; - guint32 pressed_buttons; - guint32 button_count; - - guint32 proximity_serial; - guint32 down_serial; - guint32 button_serial; - - float grab_x, grab_y; - - MetaWaylandTablet *current_tablet; -}; - -MetaWaylandTabletTool * meta_wayland_tablet_tool_new (MetaWaylandTabletSeat *seat, - ClutterInputDevice *device, - ClutterInputDeviceTool *device_tool); -void meta_wayland_tablet_tool_free (MetaWaylandTabletTool *tool); - -struct wl_resource * - meta_wayland_tablet_tool_create_new_resource (MetaWaylandTabletTool *tool, - struct wl_client *client, - struct wl_resource *seat_resource, - uint32_t id); -struct wl_resource * - meta_wayland_tablet_tool_lookup_resource (MetaWaylandTabletTool *tool, - struct wl_client *client); - -void meta_wayland_tablet_tool_update (MetaWaylandTabletTool *tool, - const ClutterEvent *event); -gboolean meta_wayland_tablet_tool_handle_event (MetaWaylandTabletTool *tool, - const ClutterEvent *event); - -gboolean meta_wayland_tablet_tool_can_grab_surface (MetaWaylandTabletTool *tool, - MetaWaylandSurface *surface, - uint32_t serial); -gboolean meta_wayland_tablet_tool_can_popup (MetaWaylandTabletTool *tool, - uint32_t serial); - -#endif /* META_WAYLAND_TABLET_TOOL_H */ diff --git a/src/wayland/meta-wayland-tablet.c b/src/wayland/meta-wayland-tablet.c deleted file mode 100644 index bb83bb255..000000000 --- a/src/wayland/meta-wayland-tablet.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2015 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: Carlos Garnacho - */ - -#include "config.h" - -#include "wayland/meta-wayland-tablet.h" - -#include -#include - -#include "compositor/meta-surface-actor-wayland.h" -#include "wayland/meta-wayland-private.h" - -#include "tablet-unstable-v2-server-protocol.h" - -static void -unbind_resource (struct wl_resource *resource) -{ - wl_list_remove (wl_resource_get_link (resource)); -} - -MetaWaylandTablet * -meta_wayland_tablet_new (ClutterInputDevice *device, - MetaWaylandTabletSeat *tablet_seat) -{ - MetaWaylandTablet *tablet; - - tablet = g_new0 (MetaWaylandTablet, 1); - wl_list_init (&tablet->resource_list); - tablet->device = device; - tablet->tablet_seat = tablet_seat; - - return tablet; -} - -void -meta_wayland_tablet_free (MetaWaylandTablet *tablet) -{ - struct wl_resource *resource, *next; - - wl_resource_for_each_safe (resource, next, &tablet->resource_list) - { - zwp_tablet_v2_send_removed (resource); - wl_list_remove (wl_resource_get_link (resource)); - wl_list_init (wl_resource_get_link (resource)); - } - - g_free (tablet); -} - -static void -tablet_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static const struct zwp_tablet_v2_interface tablet_interface = { - tablet_destroy -}; - -void -meta_wayland_tablet_notify (MetaWaylandTablet *tablet, - struct wl_resource *resource) -{ - ClutterInputDevice *device = tablet->device; - const gchar *node_path, *vendor, *product; - guint vid, pid; - - zwp_tablet_v2_send_name (resource, clutter_input_device_get_device_name (device)); - - node_path = clutter_input_device_get_device_node (device); - if (node_path) - zwp_tablet_v2_send_path (resource, node_path); - - vendor = clutter_input_device_get_vendor_id (device); - product = clutter_input_device_get_product_id (device); - - if (vendor && sscanf (vendor, "%x", &vid) == 1 && - product && sscanf (product, "%x", &pid) == 1) - zwp_tablet_v2_send_id (resource, vid, pid); - - zwp_tablet_v2_send_done (resource); -} - -struct wl_resource * -meta_wayland_tablet_create_new_resource (MetaWaylandTablet *tablet, - struct wl_client *client, - struct wl_resource *seat_resource, - uint32_t id) -{ - struct wl_resource *resource; - - resource = wl_resource_create (client, &zwp_tablet_v2_interface, - wl_resource_get_version (seat_resource), id); - wl_resource_set_implementation (resource, &tablet_interface, - tablet, unbind_resource); - wl_resource_set_user_data (resource, tablet); - wl_list_insert (&tablet->resource_list, wl_resource_get_link (resource)); - - return resource; -} - -struct wl_resource * -meta_wayland_tablet_lookup_resource (MetaWaylandTablet *tablet, - struct wl_client *client) -{ - return wl_resource_find_for_client (&tablet->resource_list, client); -} diff --git a/src/wayland/meta-wayland-tablet.h b/src/wayland/meta-wayland-tablet.h deleted file mode 100644 index 0bc3b87b9..000000000 --- a/src/wayland/meta-wayland-tablet.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2015 Red Hat - * - * 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 . - * - * Author: Carlos Garnacho - */ - -#ifndef META_WAYLAND_TABLET_H -#define META_WAYLAND_TABLET_H - -#include - -#include - -#include "backends/meta-cursor-renderer.h" -#include "wayland/meta-wayland-types.h" - -struct _MetaWaylandTablet -{ - MetaWaylandTabletSeat *tablet_seat; - ClutterInputDevice *device; - - struct wl_list resource_list; - - MetaWaylandSurface *current; -}; - -MetaWaylandTablet * meta_wayland_tablet_new (ClutterInputDevice *device, - MetaWaylandTabletSeat *tablet_seat); -void meta_wayland_tablet_free (MetaWaylandTablet *tablet); - -struct wl_resource * - meta_wayland_tablet_create_new_resource (MetaWaylandTablet *tablet, - struct wl_client *client, - struct wl_resource *seat_resource, - uint32_t id); -struct wl_resource * - meta_wayland_tablet_lookup_resource (MetaWaylandTablet *tablet, - struct wl_client *client); - -void meta_wayland_tablet_notify (MetaWaylandTablet *tablet, - struct wl_resource *resource); - -#endif /* META_WAYLAND_TABLET_H */ diff --git a/src/wayland/meta-wayland-text-input-legacy.c b/src/wayland/meta-wayland-text-input-legacy.c deleted file mode 100644 index 442708e0f..000000000 --- a/src/wayland/meta-wayland-text-input-legacy.c +++ /dev/null @@ -1,633 +0,0 @@ -/* - * Copyright (C) 2017, 2018 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: Carlos Garnacho - */ - -#include "config.h" - -#include - -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-seat.h" -#include "wayland/meta-wayland-text-input-legacy.h" -#include "wayland/meta-wayland-versions.h" - -#include "gtk-text-input-server-protocol.h" - -#define META_TYPE_WAYLAND_GTK_TEXT_INPUT_FOCUS (meta_wayland_gtk_text_input_focus_get_type ()) - -typedef enum -{ - META_WAYLAND_PENDING_STATE_NONE = 0, - META_WAYLAND_PENDING_STATE_INPUT_RECT = 1 << 0, - META_WAYLAND_PENDING_STATE_CONTENT_TYPE = 1 << 1, - META_WAYLAND_PENDING_STATE_SURROUNDING_TEXT = 1 << 2, -} MetaWaylandTextInputPendingState; - -typedef struct _MetaWaylandGtkTextInput MetaWaylandGtkTextInput; - -struct _MetaWaylandGtkTextInput -{ - MetaWaylandSeat *seat; - ClutterInputFocus *input_focus; - - struct wl_list resource_list; - struct wl_list focus_resource_list; - MetaWaylandSurface *surface; - struct wl_listener surface_listener; - uint32_t focus_serial; - - MetaWaylandTextInputPendingState pending_state; - - struct - { - char *text; - uint32_t cursor; - uint32_t anchor; - } surrounding; - - cairo_rectangle_int_t cursor_rect; - - uint32_t content_type_hint; - uint32_t content_type_purpose; -}; - -struct _MetaWaylandGtkTextInputFocus -{ - ClutterInputFocus parent_instance; - MetaWaylandGtkTextInput *text_input; -}; - -G_DECLARE_FINAL_TYPE (MetaWaylandGtkTextInputFocus, - meta_wayland_gtk_text_input_focus, - META, WAYLAND_GTK_TEXT_INPUT_FOCUS, ClutterInputFocus) -G_DEFINE_TYPE (MetaWaylandGtkTextInputFocus, meta_wayland_gtk_text_input_focus, - CLUTTER_TYPE_INPUT_FOCUS) - -static void -meta_wayland_text_input_focus_request_surrounding (ClutterInputFocus *focus) -{ - MetaWaylandGtkTextInput *text_input; - - text_input = META_WAYLAND_GTK_TEXT_INPUT_FOCUS (focus)->text_input; - clutter_input_focus_set_surrounding (focus, - text_input->surrounding.text, - text_input->surrounding.cursor, - text_input->surrounding.anchor); -} - -static void -meta_wayland_text_input_focus_delete_surrounding (ClutterInputFocus *focus, - int offset, - guint len) -{ - MetaWaylandGtkTextInput *text_input; - uint32_t before_length; - uint32_t after_length; - struct wl_resource *resource; - - text_input = META_WAYLAND_GTK_TEXT_INPUT_FOCUS (focus)->text_input; - before_length = ABS (MIN (offset, 0)); - after_length = MAX (0, offset + len); - g_warn_if_fail (ABS (offset) <= len); - - wl_resource_for_each (resource, &text_input->focus_resource_list) - { - gtk_text_input_send_delete_surrounding_text (resource, - before_length, - after_length); - } -} - -static void -meta_wayland_text_input_focus_commit_text (ClutterInputFocus *focus, - const gchar *text) -{ - MetaWaylandGtkTextInput *text_input; - struct wl_resource *resource; - - text_input = META_WAYLAND_GTK_TEXT_INPUT_FOCUS (focus)->text_input; - - wl_resource_for_each (resource, &text_input->focus_resource_list) - { - gtk_text_input_send_preedit_string (resource, NULL, 0); - gtk_text_input_send_commit_string (resource, text); - } -} - -static void -meta_wayland_text_input_focus_set_preedit_text (ClutterInputFocus *focus, - const gchar *text, - guint cursor) -{ - MetaWaylandGtkTextInput *text_input; - struct wl_resource *resource; - - text_input = META_WAYLAND_GTK_TEXT_INPUT_FOCUS (focus)->text_input; - - wl_resource_for_each (resource, &text_input->focus_resource_list) - { - gtk_text_input_send_preedit_string (resource, text, cursor); - } -} - -static void -meta_wayland_gtk_text_input_focus_class_init (MetaWaylandGtkTextInputFocusClass *klass) -{ - ClutterInputFocusClass *focus_class = CLUTTER_INPUT_FOCUS_CLASS (klass); - - focus_class->request_surrounding = meta_wayland_text_input_focus_request_surrounding; - focus_class->delete_surrounding = meta_wayland_text_input_focus_delete_surrounding; - focus_class->commit_text = meta_wayland_text_input_focus_commit_text; - focus_class->set_preedit_text = meta_wayland_text_input_focus_set_preedit_text; -} - -static void -meta_wayland_gtk_text_input_focus_init (MetaWaylandGtkTextInputFocus *focus) -{ -} - -static ClutterInputFocus * -meta_wayland_text_input_focus_new (MetaWaylandGtkTextInput *text_input) -{ - MetaWaylandGtkTextInputFocus *focus; - - focus = g_object_new (META_TYPE_WAYLAND_GTK_TEXT_INPUT_FOCUS, NULL); - focus->text_input = text_input; - - return CLUTTER_INPUT_FOCUS (focus); -} - -static void -text_input_handle_focus_surface_destroy (struct wl_listener *listener, - void *data) -{ - MetaWaylandGtkTextInput *text_input = wl_container_of (listener, text_input, - surface_listener); - - meta_wayland_gtk_text_input_set_focus (text_input, NULL); -} - -static void -move_resources (struct wl_list *destination, struct wl_list *source) -{ - wl_list_insert_list (destination, source); - wl_list_init (source); -} - -static void -move_resources_for_client (struct wl_list *destination, - struct wl_list *source, - struct wl_client *client) -{ - struct wl_resource *resource, *tmp; - wl_resource_for_each_safe (resource, tmp, source) - { - if (wl_resource_get_client (resource) == client) - { - wl_list_remove (wl_resource_get_link (resource)); - wl_list_insert (destination, wl_resource_get_link (resource)); - } - } -} - -void -meta_wayland_gtk_text_input_set_focus (MetaWaylandGtkTextInput *text_input, - MetaWaylandSurface *surface) -{ - if (text_input->surface == surface) - return; - - text_input->pending_state = META_WAYLAND_PENDING_STATE_NONE; - - if (text_input->surface) - { - if (!wl_list_empty (&text_input->focus_resource_list)) - { - ClutterInputFocus *focus = text_input->input_focus; - ClutterInputMethod *input_method; - struct wl_resource *resource; - uint32_t serial; - - if (clutter_input_focus_is_focused (focus)) - { - input_method = clutter_backend_get_input_method (clutter_get_default_backend ()); - clutter_input_method_focus_out (input_method); - } - - serial = wl_display_next_serial (text_input->seat->wl_display); - - wl_resource_for_each (resource, &text_input->focus_resource_list) - { - gtk_text_input_send_leave (resource, serial, - text_input->surface->resource); - } - - move_resources (&text_input->resource_list, - &text_input->focus_resource_list); - } - - wl_list_remove (&text_input->surface_listener.link); - text_input->surface = NULL; - } - - if (surface) - { - struct wl_resource *focus_surface_resource; - - text_input->surface = surface; - focus_surface_resource = text_input->surface->resource; - wl_resource_add_destroy_listener (focus_surface_resource, - &text_input->surface_listener); - - move_resources_for_client (&text_input->focus_resource_list, - &text_input->resource_list, - wl_resource_get_client (focus_surface_resource)); - - if (!wl_list_empty (&text_input->focus_resource_list)) - { - struct wl_resource *resource; - - text_input->focus_serial = - wl_display_next_serial (text_input->seat->wl_display); - - wl_resource_for_each (resource, &text_input->focus_resource_list) - { - gtk_text_input_send_enter (resource, text_input->focus_serial, - surface->resource); - } - } - } -} - -static void -unbind_resource (struct wl_resource *resource) -{ - wl_list_remove (wl_resource_get_link (resource)); -} - -static void -text_input_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -text_input_enable (struct wl_client *client, - struct wl_resource *resource, - uint32_t serial, - uint32_t flags) -{ - MetaWaylandGtkTextInput *text_input = wl_resource_get_user_data (resource); - ClutterInputFocus *focus = text_input->input_focus; - ClutterInputMethod *input_method; - gboolean show_preedit; - - if (serial != text_input->focus_serial) - return; - - if (!clutter_input_focus_is_focused (focus)) - { - input_method = clutter_backend_get_input_method (clutter_get_default_backend ()); - if (input_method) - clutter_input_method_focus_in (input_method, focus); - else - return; - } - - show_preedit = (flags & GTK_TEXT_INPUT_ENABLE_FLAGS_CAN_SHOW_PREEDIT) != 0; - clutter_input_focus_set_can_show_preedit (focus, show_preedit); - - if (flags & GTK_TEXT_INPUT_ENABLE_FLAGS_TOGGLE_INPUT_PANEL) - clutter_input_focus_set_input_panel_state (focus, CLUTTER_INPUT_PANEL_STATE_TOGGLE); -} - -static void -text_input_disable (struct wl_client *client, - struct wl_resource *resource) -{ - MetaWaylandGtkTextInput *text_input = wl_resource_get_user_data (resource); - ClutterInputFocus *focus = text_input->input_focus; - ClutterInputMethod *input_method; - - if (!clutter_input_focus_is_focused (focus)) - return; - - clutter_input_focus_reset (text_input->input_focus); - text_input->pending_state = META_WAYLAND_PENDING_STATE_NONE; - - input_method = clutter_backend_get_input_method (clutter_get_default_backend ()); - clutter_input_method_focus_out (input_method); -} - -static void -text_input_set_surrounding_text (struct wl_client *client, - struct wl_resource *resource, - const char *text, - int32_t cursor, - int32_t anchor) -{ - MetaWaylandGtkTextInput *text_input = wl_resource_get_user_data (resource); - - g_free (text_input->surrounding.text); - text_input->surrounding.text = g_strdup (text); - text_input->surrounding.cursor = cursor; - text_input->surrounding.anchor = anchor; - text_input->pending_state |= META_WAYLAND_PENDING_STATE_SURROUNDING_TEXT; -} - -static ClutterInputContentHintFlags -translate_hints (uint32_t hints) -{ - ClutterInputContentHintFlags clutter_hints = 0; - - if (hints & GTK_TEXT_INPUT_CONTENT_HINT_COMPLETION) - clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_COMPLETION; - if (hints & GTK_TEXT_INPUT_CONTENT_HINT_SPELLCHECK) - clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_SPELLCHECK; - if (hints & GTK_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION) - clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION; - if (hints & GTK_TEXT_INPUT_CONTENT_HINT_LOWERCASE) - clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_LOWERCASE; - if (hints & GTK_TEXT_INPUT_CONTENT_HINT_UPPERCASE) - clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_UPPERCASE; - if (hints & GTK_TEXT_INPUT_CONTENT_HINT_TITLECASE) - clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_TITLECASE; - if (hints & GTK_TEXT_INPUT_CONTENT_HINT_HIDDEN_TEXT) - clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_HIDDEN_TEXT; - if (hints & GTK_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA) - clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_SENSITIVE_DATA; - if (hints & GTK_TEXT_INPUT_CONTENT_HINT_LATIN) - clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_LATIN; - if (hints & GTK_TEXT_INPUT_CONTENT_HINT_MULTILINE) - clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_MULTILINE; - - return clutter_hints; -} - -static ClutterInputContentPurpose -translate_purpose (uint32_t purpose) -{ - switch (purpose) - { - case GTK_TEXT_INPUT_CONTENT_PURPOSE_NORMAL: - return CLUTTER_INPUT_CONTENT_PURPOSE_NORMAL; - case GTK_TEXT_INPUT_CONTENT_PURPOSE_ALPHA: - return CLUTTER_INPUT_CONTENT_PURPOSE_ALPHA; - case GTK_TEXT_INPUT_CONTENT_PURPOSE_DIGITS: - return CLUTTER_INPUT_CONTENT_PURPOSE_DIGITS; - case GTK_TEXT_INPUT_CONTENT_PURPOSE_NUMBER: - return CLUTTER_INPUT_CONTENT_PURPOSE_NUMBER; - case GTK_TEXT_INPUT_CONTENT_PURPOSE_PHONE: - return CLUTTER_INPUT_CONTENT_PURPOSE_PHONE; - case GTK_TEXT_INPUT_CONTENT_PURPOSE_URL: - return CLUTTER_INPUT_CONTENT_PURPOSE_URL; - case GTK_TEXT_INPUT_CONTENT_PURPOSE_EMAIL: - return CLUTTER_INPUT_CONTENT_PURPOSE_EMAIL; - case GTK_TEXT_INPUT_CONTENT_PURPOSE_NAME: - return CLUTTER_INPUT_CONTENT_PURPOSE_NAME; - case GTK_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD: - return CLUTTER_INPUT_CONTENT_PURPOSE_PASSWORD; - case GTK_TEXT_INPUT_CONTENT_PURPOSE_DATE: - return CLUTTER_INPUT_CONTENT_PURPOSE_DATE; - case GTK_TEXT_INPUT_CONTENT_PURPOSE_TIME: - return CLUTTER_INPUT_CONTENT_PURPOSE_TIME; - case GTK_TEXT_INPUT_CONTENT_PURPOSE_DATETIME: - return CLUTTER_INPUT_CONTENT_PURPOSE_DATETIME; - case GTK_TEXT_INPUT_CONTENT_PURPOSE_TERMINAL: - return CLUTTER_INPUT_CONTENT_PURPOSE_TERMINAL; - } - - g_warn_if_reached (); - return CLUTTER_INPUT_CONTENT_PURPOSE_NORMAL; -} - -static void -text_input_set_content_type (struct wl_client *client, - struct wl_resource *resource, - uint32_t hint, - uint32_t purpose) -{ - MetaWaylandGtkTextInput *text_input = wl_resource_get_user_data (resource); - - if (!text_input->surface) - return; - - text_input->content_type_hint = hint; - text_input->content_type_purpose = purpose; - text_input->pending_state |= META_WAYLAND_PENDING_STATE_CONTENT_TYPE; -} - -static void -text_input_set_cursor_rectangle (struct wl_client *client, - struct wl_resource *resource, - int32_t x, - int32_t y, - int32_t width, - int32_t height) -{ - MetaWaylandGtkTextInput *text_input = wl_resource_get_user_data (resource); - - if (!text_input->surface) - return; - - text_input->cursor_rect = (cairo_rectangle_int_t) { x, y, width, height }; - text_input->pending_state |= META_WAYLAND_PENDING_STATE_INPUT_RECT; -} - -static void -text_input_commit_state (struct wl_client *client, - struct wl_resource *resource) -{ - MetaWaylandGtkTextInput *text_input = wl_resource_get_user_data (resource); - ClutterInputFocus *focus = text_input->input_focus; - - if (!clutter_input_focus_is_focused (focus)) - return; - if (text_input->surface == NULL) - return; - - if (text_input->pending_state & META_WAYLAND_PENDING_STATE_CONTENT_TYPE) - { - clutter_input_focus_set_content_hints (text_input->input_focus, - translate_hints (text_input->content_type_hint)); - clutter_input_focus_set_content_purpose (text_input->input_focus, - translate_purpose (text_input->content_type_purpose)); - } - - if (text_input->pending_state & META_WAYLAND_PENDING_STATE_SURROUNDING_TEXT) - { - clutter_input_focus_set_surrounding (text_input->input_focus, - text_input->surrounding.text, - text_input->surrounding.cursor, - text_input->surrounding.anchor); - } - - if (text_input->pending_state & META_WAYLAND_PENDING_STATE_INPUT_RECT) - { - graphene_rect_t cursor_rect; - float x1, y1, x2, y2; - cairo_rectangle_int_t rect; - - rect = text_input->cursor_rect; - meta_wayland_surface_get_absolute_coordinates (text_input->surface, - rect.x, rect.y, &x1, &y1); - meta_wayland_surface_get_absolute_coordinates (text_input->surface, - rect.x + rect.width, - rect.y + rect.height, - &x2, &y2); - - graphene_rect_init (&cursor_rect, x1, y1, x2 - x1, y2 - y1); - clutter_input_focus_set_cursor_location (text_input->input_focus, - &cursor_rect); - } - - text_input->pending_state = META_WAYLAND_PENDING_STATE_NONE; -} - -static struct gtk_text_input_interface meta_text_input_interface = { - text_input_destroy, - text_input_enable, - text_input_disable, - text_input_set_surrounding_text, - text_input_set_content_type, - text_input_set_cursor_rectangle, - text_input_commit_state, -}; - -MetaWaylandGtkTextInput * -meta_wayland_gtk_text_input_new (MetaWaylandSeat *seat) -{ - MetaWaylandGtkTextInput *text_input; - - text_input = g_new0 (MetaWaylandGtkTextInput, 1); - text_input->input_focus = meta_wayland_text_input_focus_new (text_input); - text_input->seat = seat; - - wl_list_init (&text_input->resource_list); - wl_list_init (&text_input->focus_resource_list); - text_input->surface_listener.notify = text_input_handle_focus_surface_destroy; - - return text_input; -} - -void -meta_wayland_gtk_text_input_destroy (MetaWaylandGtkTextInput *text_input) -{ - meta_wayland_gtk_text_input_set_focus (text_input, NULL); - g_object_unref (text_input->input_focus); - g_free (text_input); -} - -static void -meta_wayland_text_input_create_new_resource (MetaWaylandGtkTextInput *text_input, - struct wl_client *client, - struct wl_resource *seat_resource, - uint32_t id) -{ - struct wl_resource *text_input_resource; - - text_input_resource = wl_resource_create (client, - >k_text_input_interface, - META_GTK_TEXT_INPUT_VERSION, - id); - - wl_resource_set_implementation (text_input_resource, - &meta_text_input_interface, - text_input, unbind_resource); - - if (text_input->surface && - wl_resource_get_client (text_input->surface->resource) == client) - { - wl_list_insert (&text_input->focus_resource_list, - wl_resource_get_link (text_input_resource)); - - gtk_text_input_send_enter (text_input_resource, - text_input->focus_serial, - text_input->surface->resource); - } - else - { - wl_list_insert (&text_input->resource_list, - wl_resource_get_link (text_input_resource)); - } -} - -static void -text_input_manager_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -text_input_manager_get_text_input (struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *seat_resource) -{ - MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); - - meta_wayland_text_input_create_new_resource (seat->gtk_text_input, client, - seat_resource, id); -} - -static struct gtk_text_input_manager_interface meta_text_input_manager_interface = { - text_input_manager_destroy, - text_input_manager_get_text_input, -}; - -static void -bind_text_input (struct wl_client *client, - void *data, - uint32_t version, - uint32_t id) -{ - struct wl_resource *resource; - - resource = wl_resource_create (client, - >k_text_input_manager_interface, - META_GTK_TEXT_INPUT_VERSION, - id); - wl_resource_set_implementation (resource, - &meta_text_input_manager_interface, - NULL, NULL); -} - -gboolean -meta_wayland_gtk_text_input_init (MetaWaylandCompositor *compositor) -{ - return (wl_global_create (compositor->wayland_display, - >k_text_input_manager_interface, - META_GTK_TEXT_INPUT_VERSION, - compositor->seat->gtk_text_input, - bind_text_input) != NULL); -} - -gboolean -meta_wayland_gtk_text_input_handle_event (MetaWaylandGtkTextInput *text_input, - const ClutterEvent *event) -{ - if (!text_input->surface || - !clutter_input_focus_is_focused (text_input->input_focus)) - return FALSE; - - return clutter_input_focus_filter_event (text_input->input_focus, event); -} diff --git a/src/wayland/meta-wayland-text-input-legacy.h b/src/wayland/meta-wayland-text-input-legacy.h deleted file mode 100644 index 55bfed809..000000000 --- a/src/wayland/meta-wayland-text-input-legacy.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2017 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: Carlos Garnacho - */ - -#ifndef META_WAYLAND_GTK_TEXT_INPUT_H -#define META_WAYLAND_GTK_TEXT_INPUT_H - -#include - -#include "meta/window.h" -#include "wayland/meta-wayland-types.h" - -typedef struct _MetaWaylandGtkTextInput MetaWaylandGtkTextInput; - -MetaWaylandGtkTextInput * meta_wayland_gtk_text_input_new (MetaWaylandSeat *seat); -void meta_wayland_gtk_text_input_destroy (MetaWaylandGtkTextInput *text_input); - -gboolean meta_wayland_gtk_text_input_init (MetaWaylandCompositor *compositor); - -void meta_wayland_gtk_text_input_set_focus (MetaWaylandGtkTextInput *text_input, - MetaWaylandSurface *surface); - -gboolean meta_wayland_gtk_text_input_handle_event (MetaWaylandGtkTextInput *text_input, - const ClutterEvent *event); - -#endif /* META_WAYLAND_GTK_TEXT_INPUT_H */ diff --git a/src/wayland/meta-wayland-text-input.c b/src/wayland/meta-wayland-text-input.c deleted file mode 100644 index b471e8e1a..000000000 --- a/src/wayland/meta-wayland-text-input.c +++ /dev/null @@ -1,766 +0,0 @@ -/* - * Copyright (C) 2017, 2018 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: Carlos Garnacho - */ - -#include "config.h" - -#include "wayland/meta-wayland-text-input.h" - -#include - -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-seat.h" -#include "wayland/meta-wayland-versions.h" - -#include "text-input-unstable-v3-server-protocol.h" - -#define META_TYPE_WAYLAND_TEXT_INPUT_FOCUS (meta_wayland_text_input_focus_get_type ()) - -typedef enum -{ - META_WAYLAND_PENDING_STATE_NONE = 0, - META_WAYLAND_PENDING_STATE_INPUT_RECT = 1 << 0, - META_WAYLAND_PENDING_STATE_CONTENT_TYPE = 1 << 1, - META_WAYLAND_PENDING_STATE_SURROUNDING_TEXT = 1 << 2, - META_WAYLAND_PENDING_STATE_CHANGE_CAUSE = 1 << 3, - META_WAYLAND_PENDING_STATE_ENABLED = 1 << 4, -} MetaWaylandTextInputPendingState; - -typedef struct _MetaWaylandTextInput MetaWaylandTextInput; - -struct _MetaWaylandTextInput -{ - MetaWaylandSeat *seat; - ClutterInputFocus *input_focus; - - struct wl_list resource_list; - struct wl_list focus_resource_list; - MetaWaylandSurface *surface; - struct wl_listener surface_listener; - - MetaWaylandTextInputPendingState pending_state; - - GHashTable *resource_serials; - - struct - { - char *text; - uint32_t cursor; - uint32_t anchor; - } surrounding; - - cairo_rectangle_int_t cursor_rect; - - uint32_t content_type_hint; - uint32_t content_type_purpose; - uint32_t text_change_cause; - gboolean enabled; - - guint done_idle_id; -}; - -struct _MetaWaylandTextInputFocus -{ - ClutterInputFocus parent_instance; - MetaWaylandTextInput *text_input; -}; - -G_DECLARE_FINAL_TYPE (MetaWaylandTextInputFocus, meta_wayland_text_input_focus, - META, WAYLAND_TEXT_INPUT_FOCUS, ClutterInputFocus) -G_DEFINE_TYPE (MetaWaylandTextInputFocus, meta_wayland_text_input_focus, - CLUTTER_TYPE_INPUT_FOCUS) - -static void -meta_wayland_text_input_focus_request_surrounding (ClutterInputFocus *focus) -{ - MetaWaylandTextInput *text_input; - - text_input = META_WAYLAND_TEXT_INPUT_FOCUS (focus)->text_input; - clutter_input_focus_set_surrounding (focus, - text_input->surrounding.text, - text_input->surrounding.cursor, - text_input->surrounding.anchor); -} - -static uint32_t -lookup_serial (MetaWaylandTextInput *text_input, - struct wl_resource *resource) -{ - return GPOINTER_TO_UINT (g_hash_table_lookup (text_input->resource_serials, - resource)); -} - -static void -increment_serial (MetaWaylandTextInput *text_input, - struct wl_resource *resource) -{ - uint32_t serial; - - serial = lookup_serial (text_input, resource); - g_hash_table_insert (text_input->resource_serials, resource, - GUINT_TO_POINTER (serial + 1)); -} - -static void -clutter_input_focus_send_done (ClutterInputFocus *focus) -{ - MetaWaylandTextInput *text_input; - struct wl_resource *resource; - - text_input = META_WAYLAND_TEXT_INPUT_FOCUS (focus)->text_input; - - wl_resource_for_each (resource, &text_input->focus_resource_list) - { - zwp_text_input_v3_send_done (resource, - lookup_serial (text_input, resource)); - } -} - -static gboolean -done_idle_cb (gpointer user_data) -{ - ClutterInputFocus *focus = user_data; - MetaWaylandTextInput *text_input; - - text_input = META_WAYLAND_TEXT_INPUT_FOCUS (focus)->text_input; - clutter_input_focus_send_done (focus); - - text_input->done_idle_id = 0; - return G_SOURCE_REMOVE; -} - -static void -meta_wayland_text_input_focus_defer_done (ClutterInputFocus *focus) -{ - MetaWaylandTextInput *text_input; - - text_input = META_WAYLAND_TEXT_INPUT_FOCUS (focus)->text_input; - - if (text_input->done_idle_id != 0) - return; - - /* This operates on 2 principles: - * - IM operations come as individual ClutterEvents - * - We want to run .done after them all. The slightly lower - * CLUTTER_PRIORITY_EVENTS + 1 priority should ensure we at least group - * all events seen so far. - * - * FIXME: .done may be delayed indefinitely if there's a high enough - * priority idle source in the main loop. It's unlikely that - * recurring idles run at this high priority though. - */ - text_input->done_idle_id = g_idle_add_full (CLUTTER_PRIORITY_EVENTS + 1, - done_idle_cb, focus, NULL); -} - -static void -meta_wayland_text_input_focus_flush_done (ClutterInputFocus *focus) -{ - MetaWaylandTextInput *text_input; - - text_input = META_WAYLAND_TEXT_INPUT_FOCUS (focus)->text_input; - - if (text_input->done_idle_id == 0) - return; - - g_clear_handle_id (&text_input->done_idle_id, g_source_remove); - clutter_input_focus_send_done (focus); -} - -static void -meta_wayland_text_input_focus_delete_surrounding (ClutterInputFocus *focus, - int offset, - guint len) -{ - MetaWaylandTextInput *text_input; - uint32_t before_length; - uint32_t after_length; - struct wl_resource *resource; - - text_input = META_WAYLAND_TEXT_INPUT_FOCUS (focus)->text_input; - before_length = ABS (MIN (offset, 0)); - after_length = MAX (0, offset + len); - g_warn_if_fail (ABS (offset) <= len); - - wl_resource_for_each (resource, &text_input->focus_resource_list) - { - zwp_text_input_v3_send_delete_surrounding_text (resource, - before_length, - after_length); - } - - meta_wayland_text_input_focus_defer_done (focus); -} - -static void -meta_wayland_text_input_focus_commit_text (ClutterInputFocus *focus, - const gchar *text) -{ - MetaWaylandTextInput *text_input; - struct wl_resource *resource; - - text_input = META_WAYLAND_TEXT_INPUT_FOCUS (focus)->text_input; - - wl_resource_for_each (resource, &text_input->focus_resource_list) - { - zwp_text_input_v3_send_preedit_string (resource, NULL, 0, 0); - zwp_text_input_v3_send_commit_string (resource, text); - } - - meta_wayland_text_input_focus_defer_done (focus); -} - -static void -meta_wayland_text_input_focus_set_preedit_text (ClutterInputFocus *focus, - const gchar *text, - guint cursor) -{ - MetaWaylandTextInput *text_input; - struct wl_resource *resource; - gsize pos = 0; - - text_input = META_WAYLAND_TEXT_INPUT_FOCUS (focus)->text_input; - - if (text) - pos = g_utf8_offset_to_pointer (text, cursor) - text; - - wl_resource_for_each (resource, &text_input->focus_resource_list) - { - zwp_text_input_v3_send_preedit_string (resource, text, pos, pos); - } - - meta_wayland_text_input_focus_defer_done (focus); -} - -static void -meta_wayland_text_input_focus_class_init (MetaWaylandTextInputFocusClass *klass) -{ - ClutterInputFocusClass *focus_class = CLUTTER_INPUT_FOCUS_CLASS (klass); - - focus_class->request_surrounding = meta_wayland_text_input_focus_request_surrounding; - focus_class->delete_surrounding = meta_wayland_text_input_focus_delete_surrounding; - focus_class->commit_text = meta_wayland_text_input_focus_commit_text; - focus_class->set_preedit_text = meta_wayland_text_input_focus_set_preedit_text; -} - -static void -meta_wayland_text_input_focus_init (MetaWaylandTextInputFocus *focus) -{ -} - -static ClutterInputFocus * -meta_wayland_text_input_focus_new (MetaWaylandTextInput *text_input) -{ - MetaWaylandTextInputFocus *focus; - - focus = g_object_new (META_TYPE_WAYLAND_TEXT_INPUT_FOCUS, NULL); - focus->text_input = text_input; - - return CLUTTER_INPUT_FOCUS (focus); -} - -static void -text_input_handle_focus_surface_destroy (struct wl_listener *listener, - void *data) -{ - MetaWaylandTextInput *text_input = wl_container_of (listener, text_input, - surface_listener); - - meta_wayland_text_input_set_focus (text_input, NULL); -} - -static void -move_resources (struct wl_list *destination, struct wl_list *source) -{ - wl_list_insert_list (destination, source); - wl_list_init (source); -} - -static void -move_resources_for_client (struct wl_list *destination, - struct wl_list *source, - struct wl_client *client) -{ - struct wl_resource *resource, *tmp; - wl_resource_for_each_safe (resource, tmp, source) - { - if (wl_resource_get_client (resource) == client) - { - wl_list_remove (wl_resource_get_link (resource)); - wl_list_insert (destination, wl_resource_get_link (resource)); - } - } -} - -void -meta_wayland_text_input_set_focus (MetaWaylandTextInput *text_input, - MetaWaylandSurface *surface) -{ - if (text_input->surface == surface) - return; - - text_input->pending_state = META_WAYLAND_PENDING_STATE_NONE; - - if (text_input->surface) - { - if (!wl_list_empty (&text_input->focus_resource_list)) - { - ClutterInputFocus *focus = text_input->input_focus; - ClutterInputMethod *input_method; - struct wl_resource *resource; - - if (clutter_input_focus_is_focused (focus)) - { - input_method = clutter_backend_get_input_method (clutter_get_default_backend ()); - clutter_input_method_focus_out (input_method); - } - - wl_resource_for_each (resource, &text_input->focus_resource_list) - { - zwp_text_input_v3_send_leave (resource, - text_input->surface->resource); - } - - move_resources (&text_input->resource_list, - &text_input->focus_resource_list); - } - - wl_list_remove (&text_input->surface_listener.link); - text_input->surface = NULL; - } - - if (surface) - { - struct wl_resource *focus_surface_resource; - - text_input->surface = surface; - focus_surface_resource = text_input->surface->resource; - wl_resource_add_destroy_listener (focus_surface_resource, - &text_input->surface_listener); - - move_resources_for_client (&text_input->focus_resource_list, - &text_input->resource_list, - wl_resource_get_client (focus_surface_resource)); - - if (!wl_list_empty (&text_input->focus_resource_list)) - { - struct wl_resource *resource; - - wl_resource_for_each (resource, &text_input->focus_resource_list) - { - zwp_text_input_v3_send_enter (resource, surface->resource); - } - } - } -} - -static void -text_input_destructor (struct wl_resource *resource) -{ - MetaWaylandTextInput *text_input = wl_resource_get_user_data (resource); - - g_hash_table_remove (text_input->resource_serials, resource); - wl_list_remove (wl_resource_get_link (resource)); -} - -static void -text_input_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -text_input_enable (struct wl_client *client, - struct wl_resource *resource) -{ - MetaWaylandTextInput *text_input = wl_resource_get_user_data (resource); - - text_input->enabled = TRUE; - text_input->pending_state |= META_WAYLAND_PENDING_STATE_ENABLED; -} - -static void -text_input_disable (struct wl_client *client, - struct wl_resource *resource) -{ - MetaWaylandTextInput *text_input = wl_resource_get_user_data (resource); - - text_input->enabled = FALSE; - text_input->pending_state |= META_WAYLAND_PENDING_STATE_ENABLED; -} - -static void -text_input_set_surrounding_text (struct wl_client *client, - struct wl_resource *resource, - const char *text, - int32_t cursor, - int32_t anchor) -{ - MetaWaylandTextInput *text_input = wl_resource_get_user_data (resource); - - g_free (text_input->surrounding.text); - text_input->surrounding.text = g_strdup (text); - text_input->surrounding.cursor = cursor; - text_input->surrounding.anchor = anchor; - text_input->pending_state |= META_WAYLAND_PENDING_STATE_SURROUNDING_TEXT; -} - -static void -text_input_set_text_change_cause (struct wl_client *client, - struct wl_resource *resource, - uint32_t cause) -{ - MetaWaylandTextInput *text_input = wl_resource_get_user_data (resource); - - text_input->text_change_cause = cause; - text_input->pending_state |= META_WAYLAND_PENDING_STATE_CHANGE_CAUSE; -} - -static ClutterInputContentHintFlags -translate_hints (uint32_t hints) -{ - ClutterInputContentHintFlags clutter_hints = 0; - - if (hints & ZWP_TEXT_INPUT_V3_CONTENT_HINT_COMPLETION) - clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_COMPLETION; - if (hints & ZWP_TEXT_INPUT_V3_CONTENT_HINT_SPELLCHECK) - clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_SPELLCHECK; - if (hints & ZWP_TEXT_INPUT_V3_CONTENT_HINT_AUTO_CAPITALIZATION) - clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION; - if (hints & ZWP_TEXT_INPUT_V3_CONTENT_HINT_LOWERCASE) - clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_LOWERCASE; - if (hints & ZWP_TEXT_INPUT_V3_CONTENT_HINT_UPPERCASE) - clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_UPPERCASE; - if (hints & ZWP_TEXT_INPUT_V3_CONTENT_HINT_TITLECASE) - clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_TITLECASE; - if (hints & ZWP_TEXT_INPUT_V3_CONTENT_HINT_HIDDEN_TEXT) - clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_HIDDEN_TEXT; - if (hints & ZWP_TEXT_INPUT_V3_CONTENT_HINT_SENSITIVE_DATA) - clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_SENSITIVE_DATA; - if (hints & ZWP_TEXT_INPUT_V3_CONTENT_HINT_LATIN) - clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_LATIN; - if (hints & ZWP_TEXT_INPUT_V3_CONTENT_HINT_MULTILINE) - clutter_hints |= CLUTTER_INPUT_CONTENT_HINT_MULTILINE; - - return clutter_hints; -} - -static ClutterInputContentPurpose -translate_purpose (uint32_t purpose) -{ - switch (purpose) - { - case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NORMAL: - return CLUTTER_INPUT_CONTENT_PURPOSE_NORMAL; - case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_ALPHA: - return CLUTTER_INPUT_CONTENT_PURPOSE_ALPHA; - case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_DIGITS: - return CLUTTER_INPUT_CONTENT_PURPOSE_DIGITS; - case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NUMBER: - return CLUTTER_INPUT_CONTENT_PURPOSE_NUMBER; - case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PHONE: - return CLUTTER_INPUT_CONTENT_PURPOSE_PHONE; - case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_URL: - return CLUTTER_INPUT_CONTENT_PURPOSE_URL; - case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_EMAIL: - return CLUTTER_INPUT_CONTENT_PURPOSE_EMAIL; - case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NAME: - return CLUTTER_INPUT_CONTENT_PURPOSE_NAME; - case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_PASSWORD: - return CLUTTER_INPUT_CONTENT_PURPOSE_PASSWORD; - case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_DATE: - return CLUTTER_INPUT_CONTENT_PURPOSE_DATE; - case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TIME: - return CLUTTER_INPUT_CONTENT_PURPOSE_TIME; - case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_DATETIME: - return CLUTTER_INPUT_CONTENT_PURPOSE_DATETIME; - case ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_TERMINAL: - return CLUTTER_INPUT_CONTENT_PURPOSE_TERMINAL; - } - - g_warn_if_reached (); - return CLUTTER_INPUT_CONTENT_PURPOSE_NORMAL; -} - -static void -text_input_set_content_type (struct wl_client *client, - struct wl_resource *resource, - uint32_t hint, - uint32_t purpose) -{ - MetaWaylandTextInput *text_input = wl_resource_get_user_data (resource); - - if (!text_input->surface) - return; - - text_input->content_type_hint = hint; - text_input->content_type_purpose = purpose; - text_input->pending_state |= META_WAYLAND_PENDING_STATE_CONTENT_TYPE; -} - -static void -text_input_set_cursor_rectangle (struct wl_client *client, - struct wl_resource *resource, - int32_t x, - int32_t y, - int32_t width, - int32_t height) -{ - MetaWaylandTextInput *text_input = wl_resource_get_user_data (resource); - - if (!text_input->surface) - return; - - text_input->cursor_rect = (cairo_rectangle_int_t) { x, y, width, height }; - text_input->pending_state |= META_WAYLAND_PENDING_STATE_INPUT_RECT; -} - -static void -meta_wayland_text_input_reset (MetaWaylandTextInput *text_input) -{ - g_clear_pointer (&text_input->surrounding.text, g_free); - text_input->content_type_hint = ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE; - text_input->content_type_purpose = ZWP_TEXT_INPUT_V3_CONTENT_PURPOSE_NORMAL; - text_input->text_change_cause = ZWP_TEXT_INPUT_V3_CHANGE_CAUSE_INPUT_METHOD; - text_input->cursor_rect = (cairo_rectangle_int_t) { 0, 0, 0, 0 }; - text_input->pending_state = META_WAYLAND_PENDING_STATE_NONE; -} - -static void -text_input_commit_state (struct wl_client *client, - struct wl_resource *resource) -{ - MetaWaylandTextInput *text_input = wl_resource_get_user_data (resource); - ClutterInputFocus *focus = text_input->input_focus; - gboolean enable_panel = FALSE; - ClutterInputMethod *input_method; - - increment_serial (text_input, resource); - - if (text_input->surface == NULL) - return; - - input_method = clutter_backend_get_input_method (clutter_get_default_backend ()); - - if (input_method && - text_input->pending_state & META_WAYLAND_PENDING_STATE_ENABLED) - { - if (text_input->enabled) - { - if (!clutter_input_focus_is_focused (focus)) - clutter_input_method_focus_in (input_method, focus); - else - enable_panel = TRUE; - - clutter_input_focus_set_can_show_preedit (focus, TRUE); - } - else if (clutter_input_focus_is_focused (focus)) - { - text_input->pending_state = META_WAYLAND_PENDING_STATE_NONE; - clutter_input_focus_reset (text_input->input_focus); - clutter_input_method_focus_out (input_method); - } - } - - if (!clutter_input_focus_is_focused (focus)) - { - meta_wayland_text_input_reset (text_input); - return; - } - - if (text_input->pending_state & META_WAYLAND_PENDING_STATE_CONTENT_TYPE) - { - clutter_input_focus_set_content_hints (text_input->input_focus, - translate_hints (text_input->content_type_hint)); - clutter_input_focus_set_content_purpose (text_input->input_focus, - translate_purpose (text_input->content_type_purpose)); - } - - if (text_input->pending_state & META_WAYLAND_PENDING_STATE_SURROUNDING_TEXT) - { - clutter_input_focus_set_surrounding (text_input->input_focus, - text_input->surrounding.text, - text_input->surrounding.cursor, - text_input->surrounding.anchor); - } - - if (text_input->pending_state & META_WAYLAND_PENDING_STATE_INPUT_RECT) - { - graphene_rect_t cursor_rect; - float x1, y1, x2, y2; - cairo_rectangle_int_t rect; - - rect = text_input->cursor_rect; - meta_wayland_surface_get_absolute_coordinates (text_input->surface, - rect.x, rect.y, &x1, &y1); - meta_wayland_surface_get_absolute_coordinates (text_input->surface, - rect.x + rect.width, - rect.y + rect.height, - &x2, &y2); - - graphene_rect_init (&cursor_rect, x1, y1, x2 - x1, y2 - y1); - clutter_input_focus_set_cursor_location (text_input->input_focus, - &cursor_rect); - } - - meta_wayland_text_input_reset (text_input); - - if (enable_panel) - clutter_input_focus_set_input_panel_state (focus, CLUTTER_INPUT_PANEL_STATE_ON); -} - -static struct zwp_text_input_v3_interface meta_text_input_interface = { - text_input_destroy, - text_input_enable, - text_input_disable, - text_input_set_surrounding_text, - text_input_set_text_change_cause, - text_input_set_content_type, - text_input_set_cursor_rectangle, - text_input_commit_state, -}; - -MetaWaylandTextInput * -meta_wayland_text_input_new (MetaWaylandSeat *seat) -{ - MetaWaylandTextInput *text_input; - - text_input = g_new0 (MetaWaylandTextInput, 1); - text_input->input_focus = meta_wayland_text_input_focus_new (text_input); - text_input->seat = seat; - - wl_list_init (&text_input->resource_list); - wl_list_init (&text_input->focus_resource_list); - text_input->surface_listener.notify = text_input_handle_focus_surface_destroy; - - text_input->resource_serials = g_hash_table_new (NULL, NULL); - - return text_input; -} - -void -meta_wayland_text_input_destroy (MetaWaylandTextInput *text_input) -{ - meta_wayland_text_input_set_focus (text_input, NULL); - g_object_unref (text_input->input_focus); - g_hash_table_destroy (text_input->resource_serials); - g_free (text_input); -} - -static void -meta_wayland_text_input_create_new_resource (MetaWaylandTextInput *text_input, - struct wl_client *client, - struct wl_resource *seat_resource, - uint32_t id) -{ - struct wl_resource *text_input_resource; - - text_input_resource = wl_resource_create (client, - &zwp_text_input_v3_interface, - META_ZWP_TEXT_INPUT_V3_VERSION, - id); - - wl_resource_set_implementation (text_input_resource, - &meta_text_input_interface, - text_input, text_input_destructor); - - if (text_input->surface && - wl_resource_get_client (text_input->surface->resource) == client) - { - wl_list_insert (&text_input->focus_resource_list, - wl_resource_get_link (text_input_resource)); - - zwp_text_input_v3_send_enter (text_input_resource, - text_input->surface->resource); - } - else - { - wl_list_insert (&text_input->resource_list, - wl_resource_get_link (text_input_resource)); - } -} - -static void -text_input_manager_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -text_input_manager_get_text_input (struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *seat_resource) -{ - MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); - - meta_wayland_text_input_create_new_resource (seat->text_input, client, - seat_resource, id); -} - -static struct zwp_text_input_manager_v3_interface meta_text_input_manager_interface = { - text_input_manager_destroy, - text_input_manager_get_text_input, -}; - -static void -bind_text_input (struct wl_client *client, - void *data, - uint32_t version, - uint32_t id) -{ - struct wl_resource *resource; - - resource = wl_resource_create (client, - &zwp_text_input_manager_v3_interface, - META_ZWP_TEXT_INPUT_V3_VERSION, - id); - wl_resource_set_implementation (resource, - &meta_text_input_manager_interface, - NULL, NULL); -} - -gboolean -meta_wayland_text_input_init (MetaWaylandCompositor *compositor) -{ - return (wl_global_create (compositor->wayland_display, - &zwp_text_input_manager_v3_interface, - META_ZWP_TEXT_INPUT_V3_VERSION, - compositor->seat->text_input, - bind_text_input) != NULL); -} - -gboolean -meta_wayland_text_input_handle_event (MetaWaylandTextInput *text_input, - const ClutterEvent *event) -{ - if (!text_input->surface || - !clutter_input_focus_is_focused (text_input->input_focus)) - return FALSE; - - if ((event->type == CLUTTER_KEY_PRESS || - event->type == CLUTTER_KEY_RELEASE) && - clutter_event_get_flags (event) & CLUTTER_EVENT_FLAG_INPUT_METHOD) - meta_wayland_text_input_focus_flush_done (text_input->input_focus); - - return clutter_input_focus_filter_event (text_input->input_focus, event); -} diff --git a/src/wayland/meta-wayland-text-input.h b/src/wayland/meta-wayland-text-input.h deleted file mode 100644 index 7e3544d95..000000000 --- a/src/wayland/meta-wayland-text-input.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2017 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: Carlos Garnacho - */ - -#ifndef META_WAYLAND_TEXT_INPUT_H -#define META_WAYLAND_TEXT_INPUT_H - -#include - -#include "meta/window.h" -#include "wayland/meta-wayland-types.h" - -#define META_TYPE_WAYLAND_TEXT_INPUT (meta_wayland_text_input_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandTextInput, - meta_wayland_text_input, - META, WAYLAND_TEXT_INPUT, - GObject); - -MetaWaylandTextInput * meta_wayland_text_input_new (MetaWaylandSeat *seat); -void meta_wayland_text_input_destroy (MetaWaylandTextInput *text_input); - -gboolean meta_wayland_text_input_init (MetaWaylandCompositor *compositor); - -void meta_wayland_text_input_set_focus (MetaWaylandTextInput *text_input, - MetaWaylandSurface *surface); - -gboolean meta_wayland_text_input_handle_event (MetaWaylandTextInput *text_input, - const ClutterEvent *event); - -#endif /* META_WAYLAND_TEXT_INPUT_H */ diff --git a/src/wayland/meta-wayland-touch.c b/src/wayland/meta-wayland-touch.c deleted file mode 100644 index 002ff16f7..000000000 --- a/src/wayland/meta-wayland-touch.c +++ /dev/null @@ -1,616 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Author: Carlos Garnacho - */ - -#include "config.h" - -#include -#include - -#include "compositor/meta-surface-actor-wayland.h" -#include "wayland/meta-wayland-private.h" - -G_DEFINE_TYPE (MetaWaylandTouch, meta_wayland_touch, - META_TYPE_WAYLAND_INPUT_DEVICE) - -struct _MetaWaylandTouchSurface -{ - MetaWaylandSurface *surface; - MetaWaylandTouch *touch; - struct wl_listener surface_destroy_listener; - struct wl_list resource_list; - gint touch_count; -}; - -struct _MetaWaylandTouchInfo -{ - MetaWaylandTouchSurface *touch_surface; - guint32 slot_serial; - gint32 slot; - gfloat start_x; - gfloat start_y; - gfloat x; - gfloat y; - guint updated : 1; - guint begin_delivered : 1; -}; - -static void -move_resources (struct wl_list *destination, struct wl_list *source) -{ - wl_list_insert_list (destination, source); - wl_list_init (source); -} - -static void -move_resources_for_client (struct wl_list *destination, - struct wl_list *source, - struct wl_client *client) -{ - struct wl_resource *resource, *tmp; - wl_resource_for_each_safe (resource, tmp, source) - { - if (wl_resource_get_client (resource) == client) - { - wl_list_remove (wl_resource_get_link (resource)); - wl_list_insert (destination, wl_resource_get_link (resource)); - } - } -} - -static void -touch_surface_free (gpointer data) -{ - MetaWaylandTouchSurface *touch_surface = data; - MetaWaylandTouch *touch = touch_surface->touch; - - move_resources (&touch->resource_list, - &touch_surface->resource_list); - wl_list_remove (&touch_surface->surface_destroy_listener.link); - g_free (touch_surface); -} - -static MetaWaylandTouchSurface * -touch_surface_increment_touch (MetaWaylandTouchSurface *surface) -{ - surface->touch_count++; - return surface; -} - -static void -touch_surface_decrement_touch (MetaWaylandTouchSurface *touch_surface) -{ - touch_surface->touch_count--; - - if (touch_surface->touch_count == 0) - { - /* Now that there are no touches on the surface, free the - * MetaWaylandTouchSurface, the memory is actually owned by - * the touch_surface->touch_surfaces hashtable, so remove the - * item from there. - */ - MetaWaylandTouch *touch = touch_surface->touch; - g_hash_table_remove (touch->touch_surfaces, touch_surface->surface); - } -} - -static void -touch_handle_surface_destroy (struct wl_listener *listener, void *data) -{ - MetaWaylandTouchSurface *touch_surface = wl_container_of (listener, touch_surface, surface_destroy_listener); - MetaWaylandSurface *surface = touch_surface->surface; - MetaWaylandTouch *touch = touch_surface->touch; - MetaWaylandTouchInfo *touch_info; - GHashTableIter iter; - - g_hash_table_iter_init (&iter, touch->touches); - - /* Destroy all touches on the surface, this indirectly drops touch_count - * on the touch_surface to 0, also freeing touch_surface and removing - * from the touch_surfaces hashtable. - */ - while (g_hash_table_iter_next (&iter, NULL, (gpointer*) &touch_info)) - { - if (touch_info->touch_surface == touch_surface) - g_hash_table_iter_remove (&iter); - } - - /* Ensure the surface no longer exists */ - g_assert (g_hash_table_remove (touch->touch_surfaces, surface) == FALSE); -} - -static MetaWaylandTouchSurface * -touch_surface_get (MetaWaylandTouch *touch, - MetaWaylandSurface *surface) -{ - MetaWaylandTouchSurface *touch_surface; - - touch_surface = g_hash_table_lookup (touch->touch_surfaces, surface); - - if (touch_surface) - return touch_surface_increment_touch (touch_surface); - - /* Create a new one for this surface */ - touch_surface = g_new0 (MetaWaylandTouchSurface, 1); - touch_surface->touch = touch; - touch_surface->surface = surface; - touch_surface->touch_count = 1; - touch_surface->surface_destroy_listener.notify = touch_handle_surface_destroy; - wl_resource_add_destroy_listener (touch_surface->surface->resource, - &touch_surface->surface_destroy_listener); - - wl_list_init (&touch_surface->resource_list); - move_resources_for_client (&touch_surface->resource_list, - &touch->resource_list, - wl_resource_get_client (touch_surface->surface->resource)); - - g_hash_table_insert (touch->touch_surfaces, surface, touch_surface); - - return touch_surface; -} - -static MetaWaylandTouchInfo * -touch_get_info (MetaWaylandTouch *touch, - ClutterEventSequence *sequence, - gboolean create) -{ - MetaWaylandTouchInfo *touch_info; - - touch_info = g_hash_table_lookup (touch->touches, sequence); - - if (!touch_info && create) - { - touch_info = g_new0 (MetaWaylandTouchInfo, 1); - touch_info->slot = clutter_event_sequence_get_slot (sequence); - g_hash_table_insert (touch->touches, sequence, touch_info); - } - - return touch_info; -} - -static void -touch_get_relative_coordinates (MetaWaylandTouch *touch, - MetaWaylandSurface *surface, - const ClutterEvent *event, - gfloat *x, - gfloat *y) -{ - gfloat event_x, event_y; - - clutter_event_get_coords (event, &event_x, &event_y); - - return meta_wayland_surface_get_relative_coordinates (surface, - event_x, event_y, - x, y); -} - -void -meta_wayland_touch_update (MetaWaylandTouch *touch, - const ClutterEvent *event) -{ - MetaWaylandTouchInfo *touch_info; - ClutterEventSequence *sequence; - - sequence = clutter_event_get_event_sequence (event); - - if (event->type == CLUTTER_TOUCH_BEGIN) - { - MetaWaylandSurface *surface = NULL; - ClutterActor *actor; - - actor = clutter_event_get_source (event); - - if (META_IS_SURFACE_ACTOR_WAYLAND (actor)) - surface = meta_surface_actor_wayland_get_surface (META_SURFACE_ACTOR_WAYLAND (actor)); - - if (!surface) - return; - - touch_info = touch_get_info (touch, sequence, TRUE); - touch_info->touch_surface = touch_surface_get (touch, surface); - clutter_event_get_coords (event, &touch_info->start_x, &touch_info->start_y); - } - else - touch_info = touch_get_info (touch, sequence, FALSE); - - if (!touch_info) - return; - - if (event->type != CLUTTER_TOUCH_BEGIN && - !touch_info->begin_delivered) - { - g_hash_table_remove (touch->touches, sequence); - return; - } - - if (event->type == CLUTTER_TOUCH_BEGIN || - event->type == CLUTTER_TOUCH_END) - { - MetaWaylandInputDevice *input_device = META_WAYLAND_INPUT_DEVICE (touch); - - touch_info->slot_serial = - meta_wayland_input_device_next_serial (input_device); - } - - touch_get_relative_coordinates (touch, touch_info->touch_surface->surface, - event, &touch_info->x, &touch_info->y); - touch_info->updated = TRUE; -} - -static void -handle_touch_begin (MetaWaylandTouch *touch, - const ClutterEvent *event) -{ - MetaWaylandTouchInfo *touch_info; - ClutterEventSequence *sequence; - struct wl_resource *resource; - struct wl_list *l; - - sequence = clutter_event_get_event_sequence (event); - touch_info = touch_get_info (touch, sequence, FALSE); - - if (!touch_info) - return; - - l = &touch_info->touch_surface->resource_list; - wl_resource_for_each(resource, l) - { - wl_touch_send_down (resource, touch_info->slot_serial, - clutter_event_get_time (event), - touch_info->touch_surface->surface->resource, - touch_info->slot, - wl_fixed_from_double (touch_info->x), - wl_fixed_from_double (touch_info->y)); - } - - touch_info->begin_delivered = TRUE; -} - -static void -handle_touch_update (MetaWaylandTouch *touch, - const ClutterEvent *event) -{ - MetaWaylandTouchInfo *touch_info; - ClutterEventSequence *sequence; - struct wl_resource *resource; - struct wl_list *l; - - sequence = clutter_event_get_event_sequence (event); - touch_info = touch_get_info (touch, sequence, FALSE); - - if (!touch_info) - return; - - l = &touch_info->touch_surface->resource_list; - wl_resource_for_each(resource, l) - { - wl_touch_send_motion (resource, - clutter_event_get_time (event), - touch_info->slot, - wl_fixed_from_double (touch_info->x), - wl_fixed_from_double (touch_info->y)); - } -} - -static void -handle_touch_end (MetaWaylandTouch *touch, - const ClutterEvent *event) -{ - MetaWaylandTouchInfo *touch_info; - ClutterEventSequence *sequence; - struct wl_resource *resource; - struct wl_list *l; - - sequence = clutter_event_get_event_sequence (event); - touch_info = touch_get_info (touch, sequence, FALSE); - - if (!touch_info) - return; - - l = &touch_info->touch_surface->resource_list; - wl_resource_for_each (resource, l) - { - wl_touch_send_up (resource, touch_info->slot_serial, - clutter_event_get_time (event), - touch_info->slot); - } - - g_hash_table_remove (touch->touches, sequence); -} - -static GList * -touch_get_surfaces (MetaWaylandTouch *touch, - gboolean only_updated) -{ - MetaWaylandTouchInfo *touch_info; - GList *surfaces = NULL; - GHashTableIter iter; - - g_hash_table_iter_init (&iter, touch->touches); - - while (g_hash_table_iter_next (&iter, NULL, (gpointer*) &touch_info)) - { - if (only_updated && !touch_info->updated) - continue; - if (g_list_find (surfaces, touch_info->touch_surface)) - continue; - - surfaces = g_list_prepend (surfaces, touch_info->touch_surface); - touch_info->updated = FALSE; - } - - return g_list_reverse (surfaces); -} - -static void -touch_send_frame_event (MetaWaylandTouch *touch) -{ - GList *surfaces, *s; - - surfaces = touch_get_surfaces (touch, TRUE); - - for (s = surfaces; s; s = s->next) - { - MetaWaylandTouchSurface *touch_surface = s->data; - struct wl_resource *resource; - struct wl_list *l; - - l = &touch_surface->resource_list; - wl_resource_for_each(resource, l) - { - wl_touch_send_frame (resource); - } - } - - g_list_free (surfaces); -} - -static gboolean -queue_frame_event_cb (MetaWaylandTouch *touch) -{ - touch_send_frame_event (touch); - touch->queued_frame_id = 0; - - return G_SOURCE_REMOVE; -} - -static void -send_or_queue_frame_event (MetaWaylandTouch *touch) -{ - if (clutter_events_pending ()) - { - if (touch->queued_frame_id == 0) - { - touch->queued_frame_id = - g_idle_add_full (CLUTTER_PRIORITY_EVENTS + 1, - (GSourceFunc) queue_frame_event_cb, - touch, NULL); - } - } - else - { - /* There's no more events */ - g_clear_handle_id (&touch->queued_frame_id, g_source_remove); - touch_send_frame_event (touch); - } -} - -gboolean -meta_wayland_touch_handle_event (MetaWaylandTouch *touch, - const ClutterEvent *event) -{ - switch (event->type) - { - case CLUTTER_TOUCH_BEGIN: - handle_touch_begin (touch, event); - break; - - case CLUTTER_TOUCH_UPDATE: - handle_touch_update (touch, event); - break; - - case CLUTTER_TOUCH_END: - handle_touch_end (touch, event); - break; - - case CLUTTER_TOUCH_CANCEL: - meta_wayland_touch_cancel (touch); - break; - - default: - return FALSE; - } - - send_or_queue_frame_event (touch); - return FALSE; -} - -static void -unbind_resource (struct wl_resource *resource) -{ - wl_list_remove (wl_resource_get_link (resource)); -} - -static void -touch_release (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static const struct wl_touch_interface touch_interface = { - touch_release, -}; - -static void -touch_info_free (MetaWaylandTouchInfo *touch_info) -{ - touch_surface_decrement_touch (touch_info->touch_surface); - g_free (touch_info); -} - -void -meta_wayland_touch_cancel (MetaWaylandTouch *touch) -{ - MetaWaylandInputDevice *input_device = META_WAYLAND_INPUT_DEVICE (touch); - MetaWaylandSeat *seat = meta_wayland_input_device_get_seat (input_device); - GList *surfaces, *s; - - if (!meta_wayland_seat_has_touch (seat)) - return; - - surfaces = s = touch_get_surfaces (touch, FALSE); - - for (s = surfaces; s; s = s->next) - { - MetaWaylandTouchSurface *touch_surface = s->data; - struct wl_resource *resource; - struct wl_list *l; - - l = &touch_surface->resource_list; - wl_resource_for_each(resource, l) - wl_touch_send_cancel (resource); - } - - g_hash_table_remove_all (touch->touches); - g_list_free (surfaces); -} - -void -meta_wayland_touch_enable (MetaWaylandTouch *touch) -{ - touch->touch_surfaces = g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) touch_surface_free); - touch->touches = g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) touch_info_free); - - wl_list_init (&touch->resource_list); -} - -void -meta_wayland_touch_disable (MetaWaylandTouch *touch) -{ - meta_wayland_touch_cancel (touch); - - g_clear_pointer (&touch->touch_surfaces, g_hash_table_unref); - g_clear_pointer (&touch->touches, g_hash_table_unref); -} - -void -meta_wayland_touch_create_new_resource (MetaWaylandTouch *touch, - struct wl_client *client, - struct wl_resource *seat_resource, - uint32_t id) -{ - MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); - struct wl_resource *cr; - - if (!meta_wayland_seat_has_touch (seat)) - { - wl_resource_post_error (seat_resource, WL_DISPLAY_ERROR_INVALID_METHOD, - "Cannot retrieve touch interface without touch capability"); - return; - } - - cr = wl_resource_create (client, &wl_touch_interface, wl_resource_get_version (seat_resource), id); - wl_resource_set_implementation (cr, &touch_interface, touch, unbind_resource); - wl_list_insert (&touch->resource_list, wl_resource_get_link (cr)); -} - -gboolean -meta_wayland_touch_can_popup (MetaWaylandTouch *touch, - uint32_t serial) -{ - MetaWaylandTouchInfo *touch_info; - GHashTableIter iter; - - if (!touch->touches) - return FALSE; - - g_hash_table_iter_init (&iter, touch->touches); - - while (g_hash_table_iter_next (&iter, NULL, (gpointer*) &touch_info)) - { - if (touch_info->slot_serial == serial) - return TRUE; - } - return FALSE; -} - -ClutterEventSequence * -meta_wayland_touch_find_grab_sequence (MetaWaylandTouch *touch, - MetaWaylandSurface *surface, - uint32_t serial) -{ - MetaWaylandTouchInfo *touch_info; - ClutterEventSequence *sequence; - GHashTableIter iter; - - if (!touch->touches) - return NULL; - - g_hash_table_iter_init (&iter, touch->touches); - - while (g_hash_table_iter_next (&iter, (gpointer*) &sequence, - (gpointer*) &touch_info)) - { - if (touch_info->slot_serial == serial && - touch_info->touch_surface->surface == surface) - return sequence; - } - - return NULL; -} - -gboolean -meta_wayland_touch_get_press_coords (MetaWaylandTouch *touch, - ClutterEventSequence *sequence, - gfloat *x, - gfloat *y) -{ - MetaWaylandTouchInfo *touch_info; - - if (!touch->touches) - return FALSE; - - touch_info = g_hash_table_lookup (touch->touches, sequence); - - if (!touch_info) - return FALSE; - - if (x) - *x = touch_info->start_x; - if (y) - *y = touch_info->start_y; - - return TRUE; -} - -static void -meta_wayland_touch_init (MetaWaylandTouch *touch) -{ -} - -static void -meta_wayland_touch_class_init (MetaWaylandTouchClass *klass) -{ -} diff --git a/src/wayland/meta-wayland-touch.h b/src/wayland/meta-wayland-touch.h deleted file mode 100644 index 304d8227e..000000000 --- a/src/wayland/meta-wayland-touch.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2014 Red Hat - * - * 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 . - * - * Author: Carlos Garnacho - */ - -#ifndef META_WAYLAND_TOUCH_H -#define META_WAYLAND_TOUCH_H - -#include -#include - -#include "wayland/meta-wayland-types.h" - -#define META_TYPE_WAYLAND_TOUCH (meta_wayland_touch_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandTouch, meta_wayland_touch, - META, WAYLAND_TOUCH, - MetaWaylandInputDevice) - -typedef struct _MetaWaylandTouchSurface MetaWaylandTouchSurface; -typedef struct _MetaWaylandTouchInfo MetaWaylandTouchInfo; - -struct _MetaWaylandTouch -{ - MetaWaylandInputDevice parent; - - struct wl_list resource_list; - - guint queued_frame_id; - GHashTable *touch_surfaces; /* HT of MetaWaylandSurface->MetaWaylandTouchSurface */ - GHashTable *touches; /* HT of sequence->MetaWaylandTouchInfo */ -}; - -void meta_wayland_touch_enable (MetaWaylandTouch *touch); - -void meta_wayland_touch_disable (MetaWaylandTouch *touch); - -void meta_wayland_touch_update (MetaWaylandTouch *touch, - const ClutterEvent *event); - -gboolean meta_wayland_touch_handle_event (MetaWaylandTouch *touch, - const ClutterEvent *event); - -void meta_wayland_touch_create_new_resource (MetaWaylandTouch *touch, - struct wl_client *client, - struct wl_resource *seat_resource, - uint32_t id); -void meta_wayland_touch_cancel (MetaWaylandTouch *touch); - - -ClutterEventSequence * meta_wayland_touch_find_grab_sequence (MetaWaylandTouch *touch, - MetaWaylandSurface *surface, - uint32_t serial); - -gboolean meta_wayland_touch_get_press_coords (MetaWaylandTouch *touch, - ClutterEventSequence *sequence, - gfloat *x, - gfloat *y); - -gboolean meta_wayland_touch_can_popup (MetaWaylandTouch *touch, - uint32_t serial); - -#endif /* META_WAYLAND_TOUCH_H */ diff --git a/src/wayland/meta-wayland-types.h b/src/wayland/meta-wayland-types.h deleted file mode 100644 index aeb6f6178..000000000 --- a/src/wayland/meta-wayland-types.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2013 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_WAYLAND_TYPES_H -#define META_WAYLAND_TYPES_H - -typedef struct _MetaWaylandCompositor MetaWaylandCompositor; - -typedef struct _MetaWaylandSeat MetaWaylandSeat; -typedef struct _MetaWaylandInputDevice MetaWaylandInputDevice; -typedef struct _MetaWaylandPointer MetaWaylandPointer; -typedef struct _MetaWaylandPointerGrab MetaWaylandPointerGrab; -typedef struct _MetaWaylandPointerGrabInterface MetaWaylandPointerGrabInterface; -typedef struct _MetaWaylandPopupGrab MetaWaylandPopupGrab; -typedef struct _MetaWaylandPopup MetaWaylandPopup; -typedef struct _MetaWaylandPopupSurface MetaWaylandPopupSurface; -typedef struct _MetaWaylandKeyboard MetaWaylandKeyboard; -typedef struct _MetaWaylandKeyboardGrab MetaWaylandKeyboardGrab; -typedef struct _MetaWaylandKeyboardGrabInterface MetaWaylandKeyboardGrabInterface; -typedef struct _MetaWaylandTouch MetaWaylandTouch; -typedef struct _MetaWaylandDragDestFuncs MetaWaylandDragDestFuncs; -typedef struct _MetaWaylandDataOffer MetaWaylandDataOffer; -typedef struct _MetaWaylandDataDevice MetaWaylandDataDevice; -typedef struct _MetaWaylandDataDevicePrimary MetaWaylandDataDevicePrimary; -typedef struct _MetaWaylandDataDevicePrimaryLegacy MetaWaylandDataDevicePrimaryLegacy; - -typedef struct _MetaWaylandTabletManager MetaWaylandTabletManager; -typedef struct _MetaWaylandTabletSeat MetaWaylandTabletSeat; -typedef struct _MetaWaylandTabletTool MetaWaylandTabletTool; -typedef struct _MetaWaylandTablet MetaWaylandTablet; -typedef struct _MetaWaylandTabletPad MetaWaylandTabletPad; -typedef struct _MetaWaylandTabletPadGroup MetaWaylandTabletPadGroup; -typedef struct _MetaWaylandTabletPadStrip MetaWaylandTabletPadStrip; -typedef struct _MetaWaylandTabletPadRing MetaWaylandTabletPadRing; - -typedef struct _MetaWaylandBuffer MetaWaylandBuffer; -typedef struct _MetaWaylandRegion MetaWaylandRegion; - -typedef struct _MetaWaylandSurface MetaWaylandSurface; -typedef struct _MetaWaylandSurfaceState MetaWaylandSurfaceState; - -typedef struct _MetaWaylandOutput MetaWaylandOutput; - -typedef struct _MetaWaylandWindowConfiguration MetaWaylandWindowConfiguration; - -typedef struct _MetaWaylandPointerClient MetaWaylandPointerClient; - -typedef struct _MetaWaylandActivation MetaWaylandActivation; - -#endif diff --git a/src/wayland/meta-wayland-versions.h b/src/wayland/meta-wayland-versions.h deleted file mode 100644 index 05dd937b2..000000000 --- a/src/wayland/meta-wayland-versions.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2012,2013 Intel Corporation - * 2013 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_WAYLAND_VERSIONS_H -#define META_WAYLAND_VERSIONS_H - -/* Protocol objects, will never change version */ -/* #define META_WL_DISPLAY_VERSION 1 */ -/* #define META_WL_REGISTRY_VERSION 1 */ -#define META_WL_CALLBACK_VERSION 1 - -/* Not handled by mutter-wayland directly */ -/* #define META_WL_SHM_VERSION 1 */ -/* #define META_WL_SHM_POOL_VERSION 1 */ -/* #define META_WL_DRM_VERSION 1 */ -/* #define META_WL_BUFFER_VERSION 1 */ - -/* Global/master objects (version exported by wl_registry and negotiated through bind) */ -#define META_WL_COMPOSITOR_VERSION 4 -#define META_WL_DATA_DEVICE_MANAGER_VERSION 3 -#define META_XDG_WM_BASE_VERSION 3 -#define META_ZXDG_SHELL_V6_VERSION 1 -#define META_WL_SHELL_VERSION 1 -#define META_WL_SEAT_VERSION 5 -#define META_WL_OUTPUT_VERSION 2 -#define META_XSERVER_VERSION 1 -#define META_GTK_SHELL1_VERSION 4 -#define META_WL_SUBCOMPOSITOR_VERSION 1 -#define META_ZWP_POINTER_GESTURES_V1_VERSION 1 -#define META_ZXDG_EXPORTER_V1_VERSION 1 -#define META_ZXDG_IMPORTER_V1_VERSION 1 -#define META_ZWP_LINUX_DMABUF_V1_VERSION 3 -#define META_ZWP_KEYBOARD_SHORTCUTS_INHIBIT_V1_VERSION 1 -#define META_ZXDG_OUTPUT_V1_VERSION 3 -#define META_ZWP_XWAYLAND_KEYBOARD_GRAB_V1_VERSION 1 -#define META_GTK_TEXT_INPUT_VERSION 1 -#define META_ZWP_TEXT_INPUT_V3_VERSION 1 -#define META_WP_VIEWPORTER_VERSION 1 -#define META_GTK_PRIMARY_SELECTION_VERSION 1 -#define META_ZWP_PRIMARY_SELECTION_V1_VERSION 1 -#define META_WP_PRESENTATION_VERSION 1 -#define META_XDG_ACTIVATION_V1_VERSION 1 - -#endif diff --git a/src/wayland/meta-wayland-viewporter.c b/src/wayland/meta-wayland-viewporter.c deleted file mode 100644 index 619f3177c..000000000 --- a/src/wayland/meta-wayland-viewporter.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2018-2019 Robert Mader - * - * 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 "meta-wayland-viewporter.h" - -#include - -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-subsurface.h" -#include "wayland/meta-wayland-surface.h" -#include "wayland/meta-wayland-versions.h" - -#include "viewporter-server-protocol.h" - -static void -wp_viewport_destructor (struct wl_resource *resource) -{ - MetaWaylandSurface *surface; - MetaWaylandSurfaceState *pending; - - surface = wl_resource_get_user_data (resource); - if (!surface) - return; - - g_clear_signal_handler (&surface->viewport.destroy_handler_id, surface); - - pending = meta_wayland_surface_get_pending_state (surface); - pending->viewport_src_rect.size.width = -1; - pending->viewport_dst_width = -1; - pending->has_new_viewport_src_rect = TRUE; - pending->has_new_viewport_dst_size = TRUE; - - surface->viewport.resource = NULL; -} - -static void -on_surface_destroyed (MetaWaylandSurface *surface) -{ - wl_resource_set_user_data (surface->viewport.resource, NULL); -} - -static void -wp_viewport_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -wp_viewport_set_source (struct wl_client *client, - struct wl_resource *resource, - wl_fixed_t src_x, - wl_fixed_t src_y, - wl_fixed_t src_width, - wl_fixed_t src_height) -{ - MetaWaylandSurface *surface; - float new_x; - float new_y; - float new_width; - float new_height; - - surface = wl_resource_get_user_data (resource); - if (!surface) - { - wl_resource_post_error (resource, - WP_VIEWPORT_ERROR_NO_SURFACE, - "wl_surface for this viewport no longer exists"); - return; - } - - new_x = wl_fixed_to_double (src_x); - new_y = wl_fixed_to_double (src_y); - new_width = wl_fixed_to_double (src_width); - new_height = wl_fixed_to_double (src_height); - - if ((new_x >= 0 && new_y >= 0 && - new_width > 0 && new_height > 0) || - (new_x == -1 && new_y == -1 && - new_width == -1 && new_height == -1)) - { - MetaWaylandSurfaceState *pending; - - pending = meta_wayland_surface_get_pending_state (surface); - pending->viewport_src_rect.origin.x = new_x; - pending->viewport_src_rect.origin.y = new_y; - pending->viewport_src_rect.size.width = new_width; - pending->viewport_src_rect.size.height = new_height; - pending->has_new_viewport_src_rect = TRUE; - } - else - { - wl_resource_post_error (resource, - WP_VIEWPORT_ERROR_BAD_VALUE, - "x and y values must be zero or positive and " - "width and height valuest must be positive or " - "all values must be -1 to unset the viewport"); - } -} - -static void -wp_viewport_set_destination (struct wl_client *client, - struct wl_resource *resource, - int dst_width, - int dst_height) -{ - MetaWaylandSurface *surface; - - surface = wl_resource_get_user_data (resource); - if (!surface) - { - wl_resource_post_error (resource, - WP_VIEWPORT_ERROR_NO_SURFACE, - "wl_surface for this viewport no longer exists"); - return; - } - - if ((dst_width > 0 && dst_height > 0) || - (dst_width == -1 && dst_height == -1)) - { - MetaWaylandSurfaceState *pending; - - pending = meta_wayland_surface_get_pending_state (surface); - pending->viewport_dst_width = dst_width; - pending->viewport_dst_height = dst_height; - pending->has_new_viewport_dst_size = TRUE; - } - else - { - wl_resource_post_error (resource, - WP_VIEWPORT_ERROR_BAD_VALUE, - "all values must be either positive or -1"); - } -} - -static const struct wp_viewport_interface meta_wayland_viewport_interface = { - wp_viewport_destroy, - wp_viewport_set_source, - wp_viewport_set_destination, -}; - -static void -wp_viewporter_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -wp_viewporter_get_viewport (struct wl_client *client, - struct wl_resource *resource, - uint32_t viewport_id, - struct wl_resource *surface_resource) -{ - MetaWaylandSurface *surface; - struct wl_resource *viewport_resource; - - surface = wl_resource_get_user_data (surface_resource); - if (surface->viewport.resource) - { - wl_resource_post_error (resource, - WP_VIEWPORTER_ERROR_VIEWPORT_EXISTS, - "viewport already exists on surface"); - return; - } - - viewport_resource = wl_resource_create (client, - &wp_viewport_interface, - wl_resource_get_version (resource), - viewport_id); - wl_resource_set_implementation (viewport_resource, - &meta_wayland_viewport_interface, - surface, - wp_viewport_destructor); - - surface->viewport.resource = viewport_resource; - surface->viewport.destroy_handler_id = - g_signal_connect (surface, - "destroy", - G_CALLBACK (on_surface_destroyed), - NULL); -} - -static const struct wp_viewporter_interface meta_wayland_viewporter_interface = { - wp_viewporter_destroy, - wp_viewporter_get_viewport, -}; - -static void -wp_viewporter_bind (struct wl_client *client, - void *data, - uint32_t version, - uint32_t id) -{ - struct wl_resource *resource; - - resource = wl_resource_create (client, - &wp_viewporter_interface, - version, - id); - wl_resource_set_implementation (resource, - &meta_wayland_viewporter_interface, - data, - NULL); -} - -void -meta_wayland_init_viewporter (MetaWaylandCompositor *compositor) -{ - if (wl_global_create (compositor->wayland_display, - &wp_viewporter_interface, - META_WP_VIEWPORTER_VERSION, - compositor, - wp_viewporter_bind) == NULL) - g_error ("Failed to register a global wl-viewporter object"); -} diff --git a/src/wayland/meta-wayland-viewporter.h b/src/wayland/meta-wayland-viewporter.h deleted file mode 100644 index 8cc099b11..000000000 --- a/src/wayland/meta-wayland-viewporter.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2018-2019 Robert Mader - * - * 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_WAYLAND_VIEWPORTER_H -#define META_WAYLAND_VIEWPORTER_H - -#include "wayland/meta-wayland-types.h" - -void meta_wayland_init_viewporter (MetaWaylandCompositor *compositor); - -#endif /* META_WAYLAND_VIEWPORTER_H */ diff --git a/src/wayland/meta-wayland-window-configuration.c b/src/wayland/meta-wayland-window-configuration.c deleted file mode 100644 index 6a91a7141..000000000 --- a/src/wayland/meta-wayland-window-configuration.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * 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. - * - */ - -#include "config.h" - -#include "wayland/meta-wayland-window-configuration.h" - -static uint32_t global_serial_counter = 0; - -static gboolean -is_window_size_fixed (MetaWindow *window) -{ - if (meta_window_is_fullscreen (window)) - return TRUE; - - if (meta_window_get_maximized (window) | - (META_MAXIMIZE_VERTICAL | META_MAXIMIZE_VERTICAL)) - return TRUE; - - if (meta_window_get_tile_mode (window) != META_TILE_NONE) - return TRUE; - - return FALSE; -} - -MetaWaylandWindowConfiguration * -meta_wayland_window_configuration_new (MetaWindow *window, - int x, - int y, - int width, - int height, - int scale, - MetaMoveResizeFlags flags, - MetaGravity gravity) -{ - MetaWaylandWindowConfiguration *configuration; - - configuration = g_new0 (MetaWaylandWindowConfiguration, 1); - *configuration = (MetaWaylandWindowConfiguration) { - .serial = ++global_serial_counter, - - .scale = scale, - .gravity = gravity, - .flags = flags, - }; - - if (flags & META_MOVE_RESIZE_MOVE_ACTION || - window->rect.x != x || - window->rect.y != y) - { - configuration->has_position = TRUE; - configuration->x = x; - configuration->y = y; - } - - if (flags & META_MOVE_RESIZE_RESIZE_ACTION || - is_window_size_fixed (window) || - window->rect.width != width || - window->rect.height != height) - { - configuration->has_size = TRUE; - configuration->width = width; - configuration->height = height; - } - - return configuration; -} - -MetaWaylandWindowConfiguration * -meta_wayland_window_configuration_new_relative (int rel_x, - int rel_y, - int width, - int height, - int scale) -{ - MetaWaylandWindowConfiguration *configuration; - - configuration = g_new0 (MetaWaylandWindowConfiguration, 1); - *configuration = (MetaWaylandWindowConfiguration) { - .serial = ++global_serial_counter, - - .has_relative_position = TRUE, - .rel_x = rel_x, - .rel_y = rel_y, - - .has_size = TRUE, - .width = width, - .height = height, - - .scale = scale, - }; - - return configuration; -} - -MetaWaylandWindowConfiguration * -meta_wayland_window_configuration_new_empty (void) -{ - MetaWaylandWindowConfiguration *configuration; - - configuration = g_new0 (MetaWaylandWindowConfiguration, 1); - *configuration = (MetaWaylandWindowConfiguration) { - .serial = ++global_serial_counter, - .scale = 1, - }; - - return configuration; -} - -void -meta_wayland_window_configuration_free (MetaWaylandWindowConfiguration *configuration) -{ - g_free (configuration); -} diff --git a/src/wayland/meta-wayland-window-configuration.h b/src/wayland/meta-wayland-window-configuration.h deleted file mode 100644 index b3211d1ad..000000000 --- a/src/wayland/meta-wayland-window-configuration.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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_WAYLAND_WINDOW_CONFIGURATION_H -#define META_WAYLAND_WINDOW_CONFIGURATION_H - -#include -#include - -#include "core/window-private.h" -#include "wayland/meta-wayland-types.h" - -struct _MetaWaylandWindowConfiguration -{ - uint32_t serial; - - gboolean has_position; - int x; - int y; - - gboolean has_relative_position; - int rel_x; - int rel_y; - - gboolean has_size; - int width; - int height; - - int scale; - MetaGravity gravity; - MetaMoveResizeFlags flags; -}; - -MetaWaylandWindowConfiguration * meta_wayland_window_configuration_new (MetaWindow *window, - int x, - int y, - int width, - int height, - int scale, - MetaMoveResizeFlags flags, - MetaGravity gravity); - -MetaWaylandWindowConfiguration * meta_wayland_window_configuration_new_relative (int rel_x, - int rel_y, - int width, - int height, - int scale); - -MetaWaylandWindowConfiguration * meta_wayland_window_configuration_new_empty (void); - -void meta_wayland_window_configuration_free (MetaWaylandWindowConfiguration *configuration); - -#endif /* META_WAYLAND_WINDOW_CONFIGURATION_H */ diff --git a/src/wayland/meta-wayland-wl-shell.c b/src/wayland/meta-wayland-wl-shell.c deleted file mode 100644 index 964c185b2..000000000 --- a/src/wayland/meta-wayland-wl-shell.c +++ /dev/null @@ -1,777 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2012-2013 Intel Corporation - * Copyright (C) 2013-2015 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "wayland/meta-wayland-wl-shell.h" - -#include "core/window-private.h" -#include "wayland/meta-wayland-popup.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-seat.h" -#include "wayland/meta-wayland-shell-surface.h" -#include "wayland/meta-wayland-surface.h" -#include "wayland/meta-wayland-versions.h" -#include "wayland/meta-wayland-window-configuration.h" -#include "wayland/meta-wayland.h" -#include "wayland/meta-window-wayland.h" - -typedef enum -{ - META_WL_SHELL_SURFACE_STATE_NONE, - META_WL_SHELL_SURFACE_STATE_TOPLEVEL, - META_WL_SHELL_SURFACE_STATE_POPUP, - META_WL_SHELL_SURFACE_STATE_TRANSIENT, - META_WL_SHELL_SURFACE_STATE_FULLSCREEN, - META_WL_SHELL_SURFACE_STATE_MAXIMIZED, -} MetaWlShellSurfaceState; - -struct _MetaWaylandWlShellSurface -{ - MetaWaylandShellSurface parent; - - struct wl_resource *resource; - - MetaWlShellSurfaceState state; - - char *title; - char *wm_class; - - MetaWaylandSurface *parent_surface; - GList *children; - - MetaWaylandSeat *popup_seat; - MetaWaylandPopup *popup; - gboolean pending_popup; - - int x; - int y; - - uint32_t emulated_ack_configure_serial; -}; - -static void -popup_surface_iface_init (MetaWaylandPopupSurfaceInterface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaWaylandWlShellSurface, - meta_wayland_wl_shell_surface, - META_TYPE_WAYLAND_SHELL_SURFACE, - G_IMPLEMENT_INTERFACE (META_TYPE_WAYLAND_POPUP_SURFACE, - popup_surface_iface_init)); - -static MetaWaylandSurface * -surface_from_wl_shell_surface_resource (struct wl_resource *resource) -{ - MetaWaylandWlShellSurface *wl_shell_surface = - wl_resource_get_user_data (resource); - MetaWaylandSurfaceRole *surface_role = - META_WAYLAND_SURFACE_ROLE (wl_shell_surface); - - return meta_wayland_surface_role_get_surface (surface_role); -} - -static void -sync_wl_shell_parent_relationship (MetaWaylandSurface *surface, - MetaWaylandSurface *parent); - -static void -wl_shell_surface_destructor (struct wl_resource *resource) -{ - MetaWaylandWlShellSurface *wl_shell_surface = - META_WAYLAND_WL_SHELL_SURFACE (wl_resource_get_user_data (resource)); - MetaWaylandSurface *surface = - surface_from_wl_shell_surface_resource (resource); - GList *l; - - if (wl_shell_surface->popup) - meta_wayland_popup_dismiss (wl_shell_surface->popup); - - for (l = wl_shell_surface->children; l; l = l->next) - { - MetaWaylandSurface *child_surface = l->data; - MetaWaylandWlShellSurface *child_wl_shell_surface = - META_WAYLAND_WL_SHELL_SURFACE (child_surface->role); - - child_wl_shell_surface->parent_surface = NULL; - - if (child_wl_shell_surface->parent_surface == surface) - { - meta_wayland_popup_dismiss (child_wl_shell_surface->popup); - child_wl_shell_surface->parent_surface = NULL; - } - } - - if (wl_shell_surface->parent_surface) - { - MetaWaylandSurface *parent_surface = wl_shell_surface->parent_surface; - MetaWaylandWlShellSurface *parent_wl_shell_surface = - META_WAYLAND_WL_SHELL_SURFACE (parent_surface->role); - - parent_wl_shell_surface->children = - g_list_remove (parent_wl_shell_surface->children, surface); - } - - g_free (wl_shell_surface->title); - g_free (wl_shell_surface->wm_class); - - if (wl_shell_surface->popup) - { - wl_shell_surface->parent_surface = NULL; - - meta_wayland_popup_dismiss (wl_shell_surface->popup); - } - - wl_shell_surface->resource = NULL; -} - -static void -wl_shell_surface_pong (struct wl_client *client, - struct wl_resource *resource, - uint32_t serial) -{ - MetaDisplay *display = meta_get_display (); - - meta_display_pong_for_serial (display, serial); -} - -static void -wl_shell_surface_move (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *seat_resource, - uint32_t serial) -{ - MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); - MetaWaylandSurface *surface = - surface_from_wl_shell_surface_resource (resource); - gfloat x, y; - - if (!meta_wayland_seat_get_grab_info (seat, surface, serial, TRUE, &x, &y)) - return; - - meta_wayland_surface_begin_grab_op (surface, seat, META_GRAB_OP_MOVING, x, y); -} - -static MetaGrabOp -grab_op_for_wl_shell_surface_resize_edge (int edge) -{ - MetaGrabOp op = META_GRAB_OP_WINDOW_BASE; - - if (edge & WL_SHELL_SURFACE_RESIZE_TOP) - op |= META_GRAB_OP_WINDOW_DIR_NORTH; - if (edge & WL_SHELL_SURFACE_RESIZE_BOTTOM) - op |= META_GRAB_OP_WINDOW_DIR_SOUTH; - if (edge & WL_SHELL_SURFACE_RESIZE_LEFT) - op |= META_GRAB_OP_WINDOW_DIR_WEST; - if (edge & WL_SHELL_SURFACE_RESIZE_RIGHT) - op |= META_GRAB_OP_WINDOW_DIR_EAST; - - if (op == META_GRAB_OP_WINDOW_BASE) - { - g_warning ("invalid edge: %d", edge); - return META_GRAB_OP_NONE; - } - - return op; -} - -static void -wl_shell_surface_resize (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *seat_resource, - uint32_t serial, - uint32_t edges) -{ - MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); - MetaWaylandSurface *surface = - surface_from_wl_shell_surface_resource (resource); - gfloat x, y; - MetaGrabOp grab_op; - - if (!meta_wayland_seat_get_grab_info (seat, surface, serial, TRUE, &x, &y)) - return; - - grab_op = grab_op_for_wl_shell_surface_resize_edge (edges); - meta_wayland_surface_begin_grab_op (surface, seat, grab_op, x, y); -} - -static void -wl_shell_surface_set_state (MetaWaylandSurface *surface, - MetaWlShellSurfaceState state) -{ - MetaWaylandWlShellSurface *wl_shell_surface = - META_WAYLAND_WL_SHELL_SURFACE (surface->role); - MetaWlShellSurfaceState old_state = wl_shell_surface->state; - MetaWindow *window; - - wl_shell_surface->state = state; - - window = meta_wayland_surface_get_window (surface); - if (window && old_state != state) - { - if (old_state == META_WL_SHELL_SURFACE_STATE_POPUP && - wl_shell_surface->popup) - { - meta_wayland_popup_dismiss (wl_shell_surface->popup); - wl_shell_surface->popup = NULL; - } - - if (state == META_WL_SHELL_SURFACE_STATE_FULLSCREEN) - meta_window_make_fullscreen (window); - else - meta_window_unmake_fullscreen (window); - - if (state == META_WL_SHELL_SURFACE_STATE_MAXIMIZED) - meta_window_maximize (window, META_MAXIMIZE_BOTH); - else - meta_window_unmaximize (window, META_MAXIMIZE_BOTH); - } -} - -static void -wl_shell_surface_set_toplevel (struct wl_client *client, - struct wl_resource *resource) -{ - MetaWaylandSurface *surface = - surface_from_wl_shell_surface_resource (resource); - - wl_shell_surface_set_state (surface, - META_WL_SHELL_SURFACE_STATE_TOPLEVEL); -} - -static void -set_wl_shell_surface_parent (MetaWaylandSurface *surface, - MetaWaylandSurface *parent) -{ - MetaWaylandWlShellSurface *wl_shell_surface = - META_WAYLAND_WL_SHELL_SURFACE (surface->role); - MetaWaylandWlShellSurface *parent_wl_shell_surface = - META_WAYLAND_WL_SHELL_SURFACE (parent->role); - - if (wl_shell_surface->parent_surface) - { - MetaWaylandWlShellSurface *old_parent = - META_WAYLAND_WL_SHELL_SURFACE (wl_shell_surface->parent_surface->role); - - old_parent->children = g_list_remove (old_parent->children, surface); - } - - parent_wl_shell_surface->children = - g_list_append (parent_wl_shell_surface->children, surface); - wl_shell_surface->parent_surface = parent; -} - -static void -wl_shell_surface_set_transient (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *parent_resource, - int32_t x, - int32_t y, - uint32_t flags) -{ - MetaWaylandWlShellSurface *wl_shell_surface = - META_WAYLAND_WL_SHELL_SURFACE (wl_resource_get_user_data (resource)); - MetaWaylandSurface *surface = - surface_from_wl_shell_surface_resource (resource); - MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource); - - wl_shell_surface_set_state (surface, - META_WL_SHELL_SURFACE_STATE_TRANSIENT); - - set_wl_shell_surface_parent (surface, parent_surf); - wl_shell_surface->x = x; - wl_shell_surface->y = y; - - if (meta_wayland_surface_get_window (surface) && - meta_wayland_surface_get_window (parent_surf)) - sync_wl_shell_parent_relationship (surface, parent_surf); -} - -static void -wl_shell_surface_set_fullscreen (struct wl_client *client, - struct wl_resource *resource, - uint32_t method, - uint32_t framerate, - struct wl_resource *output) -{ - MetaWaylandSurface *surface = - surface_from_wl_shell_surface_resource (resource); - - wl_shell_surface_set_state (surface, - META_WL_SHELL_SURFACE_STATE_FULLSCREEN); -} - -static void -meta_wayland_wl_shell_surface_create_popup (MetaWaylandWlShellSurface *wl_shell_surface) -{ - MetaWaylandPopupSurface *popup_surface = - META_WAYLAND_POPUP_SURFACE (wl_shell_surface); - MetaWaylandSeat *seat = wl_shell_surface->popup_seat; - MetaWaylandPopup *popup; - - popup = meta_wayland_pointer_start_popup_grab (seat->pointer, popup_surface); - if (!popup) - { - wl_shell_surface_send_popup_done (wl_shell_surface->resource); - return; - } - - wl_shell_surface->popup = popup; -} - -static void -wl_shell_surface_set_popup (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *seat_resource, - uint32_t serial, - struct wl_resource *parent_resource, - int32_t x, - int32_t y, - uint32_t flags) -{ - MetaWaylandWlShellSurface *wl_shell_surface = - META_WAYLAND_WL_SHELL_SURFACE (wl_resource_get_user_data (resource)); - MetaWaylandSurface *surface = - surface_from_wl_shell_surface_resource (resource); - MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource); - MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); - - if (wl_shell_surface->popup) - { - wl_shell_surface->parent_surface = NULL; - - meta_wayland_popup_dismiss (wl_shell_surface->popup); - } - - wl_shell_surface_set_state (surface, - META_WL_SHELL_SURFACE_STATE_POPUP); - - if (!meta_wayland_seat_can_popup (seat, serial)) - { - wl_shell_surface_send_popup_done (resource); - return; - } - - set_wl_shell_surface_parent (surface, parent_surf); - wl_shell_surface->popup_seat = seat; - wl_shell_surface->x = x; - wl_shell_surface->y = y; - wl_shell_surface->pending_popup = TRUE; - - if (meta_wayland_surface_get_window (surface) && - meta_wayland_surface_get_window (parent_surf)) - sync_wl_shell_parent_relationship (surface, parent_surf); -} - -static void -wl_shell_surface_set_maximized (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *output) -{ - MetaWaylandSurface *surface = - surface_from_wl_shell_surface_resource (resource); - - wl_shell_surface_set_state (surface, - META_WL_SHELL_SURFACE_STATE_MAXIMIZED); -} - -static void -wl_shell_surface_set_title (struct wl_client *client, - struct wl_resource *resource, - const char *title) -{ - MetaWaylandWlShellSurface *wl_shell_surface = - META_WAYLAND_WL_SHELL_SURFACE (wl_resource_get_user_data (resource)); - MetaWaylandSurface *surface = - surface_from_wl_shell_surface_resource (resource); - MetaWindow *window; - - g_clear_pointer (&wl_shell_surface->title, g_free); - - if (!g_utf8_validate (title, -1, NULL)) - title = ""; - - wl_shell_surface->title = g_strdup (title); - - window = meta_wayland_surface_get_window (surface); - if (window) - meta_window_set_title (window, title); -} - -static void -wl_shell_surface_set_class (struct wl_client *client, - struct wl_resource *resource, - const char *class_) -{ - MetaWaylandWlShellSurface *wl_shell_surface = - META_WAYLAND_WL_SHELL_SURFACE (wl_resource_get_user_data (resource)); - MetaWaylandSurface *surface = - surface_from_wl_shell_surface_resource (resource); - MetaWindow *window; - - g_clear_pointer (&wl_shell_surface->wm_class, g_free); - - if (!g_utf8_validate (class_, -1, NULL)) - class_ = ""; - - wl_shell_surface->wm_class = g_strdup (class_); - - window = meta_wayland_surface_get_window (surface); - if (window) - meta_window_set_wm_class (window, class_, class_); -} - -static const struct wl_shell_surface_interface meta_wayland_wl_shell_surface_interface = { - wl_shell_surface_pong, - wl_shell_surface_move, - wl_shell_surface_resize, - wl_shell_surface_set_toplevel, - wl_shell_surface_set_transient, - wl_shell_surface_set_fullscreen, - wl_shell_surface_set_popup, - wl_shell_surface_set_maximized, - wl_shell_surface_set_title, - wl_shell_surface_set_class, -}; - -static void -sync_wl_shell_parent_relationship (MetaWaylandSurface *surface, - MetaWaylandSurface *parent) -{ - MetaWaylandWlShellSurface *wl_shell_surface = - META_WAYLAND_WL_SHELL_SURFACE (surface->role); - MetaWindow *window; - MetaWindow *parent_window; - - window = meta_wayland_surface_get_window (surface); - parent_window = meta_wayland_surface_get_window (parent); - meta_window_set_transient_for (window, parent_window); - - if (wl_shell_surface->state == META_WL_SHELL_SURFACE_STATE_POPUP || - wl_shell_surface->state == META_WL_SHELL_SURFACE_STATE_TRANSIENT) - meta_window_wayland_place_relative_to (window, - parent_window, - wl_shell_surface->x, - wl_shell_surface->y); - - if (wl_shell_surface->state == META_WL_SHELL_SURFACE_STATE_POPUP && - wl_shell_surface->pending_popup) - { - meta_wayland_wl_shell_surface_create_popup (wl_shell_surface); - wl_shell_surface->pending_popup = FALSE; - } -} - -static void -create_wl_shell_surface_window (MetaWaylandSurface *surface) -{ - MetaWaylandWlShellSurface *wl_shell_surface = - META_WAYLAND_WL_SHELL_SURFACE (surface->role); - MetaWaylandShellSurface *shell_surface = - META_WAYLAND_SHELL_SURFACE (wl_shell_surface); - MetaWaylandSurface *parent; - MetaWindow *window; - GList *l; - - window = meta_window_wayland_new (meta_get_display (), surface); - meta_wayland_shell_surface_set_window (shell_surface, window); - - if (wl_shell_surface->title) - meta_window_set_title (window, wl_shell_surface->title); - if (wl_shell_surface->wm_class) - meta_window_set_wm_class (window, - wl_shell_surface->wm_class, - wl_shell_surface->wm_class); - - parent = wl_shell_surface->parent_surface; - if (parent && meta_wayland_surface_get_window (parent)) - sync_wl_shell_parent_relationship (surface, parent); - - for (l = wl_shell_surface->children; l; l = l->next) - { - MetaWaylandSurface *child = l->data; - - if (meta_wayland_surface_get_window (child)) - sync_wl_shell_parent_relationship (child, surface); - } -} - -static void -wl_shell_get_shell_surface (struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *surface_resource) -{ - MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); - MetaWaylandWlShellSurface *wl_shell_surface; - - if (META_IS_WAYLAND_WL_SHELL_SURFACE (surface->role) && - META_WAYLAND_WL_SHELL_SURFACE (surface->role)->resource) - { - wl_resource_post_error (surface_resource, - WL_DISPLAY_ERROR_INVALID_OBJECT, - "wl_shell::get_shell_surface already requested"); - return; - } - - if (!meta_wayland_surface_assign_role (surface, - META_TYPE_WAYLAND_WL_SHELL_SURFACE, - NULL)) - { - wl_resource_post_error (resource, WL_SHELL_ERROR_ROLE, - "wl_surface@%d already has a different role", - wl_resource_get_id (surface->resource)); - return; - } - - wl_shell_surface = META_WAYLAND_WL_SHELL_SURFACE (surface->role); - wl_shell_surface->resource = - wl_resource_create (client, - &wl_shell_surface_interface, - wl_resource_get_version (resource), - id); - wl_resource_set_implementation (wl_shell_surface->resource, - &meta_wayland_wl_shell_surface_interface, - wl_shell_surface, - wl_shell_surface_destructor); - - create_wl_shell_surface_window (surface); -} - -static const struct wl_shell_interface meta_wayland_wl_shell_interface = { - wl_shell_get_shell_surface, -}; - -static void -bind_wl_shell (struct wl_client *client, - void *data, - uint32_t version, - uint32_t id) -{ - struct wl_resource *resource; - - resource = wl_resource_create (client, &wl_shell_interface, version, id); - wl_resource_set_implementation (resource, &meta_wayland_wl_shell_interface, data, NULL); -} - -static void -wl_shell_surface_role_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending) -{ - MetaWaylandWlShellSurface *wl_shell_surface = - META_WAYLAND_WL_SHELL_SURFACE (surface_role); - MetaWaylandShellSurface *shell_surface = - META_WAYLAND_SHELL_SURFACE (wl_shell_surface); - MetaWaylandSurfaceRoleClass *surface_role_class; - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWindow *window = meta_wayland_surface_get_window (surface); - cairo_region_t *input_region; - MetaRectangle geom = { 0 }; - - surface_role_class = - META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_wl_shell_surface_parent_class); - surface_role_class->apply_state (surface_role, pending); - - /* For wl_shell, it's equivalent to an unmap. Semantics - * are poorly defined, so we can choose some that are - * convenient for us. */ - if (surface->buffer_ref->buffer && !window) - { - create_wl_shell_surface_window (surface); - } - else if (!surface->buffer_ref->buffer && window) - { - if (wl_shell_surface->popup) - meta_wayland_popup_dismiss (wl_shell_surface->popup); - else - meta_wayland_shell_surface_destroy_window (shell_surface); - return; - } - - if (!window) - return; - - input_region = meta_wayland_surface_calculate_input_region (surface); - if (!cairo_region_is_empty (input_region)) - { - cairo_region_get_extents (input_region, &geom); - cairo_region_destroy (input_region); - } - else - { - meta_wayland_shell_surface_calculate_geometry (shell_surface, &geom); - } - - pending->has_acked_configure_serial = TRUE; - pending->acked_configure_serial = - wl_shell_surface->emulated_ack_configure_serial; - - meta_window_wayland_finish_move_resize (window, geom, pending); -} - -static MetaWaylandSurface * -wl_shell_surface_role_get_toplevel (MetaWaylandSurfaceRole *surface_role) -{ - MetaWaylandWlShellSurface *wl_shell_surface = - META_WAYLAND_WL_SHELL_SURFACE (surface_role); - - if (wl_shell_surface->state == META_WL_SHELL_SURFACE_STATE_POPUP && - wl_shell_surface->parent_surface) - return meta_wayland_surface_get_toplevel (wl_shell_surface->parent_surface); - else - return meta_wayland_surface_role_get_surface (surface_role); -} - -static void -wl_shell_surface_role_configure (MetaWaylandShellSurface *shell_surface, - MetaWaylandWindowConfiguration *configuration) -{ - MetaWaylandWlShellSurface *wl_shell_surface = - META_WAYLAND_WL_SHELL_SURFACE (shell_surface); - - if (!wl_shell_surface->resource) - return; - - wl_shell_surface_send_configure (wl_shell_surface->resource, - 0, - configuration->width / configuration->scale, - configuration->height / configuration->scale); - - wl_shell_surface->emulated_ack_configure_serial = configuration->serial; -} - -static void -wl_shell_surface_role_managed (MetaWaylandShellSurface *shell_surface, - MetaWindow *window) -{ - MetaWaylandWlShellSurface *wl_shell_surface = - META_WAYLAND_WL_SHELL_SURFACE (shell_surface); - - if (wl_shell_surface->state == META_WL_SHELL_SURFACE_STATE_POPUP) - meta_window_set_type (window, META_WINDOW_DROPDOWN_MENU); -} - -static void -wl_shell_surface_role_ping (MetaWaylandShellSurface *shell_surface, - guint32 serial) -{ - MetaWaylandWlShellSurface *wl_shell_surface = - META_WAYLAND_WL_SHELL_SURFACE (shell_surface); - - wl_shell_surface_send_ping (wl_shell_surface->resource, serial); -} - -static void -wl_shell_surface_role_close (MetaWaylandShellSurface *shell_surface) -{ - /* Not supported by wl_shell_surface. */ -} - -static void -meta_wayland_wl_shell_surface_popup_done (MetaWaylandPopupSurface *popup_surface) -{ - MetaWaylandWlShellSurface *wl_shell_surface = - META_WAYLAND_WL_SHELL_SURFACE (popup_surface); - - wl_shell_surface_send_popup_done (wl_shell_surface->resource); -} - -static void -meta_wayland_wl_shell_surface_popup_dismiss (MetaWaylandPopupSurface *popup_surface) -{ - MetaWaylandWlShellSurface *wl_shell_surface = - META_WAYLAND_WL_SHELL_SURFACE (popup_surface); - MetaWaylandShellSurface *shell_surface = - META_WAYLAND_SHELL_SURFACE (wl_shell_surface); - - wl_shell_surface->popup = NULL; - - meta_wayland_shell_surface_destroy_window (shell_surface); -} - -static MetaWaylandSurface * -meta_wayland_wl_shell_surface_popup_get_surface (MetaWaylandPopupSurface *popup_surface) -{ - MetaWaylandSurfaceRole *surface_role = - META_WAYLAND_SURFACE_ROLE (popup_surface); - - return meta_wayland_surface_role_get_surface (surface_role); -} - -static void -popup_surface_iface_init (MetaWaylandPopupSurfaceInterface *iface) -{ - iface->done = meta_wayland_wl_shell_surface_popup_done; - iface->dismiss = meta_wayland_wl_shell_surface_popup_dismiss; - iface->get_surface = meta_wayland_wl_shell_surface_popup_get_surface; -} - -static void -wl_shell_surface_role_finalize (GObject *object) -{ - MetaWaylandWlShellSurface *wl_shell_surface = - META_WAYLAND_WL_SHELL_SURFACE (object); - GObjectClass *object_class; - - g_clear_pointer (&wl_shell_surface->resource, wl_resource_destroy); - - object_class = - G_OBJECT_CLASS (meta_wayland_wl_shell_surface_parent_class); - object_class->finalize (object); -} - -static void -meta_wayland_wl_shell_surface_init (MetaWaylandWlShellSurface *wl_shell_surface) -{ -} - -static void -meta_wayland_wl_shell_surface_class_init (MetaWaylandWlShellSurfaceClass *klass) -{ - GObjectClass *object_class; - MetaWaylandSurfaceRoleClass *surface_role_class; - MetaWaylandShellSurfaceClass *shell_surface_class; - - object_class = G_OBJECT_CLASS (klass); - object_class->finalize = wl_shell_surface_role_finalize; - - surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass); - surface_role_class->apply_state = wl_shell_surface_role_apply_state; - surface_role_class->get_toplevel = wl_shell_surface_role_get_toplevel; - - shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass); - shell_surface_class->configure = wl_shell_surface_role_configure; - shell_surface_class->managed = wl_shell_surface_role_managed; - shell_surface_class->ping = wl_shell_surface_role_ping; - shell_surface_class->close = wl_shell_surface_role_close; -} - -void -meta_wayland_wl_shell_init (MetaWaylandCompositor *compositor) -{ - if (wl_global_create (compositor->wayland_display, - &wl_shell_interface, - META_WL_SHELL_VERSION, - compositor, bind_wl_shell) == NULL) - g_error ("Failed to register a global wl-shell object"); -} diff --git a/src/wayland/meta-wayland-wl-shell.h b/src/wayland/meta-wayland-wl-shell.h deleted file mode 100644 index 4a62d8a72..000000000 --- a/src/wayland/meta-wayland-wl-shell.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2013-2015 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_WAYLAND_WL_SHELL_H -#define META_WAYLAND_WL_SHELL_H - -#include "wayland/meta-wayland-shell-surface.h" - -#define META_TYPE_WAYLAND_WL_SHELL_SURFACE (meta_wayland_wl_shell_surface_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandWlShellSurface, - meta_wayland_wl_shell_surface, - META, WAYLAND_WL_SHELL_SURFACE, - MetaWaylandShellSurface); - -void meta_wayland_wl_shell_init (MetaWaylandCompositor *compositor); - -#endif /* META_WAYLAND_WL_SHELL_H */ diff --git a/src/wayland/meta-wayland-xdg-foreign.c b/src/wayland/meta-wayland-xdg-foreign.c deleted file mode 100644 index eb480b996..000000000 --- a/src/wayland/meta-wayland-xdg-foreign.c +++ /dev/null @@ -1,462 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#include "config.h" - -#include "wayland/meta-wayland-xdg-foreign.h" - -#include - -#include "core/util-private.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-versions.h" -#include "wayland/meta-wayland-xdg-shell.h" -#include "wayland/meta-wayland-legacy-xdg-shell.h" - -#include "xdg-foreign-unstable-v1-server-protocol.h" - -#define META_XDG_FOREIGN_HANDLE_LENGTH 32 - -typedef struct _MetaWaylandXdgExported MetaWaylandXdgExported; -typedef struct _MetaWaylandXdgImported MetaWaylandXdgImported; - -typedef struct _MetaWaylandXdgForeign -{ - MetaWaylandCompositor *compositor; - GRand *rand; - - GHashTable *exported_surfaces; -} MetaWaylandXdgForeign; - -struct _MetaWaylandXdgExported -{ - MetaWaylandXdgForeign *foreign; - struct wl_resource *resource; - - MetaWaylandSurface *surface; - gulong surface_unmapped_handler_id; - char *handle; - - GList *imported; -}; - -struct _MetaWaylandXdgImported -{ - MetaWaylandXdgForeign *foreign; - struct wl_resource *resource; - - MetaWaylandSurface *parent_of; - gulong parent_of_unmapped_handler_id; - - MetaWaylandXdgExported *exported; -}; - -static void -meta_wayland_xdg_imported_destroy (MetaWaylandXdgImported *imported); - -static void -xdg_exporter_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -xdg_exported_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static const struct zxdg_exported_v1_interface meta_xdg_exported_interface = { - xdg_exported_destroy, -}; - -static void -meta_wayland_xdg_exported_destroy (MetaWaylandXdgExported *exported) -{ - MetaWaylandXdgForeign *foreign = exported->foreign; - - while (exported->imported) - { - MetaWaylandXdgImported *imported = exported->imported->data; - - zxdg_imported_v1_send_destroyed (imported->resource); - meta_wayland_xdg_imported_destroy (imported); - } - - g_clear_signal_handler (&exported->surface_unmapped_handler_id, - exported->surface); - wl_resource_set_user_data (exported->resource, NULL); - - g_hash_table_remove (foreign->exported_surfaces, exported->handle); - - g_free (exported->handle); - g_free (exported); -} - -static void -xdg_exported_destructor (struct wl_resource *resource) -{ - MetaWaylandXdgExported *exported = wl_resource_get_user_data (resource); - - if (exported) - meta_wayland_xdg_exported_destroy (exported); -} - -static void -exported_surface_unmapped (MetaWaylandSurface *surface, - MetaWaylandXdgExported *exported) -{ - meta_wayland_xdg_exported_destroy (exported); -} - -static void -xdg_exporter_export (struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *surface_resource) -{ - MetaWaylandXdgForeign *foreign = wl_resource_get_user_data (resource); - MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); - struct wl_resource *xdg_exported_resource; - MetaWaylandXdgExported *exported; - char *handle; - - if (!surface->role || - !meta_wayland_surface_get_window (surface) || - !(META_IS_WAYLAND_XDG_SURFACE (surface->role) || - META_IS_WAYLAND_ZXDG_SURFACE_V6 (surface->role))) - { - wl_resource_post_error (resource, - WL_DISPLAY_ERROR_INVALID_OBJECT, - "exported surface had an invalid role"); - return; - } - - xdg_exported_resource = - wl_resource_create (client, - &zxdg_exported_v1_interface, - wl_resource_get_version (resource), - id); - if (!xdg_exported_resource) - { - wl_client_post_no_memory (client); - return; - } - - exported = g_new0 (MetaWaylandXdgExported, 1); - exported->foreign = foreign; - exported->surface = surface; - exported->resource = xdg_exported_resource; - - exported->surface_unmapped_handler_id = - g_signal_connect (surface, "unmapped", - G_CALLBACK (exported_surface_unmapped), - exported); - - wl_resource_set_implementation (xdg_exported_resource, - &meta_xdg_exported_interface, - exported, - xdg_exported_destructor); - - while (TRUE) - { - handle = meta_generate_random_id (foreign->rand, - META_XDG_FOREIGN_HANDLE_LENGTH); - - if (!g_hash_table_contains (foreign->exported_surfaces, handle)) - { - g_hash_table_insert (foreign->exported_surfaces, handle, exported); - break; - } - - g_free (handle); - } - - exported->handle = handle; - - zxdg_exported_v1_send_handle (xdg_exported_resource, handle); -} - -static const struct zxdg_exporter_v1_interface meta_xdg_exporter_interface = { - xdg_exporter_destroy, - xdg_exporter_export, -}; - -static void -bind_xdg_exporter (struct wl_client *client, - void *data, - uint32_t version, - uint32_t id) -{ - MetaWaylandXdgForeign *foreign = data; - struct wl_resource *resource; - - resource = wl_resource_create (client, - &zxdg_exporter_v1_interface, - META_ZXDG_EXPORTER_V1_VERSION, - id); - - if (resource == NULL) - { - wl_client_post_no_memory (client); - return; - } - - wl_resource_set_implementation (resource, - &meta_xdg_exporter_interface, - foreign, NULL); -} - -static void -xdg_imported_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -imported_parent_of_unmapped (MetaWaylandSurface *surface, - MetaWaylandXdgImported *imported) -{ - imported->parent_of = NULL; -} - -static gboolean -is_valid_child (MetaWaylandSurface *surface) -{ - if (!surface) - return TRUE; - - if (!surface->role) - return FALSE; - - if (!META_IS_WAYLAND_XDG_TOPLEVEL (surface->role) && - !META_IS_WAYLAND_ZXDG_TOPLEVEL_V6 (surface->role)) - return FALSE; - - if (!meta_wayland_surface_get_window (surface)) - return FALSE; - - return TRUE; -} - -static void -xdg_imported_set_parent_of (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *surface_resource) -{ - MetaWaylandXdgImported *imported = wl_resource_get_user_data (resource); - MetaWaylandSurface *surface; - - if (!imported) - return; - - if (surface_resource) - surface = wl_resource_get_user_data (surface_resource); - else - surface = NULL; - - if (!is_valid_child (surface)) - { - wl_resource_post_error (imported->resource, - WL_DISPLAY_ERROR_INVALID_OBJECT, - "set_parent_of was called with an invalid child"); - return; - } - - if (imported->parent_of) - g_clear_signal_handler (&imported->parent_of_unmapped_handler_id, - imported->parent_of); - - imported->parent_of = surface; - - if (surface) - { - MetaWindow *window; - MetaWindow *exported_window; - - imported->parent_of_unmapped_handler_id = - g_signal_connect (surface, "unmapped", - G_CALLBACK (imported_parent_of_unmapped), - imported); - - window = meta_wayland_surface_get_window (surface); - exported_window = - meta_wayland_surface_get_window (imported->exported->surface); - meta_window_set_transient_for (window, exported_window); - } -} - -static const struct zxdg_imported_v1_interface meta_xdg_imported_interface = { - xdg_imported_destroy, - xdg_imported_set_parent_of, -}; - -static void -xdg_importer_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -meta_wayland_xdg_imported_destroy (MetaWaylandXdgImported *imported) -{ - MetaWaylandXdgExported *exported = imported->exported; - - exported->imported = g_list_remove (exported->imported, imported); - - if (imported->parent_of) - { - MetaWindow *window; - - g_clear_signal_handler (&imported->parent_of_unmapped_handler_id, - imported->parent_of); - - window = meta_wayland_surface_get_window (imported->parent_of); - if (window) - meta_window_set_transient_for (window, NULL); - } - - wl_resource_set_user_data (imported->resource, NULL); - - g_free (imported); -} - -static void -xdg_imported_destructor (struct wl_resource *resource) -{ - MetaWaylandXdgImported *imported = wl_resource_get_user_data (resource); - - if (!imported) - return; - - meta_wayland_xdg_imported_destroy (imported); -} - -static void -xdg_importer_import (struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - const char *handle) -{ - MetaWaylandXdgForeign *foreign = wl_resource_get_user_data (resource); - struct wl_resource *xdg_imported_resource; - MetaWaylandXdgImported *imported; - MetaWaylandXdgExported *exported; - - xdg_imported_resource = - wl_resource_create (client, - &zxdg_imported_v1_interface, - wl_resource_get_version (resource), - id); - if (!xdg_imported_resource) - { - wl_client_post_no_memory (client); - return; - } - - wl_resource_set_implementation (xdg_imported_resource, - &meta_xdg_imported_interface, - NULL, - xdg_imported_destructor); - - exported = g_hash_table_lookup (foreign->exported_surfaces, handle); - if (!exported || - (!META_IS_WAYLAND_XDG_SURFACE (exported->surface->role) && - !META_IS_WAYLAND_ZXDG_SURFACE_V6 (exported->surface->role))) - { - zxdg_imported_v1_send_destroyed (xdg_imported_resource); - return; - } - - imported = g_new0 (MetaWaylandXdgImported, 1); - imported->foreign = foreign; - imported->exported = exported; - imported->resource = xdg_imported_resource; - - wl_resource_set_user_data (xdg_imported_resource, imported); - - exported->imported = g_list_prepend (exported->imported, imported); -} - -static const struct zxdg_importer_v1_interface meta_xdg_importer_interface = { - xdg_importer_destroy, - xdg_importer_import, -}; - -static void -bind_xdg_importer (struct wl_client *client, - void *data, - uint32_t version, - uint32_t id) -{ - MetaWaylandXdgForeign *foreign = data; - struct wl_resource *resource; - - resource = wl_resource_create (client, - &zxdg_importer_v1_interface, - META_ZXDG_IMPORTER_V1_VERSION, - id); - - if (resource == NULL) - { - wl_client_post_no_memory (client); - return; - } - - wl_resource_set_implementation (resource, - &meta_xdg_importer_interface, - foreign, - NULL); -} - -gboolean -meta_wayland_xdg_foreign_init (MetaWaylandCompositor *compositor) -{ - MetaWaylandXdgForeign *foreign; - - foreign = g_new0 (MetaWaylandXdgForeign, 1); - - foreign->compositor = compositor; - foreign->rand = g_rand_new (); - foreign->exported_surfaces = g_hash_table_new ((GHashFunc) g_str_hash, - (GEqualFunc) g_str_equal); - - if (wl_global_create (compositor->wayland_display, - &zxdg_exporter_v1_interface, 1, - foreign, - bind_xdg_exporter) == NULL) - return FALSE; - - if (wl_global_create (compositor->wayland_display, - &zxdg_importer_v1_interface, 1, - foreign, - bind_xdg_importer) == NULL) - return FALSE; - - return TRUE; -} diff --git a/src/wayland/meta-wayland-xdg-foreign.h b/src/wayland/meta-wayland-xdg-foreign.h deleted file mode 100644 index 5542a301e..000000000 --- a/src/wayland/meta-wayland-xdg-foreign.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#ifndef META_WAYLAND_FOREIGN_H -#define META_WAYLAND_FOREIGN_H - -#include - -#include "wayland/meta-wayland-types.h" - -gboolean meta_wayland_xdg_foreign_init (MetaWaylandCompositor *compositor); - -#endif /* META_WAYLAND_FOREIGN_H */ diff --git a/src/wayland/meta-wayland-xdg-shell.c b/src/wayland/meta-wayland-xdg-shell.c deleted file mode 100644 index c5f0d0b91..000000000 --- a/src/wayland/meta-wayland-xdg-shell.c +++ /dev/null @@ -1,2437 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2012-2013 Intel Corporation - * Copyright (C) 2013-2015 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "wayland/meta-wayland-xdg-shell.h" - -#include "backends/meta-logical-monitor.h" -#include "core/boxes-private.h" -#include "core/window-private.h" -#include "wayland/meta-wayland-outputs.h" -#include "wayland/meta-wayland-popup.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-seat.h" -#include "wayland/meta-wayland-shell-surface.h" -#include "wayland/meta-wayland-surface.h" -#include "wayland/meta-wayland-versions.h" -#include "wayland/meta-wayland-window-configuration.h" -#include "wayland/meta-wayland.h" -#include "wayland/meta-window-wayland.h" - -#include "xdg-shell-server-protocol.h" - -enum -{ - XDG_SURFACE_PROP_0, - - XDG_SURFACE_PROP_SHELL_CLIENT, - XDG_SURFACE_PROP_RESOURCE, -}; - -typedef struct _MetaWaylandXdgShellClient -{ - struct wl_resource *resource; - GList *surfaces; - GList *surface_constructors; -} MetaWaylandXdgShellClient; - -typedef struct _MetaWaylandXdgPositioner -{ - MetaRectangle anchor_rect; - int32_t width; - int32_t height; - uint32_t gravity; - uint32_t anchor; - uint32_t constraint_adjustment; - int32_t offset_x; - int32_t offset_y; - - gboolean is_reactive; - - gboolean has_parent_size; - int32_t parent_width; - int32_t parent_height; - - gboolean acked_parent_configure; - uint32_t parent_configure_serial; -} MetaWaylandXdgPositioner; - -typedef struct _MetaWaylandXdgSurfaceConstructor -{ - MetaWaylandSurface *surface; - struct wl_resource *resource; - MetaWaylandXdgShellClient *shell_client; -} MetaWaylandXdgSurfaceConstructor; - -typedef struct _MetaWaylandXdgSurfacePrivate -{ - struct wl_resource *resource; - MetaWaylandXdgShellClient *shell_client; - MetaRectangle geometry; - - guint configure_sent : 1; - guint first_buffer_attached : 1; - guint has_set_geometry : 1; -} MetaWaylandXdgSurfacePrivate; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandXdgSurface, - meta_wayland_xdg_surface, - META_TYPE_WAYLAND_SHELL_SURFACE); - -struct _MetaWaylandXdgToplevel -{ - MetaWaylandXdgSurface parent; - - struct wl_resource *resource; -}; - -G_DEFINE_TYPE (MetaWaylandXdgToplevel, - meta_wayland_xdg_toplevel, - META_TYPE_WAYLAND_XDG_SURFACE); - -struct _MetaWaylandXdgPopup -{ - MetaWaylandXdgSurface parent; - - struct wl_resource *resource; - - MetaWaylandSurface *parent_surface; - gulong parent_surface_unmapped_handler_id; - - uint32_t pending_reposition_token; - gboolean pending_repositioned; - - MetaWaylandPopup *popup; - - gboolean dismissed_by_client; - - struct { - MetaWaylandSurface *parent_surface; - - /* - * The coordinates/dimensions in the placement rule are in logical pixel - * coordinate space, i.e. not scaled given what monitor the popup is on. - */ - MetaPlacementRule placement_rule; - - MetaWaylandSeat *grab_seat; - uint32_t grab_serial; - } setup; -}; - -static void -popup_surface_iface_init (MetaWaylandPopupSurfaceInterface *iface); - -G_DEFINE_TYPE_WITH_CODE (MetaWaylandXdgPopup, - meta_wayland_xdg_popup, - META_TYPE_WAYLAND_XDG_SURFACE, - G_IMPLEMENT_INTERFACE (META_TYPE_WAYLAND_POPUP_SURFACE, - popup_surface_iface_init)); - -static MetaPlacementRule -meta_wayland_xdg_positioner_to_placement (MetaWaylandXdgPositioner *xdg_positioner, - MetaWindow *parent_window); - -static struct wl_resource * -meta_wayland_xdg_surface_get_wm_base_resource (MetaWaylandXdgSurface *xdg_surface); - -static MetaRectangle -meta_wayland_xdg_surface_get_window_geometry (MetaWaylandXdgSurface *xdg_surface); - -static void -meta_wayland_xdg_surface_send_configure (MetaWaylandXdgSurface *xdg_surface, - MetaWaylandWindowConfiguration *configuration); - -static void -scale_placement_rule (MetaPlacementRule *placement_rule, - MetaWaylandSurface *surface); - -static MetaWaylandSurface * -surface_from_xdg_surface_resource (struct wl_resource *resource) -{ - MetaWaylandSurfaceRole *surface_role = wl_resource_get_user_data (resource); - - if (!META_IS_WAYLAND_SURFACE_ROLE (surface_role)) - return NULL; - - return meta_wayland_surface_role_get_surface (surface_role); -} - -static MetaWaylandSurface * -surface_from_xdg_toplevel_resource (struct wl_resource *resource) -{ - return surface_from_xdg_surface_resource (resource); -} - -static void -meta_wayland_xdg_surface_reset (MetaWaylandXdgSurface *xdg_surface) -{ - META_WAYLAND_XDG_SURFACE_GET_CLASS (xdg_surface)->reset (xdg_surface); -} - -static void -xdg_toplevel_destructor (struct wl_resource *resource) -{ - MetaWaylandXdgToplevel *xdg_toplevel = wl_resource_get_user_data (resource); - MetaWaylandShellSurface *shell_surface = - META_WAYLAND_SHELL_SURFACE (xdg_toplevel); - - meta_wayland_shell_surface_destroy_window (shell_surface); - xdg_toplevel->resource = NULL; -} - -static void -xdg_toplevel_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -xdg_toplevel_set_parent (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *parent_resource) -{ - MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource); - MetaWindow *transient_for = NULL; - MetaWindow *window; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - if (parent_resource) - { - MetaWaylandSurface *parent_surface = - surface_from_xdg_surface_resource (parent_resource); - - transient_for = meta_wayland_surface_get_window (parent_surface); - } - - meta_window_set_transient_for (window, transient_for); -} - -static void -xdg_toplevel_set_title (struct wl_client *client, - struct wl_resource *resource, - const char *title) -{ - MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource); - MetaWindow *window; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - if (!g_utf8_validate (title, -1, NULL)) - title = ""; - - meta_window_set_title (window, title); -} - -static void -xdg_toplevel_set_app_id (struct wl_client *client, - struct wl_resource *resource, - const char *app_id) -{ - MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource); - MetaWindow *window; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - if (!g_utf8_validate (app_id, -1, NULL)) - app_id = ""; - - meta_window_set_wm_class (window, app_id, app_id); -} - -static void -xdg_toplevel_show_window_menu (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *seat_resource, - uint32_t serial, - int32_t x, - int32_t y) -{ - MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); - MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource); - MetaWindow *window; - int monitor_scale; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - if (!meta_wayland_seat_get_grab_info (seat, surface, serial, FALSE, NULL, NULL)) - return; - - monitor_scale = meta_window_wayland_get_geometry_scale (window); - meta_window_show_menu (window, META_WINDOW_MENU_WM, - window->buffer_rect.x + (x * monitor_scale), - window->buffer_rect.y + (y * monitor_scale)); -} - -static void -xdg_toplevel_move (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *seat_resource, - uint32_t serial) -{ - MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); - MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource); - MetaWindow *window; - float x, y; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - if (!meta_wayland_seat_get_grab_info (seat, surface, serial, TRUE, &x, &y)) - return; - - meta_wayland_surface_begin_grab_op (surface, seat, META_GRAB_OP_MOVING, x, y); -} - -static MetaGrabOp -grab_op_for_xdg_toplevel_resize_edge (int edge) -{ - MetaGrabOp op = META_GRAB_OP_WINDOW_BASE; - - if (edge & XDG_TOPLEVEL_RESIZE_EDGE_TOP) - op |= META_GRAB_OP_WINDOW_DIR_NORTH; - if (edge & XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM) - op |= META_GRAB_OP_WINDOW_DIR_SOUTH; - if (edge & XDG_TOPLEVEL_RESIZE_EDGE_LEFT) - op |= META_GRAB_OP_WINDOW_DIR_WEST; - if (edge & XDG_TOPLEVEL_RESIZE_EDGE_RIGHT) - op |= META_GRAB_OP_WINDOW_DIR_EAST; - - if (op == META_GRAB_OP_WINDOW_BASE) - { - g_warning ("invalid edge: %d", edge); - return META_GRAB_OP_NONE; - } - - return op; -} - -static void -xdg_toplevel_resize (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *seat_resource, - uint32_t serial, - uint32_t edges) -{ - MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); - MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource); - MetaWindow *window; - gfloat x, y; - MetaGrabOp grab_op; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - if (!window->has_resize_func) - return; - - if (!meta_wayland_seat_get_grab_info (seat, surface, serial, TRUE, &x, &y)) - return; - - grab_op = grab_op_for_xdg_toplevel_resize_edge (edges); - meta_wayland_surface_begin_grab_op (surface, seat, grab_op, x, y); -} - -static void -xdg_toplevel_set_max_size (struct wl_client *client, - struct wl_resource *resource, - int32_t width, - int32_t height) -{ - MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource); - MetaWaylandSurfaceState *pending; - - if (width < 0 || height < 0) - { - wl_resource_post_error (resource, - XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE, - "invalid negative max size requested %i x %i", - width, height); - return; - } - - - pending = meta_wayland_surface_get_pending_state (surface); - pending->has_new_max_size = TRUE; - pending->new_max_width = width; - pending->new_max_height = height; -} - -static void -xdg_toplevel_set_min_size (struct wl_client *client, - struct wl_resource *resource, - int32_t width, - int32_t height) -{ - MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource); - MetaWaylandSurfaceState *pending; - - if (width < 0 || height < 0) - { - wl_resource_post_error (resource, - XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE, - "invalid negative min size requested %i x %i", - width, height); - return; - } - - - pending = meta_wayland_surface_get_pending_state (surface); - pending->has_new_min_size = TRUE; - pending->new_min_width = width; - pending->new_min_height = height; -} - -static void -xdg_toplevel_set_maximized (struct wl_client *client, - struct wl_resource *resource) -{ - MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource); - MetaWindow *window; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - if (!window->has_maximize_func) - return; - - meta_window_force_placement (window, TRUE); - meta_window_maximize (window, META_MAXIMIZE_BOTH); -} - -static void -xdg_toplevel_unset_maximized (struct wl_client *client, - struct wl_resource *resource) -{ - MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource); - MetaWindow *window; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - meta_window_unmaximize (window, META_MAXIMIZE_BOTH); -} - -static void -xdg_toplevel_set_fullscreen (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *output_resource) -{ - MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource); - MetaWindow *window; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - if (output_resource) - { - MetaWaylandOutput *output = wl_resource_get_user_data (output_resource); - - if (output && output->logical_monitor) - { - meta_window_move_to_monitor (window, - output->logical_monitor->number); - } - } - - meta_window_make_fullscreen (window); -} - -static void -xdg_toplevel_unset_fullscreen (struct wl_client *client, - struct wl_resource *resource) -{ - MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource); - MetaWindow *window; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - meta_window_unmake_fullscreen (window); -} - -static void -xdg_toplevel_set_minimized (struct wl_client *client, - struct wl_resource *resource) -{ - MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource); - MetaWindow *window; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - meta_window_minimize (window); -} - -static const struct xdg_toplevel_interface meta_wayland_xdg_toplevel_interface = { - xdg_toplevel_destroy, - xdg_toplevel_set_parent, - xdg_toplevel_set_title, - xdg_toplevel_set_app_id, - xdg_toplevel_show_window_menu, - xdg_toplevel_move, - xdg_toplevel_resize, - xdg_toplevel_set_max_size, - xdg_toplevel_set_min_size, - xdg_toplevel_set_maximized, - xdg_toplevel_unset_maximized, - xdg_toplevel_set_fullscreen, - xdg_toplevel_unset_fullscreen, - xdg_toplevel_set_minimized, -}; - -static void -meta_wayland_xdg_popup_unmap (MetaWaylandXdgPopup *xdg_popup) -{ - MetaWaylandShellSurface *shell_surface = - META_WAYLAND_SHELL_SURFACE (xdg_popup); - - g_assert (!xdg_popup->popup); - - if (xdg_popup->parent_surface) - { - g_clear_signal_handler (&xdg_popup->parent_surface_unmapped_handler_id, - xdg_popup->parent_surface); - xdg_popup->parent_surface = NULL; - } - - meta_wayland_shell_surface_destroy_window (shell_surface); -} - -static void -dismiss_popup (MetaWaylandXdgPopup *xdg_popup) -{ - if (xdg_popup->popup) - meta_wayland_popup_dismiss (xdg_popup->popup); - else - meta_wayland_xdg_popup_unmap (xdg_popup); -} - -static void -xdg_popup_destructor (struct wl_resource *resource) -{ - MetaWaylandXdgPopup *xdg_popup = - META_WAYLAND_XDG_POPUP (wl_resource_get_user_data (resource)); - - dismiss_popup (xdg_popup); - - xdg_popup->resource = NULL; -} - -static void -xdg_popup_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -xdg_popup_grab (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *seat_resource, - uint32_t serial) -{ - MetaWaylandXdgPopup *xdg_popup = - META_WAYLAND_XDG_POPUP (wl_resource_get_user_data (resource)); - MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); - MetaWaylandSurface *parent_surface; - - parent_surface = xdg_popup->setup.parent_surface; - if (!parent_surface) - { - wl_resource_post_error (resource, - XDG_POPUP_ERROR_INVALID_GRAB, - "tried to grab after popup was mapped"); - return; - } - - xdg_popup->setup.grab_seat = seat; - xdg_popup->setup.grab_serial = serial; -} - -static void -xdg_popup_reposition (struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *positioner_resource, - uint32_t token) -{ - MetaWaylandXdgPopup *xdg_popup = - META_WAYLAND_XDG_POPUP (wl_resource_get_user_data (resource)); - MetaWaylandSurfaceRole *surface_role = - META_WAYLAND_SURFACE_ROLE (xdg_popup); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWindow *window; - MetaWindow *parent_window; - MetaWaylandXdgPositioner *xdg_positioner; - MetaPlacementRule placement_rule; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - parent_window = meta_wayland_surface_get_window (xdg_popup->parent_surface); - - xdg_positioner = wl_resource_get_user_data (positioner_resource); - placement_rule = meta_wayland_xdg_positioner_to_placement (xdg_positioner, - parent_window); - - xdg_popup->pending_reposition_token = token; - xdg_popup->pending_repositioned = TRUE; - - scale_placement_rule (&placement_rule, surface); - - meta_window_update_placement_rule (window, &placement_rule); -} - -static const struct xdg_popup_interface meta_wayland_xdg_popup_interface = { - xdg_popup_destroy, - xdg_popup_grab, - xdg_popup_reposition, -}; - -static void -on_parent_surface_unmapped (MetaWaylandSurface *parent_surface, - MetaWaylandXdgPopup *xdg_popup) -{ - MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (xdg_popup); - struct wl_resource *xdg_wm_base_resource = - meta_wayland_xdg_surface_get_wm_base_resource (xdg_surface); - MetaWaylandShellSurface *shell_surface = - META_WAYLAND_SHELL_SURFACE (xdg_popup); - - wl_resource_post_error (xdg_wm_base_resource, - XDG_WM_BASE_ERROR_NOT_THE_TOPMOST_POPUP, - "destroyed popup not top most popup"); - xdg_popup->parent_surface = NULL; - - meta_wayland_shell_surface_destroy_window (shell_surface); -} - -static void -add_state_value (struct wl_array *states, - enum xdg_toplevel_state state) -{ - uint32_t *s; - - s = wl_array_add (states, sizeof *s); - *s = state; -} - -static void -fill_states (MetaWaylandXdgToplevel *xdg_toplevel, - struct wl_array *states) -{ - MetaWaylandSurfaceRole *surface_role = - META_WAYLAND_SURFACE_ROLE (xdg_toplevel); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWindow *window = meta_wayland_surface_get_window (surface); - - if (META_WINDOW_MAXIMIZED (window)) - add_state_value (states, XDG_TOPLEVEL_STATE_MAXIMIZED); - if (meta_window_is_fullscreen (window)) - add_state_value (states, XDG_TOPLEVEL_STATE_FULLSCREEN); - if (meta_grab_op_is_resizing (window->display->grab_op)) - add_state_value (states, XDG_TOPLEVEL_STATE_RESIZING); - if (meta_window_appears_focused (window)) - add_state_value (states, XDG_TOPLEVEL_STATE_ACTIVATED); - - if (wl_resource_get_version (xdg_toplevel->resource) >= - XDG_TOPLEVEL_STATE_TILED_LEFT_SINCE_VERSION) - { - if (window->edge_constraints.top != META_EDGE_CONSTRAINT_NONE) - add_state_value (states, XDG_TOPLEVEL_STATE_TILED_TOP); - if (window->edge_constraints.right != META_EDGE_CONSTRAINT_NONE) - add_state_value (states, XDG_TOPLEVEL_STATE_TILED_RIGHT); - if (window->edge_constraints.bottom != META_EDGE_CONSTRAINT_NONE) - add_state_value (states, XDG_TOPLEVEL_STATE_TILED_BOTTOM); - if (window->edge_constraints.left != META_EDGE_CONSTRAINT_NONE) - add_state_value (states, XDG_TOPLEVEL_STATE_TILED_LEFT); - } -} - -static void -meta_wayland_xdg_toplevel_send_configure (MetaWaylandXdgToplevel *xdg_toplevel, - MetaWaylandWindowConfiguration *configuration) -{ - MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (xdg_toplevel); - struct wl_array states; - - wl_array_init (&states); - fill_states (xdg_toplevel, &states); - - xdg_toplevel_send_configure (xdg_toplevel->resource, - configuration->width / configuration->scale, - configuration->height / configuration->scale, - &states); - wl_array_release (&states); - - meta_wayland_xdg_surface_send_configure (xdg_surface, configuration); -} - -static gboolean -is_new_size_hints_valid (MetaWindow *window, - MetaWaylandSurfaceState *pending) -{ - int new_min_width, new_min_height; - int new_max_width, new_max_height; - - if (pending->has_new_min_size) - { - new_min_width = pending->new_min_width; - new_min_height = pending->new_min_height; - } - else - { - meta_window_wayland_get_min_size (window, &new_min_width, &new_min_height); - } - - if (pending->has_new_max_size) - { - new_max_width = pending->new_max_width; - new_max_height = pending->new_max_height; - } - else - { - meta_window_wayland_get_max_size (window, &new_max_width, &new_max_height); - } - /* Zero means unlimited */ - return ((new_max_width == 0 || new_min_width <= new_max_width) && - (new_max_height == 0 || new_min_height <= new_max_height)); -} - -static void -meta_wayland_xdg_toplevel_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending) -{ - MetaWaylandXdgToplevel *xdg_toplevel = META_WAYLAND_XDG_TOPLEVEL (surface_role); - MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (xdg_toplevel); - MetaWaylandXdgSurfacePrivate *xdg_surface_priv = - meta_wayland_xdg_surface_get_instance_private (xdg_surface); - MetaWaylandActorSurface *actor_surface = - META_WAYLAND_ACTOR_SURFACE (xdg_toplevel); - MetaWaylandSurfaceRoleClass *surface_role_class; - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWindow *window; - - window = meta_wayland_surface_get_window (surface); - if (!window) - { - meta_wayland_actor_surface_queue_frame_callbacks (actor_surface, pending); - return; - } - - if (!surface->buffer_ref->buffer && xdg_surface_priv->first_buffer_attached) - { - meta_wayland_xdg_surface_reset (xdg_surface); - meta_wayland_actor_surface_queue_frame_callbacks (actor_surface, - pending); - return; - } - - surface_role_class = - META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_xdg_toplevel_parent_class); - surface_role_class->apply_state (surface_role, pending); - - if (!xdg_surface_priv->configure_sent) - { - MetaWaylandWindowConfiguration *configuration; - - configuration = meta_wayland_window_configuration_new_empty (); - meta_wayland_xdg_toplevel_send_configure (xdg_toplevel, configuration); - meta_wayland_window_configuration_free (configuration); - return; - } -} - -static void -meta_wayland_xdg_toplevel_post_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending) -{ - MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role); - MetaWaylandXdgSurfacePrivate *xdg_surface_priv = - meta_wayland_xdg_surface_get_instance_private (xdg_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWaylandSurfaceRoleClass *surface_role_class; - MetaWindow *window; - MetaRectangle old_geometry; - MetaRectangle window_geometry; - - gboolean geometry_changed; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - old_geometry = xdg_surface_priv->geometry; - - surface_role_class = - META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_xdg_toplevel_parent_class); - surface_role_class->post_apply_state (surface_role, pending); - - window_geometry = meta_wayland_xdg_surface_get_window_geometry (xdg_surface); - geometry_changed = !meta_rectangle_equal (&old_geometry, &window_geometry); - - if (geometry_changed || pending->has_acked_configure_serial) - { - meta_window_wayland_finish_move_resize (window, window_geometry, pending); - } - else if (pending->dx != 0 || pending->dy != 0) - { - g_warning ("XXX: Attach-initiated move without a new geometry. " - "This is unimplemented right now."); - } - - /* When we get to this point, we ought to have valid size hints */ - if (pending->has_new_min_size || pending->has_new_max_size) - { - if (is_new_size_hints_valid (window, pending)) - { - if (pending->has_new_min_size) - meta_window_wayland_set_min_size (window, - pending->new_min_width, - pending->new_min_height); - - if (pending->has_new_max_size) - meta_window_wayland_set_max_size (window, - pending->new_max_width, - pending->new_max_height); - - meta_window_recalc_features (window); - } - else - { - wl_resource_post_error (surface->resource, - XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE, - "Invalid min/max size"); - } - } -} - -static MetaWaylandSurface * -meta_wayland_xdg_toplevel_get_toplevel (MetaWaylandSurfaceRole *surface_role) -{ - return meta_wayland_surface_role_get_surface (surface_role); -} - -static void -meta_wayland_xdg_toplevel_reset (MetaWaylandXdgSurface *xdg_surface) -{ - MetaWaylandShellSurface *shell_surface = - META_WAYLAND_SHELL_SURFACE (xdg_surface); - MetaWaylandSurfaceRole *surface_role = - META_WAYLAND_SURFACE_ROLE (xdg_surface); - MetaWaylandXdgSurfaceClass *xdg_surface_class = - META_WAYLAND_XDG_SURFACE_CLASS (meta_wayland_xdg_toplevel_parent_class); - MetaWaylandSurface *surface; - MetaWindow *window; - - surface = meta_wayland_surface_role_get_surface (surface_role); - - meta_wayland_shell_surface_destroy_window (shell_surface); - - meta_wayland_actor_surface_reset_actor (META_WAYLAND_ACTOR_SURFACE (surface_role)); - window = meta_window_wayland_new (meta_get_display (), surface); - meta_wayland_shell_surface_set_window (shell_surface, window); - - xdg_surface_class->reset (xdg_surface); -} - -static void -meta_wayland_xdg_toplevel_configure (MetaWaylandShellSurface *shell_surface, - MetaWaylandWindowConfiguration *configuration) -{ - MetaWaylandXdgToplevel *xdg_toplevel = - META_WAYLAND_XDG_TOPLEVEL (shell_surface); - MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (xdg_toplevel); - MetaWaylandXdgSurfacePrivate *xdg_surface_priv = - meta_wayland_xdg_surface_get_instance_private (xdg_surface); - - if (!xdg_surface_priv->resource) - return; - - if (!xdg_toplevel->resource) - return; - - meta_wayland_xdg_toplevel_send_configure (xdg_toplevel, configuration); -} - -static void -meta_wayland_xdg_toplevel_managed (MetaWaylandShellSurface *shell_surface, - MetaWindow *window) -{ -} - -static void -meta_wayland_xdg_toplevel_close (MetaWaylandShellSurface *shell_surface) -{ - MetaWaylandXdgToplevel *xdg_toplevel = - META_WAYLAND_XDG_TOPLEVEL (shell_surface); - - xdg_toplevel_send_close (xdg_toplevel->resource); -} - -static void -meta_wayland_xdg_toplevel_shell_client_destroyed (MetaWaylandXdgSurface *xdg_surface) -{ - MetaWaylandXdgToplevel *xdg_toplevel = - META_WAYLAND_XDG_TOPLEVEL (xdg_surface); - struct wl_resource *xdg_wm_base_resource = - meta_wayland_xdg_surface_get_wm_base_resource (xdg_surface); - MetaWaylandXdgSurfaceClass *xdg_surface_class = - META_WAYLAND_XDG_SURFACE_CLASS (meta_wayland_xdg_toplevel_parent_class); - - xdg_surface_class->shell_client_destroyed (xdg_surface); - - if (xdg_toplevel->resource) - { - wl_resource_post_error (xdg_wm_base_resource, - XDG_WM_BASE_ERROR_DEFUNCT_SURFACES, - "xdg_wm_base of xdg_toplevel@%d was destroyed", - wl_resource_get_id (xdg_toplevel->resource)); - - wl_resource_destroy (xdg_toplevel->resource); - } -} - -static void -meta_wayland_xdg_toplevel_finalize (GObject *object) -{ - MetaWaylandXdgToplevel *xdg_toplevel = META_WAYLAND_XDG_TOPLEVEL (object); - - g_clear_pointer (&xdg_toplevel->resource, wl_resource_destroy); - - G_OBJECT_CLASS (meta_wayland_xdg_toplevel_parent_class)->finalize (object); -} - -static void -meta_wayland_xdg_toplevel_init (MetaWaylandXdgToplevel *role) -{ -} - -static void -meta_wayland_xdg_toplevel_class_init (MetaWaylandXdgToplevelClass *klass) -{ - GObjectClass *object_class; - MetaWaylandSurfaceRoleClass *surface_role_class; - MetaWaylandShellSurfaceClass *shell_surface_class; - MetaWaylandXdgSurfaceClass *xdg_surface_class; - - object_class = G_OBJECT_CLASS (klass); - object_class->finalize = meta_wayland_xdg_toplevel_finalize; - - surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass); - surface_role_class->apply_state = meta_wayland_xdg_toplevel_apply_state; - surface_role_class->post_apply_state = meta_wayland_xdg_toplevel_post_apply_state; - surface_role_class->get_toplevel = meta_wayland_xdg_toplevel_get_toplevel; - - shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass); - shell_surface_class->configure = meta_wayland_xdg_toplevel_configure; - shell_surface_class->managed = meta_wayland_xdg_toplevel_managed; - shell_surface_class->close = meta_wayland_xdg_toplevel_close; - - xdg_surface_class = META_WAYLAND_XDG_SURFACE_CLASS (klass); - xdg_surface_class->shell_client_destroyed = - meta_wayland_xdg_toplevel_shell_client_destroyed; - xdg_surface_class->reset = meta_wayland_xdg_toplevel_reset; -} - -static void -scale_placement_rule (MetaPlacementRule *placement_rule, - MetaWaylandSurface *surface) -{ - MetaWindow *window = meta_wayland_surface_get_window (surface); - int geometry_scale; - - geometry_scale = meta_window_wayland_get_geometry_scale (window); - - placement_rule->anchor_rect.x *= geometry_scale; - placement_rule->anchor_rect.y *= geometry_scale; - placement_rule->anchor_rect.width *= geometry_scale; - placement_rule->anchor_rect.height *= geometry_scale; - placement_rule->offset_x *= geometry_scale; - placement_rule->offset_y *= geometry_scale; - placement_rule->width *= geometry_scale; - placement_rule->height *= geometry_scale; -} - -static void -meta_wayland_xdg_popup_place (MetaWaylandXdgPopup *xdg_popup, - MetaPlacementRule *placement_rule) -{ - MetaWaylandSurfaceRole *surface_role = META_WAYLAND_SURFACE_ROLE (xdg_popup); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaPlacementRule scaled_placement_rule; - MetaWindow *window; - - scaled_placement_rule = *placement_rule; - scale_placement_rule (&scaled_placement_rule, surface); - - window = meta_wayland_surface_get_window (surface); - meta_window_place_with_placement_rule (window, &scaled_placement_rule); -} - -static void -finish_popup_setup (MetaWaylandXdgPopup *xdg_popup) -{ - MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (xdg_popup); - MetaWaylandShellSurface *shell_surface = - META_WAYLAND_SHELL_SURFACE (xdg_surface); - MetaWaylandSurfaceRole *surface_role = META_WAYLAND_SURFACE_ROLE (xdg_popup); - struct wl_resource *xdg_wm_base_resource = - meta_wayland_xdg_surface_get_wm_base_resource (xdg_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWaylandSurface *parent_surface; - MetaWaylandSeat *seat; - uint32_t serial; - MetaDisplay *display = meta_get_display (); - MetaWindow *window; - - parent_surface = xdg_popup->setup.parent_surface; - seat = xdg_popup->setup.grab_seat; - serial = xdg_popup->setup.grab_serial; - - xdg_popup->setup.parent_surface = NULL; - xdg_popup->setup.grab_seat = NULL; - - if (!meta_wayland_surface_get_window (parent_surface)) - { - xdg_popup_send_popup_done (xdg_popup->resource); - return; - } - - if (seat) - { - MetaWaylandSurface *top_popup; - - if (!meta_wayland_seat_can_popup (seat, serial)) - { - xdg_popup_send_popup_done (xdg_popup->resource); - return; - } - - top_popup = meta_wayland_pointer_get_top_popup (seat->pointer); - if (top_popup && parent_surface != top_popup) - { - wl_resource_post_error (xdg_wm_base_resource, - XDG_WM_BASE_ERROR_NOT_THE_TOPMOST_POPUP, - "parent not top most surface"); - return; - } - } - - xdg_popup->parent_surface = parent_surface; - xdg_popup->parent_surface_unmapped_handler_id = - g_signal_connect (parent_surface, "unmapped", - G_CALLBACK (on_parent_surface_unmapped), - xdg_popup); - - window = meta_window_wayland_new (display, surface); - meta_wayland_shell_surface_set_window (shell_surface, window); - - meta_wayland_xdg_popup_place (xdg_popup, &xdg_popup->setup.placement_rule); - - if (seat) - { - MetaWaylandPopupSurface *popup_surface; - MetaWaylandPopup *popup; - - meta_window_focus (window, meta_display_get_current_time (display)); - popup_surface = META_WAYLAND_POPUP_SURFACE (surface->role); - popup = meta_wayland_pointer_start_popup_grab (seat->pointer, - popup_surface); - if (popup == NULL) - { - xdg_popup_send_popup_done (xdg_popup->resource); - meta_wayland_shell_surface_destroy_window (shell_surface); - return; - } - - xdg_popup->popup = popup; - } - else - { - /* The keyboard focus semantics for non-grabbing xdg_wm_base popups - * is pretty undefined. Same applies for subsurfaces, but in practice, - * subsurfaces never receive keyboard focus, so it makes sense to - * do the same for non-grabbing popups. - * - * See https://bugzilla.gnome.org/show_bug.cgi?id=771694#c24 - */ - window->input = FALSE; - } -} - -static void -meta_wayland_xdg_popup_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending) -{ - MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (surface_role); - MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role); - MetaWaylandXdgSurfacePrivate *xdg_surface_priv = - meta_wayland_xdg_surface_get_instance_private (xdg_surface); - MetaWaylandActorSurface *actor_surface = - META_WAYLAND_ACTOR_SURFACE (xdg_popup); - MetaWaylandSurfaceRoleClass *surface_role_class; - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - - if (xdg_popup->setup.parent_surface) - finish_popup_setup (xdg_popup); - - if (!surface->buffer_ref->buffer && xdg_surface_priv->first_buffer_attached) - { - meta_wayland_xdg_surface_reset (xdg_surface); - meta_wayland_actor_surface_queue_frame_callbacks (actor_surface, pending); - return; - } - - surface_role_class = - META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_xdg_popup_parent_class); - surface_role_class->apply_state (surface_role, pending); - - if (xdg_popup->dismissed_by_client && surface->buffer_ref->buffer) - { - wl_resource_post_error (xdg_popup->resource, - XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE, - "Can't commit buffer to dismissed popup"); - return; - } -} - -static void -meta_wayland_xdg_popup_post_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending) -{ - MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (surface_role); - MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWaylandSurfaceRoleClass *surface_role_class = - META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_xdg_popup_parent_class); - MetaWindow *window; - MetaWindow *parent_window; - MetaRectangle buffer_rect; - MetaRectangle parent_buffer_rect; - - window = meta_wayland_surface_get_window (surface); - if (!window) - return; - - if (!surface->buffer_ref->buffer) - return; - - surface_role_class->post_apply_state (surface_role, pending); - - if (pending->has_acked_configure_serial) - { - MetaRectangle window_geometry; - - window_geometry = meta_wayland_xdg_surface_get_window_geometry (xdg_surface); - meta_window_wayland_finish_move_resize (window, window_geometry, pending); - } - - parent_window = meta_wayland_surface_get_window (xdg_popup->parent_surface); - meta_window_get_buffer_rect (window, &buffer_rect); - meta_window_get_buffer_rect (parent_window, &parent_buffer_rect); - if (!meta_rectangle_overlap (&buffer_rect, &parent_buffer_rect) && - !meta_rectangle_is_adjacent_to (&buffer_rect, &parent_buffer_rect)) - { - g_warning ("Buggy client caused popup to be placed outside of " - "parent window"); - dismiss_popup (xdg_popup); - } -} - -static MetaWaylandSurface * -meta_wayland_xdg_popup_get_toplevel (MetaWaylandSurfaceRole *surface_role) -{ - MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (surface_role); - - if (xdg_popup->parent_surface) - return meta_wayland_surface_get_toplevel (xdg_popup->parent_surface); - else - return NULL; -} - -static void -meta_wayland_xdg_popup_reset (MetaWaylandXdgSurface *xdg_surface) -{ - MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (xdg_surface); - MetaWaylandXdgSurfaceClass *xdg_surface_class = - META_WAYLAND_XDG_SURFACE_CLASS (meta_wayland_xdg_popup_parent_class); - - dismiss_popup (xdg_popup); - - xdg_popup->dismissed_by_client = TRUE; - - xdg_surface_class->reset (xdg_surface); -} - -static void -meta_wayland_xdg_popup_configure (MetaWaylandShellSurface *shell_surface, - MetaWaylandWindowConfiguration *configuration) -{ - MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (shell_surface); - MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (xdg_popup); - MetaWindow *parent_window = - meta_wayland_surface_get_window (xdg_popup->parent_surface); - int geometry_scale; - int x, y; - - /* If the parent surface was destroyed, its window will be destroyed - * before the popup receives the parent-destroy signal. This means that - * the popup may potentially get temporary focus until itself is destroyed. - * If this happen, don't try to configure the xdg_popup surface. - * - * FIXME: Could maybe add a signal that is emitted before the window is - * created so that we can avoid incorrect intermediate foci. - */ - if (!parent_window) - return; - - geometry_scale = meta_window_wayland_get_geometry_scale (parent_window); - x = configuration->rel_x / geometry_scale; - y = configuration->rel_y / geometry_scale; - if (xdg_popup->pending_repositioned) - { - xdg_popup_send_repositioned (xdg_popup->resource, - xdg_popup->pending_reposition_token); - xdg_popup->pending_repositioned = FALSE; - } - xdg_popup_send_configure (xdg_popup->resource, - x, y, - configuration->width / configuration->scale, - configuration->height / configuration->scale); - - meta_wayland_xdg_surface_send_configure (xdg_surface, configuration); -} - -static void -meta_wayland_xdg_popup_managed (MetaWaylandShellSurface *shell_surface, - MetaWindow *window) -{ - MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (shell_surface); - MetaWaylandSurface *parent = xdg_popup->parent_surface; - - g_assert (parent); - - meta_window_set_transient_for (window, - meta_wayland_surface_get_window (parent)); - meta_window_set_type (window, META_WINDOW_DROPDOWN_MENU); -} - -static void -meta_wayland_xdg_popup_shell_client_destroyed (MetaWaylandXdgSurface *xdg_surface) -{ - MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (xdg_surface); - struct wl_resource *xdg_wm_base_resource = - meta_wayland_xdg_surface_get_wm_base_resource (xdg_surface); - MetaWaylandXdgSurfaceClass *xdg_surface_class = - META_WAYLAND_XDG_SURFACE_CLASS (meta_wayland_xdg_popup_parent_class); - - xdg_surface_class->shell_client_destroyed (xdg_surface); - - if (xdg_popup->resource) - { - wl_resource_post_error (xdg_wm_base_resource, - XDG_WM_BASE_ERROR_DEFUNCT_SURFACES, - "xdg_wm_base of xdg_popup@%d was destroyed", - wl_resource_get_id (xdg_popup->resource)); - - wl_resource_destroy (xdg_popup->resource); - } -} - -static void -meta_wayland_xdg_popup_done (MetaWaylandPopupSurface *popup_surface) -{ - MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (popup_surface); - - xdg_popup_send_popup_done (xdg_popup->resource); -} - -static void -meta_wayland_xdg_popup_dismiss (MetaWaylandPopupSurface *popup_surface) -{ - MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (popup_surface); - MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (xdg_popup); - struct wl_resource *xdg_wm_base_resource = - meta_wayland_xdg_surface_get_wm_base_resource (xdg_surface); - MetaWaylandSurfaceRole *surface_role = META_WAYLAND_SURFACE_ROLE (xdg_popup); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWaylandSurface *top_popup; - - top_popup = meta_wayland_popup_get_top_popup (xdg_popup->popup); - if (surface != top_popup) - { - wl_resource_post_error (xdg_wm_base_resource, - XDG_WM_BASE_ERROR_NOT_THE_TOPMOST_POPUP, - "destroyed popup not top most popup"); - } - - xdg_popup->popup = NULL; - meta_wayland_xdg_popup_unmap (xdg_popup); -} - -static MetaWaylandSurface * -meta_wayland_xdg_popup_get_surface (MetaWaylandPopupSurface *popup_surface) -{ - MetaWaylandSurfaceRole *surface_role = - META_WAYLAND_SURFACE_ROLE (popup_surface); - - return meta_wayland_surface_role_get_surface (surface_role); -} - -static void -popup_surface_iface_init (MetaWaylandPopupSurfaceInterface *iface) -{ - iface->done = meta_wayland_xdg_popup_done; - iface->dismiss = meta_wayland_xdg_popup_dismiss; - iface->get_surface = meta_wayland_xdg_popup_get_surface; -} - -static void -meta_wayland_xdg_popup_finalize (GObject *object) -{ - MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (object); - - g_clear_pointer (&xdg_popup->resource, wl_resource_destroy); - - G_OBJECT_CLASS (meta_wayland_xdg_popup_parent_class)->finalize (object); -} - -static void -meta_wayland_xdg_popup_init (MetaWaylandXdgPopup *role) -{ -} - -static void -meta_wayland_xdg_popup_class_init (MetaWaylandXdgPopupClass *klass) -{ - GObjectClass *object_class; - MetaWaylandSurfaceRoleClass *surface_role_class; - MetaWaylandShellSurfaceClass *shell_surface_class; - MetaWaylandXdgSurfaceClass *xdg_surface_class; - - object_class = G_OBJECT_CLASS (klass); - object_class->finalize = meta_wayland_xdg_popup_finalize; - - surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass); - surface_role_class->apply_state = meta_wayland_xdg_popup_apply_state; - surface_role_class->post_apply_state = meta_wayland_xdg_popup_post_apply_state; - surface_role_class->get_toplevel = meta_wayland_xdg_popup_get_toplevel; - - shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass); - shell_surface_class->configure = meta_wayland_xdg_popup_configure; - shell_surface_class->managed = meta_wayland_xdg_popup_managed; - - xdg_surface_class = META_WAYLAND_XDG_SURFACE_CLASS (klass); - xdg_surface_class->shell_client_destroyed = - meta_wayland_xdg_popup_shell_client_destroyed; - xdg_surface_class->reset = meta_wayland_xdg_popup_reset; -} - -static struct wl_resource * -meta_wayland_xdg_surface_get_wm_base_resource (MetaWaylandXdgSurface *xdg_surface) -{ - MetaWaylandXdgSurfacePrivate *priv = - meta_wayland_xdg_surface_get_instance_private (xdg_surface); - - return priv->shell_client->resource; -} - -static MetaRectangle -meta_wayland_xdg_surface_get_window_geometry (MetaWaylandXdgSurface *xdg_surface) -{ - MetaWaylandXdgSurfacePrivate *priv = - meta_wayland_xdg_surface_get_instance_private (xdg_surface); - - return priv->geometry; -} - -static gboolean -meta_wayland_xdg_surface_is_assigned (MetaWaylandXdgSurface *xdg_surface) -{ - MetaWaylandXdgSurfacePrivate *priv = - meta_wayland_xdg_surface_get_instance_private (xdg_surface); - - return priv->resource != NULL; -} - -static void -meta_wayland_xdg_surface_send_configure (MetaWaylandXdgSurface *xdg_surface, - MetaWaylandWindowConfiguration *configuration) -{ - MetaWaylandXdgSurfacePrivate *priv = - meta_wayland_xdg_surface_get_instance_private (xdg_surface); - - xdg_surface_send_configure (priv->resource, configuration->serial); - - priv->configure_sent = TRUE; -} - -static void -xdg_surface_destructor (struct wl_resource *resource) -{ - MetaWaylandXdgSurface *xdg_surface = wl_resource_get_user_data (resource); - MetaWaylandXdgSurfacePrivate *priv = - meta_wayland_xdg_surface_get_instance_private (xdg_surface); - - priv->shell_client->surfaces = g_list_remove (priv->shell_client->surfaces, - xdg_surface); - - priv->resource = NULL; - priv->first_buffer_attached = FALSE; -} - -static void -xdg_surface_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -xdg_surface_get_toplevel (struct wl_client *client, - struct wl_resource *resource, - uint32_t id) -{ - MetaWaylandXdgSurface *xdg_surface = wl_resource_get_user_data (resource); - MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource); - struct wl_resource *xdg_wm_base_resource = - meta_wayland_xdg_surface_get_wm_base_resource (xdg_surface); - - wl_resource_post_error (xdg_wm_base_resource, XDG_WM_BASE_ERROR_ROLE, - "wl_surface@%d already has a role assigned", - wl_resource_get_id (surface->resource)); -} - -static void -xdg_surface_get_popup (struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *parent_resource, - struct wl_resource *positioner_resource) -{ - MetaWaylandXdgSurface *xdg_surface = wl_resource_get_user_data (resource); - MetaWaylandXdgSurfacePrivate *priv = - meta_wayland_xdg_surface_get_instance_private (xdg_surface); - MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource); - - wl_resource_post_error (priv->shell_client->resource, - XDG_WM_BASE_ERROR_ROLE, - "wl_surface@%d already has a role assigned", - wl_resource_get_id (surface->resource)); -} - -static void -xdg_surface_set_window_geometry (struct wl_client *client, - struct wl_resource *resource, - int32_t x, - int32_t y, - int32_t width, - int32_t height) -{ - MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource); - MetaWaylandSurfaceState *pending; - - if (width == 0 || height == 0) - { - g_warning ("Invalid geometry %dx%d+%d+%d set on xdg_surface@%d. Ignoring for " - "now, but this will result in client termination in the future.", - width, height, x, y, - wl_resource_get_id (resource)); - return; - } - - pending = meta_wayland_surface_get_pending_state (surface); - pending->has_new_geometry = TRUE; - pending->new_geometry.x = x; - pending->new_geometry.y = y; - pending->new_geometry.width = width; - pending->new_geometry.height = height; -} - -static void -xdg_surface_ack_configure (struct wl_client *client, - struct wl_resource *resource, - uint32_t serial) -{ - MetaWaylandSurface *surface = surface_from_xdg_surface_resource (resource); - MetaWaylandSurfaceState *pending; - - pending = meta_wayland_surface_get_pending_state (surface); - pending->has_acked_configure_serial = TRUE; - pending->acked_configure_serial = serial; -} - -static const struct xdg_surface_interface meta_wayland_xdg_surface_interface = { - xdg_surface_destroy, - xdg_surface_get_toplevel, - xdg_surface_get_popup, - xdg_surface_set_window_geometry, - xdg_surface_ack_configure, -}; - -static void -meta_wayland_xdg_surface_finalize (GObject *object) -{ - MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (object); - MetaWaylandXdgSurfacePrivate *priv = - meta_wayland_xdg_surface_get_instance_private (xdg_surface); - - g_clear_pointer (&priv->resource, wl_resource_destroy); - - G_OBJECT_CLASS (meta_wayland_xdg_surface_parent_class)->finalize (object); -} - -static void -meta_wayland_xdg_surface_real_reset (MetaWaylandXdgSurface *xdg_surface) -{ - MetaWaylandXdgSurfacePrivate *priv = - meta_wayland_xdg_surface_get_instance_private (xdg_surface); - - priv->first_buffer_attached = FALSE; - priv->configure_sent = FALSE; - priv->geometry = (MetaRectangle) { 0 }; - priv->has_set_geometry = FALSE; -} - -static void -meta_wayland_xdg_surface_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending) -{ - MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role); - MetaWaylandXdgSurfacePrivate *priv = - meta_wayland_xdg_surface_get_instance_private (xdg_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWindow *window = meta_wayland_surface_get_window (surface); - MetaWaylandSurfaceRoleClass *surface_role_class; - - surface_role_class = - META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_xdg_surface_parent_class); - surface_role_class->apply_state (surface_role, pending); - - /* Ignore commits when unassigned. */ - if (!priv->resource) - return; - - if (!window) - return; - - if (surface->buffer_ref->buffer) - priv->first_buffer_attached = TRUE; -} - -static void -meta_wayland_xdg_surface_post_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending) -{ - MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role); - MetaWaylandXdgSurfacePrivate *priv = - meta_wayland_xdg_surface_get_instance_private (xdg_surface); - MetaWaylandShellSurface *shell_surface = - META_WAYLAND_SHELL_SURFACE (surface_role); - - if (pending->has_new_geometry) - { - meta_wayland_shell_surface_determine_geometry (shell_surface, - &pending->new_geometry, - &priv->geometry); - if (priv->geometry.width == 0 || priv->geometry.height == 0) - { - g_warning ("Invalid window geometry for xdg_surface@%d. Ignoring " - "for now, but this will result in client termination " - "in the future.", - wl_resource_get_id (priv->resource)); - return; - } - - priv->has_set_geometry = TRUE; - } - else if (!priv->has_set_geometry) - { - MetaRectangle new_geometry = { 0 }; - - /* If the surface has never set any geometry, calculate - * a default one unioning the surface and all subsurfaces together. */ - - meta_wayland_shell_surface_calculate_geometry (shell_surface, - &new_geometry); - if (!meta_rectangle_equal (&new_geometry, &priv->geometry)) - { - pending->has_new_geometry = TRUE; - priv->geometry = new_geometry; - } - } -} - -static void -meta_wayland_xdg_surface_assigned (MetaWaylandSurfaceRole *surface_role) -{ - MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role); - MetaWaylandXdgSurfacePrivate *priv = - meta_wayland_xdg_surface_get_instance_private (xdg_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - struct wl_resource *xdg_wm_base_resource = - meta_wayland_xdg_surface_get_wm_base_resource (xdg_surface); - MetaWaylandSurfaceRoleClass *surface_role_class; - - priv->configure_sent = FALSE; - priv->first_buffer_attached = FALSE; - - if (surface->buffer_ref->buffer) - { - wl_resource_post_error (xdg_wm_base_resource, - XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE, - "wl_surface@%d already has a buffer committed", - wl_resource_get_id (surface->resource)); - return; - } - - surface_role_class = - META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_xdg_surface_parent_class); - surface_role_class->assigned (surface_role); -} - -static void -meta_wayland_xdg_surface_ping (MetaWaylandShellSurface *shell_surface, - uint32_t serial) -{ - MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (shell_surface); - MetaWaylandXdgSurfacePrivate *priv = - meta_wayland_xdg_surface_get_instance_private (xdg_surface); - - xdg_wm_base_send_ping (priv->shell_client->resource, serial); -} - -static void -meta_wayland_xdg_surface_real_shell_client_destroyed (MetaWaylandXdgSurface *xdg_surface) -{ - MetaWaylandXdgSurfacePrivate *priv = - meta_wayland_xdg_surface_get_instance_private (xdg_surface); - - if (priv->resource) - { - wl_resource_post_error (priv->shell_client->resource, - XDG_WM_BASE_ERROR_DEFUNCT_SURFACES, - "xdg_wm_base of xdg_surface@%d was destroyed", - wl_resource_get_id (priv->resource)); - - wl_resource_destroy (priv->resource); - } -} - -static void -meta_wayland_xdg_surface_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (object); - MetaWaylandXdgSurfacePrivate *priv = - meta_wayland_xdg_surface_get_instance_private (xdg_surface); - - switch (prop_id) - { - case XDG_SURFACE_PROP_SHELL_CLIENT: - priv->shell_client = g_value_get_pointer (value); - break; - - case XDG_SURFACE_PROP_RESOURCE: - priv->resource = g_value_get_pointer (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_wayland_xdg_surface_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (object); - MetaWaylandXdgSurfacePrivate *priv = - meta_wayland_xdg_surface_get_instance_private (xdg_surface); - - switch (prop_id) - { - case XDG_SURFACE_PROP_SHELL_CLIENT: - g_value_set_pointer (value, priv->shell_client); - break; - - case XDG_SURFACE_PROP_RESOURCE: - g_value_set_pointer (value, priv->resource); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_wayland_xdg_surface_init (MetaWaylandXdgSurface *xdg_surface) -{ -} - -static void -meta_wayland_xdg_surface_class_init (MetaWaylandXdgSurfaceClass *klass) -{ - GObjectClass *object_class; - MetaWaylandSurfaceRoleClass *surface_role_class; - MetaWaylandShellSurfaceClass *shell_surface_class; - GParamSpec *pspec; - - object_class = G_OBJECT_CLASS (klass); - object_class->finalize = meta_wayland_xdg_surface_finalize; - object_class->set_property = meta_wayland_xdg_surface_set_property; - object_class->get_property = meta_wayland_xdg_surface_get_property; - - surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass); - surface_role_class->apply_state = meta_wayland_xdg_surface_apply_state; - surface_role_class->post_apply_state = meta_wayland_xdg_surface_post_apply_state; - surface_role_class->assigned = meta_wayland_xdg_surface_assigned; - - shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass); - shell_surface_class->ping = meta_wayland_xdg_surface_ping; - - klass->shell_client_destroyed = - meta_wayland_xdg_surface_real_shell_client_destroyed; - klass->reset = meta_wayland_xdg_surface_real_reset; - - pspec = g_param_spec_pointer ("shell-client", - "MetaWaylandXdgShellClient", - "The shell client instance", - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, - XDG_SURFACE_PROP_SHELL_CLIENT, - pspec); - pspec = g_param_spec_pointer ("xdg-surface-resource", - "xdg_surface wl_resource", - "The xdg_surface wl_resource instance", - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, - XDG_SURFACE_PROP_RESOURCE, - pspec); -} - -static void -meta_wayland_xdg_surface_shell_client_destroyed (MetaWaylandXdgSurface *xdg_surface) -{ - MetaWaylandXdgSurfaceClass *xdg_surface_class = - META_WAYLAND_XDG_SURFACE_GET_CLASS (xdg_surface); - - xdg_surface_class->shell_client_destroyed (xdg_surface); -} - -static void -meta_wayland_xdg_surface_constructor_finalize (MetaWaylandXdgSurfaceConstructor *constructor, - MetaWaylandXdgSurface *xdg_surface) -{ - MetaWaylandXdgShellClient *shell_client = constructor->shell_client; - - shell_client->surface_constructors = - g_list_remove (shell_client->surface_constructors, constructor); - shell_client->surfaces = g_list_append (shell_client->surfaces, xdg_surface); - - wl_resource_set_implementation (constructor->resource, - &meta_wayland_xdg_surface_interface, - xdg_surface, - xdg_surface_destructor); - - g_free (constructor); -} - -static void -xdg_surface_constructor_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_post_error (resource, - XDG_SURFACE_ERROR_NOT_CONSTRUCTED, - "xdg_surface destroyed before constructed"); - wl_resource_destroy (resource); -} - -static void -xdg_surface_constructor_get_toplevel (struct wl_client *client, - struct wl_resource *resource, - uint32_t id) -{ - MetaWaylandXdgSurfaceConstructor *constructor = - wl_resource_get_user_data (resource); - MetaWaylandXdgShellClient *shell_client = constructor->shell_client; - struct wl_resource *xdg_surface_resource = constructor->resource; - MetaWaylandSurface *surface = constructor->surface; - MetaWaylandXdgToplevel *xdg_toplevel; - MetaWaylandXdgSurface *xdg_surface; - MetaWaylandShellSurface *shell_surface; - MetaWindow *window; - - if (!meta_wayland_surface_assign_role (surface, - META_TYPE_WAYLAND_XDG_TOPLEVEL, - "shell-client", shell_client, - "xdg-surface-resource", xdg_surface_resource, - NULL)) - { - wl_resource_post_error (resource, XDG_WM_BASE_ERROR_ROLE, - "wl_surface@%d already has a different role", - wl_resource_get_id (surface->resource)); - return; - } - - xdg_toplevel = META_WAYLAND_XDG_TOPLEVEL (surface->role); - xdg_toplevel->resource = wl_resource_create (client, - &xdg_toplevel_interface, - wl_resource_get_version (resource), - id); - wl_resource_set_implementation (xdg_toplevel->resource, - &meta_wayland_xdg_toplevel_interface, - xdg_toplevel, - xdg_toplevel_destructor); - - xdg_surface = META_WAYLAND_XDG_SURFACE (xdg_toplevel); - meta_wayland_xdg_surface_constructor_finalize (constructor, xdg_surface); - - window = meta_window_wayland_new (meta_get_display (), surface); - shell_surface = META_WAYLAND_SHELL_SURFACE (xdg_surface); - meta_wayland_shell_surface_set_window (shell_surface, window); -} - -static void -xdg_surface_constructor_get_popup (struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *parent_resource, - struct wl_resource *positioner_resource) -{ - MetaWaylandXdgSurfaceConstructor *constructor = - wl_resource_get_user_data (resource); - MetaWaylandXdgShellClient *shell_client = constructor->shell_client; - MetaWaylandSurface *surface = constructor->surface; - struct wl_resource *xdg_wm_base_resource = constructor->shell_client->resource; - struct wl_resource *xdg_surface_resource = constructor->resource; - MetaWaylandSurface *parent_surface; - MetaWindow *parent_window; - MetaWaylandXdgPositioner *xdg_positioner; - MetaWaylandXdgPopup *xdg_popup; - MetaWaylandXdgSurface *xdg_surface; - - if (!parent_resource) - { - wl_resource_post_error (xdg_wm_base_resource, - XDG_WM_BASE_ERROR_INVALID_POPUP_PARENT, - "Parent surface is null but Mutter does not yet " - "support specifying parent surfaces via other " - "protocols"); - return; - } - - parent_surface = surface_from_xdg_surface_resource (parent_resource); - if (!parent_surface || !META_IS_WAYLAND_XDG_SURFACE (parent_surface->role)) - { - wl_resource_post_error (xdg_wm_base_resource, - XDG_WM_BASE_ERROR_INVALID_POPUP_PARENT, - "Invalid popup parent role"); - return; - } - - parent_window = meta_wayland_surface_get_window (parent_surface); - if (!parent_window) - { - wl_resource_post_error (xdg_wm_base_resource, - XDG_WM_BASE_ERROR_INVALID_POPUP_PARENT, - "Invalid popup parent window"); - return; - } - - if (!meta_wayland_surface_assign_role (surface, - META_TYPE_WAYLAND_XDG_POPUP, - "shell-client", shell_client, - "xdg-surface-resource", xdg_surface_resource, - NULL)) - { - wl_resource_post_error (xdg_wm_base_resource, XDG_WM_BASE_ERROR_ROLE, - "wl_surface@%d already has a different role", - wl_resource_get_id (surface->resource)); - return; - } - - xdg_popup = META_WAYLAND_XDG_POPUP (surface->role); - - xdg_popup->resource = wl_resource_create (client, - &xdg_popup_interface, - wl_resource_get_version (resource), - id); - wl_resource_set_implementation (xdg_popup->resource, - &meta_wayland_xdg_popup_interface, - xdg_popup, - xdg_popup_destructor); - - xdg_surface = META_WAYLAND_XDG_SURFACE (xdg_popup); - meta_wayland_xdg_surface_constructor_finalize (constructor, xdg_surface); - - xdg_positioner = wl_resource_get_user_data (positioner_resource); - xdg_popup->setup.placement_rule = - meta_wayland_xdg_positioner_to_placement (xdg_positioner, parent_window); - xdg_popup->setup.parent_surface = parent_surface; -} - -static void -xdg_surface_constructor_set_window_geometry (struct wl_client *client, - struct wl_resource *resource, - int32_t x, - int32_t y, - int32_t width, - int32_t height) -{ - wl_resource_post_error (resource, - XDG_SURFACE_ERROR_NOT_CONSTRUCTED, - "xdg_surface::set_window_geometry called before constructed"); -} - -static void -xdg_surface_constructor_ack_configure (struct wl_client *client, - struct wl_resource *resource, - uint32_t serial) -{ - wl_resource_post_error (resource, - XDG_SURFACE_ERROR_NOT_CONSTRUCTED, - "xdg_surface::ack_configure called before constructed"); -} - -static const struct xdg_surface_interface meta_wayland_xdg_surface_constructor_interface = { - xdg_surface_constructor_destroy, - xdg_surface_constructor_get_toplevel, - xdg_surface_constructor_get_popup, - xdg_surface_constructor_set_window_geometry, - xdg_surface_constructor_ack_configure, -}; - -static void -xdg_surface_constructor_destructor (struct wl_resource *resource) -{ - MetaWaylandXdgSurfaceConstructor *constructor = - wl_resource_get_user_data (resource); - - constructor->shell_client->surface_constructors = - g_list_remove (constructor->shell_client->surface_constructors, - constructor); - - g_free (constructor); -} - -static MetaPlacementAnchor -positioner_anchor_to_placement_anchor (uint32_t anchor) -{ - switch (anchor) - { - case XDG_POSITIONER_ANCHOR_NONE: - return META_PLACEMENT_ANCHOR_NONE; - case XDG_POSITIONER_ANCHOR_TOP: - return META_PLACEMENT_ANCHOR_TOP; - case XDG_POSITIONER_ANCHOR_BOTTOM: - return META_PLACEMENT_ANCHOR_BOTTOM; - case XDG_POSITIONER_ANCHOR_LEFT: - return META_PLACEMENT_ANCHOR_LEFT; - case XDG_POSITIONER_ANCHOR_RIGHT: - return META_PLACEMENT_ANCHOR_RIGHT; - case XDG_POSITIONER_ANCHOR_TOP_LEFT: - return (META_PLACEMENT_ANCHOR_TOP | META_PLACEMENT_ANCHOR_LEFT); - case XDG_POSITIONER_ANCHOR_BOTTOM_LEFT: - return (META_PLACEMENT_ANCHOR_BOTTOM | META_PLACEMENT_ANCHOR_LEFT); - case XDG_POSITIONER_ANCHOR_TOP_RIGHT: - return (META_PLACEMENT_ANCHOR_TOP | META_PLACEMENT_ANCHOR_RIGHT); - case XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT: - return (META_PLACEMENT_ANCHOR_BOTTOM | META_PLACEMENT_ANCHOR_RIGHT); - default: - g_assert_not_reached (); - return META_PLACEMENT_ANCHOR_NONE; - } -} - -static MetaPlacementGravity -positioner_gravity_to_placement_gravity (uint32_t gravity) -{ - switch (gravity) - { - case XDG_POSITIONER_GRAVITY_NONE: - return META_PLACEMENT_GRAVITY_NONE; - case XDG_POSITIONER_GRAVITY_TOP: - return META_PLACEMENT_GRAVITY_TOP; - case XDG_POSITIONER_GRAVITY_BOTTOM: - return META_PLACEMENT_GRAVITY_BOTTOM; - case XDG_POSITIONER_GRAVITY_LEFT: - return META_PLACEMENT_GRAVITY_LEFT; - case XDG_POSITIONER_GRAVITY_RIGHT: - return META_PLACEMENT_GRAVITY_RIGHT; - case XDG_POSITIONER_GRAVITY_TOP_LEFT: - return (META_PLACEMENT_GRAVITY_TOP | META_PLACEMENT_GRAVITY_LEFT); - case XDG_POSITIONER_GRAVITY_BOTTOM_LEFT: - return (META_PLACEMENT_GRAVITY_BOTTOM | META_PLACEMENT_GRAVITY_LEFT); - case XDG_POSITIONER_GRAVITY_TOP_RIGHT: - return (META_PLACEMENT_GRAVITY_TOP | META_PLACEMENT_GRAVITY_RIGHT); - case XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT: - return (META_PLACEMENT_GRAVITY_BOTTOM | META_PLACEMENT_GRAVITY_RIGHT); - default: - g_assert_not_reached (); - return META_PLACEMENT_GRAVITY_NONE; - } -} - -static MetaPlacementRule -meta_wayland_xdg_positioner_to_placement (MetaWaylandXdgPositioner *xdg_positioner, - MetaWindow *parent_window) -{ - MetaRectangle parent_rect; - - meta_window_get_frame_rect (parent_window, &parent_rect); - - if (xdg_positioner->acked_parent_configure) - { - MetaWindowWayland *parent_wl_window = META_WINDOW_WAYLAND (parent_window); - uint32_t serial; - MetaWaylandWindowConfiguration *configuration; - - serial = xdg_positioner->parent_configure_serial; - configuration = meta_window_wayland_peek_configuration (parent_wl_window, - serial); - - if (configuration) - { - if (configuration->flags & META_MOVE_RESIZE_STATE_CHANGED) - { - if (configuration->has_position) - { - parent_rect.x = configuration->x; - parent_rect.y = configuration->y; - } - if (configuration->has_size) - { - parent_rect.width = - configuration->width / configuration->scale; - parent_rect.height = - configuration->height / configuration->scale; - } - } - else if (xdg_positioner->has_parent_size) - { - meta_rectangle_resize_with_gravity (&parent_rect, - &parent_rect, - configuration->gravity, - xdg_positioner->parent_width, - xdg_positioner->parent_height); - } - } - } - else if (xdg_positioner->has_parent_size) - { - meta_rectangle_resize_with_gravity (&parent_rect, - &parent_rect, - META_GRAVITY_SOUTH_EAST, - xdg_positioner->parent_width, - xdg_positioner->parent_height); - } - - return (MetaPlacementRule) { - .anchor_rect = xdg_positioner->anchor_rect, - .gravity = positioner_gravity_to_placement_gravity (xdg_positioner->gravity), - .anchor = positioner_anchor_to_placement_anchor (xdg_positioner->anchor), - .constraint_adjustment = xdg_positioner->constraint_adjustment, - .offset_x = xdg_positioner->offset_x, - .offset_y = xdg_positioner->offset_y, - .width = xdg_positioner->width, - .height = xdg_positioner->height, - - .is_reactive = xdg_positioner->is_reactive, - - .parent_rect = parent_rect, - }; -} - -static void -xdg_positioner_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static void -xdg_positioner_set_size (struct wl_client *client, - struct wl_resource *resource, - int32_t width, - int32_t height) -{ - MetaWaylandXdgPositioner *positioner = wl_resource_get_user_data (resource); - - if (width <= 0 || height <= 0) - { - wl_resource_post_error (resource, XDG_POSITIONER_ERROR_INVALID_INPUT, - "Invalid size"); - return; - } - - positioner->width = width; - positioner->height = height; -} - -static void -xdg_positioner_set_anchor_rect (struct wl_client *client, - struct wl_resource *resource, - int32_t x, - int32_t y, - int32_t width, - int32_t height) -{ - MetaWaylandXdgPositioner *positioner = wl_resource_get_user_data (resource); - - if (width <= 0 || height <= 0) - { - wl_resource_post_error (resource, XDG_POSITIONER_ERROR_INVALID_INPUT, - "Invalid anchor rectangle size"); - return; - } - - positioner->anchor_rect = (MetaRectangle) { - .x = x, - .y = y, - .width = width, - .height = height, - }; -} - -static void -xdg_positioner_set_anchor (struct wl_client *client, - struct wl_resource *resource, - uint32_t anchor) -{ - MetaWaylandXdgPositioner *positioner = wl_resource_get_user_data (resource); - - if (anchor > XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT) - { - wl_resource_post_error (resource, XDG_POSITIONER_ERROR_INVALID_INPUT, - "Invalid anchor"); - return; - } - - positioner->anchor = anchor; -} - -static void -xdg_positioner_set_gravity (struct wl_client *client, - struct wl_resource *resource, - uint32_t gravity) -{ - MetaWaylandXdgPositioner *positioner = wl_resource_get_user_data (resource); - - if (gravity > XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT) - { - wl_resource_post_error (resource, XDG_POSITIONER_ERROR_INVALID_INPUT, - "Invalid gravity"); - return; - } - - positioner->gravity = gravity; -} - -static void -xdg_positioner_set_constraint_adjustment (struct wl_client *client, - struct wl_resource *resource, - uint32_t constraint_adjustment) -{ - MetaWaylandXdgPositioner *positioner = wl_resource_get_user_data (resource); - uint32_t all_adjustments = (XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X | - XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X | - XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y | - XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y | - XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X | - XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y); - - if ((constraint_adjustment & ~all_adjustments) != 0) - { - wl_resource_post_error (resource, XDG_POSITIONER_ERROR_INVALID_INPUT, - "Invalid constraint action"); - return; - } - - positioner->constraint_adjustment = constraint_adjustment; -} - -static void -xdg_positioner_set_offset (struct wl_client *client, - struct wl_resource *resource, - int32_t x, - int32_t y) -{ - MetaWaylandXdgPositioner *positioner = wl_resource_get_user_data (resource); - - positioner->offset_x = x; - positioner->offset_y = y; -} - -static void -xdg_positioner_set_reactive (struct wl_client *client, - struct wl_resource *resource) -{ - MetaWaylandXdgPositioner *positioner = wl_resource_get_user_data (resource); - - positioner->is_reactive = TRUE; -} - -static void -xdg_positioner_set_parent_size (struct wl_client *client, - struct wl_resource *resource, - int32_t parent_width, - int32_t parent_height) -{ - MetaWaylandXdgPositioner *positioner = wl_resource_get_user_data (resource); - - positioner->has_parent_size = TRUE; - positioner->parent_width = parent_width; - positioner->parent_height = parent_height; -} - -static void -xdg_positioner_set_parent_configure (struct wl_client *client, - struct wl_resource *resource, - uint32_t serial) -{ - MetaWaylandXdgPositioner *positioner = wl_resource_get_user_data (resource); - - positioner->acked_parent_configure = TRUE; - positioner->parent_configure_serial = serial; -} - -static const struct xdg_positioner_interface meta_wayland_xdg_positioner_interface = { - xdg_positioner_destroy, - xdg_positioner_set_size, - xdg_positioner_set_anchor_rect, - xdg_positioner_set_anchor, - xdg_positioner_set_gravity, - xdg_positioner_set_constraint_adjustment, - xdg_positioner_set_offset, - xdg_positioner_set_reactive, - xdg_positioner_set_parent_size, - xdg_positioner_set_parent_configure, -}; - -static void -xdg_positioner_destructor (struct wl_resource *resource) -{ - MetaWaylandXdgPositioner *positioner = wl_resource_get_user_data (resource); - - g_free (positioner); -} - -static void -xdg_wm_base_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - MetaWaylandXdgShellClient *shell_client = wl_resource_get_user_data (resource); - - if (shell_client->surfaces || shell_client->surface_constructors) - wl_resource_post_error (resource, XDG_WM_BASE_ERROR_DEFUNCT_SURFACES, - "xdg_wm_base destroyed before its surfaces"); - - wl_resource_destroy (resource); -} - -static void -xdg_wm_base_create_positioner (struct wl_client *client, - struct wl_resource *resource, - uint32_t id) -{ - MetaWaylandXdgPositioner *positioner; - struct wl_resource *positioner_resource; - - positioner = g_new0 (MetaWaylandXdgPositioner, 1); - positioner_resource = wl_resource_create (client, - &xdg_positioner_interface, - wl_resource_get_version (resource), - id); - wl_resource_set_implementation (positioner_resource, - &meta_wayland_xdg_positioner_interface, - positioner, - xdg_positioner_destructor); -} - -static void -xdg_wm_base_get_xdg_surface (struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *surface_resource) -{ - MetaWaylandXdgShellClient *shell_client = wl_resource_get_user_data (resource); - MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); - MetaWaylandXdgSurfaceConstructor *constructor; - - if (surface->role && !META_IS_WAYLAND_XDG_SURFACE (surface->role)) - { - wl_resource_post_error (resource, XDG_WM_BASE_ERROR_ROLE, - "wl_surface@%d already has a different role", - wl_resource_get_id (surface->resource)); - return; - } - - if (surface->role && META_IS_WAYLAND_XDG_SURFACE (surface->role) && - meta_wayland_xdg_surface_is_assigned (META_WAYLAND_XDG_SURFACE (surface->role))) - { - wl_resource_post_error (surface_resource, - XDG_WM_BASE_ERROR_ROLE, - "xdg_wm_base::get_xdg_surface already requested"); - return; - } - - if (surface->buffer_ref->buffer) - { - wl_resource_post_error (resource, - XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE, - "wl_surface@%d already has a buffer committed", - wl_resource_get_id (surface->resource)); - return; - } - - constructor = g_new0 (MetaWaylandXdgSurfaceConstructor, 1); - constructor->surface = surface; - constructor->shell_client = shell_client; - constructor->resource = wl_resource_create (client, - &xdg_surface_interface, - wl_resource_get_version (resource), - id); - wl_resource_set_implementation (constructor->resource, - &meta_wayland_xdg_surface_constructor_interface, - constructor, - xdg_surface_constructor_destructor); - - shell_client->surface_constructors = - g_list_append (shell_client->surface_constructors, constructor); -} - -static void -xdg_wm_base_pong (struct wl_client *client, - struct wl_resource *resource, - uint32_t serial) -{ - MetaDisplay *display = meta_get_display (); - - meta_display_pong_for_serial (display, serial); -} - -static const struct xdg_wm_base_interface meta_wayland_xdg_wm_base_interface = { - xdg_wm_base_destroy, - xdg_wm_base_create_positioner, - xdg_wm_base_get_xdg_surface, - xdg_wm_base_pong, -}; - -static void -meta_wayland_xdg_shell_client_destroy (MetaWaylandXdgShellClient *shell_client) -{ - while (shell_client->surface_constructors) - { - MetaWaylandXdgSurfaceConstructor *constructor = - g_list_first (shell_client->surface_constructors)->data; - - wl_resource_destroy (constructor->resource); - } - g_list_free (shell_client->surface_constructors); - - while (shell_client->surfaces) - { - MetaWaylandXdgSurface *xdg_surface = - g_list_first (shell_client->surfaces)->data; - - meta_wayland_xdg_surface_shell_client_destroyed (xdg_surface); - } - g_list_free (shell_client->surfaces); - - g_free (shell_client); -} - -static void -xdg_wm_base_destructor (struct wl_resource *resource) -{ - MetaWaylandXdgShellClient *shell_client = - wl_resource_get_user_data (resource); - - meta_wayland_xdg_shell_client_destroy (shell_client); -} - -static void -bind_xdg_wm_base (struct wl_client *client, - void *data, - uint32_t version, - uint32_t id) -{ - MetaWaylandXdgShellClient *shell_client; - - shell_client = g_new0 (MetaWaylandXdgShellClient, 1); - - shell_client->resource = wl_resource_create (client, - &xdg_wm_base_interface, - version, id); - wl_resource_set_implementation (shell_client->resource, - &meta_wayland_xdg_wm_base_interface, - shell_client, xdg_wm_base_destructor); -} - -void -meta_wayland_xdg_shell_init (MetaWaylandCompositor *compositor) -{ - if (wl_global_create (compositor->wayland_display, - &xdg_wm_base_interface, - META_XDG_WM_BASE_VERSION, - compositor, bind_xdg_wm_base) == NULL) - g_error ("Failed to register a global xdg-shell object"); -} diff --git a/src/wayland/meta-wayland-xdg-shell.h b/src/wayland/meta-wayland-xdg-shell.h deleted file mode 100644 index f90e29bea..000000000 --- a/src/wayland/meta-wayland-xdg-shell.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2013-2015 Red Hat, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#ifndef META_WAYLAND_XDG_SHELL_H -#define META_WAYLAND_XDG_SHELL_H - -#include "wayland/meta-wayland-shell-surface.h" - -#define META_TYPE_WAYLAND_XDG_SURFACE (meta_wayland_xdg_surface_get_type ()) -G_DECLARE_DERIVABLE_TYPE (MetaWaylandXdgSurface, - meta_wayland_xdg_surface, - META, WAYLAND_XDG_SURFACE, - MetaWaylandShellSurface) - -struct _MetaWaylandXdgSurfaceClass -{ - MetaWaylandShellSurfaceClass parent_class; - - void (*shell_client_destroyed) (MetaWaylandXdgSurface *xdg_surface); - void (*reset) (MetaWaylandXdgSurface *xdg_surface); -}; - -#define META_TYPE_WAYLAND_XDG_TOPLEVEL (meta_wayland_xdg_toplevel_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandXdgToplevel, - meta_wayland_xdg_toplevel, - META, WAYLAND_XDG_TOPLEVEL, - MetaWaylandXdgSurface); - -#define META_TYPE_WAYLAND_XDG_POPUP (meta_wayland_xdg_popup_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandXdgPopup, - meta_wayland_xdg_popup, - META, WAYLAND_XDG_POPUP, - MetaWaylandXdgSurface); - -void meta_wayland_xdg_shell_init (MetaWaylandCompositor *compositor); - -#endif /* META_WAYLAND_XDG_SHELL_H */ diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c deleted file mode 100644 index e2832bbc4..000000000 --- a/src/wayland/meta-wayland.c +++ /dev/null @@ -1,741 +0,0 @@ -/* - * Wayland Support - * - * Copyright (C) 2012,2013 Intel Corporation - * - * 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 "wayland/meta-wayland.h" - -#include -#include -#include -#include - -#include "clutter/clutter.h" -#include "cogl/cogl-egl.h" -#include "compositor/meta-surface-actor-wayland.h" -#include "core/meta-context-private.h" -#include "wayland/meta-wayland-activation.h" -#include "wayland/meta-wayland-buffer.h" -#include "wayland/meta-wayland-data-device.h" -#include "wayland/meta-wayland-dma-buf.h" -#include "wayland/meta-wayland-egl-stream.h" -#include "wayland/meta-wayland-inhibit-shortcuts-dialog.h" -#include "wayland/meta-wayland-inhibit-shortcuts.h" -#include "wayland/meta-wayland-outputs.h" -#include "wayland/meta-wayland-presentation-time-private.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-region.h" -#include "wayland/meta-wayland-seat.h" -#include "wayland/meta-wayland-subsurface.h" -#include "wayland/meta-wayland-tablet-manager.h" -#include "wayland/meta-wayland-xdg-foreign.h" -#include "wayland/meta-xwayland-grab-keyboard.h" -#include "wayland/meta-xwayland-private.h" -#include "wayland/meta-xwayland.h" - -static char *_display_name_override; - -G_DEFINE_TYPE (MetaWaylandCompositor, meta_wayland_compositor, G_TYPE_OBJECT) - -MetaWaylandCompositor * -meta_wayland_compositor_get_default (void) -{ - MetaBackend *backend; - MetaContext *context; - MetaWaylandCompositor *wayland_compositor; - - backend = meta_get_backend (); - context = meta_backend_get_context (backend); - wayland_compositor = meta_context_get_wayland_compositor (context); - g_assert (wayland_compositor); - - return wayland_compositor; -} - -typedef struct -{ - GSource source; - struct wl_display *display; -} WaylandEventSource; - -static gboolean -wayland_event_source_prepare (GSource *base, - int *timeout) -{ - WaylandEventSource *source = (WaylandEventSource *)base; - - *timeout = -1; - - wl_display_flush_clients (source->display); - - return FALSE; -} - -static gboolean -wayland_event_source_dispatch (GSource *base, - GSourceFunc callback, - void *data) -{ - WaylandEventSource *source = (WaylandEventSource *)base; - struct wl_event_loop *loop = wl_display_get_event_loop (source->display); - - wl_event_loop_dispatch (loop, 0); - - return TRUE; -} - -static GSourceFuncs wayland_event_source_funcs = -{ - wayland_event_source_prepare, - NULL, - wayland_event_source_dispatch, - NULL -}; - -static GSource * -wayland_event_source_new (struct wl_display *display) -{ - WaylandEventSource *source; - struct wl_event_loop *loop = wl_display_get_event_loop (display); - - source = (WaylandEventSource *) g_source_new (&wayland_event_source_funcs, - sizeof (WaylandEventSource)); - source->display = display; - g_source_add_unix_fd (&source->source, - wl_event_loop_get_fd (loop), - G_IO_IN | G_IO_ERR); - - return &source->source; -} - -void -meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor, - MetaWindow *window) -{ - MetaWaylandSurface *surface = window ? window->surface : NULL; - - meta_wayland_seat_set_input_focus (compositor->seat, surface); -} - -static void -wl_compositor_create_surface (struct wl_client *client, - struct wl_resource *resource, - uint32_t id) -{ - MetaWaylandCompositor *compositor = wl_resource_get_user_data (resource); - - meta_wayland_surface_create (compositor, client, resource, id); -} - -static void -wl_compositor_create_region (struct wl_client *client, - struct wl_resource *resource, - uint32_t id) -{ - MetaWaylandCompositor *compositor = wl_resource_get_user_data (resource); - - meta_wayland_region_create (compositor, client, resource, id); -} - -static const struct wl_compositor_interface meta_wayland_wl_compositor_interface = { - wl_compositor_create_surface, - wl_compositor_create_region -}; - -static void -compositor_bind (struct wl_client *client, - void *data, - uint32_t version, - uint32_t id) -{ - MetaWaylandCompositor *compositor = data; - struct wl_resource *resource; - - resource = wl_resource_create (client, &wl_compositor_interface, version, id); - wl_resource_set_implementation (resource, - &meta_wayland_wl_compositor_interface, - compositor, NULL); -} - -/** - * meta_wayland_compositor_update: - * @compositor: the #MetaWaylandCompositor instance - * @event: the #ClutterEvent used to update @seat's state - * - * This is used to update display server state like updating cursor - * position and keeping track of buttons and keys pressed. It must be - * called for all input events coming from the underlying devices. - */ -void -meta_wayland_compositor_update (MetaWaylandCompositor *compositor, - const ClutterEvent *event) -{ - if (meta_wayland_tablet_manager_consumes_event (compositor->tablet_manager, event)) - meta_wayland_tablet_manager_update (compositor->tablet_manager, event); - else - meta_wayland_seat_update (compositor->seat, event); -} - -static void -on_after_update (ClutterStage *stage, - ClutterStageView *stage_view, - MetaWaylandCompositor *compositor) -{ - GList *l; - int64_t now_us; - - now_us = g_get_monotonic_time (); - - l = compositor->frame_callback_surfaces; - while (l) - { - GList *l_cur = l; - MetaWaylandSurface *surface = l->data; - MetaSurfaceActor *actor; - MetaWaylandActorSurface *actor_surface; - ClutterStageView *surface_primary_view; - - l = l->next; - - actor = meta_wayland_surface_get_actor (surface); - if (!actor) - continue; - - surface_primary_view = - meta_surface_actor_wayland_get_current_primary_view (actor, stage); - if (stage_view != surface_primary_view) - continue; - - actor_surface = META_WAYLAND_ACTOR_SURFACE (surface->role); - meta_wayland_actor_surface_emit_frame_callbacks (actor_surface, - now_us / 1000); - - compositor->frame_callback_surfaces = - g_list_delete_link (compositor->frame_callback_surfaces, l_cur); - } -} - -static MetaWaylandOutput * -get_output_for_stage_view (MetaWaylandCompositor *compositor, - ClutterStageView *stage_view) -{ - MetaCrtc *crtc; - MetaOutput *output; - MetaMonitor *monitor; - MetaLogicalMonitor *logical_monitor; - - crtc = meta_renderer_view_get_crtc (META_RENDERER_VIEW (stage_view)); - - /* - * All outputs occupy the same region of the screen, as their contents are - * the same, so pick the first one. - */ - output = meta_crtc_get_outputs (crtc)->data; - - monitor = meta_output_get_monitor (output); - logical_monitor = meta_monitor_get_logical_monitor (monitor); - return g_hash_table_lookup (compositor->outputs, &logical_monitor->winsys_id); -} - -static void -on_presented (ClutterStage *stage, - ClutterStageView *stage_view, - ClutterFrameInfo *frame_info, - MetaWaylandCompositor *compositor) -{ - MetaWaylandPresentationFeedback *feedback, *next; - struct wl_list *feedbacks; - MetaWaylandOutput *output; - - feedbacks = - meta_wayland_presentation_time_ensure_feedbacks (&compositor->presentation_time, - stage_view); - - output = get_output_for_stage_view (compositor, stage_view); - - wl_list_for_each_safe (feedback, next, feedbacks, link) - { - meta_wayland_presentation_feedback_present (feedback, - frame_info, - output); - } -} - -/** - * meta_wayland_compositor_handle_event: - * @compositor: the #MetaWaylandCompositor instance - * @event: the #ClutterEvent to be sent - * - * This method sends events to the focused wayland client, if any. - * - * Return value: whether @event was sent to a wayland client. - */ -gboolean -meta_wayland_compositor_handle_event (MetaWaylandCompositor *compositor, - const ClutterEvent *event) -{ - if (meta_wayland_tablet_manager_handle_event (compositor->tablet_manager, - event)) - return TRUE; - - return meta_wayland_seat_handle_event (compositor->seat, event); -} - -/* meta_wayland_compositor_update_key_state: - * @compositor: the #MetaWaylandCompositor - * @key_vector: bit vector of key states - * @key_vector_len: length of @key_vector - * @offset: the key for the first evdev keycode is found at this offset in @key_vector - * - * This function is used to resynchronize the key state that Mutter - * is tracking with the actual keyboard state. This is useful, for example, - * to handle changes in key state when a nested compositor doesn't - * have focus. We need to fix up the XKB modifier tracking and deliver - * any modifier changes to clients. - */ -void -meta_wayland_compositor_update_key_state (MetaWaylandCompositor *compositor, - char *key_vector, - int key_vector_len, - int offset) -{ - meta_wayland_keyboard_update_key_state (compositor->seat->keyboard, - key_vector, key_vector_len, offset); -} - -void -meta_wayland_compositor_add_frame_callback_surface (MetaWaylandCompositor *compositor, - MetaWaylandSurface *surface) -{ - if (g_list_find (compositor->frame_callback_surfaces, surface)) - return; - - compositor->frame_callback_surfaces = - g_list_prepend (compositor->frame_callback_surfaces, surface); -} - -void -meta_wayland_compositor_remove_frame_callback_surface (MetaWaylandCompositor *compositor, - MetaWaylandSurface *surface) -{ - compositor->frame_callback_surfaces = - g_list_remove (compositor->frame_callback_surfaces, surface); -} - -void -meta_wayland_compositor_add_presentation_feedback_surface (MetaWaylandCompositor *compositor, - MetaWaylandSurface *surface) -{ - if (g_list_find (compositor->presentation_time.feedback_surfaces, surface)) - return; - - compositor->presentation_time.feedback_surfaces = - g_list_prepend (compositor->presentation_time.feedback_surfaces, surface); -} - -void -meta_wayland_compositor_remove_presentation_feedback_surface (MetaWaylandCompositor *compositor, - MetaWaylandSurface *surface) -{ - compositor->presentation_time.feedback_surfaces = - g_list_remove (compositor->presentation_time.feedback_surfaces, surface); -} - -static void -set_gnome_env (const char *name, - const char *value) -{ - GDBusConnection *session_bus; - GError *error = NULL; - g_autoptr (GVariant) result = NULL; - - setenv (name, value, TRUE); - - session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); - g_assert (session_bus); - - result = g_dbus_connection_call_sync (session_bus, - "org.gnome.SessionManager", - "/org/gnome/SessionManager", - "org.gnome.SessionManager", - "Setenv", - g_variant_new ("(ss)", name, value), - NULL, - G_DBUS_CALL_FLAGS_NO_AUTO_START, - -1, NULL, &error); - if (error) - { - char *remote_error; - - remote_error = g_dbus_error_get_remote_error (error); - if (g_strcmp0 (remote_error, "org.gnome.SessionManager.NotInInitialization") != 0) - { - meta_warning ("Failed to set environment variable %s for gnome-session: %s", - name, error->message); - } - - g_free (remote_error); - g_error_free (error); - } -} - -static void meta_wayland_log_func (const char *, va_list) G_GNUC_PRINTF (1, 0); - -static void -meta_wayland_log_func (const char *fmt, - va_list arg) -{ - char *str = g_strdup_vprintf (fmt, arg); - g_warning ("WL: %s", str); - g_free (str); -} - -void -meta_wayland_compositor_prepare_shutdown (MetaWaylandCompositor *compositor) -{ - meta_xwayland_shutdown (&compositor->xwayland_manager); - - if (compositor->wayland_display) - wl_display_destroy_clients (compositor->wayland_display); -} - -static void -meta_wayland_compositor_finalize (GObject *object) -{ - MetaWaylandCompositor *compositor = META_WAYLAND_COMPOSITOR (object); - - g_clear_pointer (&compositor->seat, meta_wayland_seat_free); - - g_clear_pointer (&compositor->display_name, g_free); - g_clear_pointer (&compositor->wayland_display, wl_display_destroy); - - G_OBJECT_CLASS (meta_wayland_compositor_parent_class)->finalize (object); -} - -static void -meta_wayland_compositor_init (MetaWaylandCompositor *compositor) -{ - compositor->scheduled_surface_associations = g_hash_table_new (NULL, NULL); - - wl_log_set_handler_server (meta_wayland_log_func); - - compositor->wayland_display = wl_display_create (); - if (compositor->wayland_display == NULL) - g_error ("Failed to create the global wl_display"); -} - -static void -meta_wayland_compositor_class_init (MetaWaylandCompositorClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = meta_wayland_compositor_finalize; -} - -static bool -meta_xwayland_global_filter (const struct wl_client *client, - const struct wl_global *global, - void *data) -{ - MetaWaylandCompositor *compositor = (MetaWaylandCompositor *) data; - MetaXWaylandManager *xwayland_manager = &compositor->xwayland_manager; - - /* Keyboard grabbing protocol is for Xwayland only */ - if (client != xwayland_manager->client) - return (wl_global_get_interface (global) != - &zwp_xwayland_keyboard_grab_manager_v1_interface); - - /* All others are visible to all clients */ - return true; -} - -void -meta_wayland_override_display_name (const char *display_name) -{ - g_clear_pointer (&_display_name_override, g_free); - _display_name_override = g_strdup (display_name); -} - -static const char * -meta_wayland_get_xwayland_auth_file (MetaWaylandCompositor *compositor) -{ - return compositor->xwayland_manager.auth_file; -} - -static void -meta_wayland_init_egl (MetaWaylandCompositor *compositor) -{ - MetaBackend *backend = meta_get_backend (); - MetaEgl *egl = meta_backend_get_egl (backend); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = - clutter_backend_get_cogl_context (clutter_backend); - EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context); - g_autoptr (GError) error = NULL; - - if (!meta_egl_has_extensions (egl, egl_display, NULL, - "EGL_WL_bind_wayland_display", - NULL)) - { - meta_topic (META_DEBUG_WAYLAND, - "Not binding Wayland display, missing extension"); - return; - } - - meta_topic (META_DEBUG_WAYLAND, - "Binding Wayland EGL display"); - - if (!meta_egl_bind_wayland_display (egl, - egl_display, - compositor->wayland_display, - &error)) - g_warning ("Failed to bind Wayland display: %s", error->message); -} - -MetaWaylandCompositor * -meta_wayland_compositor_new (MetaContext *context) -{ - MetaBackend *backend = meta_context_get_backend (context); - ClutterActor *stage = meta_backend_get_stage (backend); - MetaWaylandCompositor *compositor; - GSource *wayland_event_source; - MetaX11DisplayPolicy x11_display_policy; - - compositor = g_object_new (META_TYPE_WAYLAND_COMPOSITOR, NULL); - compositor->context = context; - - wayland_event_source = wayland_event_source_new (compositor->wayland_display); - - /* XXX: Here we are setting the wayland event source to have a - * slightly lower priority than the X event source, because we are - * much more likely to get confused being told about surface changes - * relating to X clients when we don't know what's happened to them - * according to the X protocol. - */ - g_source_set_priority (wayland_event_source, GDK_PRIORITY_EVENTS + 1); - g_source_attach (wayland_event_source, NULL); - - g_signal_connect (stage, "after-update", - G_CALLBACK (on_after_update), compositor); - g_signal_connect (stage, "presented", - G_CALLBACK (on_presented), compositor); - - if (!wl_global_create (compositor->wayland_display, - &wl_compositor_interface, - META_WL_COMPOSITOR_VERSION, - compositor, compositor_bind)) - g_error ("Failed to register the global wl_compositor"); - - meta_wayland_init_egl (compositor); - meta_wayland_init_shm (compositor); - - meta_wayland_outputs_init (compositor); - meta_wayland_data_device_manager_init (compositor); - meta_wayland_data_device_primary_manager_init (compositor); - meta_wayland_data_device_primary_legacy_manager_init (compositor); - meta_wayland_subsurfaces_init (compositor); - meta_wayland_shell_init (compositor); - meta_wayland_pointer_gestures_init (compositor); - meta_wayland_tablet_manager_init (compositor); - meta_wayland_seat_init (compositor); - meta_wayland_relative_pointer_init (compositor); - meta_wayland_pointer_constraints_init (compositor); - meta_wayland_xdg_foreign_init (compositor); - meta_wayland_dma_buf_init (compositor); - meta_wayland_keyboard_shortcuts_inhibit_init (compositor); - meta_wayland_surface_inhibit_shortcuts_dialog_init (); - meta_wayland_text_input_init (compositor); - meta_wayland_gtk_text_input_init (compositor); - meta_wayland_init_presentation_time (compositor); - meta_wayland_activation_init (compositor); - - /* Xwayland specific protocol, needs to be filtered out for all other clients */ - if (meta_xwayland_grab_keyboard_init (compositor)) - wl_display_set_global_filter (compositor->wayland_display, - meta_xwayland_global_filter, - compositor); - -#ifdef HAVE_WAYLAND_EGLSTREAM - meta_wayland_eglstream_controller_init (compositor); -#endif - - x11_display_policy = - meta_context_get_x11_display_policy (compositor->context); - if (x11_display_policy != META_X11_DISPLAY_POLICY_DISABLED) - { - g_autoptr (GError) error = NULL; - - if (!meta_xwayland_init (&compositor->xwayland_manager, - compositor, - compositor->wayland_display, - &error)) - g_error ("Failed to start X Wayland: %s", error->message); - } - - if (_display_name_override) - { - compositor->display_name = g_steal_pointer (&_display_name_override); - - if (wl_display_add_socket (compositor->wayland_display, - compositor->display_name) != 0) - g_error ("Failed to create_socket"); - } - else - { - const char *display_name; - - display_name = wl_display_add_socket_auto (compositor->wayland_display); - if (!display_name) - g_error ("Failed to create socket"); - - compositor->display_name = g_strdup (display_name); - } - - g_message ("Using Wayland display name '%s'", compositor->display_name); - - if (x11_display_policy != META_X11_DISPLAY_POLICY_DISABLED) - { - set_gnome_env ("GNOME_SETUP_DISPLAY", compositor->xwayland_manager.private_connection.name); - set_gnome_env ("DISPLAY", compositor->xwayland_manager.public_connection.name); - set_gnome_env ("XAUTHORITY", meta_wayland_get_xwayland_auth_file (compositor)); - } - - set_gnome_env ("WAYLAND_DISPLAY", meta_wayland_get_wayland_display_name (compositor)); - - return compositor; -} - -const char * -meta_wayland_get_wayland_display_name (MetaWaylandCompositor *compositor) -{ - return compositor->display_name; -} - -const char * -meta_wayland_get_public_xwayland_display_name (MetaWaylandCompositor *compositor) -{ - return compositor->xwayland_manager.public_connection.name; -} - -const char * -meta_wayland_get_private_xwayland_display_name (MetaWaylandCompositor *compositor) -{ - return compositor->xwayland_manager.private_connection.name; -} - -void -meta_wayland_compositor_restore_shortcuts (MetaWaylandCompositor *compositor, - ClutterInputDevice *source) -{ - MetaWaylandKeyboard *keyboard; - - /* Clutter is not multi-seat aware yet, use the default seat instead */ - keyboard = compositor->seat->keyboard; - if (!keyboard || !keyboard->focus_surface) - return; - - if (!meta_wayland_surface_is_shortcuts_inhibited (keyboard->focus_surface, - compositor->seat)) - return; - - meta_wayland_surface_restore_shortcuts (keyboard->focus_surface, - compositor->seat); -} - -gboolean -meta_wayland_compositor_is_shortcuts_inhibited (MetaWaylandCompositor *compositor, - ClutterInputDevice *source) -{ - MetaWaylandKeyboard *keyboard; - - /* Clutter is not multi-seat aware yet, use the default seat instead */ - keyboard = compositor->seat->keyboard; - if (keyboard && keyboard->focus_surface != NULL) - return meta_wayland_surface_is_shortcuts_inhibited (keyboard->focus_surface, - compositor->seat); - - return FALSE; -} - -void -meta_wayland_compositor_flush_clients (MetaWaylandCompositor *compositor) -{ - wl_display_flush_clients (compositor->wayland_display); -} - -static void on_scheduled_association_unmanaged (MetaWindow *window, - gpointer user_data); - -static void -meta_wayland_compositor_remove_surface_association (MetaWaylandCompositor *compositor, - int id) -{ - MetaWindow *window; - - window = g_hash_table_lookup (compositor->scheduled_surface_associations, - GINT_TO_POINTER (id)); - if (window) - { - g_signal_handlers_disconnect_by_func (window, - on_scheduled_association_unmanaged, - GINT_TO_POINTER (id)); - g_hash_table_remove (compositor->scheduled_surface_associations, - GINT_TO_POINTER (id)); - } -} - -static void -on_scheduled_association_unmanaged (MetaWindow *window, - gpointer user_data) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - - meta_wayland_compositor_remove_surface_association (compositor, - GPOINTER_TO_INT (user_data)); -} - -void -meta_wayland_compositor_schedule_surface_association (MetaWaylandCompositor *compositor, - int id, - MetaWindow *window) -{ - g_signal_connect (window, "unmanaged", - G_CALLBACK (on_scheduled_association_unmanaged), - GINT_TO_POINTER (id)); - g_hash_table_insert (compositor->scheduled_surface_associations, - GINT_TO_POINTER (id), window); -} - -void -meta_wayland_compositor_notify_surface_id (MetaWaylandCompositor *compositor, - int id, - MetaWaylandSurface *surface) -{ - MetaWindow *window; - - window = g_hash_table_lookup (compositor->scheduled_surface_associations, - GINT_TO_POINTER (id)); - if (window) - { - meta_xwayland_associate_window_with_surface (window, surface); - meta_wayland_compositor_remove_surface_association (compositor, id); - } -} diff --git a/src/wayland/meta-wayland.h b/src/wayland/meta-wayland.h deleted file mode 100644 index 387e98b52..000000000 --- a/src/wayland/meta-wayland.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -#ifndef META_WAYLAND_H -#define META_WAYLAND_H - -#include "clutter/clutter.h" -#include "core/meta-context-private.h" -#include "core/util-private.h" -#include "meta/types.h" -#include "wayland/meta-wayland-types.h" - -META_EXPORT_TEST -void meta_wayland_override_display_name (const char *display_name); - -MetaWaylandCompositor * meta_wayland_compositor_new (MetaContext *context); - -void meta_wayland_compositor_prepare_shutdown (MetaWaylandCompositor *compositor); - -META_EXPORT_TEST -MetaWaylandCompositor *meta_wayland_compositor_get_default (void); - -void meta_wayland_compositor_update (MetaWaylandCompositor *compositor, - const ClutterEvent *event); - -gboolean meta_wayland_compositor_handle_event (MetaWaylandCompositor *compositor, - const ClutterEvent *event); - -void meta_wayland_compositor_update_key_state (MetaWaylandCompositor *compositor, - char *key_vector, - int key_vector_len, - int offset); - -void meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor, - MetaWindow *window); - -void meta_wayland_compositor_paint_finished (MetaWaylandCompositor *compositor); - -void meta_wayland_compositor_add_frame_callback_surface (MetaWaylandCompositor *compositor, - MetaWaylandSurface *surface); - -void meta_wayland_compositor_remove_frame_callback_surface (MetaWaylandCompositor *compositor, - MetaWaylandSurface *surface); - -void meta_wayland_compositor_add_presentation_feedback_surface (MetaWaylandCompositor *compositor, - MetaWaylandSurface *surface); - -void meta_wayland_compositor_remove_presentation_feedback_surface (MetaWaylandCompositor *compositor, - MetaWaylandSurface *surface); - -META_EXPORT_TEST -const char *meta_wayland_get_wayland_display_name (MetaWaylandCompositor *compositor); - -META_EXPORT_TEST -const char *meta_wayland_get_public_xwayland_display_name (MetaWaylandCompositor *compositor); - -const char *meta_wayland_get_private_xwayland_display_name (MetaWaylandCompositor *compositor); - -void meta_wayland_compositor_restore_shortcuts (MetaWaylandCompositor *compositor, - ClutterInputDevice *source); - -gboolean meta_wayland_compositor_is_shortcuts_inhibited (MetaWaylandCompositor *compositor, - ClutterInputDevice *source); - -void meta_wayland_compositor_flush_clients (MetaWaylandCompositor *compositor); - -void meta_wayland_compositor_schedule_surface_association (MetaWaylandCompositor *compositor, - int id, - MetaWindow *window); - -void meta_wayland_compositor_notify_surface_id (MetaWaylandCompositor *compositor, - int id, - MetaWaylandSurface *surface); - -#endif - diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c deleted file mode 100644 index 12e9567d9..000000000 --- a/src/wayland/meta-window-wayland.c +++ /dev/null @@ -1,1195 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -#include "config.h" - -#include "wayland/meta-window-wayland.h" - -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-backend-private.h" -#include "backends/meta-logical-monitor.h" -#include "compositor/meta-surface-actor-wayland.h" -#include "compositor/meta-window-actor-private.h" -#include "core/boxes-private.h" -#include "core/stack-tracker.h" -#include "core/window-private.h" -#include "meta/meta-x11-errors.h" -#include "wayland/meta-wayland-actor-surface.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-surface.h" -#include "wayland/meta-wayland-window-configuration.h" -#include "wayland/meta-wayland-xdg-shell.h" - -struct _MetaWindowWayland -{ - MetaWindow parent; - - int geometry_scale; - - GList *pending_configurations; - gboolean has_pending_state_change; - - gboolean has_last_sent_configuration; - int last_sent_x; - int last_sent_y; - int last_sent_width; - int last_sent_height; - int last_sent_rel_x; - int last_sent_rel_y; - int last_sent_geometry_scale; - MetaGravity last_sent_gravity; - - gboolean has_been_shown; -}; - -struct _MetaWindowWaylandClass -{ - MetaWindowClass parent_class; -}; - -G_DEFINE_TYPE (MetaWindowWayland, meta_window_wayland, META_TYPE_WINDOW) - -static void -set_geometry_scale_for_window (MetaWindowWayland *wl_window, - int geometry_scale) -{ - MetaWindowActor *window_actor; - - wl_window->geometry_scale = geometry_scale; - - window_actor = meta_window_actor_from_window (META_WINDOW (wl_window)); - if (window_actor) - meta_window_actor_set_geometry_scale (window_actor, geometry_scale); -} - -static int -get_window_geometry_scale_for_logical_monitor (MetaLogicalMonitor *logical_monitor) -{ - g_assert (logical_monitor); - - if (meta_is_stage_views_scaled ()) - return 1; - else - return meta_logical_monitor_get_scale (logical_monitor); -} - -static void -meta_window_wayland_manage (MetaWindow *window) -{ - MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window); - MetaDisplay *display = window->display; - - wl_window->geometry_scale = meta_window_wayland_get_geometry_scale (window); - - meta_display_register_wayland_window (display, window); - - { - meta_stack_tracker_record_add (window->display->stack_tracker, - window->stamp, - 0); - } - - meta_wayland_surface_window_managed (window->surface, window); -} - -static void -meta_window_wayland_unmanage (MetaWindow *window) -{ - { - meta_stack_tracker_record_remove (window->display->stack_tracker, - window->stamp, - 0); - } - - meta_display_unregister_wayland_window (window->display, window); -} - -static void -meta_window_wayland_ping (MetaWindow *window, - guint32 serial) -{ - meta_wayland_surface_ping (window->surface, serial); -} - -static void -meta_window_wayland_delete (MetaWindow *window, - guint32 timestamp) -{ - meta_wayland_surface_delete (window->surface); -} - -static void -meta_window_wayland_kill (MetaWindow *window) -{ - MetaWaylandSurface *surface = window->surface; - struct wl_resource *resource = surface->resource; - - /* Send the client an unrecoverable error to kill the client. */ - wl_resource_post_error (resource, - WL_DISPLAY_ERROR_NO_MEMORY, - "User requested that we kill you. Sorry. Don't take it too personally."); -} - -static void -meta_window_wayland_focus (MetaWindow *window, - guint32 timestamp) -{ - if (meta_window_is_focusable (window)) - { - meta_display_set_input_focus (window->display, - window, - FALSE, - timestamp); - } -} - -static void -meta_window_wayland_configure (MetaWindowWayland *wl_window, - MetaWaylandWindowConfiguration *configuration) -{ - MetaWindow *window = META_WINDOW (wl_window); - - meta_wayland_surface_configure_notify (window->surface, configuration); - - wl_window->pending_configurations = - g_list_prepend (wl_window->pending_configurations, configuration); -} - -static void -surface_state_changed (MetaWindow *window) -{ - MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window); - MetaWaylandWindowConfiguration *configuration; - - /* don't send notify when the window is being unmanaged */ - if (window->unmanaging) - return; - - g_return_if_fail (wl_window->has_last_sent_configuration); - - configuration = - meta_wayland_window_configuration_new (window, - wl_window->last_sent_x, - wl_window->last_sent_y, - wl_window->last_sent_width, - wl_window->last_sent_height, - wl_window->last_sent_geometry_scale, - META_MOVE_RESIZE_STATE_CHANGED, - wl_window->last_sent_gravity); - - meta_window_wayland_configure (wl_window, configuration); -} - -static void -meta_window_wayland_grab_op_began (MetaWindow *window, - MetaGrabOp op) -{ - if (meta_grab_op_is_resizing (op)) - surface_state_changed (window); - - META_WINDOW_CLASS (meta_window_wayland_parent_class)->grab_op_began (window, op); -} - -static void -meta_window_wayland_grab_op_ended (MetaWindow *window, - MetaGrabOp op) -{ - if (meta_grab_op_is_resizing (op)) - surface_state_changed (window); - - META_WINDOW_CLASS (meta_window_wayland_parent_class)->grab_op_ended (window, op); -} - -static void -meta_window_wayland_move_resize_internal (MetaWindow *window, - MetaGravity gravity, - MetaRectangle unconstrained_rect, - MetaRectangle constrained_rect, - MetaRectangle temporary_rect, - int rel_x, - int rel_y, - MetaMoveResizeFlags flags, - MetaMoveResizeResultFlags *result) -{ - MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window); - gboolean can_move_now = FALSE; - int configured_x; - int configured_y; - int configured_width; - int configured_height; - int geometry_scale; - int new_x; - int new_y; - int new_buffer_x; - int new_buffer_y; - - g_assert (window->frame == NULL); - - /* don't do anything if we're dropping the window, see #751847 */ - if (window->unmanaging) - return; - - configured_x = constrained_rect.x; - configured_y = constrained_rect.y; - - /* The scale the window is drawn in might change depending on what monitor it - * is mainly on. Scale the configured rectangle to be in logical pixel - * coordinate space so that we can have a scale independent size to pass - * to the Wayland surface. */ - geometry_scale = meta_window_wayland_get_geometry_scale (window); - - configured_width = constrained_rect.width; - configured_height = constrained_rect.height; - - /* For wayland clients, the size is completely determined by the client, - * and while this allows to avoid some trickery with frames and the resulting - * lagging, we also need to insist a bit when the constraints would apply - * a different size than the client decides. - * - * Note that this is not generally a problem for normal toplevel windows (the - * constraints don't see the size hints, or just change the position), but - * it can be for maximized or fullscreen. - */ - - if (flags & META_MOVE_RESIZE_FORCE_MOVE) - { - can_move_now = TRUE; - } - else if (flags & META_MOVE_RESIZE_WAYLAND_FINISH_MOVE_RESIZE) - { - /* This is a call to wl_surface_commit(), ignore the constrained_rect and - * update the real client size to match the buffer size. - */ - - if (window->rect.width != unconstrained_rect.width || - window->rect.height != unconstrained_rect.height) - { - *result |= META_MOVE_RESIZE_RESULT_RESIZED; - window->rect.width = unconstrained_rect.width; - window->rect.height = unconstrained_rect.height; - } - - /* This is a commit of an attach. We should move the window to match the - * new position the client wants. */ - can_move_now = TRUE; - if (window->placement.state == META_PLACEMENT_STATE_CONSTRAINED_CONFIGURED) - window->placement.state = META_PLACEMENT_STATE_CONSTRAINED_FINISHED; - } - else - { - if (window->placement.rule) - { - switch (window->placement.state) - { - case META_PLACEMENT_STATE_UNCONSTRAINED: - case META_PLACEMENT_STATE_CONSTRAINED_CONFIGURED: - case META_PLACEMENT_STATE_INVALIDATED: - can_move_now = FALSE; - break; - case META_PLACEMENT_STATE_CONSTRAINED_PENDING: - { - if (flags & META_MOVE_RESIZE_PLACEMENT_CHANGED || - rel_x != wl_window->last_sent_rel_x || - rel_y != wl_window->last_sent_rel_y || - constrained_rect.width != window->rect.width || - constrained_rect.height != window->rect.height) - { - MetaWaylandWindowConfiguration *configuration; - - configuration = - meta_wayland_window_configuration_new_relative (rel_x, - rel_y, - configured_width, - configured_height, - geometry_scale); - meta_window_wayland_configure (wl_window, configuration); - - wl_window->last_sent_rel_x = rel_x; - wl_window->last_sent_rel_y = rel_y; - - window->placement.state = META_PLACEMENT_STATE_CONSTRAINED_CONFIGURED; - - can_move_now = FALSE; - } - else - { - window->placement.state = - META_PLACEMENT_STATE_CONSTRAINED_FINISHED; - - can_move_now = TRUE; - } - break; - } - case META_PLACEMENT_STATE_CONSTRAINED_FINISHED: - can_move_now = TRUE; - break; - } - } - else if (constrained_rect.width != window->rect.width || - constrained_rect.height != window->rect.height || - flags & META_MOVE_RESIZE_STATE_CHANGED) - { - MetaWaylandWindowConfiguration *configuration; - - if (!meta_wayland_surface_get_buffer (window->surface) && - !META_WINDOW_MAXIMIZED (window) && - window->tile_mode == META_TILE_NONE && - !meta_window_is_fullscreen (window)) - return; - - configuration = - meta_wayland_window_configuration_new (window, - configured_x, - configured_y, - configured_width, - configured_height, - geometry_scale, - flags, - gravity); - meta_window_wayland_configure (wl_window, configuration); - can_move_now = FALSE; - } - else - { - can_move_now = TRUE; - } - } - - wl_window->has_last_sent_configuration = TRUE; - wl_window->last_sent_x = configured_x; - wl_window->last_sent_y = configured_y; - wl_window->last_sent_width = configured_width; - wl_window->last_sent_height = configured_height; - wl_window->last_sent_geometry_scale = geometry_scale; - wl_window->last_sent_gravity = gravity; - - if (can_move_now) - { - new_x = constrained_rect.x; - new_y = constrained_rect.y; - } - else - { - new_x = temporary_rect.x; - new_y = temporary_rect.y; - - wl_window->has_pending_state_change |= - !!(flags & META_MOVE_RESIZE_STATE_CHANGED); - } - - if (new_x != window->rect.x || new_y != window->rect.y) - { - *result |= META_MOVE_RESIZE_RESULT_MOVED; - window->rect.x = new_x; - window->rect.y = new_y; - } - - if (window->placement.rule && - window->placement.state == META_PLACEMENT_STATE_CONSTRAINED_FINISHED) - { - window->placement.current.rel_x = rel_x; - window->placement.current.rel_y = rel_y; - } - - new_buffer_x = new_x - window->custom_frame_extents.left; - new_buffer_y = new_y - window->custom_frame_extents.top; - - if (new_buffer_x != window->buffer_rect.x || - new_buffer_y != window->buffer_rect.y) - { - *result |= META_MOVE_RESIZE_RESULT_MOVED; - window->buffer_rect.x = new_buffer_x; - window->buffer_rect.y = new_buffer_y; - } - - if (can_move_now && - flags & META_MOVE_RESIZE_WAYLAND_STATE_CHANGED) - *result |= META_MOVE_RESIZE_RESULT_STATE_CHANGED; -} - -static void -scale_size (int *width, - int *height, - float scale) -{ - if (*width < G_MAXINT) - { - float new_width = (*width * scale); - *width = (int) MIN (new_width, G_MAXINT); - } - - if (*height < G_MAXINT) - { - float new_height = (*height * scale); - *height = (int) MIN (new_height, G_MAXINT); - } -} - -static void -scale_rect_size (MetaRectangle *rect, - float scale) -{ - scale_size (&rect->width, &rect->height, scale); -} - -static void -meta_window_wayland_update_main_monitor (MetaWindow *window, - MetaWindowUpdateMonitorFlags flags) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaWindow *toplevel_window; - MetaLogicalMonitor *from; - MetaLogicalMonitor *to; - MetaLogicalMonitor *scaled_new; - float from_scale, to_scale; - float scale; - MetaRectangle rect; - - from = window->monitor; - - /* If the window is not a toplevel window (i.e. it's a popup window) just use - * the monitor of the toplevel. */ - toplevel_window = meta_wayland_surface_get_toplevel_window (window->surface); - if (toplevel_window != window) - { - meta_window_update_monitor (toplevel_window, flags); - window->monitor = toplevel_window->monitor; - return; - } - - /* Require both the current and the new monitor would be the new main monitor, - * even given the resulting scale the window would end up having. This is - * needed to avoid jumping back and forth between the new and the old, since - * changing main monitor may cause the window to be resized so that it no - * longer have that same new main monitor. */ - to = meta_window_calculate_main_logical_monitor (window); - - if (from == to) - return; - - if (from == NULL || to == NULL) - { - window->monitor = to; - return; - } - - if (flags & META_WINDOW_UPDATE_MONITOR_FLAGS_FORCE) - { - window->monitor = to; - return; - } - - from_scale = meta_logical_monitor_get_scale (from); - to_scale = meta_logical_monitor_get_scale (to); - - if (from_scale == to_scale) - { - window->monitor = to; - return; - } - - if (meta_is_stage_views_scaled ()) - { - window->monitor = to; - return; - } - - /* To avoid a window alternating between two main monitors because scaling - * changes the main monitor, wait until both the current and the new scale - * will result in the same main monitor. */ - scale = to_scale / from_scale; - rect = window->rect; - scale_rect_size (&rect, scale); - scaled_new = - meta_monitor_manager_get_logical_monitor_from_rect (monitor_manager, &rect); - if (to != scaled_new) - return; - - window->monitor = to; -} - -static void -meta_window_wayland_main_monitor_changed (MetaWindow *window, - const MetaLogicalMonitor *old) -{ - MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window); - int old_geometry_scale = wl_window->geometry_scale; - int geometry_scale; - float scale_factor; - MetaWaylandSurface *surface; - - if (!window->monitor) - return; - - geometry_scale = meta_window_wayland_get_geometry_scale (window); - - /* This function makes sure that window geometry, window actor geometry and - * surface actor geometry gets set according the old and current main monitor - * scale. If there either is no past or current main monitor, or if the scale - * didn't change, there is nothing to do. */ - if (old == NULL || - window->monitor == NULL || - old_geometry_scale == geometry_scale) - return; - - /* MetaWindow keeps its rectangles in the physical pixel coordinate space. - * When the main monitor of a window changes, it can cause the corresponding - * window surfaces to be scaled given the monitor scale, so we need to scale - * the rectangles in MetaWindow accordingly. */ - - scale_factor = (float) geometry_scale / old_geometry_scale; - - /* Window size. */ - scale_rect_size (&window->rect, scale_factor); - scale_rect_size (&window->unconstrained_rect, scale_factor); - scale_rect_size (&window->saved_rect, scale_factor); - scale_size (&window->size_hints.min_width, &window->size_hints.min_height, scale_factor); - scale_size (&window->size_hints.max_width, &window->size_hints.max_height, scale_factor); - - /* Window geometry offset (XXX: Need a better place, see - * meta_window_wayland_finish_move_resize). */ - window->custom_frame_extents.left = - (int)(scale_factor * window->custom_frame_extents.left); - window->custom_frame_extents.top = - (int)(scale_factor * window->custom_frame_extents.top); - - /* Buffer rect. */ - scale_rect_size (&window->buffer_rect, scale_factor); - window->buffer_rect.x = - window->rect.x - window->custom_frame_extents.left; - window->buffer_rect.y = - window->rect.y - window->custom_frame_extents.top; - - meta_compositor_sync_window_geometry (window->display->compositor, - window, - TRUE); - - surface = window->surface; - if (surface) - { - MetaWaylandActorSurface *actor_surface = - META_WAYLAND_ACTOR_SURFACE (surface->role); - - meta_wayland_actor_surface_sync_actor_state (actor_surface); - } - - set_geometry_scale_for_window (wl_window, geometry_scale); - meta_window_emit_size_changed (window); -} - -static pid_t -meta_window_wayland_get_client_pid (MetaWindow *window) -{ - MetaWaylandSurface *surface = window->surface; - struct wl_resource *resource = surface->resource; - pid_t pid; - - wl_client_get_credentials (wl_resource_get_client (resource), &pid, NULL, NULL); - return pid; -} - -static void -appears_focused_changed (GObject *object, - GParamSpec *pspec, - gpointer user_data) -{ - MetaWindow *window = META_WINDOW (object); - - if (window->placement.rule) - return; - - surface_state_changed (window); -} - -static void -on_window_shown (MetaWindow *window) -{ - MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window); - gboolean has_been_shown; - - has_been_shown = wl_window->has_been_shown; - wl_window->has_been_shown = TRUE; - - if (!has_been_shown) - meta_compositor_sync_updates_frozen (window->display->compositor, window); -} - -static void -meta_window_wayland_init (MetaWindowWayland *wl_window) -{ - MetaWindow *window = META_WINDOW (wl_window); - - wl_window->geometry_scale = 1; - - g_signal_connect (window, "notify::appears-focused", - G_CALLBACK (appears_focused_changed), NULL); - g_signal_connect (window, "shown", - G_CALLBACK (on_window_shown), NULL); -} - -static void -meta_window_wayland_force_restore_shortcuts (MetaWindow *window, - ClutterInputDevice *source) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - - meta_wayland_compositor_restore_shortcuts (compositor, source); -} - -static gboolean -meta_window_wayland_shortcuts_inhibited (MetaWindow *window, - ClutterInputDevice *source) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - - return meta_wayland_compositor_is_shortcuts_inhibited (compositor, source); -} - -static gboolean -meta_window_wayland_is_focusable (MetaWindow *window) -{ - return window->input; -} - -static gboolean -meta_window_wayland_can_ping (MetaWindow *window) -{ - return TRUE; -} - -static gboolean -meta_window_wayland_is_stackable (MetaWindow *window) -{ - return meta_wayland_surface_get_buffer (window->surface) != NULL; -} - -static gboolean -meta_window_wayland_are_updates_frozen (MetaWindow *window) -{ - MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window); - - return !wl_window->has_been_shown; -} - -static gboolean -meta_window_wayland_is_focus_async (MetaWindow *window) -{ - return FALSE; -} - -static MetaStackLayer -meta_window_wayland_calculate_layer (MetaWindow *window) -{ - return meta_window_get_default_layer (window); -} - -static void -meta_window_wayland_map (MetaWindow *window) -{ -} - -static void -meta_window_wayland_unmap (MetaWindow *window) -{ -} - -static void -meta_window_wayland_finalize (GObject *object) -{ - MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (object); - - g_list_free_full (wl_window->pending_configurations, - (GDestroyNotify) meta_wayland_window_configuration_free); - - G_OBJECT_CLASS (meta_window_wayland_parent_class)->finalize (object); -} - -static void -meta_window_wayland_class_init (MetaWindowWaylandClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaWindowClass *window_class = META_WINDOW_CLASS (klass); - - object_class->finalize = meta_window_wayland_finalize; - - window_class->manage = meta_window_wayland_manage; - window_class->unmanage = meta_window_wayland_unmanage; - window_class->ping = meta_window_wayland_ping; - window_class->delete = meta_window_wayland_delete; - window_class->kill = meta_window_wayland_kill; - window_class->focus = meta_window_wayland_focus; - window_class->grab_op_began = meta_window_wayland_grab_op_began; - window_class->grab_op_ended = meta_window_wayland_grab_op_ended; - window_class->move_resize_internal = meta_window_wayland_move_resize_internal; - window_class->update_main_monitor = meta_window_wayland_update_main_monitor; - window_class->main_monitor_changed = meta_window_wayland_main_monitor_changed; - window_class->get_client_pid = meta_window_wayland_get_client_pid; - window_class->force_restore_shortcuts = meta_window_wayland_force_restore_shortcuts; - window_class->shortcuts_inhibited = meta_window_wayland_shortcuts_inhibited; - window_class->is_focusable = meta_window_wayland_is_focusable; - window_class->is_stackable = meta_window_wayland_is_stackable; - window_class->can_ping = meta_window_wayland_can_ping; - window_class->are_updates_frozen = meta_window_wayland_are_updates_frozen; - window_class->calculate_layer = meta_window_wayland_calculate_layer; - window_class->map = meta_window_wayland_map; - window_class->unmap = meta_window_wayland_unmap; - window_class->is_focus_async = meta_window_wayland_is_focus_async; -} - -MetaWindow * -meta_window_wayland_new (MetaDisplay *display, - MetaWaylandSurface *surface) -{ - XWindowAttributes attrs = { 0 }; - MetaWindowWayland *wl_window; - MetaWindow *window; - - /* - * Set attributes used by _meta_window_shared_new, don't bother trying to fake - * X11 window attributes with the rest, since they'll be ignored anyway. - */ - attrs.x = 0; - attrs.y = 0; - attrs.width = 0; - attrs.height = 0; - attrs.depth = 24; - attrs.visual = NULL; - attrs.map_state = IsUnmapped; - attrs.override_redirect = False; - - window = _meta_window_shared_new (display, - META_WINDOW_CLIENT_TYPE_WAYLAND, - surface, - None, - WithdrawnState, - META_COMP_EFFECT_CREATE, - &attrs); - - wl_window = META_WINDOW_WAYLAND (window); - set_geometry_scale_for_window (wl_window, wl_window->geometry_scale); - - return window; -} - -MetaWaylandWindowConfiguration * -meta_window_wayland_peek_configuration (MetaWindowWayland *wl_window, - uint32_t serial) -{ - GList *l; - - for (l = wl_window->pending_configurations; l; l = l->next) - { - MetaWaylandWindowConfiguration *configuration = l->data; - - if (configuration->serial == serial) - return configuration; - } - - return NULL; -} - -static MetaWaylandWindowConfiguration * -acquire_acked_configuration (MetaWindowWayland *wl_window, - MetaWaylandSurfaceState *pending) -{ - GList *l; - - if (!pending->has_acked_configure_serial) - return NULL; - - for (l = wl_window->pending_configurations; l; l = l->next) - { - MetaWaylandWindowConfiguration *configuration = l->data; - GList *tail; - gboolean is_matching_configuration; - - if (configuration->serial > pending->acked_configure_serial) - continue; - - tail = l; - - if (tail->prev) - { - tail->prev->next = NULL; - tail->prev = NULL; - } - else - { - wl_window->pending_configurations = NULL; - } - - is_matching_configuration = - configuration->serial == pending->acked_configure_serial; - - if (is_matching_configuration) - tail = g_list_delete_link (tail, l); - g_list_free_full (tail, - (GDestroyNotify) meta_wayland_window_configuration_free); - - if (is_matching_configuration) - return configuration; - else - return NULL; - } - - return NULL; -} - -int -meta_window_wayland_get_geometry_scale (MetaWindow *window) -{ - if (!window->monitor) - return 1; - - return get_window_geometry_scale_for_logical_monitor (window->monitor); -} - -static void -calculate_offset (MetaWaylandWindowConfiguration *configuration, - MetaRectangle *geometry, - MetaRectangle *rect) -{ - int offset_x; - int offset_y; - - rect->x = configuration->x; - rect->y = configuration->y; - - offset_x = configuration->width - geometry->width; - offset_y = configuration->height - geometry->height; - switch (configuration->gravity) - { - case META_GRAVITY_SOUTH: - case META_GRAVITY_SOUTH_WEST: - rect->y += offset_y; - break; - case META_GRAVITY_EAST: - case META_GRAVITY_NORTH_EAST: - rect->x += offset_x; - break; - case META_GRAVITY_SOUTH_EAST: - rect->x += offset_x; - rect->y += offset_y; - break; - default: - break; - } -} - -/** - * meta_window_move_resize_wayland: - * - * Complete a resize operation from a wayland client. - */ -void -meta_window_wayland_finish_move_resize (MetaWindow *window, - MetaRectangle new_geom, - MetaWaylandSurfaceState *pending) -{ - MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window); - MetaDisplay *display = window->display; - int dx, dy; - int geometry_scale; - MetaGravity gravity; - MetaRectangle rect; - MetaMoveResizeFlags flags; - MetaWaylandWindowConfiguration *acked_configuration; - gboolean is_window_being_resized; - - /* new_geom is in the logical pixel coordinate space, but MetaWindow wants its - * rects to represent what in turn will end up on the stage, i.e. we need to - * scale new_geom to physical pixels given what buffer scale and texture scale - * is in use. */ - - geometry_scale = meta_window_wayland_get_geometry_scale (window); - new_geom.x *= geometry_scale; - new_geom.y *= geometry_scale; - new_geom.width *= geometry_scale; - new_geom.height *= geometry_scale; - - /* The (dx, dy) offset is also in logical pixel coordinate space and needs - * to be scaled in the same way as new_geom. */ - dx = pending->dx * geometry_scale; - dy = pending->dy * geometry_scale; - - /* XXX: Find a better place to store the window geometry offsets. */ - window->custom_frame_extents.left = new_geom.x; - window->custom_frame_extents.top = new_geom.y; - - flags = META_MOVE_RESIZE_WAYLAND_FINISH_MOVE_RESIZE; - - acked_configuration = acquire_acked_configuration (wl_window, pending); - - /* x/y are ignored when we're doing interactive resizing */ - is_window_being_resized = (meta_grab_op_is_resizing (display->grab_op) && - display->grab_window == window); - - rect = (MetaRectangle) { - .x = window->rect.x, - .y = window->rect.y, - .width = new_geom.width, - .height = new_geom.height - }; - - if (!is_window_being_resized) - { - if (acked_configuration) - { - if (window->placement.rule) - { - MetaWindow *parent; - - parent = meta_window_get_transient_for (window); - rect.x = parent->rect.x + acked_configuration->rel_x; - rect.y = parent->rect.y + acked_configuration->rel_y; - } - else if (acked_configuration->has_position) - { - calculate_offset (acked_configuration, &new_geom, &rect); - } - } - } - else - { - if (acked_configuration && acked_configuration->has_position) - calculate_offset (acked_configuration, &new_geom, &rect); - } - - rect.x += dx; - rect.y += dy; - - if (rect.x != window->rect.x || rect.y != window->rect.y) - flags |= META_MOVE_RESIZE_MOVE_ACTION; - - if (wl_window->has_pending_state_change && acked_configuration) - { - flags |= META_MOVE_RESIZE_WAYLAND_STATE_CHANGED; - wl_window->has_pending_state_change = FALSE; - } - - if (rect.width != window->rect.width || rect.height != window->rect.height) - flags |= META_MOVE_RESIZE_RESIZE_ACTION; - - if (window->display->grab_window == window) - gravity = meta_resize_gravity_from_grab_op (window->display->grab_op); - else - gravity = META_GRAVITY_STATIC; - meta_window_move_resize_internal (window, flags, gravity, rect); - - g_clear_pointer (&acked_configuration, meta_wayland_window_configuration_free); -} - -void -meta_window_wayland_place_relative_to (MetaWindow *window, - MetaWindow *other, - int x, - int y) -{ - int geometry_scale; - - /* If there is no monitor, we can't position the window reliably. */ - if (!other->monitor) - return; - - geometry_scale = meta_window_wayland_get_geometry_scale (other); - meta_window_move_frame (window, FALSE, - other->buffer_rect.x + (x * geometry_scale), - other->buffer_rect.y + (y * geometry_scale)); - window->placed = TRUE; -} - -void -meta_window_place_with_placement_rule (MetaWindow *window, - MetaPlacementRule *placement_rule) -{ - gboolean first_placement; - - first_placement = !window->placement.rule; - - g_clear_pointer (&window->placement.rule, g_free); - window->placement.rule = g_new0 (MetaPlacementRule, 1); - *window->placement.rule = *placement_rule; - - window->unconstrained_rect.x = window->rect.x; - window->unconstrained_rect.y = window->rect.y; - window->unconstrained_rect.width = placement_rule->width; - window->unconstrained_rect.height = placement_rule->height; - - window->calc_placement = first_placement; - meta_window_move_resize_internal (window, - (META_MOVE_RESIZE_MOVE_ACTION | - META_MOVE_RESIZE_RESIZE_ACTION | - META_MOVE_RESIZE_PLACEMENT_CHANGED), - META_GRAVITY_NORTH_WEST, - window->unconstrained_rect); - window->calc_placement = FALSE; -} - -void -meta_window_update_placement_rule (MetaWindow *window, - MetaPlacementRule *placement_rule) -{ - window->placement.state = META_PLACEMENT_STATE_INVALIDATED; - meta_window_place_with_placement_rule (window, placement_rule); -} - -void -meta_window_wayland_set_min_size (MetaWindow *window, - int width, - int height) -{ - gint64 new_width, new_height; - float scale; - - meta_topic (META_DEBUG_GEOMETRY, "Window %s sets min size %d x %d", - window->desc, width, height); - - if (width == 0 && height == 0) - { - window->size_hints.min_width = 0; - window->size_hints.min_height = 0; - window->size_hints.flags &= ~PMinSize; - - return; - } - - scale = (float) meta_window_wayland_get_geometry_scale (window); - scale_size (&width, &height, scale); - - new_width = width + (window->custom_frame_extents.left + - window->custom_frame_extents.right); - new_height = height + (window->custom_frame_extents.top + - window->custom_frame_extents.bottom); - - window->size_hints.min_width = (int) MIN (new_width, G_MAXINT); - window->size_hints.min_height = (int) MIN (new_height, G_MAXINT); - window->size_hints.flags |= PMinSize; -} - -void -meta_window_wayland_set_max_size (MetaWindow *window, - int width, - int height) - -{ - gint64 new_width, new_height; - float scale; - - meta_topic (META_DEBUG_GEOMETRY, "Window %s sets max size %d x %d", - window->desc, width, height); - - if (width == 0 && height == 0) - { - window->size_hints.max_width = G_MAXINT; - window->size_hints.max_height = G_MAXINT; - window->size_hints.flags &= ~PMaxSize; - - return; - } - - scale = (float) meta_window_wayland_get_geometry_scale (window); - scale_size (&width, &height, scale); - - new_width = width + (window->custom_frame_extents.left + - window->custom_frame_extents.right); - new_height = height + (window->custom_frame_extents.top + - window->custom_frame_extents.bottom); - - window->size_hints.max_width = (int) ((new_width > 0 && new_width < G_MAXINT) ? - new_width : G_MAXINT); - window->size_hints.max_height = (int) ((new_height > 0 && new_height < G_MAXINT) ? - new_height : G_MAXINT); - window->size_hints.flags |= PMaxSize; -} - -void -meta_window_wayland_get_min_size (MetaWindow *window, - int *width, - int *height) -{ - gint64 current_width, current_height; - float scale; - - if (!(window->size_hints.flags & PMinSize)) - { - /* Zero means unlimited */ - *width = 0; - *height = 0; - - return; - } - - current_width = window->size_hints.min_width - - (window->custom_frame_extents.left + - window->custom_frame_extents.right); - current_height = window->size_hints.min_height - - (window->custom_frame_extents.top + - window->custom_frame_extents.bottom); - - *width = MAX (current_width, 0); - *height = MAX (current_height, 0); - - scale = 1.0 / (float) meta_window_wayland_get_geometry_scale (window); - scale_size (width, height, scale); -} - -void -meta_window_wayland_get_max_size (MetaWindow *window, - int *width, - int *height) -{ - gint64 current_width = 0; - gint64 current_height = 0; - float scale; - - if (!(window->size_hints.flags & PMaxSize)) - { - /* Zero means unlimited */ - *width = 0; - *height = 0; - - return; - } - - if (window->size_hints.max_width < G_MAXINT) - current_width = window->size_hints.max_width - - (window->custom_frame_extents.left + - window->custom_frame_extents.right); - - if (window->size_hints.max_height < G_MAXINT) - current_height = window->size_hints.max_height - - (window->custom_frame_extents.top + - window->custom_frame_extents.bottom); - - *width = CLAMP (current_width, 0, G_MAXINT); - *height = CLAMP (current_height, 0, G_MAXINT); - - scale = 1.0 / (float) meta_window_wayland_get_geometry_scale (window); - scale_size (width, height, scale); -} diff --git a/src/wayland/meta-window-wayland.h b/src/wayland/meta-window-wayland.h deleted file mode 100644 index db152daaa..000000000 --- a/src/wayland/meta-window-wayland.h +++ /dev/null @@ -1,80 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -#ifndef META_WINDOW_WAYLAND_H -#define META_WINDOW_WAYLAND_H - -#include "core/window-private.h" -#include "meta/window.h" -#include "wayland/meta-wayland-types.h" - -G_BEGIN_DECLS - -#define META_TYPE_WINDOW_WAYLAND (meta_window_wayland_get_type()) -G_DECLARE_FINAL_TYPE (MetaWindowWayland, meta_window_wayland, - META, WINDOW_WAYLAND, - MetaWindow) - -MetaWindow * meta_window_wayland_new (MetaDisplay *display, - MetaWaylandSurface *surface); - -void meta_window_wayland_finish_move_resize (MetaWindow *window, - MetaRectangle new_geom, - MetaWaylandSurfaceState *pending); - -int meta_window_wayland_get_geometry_scale (MetaWindow *window); - -void meta_window_wayland_place_relative_to (MetaWindow *window, - MetaWindow *other, - int x, - int y); - -void meta_window_place_with_placement_rule (MetaWindow *window, - MetaPlacementRule *placement_rule); - -void meta_window_update_placement_rule (MetaWindow *window, - MetaPlacementRule *placement_rule); - -MetaWaylandWindowConfiguration * - meta_window_wayland_peek_configuration (MetaWindowWayland *wl_window, - uint32_t serial); - -void meta_window_wayland_set_min_size (MetaWindow *window, - int width, - int height); - -void meta_window_wayland_set_max_size (MetaWindow *window, - int width, - int height); - -void meta_window_wayland_get_min_size (MetaWindow *window, - int *width, - int *height); - - -void meta_window_wayland_get_max_size (MetaWindow *window, - int *width, - int *height); - -#endif diff --git a/src/wayland/meta-window-xwayland.c b/src/wayland/meta-window-xwayland.c deleted file mode 100644 index 54ccc91fe..000000000 --- a/src/wayland/meta-window-xwayland.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright (C) 2017 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, see . - * - */ - -#include "config.h" - -#include - -#include "core/frame.h" -#include "meta/meta-x11-errors.h" -#include "x11/window-x11.h" -#include "x11/window-x11-private.h" -#include "x11/xprops.h" -#include "wayland/meta-window-xwayland.h" -#include "wayland/meta-wayland.h" - -enum -{ - PROP_0, - - PROP_XWAYLAND_MAY_GRAB_KEYBOARD, - - PROP_LAST -}; - -static GParamSpec *obj_props[PROP_LAST]; - -struct _MetaWindowXwayland -{ - MetaWindowX11 parent; - - gboolean xwayland_may_grab_keyboard; - int freeze_count; -}; - -struct _MetaWindowXwaylandClass -{ - MetaWindowX11Class parent_class; -}; - -G_DEFINE_TYPE (MetaWindowXwayland, meta_window_xwayland, META_TYPE_WINDOW_X11) - -static void -meta_window_xwayland_init (MetaWindowXwayland *window_xwayland) -{ -} - -/** - * meta_window_xwayland_adjust_fullscreen_monitor_rect: - * - * This function implements a workaround for X11 apps which use randr to change the - * the monitor resolution, followed by setting _NET_WM_FULLSCREEN to make the - * window-manager fullscreen them. - * - * Newer versions of Xwayland support the randr part of this by supporting randr - * resolution change emulation in combination with using WPviewport to scale the - * app's window (at the emulated resolution) to fill the entire monitor. - * - * Apps using randr in combination with NET_WM_STATE_FULLSCREEN expect the - * fullscreen window to have the size of the emulated randr resolution since - * when running on regular Xorg the resolution will actually be changed and - * after that going fullscreen through NET_WM_STATE_FULLSCREEN will size - * the window to be equal to the new resolution. - * - * We need to emulate this behavior for these apps to work correctly. - * - * Xwayland's emulated resolution is a per X11 client setting and Xwayland - * will set a special _XWAYLAND_RANDR_EMU_MONITOR_RECTS property on the - * toplevel windows of a client (and only those of that client), which has - * changed the (emulated) resolution through a randr call. - * - * Here we check for that property and if it is set we adjust the fullscreen - * monitor rect for this window to match the emulated resolution. - * - * Here is a step-by-step of such an app going fullscreen: - * 1. App changes monitor resolution with randr. - * 2. Xwayland sets the _XWAYLAND_RANDR_EMU_MONITOR_RECTS property on all the - * apps current and future windows. This property contains the origin of the - * monitor for which the emulated resolution is set and the emulated - * resolution. - * 3. App sets _NET_WM_FULLSCREEN. - * 4. We check the property and adjust the app's fullscreen size to match - * the emulated resolution. - * 5. Xwayland sees a Window at monitor origin fully covering the emulated - * monitor resolution. Xwayland sets a viewport making the emulated - * resolution sized window cover the full actual monitor resolution. - */ -static void -meta_window_xwayland_adjust_fullscreen_monitor_rect (MetaWindow *window, - MetaRectangle *fs_monitor_rect) -{ - MetaX11Display *x11_display = window->display->x11_display; - MetaRectangle win_monitor_rect; - cairo_rectangle_int_t *rects; - uint32_t *list = NULL; - int i, n_items = 0; - - if (!window->monitor) - { - g_warning ("MetaWindow does not have a monitor"); - return; - } - - win_monitor_rect = meta_logical_monitor_get_layout (window->monitor); - - if (!meta_prop_get_cardinal_list (x11_display, - window->xwindow, - x11_display->atom__XWAYLAND_RANDR_EMU_MONITOR_RECTS, - &list, &n_items)) - return; - - if (n_items % 4) - { - meta_verbose ("_XWAYLAND_RANDR_EMU_MONITOR_RECTS on %s has %d values which is not a multiple of 4", - window->desc, n_items); - g_free (list); - return; - } - - rects = (cairo_rectangle_int_t *) list; - n_items = n_items / 4; - for (i = 0; i < n_items; i++) - { - if (rects[i].x == win_monitor_rect.x && rects[i].y == win_monitor_rect.y) - { - fs_monitor_rect->width = rects[i].width; - fs_monitor_rect->height = rects[i].height; - break; - } - } - - g_free (list); -} - -static void -meta_window_xwayland_force_restore_shortcuts (MetaWindow *window, - ClutterInputDevice *source) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - - meta_wayland_compositor_restore_shortcuts (compositor, source); -} - -static gboolean -meta_window_xwayland_shortcuts_inhibited (MetaWindow *window, - ClutterInputDevice *source) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - - return meta_wayland_compositor_is_shortcuts_inhibited (compositor, source); -} - -static void -apply_allow_commits_x11_property (MetaWindowXwayland *xwayland_window, - gboolean allow_commits) -{ - MetaWindow *window = META_WINDOW (xwayland_window); - MetaDisplay *display = window->display; - MetaX11Display *x11_display = display->x11_display; - MetaFrame *frame; - Window xwin; - guint32 property[1]; - - if (!x11_display) - return; - - frame = meta_window_get_frame (window); - if (!frame) - xwin = window->xwindow; - else - xwin = meta_frame_get_xwindow (frame); - - if (!xwin) - return; - - property[0] = !!allow_commits; - - meta_x11_error_trap_push (x11_display); - XChangeProperty (x11_display->xdisplay, xwin, - x11_display->atom__XWAYLAND_ALLOW_COMMITS, - XA_CARDINAL, 32, PropModeReplace, - (guchar*) &property, 1); - meta_x11_error_trap_pop (x11_display); - XFlush (x11_display->xdisplay); -} - -static void -meta_window_xwayland_freeze_commits (MetaWindow *window) -{ - MetaWindowXwayland *xwayland_window = META_WINDOW_XWAYLAND (window); - - if (xwayland_window->freeze_count == 0) - apply_allow_commits_x11_property (xwayland_window, FALSE); - - xwayland_window->freeze_count++; -} - -static void -meta_window_xwayland_thaw_commits (MetaWindow *window) -{ - MetaWindowXwayland *xwayland_window = META_WINDOW_XWAYLAND (window); - - g_return_if_fail (xwayland_window->freeze_count > 0); - - xwayland_window->freeze_count--; - if (xwayland_window->freeze_count > 0) - return; - - apply_allow_commits_x11_property (xwayland_window, TRUE); -} - -static gboolean -meta_window_xwayland_always_update_shape (MetaWindow *window) -{ - /* - * On Xwayland, resizing a window will clear the corresponding Wayland - * buffer to plain solid black. - * - * Therefore, to address the black shadows which sometimes show during - * resize with Xwayland, we need to always update the window shape - * regardless of the actual frozen state of the window actor. - */ - - return TRUE; -} - -static void -meta_window_xwayland_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaWindowXwayland *window = META_WINDOW_XWAYLAND (object); - - switch (prop_id) - { - case PROP_XWAYLAND_MAY_GRAB_KEYBOARD: - g_value_set_boolean (value, window->xwayland_may_grab_keyboard); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_window_xwayland_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaWindowXwayland *window = META_WINDOW_XWAYLAND (object); - - switch (prop_id) - { - case PROP_XWAYLAND_MAY_GRAB_KEYBOARD: - window->xwayland_may_grab_keyboard = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_window_xwayland_class_init (MetaWindowXwaylandClass *klass) -{ - MetaWindowClass *window_class = META_WINDOW_CLASS (klass); - MetaWindowX11Class *window_x11_class = META_WINDOW_X11_CLASS (klass); - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - window_class->adjust_fullscreen_monitor_rect = meta_window_xwayland_adjust_fullscreen_monitor_rect; - window_class->force_restore_shortcuts = meta_window_xwayland_force_restore_shortcuts; - window_class->shortcuts_inhibited = meta_window_xwayland_shortcuts_inhibited; - - window_x11_class->freeze_commits = meta_window_xwayland_freeze_commits; - window_x11_class->thaw_commits = meta_window_xwayland_thaw_commits; - window_x11_class->always_update_shape = meta_window_xwayland_always_update_shape; - - gobject_class->get_property = meta_window_xwayland_get_property; - gobject_class->set_property = meta_window_xwayland_set_property; - - obj_props[PROP_XWAYLAND_MAY_GRAB_KEYBOARD] = - g_param_spec_boolean ("xwayland-may-grab-keyboard", - "Xwayland may use keyboard grabs", - "Whether the client may use Xwayland keyboard grabs on this window", - FALSE, - G_PARAM_READWRITE); - - g_object_class_install_properties (gobject_class, PROP_LAST, obj_props); -} diff --git a/src/wayland/meta-window-xwayland.h b/src/wayland/meta-window-xwayland.h deleted file mode 100644 index 5ea6041d4..000000000 --- a/src/wayland/meta-window-xwayland.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2017 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, see . - * - */ - -#ifndef META_WINDOW_XWAYLAND_H -#define META_WINDOW_XWAYLAND_H - -#include "meta/window.h" -#include "x11/window-x11.h" -#include "x11/window-x11-private.h" - -G_BEGIN_DECLS - -#define META_TYPE_WINDOW_XWAYLAND (meta_window_xwayland_get_type()) -G_DECLARE_FINAL_TYPE (MetaWindowXwayland, meta_window_xwayland, - META, WINDOW_XWAYLAND, MetaWindowX11) - -G_END_DECLS - -#endif diff --git a/src/wayland/meta-xwayland-dnd-private.h b/src/wayland/meta-xwayland-dnd-private.h deleted file mode 100644 index b55b4f8d3..000000000 --- a/src/wayland/meta-xwayland-dnd-private.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2015 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jonas Ådahl - */ - -#ifndef META_XWAYLAND_SELECTION_PRIVATE_H -#define META_XWAYLAND_SELECTION_PRIVATE_H - -#define META_TYPE_WAYLAND_DATA_SOURCE_XWAYLAND (meta_wayland_data_source_xwayland_get_type ()) -G_DECLARE_FINAL_TYPE (MetaWaylandDataSourceXWayland, - meta_wayland_data_source_xwayland, - META, WAYLAND_DATA_SOURCE_XWAYLAND, - MetaWaylandDataSource); - -#endif /* META_XWAYLAND_SELECTION_PRIVATE_H */ diff --git a/src/wayland/meta-xwayland-dnd.c b/src/wayland/meta-xwayland-dnd.c deleted file mode 100644 index a3148ed95..000000000 --- a/src/wayland/meta-xwayland-dnd.c +++ /dev/null @@ -1,991 +0,0 @@ -/* - * Copyright © 2012 Intel Corporation - * - * Permission to use, copy, modify, distribute, and sell this software and - * its documentation for any purpose is hereby granted without fee, provided - * that the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of the copyright holders not be used in - * advertising or publicity pertaining to distribution of the software - * without specific, written prior permission. The copyright holders make - * no representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF - * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* The file is loosely based on xwayland/selection.c from Weston */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "meta/meta-x11-errors.h" -#include "wayland/meta-wayland-data-device.h" -#include "wayland/meta-xwayland-private.h" -#include "wayland/meta-xwayland-dnd-private.h" -#include "wayland/meta-xwayland.h" -#include "x11/meta-x11-display-private.h" - -#define INCR_CHUNK_SIZE (128 * 1024) -#define XDND_VERSION 5 - -struct _MetaWaylandDataSourceXWayland -{ - MetaWaylandDataSource parent; - MetaXWaylandDnd *dnd; - gboolean has_utf8_string_atom; -}; - -struct _MetaXWaylandDnd -{ - Window owner; - Time client_message_timestamp; - MetaWaylandDataSource *source; /* owned by MetaWaylandDataDevice */ - MetaWaylandSurface *focus_surface; - Window dnd_window; /* Mutter-internal window, acts as peer on wayland drop sites */ - Window dnd_dest; /* X11 drag dest window */ - guint32 last_motion_time; -}; - -enum -{ - ATOM_DND_SELECTION, - ATOM_DND_AWARE, - ATOM_DND_STATUS, - ATOM_DND_POSITION, - ATOM_DND_ENTER, - ATOM_DND_LEAVE, - ATOM_DND_DROP, - ATOM_DND_FINISHED, - ATOM_DND_PROXY, - ATOM_DND_TYPE_LIST, - ATOM_DND_ACTION_MOVE, - ATOM_DND_ACTION_COPY, - ATOM_DND_ACTION_ASK, - ATOM_DND_ACTION_PRIVATE, - N_DND_ATOMS -}; - -/* Matches order in enum above */ -const gchar *atom_names[] = { - "XdndSelection", - "XdndAware", - "XdndStatus", - "XdndPosition", - "XdndEnter", - "XdndLeave", - "XdndDrop", - "XdndFinished", - "XdndProxy", - "XdndTypeList", - "XdndActionMove", - "XdndActionCopy", - "XdndActionAsk", - "XdndActionPrivate", - NULL -}; - -Atom xdnd_atoms[N_DND_ATOMS]; - -G_DEFINE_TYPE (MetaWaylandDataSourceXWayland, meta_wayland_data_source_xwayland, - META_TYPE_WAYLAND_DATA_SOURCE); - -/* XDND helpers */ -static Atom -action_to_atom (uint32_t action) -{ - if (action & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY) - return xdnd_atoms[ATOM_DND_ACTION_COPY]; - else if (action & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE) - return xdnd_atoms[ATOM_DND_ACTION_MOVE]; - else if (action & WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK) - return xdnd_atoms[ATOM_DND_ACTION_ASK]; - else - return None; -} - -static enum wl_data_device_manager_dnd_action -atom_to_action (Atom atom) -{ - if (atom == xdnd_atoms[ATOM_DND_ACTION_COPY] || - atom == xdnd_atoms[ATOM_DND_ACTION_PRIVATE]) - return WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY; - else if (atom == xdnd_atoms[ATOM_DND_ACTION_MOVE]) - return WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE; - else if (atom == xdnd_atoms[ATOM_DND_ACTION_ASK]) - return WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK; - else - return WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE; -} - -static void -xdnd_send_enter (MetaXWaylandDnd *dnd, - Window dest) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaX11Display *x11_display = meta_get_display ()->x11_display; - Display *xdisplay = x11_display->xdisplay; - MetaWaylandDataSource *data_source; - XEvent xev = { 0 }; - gchar **p; - struct wl_array *source_mime_types; - - meta_x11_error_trap_push (x11_display); - - data_source = compositor->seat->data_device.dnd_data_source; - xev.xclient.type = ClientMessage; - xev.xclient.message_type = xdnd_atoms[ATOM_DND_ENTER]; - xev.xclient.format = 32; - xev.xclient.window = dest; - - xev.xclient.data.l[0] = x11_display->selection.xwindow; - xev.xclient.data.l[1] = XDND_VERSION << 24; /* version */ - xev.xclient.data.l[2] = xev.xclient.data.l[3] = xev.xclient.data.l[4] = 0; - - source_mime_types = meta_wayland_data_source_get_mime_types (data_source); - if (source_mime_types->size <= 3) - { - /* The mimetype atoms fit in this same message */ - gint i = 2; - - wl_array_for_each (p, source_mime_types) - { - xev.xclient.data.l[i++] = gdk_x11_get_xatom_by_name (*p); - } - } - else - { - /* We have more than 3 mimetypes, we must set up - * the mimetype list as a XdndTypeList property. - */ - g_autofree Atom *atomlist = NULL; - gint i = 0; - - xev.xclient.data.l[1] |= 1; - atomlist = g_new0 (Atom, source_mime_types->size); - - wl_array_for_each (p, source_mime_types) - { - atomlist[i++] = gdk_x11_get_xatom_by_name (*p); - } - - XChangeProperty (xdisplay, x11_display->selection.xwindow, - xdnd_atoms[ATOM_DND_TYPE_LIST], - XA_ATOM, 32, PropModeReplace, - (guchar *) atomlist, i); - } - - XSendEvent (xdisplay, dest, False, NoEventMask, &xev); - - if (meta_x11_error_trap_pop_with_return (x11_display) != Success) - g_critical ("Error sending XdndEnter"); -} - -static void -xdnd_send_leave (MetaXWaylandDnd *dnd, - Window dest) -{ - MetaX11Display *x11_display = meta_get_display ()->x11_display; - Display *xdisplay = x11_display->xdisplay; - XEvent xev = { 0 }; - - xev.xclient.type = ClientMessage; - xev.xclient.message_type = xdnd_atoms[ATOM_DND_LEAVE]; - xev.xclient.format = 32; - xev.xclient.window = dest; - xev.xclient.data.l[0] = x11_display->selection.xwindow; - - meta_x11_error_trap_push (x11_display); - XSendEvent (xdisplay, dest, False, NoEventMask, &xev); - meta_x11_error_trap_pop (x11_display); -} - -static void -xdnd_send_position (MetaXWaylandDnd *dnd, - Window dest, - uint32_t time, - int x, - int y) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaWaylandDataSource *source = compositor->seat->data_device.dnd_data_source; - MetaX11Display *x11_display = meta_get_display ()->x11_display; - Display *xdisplay = x11_display->xdisplay; - uint32_t action = 0, user_action, actions; - XEvent xev = { 0 }; - - user_action = meta_wayland_data_source_get_user_action (source); - meta_wayland_data_source_get_actions (source, &actions); - - if (user_action & actions) - action = user_action; - if (!action) - action = actions; - - xev.xclient.type = ClientMessage; - xev.xclient.message_type = xdnd_atoms[ATOM_DND_POSITION]; - xev.xclient.format = 32; - xev.xclient.window = dest; - - xev.xclient.data.l[0] = x11_display->selection.xwindow; - xev.xclient.data.l[1] = 0; - xev.xclient.data.l[2] = (x << 16) | y; - xev.xclient.data.l[3] = time; - xev.xclient.data.l[4] = action_to_atom (action); - - meta_x11_error_trap_push (x11_display); - XSendEvent (xdisplay, dest, False, NoEventMask, &xev); - - if (meta_x11_error_trap_pop_with_return (x11_display) != Success) - g_critical ("Error sending XdndPosition"); -} - -static void -xdnd_send_drop (MetaXWaylandDnd *dnd, - Window dest, - uint32_t time) -{ - MetaX11Display *x11_display = meta_get_display ()->x11_display; - Display *xdisplay = x11_display->xdisplay; - XEvent xev = { 0 }; - - xev.xclient.type = ClientMessage; - xev.xclient.message_type = xdnd_atoms[ATOM_DND_DROP]; - xev.xclient.format = 32; - xev.xclient.window = dest; - - xev.xclient.data.l[0] = x11_display->selection.xwindow; - xev.xclient.data.l[2] = time; - - meta_x11_error_trap_push (x11_display); - XSendEvent (xdisplay, dest, False, NoEventMask, &xev); - - if (meta_x11_error_trap_pop_with_return (x11_display) != Success) - g_critical ("Error sending XdndDrop"); -} - -static void -xdnd_send_finished (MetaXWaylandDnd *dnd, - Window dest, - gboolean accepted) -{ - MetaX11Display *x11_display = meta_get_display ()->x11_display; - Display *xdisplay = x11_display->xdisplay; - MetaWaylandDataSource *source = dnd->source; - uint32_t action = 0; - XEvent xev = { 0 }; - - xev.xclient.type = ClientMessage; - xev.xclient.message_type = xdnd_atoms[ATOM_DND_FINISHED]; - xev.xclient.format = 32; - xev.xclient.window = dest; - - xev.xclient.data.l[0] = dnd->dnd_window; - - if (accepted) - { - action = meta_wayland_data_source_get_current_action (source); - xev.xclient.data.l[1] = 1; /* Drop successful */ - xev.xclient.data.l[2] = action_to_atom (action); - } - - meta_x11_error_trap_push (x11_display); - XSendEvent (xdisplay, dest, False, NoEventMask, &xev); - - if (meta_x11_error_trap_pop_with_return (x11_display) != Success) - g_critical ("Error sending XdndFinished"); -} - -static void -xdnd_send_status (MetaXWaylandDnd *dnd, - Window dest, - uint32_t action) -{ - MetaX11Display *x11_display = meta_get_display ()->x11_display; - Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); - XEvent xev = { 0 }; - - xev.xclient.type = ClientMessage; - xev.xclient.message_type = xdnd_atoms[ATOM_DND_STATUS]; - xev.xclient.format = 32; - xev.xclient.window = dest; - - xev.xclient.data.l[0] = dnd->dnd_window; - xev.xclient.data.l[1] = 1 << 1; /* Bit 2: dest wants XdndPosition messages */ - xev.xclient.data.l[4] = action_to_atom (action); - - if (xev.xclient.data.l[4]) - xev.xclient.data.l[1] |= 1 << 0; /* Bit 1: dest accepts the drop */ - - meta_x11_error_trap_push (x11_display); - XSendEvent (xdisplay, dest, False, NoEventMask, &xev); - - if (meta_x11_error_trap_pop_with_return (x11_display) != Success) - g_critical ("Error sending Xdndstatus"); -} - -static void -meta_xwayland_end_dnd_grab (MetaWaylandDataDevice *data_device, - gboolean success) -{ - Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaXWaylandManager *manager = &compositor->xwayland_manager; - MetaWaylandDragGrab *drag_grab = compositor->seat->data_device.current_grab; - MetaXWaylandDnd *dnd = manager->dnd; - - if (drag_grab) - { - if (!success && dnd->source) - meta_wayland_data_source_set_current_offer (dnd->source, NULL); - - meta_wayland_data_device_end_drag (data_device); - } - - XMoveResizeWindow (xdisplay, dnd->dnd_window, -1, -1, 1, 1); - XUnmapWindow (xdisplay, dnd->dnd_window); -} - -static void -transfer_cb (MetaSelection *selection, - GAsyncResult *res, - GOutputStream *stream) -{ - GError *error = NULL; - - if (!meta_selection_transfer_finish (selection, res, &error)) - { - g_warning ("Could not transfer DnD selection: %s", error->message); - g_error_free (error); - } - - g_output_stream_close (stream, NULL, NULL); - g_object_unref (stream); -} - -static void -meta_x11_source_send (MetaWaylandDataSource *source, - const gchar *mime_type, - gint fd) -{ - MetaDisplay *display = meta_get_display (); - GOutputStream *stream; - - stream = g_unix_output_stream_new (fd, TRUE); - meta_selection_transfer_async (meta_display_get_selection (display), - META_SELECTION_DND, - mime_type, - -1, - stream, - NULL, - (GAsyncReadyCallback) transfer_cb, - stream); -} - -static void -meta_x11_source_target (MetaWaylandDataSource *source, - const gchar *mime_type) -{ - MetaWaylandDataSourceXWayland *source_xwayland = - META_WAYLAND_DATA_SOURCE_XWAYLAND (source); - MetaXWaylandDnd *dnd = source_xwayland->dnd; - uint32_t action = 0; - - if (mime_type) - action = meta_wayland_data_source_get_current_action (source); - - xdnd_send_status (dnd, dnd->owner, action); -} - -static void -meta_x11_source_cancel (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourceXWayland *source_xwayland = - META_WAYLAND_DATA_SOURCE_XWAYLAND (source); - MetaXWaylandDnd *dnd = source_xwayland->dnd; - - xdnd_send_finished (dnd, dnd->owner, FALSE); -} - -static void -meta_x11_source_action (MetaWaylandDataSource *source, - uint32_t action) -{ - MetaWaylandDataSourceXWayland *source_xwayland = - META_WAYLAND_DATA_SOURCE_XWAYLAND (source); - MetaXWaylandDnd *dnd = source_xwayland->dnd; - - if (!meta_wayland_data_source_has_target (source)) - action = 0; - - xdnd_send_status (dnd, dnd->owner, action); -} - -static void -meta_x11_source_drop_performed (MetaWaylandDataSource *source) -{ -} - -static void -meta_x11_source_drag_finished (MetaWaylandDataSource *source) -{ - MetaWaylandDataSourceXWayland *source_xwayland = - META_WAYLAND_DATA_SOURCE_XWAYLAND (source); - MetaXWaylandDnd *dnd = source_xwayland->dnd; - MetaX11Display *x11_display = meta_get_display ()->x11_display; - uint32_t action = meta_wayland_data_source_get_current_action (source); - - if (action == WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE) - { - Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); - - /* Request data deletion on the drag source */ - XConvertSelection (xdisplay, - xdnd_atoms[ATOM_DND_SELECTION], - gdk_x11_get_xatom_by_name ("DELETE"), - gdk_x11_get_xatom_by_name ("_META_SELECTION"), - x11_display->selection.xwindow, - META_CURRENT_TIME); - } - - xdnd_send_finished (dnd, dnd->owner, TRUE); -} - -static void -meta_wayland_data_source_xwayland_init (MetaWaylandDataSourceXWayland *source_xwayland) -{ -} - -static void -meta_wayland_data_source_xwayland_class_init (MetaWaylandDataSourceXWaylandClass *klass) -{ - MetaWaylandDataSourceClass *data_source_class = - META_WAYLAND_DATA_SOURCE_CLASS (klass); - - data_source_class->send = meta_x11_source_send; - data_source_class->target = meta_x11_source_target; - data_source_class->cancel = meta_x11_source_cancel; - data_source_class->action = meta_x11_source_action; - data_source_class->drop_performed = meta_x11_source_drop_performed; - data_source_class->drag_finished = meta_x11_source_drag_finished; -} - -static MetaWaylandDataSource * -meta_wayland_data_source_xwayland_new (MetaXWaylandDnd *dnd) -{ - MetaWaylandDataSourceXWayland *source_xwayland; - - source_xwayland = g_object_new (META_TYPE_WAYLAND_DATA_SOURCE_XWAYLAND, NULL); - source_xwayland->dnd = dnd; - - return META_WAYLAND_DATA_SOURCE (source_xwayland); -} - -static void -meta_x11_drag_dest_focus_in (MetaWaylandDataDevice *data_device, - MetaWaylandSurface *surface, - MetaWaylandDataOffer *offer) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaXWaylandDnd *dnd = compositor->xwayland_manager.dnd; - - dnd->dnd_dest = meta_wayland_surface_get_window (surface)->xwindow; - xdnd_send_enter (dnd, dnd->dnd_dest); -} - -static void -meta_x11_drag_dest_focus_out (MetaWaylandDataDevice *data_device, - MetaWaylandSurface *surface) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaXWaylandDnd *dnd = compositor->xwayland_manager.dnd; - - xdnd_send_leave (dnd, dnd->dnd_dest); - dnd->dnd_dest = None; -} - -static void -meta_x11_drag_dest_motion (MetaWaylandDataDevice *data_device, - MetaWaylandSurface *surface, - const ClutterEvent *event) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaXWaylandDnd *dnd = compositor->xwayland_manager.dnd; - guint32 time; - gfloat x, y; - - time = clutter_event_get_time (event); - clutter_event_get_coords (event, &x, &y); - xdnd_send_position (dnd, dnd->dnd_dest, time, x, y); -} - -static void -meta_x11_drag_dest_drop (MetaWaylandDataDevice *data_device, - MetaWaylandSurface *surface) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaXWaylandDnd *dnd = compositor->xwayland_manager.dnd; - - xdnd_send_drop (dnd, dnd->dnd_dest, - meta_display_get_current_time_roundtrip (meta_get_display ())); -} - -static void -meta_x11_drag_dest_update (MetaWaylandDataDevice *data_device, - MetaWaylandSurface *surface) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaXWaylandDnd *dnd = compositor->xwayland_manager.dnd; - MetaWaylandSeat *seat = compositor->seat; - graphene_point_t pos; - - clutter_seat_query_state (clutter_input_device_get_seat (seat->pointer->device), - seat->pointer->device, NULL, &pos, NULL); - xdnd_send_position (dnd, dnd->dnd_dest, - clutter_get_current_event_time (), - pos.x, pos.y); -} - -static const MetaWaylandDragDestFuncs meta_x11_drag_dest_funcs = { - meta_x11_drag_dest_focus_in, - meta_x11_drag_dest_focus_out, - meta_x11_drag_dest_motion, - meta_x11_drag_dest_drop, - meta_x11_drag_dest_update -}; - -const MetaWaylandDragDestFuncs * -meta_xwayland_selection_get_drag_dest_funcs (void) -{ - return &meta_x11_drag_dest_funcs; -} - -static gboolean -meta_xwayland_data_source_fetch_mimetype_list (MetaWaylandDataSource *source, - Window window, - Atom prop) -{ - MetaWaylandDataSourceXWayland *source_xwayland = - META_WAYLAND_DATA_SOURCE_XWAYLAND (source); - Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); - gulong nitems_ret, bytes_after_ret, i; - Atom *atoms, type_ret, utf8_string; - int format_ret; - struct wl_array *source_mime_types; - - source_mime_types = meta_wayland_data_source_get_mime_types (source); - if (source_mime_types->size != 0) - return TRUE; - - utf8_string = gdk_x11_get_xatom_by_name ("UTF8_STRING"); - XGetWindowProperty (xdisplay, window, prop, - 0, /* offset */ - 0x1fffffff, /* length */ - False, /* delete */ - AnyPropertyType, - &type_ret, - &format_ret, - &nitems_ret, - &bytes_after_ret, - (guchar **) &atoms); - - if (nitems_ret == 0 || type_ret != XA_ATOM) - { - XFree (atoms); - return FALSE; - } - - for (i = 0; i < nitems_ret; i++) - { - const gchar *mime_type; - - if (atoms[i] == utf8_string) - { - meta_wayland_data_source_add_mime_type (source, - "text/plain;charset=utf-8"); - source_xwayland->has_utf8_string_atom = TRUE; - } - - mime_type = gdk_x11_get_xatom_name (atoms[i]); - meta_wayland_data_source_add_mime_type (source, mime_type); - } - - XFree (atoms); - - return TRUE; -} - -static MetaWaylandSurface * -pick_drop_surface (MetaWaylandCompositor *compositor, - const ClutterEvent *event) -{ - MetaDisplay *display = meta_get_display (); - MetaWindow *focus_window = NULL; - graphene_point_t pos; - - clutter_event_get_coords (event, &pos.x, &pos.y); - focus_window = meta_stack_get_default_focus_window_at_point (display->stack, - NULL, NULL, - pos.x, pos.y); - return focus_window ? focus_window->surface : NULL; -} - -static void -repick_drop_surface (MetaWaylandCompositor *compositor, - MetaWaylandDragGrab *drag_grab, - const ClutterEvent *event) -{ - Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); - MetaXWaylandDnd *dnd = compositor->xwayland_manager.dnd; - MetaWaylandSurface *focus = NULL; - MetaWindow *focus_window; - - focus = pick_drop_surface (compositor, event); - if (dnd->focus_surface == focus) - return; - - dnd->focus_surface = focus; - - if (focus) - focus_window = meta_wayland_surface_get_window (focus); - else - focus_window = NULL; - - if (focus_window && - focus_window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND) - { - XMapRaised (xdisplay, dnd->dnd_window); - XMoveResizeWindow (xdisplay, dnd->dnd_window, - focus_window->rect.x, - focus_window->rect.y, - focus_window->rect.width, - focus_window->rect.height); - } - else - { - XMoveResizeWindow (xdisplay, dnd->dnd_window, -1, -1, 1, 1); - XUnmapWindow (xdisplay, dnd->dnd_window); - } -} - -static void -drag_xgrab_focus (MetaWaylandPointerGrab *grab, - MetaWaylandSurface *surface) -{ - /* Do not update the focus here. First, the surface may perfectly - * be the X11 source DnD icon window's, so we can only be fooled - * here. Second, delaying focus handling to XdndEnter/Leave - * makes us do the negotiation orderly on the X11 side. - */ -} - -static void -drag_xgrab_motion (MetaWaylandPointerGrab *grab, - const ClutterEvent *event) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaXWaylandDnd *dnd = compositor->xwayland_manager.dnd; - MetaWaylandSeat *seat = compositor->seat; - - repick_drop_surface (compositor, - (MetaWaylandDragGrab *) grab, - event); - - dnd->last_motion_time = clutter_event_get_time (event); - meta_wayland_pointer_send_motion (seat->pointer, event); -} - -static void -drag_xgrab_button (MetaWaylandPointerGrab *grab, - const ClutterEvent *event) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaWaylandSeat *seat = compositor->seat; - MetaWaylandDataSource *data_source; - - meta_wayland_pointer_send_button (seat->pointer, event); - data_source = compositor->seat->data_device.dnd_data_source; - - if (seat->pointer->button_count == 0 && - (!meta_wayland_drag_grab_get_focus ((MetaWaylandDragGrab *) grab) || - meta_wayland_data_source_get_current_action (data_source) == - WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE)) - meta_xwayland_end_dnd_grab (&seat->data_device, FALSE); -} - -static const MetaWaylandPointerGrabInterface drag_xgrab_interface = { - drag_xgrab_focus, - drag_xgrab_motion, - drag_xgrab_button, -}; - -static gboolean -meta_xwayland_dnd_handle_client_message (MetaWaylandCompositor *compositor, - XEvent *xevent) -{ - XClientMessageEvent *event = (XClientMessageEvent *) xevent; - MetaXWaylandDnd *dnd = compositor->xwayland_manager.dnd; - MetaWaylandSeat *seat = compositor->seat; - MetaX11Display *x11_display = meta_get_display ()->x11_display; - - /* Source side messages */ - if (event->window == x11_display->selection.xwindow) - { - MetaWaylandDataSource *data_source; - uint32_t action = 0; - - data_source = compositor->seat->data_device.dnd_data_source; - - if (!data_source) - return FALSE; - - if (event->message_type == xdnd_atoms[ATOM_DND_STATUS]) - { - /* The first bit in data.l[1] is set if the drag was accepted */ - meta_wayland_data_source_set_has_target (data_source, - (event->data.l[1] & 1) != 0); - - /* data.l[4] contains the action atom */ - if (event->data.l[4]) - action = atom_to_action ((Atom) event->data.l[4]); - - meta_wayland_data_source_set_current_action (data_source, action); - return TRUE; - } - else if (event->message_type == xdnd_atoms[ATOM_DND_FINISHED]) - { - /* Reject messages mid-grab */ - if (compositor->seat->data_device.current_grab) - return FALSE; - - meta_wayland_data_source_notify_finish (data_source); - return TRUE; - } - } - /* Dest side messages */ - else if (dnd->source && - compositor->seat->data_device.current_grab && - (Window) event->data.l[0] == dnd->owner) - { - MetaWaylandDragGrab *drag_grab = compositor->seat->data_device.current_grab; - MetaWaylandSurface *drag_focus = meta_wayland_drag_grab_get_focus (drag_grab); - - if (!drag_focus && - event->message_type != xdnd_atoms[ATOM_DND_ENTER]) - return FALSE; - - if (event->message_type == xdnd_atoms[ATOM_DND_ENTER]) - { - /* Bit 1 in data.l[1] determines whether there's 3 or less mimetype - * atoms (and are thus contained in this same message), or whether - * there's more than 3 and we need to check the XdndTypeList property - * for the full list. - */ - if (!(event->data.l[1] & 1)) - { - /* Mimetypes are contained in this message */ - const gchar *mimetype; - gint i; - struct wl_array *source_mime_types; - - /* We only need to fetch once */ - source_mime_types = - meta_wayland_data_source_get_mime_types (dnd->source); - if (source_mime_types->size == 0) - { - for (i = 2; i <= 4; i++) - { - if (event->data.l[i] == None) - break; - - mimetype = gdk_x11_get_xatom_name (event->data.l[i]); - meta_wayland_data_source_add_mime_type (dnd->source, - mimetype); - } - } - } - else - { - /* Fetch mimetypes from type list */ - meta_xwayland_data_source_fetch_mimetype_list (dnd->source, - event->data.l[0], - xdnd_atoms[ATOM_DND_TYPE_LIST]); - } - - meta_wayland_data_source_set_actions (dnd->source, - WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | - WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE | - WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK); - meta_wayland_drag_grab_set_focus (drag_grab, dnd->focus_surface); - return TRUE; - } - else if (event->message_type == xdnd_atoms[ATOM_DND_POSITION]) - { - ClutterEvent *motion; - graphene_point_t pos; - uint32_t action = 0; - - dnd->client_message_timestamp = event->data.l[3]; - - motion = clutter_event_new (CLUTTER_MOTION); - clutter_seat_query_state (clutter_input_device_get_seat (seat->pointer->device), - seat->pointer->device, NULL, &pos, NULL); - clutter_event_set_coords (motion, pos.x, pos.y); - clutter_event_set_device (motion, seat->pointer->device); - clutter_event_set_source_device (motion, seat->pointer->device); - clutter_event_set_time (motion, dnd->last_motion_time); - - action = atom_to_action ((Atom) event->data.l[4]); - meta_wayland_data_source_set_user_action (dnd->source, action); - - meta_wayland_surface_drag_dest_motion (drag_focus, motion); - xdnd_send_status (dnd, (Window) event->data.l[0], - meta_wayland_data_source_get_current_action (dnd->source)); - - clutter_event_free (motion); - return TRUE; - } - else if (event->message_type == xdnd_atoms[ATOM_DND_LEAVE]) - { - meta_wayland_drag_grab_set_focus (drag_grab, NULL); - return TRUE; - } - else if (event->message_type == xdnd_atoms[ATOM_DND_DROP]) - { - dnd->client_message_timestamp = event->data.l[2]; - meta_wayland_surface_drag_dest_drop (drag_focus); - meta_xwayland_end_dnd_grab (&seat->data_device, TRUE); - return TRUE; - } - } - - return FALSE; -} - -static gboolean -meta_xwayland_dnd_handle_xfixes_selection_notify (MetaWaylandCompositor *compositor, - XEvent *xevent) -{ - XFixesSelectionNotifyEvent *event = (XFixesSelectionNotifyEvent *) xevent; - MetaXWaylandDnd *dnd = compositor->xwayland_manager.dnd; - MetaWaylandDataDevice *data_device = &compositor->seat->data_device; - MetaX11Display *x11_display = meta_get_display ()->x11_display; - MetaWaylandSurface *focus; - - if (event->selection != xdnd_atoms[ATOM_DND_SELECTION]) - return FALSE; - - dnd->owner = event->owner; - focus = compositor->seat->pointer->focus_surface; - - if (event->owner != None && event->owner != x11_display->selection.xwindow && - focus && meta_xwayland_is_xwayland_surface (focus)) - { - dnd->source = meta_wayland_data_source_xwayland_new (dnd); - meta_wayland_data_device_set_dnd_source (&compositor->seat->data_device, - dnd->source); - - meta_wayland_data_device_start_drag (data_device, - wl_resource_get_client (focus->resource), - &drag_xgrab_interface, - focus, dnd->source, - NULL); - } - else if (event->owner == None) - { - meta_xwayland_end_dnd_grab (data_device, FALSE); - g_clear_object (&dnd->source); - } - - return FALSE; -} - -gboolean -meta_xwayland_dnd_handle_event (XEvent *xevent) -{ - MetaWaylandCompositor *compositor; - - compositor = meta_wayland_compositor_get_default (); - - if (!compositor->xwayland_manager.dnd) - return FALSE; - - switch (xevent->type) - { - case ClientMessage: - return meta_xwayland_dnd_handle_client_message (compositor, xevent); - default: - { - MetaX11Display *x11_display = meta_get_display ()->x11_display; - - if (xevent->type - x11_display->xfixes_event_base == XFixesSelectionNotify) - return meta_xwayland_dnd_handle_xfixes_selection_notify (compositor, xevent); - - return FALSE; - } - } -} - -void -meta_xwayland_init_dnd (Display *xdisplay) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaXWaylandManager *manager = &compositor->xwayland_manager; - MetaXWaylandDnd *dnd = manager->dnd; - XSetWindowAttributes attributes; - guint32 i, version = XDND_VERSION; - - g_assert (manager->dnd == NULL); - - manager->dnd = dnd = g_new0 (MetaXWaylandDnd, 1); - - for (i = 0; i < N_DND_ATOMS; i++) - xdnd_atoms[i] = gdk_x11_get_xatom_by_name (atom_names[i]); - - attributes.event_mask = PropertyChangeMask | SubstructureNotifyMask; - attributes.override_redirect = True; - - dnd->dnd_window = XCreateWindow (xdisplay, - gdk_x11_window_get_xid (gdk_get_default_root_window ()), - -1, -1, 1, 1, - 0, /* border width */ - 0, /* depth */ - InputOnly, /* class */ - CopyFromParent, /* visual */ - CWEventMask | CWOverrideRedirect, - &attributes); - XChangeProperty (xdisplay, dnd->dnd_window, - xdnd_atoms[ATOM_DND_AWARE], - XA_ATOM, 32, PropModeReplace, - (guchar*) &version, 1); -} - -void -meta_xwayland_shutdown_dnd (MetaXWaylandManager *manager, - Display *xdisplay) -{ - MetaXWaylandDnd *dnd = manager->dnd; - - g_assert (dnd != NULL); - - XDestroyWindow (xdisplay, dnd->dnd_window); - dnd->dnd_window = None; - - g_free (dnd); - manager->dnd = NULL; -} diff --git a/src/wayland/meta-xwayland-grab-keyboard.c b/src/wayland/meta-xwayland-grab-keyboard.c deleted file mode 100644 index 66c80d809..000000000 --- a/src/wayland/meta-xwayland-grab-keyboard.c +++ /dev/null @@ -1,346 +0,0 @@ -/* - * Copyright (C) 2017 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Olivier Fourdan - */ - -#include "config.h" - -#include - -#include "meta/meta-backend.h" -#include "backends/meta-settings-private.h" -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-wayland-versions.h" -#include "wayland/meta-wayland-seat.h" -#include "wayland/meta-window-wayland.h" -#include "wayland/meta-xwayland-grab-keyboard.h" - -struct _MetaXwaylandKeyboardActiveGrab -{ - MetaWaylandSurface *surface; - MetaWaylandSeat *seat; - MetaWaylandKeyboardGrab keyboard_grab; - gulong surface_destroyed_handler; - gulong shortcuts_restored_handler; - gulong window_associate_handler; - struct wl_resource *resource; -}; - -static gboolean -meta_xwayland_keyboard_grab_key (MetaWaylandKeyboardGrab *grab, - const ClutterEvent *event) -{ - MetaXwaylandKeyboardActiveGrab *active_grab; - MetaWaylandKeyboard *keyboard; - - active_grab = wl_container_of (grab, active_grab, keyboard_grab); - keyboard = active_grab->keyboard_grab.keyboard; - - /* Force focus onto the surface who has the active grab on the keyboard */ - if (active_grab->surface != NULL && keyboard->focus_surface != active_grab->surface) - meta_wayland_keyboard_set_focus (keyboard, active_grab->surface); - - /* Chain-up with default keyboard handler */ - return keyboard->default_grab.interface->key (&keyboard->default_grab, event); -} - -static void -meta_xwayland_keyboard_grab_modifiers (MetaWaylandKeyboardGrab *grab, - ClutterModifierType modifiers) -{ - MetaXwaylandKeyboardActiveGrab *active_grab; - MetaWaylandKeyboard *keyboard; - - active_grab = wl_container_of (grab, active_grab, keyboard_grab); - keyboard = active_grab->keyboard_grab.keyboard; - - /* Force focus onto the surface who has the active grab on the keyboard */ - if (active_grab->surface != NULL && keyboard->focus_surface != active_grab->surface) - meta_wayland_keyboard_set_focus (keyboard, active_grab->surface); - - /* Chain-up with default keyboard handler */ - return keyboard->default_grab.interface->modifiers (&keyboard->default_grab, - modifiers); -} - -static void -meta_xwayland_keyboard_grab_end (MetaXwaylandKeyboardActiveGrab *active_grab) -{ - MetaWaylandSeat *seat = active_grab->seat; - - if (seat->keyboard->grab->interface->key == meta_xwayland_keyboard_grab_key) - { - meta_wayland_keyboard_end_grab (active_grab->keyboard_grab.keyboard); - meta_wayland_keyboard_set_focus (active_grab->keyboard_grab.keyboard, NULL); - meta_display_sync_wayland_input_focus (meta_get_display ()); - } - - if (!active_grab->surface) - return; - - g_clear_signal_handler (&active_grab->surface_destroyed_handler, - active_grab->surface); - - g_clear_signal_handler (&active_grab->shortcuts_restored_handler, - active_grab->surface); - - meta_wayland_surface_restore_shortcuts (active_grab->surface, - active_grab->seat); - - g_clear_signal_handler (&active_grab->window_associate_handler, - active_grab->surface->role); - - active_grab->surface = NULL; -} - -static const MetaWaylandKeyboardGrabInterface - keyboard_grab_interface = { - meta_xwayland_keyboard_grab_key, - meta_xwayland_keyboard_grab_modifiers - }; - -static void -zwp_xwayland_keyboard_grab_destructor (struct wl_resource *resource) -{ - MetaXwaylandKeyboardActiveGrab *active_grab; - - active_grab = wl_resource_get_user_data (resource); - meta_xwayland_keyboard_grab_end (active_grab); - - g_free (active_grab); -} - -static void -zwp_xwayland_keyboard_grab_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static const struct zwp_xwayland_keyboard_grab_v1_interface - xwayland_keyboard_grab_interface = { - zwp_xwayland_keyboard_grab_destroy, - }; - -static void -surface_destroyed_cb (MetaWaylandSurface *surface, - MetaXwaylandKeyboardActiveGrab *active_grab) -{ - active_grab->surface = NULL; -} - -static void -shortcuts_restored_cb (MetaWaylandSurface *surface, - MetaXwaylandKeyboardActiveGrab *active_grab) -{ - meta_xwayland_keyboard_grab_end (active_grab); -} - -static void -zwp_xwayland_keyboard_grab_manager_destroy (struct wl_client *client, - struct wl_resource *resource) -{ - wl_resource_destroy (resource); -} - -static gboolean -application_is_in_pattern_array (MetaWindow *window, - GPtrArray *pattern_array) -{ - const char *class; - const char *name; - guint i; - - if (window->res_class) - class = window->res_class; - else - class = ""; - - if (window->res_name) - name = window->res_name; - else - name = ""; - - for (i = 0; pattern_array && i < pattern_array->len; i++) - { - GPatternSpec *pattern = (GPatternSpec *) g_ptr_array_index (pattern_array, i); - - if (g_pattern_match_string (pattern, class) || - g_pattern_match_string (pattern, name)) - return TRUE; - } - - return FALSE; -} - -static gboolean -meta_xwayland_grab_is_granted (MetaWindow *window) -{ - MetaBackend *backend; - MetaSettings *settings; - GPtrArray *allow_list; - GPtrArray *deny_list; - gboolean may_grab; - - backend = meta_get_backend (); - settings = meta_backend_get_settings (backend); - - /* Check whether the window is in the deny list */ - meta_settings_get_xwayland_grab_patterns (settings, &allow_list, &deny_list); - - if (deny_list && application_is_in_pattern_array (window, deny_list)) - return FALSE; - - /* Check if we are dealing with good citizen Xwayland client allowing itself. */ - g_object_get (G_OBJECT (window), "xwayland-may-grab-keyboard", &may_grab, NULL); - if (may_grab) - return TRUE; - - /* Last resort, is it in the grant list. */ - if (allow_list && application_is_in_pattern_array (window, allow_list)) - return TRUE; - - return FALSE; -} - -static gboolean -meta_xwayland_grab_should_lock_focus (MetaWindow *window) -{ - MetaBackend *backend; - MetaSettings *settings; - - /* Lock focus applies to O-R windows which never receive keyboard focus otherwise */ - if (!window->override_redirect) - return FALSE; - - backend = meta_get_backend (); - settings = meta_backend_get_settings (backend); - - return meta_settings_are_xwayland_grabs_allowed (settings); -} - -static void -meta_xwayland_keyboard_grab_activate (MetaXwaylandKeyboardActiveGrab *active_grab) -{ - MetaWaylandSurface *surface = active_grab->surface; - MetaWindow *window = meta_wayland_surface_get_window (surface); - MetaWaylandSeat *seat = active_grab->seat; - - if (meta_xwayland_grab_is_granted (window)) - { - meta_verbose ("XWayland window %s has a grab granted", window->desc); - meta_wayland_surface_inhibit_shortcuts (surface, seat); - - if (meta_xwayland_grab_should_lock_focus (window)) - meta_wayland_keyboard_start_grab (seat->keyboard, &active_grab->keyboard_grab); - } - - g_clear_signal_handler (&active_grab->window_associate_handler, - active_grab->surface->role); -} - -static void -meta_xwayland_keyboard_window_associated (MetaWaylandSurfaceRole *surface_role, - MetaXwaylandKeyboardActiveGrab *active_grab) -{ - meta_xwayland_keyboard_grab_activate (active_grab); -} - -static void -zwp_xwayland_keyboard_grab_manager_grab (struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *surface_resource, - struct wl_resource *seat_resource) -{ - MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource); - MetaWindow *window = meta_wayland_surface_get_window (surface); - MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource); - MetaXwaylandKeyboardActiveGrab *active_grab; - struct wl_resource *grab_resource; - - grab_resource = wl_resource_create (client, - &zwp_xwayland_keyboard_grab_manager_v1_interface, - wl_resource_get_version (resource), - id); - - active_grab = g_new0 (MetaXwaylandKeyboardActiveGrab, 1); - active_grab->surface = surface; - active_grab->resource = grab_resource; - active_grab->seat = seat; - active_grab->keyboard_grab.interface = &keyboard_grab_interface; - active_grab->surface_destroyed_handler = - g_signal_connect (surface, "destroy", - G_CALLBACK (surface_destroyed_cb), - active_grab); - active_grab->shortcuts_restored_handler = - g_signal_connect (surface, "shortcuts-restored", - G_CALLBACK (shortcuts_restored_cb), - active_grab); - - if (window) - meta_xwayland_keyboard_grab_activate (active_grab); - else if (surface->role) - active_grab->window_associate_handler = - g_signal_connect (surface->role, "window-associated", - G_CALLBACK (meta_xwayland_keyboard_window_associated), - active_grab); - else - g_warning ("Cannot grant Xwayland grab to surface %p", surface); - - wl_resource_set_implementation (grab_resource, - &xwayland_keyboard_grab_interface, - active_grab, - zwp_xwayland_keyboard_grab_destructor); -} - -static const struct zwp_xwayland_keyboard_grab_manager_v1_interface - meta_keyboard_grab_manager_interface = { - zwp_xwayland_keyboard_grab_manager_destroy, - zwp_xwayland_keyboard_grab_manager_grab, - }; - -static void -bind_keyboard_grab (struct wl_client *client, - void *data, - uint32_t version, - uint32_t id) -{ - struct wl_resource *resource; - - resource = wl_resource_create (client, - &zwp_xwayland_keyboard_grab_manager_v1_interface, - MIN (META_ZWP_XWAYLAND_KEYBOARD_GRAB_V1_VERSION, version), - id); - - wl_resource_set_implementation (resource, - &meta_keyboard_grab_manager_interface, - NULL, NULL); -} - -gboolean -meta_xwayland_grab_keyboard_init (MetaWaylandCompositor *compositor) -{ - return (wl_global_create (compositor->wayland_display, - &zwp_xwayland_keyboard_grab_manager_v1_interface, - META_ZWP_XWAYLAND_KEYBOARD_GRAB_V1_VERSION, - NULL, - bind_keyboard_grab) != NULL); -} diff --git a/src/wayland/meta-xwayland-grab-keyboard.h b/src/wayland/meta-xwayland-grab-keyboard.h deleted file mode 100644 index 597854af5..000000000 --- a/src/wayland/meta-xwayland-grab-keyboard.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2017 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Olivier Fourdan - */ - -#ifndef META_XWAYLAND_GRAB_KEYBOARD_H -#define META_XWAYLAND_GRAB_KEYBOARD_H - -#include - -#include "wayland/meta-wayland-types.h" -#include "meta/window.h" - -#include "xwayland-keyboard-grab-unstable-v1-server-protocol.h" - -#define META_TYPE_XWAYLAND_KEYBOARD_ACTIVE_GRAB (meta_xwayland_keyboard_active_grab_get_type ()) -G_DECLARE_FINAL_TYPE (MetaXwaylandKeyboardActiveGrab, - meta_xwayland_keyboard_active_grab, - META, XWAYLAND_KEYBOARD_ACTIVE_GRAB, - GObject); - -gboolean meta_xwayland_grab_keyboard_init (MetaWaylandCompositor *compositor); - -#endif /* META_XWAYLAND_GRAB_KEYBOARD_H */ diff --git a/src/wayland/meta-xwayland-private.h b/src/wayland/meta-xwayland-private.h deleted file mode 100644 index 51fba035e..000000000 --- a/src/wayland/meta-xwayland-private.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2013 Intel Corporation - * - * 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_XWAYLAND_PRIVATE_H -#define META_XWAYLAND_PRIVATE_H - -#include - -#include "wayland/meta-wayland-private.h" - -gboolean -meta_xwayland_init (MetaXWaylandManager *manager, - MetaWaylandCompositor *compositor, - struct wl_display *display, - GError **error); - -void -meta_xwayland_complete_init (MetaDisplay *display, - Display *xdisplay); - -void -meta_xwayland_shutdown (MetaXWaylandManager *manager); - -gboolean -meta_xwayland_handle_xevent (XEvent *event); - -/* wl_data_device/X11 selection interoperation */ -void meta_xwayland_init_dnd (Display *xdisplay); -void meta_xwayland_shutdown_dnd (MetaXWaylandManager *manager, - Display *xdisplay); -gboolean meta_xwayland_dnd_handle_event (XEvent *xevent); - -const MetaWaylandDragDestFuncs * meta_xwayland_selection_get_drag_dest_funcs (void); - -void meta_xwayland_start_xserver (MetaXWaylandManager *manager, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean meta_xwayland_start_xserver_finish (MetaXWaylandManager *manager, - GAsyncResult *result, - GError **error); - -#endif /* META_XWAYLAND_PRIVATE_H */ diff --git a/src/wayland/meta-xwayland-surface.c b/src/wayland/meta-xwayland-surface.c deleted file mode 100644 index 4697c9d21..000000000 --- a/src/wayland/meta-xwayland-surface.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (C) 2013 Intel Corporation - * Copyright (C) 2013-2019 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#include "config.h" - -#include "wayland/meta-xwayland-surface.h" - -#include "compositor/meta-surface-actor-wayland.h" -#include "compositor/meta-window-actor-private.h" -#include "wayland/meta-wayland-actor-surface.h" -#include "wayland/meta-xwayland-private.h" - -enum -{ - WINDOW_ASSOCIATED, - - N_SIGNALS -}; - -static guint signals[N_SIGNALS]; - -struct _MetaXwaylandSurface -{ - MetaWaylandActorSurface parent; - - MetaWindow *window; - - gulong unmanaging_handler_id; -}; - -G_DEFINE_TYPE (MetaXwaylandSurface, - meta_xwayland_surface, - META_TYPE_WAYLAND_ACTOR_SURFACE) - -static void -clear_window (MetaXwaylandSurface *xwayland_surface) -{ - MetaWaylandSurfaceRole *surface_role = - META_WAYLAND_SURFACE_ROLE (xwayland_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaSurfaceActor *surface_actor; - - if (!xwayland_surface->window) - return; - - g_clear_signal_handler (&xwayland_surface->unmanaging_handler_id, - xwayland_surface->window); - - xwayland_surface->window->surface = NULL; - xwayland_surface->window = NULL; - - surface_actor = meta_wayland_surface_get_actor (surface); - if (surface_actor) - clutter_actor_set_reactive (CLUTTER_ACTOR (surface_actor), FALSE); - - meta_wayland_surface_notify_unmapped (surface); -} - -static void -window_unmanaging (MetaWindow *window, - MetaXwaylandSurface *xwayland_surface) -{ - clear_window (xwayland_surface); -} - -void -meta_xwayland_surface_associate_with_window (MetaXwaylandSurface *xwayland_surface, - MetaWindow *window) -{ - MetaWaylandSurfaceRole *surface_role = - META_WAYLAND_SURFACE_ROLE (xwayland_surface); - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaSurfaceActor *surface_actor; - MetaWindowActor *window_actor; - - /* - * If the window has an existing surface, like if we're undecorating or - * decorating the window, then we need to detach the window from its old - * surface. - */ - if (window->surface) - { - MetaXwaylandSurface *other_xwayland_surface; - - other_xwayland_surface = META_XWAYLAND_SURFACE (window->surface->role); - clear_window (other_xwayland_surface); - } - - window->surface = surface; - xwayland_surface->window = window; - - surface_actor = meta_wayland_surface_get_actor (surface); - if (surface_actor) - clutter_actor_set_reactive (CLUTTER_ACTOR (surface_actor), TRUE); - - xwayland_surface->unmanaging_handler_id = - g_signal_connect (window, - "unmanaging", - G_CALLBACK (window_unmanaging), - xwayland_surface); - - g_signal_emit (xwayland_surface, signals[WINDOW_ASSOCIATED], 0); - - window_actor = meta_window_actor_from_window (window); - if (window_actor) - meta_window_actor_assign_surface_actor (window_actor, surface_actor); -} - -static void -meta_xwayland_surface_assigned (MetaWaylandSurfaceRole *surface_role) -{ - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaWaylandSurfaceRoleClass *surface_role_class = - META_WAYLAND_SURFACE_ROLE_CLASS (meta_xwayland_surface_parent_class); - - surface->dnd.funcs = meta_xwayland_selection_get_drag_dest_funcs (); - - surface_role_class->assigned (surface_role); -} - -static void -meta_xwayland_surface_pre_apply_state (MetaWaylandSurfaceRole *surface_role, - MetaWaylandSurfaceState *pending) -{ - MetaWaylandSurface *surface = - meta_wayland_surface_role_get_surface (surface_role); - MetaXwaylandSurface *xwayland_surface = META_XWAYLAND_SURFACE (surface_role); - - if (pending->newly_attached && - surface->buffer_ref->buffer && - xwayland_surface->window) - meta_window_queue (xwayland_surface->window, META_QUEUE_CALC_SHOWING); -} - -static void -meta_xwayland_surface_get_relative_coordinates (MetaWaylandSurfaceRole *surface_role, - float abs_x, - float abs_y, - float *out_sx, - float *out_sy) -{ - MetaXwaylandSurface *xwayland_surface = META_XWAYLAND_SURFACE (surface_role); - MetaRectangle window_rect = { 0 }; - - if (xwayland_surface->window) - meta_window_get_buffer_rect (xwayland_surface->window, &window_rect); - - *out_sx = abs_x - window_rect.x; - *out_sy = abs_y - window_rect.y; -} - -static MetaWaylandSurface * -meta_xwayland_surface_get_toplevel (MetaWaylandSurfaceRole *surface_role) -{ - return meta_wayland_surface_role_get_surface (surface_role); -} - -static MetaWindow * -meta_xwayland_surface_get_window (MetaWaylandSurfaceRole *surface_role) -{ - MetaXwaylandSurface *xwayland_surface = META_XWAYLAND_SURFACE (surface_role); - - return xwayland_surface->window; -} - -static double -meta_xwayland_surface_get_geometry_scale (MetaWaylandActorSurface *actor_surface) -{ - return 1; -} - -static void -meta_xwayland_surface_sync_actor_state (MetaWaylandActorSurface *actor_surface) -{ - MetaXwaylandSurface *xwayland_surface = META_XWAYLAND_SURFACE (actor_surface); - MetaWaylandActorSurfaceClass *actor_surface_class = - META_WAYLAND_ACTOR_SURFACE_CLASS (meta_xwayland_surface_parent_class); - - if (xwayland_surface->window) - { - MetaWindowActor *window_actor = - meta_window_actor_from_window (xwayland_surface->window); - - actor_surface_class->sync_actor_state (actor_surface); - meta_window_actor_update_regions (window_actor); - } -} - -static void -meta_xwayland_surface_finalize (GObject *object) -{ - MetaXwaylandSurface *xwayland_surface = META_XWAYLAND_SURFACE (object); - GObjectClass *parent_object_class = - G_OBJECT_CLASS (meta_xwayland_surface_parent_class); - - clear_window (xwayland_surface); - - parent_object_class->finalize (object); -} - -static void -meta_xwayland_surface_init (MetaXwaylandSurface *xwayland_surface) -{ -} - -static void -meta_xwayland_surface_class_init (MetaXwaylandSurfaceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaWaylandSurfaceRoleClass *surface_role_class = - META_WAYLAND_SURFACE_ROLE_CLASS (klass); - MetaWaylandActorSurfaceClass *actor_surface_class = - META_WAYLAND_ACTOR_SURFACE_CLASS (klass); - - object_class->finalize = meta_xwayland_surface_finalize; - - surface_role_class->assigned = meta_xwayland_surface_assigned; - surface_role_class->pre_apply_state = meta_xwayland_surface_pre_apply_state; - surface_role_class->get_relative_coordinates = - meta_xwayland_surface_get_relative_coordinates; - surface_role_class->get_toplevel = meta_xwayland_surface_get_toplevel; - surface_role_class->get_window = meta_xwayland_surface_get_window; - - actor_surface_class->get_geometry_scale = - meta_xwayland_surface_get_geometry_scale; - actor_surface_class->sync_actor_state = - meta_xwayland_surface_sync_actor_state; - - signals[WINDOW_ASSOCIATED] = - g_signal_new ("window-associated", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); -} diff --git a/src/wayland/meta-xwayland-surface.h b/src/wayland/meta-xwayland-surface.h deleted file mode 100644 index 4bf305039..000000000 --- a/src/wayland/meta-xwayland-surface.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2013 Intel Corporation - * Copyright (C) 2013-2019 Red Hat Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - */ - -#ifndef META_XWAYLAND_SURFACE_H -#define META_XWAYLAND_SURFACE_H - -#include "meta/types.h" -#include "wayland/meta-wayland-actor-surface.h" - -#define META_TYPE_XWAYLAND_SURFACE (meta_xwayland_surface_get_type ()) -G_DECLARE_FINAL_TYPE (MetaXwaylandSurface, - meta_xwayland_surface, - META, XWAYLAND_SURFACE, - MetaWaylandActorSurface) - -void -meta_xwayland_surface_associate_with_window (MetaXwaylandSurface *xwayland_surface, - MetaWindow *window); - -#endif /* META_XWAYLAND_SURFACE_H */ diff --git a/src/wayland/meta-xwayland.c b/src/wayland/meta-xwayland.c deleted file mode 100644 index dce4facd0..000000000 --- a/src/wayland/meta-xwayland.c +++ /dev/null @@ -1,1417 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * X Wayland Support - * - * Copyright (C) 2013 Intel Corporation - * - * 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 "wayland/meta-xwayland.h" -#include "wayland/meta-xwayland-private.h" - -#include -#include -#include -#include -#include -#include -#include -#if defined(HAVE_SYS_RANDOM) -#include -#elif defined(HAVE_LINUX_RANDOM) -#include -#endif -#include -#include -#include -#include - -#include - -#include "backends/meta-monitor-manager-private.h" -#include "backends/meta-settings-private.h" -#include "meta/main.h" -#include "meta/meta-backend.h" -#include "wayland/meta-xwayland-surface.h" -#include "x11/meta-x11-display-private.h" - -#ifdef HAVE_XWAYLAND_LISTENFD -#define XWAYLAND_LISTENFD "-listenfd" -#else -#define XWAYLAND_LISTENFD "-listen" -#endif - -#define X11_TMP_UNIX_DIR "/tmp/.X11-unix" -#define X11_TMP_UNIX_PATH "/tmp/.X11-unix/X" - -static int display_number_override = -1; - -static void meta_xwayland_stop_xserver (MetaXWaylandManager *manager); - -static void -meta_xwayland_set_primary_output (Display *xdisplay); - -void -meta_xwayland_associate_window_with_surface (MetaWindow *window, - MetaWaylandSurface *surface) -{ - MetaDisplay *display = window->display; - MetaXwaylandSurface *xwayland_surface; - - if (!meta_wayland_surface_assign_role (surface, - META_TYPE_XWAYLAND_SURFACE, - NULL)) - { - wl_resource_post_error (surface->resource, - WL_DISPLAY_ERROR_INVALID_OBJECT, - "wl_surface@%d already has a different role", - wl_resource_get_id (surface->resource)); - return; - } - - xwayland_surface = META_XWAYLAND_SURFACE (surface->role); - meta_xwayland_surface_associate_with_window (xwayland_surface, window); - - /* Now that we have a surface check if it should have focus. */ - meta_display_sync_wayland_input_focus (display); -} - -static gboolean -associate_window_with_surface_id (MetaXWaylandManager *manager, - MetaWindow *window, - guint32 surface_id) -{ - struct wl_resource *resource; - - resource = wl_client_get_object (manager->client, surface_id); - if (resource) - { - MetaWaylandSurface *surface = wl_resource_get_user_data (resource); - meta_xwayland_associate_window_with_surface (window, surface); - return TRUE; - } - else - return FALSE; -} - -void -meta_xwayland_handle_wl_surface_id (MetaWindow *window, - guint32 surface_id) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaXWaylandManager *manager = &compositor->xwayland_manager; - - if (!associate_window_with_surface_id (manager, window, surface_id)) - { - /* No surface ID yet, schedule this association for whenever the - * surface is made known. - */ - meta_wayland_compositor_schedule_surface_association (compositor, - surface_id, window); - } -} - -gboolean -meta_xwayland_is_xwayland_surface (MetaWaylandSurface *surface) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaXWaylandManager *manager = &compositor->xwayland_manager; - - return wl_resource_get_client (surface->resource) == manager->client; -} - -static char * -meta_xwayland_get_exe_from_proc_entry (const char *proc_entry) -{ - g_autofree char *exepath; - char *executable; - char *p; - - exepath = g_file_read_link (proc_entry, NULL); - if (!exepath) - return NULL; - - p = strrchr (exepath, G_DIR_SEPARATOR); - if (p) - executable = g_strdup (++p); - else - executable = g_strdup (exepath); - - return executable; -} - -static char * -meta_xwayland_get_exe_from_pid (uint32_t pid) -{ - g_autofree char *proc_entry; - char *executable; - - proc_entry = g_strdup_printf ("/proc/%i/exe", pid); - executable = meta_xwayland_get_exe_from_proc_entry (proc_entry); - - return executable; -} - -static char * -meta_xwayland_get_self_exe (void) -{ - g_autofree char *proc_entry; - char *executable; - - proc_entry = g_strdup_printf ("/proc/self/exe"); - executable = meta_xwayland_get_exe_from_proc_entry (proc_entry); - - return executable; -} - -static gboolean -can_xwayland_ignore_exe (const char *executable, - const char *self) -{ - char ** ignore_executables; - gboolean ret; - - if (!g_strcmp0 (executable, self)) - return TRUE; - - ignore_executables = g_strsplit_set (XWAYLAND_IGNORE_EXECUTABLES, ",", -1); - ret = g_strv_contains ((const char * const *) ignore_executables, executable); - g_strfreev (ignore_executables); - - return ret; -} - -static uint32_t -meta_xwayland_get_client_pid (xcb_connection_t *xcb, - uint32_t client) -{ - xcb_res_client_id_spec_t spec = { 0 }; - xcb_res_query_client_ids_cookie_t cookie; - xcb_res_query_client_ids_reply_t *reply = NULL; - uint32_t pid = 0, *value; - - spec.client = client; - spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID; - - cookie = xcb_res_query_client_ids (xcb, 1, &spec); - reply = xcb_res_query_client_ids_reply (xcb, cookie, NULL); - - if (reply == NULL) - return 0; - - xcb_res_client_id_value_iterator_t it; - for (it = xcb_res_query_client_ids_ids_iterator (reply); - it.rem; - xcb_res_client_id_value_next (&it)) - { - spec = it.data->spec; - if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) - { - value = xcb_res_client_id_value_value (it.data); - pid = *value; - break; - } - } - free (reply); - - return pid; -} - -static gboolean -can_terminate_xwayland (Display *xdisplay) -{ - xcb_connection_t *xcb = XGetXCBConnection (xdisplay); - xcb_res_query_clients_cookie_t cookie; - xcb_res_query_clients_reply_t *reply = NULL; - xcb_res_client_iterator_t it; - gboolean can_terminate; - char *self; - - cookie = xcb_res_query_clients (xcb); - reply = xcb_res_query_clients_reply (xcb, cookie, NULL); - - /* Could not get the list of X11 clients, better not terminate Xwayland */ - if (reply == NULL) - return FALSE; - - can_terminate = TRUE; - self = meta_xwayland_get_self_exe (); - for (it = xcb_res_query_clients_clients_iterator (reply); - it.rem && can_terminate; - xcb_res_client_next (&it)) - { - uint32_t pid; - char *executable; - - pid = meta_xwayland_get_client_pid (xcb, it.data->resource_base); - if (pid == 0) - { - /* Unknown PID, don't risk terminating it */ - can_terminate = FALSE; - break; - } - - executable = meta_xwayland_get_exe_from_pid (pid); - can_terminate = can_xwayland_ignore_exe (executable, self); - g_free (executable); - } - free (reply); - - return can_terminate; -} - -static gboolean -try_display (int display, - char **filename_out, - int *fd_out, - GError **error) -{ - gboolean ret = FALSE; - char *filename; - int fd; - - filename = g_strdup_printf ("/tmp/.X%d-lock", display); - - again: - fd = open (filename, O_WRONLY | O_CLOEXEC | O_CREAT | O_EXCL, 0444); - - if (fd < 0 && errno == EEXIST) - { - char pid[11]; - char *end; - pid_t other; - int read_bytes; - - fd = open (filename, O_CLOEXEC, O_RDONLY); - if (fd < 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "Failed to open lock file %s: %s", - filename, g_strerror (errno)); - goto out; - } - - read_bytes = read (fd, pid, 11); - if (read_bytes != 11) - { - if (read_bytes < 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "Failed to read from lock file %s: %s", - filename, g_strerror (errno)); - } - else - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT, - "Only read %d bytes (needed 11) from lock file: %s", - read_bytes, filename); - } - goto out; - } - close (fd); - fd = -1; - - pid[10] = '\0'; - other = strtol (pid, &end, 0); - if (end != pid + 10) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, - "Can't parse lock file %s", filename); - goto out; - } - - if (kill (other, 0) < 0 && errno == ESRCH) - { - /* Process is dead. Try unlinking the lock file and trying again. */ - if (unlink (filename) < 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "Failed to unlink stale lock file %s: %s", - filename, g_strerror (errno)); - goto out; - } - - goto again; - } - - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Lock file %s is already occupied", filename); - goto out; - } - else if (fd < 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "Failed to create lock file %s: %s", - filename, g_strerror (errno)); - goto out; - } - - ret = TRUE; - - out: - if (!ret) - { - g_free (filename); - filename = NULL; - - if (fd >= 0) - { - close (fd); - fd = -1; - } - } - - *filename_out = filename; - *fd_out = fd; - return ret; -} - -static char * -create_lock_file (int display, - int *display_out, - GError **error) -{ - char *filename; - int fd; - char pid[12]; - int size; - int number_of_tries = 0; - g_autoptr (GError) local_error = NULL; - - while (!try_display (display, &filename, &fd, &local_error)) - { - meta_topic (META_DEBUG_WAYLAND, - "Failed to lock X11 display: %s", local_error->message); - g_clear_error (&local_error); - display++; - number_of_tries++; - - /* If we can't get a display after 50 times, then something's wrong. Just - * abort in this case. */ - if (number_of_tries >= 50) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Gave up after trying to lock different " - "X11 display lock file 50 times"); - return NULL; - } - } - - /* Subtle detail: we use the pid of the wayland compositor, not the xserver - * in the lock file. Another subtlety: snprintf returns the number of bytes - * it _would've_ written without either the NUL or the size clamping, hence - * the disparity in size. */ - size = snprintf (pid, 12, "%10d\n", getpid ()); - errno = 0; - if (size != 11 || write (fd, pid, 11) != 11) - { - if (errno != 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "Failed to write pid to lock file %s: %s", - filename, g_strerror (errno)); - } - else - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to write pid to lock file %s", filename); - } - - unlink (filename); - close (fd); - g_free (filename); - return NULL; - } - - close (fd); - - *display_out = display; - return filename; -} - -static int -bind_to_abstract_socket (int display, - GError **error) -{ - struct sockaddr_un addr; - socklen_t size, name_size; - int fd; - - fd = socket (PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0); - if (fd < 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "Failed to create socket: %s", g_strerror (errno)); - return -1; - } - - addr.sun_family = AF_LOCAL; - name_size = snprintf (addr.sun_path, sizeof addr.sun_path, - "%c%s%d", 0, X11_TMP_UNIX_PATH, display); - size = offsetof (struct sockaddr_un, sun_path) + name_size; - if (bind (fd, (struct sockaddr *) &addr, size) < 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "Failed to bind to %s: %s", - addr.sun_path + 1, g_strerror (errno)); - close (fd); - return -1; - } - - if (listen (fd, 1) < 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "Failed to listen to %s: %s", - addr.sun_path + 1, g_strerror (errno)); - close (fd); - return -1; - } - - return fd; -} - -static int -bind_to_unix_socket (int display, - GError **error) -{ - struct sockaddr_un addr; - socklen_t size, name_size; - int fd; - - fd = socket (PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0); - if (fd < 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "Failed to create socket: %s", g_strerror (errno)); - return -1; - } - - addr.sun_family = AF_LOCAL; - name_size = snprintf (addr.sun_path, sizeof addr.sun_path, - "%s%d", X11_TMP_UNIX_PATH, display) + 1; - size = offsetof (struct sockaddr_un, sun_path) + name_size; - unlink (addr.sun_path); - if (bind (fd, (struct sockaddr *) &addr, size) < 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "Failed to bind to %s: %s", - addr.sun_path, g_strerror (errno)); - close (fd); - return -1; - } - - if (listen (fd, 1) < 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "Failed to listen to %s: %s", - addr.sun_path, g_strerror (errno)); - unlink (addr.sun_path); - close (fd); - return -1; - } - - return fd; -} - -static void -xserver_died (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - GSubprocess *proc = G_SUBPROCESS (source); - MetaDisplay *display = meta_get_display (); - g_autoptr (GError) error = NULL; - MetaX11DisplayPolicy x11_display_policy; - - x11_display_policy = - meta_context_get_x11_display_policy (compositor->context); - if (!g_subprocess_wait_finish (proc, result, &error)) - { - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - return; - - g_warning ("Failed to finish waiting for Xwayland: %s", error->message); - } - else if (!g_subprocess_get_successful (proc)) - { - if (x11_display_policy == META_X11_DISPLAY_POLICY_MANDATORY) - g_warning ("X Wayland crashed; exiting"); - else - g_warning ("X Wayland crashed; attempting to recover"); - } - - if (x11_display_policy == META_X11_DISPLAY_POLICY_MANDATORY) - { - meta_exit (META_EXIT_ERROR); - } - else if (x11_display_policy == META_X11_DISPLAY_POLICY_ON_DEMAND) - { - g_autoptr (GError) error = NULL; - - if (display->x11_display) - meta_display_shutdown_x11 (display); - - if (!meta_xwayland_init (&compositor->xwayland_manager, - compositor, - compositor->wayland_display, - &error)) - g_warning ("Failed to init X sockets: %s", error->message); - } -} - -static void -meta_xwayland_terminate (MetaXWaylandManager *manager) -{ - MetaDisplay *display = meta_get_display (); - - g_clear_handle_id (&manager->xserver_grace_period_id, g_source_remove); - meta_display_shutdown_x11 (display); - meta_xwayland_stop_xserver (manager); -} - -static gboolean -shutdown_xwayland_cb (gpointer data) -{ - MetaXWaylandManager *manager = data; - MetaDisplay *display = meta_get_display (); - MetaBackend *backend = meta_get_backend (); - - if (!meta_settings_is_experimental_feature_enabled (meta_backend_get_settings (backend), - META_EXPERIMENTAL_FEATURE_AUTOCLOSE_XWAYLAND)) - return G_SOURCE_REMOVE; - - if (display->x11_display && - !can_terminate_xwayland (display->x11_display->xdisplay)) - return G_SOURCE_CONTINUE; - - meta_verbose ("Shutting down Xwayland"); - manager->xserver_grace_period_id = 0; - meta_xwayland_terminate (manager); - return G_SOURCE_REMOVE; -} - -static int -x_io_error (Display *display) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaX11DisplayPolicy x11_display_policy; - - g_warning ("Connection to xwayland lost"); - - x11_display_policy = - meta_context_get_x11_display_policy (compositor->context); - if (x11_display_policy == META_X11_DISPLAY_POLICY_MANDATORY) - meta_exit (META_EXIT_ERROR); - - return 0; -} - -static int -x_io_error_noop (Display *display) -{ - return 0; -} - -#ifdef HAVE_XSETIOERROREXITHANDLER -static void -x_io_error_exit (Display *display, - void *data) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaXWaylandManager *manager = &compositor->xwayland_manager; - - g_warning ("Xwayland just died, attempting to recover"); - manager->xserver_grace_period_id = - g_idle_add (shutdown_xwayland_cb, manager); -} - -static void -x_io_error_exit_noop (Display *display, - void *data) -{ -} -#endif - -void -meta_xwayland_override_display_number (int number) -{ - display_number_override = number; -} - -static gboolean -ensure_x11_unix_perms (GError **error) -{ - struct stat buf; - - if (lstat (X11_TMP_UNIX_DIR, &buf) != 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "Failed to check permissions on directory \"%s\": %s", - X11_TMP_UNIX_DIR, g_strerror (errno)); - return FALSE; - } - - /* If the directory already exists, it should belong to root or ourselves ... */ - if (buf.st_uid != 0 && buf.st_uid != getuid ()) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED, - "Wrong ownership for directory \"%s\"", - X11_TMP_UNIX_DIR); - return FALSE; - } - - /* ... be writable ... */ - if ((buf.st_mode & 0022) != 0022) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED, - "Directory \"%s\" is not writable", - X11_TMP_UNIX_DIR); - return FALSE; - } - - /* ... and have the sticky bit set */ - if ((buf.st_mode & 01000) != 01000) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED, - "Directory \"%s\" is missing the sticky bit", - X11_TMP_UNIX_DIR); - return FALSE; - } - - return TRUE; -} - -static gboolean -ensure_x11_unix_dir (GError **error) -{ - if (mkdir (X11_TMP_UNIX_DIR, 01777) != 0) - { - if (errno == EEXIST) - return ensure_x11_unix_perms (error); - - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "Failed to create directory \"%s\": %s", - X11_TMP_UNIX_DIR, g_strerror (errno)); - return FALSE; - } - - return TRUE; -} - -static gboolean -open_display_sockets (MetaXWaylandManager *manager, - int display_index, - int *abstract_fd_out, - int *unix_fd_out, - GError **error) -{ - int abstract_fd, unix_fd; - - abstract_fd = bind_to_abstract_socket (display_index, error); - if (abstract_fd < 0) - return FALSE; - - unix_fd = bind_to_unix_socket (display_index, error); - if (unix_fd < 0) - { - close (abstract_fd); - return FALSE; - } - - *abstract_fd_out = abstract_fd; - *unix_fd_out = unix_fd; - - return TRUE; -} - -static gboolean -choose_xdisplay (MetaXWaylandManager *manager, - MetaXWaylandConnection *connection, - int *display, - GError **error) -{ - int number_of_tries = 0; - char *lock_file = NULL; - - if (!ensure_x11_unix_dir (error)) - return FALSE; - - do - { - g_autoptr (GError) local_error = NULL; - - lock_file = create_lock_file (*display, display, &local_error); - if (!lock_file) - { - g_prefix_error (&local_error, "Failed to create an X lock file: "); - g_propagate_error (error, g_steal_pointer (&local_error)); - return FALSE; - } - - if (!open_display_sockets (manager, *display, - &connection->abstract_fd, - &connection->unix_fd, - &local_error)) - { - unlink (lock_file); - - if (++number_of_tries >= 50) - { - g_prefix_error (&local_error, "Failed to bind X11 socket: "); - g_propagate_error (error, g_steal_pointer (&local_error)); - return FALSE; - } - - (*display)++; - continue; - } - - break; - } - while (1); - - connection->display_index = *display; - connection->name = g_strdup_printf (":%d", connection->display_index); - connection->lock_file = lock_file; - - return TRUE; -} - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (FILE, fclose) - -static gboolean -prepare_auth_file (MetaXWaylandManager *manager, - GError **error) -{ - Xauth auth_entry = { 0 }; - g_autoptr (FILE) fp = NULL; - char auth_data[16]; - int fd; - - manager->auth_file = g_build_filename (g_get_user_runtime_dir (), - ".mutter-Xwaylandauth.XXXXXX", - NULL); - - if (getrandom (auth_data, sizeof (auth_data), 0) != sizeof (auth_data)) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "Failed to get random data: %s", g_strerror (errno)); - return FALSE; - } - - auth_entry.family = FamilyLocal; - auth_entry.address = (char *) g_get_host_name (); - auth_entry.address_length = strlen (auth_entry.address); - auth_entry.name = (char *) "MIT-MAGIC-COOKIE-1"; - auth_entry.name_length = strlen (auth_entry.name); - auth_entry.data = auth_data; - auth_entry.data_length = sizeof (auth_data); - - fd = g_mkstemp (manager->auth_file); - if (fd < 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "Failed to open Xauthority file: %s", g_strerror (errno)); - return FALSE; - } - - fp = fdopen (fd, "w+"); - if (!fp) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "Failed to open Xauthority stream: %s", g_strerror (errno)); - close (fd); - return FALSE; - } - - if (!XauWriteAuth (fp, &auth_entry)) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "Error writing to Xauthority file: %s", g_strerror (errno)); - return FALSE; - } - - auth_entry.family = FamilyWild; - if (!XauWriteAuth (fp, &auth_entry)) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "Error writing to Xauthority file: %s", g_strerror (errno)); - return FALSE; - } - - if (fflush (fp) == EOF) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "Error writing to Xauthority file: %s", g_strerror (errno)); - return FALSE; - } - - return TRUE; -} - -static void -add_local_user_to_xhost (Display *xdisplay) -{ - XHostAddress host_entry; - XServerInterpretedAddress siaddr; - - siaddr.type = (char *) "localuser"; - siaddr.typelength = strlen (siaddr.type); - siaddr.value = (char *) g_get_user_name(); - siaddr.valuelength = strlen (siaddr.value); - - host_entry.family = FamilyServerInterpreted; - host_entry.address = (char *) &siaddr; - - XAddHost (xdisplay, &host_entry); -} - -static void -on_init_x11_cb (MetaDisplay *display, - GAsyncResult *result, - gpointer user_data) -{ - g_autoptr (GError) error = NULL; - - if (!meta_display_init_x11_finish (display, result, &error)) - g_warning ("Failed to initialize X11 display: %s", error->message); -} - -static gboolean -on_displayfd_ready (int fd, - GIOCondition condition, - gpointer user_data) -{ - GTask *task = user_data; - - /* The server writes its display name to the displayfd - * socket when it's ready. We don't care about the data - * in the socket, just that it wrote something, since - * that means it's ready. */ - g_task_return_boolean (task, !!(condition & G_IO_IN)); - g_object_unref (task); - - return G_SOURCE_REMOVE; -} - -static int -steal_fd (int *fd_ptr) -{ - int fd = *fd_ptr; - *fd_ptr = -1; - return fd; -} - -void -meta_xwayland_start_xserver (MetaXWaylandManager *manager, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - struct { - const char *extension_name; - MetaXwaylandExtension disable_extension; - } x11_extension_names[] = { - { "SECURITY", META_XWAYLAND_EXTENSION_SECURITY }, - { "XTEST", META_XWAYLAND_EXTENSION_XTEST }, - }; - - int xwayland_client_fd[2]; - int displayfd[2]; - g_autoptr(GSubprocessLauncher) launcher = NULL; - GSubprocessFlags flags; - GError *error = NULL; - g_autoptr (GTask) task = NULL; - MetaBackend *backend; - MetaSettings *settings; - const char *args[32]; - int xwayland_disable_extensions; - int i, j; - - task = g_task_new (NULL, cancellable, callback, user_data); - g_task_set_source_tag (task, meta_xwayland_start_xserver); - g_task_set_task_data (task, manager, NULL); - - /* We want xwayland to be a wayland client so we make a socketpair to setup a - * wayland protocol connection. */ - if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, xwayland_client_fd) < 0) - { - g_task_return_new_error (task, - G_IO_ERROR, - g_io_error_from_errno (errno), - "xwayland_client_fd socketpair failed"); - return; - } - - if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, displayfd) < 0) - { - close (xwayland_client_fd[0]); - close (xwayland_client_fd[1]); - - g_task_return_new_error (task, - G_IO_ERROR, - g_io_error_from_errno (errno), - "displayfd socketpair failed"); - return; - } - - /* xwayland, please. */ - flags = G_SUBPROCESS_FLAGS_NONE; - - if (getenv ("XWAYLAND_STFU")) - { - flags |= G_SUBPROCESS_FLAGS_STDOUT_SILENCE; - flags |= G_SUBPROCESS_FLAGS_STDERR_SILENCE; - } - - backend = meta_get_backend (); - settings = meta_backend_get_settings (backend); - xwayland_disable_extensions = - meta_settings_get_xwayland_disable_extensions (settings); - - launcher = g_subprocess_launcher_new (flags); - - g_subprocess_launcher_take_fd (launcher, - steal_fd (&xwayland_client_fd[1]), 3); - g_subprocess_launcher_take_fd (launcher, - steal_fd (&manager->public_connection.abstract_fd), 4); - g_subprocess_launcher_take_fd (launcher, - steal_fd (&manager->public_connection.unix_fd), 5); - g_subprocess_launcher_take_fd (launcher, - steal_fd (&displayfd[1]), 6); - g_subprocess_launcher_take_fd (launcher, - steal_fd (&manager->private_connection.abstract_fd), 7); - - g_subprocess_launcher_setenv (launcher, "WAYLAND_SOCKET", "3", TRUE); - - i = 0; - args[i++] = XWAYLAND_PATH; - args[i++] = manager->public_connection.name; - args[i++] = "-rootless"; - args[i++] = "-noreset"; - args[i++] = "-accessx"; - args[i++] = "-core"; - args[i++] = "-auth"; - args[i++] = manager->auth_file; - args[i++] = XWAYLAND_LISTENFD; - args[i++] = "4"; - args[i++] = XWAYLAND_LISTENFD; - args[i++] = "5"; - args[i++] = "-displayfd"; - args[i++] = "6"; -#ifdef HAVE_XWAYLAND_INITFD - args[i++] = "-initfd"; - args[i++] = "7"; -#else - args[i++] = XWAYLAND_LISTENFD; - args[i++] = "7"; -#endif - for (j = 0; j < G_N_ELEMENTS (x11_extension_names); j++) - { - /* Make sure we don't go past the array size - We need room for - * 2 arguments, plus the last NULL terminator. - */ - if (i + 3 > G_N_ELEMENTS (args)) - break; - - if (xwayland_disable_extensions & x11_extension_names[j].disable_extension) - { - args[i++] = "-extension"; - args[i++] = x11_extension_names[j].extension_name; - } - } - /* Terminator */ - args[i++] = NULL; - - manager->proc = g_subprocess_launcher_spawnv (launcher, args, &error); - - if (!manager->proc) - { - close (displayfd[0]); - close (xwayland_client_fd[0]); - - g_task_return_error (task, error); - return; - } - - manager->xserver_died_cancellable = g_cancellable_new (); - g_subprocess_wait_async (manager->proc, manager->xserver_died_cancellable, - xserver_died, NULL); - g_unix_fd_add (displayfd[0], G_IO_IN, on_displayfd_ready, - g_steal_pointer (&task)); - manager->client = wl_client_create (manager->wayland_display, - xwayland_client_fd[0]); -} - -gboolean -meta_xwayland_start_xserver_finish (MetaXWaylandManager *manager, - GAsyncResult *result, - GError **error) -{ - g_assert (g_task_get_source_tag (G_TASK (result)) == - meta_xwayland_start_xserver); - - return g_task_propagate_boolean (G_TASK (result), error); -} - -static gboolean -xdisplay_connection_activity_cb (gint fd, - GIOCondition cond, - gpointer user_data) -{ - MetaXWaylandManager *manager = user_data; - MetaDisplay *display = meta_get_display (); - - meta_display_init_x11 (display, NULL, - (GAsyncReadyCallback) on_init_x11_cb, NULL); - - /* Stop watching both file descriptors */ - g_clear_handle_id (&manager->abstract_fd_watch_id, g_source_remove); - g_clear_handle_id (&manager->unix_fd_watch_id, g_source_remove); - - return G_SOURCE_REMOVE; -} - -static void -meta_xwayland_stop_xserver_timeout (MetaXWaylandManager *manager) -{ - if (manager->xserver_grace_period_id) - return; - - manager->xserver_grace_period_id = - g_timeout_add_seconds (10, shutdown_xwayland_cb, manager); -} - -static void -window_unmanaged_cb (MetaWindow *window, - MetaXWaylandManager *manager) -{ - manager->x11_windows = g_list_remove (manager->x11_windows, window); - g_signal_handlers_disconnect_by_func (window, - window_unmanaged_cb, - manager); - if (!manager->x11_windows) - { - meta_verbose ("All X11 windows gone, setting shutdown timeout"); - meta_xwayland_stop_xserver_timeout (manager); - } -} - -static void -window_created_cb (MetaDisplay *display, - MetaWindow *window, - MetaXWaylandManager *manager) -{ - /* Ignore all internal windows */ - if (!window->xwindow || - meta_window_get_pid (window) == getpid ()) - return; - - manager->x11_windows = g_list_prepend (manager->x11_windows, window); - g_signal_connect (window, "unmanaged", - G_CALLBACK (window_unmanaged_cb), manager); - - g_clear_handle_id (&manager->xserver_grace_period_id, g_source_remove); -} - -static void -meta_xwayland_stop_xserver (MetaXWaylandManager *manager) -{ - if (manager->proc) - g_subprocess_send_signal (manager->proc, SIGTERM); - g_signal_handlers_disconnect_by_func (meta_get_display (), - window_created_cb, - manager); - g_clear_object (&manager->xserver_died_cancellable); - g_clear_object (&manager->proc); -} - -gboolean -meta_xwayland_init (MetaXWaylandManager *manager, - MetaWaylandCompositor *compositor, - struct wl_display *wl_display, - GError **error) -{ - MetaContext *context = compositor->context; - MetaX11DisplayPolicy policy; - int display = 0; - - if (display_number_override != -1) - display = display_number_override; - else if (g_getenv ("RUNNING_UNDER_GDM")) - display = 1024; - - - if (!manager->public_connection.name) - { - if (!choose_xdisplay (manager, &manager->public_connection, &display, error)) - return FALSE; - - display++; - if (!choose_xdisplay (manager, &manager->private_connection, &display, error)) - return FALSE; - - if (!prepare_auth_file (manager, error)) - return FALSE; - } - else - { - if (!open_display_sockets (manager, - manager->public_connection.display_index, - &manager->public_connection.abstract_fd, - &manager->public_connection.unix_fd, - error)) - return FALSE; - - if (!open_display_sockets (manager, - manager->private_connection.display_index, - &manager->private_connection.abstract_fd, - &manager->private_connection.unix_fd, - error)) - return FALSE; - } - - g_message ("Using public X11 display %s, (using %s for managed services)", - manager->public_connection.name, - manager->private_connection.name); - - manager->wayland_display = wl_display; - policy = meta_context_get_x11_display_policy (context); - - if (policy == META_X11_DISPLAY_POLICY_ON_DEMAND) - { - manager->abstract_fd_watch_id = - g_unix_fd_add (manager->public_connection.abstract_fd, G_IO_IN, - xdisplay_connection_activity_cb, manager); - manager->unix_fd_watch_id = - g_unix_fd_add (manager->public_connection.unix_fd, G_IO_IN, - xdisplay_connection_activity_cb, manager); - } - - return TRUE; -} - -static void -monitors_changed_cb (MetaMonitorManager *monitor_manager) -{ - MetaX11Display *x11_display = meta_get_display ()->x11_display; - - meta_xwayland_set_primary_output (x11_display->xdisplay); -} - -static void -on_x11_display_closing (MetaDisplay *display, - MetaXWaylandManager *manager) -{ - Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display); - - meta_xwayland_shutdown_dnd (manager, xdisplay); - g_signal_handlers_disconnect_by_func (meta_monitor_manager_get (), - monitors_changed_cb, - NULL); - g_signal_handlers_disconnect_by_func (display, - on_x11_display_closing, - manager); -} - -static void -meta_xwayland_init_xrandr (MetaXWaylandManager *manager, - Display *xdisplay) -{ - MetaMonitorManager *monitor_manager = meta_monitor_manager_get (); - - manager->has_xrandr = XRRQueryExtension (xdisplay, - &manager->rr_event_base, - &manager->rr_error_base); - - if (!manager->has_xrandr) - return; - - XRRSelectInput (xdisplay, DefaultRootWindow (xdisplay), - RRCrtcChangeNotifyMask | RROutputChangeNotifyMask); - - g_signal_connect (monitor_manager, "monitors-changed", - G_CALLBACK (monitors_changed_cb), NULL); - - meta_xwayland_set_primary_output (xdisplay); -} - -/* To be called right after connecting */ -void -meta_xwayland_complete_init (MetaDisplay *display, - Display *xdisplay) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaXWaylandManager *manager = &compositor->xwayland_manager; - MetaX11DisplayPolicy x11_display_policy; - - /* We install an X IO error handler in addition to the child watch, - because after Xlib connects our child watch may not be called soon - enough, and therefore we won't crash when X exits (and most important - we won't reset the tty). - */ - XSetIOErrorHandler (x_io_error); -#ifdef HAVE_XSETIOERROREXITHANDLER - XSetIOErrorExitHandler (xdisplay, x_io_error_exit, display); -#endif - - g_signal_connect (display, "x11-display-closing", - G_CALLBACK (on_x11_display_closing), manager); - meta_xwayland_init_dnd (xdisplay); - add_local_user_to_xhost (xdisplay); - meta_xwayland_init_xrandr (manager, xdisplay); - - x11_display_policy = - meta_context_get_x11_display_policy (compositor->context); - if (x11_display_policy == META_X11_DISPLAY_POLICY_ON_DEMAND) - { - meta_xwayland_stop_xserver_timeout (manager); - g_signal_connect (meta_get_display (), "window-created", - G_CALLBACK (window_created_cb), manager); - } -} - -static void -meta_xwayland_connection_release (MetaXWaylandConnection *connection) -{ - unlink (connection->lock_file); - g_clear_pointer (&connection->lock_file, g_free); -} - -void -meta_xwayland_shutdown (MetaXWaylandManager *manager) -{ -#ifdef HAVE_XSETIOERROREXITHANDLER - MetaDisplay *display = meta_get_display (); - MetaX11Display *x11_display; -#endif - char path[256]; - - g_cancellable_cancel (manager->xserver_died_cancellable); - - XSetIOErrorHandler (x_io_error_noop); -#ifdef HAVE_XSETIOERROREXITHANDLER - x11_display = display->x11_display; - if (x11_display) - { - XSetIOErrorExitHandler (meta_x11_display_get_xdisplay (x11_display), - x_io_error_exit_noop, NULL); - } -#endif - - meta_xwayland_terminate (manager); - - snprintf (path, sizeof path, "%s%d", X11_TMP_UNIX_PATH, - manager->public_connection.display_index); - unlink (path); - - snprintf (path, sizeof path, "%s%d", X11_TMP_UNIX_PATH, - manager->private_connection.display_index); - unlink (path); - - g_clear_pointer (&manager->public_connection.name, g_free); - g_clear_pointer (&manager->private_connection.name, g_free); - - meta_xwayland_connection_release (&manager->public_connection); - meta_xwayland_connection_release (&manager->private_connection); - - if (manager->auth_file) - { - unlink (manager->auth_file); - g_clear_pointer (&manager->auth_file, g_free); - } -} - -static void -meta_xwayland_set_primary_output (Display *xdisplay) -{ - XRRScreenResources *resources; - MetaMonitorManager *monitor_manager; - MetaLogicalMonitor *primary_monitor; - int i; - - monitor_manager = meta_monitor_manager_get (); - primary_monitor = - meta_monitor_manager_get_primary_logical_monitor (monitor_manager); - - if (!primary_monitor) - return; - - resources = XRRGetScreenResourcesCurrent (xdisplay, - DefaultRootWindow (xdisplay)); - if (!resources) - return; - - for (i = 0; i < resources->noutput; i++) - { - RROutput output_id = resources->outputs[i]; - XRROutputInfo *xrandr_output; - XRRCrtcInfo *crtc_info = NULL; - MetaRectangle crtc_geometry; - - xrandr_output = XRRGetOutputInfo (xdisplay, resources, output_id); - if (!xrandr_output) - continue; - - if (xrandr_output->crtc) - crtc_info = XRRGetCrtcInfo (xdisplay, resources, xrandr_output->crtc); - - XRRFreeOutputInfo (xrandr_output); - - if (!crtc_info) - continue; - - crtc_geometry.x = crtc_info->x; - crtc_geometry.y = crtc_info->y; - crtc_geometry.width = crtc_info->width; - crtc_geometry.height = crtc_info->height; - - XRRFreeCrtcInfo (crtc_info); - - if (meta_rectangle_equal (&crtc_geometry, &primary_monitor->rect)) - { - XRRSetOutputPrimary (xdisplay, DefaultRootWindow (xdisplay), - output_id); - break; - } - } - - XRRFreeScreenResources (resources); -} - -gboolean -meta_xwayland_handle_xevent (XEvent *event) -{ - MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); - MetaXWaylandManager *manager = &compositor->xwayland_manager; - - if (meta_xwayland_dnd_handle_event (event)) - return TRUE; - - if (manager->has_xrandr && event->type == manager->rr_event_base + RRNotify) - { - MetaX11Display *x11_display = meta_get_display ()->x11_display; - meta_xwayland_set_primary_output (x11_display->xdisplay); - return TRUE; - } - - return FALSE; -} diff --git a/src/wayland/meta-xwayland.h b/src/wayland/meta-xwayland.h deleted file mode 100644 index dac9c689f..000000000 --- a/src/wayland/meta-xwayland.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2014 Red Hat - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - * - * Written by: - * Jasper St. Pierre - */ - -#ifndef META_XWAYLAND_H -#define META_XWAYLAND_H - -#include - -#include "core/util-private.h" -#include "meta/types.h" -#include "wayland/meta-wayland-types.h" - -META_EXPORT_TEST -void -meta_xwayland_override_display_number (int number); - -void -meta_xwayland_handle_wl_surface_id (MetaWindow *window, - guint32 surface_id); - -gboolean -meta_xwayland_is_xwayland_surface (MetaWaylandSurface *surface); - -void -meta_xwayland_handle_xwayland_grab (MetaWindow *window, - gboolean allow); - -void -meta_xwayland_associate_window_with_surface (MetaWindow *window, - MetaWaylandSurface *surface); - -#endif /* META_XWAYLAND_H */ diff --git a/src/wayland/protocol/gtk-primary-selection.xml b/src/wayland/protocol/gtk-primary-selection.xml deleted file mode 100644 index 02cab94fc..000000000 --- a/src/wayland/protocol/gtk-primary-selection.xml +++ /dev/null @@ -1,225 +0,0 @@ - - - - Copyright © 2015, 2016 Red Hat - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice (including the next - paragraph) shall be included in all copies or substantial portions of the - Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - - - - This protocol provides the ability to have a primary selection device to - match that of the X server. This primary selection is a shortcut to the - common clipboard selection, where text just needs to be selected in order - to allow copying it elsewhere. The de facto way to perform this action - is the middle mouse button, although it is not limited to this one. - - Clients wishing to honor primary selection should create a primary - selection source and set it as the selection through - wp_primary_selection_device.set_selection whenever the text selection - changes. In order to minimize calls in pointer-driven text selection, - it should happen only once after the operation finished. Similarly, - a NULL source should be set when text is unselected. - - wp_primary_selection_offer objects are first announced through the - wp_primary_selection_device.data_offer event. Immediately after this event, - the primary data offer will emit wp_primary_selection_offer.offer events - to let know of the mime types being offered. - - When the primary selection changes, the client with the keyboard focus - will receive wp_primary_selection_device.selection events. Only the client - with the keyboard focus will receive such events with a non-NULL - wp_primary_selection_offer. Across keyboard focus changes, previously - focused clients will receive wp_primary_selection_device.events with a - NULL wp_primary_selection_offer. - - In order to request the primary selection data, the client must pass - a recent serial pertaining to the press event that is triggering the - operation, if the compositor deems the serial valid and recent, the - wp_primary_selection_source.send event will happen in the other end - to let the transfer begin. The client owning the primary selection - should write the requested data, and close the file descriptor - immediately. - - If the primary selection owner client disappeared during the transfer, - the client reading the data will receive a - wp_primary_selection_device.selection event with a NULL - wp_primary_selection_offer, the client should take this as a hint - to finish the reads related to the no longer existing offer. - - The primary selection owner should be checking for errors during - writes, merely cancelling the ongoing transfer if any happened. - - - - - The primary selection device manager is a singleton global object that - provides access to the primary selection. It allows to create - wp_primary_selection_source objects, as well as retrieving the per-seat - wp_primary_selection_device objects. - - - - - Create a new primary selection source. - - - - - - - Create a new data device for a given seat. - - - - - - - - Destroy the primary selection device manager. - - - - - - - - Replaces the current selection. The previous owner of the primary selection - will receive a wp_primary_selection_source.cancelled event. - - To unset the selection, set the source to NULL. - - - - - - - - Introduces a new wp_primary_selection_offer object that may be used - to receive the current primary selection. Immediately following this - event, the new wp_primary_selection_offer object will send - wp_primary_selection_offer.offer events to describe the offered mime - types. - - - - - - - The wp_primary_selection_device.selection event is sent to notify the - client of a new primary selection. This event is sent after the - wp_primary_selection.data_offer event introducing this object, and after - the offer has announced its mimetypes through - wp_primary_selection_offer.offer. - - The data_offer is valid until a new offer or NULL is received - or until the client loses keyboard focus. The client must destroy the - previous selection data_offer, if any, upon receiving this event. - - - - - - - Destroy the primary selection device. - - - - - - - A wp_primary_selection_offer represents an offer to transfer the contents - of the primary selection clipboard to the client. Similar to - wl_data_offer, the offer also describes the mime types that the source - will transferthat the - data can be converted to and provides the mechanisms for transferring the - data directly to the client. - - - - - To transfer the contents of the primary selection clipboard, the client - issues this request and indicates the mime type that it wants to - receive. The transfer happens through the passed file descriptor - (typically created with the pipe system call). The source client writes - the data in the mime type representation requested and then closes the - file descriptor. - - The receiving client reads from the read end of the pipe until EOF and - closes its end, at which point the transfer is complete. - - - - - - - - Destroy the primary selection offer. - - - - - - Sent immediately after creating announcing the wp_primary_selection_offer - through wp_primary_selection_device.data_offer. One event is sent per - offered mime type. - - - - - - - - The source side of a wp_primary_selection_offer, it provides a way to - describe the offered data and respond to requests to transfer the - requested contents of the primary selection clipboard. - - - - - This request adds a mime type to the set of mime types advertised to - targets. Can be called several times to offer multiple types. - - - - - - - Destroy the primary selection source. - - - - - - Request for the current primary selection contents from the client. - Send the specified mime type over the passed file descriptor, then - close it. - - - - - - - - This primary selection source is no longer valid. The client should - clean up and destroy this primary selection source. - - - - diff --git a/src/wayland/protocol/gtk-shell.xml b/src/wayland/protocol/gtk-shell.xml deleted file mode 100644 index 1aab593c4..000000000 --- a/src/wayland/protocol/gtk-shell.xml +++ /dev/null @@ -1,90 +0,0 @@ - - - - - gtk_shell is a protocol extension providing additional features for - clients implementing it. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/wayland/protocol/gtk-text-input.xml b/src/wayland/protocol/gtk-text-input.xml deleted file mode 100644 index a134a19f6..000000000 --- a/src/wayland/protocol/gtk-text-input.xml +++ /dev/null @@ -1,302 +0,0 @@ - - - - - Copyright © 2012, 2013 Intel Corporation - Copyright © 2015, 2016 Jan Arne Petersen - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that copyright notice and this permission - notice appear in supporting documentation, and that the name of - the copyright holders not be used in advertising or publicity - pertaining to distribution of the software without specific, - written prior permission. The copyright holders make no - representations about the suitability of this software for any - purpose. It is provided "as is" without express or implied - warranty. - - THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF - THIS SOFTWARE. - - - - - The gtk_text_input interface represents text input and input methods - associated with a seat. It provides enter/leave events to follow the - text input focus for a seat. - - Requests are used to enable/disable the text-input object and set - state information like surrounding and selected text or the content type. - The information about the entered text is sent to the text-input object - via the pre-edit and commit_string events. Using this interface removes - the need for applications to directly process hardware key events and - compose text out of them. - - Text is valid UTF-8 encoded, indices and lengths are in bytes. Indices - have to always point to the first byte of an UTF-8 encoded code point. - Lengths are not allowed to contain just a part of an UTF-8 encoded code - point. - - Focus moving throughout surfaces will result in the emission of - gtk_text_input.enter and gtk_text_input.leave events. The focused - surface must perform gtk_text_input.enable and - gtk_text_input.disable requests as the keyboard focus moves across - editable and non-editable elements of the UI. Those two requests are not - expected to be paired with each other, the compositor must be able to - handle consecutive series of the same request. - - State is sent by the state requests (set_surrounding_text, - set_content_type and set_cursor_rectangle) and a commit request. - After an enter event or disable request all state information is - invalidated and needs to be resent by the client. - - This protocol defines requests and events necessary for regular clients - to communicate with an input method. The gtk_input_method protocol - defines the interfaces necessary to implement standalone input methods. - If a compositor implements both interfaces, it will be the arbiter of the - communication between both. - - Warning! The protocol described in this file is experimental and - backward incompatible changes may be made. Backward compatible changes - may be added together with the corresponding interface version bump. - Backward incompatible changes are done by bumping the version number in - the protocol and interface names and resetting the interface version. - Once the protocol is to be declared stable, the 'z' prefix and the - version number in the protocol and interface names are removed and the - interface version number is reset. - - - - - Destroy the wp_text_input object. Also disables all surfaces enabled - through this wp_text_input object - - - - - - Content hint is a bitmask to allow to modify the behavior of the text - input. - - - - - - - - - Requests text input on a surface. The serial provided must be the one - received on gtk_text_input.enter. - - - - - - - - Explicitly disable text input in a surface (typically when there is no - focus on any text entry inside the surface). - - - - - - Sets the plain surrounding text around the input position. Text is - UTF-8 encoded. Cursor is the byte offset within the surrounding text. - Anchor is the byte offset of the selection anchor within the - surrounding text. If there is no selected text, anchor is the same as - cursor. - - Make sure to always send some text before and after the cursor - except when the cursor is at the beginning or end of text. - - When there was a configure_surrounding_text event take the - before_cursor and after_cursor arguments into account for picking how - much surrounding text to send. - - There is a maximum length of wayland messages so text can not be - longer than 4000 bytes. - - - - - - - - - Content hint is a bitmask to allow to modify the behavior of the text - input. - - - - - - - - - - - - - - - - - The content purpose allows to specify the primary purpose of a text - input. - - This allows an input method to show special purpose input panels with - extra characters or to disallow some characters. - - - - - - - - - - - - - - - - - - - - Sets the content purpose and content hint. While the purpose is the - basic purpose of an input field, the hint flags allow to modify some - of the behavior. - - When no content type is explicitly set, a normal content purpose with - none hint should be assumed. - - - - - - - - Sets the cursor outline as a x, y, width, height rectangle in surface - local coordinates. - - Allows the compositor to put a window with word suggestions near the - cursor. - - - - - - - - - - Allows to atomically send state updates from client. The previous - set_surrounding_text, set_content_type and set_cursor_rectangle - become effective after this call. - - Serial should be set to the serial from the last wp_text_input.enter - event. - - To make sure to not receive outdated input method events after a - state update, wl_display_sync() should be called after making this - request. - - - - - - Notification that this seat's text-input focus is on a certain surface. - - When the seat has the keyboard capability the text-input focus follows - the keyboard focus. - - - - - - - - Notification that this seat's text-input focus is no longer on - a certain surface. The client should reset any preedit string previously - set. - - The leave notification is sent before the enter notification - for the new focus. - - When the seat has the keyboard capability the text-input focus follows - the keyboard focus. - - - - - - - - Notify when a new composing text (pre-edit) should be set around the - current cursor position. Any previously set composing text should - be removed. - - - - - - - - Notify when text should be inserted into the editor widget. The text to - commit could be either just a single character after a key press or the - result of some composing (pre-edit). - - The text argument could be also null if some text is removed (see - gtk_text_input.delete_surrounding_text). - - Any previously set composing text should be removed. - - - - - - - Notify when the text around the current cursor position should be - deleted. Before_length and after_length is the length (in bytes) of text - before and after the current cursor position (excluding the selection) - to delete. - - This event should be handled as part of a following commit_string or - preedit_string event. - - - - - - - - - A factory for text-input objects. This object is a global singleton. - - - - - Destroy the wp_text_input_manager object. - - - - - - Creates a new text-input object for a given seat. - - - - - - diff --git a/src/x11/atomnames.h b/src/x11/atomnames.h deleted file mode 100644 index 4b25b099a..000000000 --- a/src/x11/atomnames.h +++ /dev/null @@ -1,186 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002, 2003, 2004 Red Hat, Inc. - * Copyright (C) 2003, 2004 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * Copyright (C) 2008 Thomas Thurman - * - * 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 . - */ - -/* - * \file atomnames.h A list of atom names. - * - * This is a list of the names of all the X atoms that Mutter uses. - * Each is wrapped in a macro "item()" which is undefined here; the - * idea is that when you need to make a big list of all the X atoms, - * you can define item(), include this file, and then undefine it - * again. - * - * If you also define EWMH_ATOMS_ONLY then you will only get _NET_WM_* - * atoms rather than all of them. - */ - -#ifndef item -#error "item(x) must be defined when you include atomnames.h" -#endif - -#ifndef EWMH_ATOMS_ONLY - -item(WM_PROTOCOLS) /* MUST BE FIRST */ -item(WM_TAKE_FOCUS) -item(WM_DELETE_WINDOW) -item(WM_STATE) -item(_MOTIF_WM_HINTS) -item(WM_CHANGE_STATE) -item(SM_CLIENT_ID) -item(WM_CLIENT_LEADER) -item(WM_WINDOW_ROLE) -item(UTF8_STRING) -item(WM_ICON_SIZE) -item(_KWM_WIN_ICON) -item(_MUTTER_HINTS) -item(_GTK_THEME_VARIANT) -item(_GTK_APPLICATION_ID) -item(_GTK_UNIQUE_BUS_NAME) -item(_GTK_APPLICATION_OBJECT_PATH) -item(_GTK_WINDOW_OBJECT_PATH) -item(_GTK_APP_MENU_OBJECT_PATH) -item(_GTK_MENUBAR_OBJECT_PATH) -item(_GTK_FRAME_EXTENTS) -item(_GTK_SHOW_WINDOW_MENU) -item(_GTK_EDGE_CONSTRAINTS) -item(_GTK_WORKAREAS) -item(_GNOME_WM_KEYBINDINGS) -item(_GNOME_PANEL_ACTION) -item(_GNOME_PANEL_ACTION_MAIN_MENU) -item(_GNOME_PANEL_ACTION_RUN_DIALOG) -item(_MUTTER_TIMESTAMP_PING) -item(_MUTTER_FOCUS_SET) -item(_MUTTER_SENTINEL) -item(_MUTTER_VERSION) -item(WM_CLIENT_MACHINE) -item(MANAGER) -item(TARGETS) -item(MULTIPLE) -item(TIMESTAMP) -item(VERSION) -item(ATOM_PAIR) -item(_XKB_RULES_NAMES) -item(WL_SURFACE_ID) -item(_XWAYLAND_MAY_GRAB_KEYBOARD) -item(_XWAYLAND_RANDR_EMU_MONITOR_RECTS) -item(_XWAYLAND_ALLOW_COMMITS) - -/* Oddities: These are used, and we need atoms for them, - * but when we need all _NET_WM hints (i.e. when we're making - * lists of which _NET_WM hints we support in order to advertise - * it) we haven't historically listed them. I don't know what - * the reason for this is. It may be a bug. - */ -item(_NET_WM_SYNC_REQUEST) -item(_NET_WM_SYNC_REQUEST_COUNTER) -item(_NET_WM_VISIBLE_NAME) -item(_NET_SUPPORTING_WM_CHECK) - -/* But I suppose it's quite reasonable not to advertise using - * _NET_SUPPORTED that we support _NET_SUPPORTED :) - */ -item(_NET_SUPPORTED) - -#endif /* !EWMH_ATOMS_ONLY */ - -/**************************************************************************/ - -item(_NET_WM_NAME) -item(_NET_CLOSE_WINDOW) -item(_NET_WM_STATE) -item(_NET_WM_STATE_SHADED) -item(_NET_WM_STATE_MAXIMIZED_HORZ) -item(_NET_WM_STATE_MAXIMIZED_VERT) -item(_NET_WM_DESKTOP) -item(_NET_NUMBER_OF_DESKTOPS) -item(_NET_CURRENT_DESKTOP) -item(_NET_WM_WINDOW_TYPE) -item(_NET_WM_WINDOW_TYPE_DESKTOP) -item(_NET_WM_WINDOW_TYPE_DOCK) -item(_NET_WM_WINDOW_TYPE_TOOLBAR) -item(_NET_WM_WINDOW_TYPE_MENU) -item(_NET_WM_WINDOW_TYPE_UTILITY) -item(_NET_WM_WINDOW_TYPE_SPLASH) -item(_NET_WM_WINDOW_TYPE_DIALOG) -item(_NET_WM_WINDOW_TYPE_DROPDOWN_MENU) -item(_NET_WM_WINDOW_TYPE_POPUP_MENU) -item(_NET_WM_WINDOW_TYPE_TOOLTIP) -item(_NET_WM_WINDOW_TYPE_NOTIFICATION) -item(_NET_WM_WINDOW_TYPE_COMBO) -item(_NET_WM_WINDOW_TYPE_DND) -item(_NET_WM_WINDOW_TYPE_NORMAL) -item(_NET_WM_STATE_MODAL) -item(_NET_CLIENT_LIST) -item(_NET_CLIENT_LIST_STACKING) -item(_NET_WM_STATE_SKIP_TASKBAR) -item(_NET_WM_STATE_SKIP_PAGER) -item(_NET_WM_ICON) -item(_NET_WM_ICON_GEOMETRY) -item(_NET_WM_MOVERESIZE) -item(_NET_ACTIVE_WINDOW) -item(_NET_WM_STRUT) -item(_NET_WM_STATE_HIDDEN) -item(_NET_WM_STATE_FULLSCREEN) -item(_NET_WM_PING) -item(_NET_WM_PID) -item(_NET_WORKAREA) -item(_NET_SHOWING_DESKTOP) -item(_NET_DESKTOP_LAYOUT) -item(_NET_DESKTOP_NAMES) -item(_NET_WM_ALLOWED_ACTIONS) -item(_NET_WM_ACTION_MOVE) -item(_NET_WM_ACTION_RESIZE) -item(_NET_WM_ACTION_SHADE) -item(_NET_WM_ACTION_STICK) -item(_NET_WM_ACTION_MAXIMIZE_HORZ) -item(_NET_WM_ACTION_MAXIMIZE_VERT) -item(_NET_WM_ACTION_CHANGE_DESKTOP) -item(_NET_WM_ACTION_CLOSE) -item(_NET_WM_STATE_ABOVE) -item(_NET_WM_STATE_BELOW) -item(_NET_STARTUP_ID) -item(_NET_WM_STRUT_PARTIAL) -item(_NET_WM_ACTION_FULLSCREEN) -item(_NET_WM_ACTION_MINIMIZE) -item(_NET_FRAME_EXTENTS) -item(_NET_REQUEST_FRAME_EXTENTS) -item(_NET_WM_USER_TIME) -item(_NET_WM_STATE_DEMANDS_ATTENTION) -item(_NET_MOVERESIZE_WINDOW) -item(_NET_DESKTOP_GEOMETRY) -item(_NET_DESKTOP_VIEWPORT) -item(_NET_WM_USER_TIME_WINDOW) -item(_NET_WM_ACTION_ABOVE) -item(_NET_WM_ACTION_BELOW) -item(_NET_WM_STATE_STICKY) -item(_NET_WM_FULLSCREEN_MONITORS) -item(_NET_WM_STATE_FOCUSED) -item(_NET_WM_BYPASS_COMPOSITOR) -item(_NET_WM_OPAQUE_REGION) -item(_NET_WM_FRAME_DRAWN) -item(_NET_WM_FRAME_TIMINGS) -item(_NET_WM_WINDOW_OPACITY) -item(_NET_RESTACK_WINDOW) - -/* eof atomnames.h */ - diff --git a/src/x11/events.c b/src/x11/events.c deleted file mode 100644 index 9dec73a9b..000000000 --- a/src/x11/events.c +++ /dev/null @@ -1,1936 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002, 2003, 2004 Red Hat, Inc. - * Copyright (C) 2003, 2004 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * 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 . - */ - -#include "config.h" - -#include "x11/events.h" - -#include -#include -#include -#include - -#include "backends/meta-cursor-tracker-private.h" -#include "backends/x11/meta-backend-x11.h" -#include "backends/x11/meta-cursor-tracker-x11.h" -#include "compositor/meta-compositor-x11.h" -#include "cogl/cogl.h" -#include "core/bell.h" -#include "core/display-private.h" -#include "core/meta-workspace-manager-private.h" -#include "core/window-private.h" -#include "core/workspace-private.h" -#include "meta/meta-backend.h" -#include "meta/meta-context.h" -#include "meta/meta-x11-errors.h" -#include "x11/meta-startup-notification-x11.h" -#include "x11/meta-x11-display-private.h" -#include "x11/meta-x11-selection-private.h" -#include "x11/meta-x11-selection-input-stream-private.h" -#include "x11/meta-x11-selection-output-stream-private.h" -#include "x11/window-x11.h" -#include "x11/xprops.h" - -#ifdef HAVE_WAYLAND -#include "wayland/meta-wayland-private.h" -#include "wayland/meta-xwayland-private.h" -#include "wayland/meta-xwayland.h" -#endif - -static XIEvent * -get_input_event (MetaX11Display *x11_display, - XEvent *event) -{ - if (event->type == GenericEvent && - event->xcookie.extension == x11_display->xinput_opcode) - { - XIEvent *input_event; - - /* NB: GDK event filters already have generic events - * allocated, so no need to do XGetEventData() on our own - */ - input_event = (XIEvent *) event->xcookie.data; - - switch (input_event->evtype) - { - case XI_Motion: - case XI_ButtonPress: - case XI_ButtonRelease: - if (((XIDeviceEvent *) input_event)->deviceid == META_VIRTUAL_CORE_POINTER_ID) - return input_event; - break; - case XI_KeyPress: - case XI_KeyRelease: - if (((XIDeviceEvent *) input_event)->deviceid == META_VIRTUAL_CORE_KEYBOARD_ID) - return input_event; - break; - case XI_FocusIn: - case XI_FocusOut: - if (((XIEnterEvent *) input_event)->deviceid == META_VIRTUAL_CORE_KEYBOARD_ID) - return input_event; - break; - case XI_Enter: - case XI_Leave: - if (((XIEnterEvent *) input_event)->deviceid == META_VIRTUAL_CORE_POINTER_ID) - return input_event; - break; - case XI_BarrierHit: - case XI_BarrierLeave: - if (((XIBarrierEvent *) input_event)->deviceid == META_VIRTUAL_CORE_POINTER_ID) - return input_event; - break; - default: - break; - } - } - - return NULL; -} - -static Window -xievent_get_modified_window (MetaX11Display *x11_display, - XIEvent *input_event) -{ - switch (input_event->evtype) - { - case XI_Motion: - case XI_ButtonPress: - case XI_ButtonRelease: - case XI_KeyPress: - case XI_KeyRelease: - return ((XIDeviceEvent *) input_event)->event; - case XI_FocusIn: - case XI_FocusOut: - case XI_Enter: - case XI_Leave: - return ((XIEnterEvent *) input_event)->event; - case XI_BarrierHit: - case XI_BarrierLeave: - return ((XIBarrierEvent *) input_event)->event; - } - - return None; -} - -/* Return the window this has to do with, if any, rather - * than the frame or root window that was selecting - * for substructure - */ -static Window -event_get_modified_window (MetaX11Display *x11_display, - XEvent *event) -{ - XIEvent *input_event = get_input_event (x11_display, event); - - if (input_event) - return xievent_get_modified_window (x11_display, input_event); - - switch (event->type) - { - case KeymapNotify: - case Expose: - case GraphicsExpose: - case NoExpose: - case VisibilityNotify: - case ResizeRequest: - case PropertyNotify: - case SelectionClear: - case SelectionRequest: - case SelectionNotify: - case ColormapNotify: - case ClientMessage: - return event->xany.window; - - case CreateNotify: - return event->xcreatewindow.window; - - case DestroyNotify: - return event->xdestroywindow.window; - - case UnmapNotify: - return event->xunmap.window; - - case MapNotify: - return event->xmap.window; - - case MapRequest: - return event->xmaprequest.window; - - case ReparentNotify: - return event->xreparent.window; - - case ConfigureNotify: - return event->xconfigure.window; - - case ConfigureRequest: - return event->xconfigurerequest.window; - - case GravityNotify: - return event->xgravity.window; - - case CirculateNotify: - return event->xcirculate.window; - - case CirculateRequest: - return event->xcirculaterequest.window; - - case MappingNotify: - return None; - - default: - if (META_X11_DISPLAY_HAS_SHAPE (x11_display) && - event->type == (x11_display->shape_event_base + ShapeNotify)) - { - XShapeEvent *sev = (XShapeEvent*) event; - return sev->window; - } - - return None; - } -} - -static guint32 -event_get_time (MetaX11Display *x11_display, - XEvent *event) -{ - XIEvent *input_event = get_input_event (x11_display, event); - - if (input_event) - return input_event->time; - - switch (event->type) - { - case PropertyNotify: - return event->xproperty.time; - - case SelectionClear: - case SelectionRequest: - case SelectionNotify: - return event->xselection.time; - - case KeymapNotify: - case Expose: - case GraphicsExpose: - case NoExpose: - case MapNotify: - case UnmapNotify: - case VisibilityNotify: - case ResizeRequest: - case ColormapNotify: - case ClientMessage: - case CreateNotify: - case DestroyNotify: - case MapRequest: - case ReparentNotify: - case ConfigureNotify: - case ConfigureRequest: - case GravityNotify: - case CirculateNotify: - case CirculateRequest: - case MappingNotify: - default: - return META_CURRENT_TIME; - } -} - -const char* -meta_event_detail_to_string (int d) -{ - const char *detail = "???"; - switch (d) - { - /* We are an ancestor in the A<->B focus change relationship */ - case XINotifyAncestor: - detail = "NotifyAncestor"; - break; - case XINotifyDetailNone: - detail = "NotifyDetailNone"; - break; - /* We are a descendant in the A<->B focus change relationship */ - case XINotifyInferior: - detail = "NotifyInferior"; - break; - case XINotifyNonlinear: - detail = "NotifyNonlinear"; - break; - case XINotifyNonlinearVirtual: - detail = "NotifyNonlinearVirtual"; - break; - case XINotifyPointer: - detail = "NotifyPointer"; - break; - case XINotifyPointerRoot: - detail = "NotifyPointerRoot"; - break; - case XINotifyVirtual: - detail = "NotifyVirtual"; - break; - } - - return detail; -} - -const char* -meta_event_mode_to_string (int m) -{ - const char *mode = "???"; - switch (m) - { - case XINotifyNormal: - mode = "NotifyNormal"; - break; - case XINotifyGrab: - mode = "NotifyGrab"; - break; - case XINotifyUngrab: - mode = "NotifyUngrab"; - break; - case XINotifyWhileGrabbed: - mode = "NotifyWhileGrabbed"; - break; - } - - return mode; -} - -G_GNUC_UNUSED static const char* -stack_mode_to_string (int mode) -{ - switch (mode) - { - case Above: - return "Above"; - case Below: - return "Below"; - case TopIf: - return "TopIf"; - case BottomIf: - return "BottomIf"; - case Opposite: - return "Opposite"; - } - - return "Unknown"; -} - -static gint64 -sync_value_to_64 (const XSyncValue *value) -{ - gint64 v; - - v = XSyncValueLow32 (*value); - v |= (((gint64)XSyncValueHigh32 (*value)) << 32); - - return v; -} - -static const char* -alarm_state_to_string (XSyncAlarmState state) -{ - switch (state) - { - case XSyncAlarmActive: - return "Active"; - case XSyncAlarmInactive: - return "Inactive"; - case XSyncAlarmDestroyed: - return "Destroyed"; - default: - return "(unknown)"; - } -} - -static void -meta_spew_xi2_event (MetaX11Display *x11_display, - XIEvent *input_event, - const char **name_p, - char **extra_p) -{ - const char *name = NULL; - char *extra = NULL; - - XIEnterEvent *enter_event = (XIEnterEvent *) input_event; - - switch (input_event->evtype) - { - case XI_FocusIn: - name = "XI_FocusIn"; - break; - case XI_FocusOut: - name = "XI_FocusOut"; - break; - case XI_Enter: - name = "XI_Enter"; - break; - case XI_Leave: - name = "XI_Leave"; - break; - case XI_BarrierHit: - name = "XI_BarrierHit"; - break; - case XI_BarrierLeave: - name = "XI_BarrierLeave"; - break; - } - - switch (input_event->evtype) - { - case XI_FocusIn: - case XI_FocusOut: - extra = g_strdup_printf ("detail: %s mode: %s\n", - meta_event_detail_to_string (enter_event->detail), - meta_event_mode_to_string (enter_event->mode)); - break; - case XI_Enter: - case XI_Leave: - extra = g_strdup_printf ("win: 0x%lx root: 0x%lx mode: %s detail: %s focus: %d x: %g y: %g", - enter_event->event, - enter_event->root, - meta_event_mode_to_string (enter_event->mode), - meta_event_detail_to_string (enter_event->detail), - enter_event->focus, - enter_event->root_x, - enter_event->root_y); - break; - } - - *name_p = name; - *extra_p = extra; -} - -static void -meta_spew_core_event (MetaX11Display *x11_display, - XEvent *event, - const char **name_p, - char **extra_p) -{ - const char *name = NULL; - char *extra = NULL; - - switch (event->type) - { - case KeymapNotify: - name = "KeymapNotify"; - break; - case Expose: - name = "Expose"; - break; - case GraphicsExpose: - name = "GraphicsExpose"; - break; - case NoExpose: - name = "NoExpose"; - break; - case VisibilityNotify: - name = "VisibilityNotify"; - break; - case CreateNotify: - name = "CreateNotify"; - extra = g_strdup_printf ("parent: 0x%lx window: 0x%lx", - event->xcreatewindow.parent, - event->xcreatewindow.window); - break; - case DestroyNotify: - name = "DestroyNotify"; - extra = g_strdup_printf ("event: 0x%lx window: 0x%lx", - event->xdestroywindow.event, - event->xdestroywindow.window); - break; - case UnmapNotify: - name = "UnmapNotify"; - extra = g_strdup_printf ("event: 0x%lx window: 0x%lx from_configure: %d", - event->xunmap.event, - event->xunmap.window, - event->xunmap.from_configure); - break; - case MapNotify: - name = "MapNotify"; - extra = g_strdup_printf ("event: 0x%lx window: 0x%lx override_redirect: %d", - event->xmap.event, - event->xmap.window, - event->xmap.override_redirect); - break; - case MapRequest: - name = "MapRequest"; - extra = g_strdup_printf ("window: 0x%lx parent: 0x%lx\n", - event->xmaprequest.window, - event->xmaprequest.parent); - break; - case ReparentNotify: - name = "ReparentNotify"; - extra = g_strdup_printf ("window: 0x%lx parent: 0x%lx event: 0x%lx\n", - event->xreparent.window, - event->xreparent.parent, - event->xreparent.event); - break; - case ConfigureNotify: - name = "ConfigureNotify"; - extra = g_strdup_printf ("x: %d y: %d w: %d h: %d above: 0x%lx override_redirect: %d", - event->xconfigure.x, - event->xconfigure.y, - event->xconfigure.width, - event->xconfigure.height, - event->xconfigure.above, - event->xconfigure.override_redirect); - break; - case ConfigureRequest: - name = "ConfigureRequest"; - extra = g_strdup_printf ("parent: 0x%lx window: 0x%lx x: %d %sy: %d %sw: %d %sh: %d %sborder: %d %sabove: %lx %sstackmode: %s %s", - event->xconfigurerequest.parent, - event->xconfigurerequest.window, - event->xconfigurerequest.x, - event->xconfigurerequest.value_mask & - CWX ? "" : "(unset) ", - event->xconfigurerequest.y, - event->xconfigurerequest.value_mask & - CWY ? "" : "(unset) ", - event->xconfigurerequest.width, - event->xconfigurerequest.value_mask & - CWWidth ? "" : "(unset) ", - event->xconfigurerequest.height, - event->xconfigurerequest.value_mask & - CWHeight ? "" : "(unset) ", - event->xconfigurerequest.border_width, - event->xconfigurerequest.value_mask & - CWBorderWidth ? "" : "(unset)", - event->xconfigurerequest.above, - event->xconfigurerequest.value_mask & - CWSibling ? "" : "(unset)", - stack_mode_to_string (event->xconfigurerequest.detail), - event->xconfigurerequest.value_mask & - CWStackMode ? "" : "(unset)"); - break; - case GravityNotify: - name = "GravityNotify"; - break; - case ResizeRequest: - name = "ResizeRequest"; - extra = g_strdup_printf ("width = %d height = %d", - event->xresizerequest.width, - event->xresizerequest.height); - break; - case CirculateNotify: - name = "CirculateNotify"; - break; - case CirculateRequest: - name = "CirculateRequest"; - break; - case PropertyNotify: - { - char *str; - const char *state; - - name = "PropertyNotify"; - - meta_x11_error_trap_push (x11_display); - str = XGetAtomName (x11_display->xdisplay, - event->xproperty.atom); - meta_x11_error_trap_pop (x11_display); - - if (event->xproperty.state == PropertyNewValue) - state = "PropertyNewValue"; - else if (event->xproperty.state == PropertyDelete) - state = "PropertyDelete"; - else - state = "???"; - - extra = g_strdup_printf ("atom: %s state: %s", - str ? str : "(unknown atom)", - state); - meta_XFree (str); - } - break; - case SelectionClear: - name = "SelectionClear"; - break; - case SelectionRequest: - name = "SelectionRequest"; - break; - case SelectionNotify: - name = "SelectionNotify"; - break; - case ColormapNotify: - name = "ColormapNotify"; - break; - case ClientMessage: - { - char *str; - name = "ClientMessage"; - meta_x11_error_trap_push (x11_display); - str = XGetAtomName (x11_display->xdisplay, - event->xclient.message_type); - meta_x11_error_trap_pop (x11_display); - extra = g_strdup_printf ("type: %s format: %d\n", - str ? str : "(unknown atom)", - event->xclient.format); - meta_XFree (str); - } - break; - case MappingNotify: - name = "MappingNotify"; - break; - default: - if (META_X11_DISPLAY_HAS_XSYNC (x11_display) && - event->type == (x11_display->xsync_event_base + XSyncAlarmNotify)) - { - XSyncAlarmNotifyEvent *aevent = (XSyncAlarmNotifyEvent*) event; - - name = "XSyncAlarmNotify"; - extra = - g_strdup_printf ("alarm: 0x%lx" - " counter_value: %" G_GINT64_FORMAT - " alarm_value: %" G_GINT64_FORMAT - " time: %u alarm state: %s", - aevent->alarm, - (gint64) sync_value_to_64 (&aevent->counter_value), - (gint64) sync_value_to_64 (&aevent->alarm_value), - (unsigned int)aevent->time, - alarm_state_to_string (aevent->state)); - } - else - if (META_X11_DISPLAY_HAS_SHAPE (x11_display) && - event->type == (x11_display->shape_event_base + ShapeNotify)) - { - XShapeEvent *sev = (XShapeEvent*) event; - - name = "ShapeNotify"; - - extra = - g_strdup_printf ("kind: %s " - "x: %d y: %d w: %u h: %u " - "shaped: %d", - sev->kind == ShapeBounding ? - "ShapeBounding" : - (sev->kind == ShapeClip ? - "ShapeClip" : "(unknown)"), - sev->x, sev->y, sev->width, sev->height, - sev->shaped); - } - else - { - name = "(Unknown event)"; - extra = g_strdup_printf ("type: %d", event->xany.type); - } - break; - } - - *name_p = name; - *extra_p = extra; -} - -static char * -meta_spew_event (MetaX11Display *x11_display, - XEvent *event) -{ - const char *name = NULL; - char *extra = NULL; - char *winname; - char *ret; - XIEvent *input_event; - - input_event = get_input_event (x11_display, event); - - if (input_event) - meta_spew_xi2_event (x11_display, input_event, &name, &extra); - else - meta_spew_core_event (x11_display, event, &name, &extra); - - if (event->xany.window == x11_display->xroot) - winname = g_strdup_printf ("root"); - else - winname = g_strdup_printf ("0x%lx", event->xany.window); - - ret = g_strdup_printf ("%s on %s%s %s %sserial %lu", name, winname, - extra ? ":" : "", extra ? extra : "", - event->xany.send_event ? "SEND " : "", - event->xany.serial); - - g_free (winname); - g_free (extra); - - return ret; -} - -G_GNUC_UNUSED static void -meta_spew_event_print (MetaX11Display *x11_display, - XEvent *event) -{ - char *event_str; - - /* filter overnumerous events */ - if (event->type == Expose || event->type == MotionNotify || - event->type == NoExpose) - return; - - if (event->type == (x11_display->damage_event_base + XDamageNotify)) - return; - - if (event->type == (x11_display->xsync_event_base + XSyncAlarmNotify)) - return; - - if (event->type == PropertyNotify && - event->xproperty.atom == x11_display->atom__NET_WM_USER_TIME) - return; - - event_str = meta_spew_event (x11_display, event); - g_print ("%s\n", event_str); - g_free (event_str); -} - -static gboolean -handle_window_focus_event (MetaX11Display *x11_display, - MetaWindow *window, - XIEnterEvent *event, - unsigned long serial) -{ - MetaDisplay *display = x11_display->display; - MetaWindow *focus_window; -#ifdef WITH_VERBOSE_MODE - const char *window_type; - - /* Note the event can be on either the window or the frame, - * we focus the frame for shaded windows - */ - if (window) - { - if (event->event == window->xwindow) - window_type = "client window"; - else if (window->frame && event->event == window->frame->xwindow) - window_type = "frame window"; - else - window_type = "unknown client window"; - } - else if (meta_x11_display_xwindow_is_a_no_focus_window (x11_display, - event->event)) - window_type = "no_focus_window"; - else if (event->event == x11_display->xroot) - window_type = "root window"; - else - window_type = "unknown window"; - - meta_topic (META_DEBUG_FOCUS, - "Focus %s event received on %s 0x%lx (%s) " - "mode %s detail %s serial %lu", - event->evtype == XI_FocusIn ? "in" : - event->evtype == XI_FocusOut ? "out" : - "???", - window ? window->desc : "", - event->event, window_type, - meta_event_mode_to_string (event->mode), - meta_event_detail_to_string (event->mode), - serial); -#endif - - /* FIXME our pointer tracking is broken; see how - * gtk+/gdk/x11/gdkevents-x11.c or XFree86/xc/programs/xterm/misc.c - * for how to handle it the correct way. In brief you need to track - * pointer focus and regular focus, and handle EnterNotify in - * PointerRoot mode with no window manager. However as noted above, - * accurate focus tracking will break things because we want to keep - * windows "focused" when using keybindings on them, and also we - * sometimes "focus" a window by focusing its frame or - * no_focus_window; so this all needs rethinking massively. - * - * My suggestion is to change it so that we clearly separate - * actual keyboard focus tracking using the xterm algorithm, - * and mutter's "pretend" focus window, and go through all - * the code and decide which one should be used in each place; - * a hard bit is deciding on a policy for that. - * - * http://bugzilla.gnome.org/show_bug.cgi?id=90382 - */ - - /* We ignore grabs, though this is questionable. It may be better to - * increase the intelligence of the focus window tracking. - * - * The problem is that keybindings for windows are done with - * XGrabKey, which means focus_window disappears and the front of - * the MRU list gets confused from what the user expects once a - * keybinding is used. - */ - - if (event->mode == XINotifyGrab || - event->mode == XINotifyUngrab || - /* From WindowMaker, ignore all funky pointer root events */ - event->detail > XINotifyNonlinearVirtual) - { - meta_topic (META_DEBUG_FOCUS, - "Ignoring focus event generated by a grab or other weirdness"); - return FALSE; - } - - if (event->evtype == XI_FocusIn) - { - x11_display->server_focus_window = event->event; - x11_display->server_focus_serial = serial; - focus_window = window; - } - else if (event->evtype == XI_FocusOut) - { - if (event->detail == XINotifyInferior) - { - /* This event means the client moved focus to a subwindow */ - meta_topic (META_DEBUG_FOCUS, - "Ignoring focus out with NotifyInferior"); - return FALSE; - } - - x11_display->server_focus_window = None; - x11_display->server_focus_serial = serial; - focus_window = NULL; - } - else - g_assert_not_reached (); - - /* If display->focused_by_us, then the focus_serial will be used only - * for a focus change we made and have already accounted for. - * (See request_xserver_input_focus_change().) Otherwise, we can get - * multiple focus events with the same serial. - */ - if (x11_display->server_focus_serial > x11_display->focus_serial || - (!x11_display->focused_by_us && - x11_display->server_focus_serial == x11_display->focus_serial)) - { - meta_x11_display_update_focus_window (x11_display, - focus_window ? - focus_window->xwindow : None, - x11_display->server_focus_serial, - FALSE); - meta_display_update_focus_window (display, focus_window); - return TRUE; - } - else - { - return FALSE; - } -} - -static gboolean -crossing_serial_is_ignored (MetaX11Display *x11_display, - unsigned long serial) -{ - int i; - - i = 0; - while (i < N_IGNORED_CROSSING_SERIALS) - { - if (x11_display->display->ignored_crossing_serials[i] == serial) - return TRUE; - ++i; - } - return FALSE; -} - -static gboolean -handle_input_xevent (MetaX11Display *x11_display, - XIEvent *input_event, - unsigned long serial) -{ - XIEnterEvent *enter_event = (XIEnterEvent *) input_event; - Window modified; - MetaWindow *window; - MetaDisplay *display = x11_display->display; - MetaWorkspaceManager *workspace_manager = display->workspace_manager; - - if (input_event == NULL) - return FALSE; - - switch (input_event->evtype) - { - case XI_Enter: - case XI_Leave: - case XI_FocusIn: - case XI_FocusOut: - break; - default: - return FALSE; - } - - modified = xievent_get_modified_window (x11_display, input_event); - window = modified != None ? - meta_x11_display_lookup_x_window (x11_display, modified) : - NULL; - - /* If this is an event for a GTK+ widget, let GTK+ handle it. */ - if (meta_ui_window_is_widget (x11_display->ui, modified)) - return FALSE; - - switch (input_event->evtype) - { - case XI_Enter: - if (display->event_route != META_EVENT_ROUTE_NORMAL) - break; - - /* Check if we've entered a window; do this even if window->has_focus to - * avoid races. - */ - if (window && !crossing_serial_is_ignored (x11_display, serial) && - enter_event->mode != XINotifyGrab && - enter_event->mode != XINotifyUngrab && - enter_event->detail != XINotifyInferior && - meta_x11_display_focus_sentinel_clear (x11_display)) - { - meta_window_handle_enter (window, - enter_event->time, - enter_event->root_x, - enter_event->root_y); - } - break; - case XI_Leave: - if (display->event_route != META_EVENT_ROUTE_NORMAL) - break; - - if (window != NULL && - enter_event->mode != XINotifyGrab && - enter_event->mode != XINotifyUngrab) - { - meta_window_handle_leave (window); - } - break; - case XI_FocusIn: - case XI_FocusOut: - if (handle_window_focus_event (x11_display, window, enter_event, serial) && - enter_event->event == enter_event->root) - { - if (enter_event->evtype == XI_FocusIn && - enter_event->detail == XINotifyDetailNone) - { - meta_topic (META_DEBUG_FOCUS, - "Focus got set to None, probably due to " - "brain-damage in the X protocol (see bug " - "125492). Setting the default focus window."); - meta_workspace_focus_default_window (workspace_manager->active_workspace, - NULL, - meta_x11_display_get_current_time_roundtrip (x11_display)); - } - else if (enter_event->evtype == XI_FocusIn && - enter_event->mode == XINotifyNormal && - enter_event->detail == XINotifyInferior) - { - meta_topic (META_DEBUG_FOCUS, - "Focus got set to root window, probably due to " - "gnome-session logout dialog usage (see bug " - "153220). Setting the default focus window."); - meta_workspace_focus_default_window (workspace_manager->active_workspace, - NULL, - meta_x11_display_get_current_time_roundtrip (x11_display)); - } - } - break; - } - - /* Don't eat events for GTK frames (we need to update the :hover state on buttons) */ - if (window && window->frame && modified == window->frame->xwindow) - return FALSE; - - /* Don't pass these events through to Clutter / GTK+ */ - return TRUE; -} - -static void -process_request_frame_extents (MetaX11Display *x11_display, - XEvent *event) -{ - /* The X window whose frame extents will be set. */ - Window xwindow = event->xclient.window; - unsigned long data[4] = { 0, 0, 0, 0 }; - - MotifWmHints *hints = NULL; - gboolean hints_set = FALSE; - - meta_verbose ("Setting frame extents for 0x%lx", xwindow); - - /* See if the window is decorated. */ - hints_set = meta_prop_get_motif_hints (x11_display, - xwindow, - x11_display->atom__MOTIF_WM_HINTS, - &hints); - if ((hints_set && hints->decorations) || !hints_set) - { - MetaFrameBorders borders; - - /* Return estimated frame extents for a normal window. */ - meta_ui_theme_get_frame_borders (x11_display->ui, - META_FRAME_TYPE_NORMAL, - 0, - &borders); - data[0] = borders.visible.left; - data[1] = borders.visible.right; - data[2] = borders.visible.top; - data[3] = borders.visible.bottom; - } - - meta_topic (META_DEBUG_GEOMETRY, - "Setting _NET_FRAME_EXTENTS on unmanaged window 0x%lx " - "to top = %lu, left = %lu, bottom = %lu, right = %lu", - xwindow, data[0], data[1], data[2], data[3]); - - meta_x11_error_trap_push (x11_display); - XChangeProperty (x11_display->xdisplay, xwindow, - x11_display->atom__NET_FRAME_EXTENTS, - XA_CARDINAL, - 32, PropModeReplace, (guchar*) data, 4); - meta_x11_error_trap_pop (x11_display); - - g_free (hints); -} - -/* from fvwm2, Copyright Matthias Clasen, Dominik Vogt */ -static gboolean -convert_property (MetaX11Display *x11_display, - Window w, - Atom target, - Atom property) -{ -#define N_TARGETS 4 - Atom conversion_targets[N_TARGETS]; - long icccm_version[] = { 2, 0 }; - - conversion_targets[0] = x11_display->atom_TARGETS; - conversion_targets[1] = x11_display->atom_MULTIPLE; - conversion_targets[2] = x11_display->atom_TIMESTAMP; - conversion_targets[3] = x11_display->atom_VERSION; - - meta_x11_error_trap_push (x11_display); - if (target == x11_display->atom_TARGETS) - XChangeProperty (x11_display->xdisplay, w, property, - XA_ATOM, 32, PropModeReplace, - (unsigned char *)conversion_targets, N_TARGETS); - else if (target == x11_display->atom_TIMESTAMP) - XChangeProperty (x11_display->xdisplay, w, property, - XA_INTEGER, 32, PropModeReplace, - (unsigned char *)&x11_display->wm_sn_timestamp, 1); - else if (target == x11_display->atom_VERSION) - XChangeProperty (x11_display->xdisplay, w, property, - XA_INTEGER, 32, PropModeReplace, - (unsigned char *)icccm_version, 2); - else - { - meta_x11_error_trap_pop_with_return (x11_display); - return FALSE; - } - - if (meta_x11_error_trap_pop_with_return (x11_display) != Success) - return FALSE; - - /* Be sure the PropertyNotify has arrived so we - * can send SelectionNotify - */ - /* FIXME the error trap pop synced anyway, right? */ - meta_topic (META_DEBUG_SYNC, "Syncing on %s", G_STRFUNC); - XSync (x11_display->xdisplay, False); - - return TRUE; -} - -/* from fvwm2, Copyright Matthias Clasen, Dominik Vogt */ -static void -process_selection_request (MetaX11Display *x11_display, - XEvent *event) -{ - XSelectionEvent reply; - - if (x11_display->wm_sn_selection_window != event->xselectionrequest.owner || - x11_display->wm_sn_atom != event->xselectionrequest.selection) - { - char *str; - - meta_x11_error_trap_push (x11_display); - str = XGetAtomName (x11_display->xdisplay, - event->xselectionrequest.selection); - meta_x11_error_trap_pop (x11_display); - - meta_verbose ("Selection request with selection %s window 0x%lx not a WM_Sn selection we recognize", - str ? str : "(bad atom)", event->xselectionrequest.owner); - - meta_XFree (str); - - return; - } - - reply.type = SelectionNotify; - reply.display = x11_display->xdisplay; - reply.requestor = event->xselectionrequest.requestor; - reply.selection = event->xselectionrequest.selection; - reply.target = event->xselectionrequest.target; - reply.property = None; - reply.time = event->xselectionrequest.time; - - if (event->xselectionrequest.target == x11_display->atom_MULTIPLE) - { - if (event->xselectionrequest.property != None) - { - Atom type, *adata; - int i, format; - unsigned long num, rest; - unsigned char *data; - - meta_x11_error_trap_push (x11_display); - if (XGetWindowProperty (x11_display->xdisplay, - event->xselectionrequest.requestor, - event->xselectionrequest.property, 0, 256, False, - x11_display->atom_ATOM_PAIR, - &type, &format, &num, &rest, &data) != Success) - { - meta_x11_error_trap_pop_with_return (x11_display); - return; - } - - if (meta_x11_error_trap_pop_with_return (x11_display) == Success) - { - /* FIXME: to be 100% correct, should deal with rest > 0, - * but since we have 4 possible targets, we will hardly ever - * meet multiple requests with a length > 8 - */ - adata = (Atom*)data; - i = 0; - while (i < (int) num) - { - if (!convert_property (x11_display, - event->xselectionrequest.requestor, - adata[i], adata[i+1])) - adata[i+1] = None; - i += 2; - } - - meta_x11_error_trap_push (x11_display); - XChangeProperty (x11_display->xdisplay, - event->xselectionrequest.requestor, - event->xselectionrequest.property, - x11_display->atom_ATOM_PAIR, - 32, PropModeReplace, data, num); - meta_x11_error_trap_pop (x11_display); - meta_XFree (data); - } - } - } - else - { - if (event->xselectionrequest.property == None) - event->xselectionrequest.property = event->xselectionrequest.target; - - if (convert_property (x11_display, - event->xselectionrequest.requestor, - event->xselectionrequest.target, - event->xselectionrequest.property)) - reply.property = event->xselectionrequest.property; - } - - XSendEvent (x11_display->xdisplay, - event->xselectionrequest.requestor, - False, 0L, (XEvent*)&reply); - - meta_verbose ("Handled selection request"); -} - -static gboolean -close_display_idle_cb (gpointer user_data) -{ - MetaX11Display *x11_display = META_X11_DISPLAY (user_data); - MetaDisplay *display = x11_display->display; - MetaContext *context = meta_display_get_context (display); - - meta_display_close (display, - x11_display->xselectionclear_timestamp); - x11_display->display_close_idle = 0; - meta_context_terminate (context); - - return G_SOURCE_REMOVE; -} - -static gboolean -process_selection_clear (MetaX11Display *x11_display, - XEvent *event) -{ - if (x11_display->wm_sn_selection_window != event->xselectionclear.window || - x11_display->wm_sn_atom != event->xselectionclear.selection) - { - char *str; - - meta_x11_error_trap_push (x11_display); - str = XGetAtomName (x11_display->xdisplay, - event->xselectionclear.selection); - meta_x11_error_trap_pop (x11_display); - - meta_verbose ("Selection clear with selection %s window 0x%lx not a WM_Sn selection we recognize", - str ? str : "(bad atom)", event->xselectionclear.window); - - meta_XFree (str); - - return FALSE; - } - - meta_verbose ("Got selection clear for on display %s", - x11_display->name); - - /* We can't close a GdkDisplay in an even handler. */ - if (!x11_display->display_close_idle) - { - x11_display->xselectionclear_timestamp = event->xselectionclear.time; - x11_display->display_close_idle = g_idle_add (close_display_idle_cb, x11_display); - } - - return TRUE; -} - -static void -notify_bell (MetaX11Display *x11_display, - XkbAnyEvent *xkb_ev) -{ - MetaDisplay *display = x11_display->display; - XkbBellNotifyEvent *xkb_bell_event = (XkbBellNotifyEvent*) xkb_ev; - MetaWindow *window; - - window = meta_x11_display_lookup_x_window (x11_display, - xkb_bell_event->window); - if (!window && display->focus_window && display->focus_window->frame) - window = display->focus_window; - - x11_display->last_bell_time = xkb_ev->time; - if (!meta_bell_notify (display, window) && - meta_prefs_bell_is_audible ()) - { - /* Force a classic bell if the libcanberra bell failed. */ - XkbForceDeviceBell (x11_display->xdisplay, - xkb_bell_event->device, - xkb_bell_event->bell_class, - xkb_bell_event->bell_id, - xkb_bell_event->percent); - } -} - -static gboolean -handle_other_xevent (MetaX11Display *x11_display, - XEvent *event) -{ - MetaDisplay *display = x11_display->display; - MetaWorkspaceManager *workspace_manager = display->workspace_manager; - Window modified; - MetaWindow *window; - MetaWindow *property_for_window; - gboolean frame_was_receiver; - gboolean bypass_gtk = FALSE; - - modified = event_get_modified_window (x11_display, event); - window = modified != None ? meta_x11_display_lookup_x_window (x11_display, modified) : NULL; - frame_was_receiver = (window && window->frame && modified == window->frame->xwindow); - - /* We only want to respond to _NET_WM_USER_TIME property notify - * events on _NET_WM_USER_TIME_WINDOW windows; in particular, - * responding to UnmapNotify events is kind of bad. - */ - property_for_window = NULL; - if (window && modified == window->user_time_window) - { - property_for_window = window; - window = NULL; - } - - if (META_X11_DISPLAY_HAS_XSYNC (x11_display) && - event->type == (x11_display->xsync_event_base + XSyncAlarmNotify)) - { - MetaWindow *alarm_window = meta_x11_display_lookup_sync_alarm (x11_display, - ((XSyncAlarmNotifyEvent*)event)->alarm); - - if (alarm_window != NULL) - { - XSyncValue value = ((XSyncAlarmNotifyEvent*)event)->counter_value; - gint64 new_counter_value; - new_counter_value = XSyncValueLow32 (value) + ((gint64)XSyncValueHigh32 (value) << 32); - meta_window_x11_update_sync_request_counter (alarm_window, new_counter_value); - bypass_gtk = TRUE; /* GTK doesn't want to see this really */ - } - else - { - if (x11_display->alarm_filter && - x11_display->alarm_filter (x11_display, - (XSyncAlarmNotifyEvent*)event, - x11_display->alarm_filter_data)) - bypass_gtk = TRUE; - } - - goto out; - } - - if (META_X11_DISPLAY_HAS_SHAPE (x11_display) && - event->type == (x11_display->shape_event_base + ShapeNotify)) - { - bypass_gtk = TRUE; /* GTK doesn't want to see this really */ - - if (window && !frame_was_receiver) - { - XShapeEvent *sev = (XShapeEvent*) event; - - if (sev->kind == ShapeBounding) - meta_window_x11_update_shape_region (window); - else if (sev->kind == ShapeInput) - meta_window_x11_update_input_region (window); - } - else - { - meta_topic (META_DEBUG_SHAPES, - "ShapeNotify not on a client window (window %s frame_was_receiver = %d)", - window ? window->desc : "(none)", - frame_was_receiver); - } - - goto out; - } - - switch (event->type) - { - case KeymapNotify: - break; - case Expose: - break; - case GraphicsExpose: - break; - case NoExpose: - break; - case VisibilityNotify: - break; - case CreateNotify: - { - if (event->xcreatewindow.parent == x11_display->xroot) - meta_stack_tracker_create_event (display->stack_tracker, - &event->xcreatewindow); - } - break; - - case DestroyNotify: - { - if (event->xdestroywindow.event == x11_display->xroot) - meta_stack_tracker_destroy_event (display->stack_tracker, - &event->xdestroywindow); - } - if (window) - { - /* FIXME: It sucks that DestroyNotify events don't come with - * a timestamp; could we do something better here? Maybe X - * will change one day? - */ - guint32 timestamp; - timestamp = meta_display_get_current_time_roundtrip (display); - - if (display->grab_op != META_GRAB_OP_NONE && - display->grab_window == window) - meta_display_end_grab_op (display, timestamp); - - if (frame_was_receiver) - { - meta_warning ("Unexpected destruction of frame 0x%lx, not sure if this should silently fail or be considered a bug", - window->frame->xwindow); - meta_x11_error_trap_push (x11_display); - meta_window_destroy_frame (window->frame->window); - meta_x11_error_trap_pop (x11_display); - } - else - { - /* Unmanage destroyed window */ - meta_window_unmanage (window, timestamp); - window = NULL; - } - } - break; - case UnmapNotify: - if (window) - { - /* FIXME: It sucks that UnmapNotify events don't come with - * a timestamp; could we do something better here? Maybe X - * will change one day? - */ - guint32 timestamp; - timestamp = meta_display_get_current_time_roundtrip (display); - - if (display->grab_op != META_GRAB_OP_NONE && - display->grab_window == window && - window->frame == NULL) - meta_display_end_grab_op (display, timestamp); - - if (!frame_was_receiver) - { - if (window->unmaps_pending == 0) - { - meta_topic (META_DEBUG_WINDOW_STATE, - "Window %s withdrawn", - window->desc); - - /* Unmanage withdrawn window */ - window->withdrawn = TRUE; - meta_window_unmanage (window, timestamp); - window = NULL; - } - else - { - window->unmaps_pending -= 1; - meta_topic (META_DEBUG_WINDOW_STATE, - "Received pending unmap, %d now pending", - window->unmaps_pending); - } - } - } - break; - case MapNotify: - /* NB: override redirect windows won't cause a map request so we - * watch out for map notifies against any root windows too if a - * compositor is enabled: */ - if (window == NULL && event->xmap.event == x11_display->xroot) - { - window = meta_window_x11_new (display, event->xmap.window, - FALSE, META_COMP_EFFECT_CREATE); - } - else if (window && window->restore_focus_on_map && - window->reparents_pending == 0) - { - meta_window_focus (window, - meta_display_get_current_time_roundtrip (display)); - } - - break; - case MapRequest: - if (window == NULL) - { - window = meta_window_x11_new (display, event->xmaprequest.window, - FALSE, META_COMP_EFFECT_CREATE); - /* The window might have initial iconic state, but this is a - * MapRequest, fall through to ensure it is unminimized in - * that case. - */ - } - else if (frame_was_receiver) - { - meta_warning ("Map requests on the frame window are unexpected"); - break; - } - - /* Double check that creating the MetaWindow succeeded */ - if (window == NULL) - break; - - meta_verbose ("MapRequest on %s mapped = %d minimized = %d", - window->desc, window->mapped, window->minimized); - - if (window->minimized) - { - meta_window_unminimize (window); - if (window->workspace != workspace_manager->active_workspace) - { - meta_verbose ("Changing workspace due to MapRequest mapped = %d minimized = %d", - window->mapped, window->minimized); - meta_window_change_workspace (window, - workspace_manager->active_workspace); - } - } - break; - case ReparentNotify: - { - if (window && window->reparents_pending > 0) - window->reparents_pending -= 1; - if (event->xreparent.event == x11_display->xroot) - meta_stack_tracker_reparent_event (display->stack_tracker, - &event->xreparent); - } - break; - case ConfigureNotify: - if (event->xconfigure.event != event->xconfigure.window) - { - if (event->xconfigure.event == x11_display->xroot && - event->xconfigure.window != x11_display->composite_overlay_window) - meta_stack_tracker_configure_event (display->stack_tracker, - &event->xconfigure); - } - - if (window && window->override_redirect) - meta_window_x11_configure_notify (window, &event->xconfigure); - - break; - case ConfigureRequest: - /* This comment and code is found in both twm and fvwm */ - /* - * According to the July 27, 1988 ICCCM draft, we should ignore size and - * position fields in the WM_NORMAL_HINTS property when we map a window. - * Instead, we'll read the current geometry. Therefore, we should respond - * to configuration requests for windows which have never been mapped. - */ - if (window == NULL) - { - unsigned int xwcm; - XWindowChanges xwc; - - xwcm = event->xconfigurerequest.value_mask & - (CWX | CWY | CWWidth | CWHeight | CWBorderWidth); - - xwc.x = event->xconfigurerequest.x; - xwc.y = event->xconfigurerequest.y; - xwc.width = event->xconfigurerequest.width; - xwc.height = event->xconfigurerequest.height; - xwc.border_width = event->xconfigurerequest.border_width; - - meta_verbose ("Configuring withdrawn window to %d,%d %dx%d border %d (some values may not be in mask)", - xwc.x, xwc.y, xwc.width, xwc.height, xwc.border_width); - meta_x11_error_trap_push (x11_display); - XConfigureWindow (x11_display->xdisplay, event->xconfigurerequest.window, - xwcm, &xwc); - meta_x11_error_trap_pop (x11_display); - } - else - { - if (!frame_was_receiver) - meta_window_x11_configure_request (window, event); - } - break; - case GravityNotify: - break; - case ResizeRequest: - break; - case CirculateNotify: - break; - case CirculateRequest: - break; - case PropertyNotify: - { - MetaGroup *group; - - if (window && !frame_was_receiver) - meta_window_x11_property_notify (window, event); - else if (property_for_window && !frame_was_receiver) - meta_window_x11_property_notify (property_for_window, event); - - group = meta_x11_display_lookup_group (x11_display, - event->xproperty.window); - if (group != NULL) - meta_group_property_notify (group, event); - - if (event->xproperty.window == x11_display->xroot) - { - if (event->xproperty.atom == - x11_display->atom__NET_DESKTOP_LAYOUT) - meta_x11_display_update_workspace_layout (x11_display); - else if (event->xproperty.atom == - x11_display->atom__NET_DESKTOP_NAMES) - meta_x11_display_update_workspace_names (x11_display); - - /* we just use this property as a sentinel to avoid - * certain race conditions. See the comment for the - * sentinel_counter variable declaration in display.h - */ - if (event->xproperty.atom == - x11_display->atom__MUTTER_SENTINEL) - { - meta_x11_display_decrement_focus_sentinel (x11_display); - } - } - } - break; - case SelectionRequest: - process_selection_request (x11_display, event); - break; - case SelectionNotify: - break; - case ColormapNotify: - break; - case ClientMessage: - if (window) - { -#ifdef HAVE_WAYLAND - if (event->xclient.message_type == x11_display->atom_WL_SURFACE_ID) - { - guint32 surface_id = event->xclient.data.l[0]; - meta_xwayland_handle_wl_surface_id (window, surface_id); - } - else if (event->xclient.message_type == - x11_display->atom__XWAYLAND_MAY_GRAB_KEYBOARD) - { - if (meta_is_wayland_compositor ()) - g_object_set (G_OBJECT (window), - "xwayland-may-grab-keyboard", (event->xclient.data.l[0] != 0), - NULL); - } - else -#endif - if (!frame_was_receiver) - meta_window_x11_client_message (window, event); - } - else - { - if (event->xclient.window == x11_display->xroot) - { - if (event->xclient.message_type == - x11_display->atom__NET_CURRENT_DESKTOP) - { - int space; - MetaWorkspace *workspace; - guint32 time; - - space = event->xclient.data.l[0]; - time = event->xclient.data.l[1]; - - meta_verbose ("Request to change current workspace to %d with " - "specified timestamp of %u", - space, time); - - workspace = meta_workspace_manager_get_workspace_by_index (workspace_manager, space); - - if (workspace) - { - /* Handle clients using the older version of the spec... */ - if (time == 0) - time = meta_x11_display_get_current_time_roundtrip (x11_display); - - meta_workspace_activate (workspace, time); - } - else - { - meta_verbose ("Don't know about workspace %d", space); - } - } - else if (event->xclient.message_type == - x11_display->atom__NET_NUMBER_OF_DESKTOPS) - { - int num_spaces; - - num_spaces = event->xclient.data.l[0]; - - meta_verbose ("Request to set number of workspaces to %d", - num_spaces); - - meta_prefs_set_num_workspaces (num_spaces); - } - else if (event->xclient.message_type == - x11_display->atom__NET_SHOWING_DESKTOP) - { - gboolean showing_desktop; - guint32 timestamp; - - showing_desktop = event->xclient.data.l[0] != 0; - /* FIXME: Braindead protocol doesn't have a timestamp */ - timestamp = meta_x11_display_get_current_time_roundtrip (x11_display); - meta_verbose ("Request to %s desktop", - showing_desktop ? "show" : "hide"); - - if (showing_desktop) - meta_workspace_manager_show_desktop (workspace_manager, timestamp); - else - { - meta_workspace_manager_unshow_desktop (workspace_manager); - meta_workspace_focus_default_window (workspace_manager->active_workspace, NULL, timestamp); - } - } - else if (event->xclient.message_type == - x11_display->atom_WM_PROTOCOLS) - { - meta_verbose ("Received WM_PROTOCOLS message"); - - if ((Atom)event->xclient.data.l[0] == x11_display->atom__NET_WM_PING) - { - guint32 timestamp = event->xclient.data.l[1]; - - meta_display_pong_for_serial (display, timestamp); - - /* We don't want ping reply events going into - * the GTK+ event loop because gtk+ will treat - * them as ping requests and send more replies. - */ - bypass_gtk = TRUE; - } - } - } - - if (event->xclient.message_type == - x11_display->atom__NET_REQUEST_FRAME_EXTENTS) - { - meta_verbose ("Received _NET_REQUEST_FRAME_EXTENTS message"); - process_request_frame_extents (x11_display, event); - } - } - break; - case MappingNotify: - { - gboolean ignore_current; - - ignore_current = FALSE; - - /* Check whether the next event is an identical MappingNotify - * event. If it is, ignore the current event, we'll update - * when we get the next one. - */ - if (XPending (x11_display->xdisplay)) - { - XEvent next_event; - - XPeekEvent (x11_display->xdisplay, &next_event); - - if (next_event.type == MappingNotify && - next_event.xmapping.request == event->xmapping.request) - ignore_current = TRUE; - } - - if (!ignore_current) - { - /* Let XLib know that there is a new keyboard mapping. - */ - XRefreshKeyboardMapping (&event->xmapping); - } - } - break; - default: - if (event->type == x11_display->xkb_base_event_type) - { - XkbAnyEvent *xkb_ev = (XkbAnyEvent *) event; - - switch (xkb_ev->xkb_type) - { - case XkbBellNotify: - if (XSERVER_TIME_IS_BEFORE(x11_display->last_bell_time, - xkb_ev->time - 100)) - { - notify_bell (x11_display, xkb_ev); - } - break; - default: - break; - } - } - break; - } - - out: - return bypass_gtk; -} - -static gboolean -window_has_xwindow (MetaWindow *window, - Window xwindow) -{ - if (window->xwindow == xwindow) - return TRUE; - - if (window->frame && window->frame->xwindow == xwindow) - return TRUE; - - return FALSE; -} - -static gboolean -process_selection_event (MetaX11Display *x11_display, - XEvent *event) -{ - gboolean handled = FALSE; - GList *l; - - handled |= meta_x11_selection_handle_event (x11_display, event); - - for (l = x11_display->selection.input_streams; l && !handled;) - { - GList *next = l->next; - - handled |= meta_x11_selection_input_stream_xevent (l->data, event); - l = next; - } - - for (l = x11_display->selection.output_streams; l && !handled;) - { - GList *next = l->next; - - handled |= meta_x11_selection_output_stream_xevent (l->data, event); - l = next; - } - - return handled; -} - -/** - * meta_display_handle_xevent: - * @display: The MetaDisplay that events are coming from - * @event: The event that just happened - * - * This is the most important function in the whole program. It is the heart, - * it is the nexus, it is the Grand Central Station of Mutter's world. - * When we create a #MetaDisplay, we ask GDK to pass *all* events for *all* - * windows to this function. So every time anything happens that we might - * want to know about, this function gets called. You see why it gets a bit - * busy around here. Most of this function is a ginormous switch statement - * dealing with all the kinds of events that might turn up. - */ -static gboolean -meta_x11_display_handle_xevent (MetaX11Display *x11_display, - XEvent *event) -{ - MetaDisplay *display = x11_display->display; - MetaBackend *backend = meta_get_backend (); - Window modified; - gboolean bypass_compositor = FALSE, bypass_gtk = FALSE; - XIEvent *input_event; - MetaCursorTracker *cursor_tracker; - - COGL_TRACE_BEGIN_SCOPED (MetaX11DisplayHandleXevent, - "X11Display (handle X11 event)"); - -#if 0 - meta_spew_event_print (x11_display, event); -#endif - - if (meta_x11_startup_notification_handle_xevent (x11_display, event)) - { - bypass_gtk = bypass_compositor = TRUE; - goto out; - } - -#ifdef HAVE_WAYLAND - if (meta_is_wayland_compositor () && - meta_xwayland_handle_xevent (event)) - { - bypass_gtk = bypass_compositor = TRUE; - goto out; - } -#endif - - if (process_selection_event (x11_display, event)) - { - bypass_gtk = bypass_compositor = TRUE; - goto out; - } - - display->current_time = event_get_time (x11_display, event); - - if (META_IS_BACKEND_X11 (backend)) - meta_backend_x11_handle_event (META_BACKEND_X11 (backend), event); - - if (x11_display->focused_by_us && - event->xany.serial > x11_display->focus_serial && - display->focus_window && - !window_has_xwindow (display->focus_window, x11_display->server_focus_window)) - { - meta_topic (META_DEBUG_FOCUS, "Earlier attempt to focus %s failed", - display->focus_window->desc); - meta_x11_display_update_focus_window (x11_display, - x11_display->server_focus_window, - x11_display->server_focus_serial, - FALSE); - meta_display_update_focus_window (display, - meta_x11_display_lookup_x_window (x11_display, - x11_display->server_focus_window)); - } - - if (event->xany.window == x11_display->xroot) - { - cursor_tracker = meta_backend_get_cursor_tracker (backend); - if (META_IS_CURSOR_TRACKER_X11 (cursor_tracker)) - { - MetaCursorTrackerX11 *cursor_tracker_x11 = - META_CURSOR_TRACKER_X11 (cursor_tracker); - - if (meta_cursor_tracker_x11_handle_xevent (cursor_tracker_x11, event)) - { - bypass_gtk = bypass_compositor = TRUE; - goto out; - } - } - } - - modified = event_get_modified_window (x11_display, event); - - input_event = get_input_event (x11_display, event); - - if (event->type == UnmapNotify) - { - if (meta_ui_window_should_not_cause_focus (x11_display->xdisplay, - modified)) - { - meta_display_add_ignored_crossing_serial (display, event->xany.serial); - meta_topic (META_DEBUG_FOCUS, - "Adding EnterNotify serial %lu to ignored focus serials", - event->xany.serial); - } - } - - if (meta_x11_display_process_barrier_xevent (x11_display, input_event)) - { - bypass_gtk = bypass_compositor = TRUE; - goto out; - } - - if (handle_input_xevent (x11_display, input_event, event->xany.serial)) - { - bypass_gtk = bypass_compositor = TRUE; - goto out; - } - - if (handle_other_xevent (x11_display, event)) - { - bypass_gtk = TRUE; - goto out; - } - - if (event->type == SelectionClear) - { - if (process_selection_clear (x11_display, event)) - { - bypass_gtk = TRUE; - goto out; - } - } - - out: - if (!bypass_compositor && META_IS_COMPOSITOR_X11 (display->compositor)) - { - MetaCompositorX11 *compositor_x11 = - META_COMPOSITOR_X11 (display->compositor); - MetaWindow *window; - - if (modified != None) - window = meta_x11_display_lookup_x_window (x11_display, modified); - else - window = NULL; - - meta_compositor_x11_process_xevent (compositor_x11, event, window); - } - - display->current_time = META_CURRENT_TIME; - return bypass_gtk; -} - - -static GdkFilterReturn -xevent_filter (GdkXEvent *xevent, - GdkEvent *event, - gpointer data) -{ - MetaX11Display *x11_display = data; - - if (meta_x11_display_handle_xevent (x11_display, xevent)) - return GDK_FILTER_REMOVE; - else - return GDK_FILTER_CONTINUE; -} - -void -meta_x11_display_init_events (MetaX11Display *x11_display) -{ - gdk_window_add_filter (NULL, xevent_filter, x11_display); -} - -void -meta_x11_display_free_events (MetaX11Display *x11_display) -{ - gdk_window_remove_filter (NULL, xevent_filter, x11_display); -} diff --git a/src/x11/events.h b/src/x11/events.h deleted file mode 100644 index 7e73edab6..000000000 --- a/src/x11/events.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002, 2003, 2004 Red Hat, Inc. - * Copyright (C) 2003, 2004 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * 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 . - */ - -#include "meta/display.h" - -#ifndef META_EVENTS_X11_H -#define META_EVENTS_X11_H - -void meta_x11_display_init_events (MetaX11Display *x11_display); -void meta_x11_display_free_events (MetaX11Display *x11_display); - -#endif diff --git a/src/x11/group-private.h b/src/x11/group-private.h deleted file mode 100644 index f8149becc..000000000 --- a/src/x11/group-private.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter window group private header */ - -/* - * Copyright (C) 2002 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 . - */ - -#ifndef META_GROUP_PRIVATE_H -#define META_GROUP_PRIVATE_H - -#include "meta/group.h" - -struct _MetaGroup -{ - int refcount; - MetaX11Display *x11_display; - GSList *windows; - Window group_leader; - char *startup_id; - char *wm_client_machine; -}; - -#endif - - - - diff --git a/src/x11/group-props.c b/src/x11/group-props.c deleted file mode 100644 index 24ee4992c..000000000 --- a/src/x11/group-props.c +++ /dev/null @@ -1,235 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* MetaGroup property handling */ - -/* - * Copyright (C) 2002 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 . - */ - -#include "config.h" - -#include "x11/group-props.h" - -#include - -#include "x11/group-private.h" -#include "x11/meta-x11-display-private.h" -#include "x11/xprops.h" - -typedef void (* InitValueFunc) (MetaX11Display *x11_display, - Atom property, - MetaPropValue *value); -typedef void (* ReloadValueFunc) (MetaGroup *group, - MetaPropValue *value); - -struct _MetaGroupPropHooks -{ - Atom property; - InitValueFunc init_func; - ReloadValueFunc reload_func; -}; - -static void init_prop_value (MetaX11Display *x11_display, - Atom property, - MetaPropValue *value); -static void reload_prop_value (MetaGroup *group, - MetaPropValue *value); -static MetaGroupPropHooks *find_hooks (MetaX11Display *x11_display, - Atom property); - -void -meta_group_reload_property (MetaGroup *group, - Atom property) -{ - meta_group_reload_properties (group, &property, 1); -} - -void -meta_group_reload_properties (MetaGroup *group, - const Atom *properties, - int n_properties) -{ - int i; - MetaPropValue *values; - - g_return_if_fail (properties != NULL); - g_return_if_fail (n_properties > 0); - - values = g_new0 (MetaPropValue, n_properties); - - i = 0; - while (i < n_properties) - { - init_prop_value (group->x11_display, properties[i], &values[i]); - ++i; - } - - meta_prop_get_values (group->x11_display, - group->group_leader, - values, n_properties); - - i = 0; - while (i < n_properties) - { - reload_prop_value (group, &values[i]); - - ++i; - } - - meta_prop_free_values (values, n_properties); - - g_free (values); -} - -/* Fill in the MetaPropValue used to get the value of "property" */ -static void -init_prop_value (MetaX11Display *x11_display, - Atom property, - MetaPropValue *value) -{ - MetaGroupPropHooks *hooks; - - value->type = META_PROP_VALUE_INVALID; - value->atom = None; - - hooks = find_hooks (x11_display, property); - if (hooks && hooks->init_func != NULL) - (* hooks->init_func) (x11_display, property, value); -} - -static void -reload_prop_value (MetaGroup *group, - MetaPropValue *value) -{ - MetaGroupPropHooks *hooks; - - hooks = find_hooks (group->x11_display, value->atom); - if (hooks && hooks->reload_func != NULL) - (* hooks->reload_func) (group, value); -} - -static void -init_wm_client_machine (MetaX11Display *x11_display, - Atom property, - MetaPropValue *value) -{ - value->type = META_PROP_VALUE_STRING; - value->atom = x11_display->atom_WM_CLIENT_MACHINE; -} - -static void -reload_wm_client_machine (MetaGroup *group, - MetaPropValue *value) -{ - g_free (group->wm_client_machine); - group->wm_client_machine = NULL; - - if (value->type != META_PROP_VALUE_INVALID) - group->wm_client_machine = g_strdup (value->v.str); - - meta_verbose ("Group has client machine \"%s\"", - group->wm_client_machine ? group->wm_client_machine : "unset"); -} - -static void -init_net_startup_id (MetaX11Display *x11_display, - Atom property, - MetaPropValue *value) -{ - value->type = META_PROP_VALUE_UTF8; - value->atom = x11_display->atom__NET_STARTUP_ID; -} - -static void -reload_net_startup_id (MetaGroup *group, - MetaPropValue *value) -{ - g_free (group->startup_id); - group->startup_id = NULL; - - if (value->type != META_PROP_VALUE_INVALID) - group->startup_id = g_strdup (value->v.str); - - meta_verbose ("Group has startup id \"%s\"", - group->startup_id ? group->startup_id : "unset"); -} - -#define N_HOOKS 3 - -void -meta_x11_display_init_group_prop_hooks (MetaX11Display *x11_display) -{ - int i; - MetaGroupPropHooks *hooks; - - g_assert (x11_display->group_prop_hooks == NULL); - - x11_display->group_prop_hooks = g_new0 (MetaGroupPropHooks, N_HOOKS); - hooks = x11_display->group_prop_hooks; - - i = 0; - - hooks[i].property = x11_display->atom_WM_CLIENT_MACHINE; - hooks[i].init_func = init_wm_client_machine; - hooks[i].reload_func = reload_wm_client_machine; - ++i; - - hooks[i].property = x11_display->atom__NET_WM_PID; - hooks[i].init_func = NULL; - hooks[i].reload_func = NULL; - ++i; - - hooks[i].property = x11_display->atom__NET_STARTUP_ID; - hooks[i].init_func = init_net_startup_id; - hooks[i].reload_func = reload_net_startup_id; - ++i; - - if (i != N_HOOKS) - { - g_error ("Initialized %d group hooks should have been %d", i, N_HOOKS); - } -} - -void -meta_x11_display_free_group_prop_hooks (MetaX11Display *x11_display) -{ - g_assert (x11_display->group_prop_hooks != NULL); - - g_free (x11_display->group_prop_hooks); - x11_display->group_prop_hooks = NULL; -} - -static MetaGroupPropHooks* -find_hooks (MetaX11Display *x11_display, - Atom property) -{ - int i; - - /* FIXME we could sort the array and do binary search or - * something - */ - - i = 0; - while (i < N_HOOKS) - { - if (x11_display->group_prop_hooks[i].property == property) - return &x11_display->group_prop_hooks[i]; - - ++i; - } - - return NULL; -} diff --git a/src/x11/group-props.h b/src/x11/group-props.h deleted file mode 100644 index 19b570008..000000000 --- a/src/x11/group-props.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* MetaGroup property handling */ - -/* - * Copyright (C) 2002 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 . - */ - -#ifndef META_GROUP_PROPS_H -#define META_GROUP_PROPS_H - -#include "core/window-private.h" -#include "meta/group.h" - -void meta_group_reload_property (MetaGroup *group, - Atom property); -void meta_group_reload_properties (MetaGroup *group, - const Atom *properties, - int n_properties); - -void meta_x11_display_init_group_prop_hooks (MetaX11Display *x11_display); -void meta_x11_display_free_group_prop_hooks (MetaX11Display *x11_display); - -#endif /* META_GROUP_PROPS_H */ diff --git a/src/x11/group.c b/src/x11/group.c deleted file mode 100644 index 27f21d068..000000000 --- a/src/x11/group.c +++ /dev/null @@ -1,332 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2002 Red Hat Inc. - * Copyright (C) 2003 Rob Adams - * - * 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 . - */ - -/** - * SECTION:group - * @title: MetaGroup - * @short_description: Mutter window groups - * - */ - -#include "config.h" - -#include "x11/group-private.h" - -#include - -#include "core/window-private.h" -#include "meta/util.h" -#include "meta/window.h" -#include "x11/group-props.h" -#include "x11/meta-x11-display-private.h" - -static MetaGroup* -meta_group_new (MetaX11Display *x11_display, - Window group_leader) -{ - g_autofree MetaGroup *group = NULL; -#define N_INITIAL_PROPS 3 - Atom initial_props[N_INITIAL_PROPS]; - int i; - - g_assert (N_INITIAL_PROPS == (int) G_N_ELEMENTS (initial_props)); - - group = g_new0 (MetaGroup, 1); - - group->x11_display = x11_display; - group->windows = NULL; - group->group_leader = group_leader; - group->refcount = 1; /* owned by caller, hash table has only weak ref */ - - xcb_connection_t *xcb_conn = XGetXCBConnection (x11_display->xdisplay); - g_autofree xcb_generic_error_t *e = NULL; - g_autofree xcb_get_window_attributes_reply_t *attrs = - xcb_get_window_attributes_reply (xcb_conn, - xcb_get_window_attributes (xcb_conn, group_leader), - &e); - if (e || !attrs) - return NULL; - - const uint32_t events[] = { attrs->your_event_mask | XCB_EVENT_MASK_PROPERTY_CHANGE }; - xcb_change_window_attributes (xcb_conn, group_leader, - XCB_CW_EVENT_MASK, events); - - if (x11_display->groups_by_leader == NULL) - x11_display->groups_by_leader = g_hash_table_new (meta_unsigned_long_hash, - meta_unsigned_long_equal); - - g_assert (g_hash_table_lookup (x11_display->groups_by_leader, &group_leader) == NULL); - - g_hash_table_insert (x11_display->groups_by_leader, - &group->group_leader, - group); - - /* Fill these in the order we want them to be gotten */ - i = 0; - initial_props[i++] = x11_display->atom_WM_CLIENT_MACHINE; - initial_props[i++] = x11_display->atom__NET_WM_PID; - initial_props[i++] = x11_display->atom__NET_STARTUP_ID; - g_assert (N_INITIAL_PROPS == i); - - meta_group_reload_properties (group, initial_props, N_INITIAL_PROPS); - - meta_topic (META_DEBUG_GROUPS, - "Created new group with leader 0x%lx", - group->group_leader); - - return g_steal_pointer (&group); -} - -static void -meta_group_unref (MetaGroup *group) -{ - g_return_if_fail (group->refcount > 0); - - group->refcount -= 1; - if (group->refcount == 0) - { - meta_topic (META_DEBUG_GROUPS, - "Destroying group with leader 0x%lx", - group->group_leader); - - g_assert (group->x11_display->groups_by_leader != NULL); - - g_hash_table_remove (group->x11_display->groups_by_leader, - &group->group_leader); - - /* mop up hash table, this is how it gets freed on display close */ - if (g_hash_table_size (group->x11_display->groups_by_leader) == 0) - { - g_hash_table_destroy (group->x11_display->groups_by_leader); - group->x11_display->groups_by_leader = NULL; - } - - g_free (group->wm_client_machine); - g_free (group->startup_id); - - g_free (group); - } -} - -/** - * meta_window_get_group: (skip) - * @window: a #MetaWindow - * - */ -MetaGroup* -meta_window_get_group (MetaWindow *window) -{ - if (window->unmanaging) - return NULL; - - return window->group; -} - -void -meta_window_compute_group (MetaWindow* window) -{ - MetaGroup *group; - MetaWindow *ancestor; - MetaX11Display *x11_display = window->display->x11_display; - - /* use window->xwindow if no window->xgroup_leader */ - - group = NULL; - - /* Determine the ancestor of the window; its group setting will override the - * normal grouping rules; see bug 328211. - */ - ancestor = meta_window_find_root_ancestor (window); - - if (x11_display->groups_by_leader) - { - if (ancestor != window) - group = ancestor->group; - else if (window->xgroup_leader != None) - group = g_hash_table_lookup (x11_display->groups_by_leader, - &window->xgroup_leader); - else - group = g_hash_table_lookup (x11_display->groups_by_leader, - &window->xwindow); - } - - if (group != NULL) - { - window->group = group; - group->refcount += 1; - } - else - { - if (ancestor != window && ancestor->xgroup_leader != None) - group = meta_group_new (x11_display, - ancestor->xgroup_leader); - else if (window->xgroup_leader != None) - group = meta_group_new (x11_display, - window->xgroup_leader); - else - group = meta_group_new (x11_display, - window->xwindow); - - window->group = group; - } - - if (!window->group) - return; - - window->group->windows = g_slist_prepend (window->group->windows, window); - - meta_topic (META_DEBUG_GROUPS, - "Adding %s to group with leader 0x%lx", - window->desc, group->group_leader); -} - -static void -remove_window_from_group (MetaWindow *window) -{ - if (window->group != NULL) - { - meta_topic (META_DEBUG_GROUPS, - "Removing %s from group with leader 0x%lx", - window->desc, window->group->group_leader); - - window->group->windows = - g_slist_remove (window->group->windows, - window); - meta_group_unref (window->group); - window->group = NULL; - } -} - -void -meta_window_group_leader_changed (MetaWindow *window) -{ - remove_window_from_group (window); - meta_window_compute_group (window); -} - -void -meta_window_shutdown_group (MetaWindow *window) -{ - remove_window_from_group (window); -} - -/** - * meta_x11_display_lookup_group: (skip) - * @x11_display: a #MetaX11Display - * @group_leader: a X window - * - */ -MetaGroup * -meta_x11_display_lookup_group (MetaX11Display *x11_display, - Window group_leader) -{ - MetaGroup *group; - - group = NULL; - - if (x11_display->groups_by_leader) - group = g_hash_table_lookup (x11_display->groups_by_leader, - &group_leader); - - return group; -} - -/** - * meta_group_list_windows: - * @group: A #MetaGroup - * - * Returns: (transfer container) (element-type Meta.Window): List of windows - */ -GSList* -meta_group_list_windows (MetaGroup *group) -{ - return g_slist_copy (group->windows); -} - -void -meta_group_update_layers (MetaGroup *group) -{ - GSList *tmp; - GSList *frozen_stacks; - - if (group->windows == NULL) - return; - - frozen_stacks = NULL; - tmp = group->windows; - while (tmp != NULL) - { - MetaWindow *window = tmp->data; - - /* we end up freezing the same stack a lot of times, - * but doesn't hurt anything. have to handle - * groups that span 2 screens. - */ - meta_stack_freeze (window->display->stack); - frozen_stacks = g_slist_prepend (frozen_stacks, window->display->stack); - - meta_stack_update_layer (window->display->stack, - window); - - tmp = tmp->next; - } - - tmp = frozen_stacks; - while (tmp != NULL) - { - meta_stack_thaw (tmp->data); - tmp = tmp->next; - } - - g_slist_free (frozen_stacks); -} - -const char* -meta_group_get_startup_id (MetaGroup *group) -{ - return group->startup_id; -} - -/** - * meta_group_property_notify: (skip) - * @group: a #MetaGroup - * @event: a X event - * - */ -gboolean -meta_group_property_notify (MetaGroup *group, - XEvent *event) -{ - meta_group_reload_property (group, - event->xproperty.atom); - - return TRUE; - -} - -int -meta_group_get_size (MetaGroup *group) -{ - if (!group) - return 0; - - return group->refcount; -} - diff --git a/src/x11/iconcache.c b/src/x11/iconcache.c deleted file mode 100644 index 941cf2075..000000000 --- a/src/x11/iconcache.c +++ /dev/null @@ -1,575 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter window icons */ - -/* - * Copyright (C) 2002 Havoc Pennington - * - * 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 . - */ - -#include "config.h" - -#include "x11/iconcache.h" - -#include -#include -#include -#include -#include - -#include "meta/meta-x11-errors.h" -#include "x11/meta-x11-display-private.h" - -static gboolean -find_largest_sizes (gulong *data, - gulong nitems, - int *width, - int *height) -{ - *width = 0; - *height = 0; - - while (nitems > 0) - { - int w, h; - - if (nitems < 3) - return FALSE; /* no space for w, h */ - - w = data[0]; - h = data[1]; - - if (nitems < ((gulong)(w * h) + 2)) - return FALSE; /* not enough data */ - - *width = MAX (w, *width); - *height = MAX (h, *height); - - data += (w * h) + 2; - nitems -= (w * h) + 2; - } - - return TRUE; -} - -static gboolean -find_best_size (gulong *data, - gulong nitems, - int ideal_width, - int ideal_height, - int *width, - int *height, - gulong **start) -{ - int best_w; - int best_h; - gulong *best_start; - int max_width, max_height; - - *width = 0; - *height = 0; - *start = NULL; - - if (!find_largest_sizes (data, nitems, &max_width, &max_height)) - return FALSE; - - if (ideal_width < 0) - ideal_width = max_width; - if (ideal_height < 0) - ideal_height = max_height; - - best_w = 0; - best_h = 0; - best_start = NULL; - - while (nitems > 0) - { - int w, h; - gboolean replace; - - replace = FALSE; - - if (nitems < 3) - return FALSE; /* no space for w, h */ - - w = data[0]; - h = data[1]; - - if (nitems < ((gulong)(w * h) + 2)) - break; /* not enough data */ - - if (best_start == NULL) - { - replace = TRUE; - } - else - { - /* work with averages */ - const int ideal_size = (ideal_width + ideal_height) / 2; - int best_size = (best_w + best_h) / 2; - int this_size = (w + h) / 2; - - /* larger than desired is always better than smaller */ - if (best_size < ideal_size && - this_size >= ideal_size) - replace = TRUE; - /* if we have too small, pick anything bigger */ - else if (best_size < ideal_size && - this_size > best_size) - replace = TRUE; - /* if we have too large, pick anything smaller - * but still >= the ideal - */ - else if (best_size > ideal_size && - this_size >= ideal_size && - this_size < best_size) - replace = TRUE; - } - - if (replace) - { - best_start = data + 2; - best_w = w; - best_h = h; - } - - data += (w * h) + 2; - nitems -= (w * h) + 2; - } - - if (best_start) - { - *start = best_start; - *width = best_w; - *height = best_h; - return TRUE; - } - else - return FALSE; -} - -static cairo_surface_t * -argbdata_to_surface (gulong *argb_data, int w, int h) -{ - cairo_surface_t *surface; - int y, x, stride; - uint32_t *data; - - surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w, h); - stride = cairo_image_surface_get_stride (surface) / sizeof (uint32_t); - data = (uint32_t *) cairo_image_surface_get_data (surface); - - /* One could speed this up a lot. */ - for (y = 0; y < h; y++) - { - for (x = 0; x < w; x++) - { - uint32_t *p = &data[y * stride + x]; - gulong *d = &argb_data[y * w + x]; - *p = *d; - } - } - - cairo_surface_mark_dirty (surface); - - return surface; -} - -static gboolean -read_rgb_icon (MetaX11Display *x11_display, - Window xwindow, - int ideal_width, - int ideal_height, - int ideal_mini_width, - int ideal_mini_height, - cairo_surface_t **icon, - cairo_surface_t **mini_icon) -{ - Atom type; - int format; - gulong nitems; - gulong bytes_after; - int result, err; - guchar *data; - gulong *best; - int w, h; - gulong *best_mini; - int mini_w, mini_h; - gulong *data_as_long; - - meta_x11_error_trap_push (x11_display); - type = None; - data = NULL; - result = XGetWindowProperty (x11_display->xdisplay, - xwindow, - x11_display->atom__NET_WM_ICON, - 0, G_MAXLONG, - False, XA_CARDINAL, &type, &format, &nitems, - &bytes_after, &data); - err = meta_x11_error_trap_pop_with_return (x11_display); - - if (err != Success || - result != Success) - return FALSE; - - if (type != XA_CARDINAL) - { - XFree (data); - return FALSE; - } - - data_as_long = (gulong *)data; - - if (!find_best_size (data_as_long, nitems, - ideal_width, ideal_height, - &w, &h, &best)) - { - XFree (data); - return FALSE; - } - - if (!find_best_size (data_as_long, nitems, - ideal_mini_width, ideal_mini_height, - &mini_w, &mini_h, &best_mini)) - { - XFree (data); - return FALSE; - } - - *icon = argbdata_to_surface (best, w, h); - *mini_icon = argbdata_to_surface (best_mini, mini_w, mini_h); - - XFree (data); - - return TRUE; -} - -static void -get_pixmap_geometry (MetaX11Display *x11_display, - Pixmap pixmap, - int *w, - int *h, - int *d) -{ - Window root_ignored; - int x_ignored, y_ignored; - guint width, height; - guint border_width_ignored; - guint depth; - - if (w) - *w = 1; - if (h) - *h = 1; - if (d) - *d = 1; - - XGetGeometry (x11_display->xdisplay, - pixmap, &root_ignored, &x_ignored, &y_ignored, - &width, &height, &border_width_ignored, &depth); - - if (w) - *w = width; - if (h) - *h = height; - if (d) - *d = depth; -} - -static cairo_surface_t * -surface_from_pixmap (Display *xdisplay, Pixmap xpixmap, - int width, int height) -{ - Window root_return; - XVisualInfo visual_info; - int x_ret, y_ret; - unsigned int w_ret, h_ret, bw_ret, depth_ret; - - if (!XGetGeometry (xdisplay, xpixmap, &root_return, - &x_ret, &y_ret, &w_ret, &h_ret, &bw_ret, &depth_ret)) - return NULL; - - if (!XMatchVisualInfo (xdisplay, DefaultScreen (xdisplay), - depth_ret, TrueColor, &visual_info)) - return NULL; - - return cairo_xlib_surface_create (xdisplay, xpixmap, visual_info.visual, - w_ret, h_ret); -} - -static gboolean -try_pixmap_and_mask (MetaX11Display *x11_display, - Pixmap src_pixmap, - Pixmap src_mask, - cairo_surface_t **iconp) -{ - Display *xdisplay = x11_display->xdisplay; - cairo_surface_t *icon, *mask = NULL; - int w, h, d; - - if (src_pixmap == None) - return FALSE; - - meta_x11_error_trap_push (x11_display); - - get_pixmap_geometry (x11_display, src_pixmap, &w, &h, &d); - icon = surface_from_pixmap (xdisplay, src_pixmap, w, h); - - if (icon && src_mask != None) - { - get_pixmap_geometry (x11_display, src_mask, &w, &h, &d); - - if (d == 1) - mask = surface_from_pixmap (xdisplay, src_mask, w, h); - } - - meta_x11_error_trap_pop (x11_display); - - if (icon && mask) - { - cairo_surface_t *masked; - cairo_t *cr; - - masked = cairo_surface_create_similar_image (icon, - CAIRO_FORMAT_ARGB32, - cairo_xlib_surface_get_width (icon), - cairo_xlib_surface_get_height (icon)); - cr = cairo_create (masked); - - cairo_set_source_surface (cr, icon, 0, 0); - cairo_mask_surface (cr, mask, 0, 0); - - cairo_destroy (cr); - cairo_surface_destroy (icon); - cairo_surface_destroy (mask); - - icon = masked; - } - - if (icon) - { - *iconp = icon; - return TRUE; - } - else - { - return FALSE; - } -} - -static void -get_kwm_win_icon (MetaX11Display *x11_display, - Window xwindow, - Pixmap *pixmap, - Pixmap *mask) -{ - Atom type; - int format; - gulong nitems; - gulong bytes_after; - guchar *data; - Pixmap *icons; - int err, result; - - *pixmap = None; - *mask = None; - - meta_x11_error_trap_push (x11_display); - icons = NULL; - result = XGetWindowProperty (x11_display->xdisplay, xwindow, - x11_display->atom__KWM_WIN_ICON, - 0, G_MAXLONG, - False, - x11_display->atom__KWM_WIN_ICON, - &type, &format, &nitems, - &bytes_after, &data); - icons = (Pixmap *)data; - - err = meta_x11_error_trap_pop_with_return (x11_display); - if (err != Success || - result != Success) - return; - - if (type != x11_display->atom__KWM_WIN_ICON) - { - XFree (icons); - return; - } - - *pixmap = icons[0]; - *mask = icons[1]; - - XFree (icons); - - return; -} - -void -meta_icon_cache_init (MetaIconCache *icon_cache) -{ - g_return_if_fail (icon_cache != NULL); - - icon_cache->origin = USING_NO_ICON; - icon_cache->prev_pixmap = None; - icon_cache->prev_mask = None; - icon_cache->wm_hints_dirty = TRUE; - icon_cache->kwm_win_icon_dirty = TRUE; - icon_cache->net_wm_icon_dirty = TRUE; -} - -void -meta_icon_cache_property_changed (MetaIconCache *icon_cache, - MetaX11Display *x11_display, - Atom atom) -{ - if (atom == x11_display->atom__NET_WM_ICON) - icon_cache->net_wm_icon_dirty = TRUE; - else if (atom == x11_display->atom__KWM_WIN_ICON) - icon_cache->kwm_win_icon_dirty = TRUE; - else if (atom == XA_WM_HINTS) - icon_cache->wm_hints_dirty = TRUE; -} - -gboolean -meta_icon_cache_get_icon_invalidated (MetaIconCache *icon_cache) -{ - if (icon_cache->origin <= USING_KWM_WIN_ICON && - icon_cache->kwm_win_icon_dirty) - return TRUE; - else if (icon_cache->origin <= USING_WM_HINTS && - icon_cache->wm_hints_dirty) - return TRUE; - else if (icon_cache->origin <= USING_NET_WM_ICON && - icon_cache->net_wm_icon_dirty) - return TRUE; - else if (icon_cache->origin < USING_FALLBACK_ICON) - return TRUE; - else - return FALSE; -} - -gboolean -meta_read_icons (MetaX11Display *x11_display, - Window xwindow, - MetaIconCache *icon_cache, - Pixmap wm_hints_pixmap, - Pixmap wm_hints_mask, - cairo_surface_t **iconp, - int ideal_width, - int ideal_height, - cairo_surface_t **mini_iconp, - int ideal_mini_width, - int ideal_mini_height) -{ - /* Return value is whether the icon changed */ - - g_return_val_if_fail (icon_cache != NULL, FALSE); - - *iconp = NULL; - *mini_iconp = NULL; - - if (!meta_icon_cache_get_icon_invalidated (icon_cache)) - return FALSE; /* we have no new info to use */ - - /* Our algorithm here assumes that we can't have for example origin - * < USING_NET_WM_ICON and icon_cache->net_wm_icon_dirty == FALSE - * unless we have tried to read NET_WM_ICON. - * - * Put another way, if an icon origin is not dirty, then we have - * tried to read it at the current size. If it is dirty, then - * we haven't done that since the last change. - */ - - if (icon_cache->origin <= USING_NET_WM_ICON && - icon_cache->net_wm_icon_dirty) - { - icon_cache->net_wm_icon_dirty = FALSE; - - if (read_rgb_icon (x11_display, xwindow, - ideal_width, ideal_height, - ideal_mini_width, ideal_mini_height, - iconp, mini_iconp)) - { - icon_cache->origin = USING_NET_WM_ICON; - return TRUE; - } - } - - if (icon_cache->origin <= USING_WM_HINTS && - icon_cache->wm_hints_dirty) - { - Pixmap pixmap; - Pixmap mask; - - icon_cache->wm_hints_dirty = FALSE; - - pixmap = wm_hints_pixmap; - mask = wm_hints_mask; - - /* We won't update if pixmap is unchanged; - * avoids a get_from_drawable() on every geometry - * hints change - */ - if ((pixmap != icon_cache->prev_pixmap || - mask != icon_cache->prev_mask) && - pixmap != None) - { - if (try_pixmap_and_mask (x11_display, pixmap, mask, iconp)) - { - *mini_iconp = cairo_surface_reference (*iconp); - icon_cache->prev_pixmap = pixmap; - icon_cache->prev_mask = mask; - icon_cache->origin = USING_WM_HINTS; - return TRUE; - } - } - } - - if (icon_cache->origin <= USING_KWM_WIN_ICON && - icon_cache->kwm_win_icon_dirty) - { - Pixmap pixmap; - Pixmap mask; - - icon_cache->kwm_win_icon_dirty = FALSE; - - get_kwm_win_icon (x11_display, xwindow, &pixmap, &mask); - - if ((pixmap != icon_cache->prev_pixmap || - mask != icon_cache->prev_mask) && - pixmap != None) - { - if (try_pixmap_and_mask (x11_display, pixmap, mask, iconp)) - { - *mini_iconp = cairo_surface_reference (*iconp); - icon_cache->prev_pixmap = pixmap; - icon_cache->prev_mask = mask; - icon_cache->origin = USING_KWM_WIN_ICON; - return TRUE; - } - } - } - - if (icon_cache->origin < USING_FALLBACK_ICON) - { - icon_cache->origin = USING_FALLBACK_ICON; - *iconp = NULL; - *mini_iconp = NULL; - return TRUE; - } - - /* found nothing new */ - return FALSE; -} diff --git a/src/x11/iconcache.h b/src/x11/iconcache.h deleted file mode 100644 index a4b63edf0..000000000 --- a/src/x11/iconcache.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter window icons */ - -/* - * Copyright (C) 2002 Havoc Pennington - * - * 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 . - */ - -#ifndef META_ICON_CACHE_H -#define META_ICON_CACHE_H - -#include "x11/meta-x11-display-private.h" - -typedef struct _MetaIconCache MetaIconCache; - -typedef enum -{ - /* These MUST be in ascending order of preference; - * i.e. if we get _NET_WM_ICON and already have - * WM_HINTS, we prefer _NET_WM_ICON - */ - USING_NO_ICON, - USING_FALLBACK_ICON, - USING_KWM_WIN_ICON, - USING_WM_HINTS, - USING_NET_WM_ICON -} IconOrigin; - -struct _MetaIconCache -{ - int origin; - Pixmap prev_pixmap; - Pixmap prev_mask; - /* TRUE if these props have changed */ - guint wm_hints_dirty : 1; - guint kwm_win_icon_dirty : 1; - guint net_wm_icon_dirty : 1; -}; - -void meta_icon_cache_init (MetaIconCache *icon_cache); -void meta_icon_cache_property_changed (MetaIconCache *icon_cache, - MetaX11Display *x11_display, - Atom atom); -gboolean meta_icon_cache_get_icon_invalidated (MetaIconCache *icon_cache); - -gboolean meta_read_icons (MetaX11Display *x11_display, - Window xwindow, - MetaIconCache *icon_cache, - Pixmap wm_hints_pixmap, - Pixmap wm_hints_mask, - cairo_surface_t **iconp, - int ideal_width, - int ideal_height, - cairo_surface_t **mini_iconp, - int ideal_mini_width, - int ideal_mini_height); - -#endif - - - - diff --git a/src/x11/meta-selection-source-x11-private.h b/src/x11/meta-selection-source-x11-private.h deleted file mode 100644 index bcd21a356..000000000 --- a/src/x11/meta-selection-source-x11-private.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2018 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: Carlos Garnacho - */ - -#ifndef META_SELECTION_SOURCE_X11_H -#define META_SELECTION_SOURCE_X11_H - -#include "meta/meta-selection-source.h" -#include "x11/meta-x11-display-private.h" - -#define META_TYPE_SELECTION_SOURCE_X11 (meta_selection_source_x11_get_type ()) -G_DECLARE_FINAL_TYPE (MetaSelectionSourceX11, - meta_selection_source_x11, - META, SELECTION_SOURCE_X11, - MetaSelectionSource) - -void meta_selection_source_x11_new_async (MetaX11Display *display, - Window owner, - uint32_t timestamp, - Atom xselection, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -MetaSelectionSource * meta_selection_source_x11_new_finish (GAsyncResult *result, - GError **error); - -#endif /* META_SELECTION_SOURCE_X11_H */ diff --git a/src/x11/meta-selection-source-x11.c b/src/x11/meta-selection-source-x11.c deleted file mode 100644 index c9fc8fbc6..000000000 --- a/src/x11/meta-selection-source-x11.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright (C) 2018 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: Carlos Garnacho - */ - -#include "config.h" - -#include - -#include "x11/meta-x11-selection-input-stream-private.h" -#include "x11/meta-selection-source-x11-private.h" - -#define MAX_MIMETYPE_SIZE 4096 - -struct _MetaSelectionSourceX11 -{ - MetaSelectionSource parent_instance; - MetaX11Display *x11_display; - GList *mimetypes; - Window owner; - Atom xselection; - uint32_t timestamp; -}; - -G_DEFINE_TYPE (MetaSelectionSourceX11, meta_selection_source_x11, - META_TYPE_SELECTION_SOURCE) - -static void -stream_new_cb (GObject *source, - GAsyncResult *res, - GTask *task) -{ - GInputStream *stream; - GError *error = NULL; - - stream = meta_x11_selection_input_stream_new_finish (res, NULL, NULL, &error); - - if (stream) - g_task_return_pointer (task, stream, g_object_unref); - else - g_task_return_error (task, error); - - g_object_unref (task); -} - -static void -meta_selection_source_x11_finalize (GObject *object) -{ - MetaSelectionSourceX11 *source_x11 = META_SELECTION_SOURCE_X11 (object); - - g_list_free_full (source_x11->mimetypes, g_free); - - G_OBJECT_CLASS (meta_selection_source_x11_parent_class)->finalize (object); -} - -static void -meta_selection_source_x11_read_async (MetaSelectionSource *source, - const gchar *mimetype, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MetaSelectionSourceX11 *source_x11 = META_SELECTION_SOURCE_X11 (source); - GTask *task; - - task = g_task_new (source, cancellable, callback, user_data); - g_task_set_source_tag (task, meta_selection_source_x11_read_async); - - if (strcmp (mimetype, "text/plain") == 0 && - g_list_find_custom (source_x11->mimetypes, "STRING", - (GCompareFunc) g_strcmp0)) - mimetype = "STRING"; - else if (strcmp (mimetype, "text/plain;charset=utf-8") == 0 && - g_list_find_custom (source_x11->mimetypes, "UTF8_STRING", - (GCompareFunc) g_strcmp0)) - mimetype = "UTF8_STRING"; - - meta_x11_selection_input_stream_new_async (source_x11->x11_display, - source_x11->x11_display->selection.xwindow, - gdk_x11_get_xatom_name (source_x11->xselection), - mimetype, - source_x11->timestamp, - G_PRIORITY_DEFAULT, - cancellable, - (GAsyncReadyCallback) stream_new_cb, - task); -} - -static GInputStream * -meta_selection_source_x11_read_finish (MetaSelectionSource *source, - GAsyncResult *result, - GError **error) -{ - g_return_val_if_fail (g_task_is_valid (result, source), NULL); - g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == - meta_selection_source_x11_read_async, NULL); - - return g_task_propagate_pointer (G_TASK (result), error); -} - -static GList * -meta_selection_source_x11_get_mimetypes (MetaSelectionSource *source) -{ - MetaSelectionSourceX11 *source_x11 = META_SELECTION_SOURCE_X11 (source); - - return g_list_copy_deep (source_x11->mimetypes, (GCopyFunc) g_strdup, NULL); -} - -static void -meta_selection_source_x11_class_init (MetaSelectionSourceX11Class *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - MetaSelectionSourceClass *source_class = META_SELECTION_SOURCE_CLASS (klass); - - object_class->finalize = meta_selection_source_x11_finalize; - - source_class->read_async = meta_selection_source_x11_read_async; - source_class->read_finish = meta_selection_source_x11_read_finish; - source_class->get_mimetypes = meta_selection_source_x11_get_mimetypes; -} - -static void -meta_selection_source_x11_init (MetaSelectionSourceX11 *source) -{ -} - -static GList * -atoms_to_mimetypes (MetaX11Display *display, - GBytes *bytes) -{ - GList *mimetypes = NULL; - const Atom *atoms; - gsize size; - guint i, n_atoms; - gboolean utf8_string_found = FALSE, utf8_text_plain_found = FALSE; - gboolean string_found = FALSE, text_plain_found = FALSE; - - atoms = g_bytes_get_data (bytes, &size); - n_atoms = size / sizeof (Atom); - - for (i = 0; i < n_atoms; i++) - { - const gchar *mimetype; - - mimetype = gdk_x11_get_xatom_name (atoms[i]); - mimetypes = g_list_prepend (mimetypes, g_strdup (mimetype)); - - utf8_text_plain_found |= strcmp (mimetype, "text/plain;charset=utf-8") == 0; - text_plain_found |= strcmp (mimetype, "text/plain") == 0; - utf8_string_found |= strcmp (mimetype, "UTF8_STRING") == 0; - string_found |= strcmp (mimetype, "STRING") == 0; - } - - /* Ensure non-x11 clients get well-known mimetypes */ - if (string_found && !text_plain_found) - mimetypes = g_list_prepend (mimetypes, g_strdup ("text/plain")); - if (utf8_string_found && !utf8_text_plain_found) - mimetypes = g_list_prepend (mimetypes, g_strdup ("text/plain;charset=utf-8")); - - return mimetypes; -} - -static void -read_mimetypes_cb (GInputStream *stream, - GAsyncResult *res, - GTask *task) -{ - MetaSelectionSourceX11 *source_x11 = g_task_get_task_data (task); - GError *error = NULL; - GBytes *bytes; - - bytes = g_input_stream_read_bytes_finish (stream, res, &error); - if (error) - { - g_task_return_error (task, error); - g_object_unref (task); - g_object_unref (stream); - return; - } - - source_x11->mimetypes = atoms_to_mimetypes (source_x11->x11_display, bytes); - g_bytes_unref (bytes); - - g_task_return_pointer (task, - g_object_ref (g_task_get_task_data (task)), - g_object_unref); - g_object_unref (task); - g_object_unref (stream); -} - -static void -get_mimetypes_cb (GObject *source, - GAsyncResult *res, - GTask *task) -{ - GInputStream *stream; - GError *error = NULL; - - stream = meta_x11_selection_input_stream_new_finish (res, NULL, NULL, &error); - if (error) - { - g_task_return_error (task, error); - g_object_unref (task); - return; - } - - g_input_stream_read_bytes_async (stream, - MAX_MIMETYPE_SIZE, - G_PRIORITY_DEFAULT, - g_task_get_cancellable (task), - (GAsyncReadyCallback) read_mimetypes_cb, - task); -} - -void -meta_selection_source_x11_new_async (MetaX11Display *x11_display, - Window owner, - uint32_t timestamp, - Atom xselection, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MetaSelectionSourceX11 *source; - GTask *task; - - source = g_object_new (META_TYPE_SELECTION_SOURCE_X11, NULL); - source->x11_display = x11_display; - source->owner = owner; - source->timestamp = timestamp; - source->xselection = xselection; - - task = g_task_new (NULL, cancellable, callback, user_data); - g_task_set_source_tag (task, meta_selection_source_x11_new_async); - g_task_set_task_data (task, source, g_object_unref); - - meta_x11_selection_input_stream_new_async (x11_display, - x11_display->selection.xwindow, - gdk_x11_get_xatom_name (xselection), - "TARGETS", - timestamp, - G_PRIORITY_DEFAULT, - cancellable, - (GAsyncReadyCallback) get_mimetypes_cb, - task); -} - -MetaSelectionSource * -meta_selection_source_x11_new_finish (GAsyncResult *result, - GError **error) -{ - GTask *task = G_TASK (result); - - g_return_val_if_fail (g_task_is_valid (task, NULL), NULL); - g_return_val_if_fail (g_task_get_source_tag (task) == - meta_selection_source_x11_new_async, NULL); - - return g_task_propagate_pointer (task, error); -} diff --git a/src/x11/meta-startup-notification-x11.c b/src/x11/meta-startup-notification-x11.c deleted file mode 100644 index 42be6d580..000000000 --- a/src/x11/meta-startup-notification-x11.c +++ /dev/null @@ -1,377 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * Copyright (C) 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 . - */ - -#include "config.h" -#include "meta-startup-notification-x11.h" - -#include -#include - -#include "core/display-private.h" -#include "core/startup-notification-private.h" -#include "meta/meta-x11-errors.h" -#include "x11/meta-x11-display-private.h" - -#ifdef HAVE_STARTUP_NOTIFICATION - -enum -{ - PROP_SEQ_X11_0, - PROP_SEQ_X11_SEQ, - N_SEQ_X11_PROPS -}; - -struct _MetaStartupSequenceX11 -{ - MetaStartupSequence parent_instance; - SnStartupSequence *seq; -}; - -struct _MetaX11StartupNotification -{ - SnDisplay *sn_display; - SnMonitorContext *sn_context; -}; - -static GParamSpec *seq_x11_props[N_SEQ_X11_PROPS]; - -G_DEFINE_TYPE (MetaStartupSequenceX11, - meta_startup_sequence_x11, - META_TYPE_STARTUP_SEQUENCE) - -static void -meta_startup_sequence_x11_complete (MetaStartupSequence *seq) -{ - MetaStartupSequenceX11 *seq_x11; - - seq_x11 = META_STARTUP_SEQUENCE_X11 (seq); - sn_startup_sequence_complete (seq_x11->seq); -} - -static void -meta_startup_sequence_x11_finalize (GObject *object) -{ - MetaStartupSequenceX11 *seq_x11; - - seq_x11 = META_STARTUP_SEQUENCE_X11 (object); - sn_startup_sequence_unref (seq_x11->seq); - - G_OBJECT_CLASS (meta_startup_sequence_x11_parent_class)->finalize (object); -} - -static void -meta_startup_sequence_x11_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaStartupSequenceX11 *seq_x11; - - seq_x11 = META_STARTUP_SEQUENCE_X11 (object); - - switch (prop_id) - { - case PROP_SEQ_X11_SEQ: - seq_x11->seq = g_value_get_pointer (value); - sn_startup_sequence_ref (seq_x11->seq); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_startup_sequence_x11_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaStartupSequenceX11 *seq_x11; - - seq_x11 = META_STARTUP_SEQUENCE_X11 (object); - - switch (prop_id) - { - case PROP_SEQ_X11_SEQ: - g_value_set_pointer (value, seq_x11->seq); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -meta_startup_sequence_x11_init (MetaStartupSequenceX11 *seq) -{ -} - -static void -meta_startup_sequence_x11_class_init (MetaStartupSequenceX11Class *klass) -{ - MetaStartupSequenceClass *seq_class; - GObjectClass *object_class; - - seq_class = META_STARTUP_SEQUENCE_CLASS (klass); - seq_class->complete = meta_startup_sequence_x11_complete; - - object_class = G_OBJECT_CLASS (klass); - object_class->finalize = meta_startup_sequence_x11_finalize; - object_class->set_property = meta_startup_sequence_x11_set_property; - object_class->get_property = meta_startup_sequence_x11_get_property; - - seq_x11_props[PROP_SEQ_X11_SEQ] = - g_param_spec_pointer ("seq", - "Sequence", - "Sequence", - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); - - g_object_class_install_properties (object_class, N_SEQ_X11_PROPS, - seq_x11_props); -} - -static MetaStartupSequence * -meta_startup_sequence_x11_new (SnStartupSequence *seq) -{ - gint64 timestamp; - - timestamp = sn_startup_sequence_get_timestamp (seq); - return g_object_new (META_TYPE_STARTUP_SEQUENCE_X11, - "id", sn_startup_sequence_get_id (seq), - "icon-name", sn_startup_sequence_get_icon_name (seq), - "application-id", sn_startup_sequence_get_application_id (seq), - "wmclass", sn_startup_sequence_get_wmclass (seq), - "name", sn_startup_sequence_get_name (seq), - "workspace", sn_startup_sequence_get_workspace (seq), - "timestamp", timestamp, - "seq", seq, - NULL); -} - -static void -sn_error_trap_push (SnDisplay *sn_display, - Display *xdisplay) -{ - MetaDisplay *display; - - display = meta_display_for_x_display (xdisplay); - if (display != NULL) - meta_x11_error_trap_push (display->x11_display); -} - -static void -sn_error_trap_pop (SnDisplay *sn_display, - Display *xdisplay) -{ - MetaDisplay *display; - - display = meta_display_for_x_display (xdisplay); - if (display != NULL) - meta_x11_error_trap_pop (display->x11_display); -} - -static void -meta_startup_notification_sn_event (SnMonitorEvent *event, - void *user_data) -{ - MetaX11Display *x11_display = user_data; - MetaStartupNotification *sn = x11_display->display->startup_notification; - MetaStartupSequence *seq; - SnStartupSequence *sequence; - - sequence = sn_monitor_event_get_startup_sequence (event); - - sn_startup_sequence_ref (sequence); - - switch (sn_monitor_event_get_type (event)) - { - case SN_MONITOR_EVENT_INITIATED: - { - const char *wmclass; - - wmclass = sn_startup_sequence_get_wmclass (sequence); - - meta_topic (META_DEBUG_STARTUP, - "Received startup initiated for %s wmclass %s", - sn_startup_sequence_get_id (sequence), - wmclass ? wmclass : "(unset)"); - - seq = meta_startup_sequence_x11_new (sequence); - meta_startup_notification_add_sequence (sn, seq); - g_object_unref (seq); - } - break; - - case SN_MONITOR_EVENT_COMPLETED: - { - meta_topic (META_DEBUG_STARTUP, - "Received startup completed for %s", - sn_startup_sequence_get_id (sequence)); - - seq = meta_startup_notification_lookup_sequence (sn, sn_startup_sequence_get_id (sequence)); - if (seq) - { - meta_startup_sequence_complete (seq); - meta_startup_notification_remove_sequence (sn, seq); - } - } - break; - - case SN_MONITOR_EVENT_CHANGED: - meta_topic (META_DEBUG_STARTUP, - "Received startup changed for %s", - sn_startup_sequence_get_id (sequence)); - break; - - case SN_MONITOR_EVENT_CANCELED: - meta_topic (META_DEBUG_STARTUP, - "Received startup canceled for %s", - sn_startup_sequence_get_id (sequence)); - break; - } - - sn_startup_sequence_unref (sequence); -} -#endif - -void -meta_x11_startup_notification_init (MetaX11Display *x11_display) -{ -#ifdef HAVE_STARTUP_NOTIFICATION - MetaX11StartupNotification *x11_sn; - - x11_sn = g_new0 (MetaX11StartupNotification, 1); - x11_sn->sn_display = sn_display_new (x11_display->xdisplay, - sn_error_trap_push, - sn_error_trap_pop); - x11_sn->sn_context = - sn_monitor_context_new (x11_sn->sn_display, - meta_x11_display_get_screen_number (x11_display), - meta_startup_notification_sn_event, - x11_display, - NULL); - - x11_display->startup_notification = x11_sn; -#endif -} - -void -meta_x11_startup_notification_release (MetaX11Display *x11_display) -{ -#ifdef HAVE_STARTUP_NOTIFICATION - MetaX11StartupNotification *x11_sn = x11_display->startup_notification; - - x11_display->startup_notification = NULL; - - if (x11_sn) - { - sn_monitor_context_unref (x11_sn->sn_context); - sn_display_unref (x11_sn->sn_display); - g_free (x11_sn); - } -#endif -} - -gboolean -meta_x11_startup_notification_handle_xevent (MetaX11Display *x11_display, - XEvent *xevent) -{ -#ifdef HAVE_STARTUP_NOTIFICATION - MetaX11StartupNotification *x11_sn = x11_display->startup_notification; - - if (!x11_sn) - return FALSE; - - return sn_display_process_event (x11_sn->sn_display, xevent); -#else - return FALSE; -#endif -} - -#ifdef HAVE_STARTUP_NOTIFICATION -typedef void (* SetAppIdFunc) (SnLauncherContext *context, - const char *app_id); -#endif - -gchar * -meta_x11_startup_notification_launch (MetaX11Display *x11_display, - GAppInfo *app_info, - uint32_t timestamp, - int workspace) -{ - gchar *startup_id = NULL; -#ifdef HAVE_STARTUP_NOTIFICATION - MetaX11StartupNotification *x11_sn = x11_display->startup_notification; - SnLauncherContext *sn_launcher; - int screen; - - screen = meta_x11_display_get_screen_number (x11_display); - sn_launcher = sn_launcher_context_new (x11_sn->sn_display, screen); - - sn_launcher_context_set_name (sn_launcher, g_app_info_get_name (app_info)); - sn_launcher_context_set_workspace (sn_launcher, workspace); - sn_launcher_context_set_binary_name (sn_launcher, - g_app_info_get_executable (app_info)); - - if (G_IS_DESKTOP_APP_INFO (app_info)) - { - const char *application_id; - SetAppIdFunc func = NULL; - GModule *self; - - application_id = - g_desktop_app_info_get_filename (G_DESKTOP_APP_INFO (app_info)); - self = g_module_open (NULL, G_MODULE_BIND_MASK); - - /* This here is a terrible workaround to bypass a libsn bug that is not - * likely to get fixed at this point. - * sn_launcher_context_set_application_id is correctly defined in the - * sn-launcher.h file, but it's mistakenly called - * sn_launcher_set_application_id in the C file. - * - * We look up the symbol instead, but still prefer the correctly named - * function, if one were ever to be added. - */ - if (!g_module_symbol (self, "sn_launcher_context_set_application_id", - (gpointer *) &func)) - { - g_module_symbol (self, "sn_launcher_set_application_id", - (gpointer *) &func); - } - - if (func && application_id) - func (sn_launcher, application_id); - - g_module_close (self); - } - - sn_launcher_context_initiate (sn_launcher, - g_get_prgname (), - g_app_info_get_name (app_info), - timestamp); - - startup_id = g_strdup (sn_launcher_context_get_startup_id (sn_launcher)); - - /* Fire and forget, we have a SnMonitor in addition */ - sn_launcher_context_unref (sn_launcher); -#endif /* HAVE_STARTUP_NOTIFICATION */ - - return startup_id; -} diff --git a/src/x11/meta-startup-notification-x11.h b/src/x11/meta-startup-notification-x11.h deleted file mode 100644 index b46a45e5d..000000000 --- a/src/x11/meta-startup-notification-x11.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * Copyright (C) 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 . - */ - -#include "meta-x11-display-private.h" - -#ifndef META_X11_STARTUP_NOTIFICATION_H -#define META_X11_STARTUP_NOTIFICATION_H - -typedef struct _MetaX11StartupNotification MetaX11StartupNotification; - -#define META_TYPE_STARTUP_SEQUENCE_X11 (meta_startup_sequence_x11_get_type ()) - -G_DECLARE_FINAL_TYPE (MetaStartupSequenceX11, - meta_startup_sequence_x11, - META, STARTUP_SEQUENCE_X11, - MetaStartupSequence) - -void meta_x11_startup_notification_init (MetaX11Display *x11_display); -void meta_x11_startup_notification_release (MetaX11Display *x11_display); - -gboolean meta_x11_startup_notification_handle_xevent (MetaX11Display *x11_display, - XEvent *xevent); - -gchar * meta_x11_startup_notification_launch (MetaX11Display *x11_display, - GAppInfo *app_info, - uint32_t timestamp, - int workspace); - -#endif /* META_X11_STARTUP_NOTIFICATION_H */ diff --git a/src/x11/meta-x11-display-private.h b/src/x11/meta-x11-display-private.h deleted file mode 100644 index d53073e11..000000000 --- a/src/x11/meta-x11-display-private.h +++ /dev/null @@ -1,261 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter X display handler */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002 Red Hat, Inc. - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * 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 . - */ - -#ifndef META_X11_DISPLAY_PRIVATE_H -#define META_X11_DISPLAY_PRIVATE_H - -#include -#include - -#include "backends/meta-monitor-manager-private.h" -#include "core/display-private.h" -#include "meta/common.h" -#include "meta/meta-selection-source.h" -#include "meta/types.h" -#include "meta/meta-x11-display.h" -#include "meta-startup-notification-x11.h" -#include "meta-x11-stack-private.h" -#include "ui/ui.h" - -typedef struct _MetaGroupPropHooks MetaGroupPropHooks; -typedef struct _MetaWindowPropHooks MetaWindowPropHooks; - -typedef gboolean (*MetaAlarmFilter) (MetaX11Display *x11_display, - XSyncAlarmNotifyEvent *event, - gpointer data); - -struct _MetaX11Display -{ - GObject parent; - - MetaDisplay *display; - GdkDisplay *gdk_display; - - char *name; - char *screen_name; - - Display *xdisplay; - Window xroot; - int default_depth; - Visual *default_xvisual; - - guint32 timestamp; - - /* Pull in all the names of atoms as fields; we will intern them when the - * class is constructed. - */ -#define item(x) Atom atom_##x; -#include "x11/atomnames.h" -#undef item - - Window leader_window; - Window timestamp_pinging_window; - - /* The window and serial of the most recent FocusIn event. */ - Window server_focus_window; - gulong server_focus_serial; - - /* For windows we've focused that don't necessarily have an X window, - * like the no_focus_window or the stage X window. */ - Window focus_xwindow; - gulong focus_serial; - - /* This window holds the focus when we don't want to focus - * any actual clients - */ - Window no_focus_window; - - /* Instead of unmapping withdrawn windows we can leave them mapped - * and restack them below a guard window. When using a compositor - * this allows us to provide live previews of unmapped windows */ - Window guard_window; - - Window wm_sn_selection_window; - Atom wm_sn_atom; - guint32 wm_sn_timestamp; - - guint display_close_idle; - guint32 xselectionclear_timestamp; - - Window wm_cm_selection_window; - - Window composite_overlay_window; - - GHashTable *xids; - - gboolean has_xinerama_indices; - - /* Managed by group.c */ - GHashTable *groups_by_leader; - - /* Managed by window-props.c */ - MetaWindowPropHooks *prop_hooks_table; - GHashTable *prop_hooks; - int n_prop_hooks; - - /* Managed by group-props.c */ - MetaGroupPropHooks *group_prop_hooks; - - int xkb_base_event_type; - guint32 last_bell_time; - - MetaAlarmFilter alarm_filter; - gpointer alarm_filter_data; - - MetaUI *ui; - - struct { - Window xwindow; - guint timeout_id; - MetaSelectionSource *owners[META_N_SELECTION_TYPES]; - GCancellable *cancellables[META_N_SELECTION_TYPES]; - - GList *input_streams; - GList *output_streams; - } selection; - - /* If true, server->focus_serial refers to us changing the focus; in - * this case, we can ignore focus events that have exactly focus_serial, - * since we take care to make another request immediately afterwards. - * But if focus is being changed by another client, we have to accept - * multiple events with the same serial. - */ - guint focused_by_us : 1; - - guint keys_grabbed : 1; - - guint closing : 1; - - /* we use property updates as sentinels for certain window focus events - * to avoid some race conditions on EnterNotify events - */ - int sentinel_counter; - - int composite_event_base; - int composite_error_base; - int composite_major_version; - int composite_minor_version; - int damage_event_base; - int damage_error_base; - int xfixes_event_base; - int xfixes_error_base; - int xinput_error_base; - int xinput_event_base; - int xinput_opcode; - int xsync_event_base; - int xsync_error_base; - int shape_event_base; - int shape_error_base; - unsigned int have_xsync : 1; -#define META_X11_DISPLAY_HAS_XSYNC(x11_display) ((x11_display)->have_xsync) - unsigned int have_shape : 1; -#define META_X11_DISPLAY_HAS_SHAPE(x11_display) ((x11_display)->have_shape) - unsigned int have_composite : 1; - unsigned int have_damage : 1; -#define META_X11_DISPLAY_HAS_COMPOSITE(x11_display) ((x11_display)->have_composite) -#define META_X11_DISPLAY_HAS_DAMAGE(x11_display) ((x11_display)->have_damage) - gboolean have_xinput_23 : 1; -#define META_X11_DISPLAY_HAS_XINPUT_23(x11_display) ((x11_display)->have_xinput_23) - - MetaX11StartupNotification *startup_notification; - MetaX11Stack *x11_stack; - - XserverRegion empty_region; -}; - -MetaX11Display *meta_x11_display_new (MetaDisplay *display, GError **error); - -void meta_x11_display_restore_active_workspace (MetaX11Display *x11_display); - -Window meta_x11_display_create_offscreen_window (MetaX11Display *x11_display, - Window parent, - long valuemask); - -Cursor meta_x11_display_create_x_cursor (MetaX11Display *x11_display, - MetaCursor cursor); - -void meta_x11_display_reload_cursor (MetaX11Display *x11_display); - -MetaWindow *meta_x11_display_lookup_x_window (MetaX11Display *x11_display, - Window xwindow); -void meta_x11_display_register_x_window (MetaX11Display *x11_display, - Window *xwindowp, - MetaWindow *window); -void meta_x11_display_unregister_x_window (MetaX11Display *x11_display, - Window xwindow); - -MetaWindow *meta_x11_display_lookup_sync_alarm (MetaX11Display *x11_display, - XSyncAlarm alarm); -void meta_x11_display_register_sync_alarm (MetaX11Display *x11_display, - XSyncAlarm *alarmp, - MetaWindow *window); -void meta_x11_display_unregister_sync_alarm (MetaX11Display *x11_display, - XSyncAlarm alarm); - -gboolean meta_x11_display_process_barrier_xevent (MetaX11Display *x11_display, - XIEvent *event); - -META_EXPORT -void meta_x11_display_set_alarm_filter (MetaX11Display *x11_display, - MetaAlarmFilter filter, - gpointer data); - -void meta_x11_display_create_guard_window (MetaX11Display *x11_display); - -/* make a request to ensure the event serial has changed */ -void meta_x11_display_increment_event_serial (MetaX11Display *x11_display); - -guint32 meta_x11_display_get_current_time_roundtrip (MetaX11Display *x11_display); - -void meta_x11_display_set_input_focus_xwindow (MetaX11Display *x11_display, - Window window, - guint32 timestamp); - -int meta_x11_display_logical_monitor_to_xinerama_index (MetaX11Display *x11_display, - MetaLogicalMonitor *logical_monitor); - -MetaLogicalMonitor *meta_x11_display_xinerama_index_to_logical_monitor (MetaX11Display *x11_display, - int xinerama_index); - -void meta_x11_display_update_workspace_layout (MetaX11Display *x11_display); -void meta_x11_display_update_workspace_names (MetaX11Display *x11_display); - -void meta_x11_display_increment_focus_sentinel (MetaX11Display *x11_display); -void meta_x11_display_decrement_focus_sentinel (MetaX11Display *x11_display); -gboolean meta_x11_display_focus_sentinel_clear (MetaX11Display *x11_display); - -void meta_x11_display_update_focus_window (MetaX11Display *x11_display, - Window xwindow, - gulong serial, - gboolean focused_by_us); -void meta_x11_display_set_input_focus (MetaX11Display *x11_display, - MetaWindow *window, - gboolean focus_frame, - uint32_t timestamp); - -MetaDisplay * meta_x11_display_get_display (MetaX11Display *x11_display); - -const gchar * meta_x11_get_display_name (void); - -#endif /* META_X11_DISPLAY_PRIVATE_H */ diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c deleted file mode 100644 index 8b446e348..000000000 --- a/src/x11/meta-x11-display.c +++ /dev/null @@ -1,2320 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002, 2003, 2004 Red Hat, Inc. - * Copyright (C) 2003, 2004 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * 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 . - */ - -/** - * SECTION:x11-display - * @title: MetaX11Display - * @short_description: Mutter X display handler - * - * The X11 display is represented as a #MetaX11Display struct. - */ - -#include "config.h" - -#include "core/display-private.h" -#include "x11/meta-x11-display-private.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "backends/meta-backend-private.h" -#include "backends/meta-dnd-private.h" -#include "backends/meta-cursor-sprite-xcursor.h" -#include "backends/meta-logical-monitor.h" -#include "backends/meta-settings-private.h" -#include "backends/x11/meta-backend-x11.h" -#include "backends/x11/meta-stage-x11.h" -#include "core/frame.h" -#include "core/meta-workspace-manager-private.h" -#include "core/util-private.h" -#include "core/workspace-private.h" -#include "meta/main.h" -#include "meta/meta-x11-errors.h" - -#include "x11/events.h" -#include "x11/group-props.h" -#include "x11/meta-x11-selection-private.h" -#include "x11/window-props.h" -#include "x11/xprops.h" - -#ifdef HAVE_WAYLAND -#include "wayland/meta-xwayland-private.h" -#endif - -G_DEFINE_TYPE (MetaX11Display, meta_x11_display, G_TYPE_OBJECT) - -static GQuark quark_x11_display_logical_monitor_data = 0; - -typedef struct _MetaX11DisplayLogicalMonitorData -{ - int xinerama_index; -} MetaX11DisplayLogicalMonitorData; - -static GdkDisplay *prepared_gdk_display = NULL; - -static char *get_screen_name (Display *xdisplay, - int number); - -static void on_monitors_changed_internal (MetaMonitorManager *monitor_manager, - MetaX11Display *x11_display); - -static void update_cursor_theme (MetaX11Display *x11_display); -static void unset_wm_check_hint (MetaX11Display *x11_display); - -static void prefs_changed_callback (MetaPreference pref, - void *data); - -static void -meta_x11_display_unmanage_windows (MetaX11Display *x11_display) -{ - GList *windows, *l; - - if (!x11_display->xids) - return; - - windows = g_hash_table_get_values (x11_display->xids); - g_list_foreach (windows, (GFunc) g_object_ref, NULL); - - for (l = windows; l; l = l->next) - { - if (META_IS_WINDOW (l->data)) - { - MetaWindow *window = l->data; - - if (!window->unmanaging) - meta_window_unmanage (window, META_CURRENT_TIME); - } - else if (META_IS_BARRIER (l->data)) - meta_barrier_destroy (META_BARRIER (l->data)); - else - g_assert_not_reached (); - } - g_list_free_full (windows, g_object_unref); -} - -static void -meta_x11_display_dispose (GObject *object) -{ - MetaX11Display *x11_display = META_X11_DISPLAY (object); - - x11_display->closing = TRUE; - - if (x11_display->empty_region != None) - { - XFixesDestroyRegion (x11_display->xdisplay, - x11_display->empty_region); - x11_display->empty_region = None; - } - - meta_x11_startup_notification_release (x11_display); - - meta_prefs_remove_listener (prefs_changed_callback, x11_display); - - meta_x11_display_ungrab_keys (x11_display); - - g_clear_object (&x11_display->x11_stack); - - meta_x11_selection_shutdown (x11_display); - meta_x11_display_unmanage_windows (x11_display); - - if (x11_display->ui) - { - meta_ui_free (x11_display->ui); - x11_display->ui = NULL; - } - - if (x11_display->no_focus_window != None) - { - XUnmapWindow (x11_display->xdisplay, x11_display->no_focus_window); - XDestroyWindow (x11_display->xdisplay, x11_display->no_focus_window); - - x11_display->no_focus_window = None; - } - - if (x11_display->composite_overlay_window != None) - { - XCompositeReleaseOverlayWindow (x11_display->xdisplay, - x11_display->composite_overlay_window); - - x11_display->composite_overlay_window = None; - } - - if (x11_display->wm_sn_selection_window != None) - { - XDestroyWindow (x11_display->xdisplay, x11_display->wm_sn_selection_window); - x11_display->wm_sn_selection_window = None; - } - - if (x11_display->timestamp_pinging_window != None) - { - XDestroyWindow (x11_display->xdisplay, x11_display->timestamp_pinging_window); - x11_display->timestamp_pinging_window = None; - } - - if (x11_display->leader_window != None) - { - XDestroyWindow (x11_display->xdisplay, x11_display->leader_window); - x11_display->leader_window = None; - } - - if (x11_display->guard_window != None) - { - XUnmapWindow (x11_display->xdisplay, x11_display->guard_window); - XDestroyWindow (x11_display->xdisplay, x11_display->guard_window); - x11_display->guard_window = None; - } - - if (x11_display->prop_hooks) - { - meta_x11_display_free_window_prop_hooks (x11_display); - x11_display->prop_hooks = NULL; - } - - if (x11_display->group_prop_hooks) - { - meta_x11_display_free_group_prop_hooks (x11_display); - x11_display->group_prop_hooks = NULL; - } - - if (x11_display->xids) - { - /* Must be after all calls to meta_window_unmanage() since they - * unregister windows - */ - g_hash_table_destroy (x11_display->xids); - x11_display->xids = NULL; - } - - if (x11_display->xroot != None) - { - unset_wm_check_hint (x11_display); - - meta_x11_error_trap_push (x11_display); - XSelectInput (x11_display->xdisplay, x11_display->xroot, 0); - if (meta_x11_error_trap_pop_with_return (x11_display) != Success) - meta_warning ("Could not release screen %d on display \"%s\"", - DefaultScreen (x11_display->xdisplay), - x11_display->name); - - x11_display->xroot = None; - } - - - if (x11_display->xdisplay) - { - meta_x11_display_free_events (x11_display); - - x11_display->xdisplay = NULL; - } - - if (x11_display->gdk_display) - { - gdk_display_close (x11_display->gdk_display); - x11_display->gdk_display = NULL; - } - - g_clear_handle_id (&x11_display->display_close_idle, g_source_remove); - - g_free (x11_display->name); - x11_display->name = NULL; - - g_free (x11_display->screen_name); - x11_display->screen_name = NULL; - - G_OBJECT_CLASS (meta_x11_display_parent_class)->dispose (object); -} - -static void -meta_x11_display_class_init (MetaX11DisplayClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = meta_x11_display_dispose; -} - -static void -meta_x11_display_init (MetaX11Display *x11_display) -{ - quark_x11_display_logical_monitor_data = - g_quark_from_static_string ("-meta-x11-display-logical-monitor-data"); -} - -static void -query_xsync_extension (MetaX11Display *x11_display) -{ - int major, minor; - - x11_display->have_xsync = FALSE; - - x11_display->xsync_error_base = 0; - x11_display->xsync_event_base = 0; - - /* I don't think we really have to fill these in */ - major = SYNC_MAJOR_VERSION; - minor = SYNC_MINOR_VERSION; - - if (!XSyncQueryExtension (x11_display->xdisplay, - &x11_display->xsync_event_base, - &x11_display->xsync_error_base) || - !XSyncInitialize (x11_display->xdisplay, - &major, &minor)) - { - x11_display->xsync_error_base = 0; - x11_display->xsync_event_base = 0; - } - else - { - x11_display->have_xsync = TRUE; - XSyncSetPriority (x11_display->xdisplay, None, 10); - } - - meta_verbose ("Attempted to init Xsync, found version %d.%d error base %d event base %d", - major, minor, - x11_display->xsync_error_base, - x11_display->xsync_event_base); -} - -static void -query_xshape_extension (MetaX11Display *x11_display) -{ - x11_display->have_shape = FALSE; - - x11_display->shape_error_base = 0; - x11_display->shape_event_base = 0; - - if (!XShapeQueryExtension (x11_display->xdisplay, - &x11_display->shape_event_base, - &x11_display->shape_error_base)) - { - x11_display->shape_error_base = 0; - x11_display->shape_event_base = 0; - } - else - x11_display->have_shape = TRUE; - - meta_verbose ("Attempted to init Shape, found error base %d event base %d", - x11_display->shape_error_base, - x11_display->shape_event_base); -} - -static void -query_xcomposite_extension (MetaX11Display *x11_display) -{ - x11_display->have_composite = FALSE; - - x11_display->composite_error_base = 0; - x11_display->composite_event_base = 0; - - if (!XCompositeQueryExtension (x11_display->xdisplay, - &x11_display->composite_event_base, - &x11_display->composite_error_base)) - { - x11_display->composite_error_base = 0; - x11_display->composite_event_base = 0; - } - else - { - x11_display->composite_major_version = 0; - x11_display->composite_minor_version = 0; - if (XCompositeQueryVersion (x11_display->xdisplay, - &x11_display->composite_major_version, - &x11_display->composite_minor_version)) - { - x11_display->have_composite = TRUE; - } - else - { - x11_display->composite_major_version = 0; - x11_display->composite_minor_version = 0; - } - } - - meta_verbose ("Attempted to init Composite, found error base %d event base %d " - "extn ver %d %d", - x11_display->composite_error_base, - x11_display->composite_event_base, - x11_display->composite_major_version, - x11_display->composite_minor_version); -} - -static void -query_xdamage_extension (MetaX11Display *x11_display) -{ - x11_display->have_damage = FALSE; - - x11_display->damage_error_base = 0; - x11_display->damage_event_base = 0; - - if (!XDamageQueryExtension (x11_display->xdisplay, - &x11_display->damage_event_base, - &x11_display->damage_error_base)) - { - x11_display->damage_error_base = 0; - x11_display->damage_event_base = 0; - } - else - x11_display->have_damage = TRUE; - - meta_verbose ("Attempted to init Damage, found error base %d event base %d", - x11_display->damage_error_base, - x11_display->damage_event_base); -} - -static void -query_xfixes_extension (MetaX11Display *x11_display) -{ - x11_display->xfixes_error_base = 0; - x11_display->xfixes_event_base = 0; - - if (XFixesQueryExtension (x11_display->xdisplay, - &x11_display->xfixes_event_base, - &x11_display->xfixes_error_base)) - { - int xfixes_major, xfixes_minor; - - XFixesQueryVersion (x11_display->xdisplay, &xfixes_major, &xfixes_minor); - - if (xfixes_major * 100 + xfixes_minor < 500) - meta_fatal ("Mutter requires XFixes 5.0"); - } - else - { - meta_fatal ("Mutter requires XFixes 5.0"); - } - - meta_verbose ("Attempted to init XFixes, found error base %d event base %d", - x11_display->xfixes_error_base, - x11_display->xfixes_event_base); -} - -static void -query_xi_extension (MetaX11Display *x11_display) -{ - int major = 2, minor = 3; - gboolean has_xi = FALSE; - - if (XQueryExtension (x11_display->xdisplay, - "XInputExtension", - &x11_display->xinput_opcode, - &x11_display->xinput_error_base, - &x11_display->xinput_event_base)) - { - if (XIQueryVersion (x11_display->xdisplay, &major, &minor) == Success) - { - int version = (major * 10) + minor; - if (version >= 22) - has_xi = TRUE; - - if (version >= 23) - x11_display->have_xinput_23 = TRUE; - } - } - - if (!has_xi) - meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer"); -} - -/* - * Initialises the bell subsystem. This involves initialising - * XKB (which, despite being a keyboard extension, is the - * place to look for bell notifications), then asking it - * to send us bell notifications, and then also switching - * off the audible bell if we're using a visual one ourselves. - * - * \bug There is a line of code that's never run that tells - * XKB to reset the bell status after we quit. Bill H said - * () - * that XFree86's implementation is broken so we shouldn't - * call it, but that was in 2002. Is it working now? - */ -static void -init_x11_bell (MetaX11Display *x11_display) -{ - int xkb_base_error_type, xkb_opcode; - - if (!XkbQueryExtension (x11_display->xdisplay, &xkb_opcode, - &x11_display->xkb_base_event_type, - &xkb_base_error_type, - NULL, NULL)) - { - x11_display->xkb_base_event_type = -1; - meta_warning ("could not find XKB extension."); - } - else - { - unsigned int mask = XkbBellNotifyMask; - gboolean visual_bell_auto_reset = FALSE; - /* TRUE if and when non-broken version is available */ - XkbSelectEvents (x11_display->xdisplay, - XkbUseCoreKbd, - XkbBellNotifyMask, - XkbBellNotifyMask); - - if (visual_bell_auto_reset) - { - XkbSetAutoResetControls (x11_display->xdisplay, - XkbAudibleBellMask, - &mask, - &mask); - } - } - - /* We are playing sounds using libcanberra support, we handle the - * bell whether its an audible bell or a visible bell */ - XkbChangeEnabledControls (x11_display->xdisplay, - XkbUseCoreKbd, - XkbAudibleBellMask, - 0); -} - -/* - * \bug This is never called! If we had XkbSetAutoResetControls - * enabled in meta_x11_bell_init(), this wouldn't be a problem, - * but we don't. - */ -G_GNUC_UNUSED static void -shutdown_x11_bell (MetaX11Display *x11_display) -{ - /* TODO: persist initial bell state in display, reset here */ - XkbChangeEnabledControls (x11_display->xdisplay, - XkbUseCoreKbd, - XkbAudibleBellMask, - XkbAudibleBellMask); -} - -static void -set_desktop_geometry_hint (MetaX11Display *x11_display) -{ - unsigned long data[2]; - int monitor_width, monitor_height; - - if (x11_display->display->closing > 0) - return; - - meta_display_get_size (x11_display->display, &monitor_width, &monitor_height); - - data[0] = monitor_width; - data[1] = monitor_height; - - meta_verbose ("Setting _NET_DESKTOP_GEOMETRY to %lu, %lu", data[0], data[1]); - - meta_x11_error_trap_push (x11_display); - XChangeProperty (x11_display->xdisplay, - x11_display->xroot, - x11_display->atom__NET_DESKTOP_GEOMETRY, - XA_CARDINAL, - 32, PropModeReplace, (guchar*) data, 2); - meta_x11_error_trap_pop (x11_display); -} - -static void -set_desktop_viewport_hint (MetaX11Display *x11_display) -{ - unsigned long data[2]; - - if (x11_display->display->closing > 0) - return; - - /* - * Mutter does not implement viewports, so this is a fixed 0,0 - */ - data[0] = 0; - data[1] = 0; - - meta_verbose ("Setting _NET_DESKTOP_VIEWPORT to 0, 0"); - - meta_x11_error_trap_push (x11_display); - XChangeProperty (x11_display->xdisplay, - x11_display->xroot, - x11_display->atom__NET_DESKTOP_VIEWPORT, - XA_CARDINAL, - 32, PropModeReplace, (guchar*) data, 2); - meta_x11_error_trap_pop (x11_display); -} - -static int -set_wm_check_hint (MetaX11Display *x11_display) -{ - unsigned long data[1]; - - g_return_val_if_fail (x11_display->leader_window != None, 0); - - data[0] = x11_display->leader_window; - - XChangeProperty (x11_display->xdisplay, - x11_display->xroot, - x11_display->atom__NET_SUPPORTING_WM_CHECK, - XA_WINDOW, - 32, PropModeReplace, (guchar*) data, 1); - - return Success; -} - -static void -unset_wm_check_hint (MetaX11Display *x11_display) -{ - XDeleteProperty (x11_display->xdisplay, - x11_display->xroot, - x11_display->atom__NET_SUPPORTING_WM_CHECK); -} - -static int -set_supported_hint (MetaX11Display *x11_display) -{ - Atom atoms[] = { -#define EWMH_ATOMS_ONLY -#define item(x) x11_display->atom_##x, -#include "x11/atomnames.h" -#undef item -#undef EWMH_ATOMS_ONLY - - x11_display->atom__GTK_FRAME_EXTENTS, - x11_display->atom__GTK_SHOW_WINDOW_MENU, - x11_display->atom__GTK_EDGE_CONSTRAINTS, - x11_display->atom__GTK_WORKAREAS, - }; - - XChangeProperty (x11_display->xdisplay, - x11_display->xroot, - x11_display->atom__NET_SUPPORTED, - XA_ATOM, - 32, PropModeReplace, - (guchar*) atoms, G_N_ELEMENTS(atoms)); - - return Success; -} - -static int -set_wm_icon_size_hint (MetaX11Display *x11_display) -{ -#define N_VALS 6 - gulong vals[N_VALS]; - - /* We've bumped the real icon size up to 96x96, but - * we really should not add these sorts of constraints - * on clients still using the legacy WM_HINTS interface. - */ -#define LEGACY_ICON_SIZE 32 - - /* min width, min height, max w, max h, width inc, height inc */ - vals[0] = LEGACY_ICON_SIZE; - vals[1] = LEGACY_ICON_SIZE; - vals[2] = LEGACY_ICON_SIZE; - vals[3] = LEGACY_ICON_SIZE; - vals[4] = 0; - vals[5] = 0; -#undef LEGACY_ICON_SIZE - - XChangeProperty (x11_display->xdisplay, - x11_display->xroot, - x11_display->atom_WM_ICON_SIZE, - XA_CARDINAL, - 32, PropModeReplace, (guchar*) vals, N_VALS); - - return Success; -#undef N_VALS -} - -static Window -take_manager_selection (MetaX11Display *x11_display, - Window xroot, - Atom manager_atom, - int timestamp, - gboolean should_replace) -{ - Window current_owner, new_owner; - - current_owner = XGetSelectionOwner (x11_display->xdisplay, manager_atom); - if (current_owner != None) - { - XSetWindowAttributes attrs; - - if (should_replace) - { - /* We want to find out when the current selection owner dies */ - meta_x11_error_trap_push (x11_display); - attrs.event_mask = StructureNotifyMask; - XChangeWindowAttributes (x11_display->xdisplay, current_owner, CWEventMask, &attrs); - if (meta_x11_error_trap_pop_with_return (x11_display) != Success) - current_owner = None; /* don't wait for it to die later on */ - } - else - { - meta_warning (_("Display “%s” already has a window manager; try using the --replace option to replace the current window manager."), - x11_display->name); - return None; - } - } - - /* We need SelectionClear and SelectionRequest events on the new owner, - * but those cannot be masked, so we only need NoEventMask. - */ - new_owner = meta_x11_display_create_offscreen_window (x11_display, xroot, NoEventMask); - - XSetSelectionOwner (x11_display->xdisplay, manager_atom, new_owner, timestamp); - - if (XGetSelectionOwner (x11_display->xdisplay, manager_atom) != new_owner) - { - meta_warning ("Could not acquire selection: %s", XGetAtomName (x11_display->xdisplay, manager_atom)); - return None; - } - - { - /* Send client message indicating that we are now the selection owner */ - XClientMessageEvent ev; - - ev.type = ClientMessage; - ev.window = xroot; - ev.message_type = x11_display->atom_MANAGER; - ev.format = 32; - ev.data.l[0] = timestamp; - ev.data.l[1] = manager_atom; - - XSendEvent (x11_display->xdisplay, xroot, False, StructureNotifyMask, (XEvent *) &ev); - } - - /* Wait for old window manager to go away */ - if (current_owner != None) - { - XEvent event; - - /* We sort of block infinitely here which is probably lame. */ - - meta_verbose ("Waiting for old window manager to exit"); - do - XWindowEvent (x11_display->xdisplay, current_owner, StructureNotifyMask, &event); - while (event.type != DestroyNotify); - } - - return new_owner; -} - -/* Create the leader window here. Set its properties and - * use the timestamp from one of the PropertyNotify events - * that will follow. - */ -static void -init_leader_window (MetaX11Display *x11_display, - guint32 *timestamp) -{ - MetaContext *context = meta_display_get_context (x11_display->display); - const char *gnome_wm_keybindings; - gulong data[1]; - XEvent event; - - /* We only care about the PropertyChangeMask in the next 30 or so lines of - * code. Note that gdk will at some point unset the PropertyChangeMask for - * this window, so we can't rely on it still being set later. See bug - * 354213 for details. - */ - x11_display->leader_window = - meta_x11_display_create_offscreen_window (x11_display, - x11_display->xroot, - PropertyChangeMask); - - meta_prop_set_utf8_string_hint (x11_display, - x11_display->leader_window, - x11_display->atom__NET_WM_NAME, - meta_context_get_name (context)); - - gnome_wm_keybindings = meta_context_get_gnome_wm_keybindings (context); - meta_prop_set_utf8_string_hint (x11_display, - x11_display->leader_window, - x11_display->atom__GNOME_WM_KEYBINDINGS, - gnome_wm_keybindings); - - meta_prop_set_utf8_string_hint (x11_display, - x11_display->leader_window, - x11_display->atom__MUTTER_VERSION, - VERSION); - - data[0] = x11_display->leader_window; - XChangeProperty (x11_display->xdisplay, - x11_display->leader_window, - x11_display->atom__NET_SUPPORTING_WM_CHECK, - XA_WINDOW, - 32, PropModeReplace, (guchar*) data, 1); - - XWindowEvent (x11_display->xdisplay, - x11_display->leader_window, - PropertyChangeMask, - &event); - - if (timestamp) - *timestamp = event.xproperty.time; - - /* Make it painfully clear that we can't rely on PropertyNotify events on - * this window, as per bug 354213. - */ - XSelectInput (x11_display->xdisplay, - x11_display->leader_window, - NoEventMask); -} - -static void -init_event_masks (MetaX11Display *x11_display) -{ - long event_mask; - unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 }; - XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits }; - - XISetMask (mask.mask, XI_Enter); - XISetMask (mask.mask, XI_Leave); - XISetMask (mask.mask, XI_FocusIn); - XISetMask (mask.mask, XI_FocusOut); - if (META_X11_DISPLAY_HAS_XINPUT_23 (x11_display)) - { - XISetMask (mask.mask, XI_BarrierHit); - XISetMask (mask.mask, XI_BarrierLeave); - } - XISelectEvents (x11_display->xdisplay, x11_display->xroot, &mask, 1); - - event_mask = (SubstructureRedirectMask | SubstructureNotifyMask | - StructureNotifyMask | ColormapChangeMask | PropertyChangeMask); - XSelectInput (x11_display->xdisplay, x11_display->xroot, event_mask); -} - -static void -set_active_workspace_hint (MetaWorkspaceManager *workspace_manager, - MetaX11Display *x11_display) -{ - unsigned long data[1]; - - /* this is because we destroy the spaces in order, - * so we always end up setting a current desktop of - * 0 when closing a screen, so lose the current desktop - * on restart. By doing this we keep the current - * desktop on restart. - */ - if (x11_display->display->closing > 0) - return; - - data[0] = meta_workspace_index (workspace_manager->active_workspace); - - meta_verbose ("Setting _NET_CURRENT_DESKTOP to %lu", data[0]); - - meta_x11_error_trap_push (x11_display); - XChangeProperty (x11_display->xdisplay, - x11_display->xroot, - x11_display->atom__NET_CURRENT_DESKTOP, - XA_CARDINAL, - 32, PropModeReplace, (guchar*) data, 1); - meta_x11_error_trap_pop (x11_display); -} - -static void -set_number_of_spaces_hint (MetaWorkspaceManager *workspace_manager, - GParamSpec *pspec, - gpointer user_data) -{ - MetaX11Display *x11_display = user_data; - unsigned long data[1]; - - if (x11_display->display->closing > 0) - return; - - data[0] = meta_workspace_manager_get_n_workspaces (workspace_manager); - - meta_verbose ("Setting _NET_NUMBER_OF_DESKTOPS to %lu", data[0]); - - meta_x11_error_trap_push (x11_display); - XChangeProperty (x11_display->xdisplay, - x11_display->xroot, - x11_display->atom__NET_NUMBER_OF_DESKTOPS, - XA_CARDINAL, - 32, PropModeReplace, (guchar*) data, 1); - meta_x11_error_trap_pop (x11_display); -} - -static void -set_showing_desktop_hint (MetaWorkspaceManager *workspace_manager, - MetaX11Display *x11_display) -{ - unsigned long data[1]; - - data[0] = workspace_manager->active_workspace->showing_desktop ? 1 : 0; - - meta_x11_error_trap_push (x11_display); - XChangeProperty (x11_display->xdisplay, - x11_display->xroot, - x11_display->atom__NET_SHOWING_DESKTOP, - XA_CARDINAL, - 32, PropModeReplace, (guchar*) data, 1); - meta_x11_error_trap_pop (x11_display); -} - -static void -set_workspace_names (MetaX11Display *x11_display) -{ - MetaWorkspaceManager *workspace_manager; - GString *flattened; - int i; - int n_spaces; - - workspace_manager = x11_display->display->workspace_manager; - - /* flatten to nul-separated list */ - n_spaces = meta_workspace_manager_get_n_workspaces (workspace_manager); - flattened = g_string_new (""); - i = 0; - while (i < n_spaces) - { - const char *name; - - name = meta_prefs_get_workspace_name (i); - - if (name) - g_string_append_len (flattened, name, - strlen (name) + 1); - else - g_string_append_len (flattened, "", 1); - - ++i; - } - - meta_x11_error_trap_push (x11_display); - XChangeProperty (x11_display->xdisplay, - x11_display->xroot, - x11_display->atom__NET_DESKTOP_NAMES, - x11_display->atom_UTF8_STRING, - 8, PropModeReplace, - (unsigned char *)flattened->str, flattened->len); - meta_x11_error_trap_pop (x11_display); - - g_string_free (flattened, TRUE); -} - -static void -set_workspace_work_area_hint (MetaWorkspace *workspace, - MetaX11Display *x11_display) -{ - MetaMonitorManager *monitor_manager; - GList *logical_monitors; - GList *l; - int num_monitors; - unsigned long *data; - unsigned long *tmp; - g_autofree char *workarea_name; - Atom workarea_atom; - - monitor_manager = meta_backend_get_monitor_manager (meta_get_backend ()); - logical_monitors = meta_monitor_manager_get_logical_monitors (monitor_manager); - num_monitors = meta_monitor_manager_get_num_logical_monitors (monitor_manager); - - data = g_new (unsigned long, num_monitors * 4); - tmp = data; - - for (l = logical_monitors; l; l = l->next) - { - MetaRectangle area; - - meta_workspace_get_work_area_for_logical_monitor (workspace, l->data, &area); - - tmp[0] = area.x; - tmp[1] = area.y; - tmp[2] = area.width; - tmp[3] = area.height; - - tmp += 4; - } - - workarea_name = g_strdup_printf ("_GTK_WORKAREAS_D%d", - meta_workspace_index (workspace)); - - workarea_atom = XInternAtom (x11_display->xdisplay, workarea_name, False); - - meta_x11_error_trap_push (x11_display); - XChangeProperty (x11_display->xdisplay, - x11_display->xroot, - workarea_atom, - XA_CARDINAL, 32, PropModeReplace, - (guchar*) data, num_monitors * 4); - meta_x11_error_trap_pop (x11_display); - - g_free (data); -} - -static void -set_work_area_hint (MetaDisplay *display, - MetaX11Display *x11_display) -{ - MetaWorkspaceManager *workspace_manager = display->workspace_manager; - int num_workspaces; - GList *l; - unsigned long *data, *tmp; - MetaRectangle area; - - num_workspaces = meta_workspace_manager_get_n_workspaces (workspace_manager); - data = g_new (unsigned long, num_workspaces * 4); - tmp = data; - - for (l = workspace_manager->workspaces; l; l = l->next) - { - MetaWorkspace *workspace = l->data; - - meta_workspace_get_work_area_all_monitors (workspace, &area); - set_workspace_work_area_hint (workspace, x11_display); - - tmp[0] = area.x; - tmp[1] = area.y; - tmp[2] = area.width; - tmp[3] = area.height; - - tmp += 4; - } - - meta_x11_error_trap_push (x11_display); - XChangeProperty (x11_display->xdisplay, - x11_display->xroot, - x11_display->atom__NET_WORKAREA, - XA_CARDINAL, 32, PropModeReplace, - (guchar*) data, num_workspaces*4); - meta_x11_error_trap_pop (x11_display); - - g_free (data); -} - -const gchar * -meta_x11_get_display_name (void) -{ -#ifdef HAVE_WAYLAND - if (meta_is_wayland_compositor ()) - { - MetaWaylandCompositor *compositor; - - compositor = meta_wayland_compositor_get_default (); - - return meta_wayland_get_private_xwayland_display_name (compositor); - } - else -#endif - { - return g_getenv ("DISPLAY"); - } -} - -gboolean -meta_x11_init_gdk_display (GError **error) -{ - const char *xdisplay_name; - GdkDisplay *gdk_display; - const char *gdk_gl_env = NULL; - const char *old_no_at_bridge; - Display *xdisplay; - - xdisplay_name = meta_x11_get_display_name (); - if (!xdisplay_name) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Unable to open display, DISPLAY not set"); - return FALSE; - } - - gdk_set_allowed_backends ("x11"); - - gdk_gl_env = g_getenv ("GDK_GL"); - g_setenv ("GDK_GL", "disable", TRUE); - - gdk_parse_args (NULL, NULL); - if (!gtk_parse_args (NULL, NULL)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to initialize gtk"); - return FALSE; - } - - old_no_at_bridge = g_getenv ("NO_AT_BRIDGE"); - g_setenv ("NO_AT_BRIDGE", "1", TRUE); - gdk_display = gdk_display_open (xdisplay_name); - - if (old_no_at_bridge) - g_setenv ("NO_AT_BRIDGE", old_no_at_bridge, TRUE); - else - g_unsetenv ("NO_AT_BRIDGE"); - - if (!gdk_display) - { - meta_warning (_("Failed to initialize GDK")); - - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to initialize GDK"); - - return FALSE; - } - - if (gdk_gl_env) - g_setenv("GDK_GL", gdk_gl_env, TRUE); - else - unsetenv("GDK_GL"); - - /* We need to be able to fully trust that the window and monitor sizes - that Gdk reports corresponds to the X ones, so we disable the automatic - scale handling */ - gdk_x11_display_set_window_scale (gdk_display, 1); - - meta_verbose ("Opening display '%s'", XDisplayName (NULL)); - - xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display); - - if (xdisplay == NULL) - { - meta_warning (_("Failed to open X Window System display “%s”"), - XDisplayName (NULL)); - - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to open X11 display"); - - gdk_display_close (gdk_display); - - return FALSE; - } - - prepared_gdk_display = gdk_display; - - return TRUE; -} - -/** - * meta_x11_display_new: - * - * Opens a new X11 display, sets it up, initialises all the X extensions - * we will need. - * - * Returns: #MetaX11Display if the display was opened successfully, - * and %NULL otherwise-- that is, if the display doesn't exist or - * it already has a window manager, and sets the error appropriately. - */ -MetaX11Display * -meta_x11_display_new (MetaDisplay *display, GError **error) -{ - MetaX11Display *x11_display; - Display *xdisplay; - Screen *xscreen; - Window xroot; - int i, number; - Window new_wm_sn_owner; - gboolean replace_current_wm; - Atom wm_sn_atom; - char buf[128]; - guint32 timestamp; - Atom atom_restart_helper; - Window restart_helper_window = None; - GdkDisplay *gdk_display; - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - - /* A list of all atom names, so that we can intern them in one go. */ - const char *atom_names[] = { -#define item(x) #x, -#include "x11/atomnames.h" -#undef item - }; - Atom atoms[G_N_ELEMENTS(atom_names)]; - - if (!meta_x11_init_gdk_display (error)) - return NULL; - - g_assert (prepared_gdk_display); - gdk_display = g_steal_pointer (&prepared_gdk_display); - xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display); - -#ifdef HAVE_WAYLAND - if (meta_is_wayland_compositor ()) - meta_xwayland_complete_init (display, xdisplay); -#endif - - if (meta_is_syncing ()) - XSynchronize (xdisplay, True); - - replace_current_wm = - meta_context_is_replacing (meta_backend_get_context (backend)); - - /* According to _gdk_x11_display_open (), this will be returned - * by gdk_display_get_default_screen () - */ - number = DefaultScreen (xdisplay); - - xroot = RootWindow (xdisplay, number); - - /* FVWM checks for None here, I don't know if this - * ever actually happens - */ - if (xroot == None) - { - meta_warning (_("Screen %d on display “%s” is invalid"), - number, XDisplayName (NULL)); - - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to open default X11 screen"); - - XFlush (xdisplay); - XCloseDisplay (xdisplay); - - gdk_display_close (gdk_display); - - return NULL; - } - - xscreen = ScreenOfDisplay (xdisplay, number); - - atom_restart_helper = XInternAtom (xdisplay, "_MUTTER_RESTART_HELPER", False); - restart_helper_window = XGetSelectionOwner (xdisplay, atom_restart_helper); - if (restart_helper_window) - meta_set_is_restart (TRUE); - - x11_display = g_object_new (META_TYPE_X11_DISPLAY, NULL); - x11_display->gdk_display = gdk_display; - x11_display->display = display; - - /* here we use XDisplayName which is what the user - * probably put in, vs. DisplayString(display) which is - * canonicalized by XOpenDisplay() - */ - x11_display->xdisplay = xdisplay; - x11_display->xroot = xroot; - - x11_display->name = g_strdup (XDisplayName (NULL)); - x11_display->screen_name = get_screen_name (xdisplay, number); - x11_display->default_xvisual = DefaultVisualOfScreen (xscreen); - x11_display->default_depth = DefaultDepthOfScreen (xscreen); - - meta_verbose ("Creating %d atoms", (int) G_N_ELEMENTS (atom_names)); - XInternAtoms (xdisplay, (char **)atom_names, G_N_ELEMENTS (atom_names), - False, atoms); - - i = 0; -#define item(x) x11_display->atom_##x = atoms[i++]; -#include "x11/atomnames.h" -#undef item - - query_xsync_extension (x11_display); - query_xshape_extension (x11_display); - query_xcomposite_extension (x11_display); - query_xdamage_extension (x11_display); - query_xfixes_extension (x11_display); - query_xi_extension (x11_display); - - g_signal_connect_object (display, - "cursor-updated", - G_CALLBACK (update_cursor_theme), - x11_display, - G_CONNECT_SWAPPED); - - update_cursor_theme (x11_display); - - x11_display->xids = g_hash_table_new (meta_unsigned_long_hash, - meta_unsigned_long_equal); - - x11_display->groups_by_leader = NULL; - x11_display->ui = NULL; - x11_display->composite_overlay_window = None; - x11_display->guard_window = None; - x11_display->leader_window = None; - x11_display->timestamp_pinging_window = None; - x11_display->wm_sn_selection_window = None; - - x11_display->display_close_idle = 0; - x11_display->xselectionclear_timestamp = 0; - - x11_display->last_bell_time = 0; - x11_display->focus_serial = 0; - x11_display->server_focus_window = None; - x11_display->server_focus_serial = 0; - - x11_display->prop_hooks = NULL; - meta_x11_display_init_window_prop_hooks (x11_display); - x11_display->group_prop_hooks = NULL; - meta_x11_display_init_group_prop_hooks (x11_display); - - g_signal_connect_object (monitor_manager, - "monitors-changed-internal", - G_CALLBACK (on_monitors_changed_internal), - x11_display, - 0); - - init_leader_window (x11_display, ×tamp); - x11_display->timestamp = timestamp; - - /* Make a little window used only for pinging the server for timestamps; note - * that meta_create_offscreen_window already selects for PropertyChangeMask. - */ - x11_display->timestamp_pinging_window = - meta_x11_display_create_offscreen_window (x11_display, - xroot, - PropertyChangeMask); - - sprintf (buf, "WM_S%d", number); - - wm_sn_atom = XInternAtom (xdisplay, buf, False); - new_wm_sn_owner = take_manager_selection (x11_display, xroot, wm_sn_atom, timestamp, replace_current_wm); - if (new_wm_sn_owner == None) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Failed to acquire window manager ownership"); - - g_object_run_dispose (G_OBJECT (x11_display)); - g_clear_object (&x11_display); - - return NULL; - } - - x11_display->wm_sn_selection_window = new_wm_sn_owner; - x11_display->wm_sn_atom = wm_sn_atom; - x11_display->wm_sn_timestamp = timestamp; - - init_event_masks (x11_display); - - /* Select for cursor changes so the cursor tracker is up to date. */ - XFixesSelectCursorInput (xdisplay, xroot, XFixesDisplayCursorNotifyMask); - - /* If we're a Wayland compositor, then we don't grab the COW, since it - * will map it. */ - if (!meta_is_wayland_compositor ()) - x11_display->composite_overlay_window = XCompositeGetOverlayWindow (xdisplay, xroot); - - /* Now that we've gotten taken a reference count on the COW, we - * can close the helper that is holding on to it */ - if (meta_is_restart ()) - XSetSelectionOwner (xdisplay, atom_restart_helper, None, META_CURRENT_TIME); - - /* Handle creating a no_focus_window for this screen */ - x11_display->no_focus_window = - meta_x11_display_create_offscreen_window (x11_display, - xroot, - FocusChangeMask|KeyPressMask|KeyReleaseMask); - XMapWindow (xdisplay, x11_display->no_focus_window); - /* Done with no_focus_window stuff */ - - meta_x11_display_init_events (x11_display); - - set_wm_icon_size_hint (x11_display); - - set_supported_hint (x11_display); - - set_wm_check_hint (x11_display); - - set_desktop_viewport_hint (x11_display); - - set_desktop_geometry_hint (x11_display); - - x11_display->ui = meta_ui_new (x11_display); - x11_display->x11_stack = meta_x11_stack_new (x11_display); - - x11_display->keys_grabbed = FALSE; - meta_x11_display_grab_keys (x11_display); - - meta_x11_display_update_workspace_layout (x11_display); - - if (meta_prefs_get_dynamic_workspaces ()) - { - int num = 0; - int n_items = 0; - uint32_t *list = NULL; - - if (meta_prop_get_cardinal_list (x11_display, - x11_display->xroot, - x11_display->atom__NET_NUMBER_OF_DESKTOPS, - &list, &n_items)) - { - num = list[0]; - g_free (list); - } - - if (num > meta_workspace_manager_get_n_workspaces (display->workspace_manager)) - meta_workspace_manager_update_num_workspaces (display->workspace_manager, timestamp, num); - } - - g_signal_connect_object (display->workspace_manager, "active-workspace-changed", - G_CALLBACK (set_active_workspace_hint), - x11_display, 0); - - set_number_of_spaces_hint (display->workspace_manager, NULL, x11_display); - - g_signal_connect_object (display->workspace_manager, "notify::n-workspaces", - G_CALLBACK (set_number_of_spaces_hint), - x11_display, 0); - - set_showing_desktop_hint (display->workspace_manager, x11_display); - - g_signal_connect_object (display->workspace_manager, "showing-desktop-changed", - G_CALLBACK (set_showing_desktop_hint), - x11_display, 0); - - set_workspace_names (x11_display); - - meta_prefs_add_listener (prefs_changed_callback, x11_display); - - set_work_area_hint (display, x11_display); - - g_signal_connect_object (display, "workareas-changed", - G_CALLBACK (set_work_area_hint), - x11_display, 0); - - init_x11_bell (x11_display); - - meta_x11_startup_notification_init (x11_display); - meta_x11_selection_init (x11_display); - - if (!meta_is_wayland_compositor ()) - meta_dnd_init_xdnd (x11_display); - - return x11_display; -} - -void -meta_x11_display_restore_active_workspace (MetaX11Display *x11_display) -{ - MetaDisplay *display; - MetaWorkspace *current_workspace; - uint32_t current_workspace_index = 0; - guint32 timestamp; - - g_return_if_fail (META_IS_X11_DISPLAY (x11_display)); - - display = x11_display->display; - timestamp = x11_display->timestamp; - - /* Get current workspace */ - if (meta_prop_get_cardinal (x11_display, - x11_display->xroot, - x11_display->atom__NET_CURRENT_DESKTOP, - ¤t_workspace_index)) - { - meta_verbose ("Read existing _NET_CURRENT_DESKTOP = %d", - (int) current_workspace_index); - - /* Switch to the _NET_CURRENT_DESKTOP workspace */ - current_workspace = meta_workspace_manager_get_workspace_by_index (display->workspace_manager, - current_workspace_index); - - if (current_workspace != NULL) - meta_workspace_activate (current_workspace, timestamp); - } - else - { - meta_verbose ("No _NET_CURRENT_DESKTOP present"); - } - - set_active_workspace_hint (display->workspace_manager, x11_display); -} - -int -meta_x11_display_get_screen_number (MetaX11Display *x11_display) -{ - return DefaultScreen (x11_display->xdisplay); -} - -MetaDisplay * -meta_x11_display_get_display (MetaX11Display *x11_display) -{ - return x11_display->display; -} - -/** - * meta_x11_display_get_xdisplay: (skip) - * @x11_display: a #MetaX11Display - * - */ -Display * -meta_x11_display_get_xdisplay (MetaX11Display *x11_display) -{ - return x11_display->xdisplay; -} - -/** - * meta_x11_display_get_xroot: (skip) - * @x11_display: A #MetaX11Display - * - */ -Window -meta_x11_display_get_xroot (MetaX11Display *x11_display) -{ - return x11_display->xroot; -} - -/** - * meta_x11_display_get_xinput_opcode: (skip) - * @x11_display: a #MetaX11Display - * - */ -int -meta_x11_display_get_xinput_opcode (MetaX11Display *x11_display) -{ - return x11_display->xinput_opcode; -} - -int -meta_x11_display_get_damage_event_base (MetaX11Display *x11_display) -{ - return x11_display->damage_event_base; -} - -int -meta_x11_display_get_shape_event_base (MetaX11Display *x11_display) -{ - return x11_display->shape_event_base; -} - -gboolean -meta_x11_display_has_shape (MetaX11Display *x11_display) -{ - return META_X11_DISPLAY_HAS_SHAPE (x11_display); -} - -Window -meta_x11_display_create_offscreen_window (MetaX11Display *x11_display, - Window parent, - long valuemask) -{ - XSetWindowAttributes attrs; - - /* we want to be override redirect because sometimes we - * create a window on a screen we aren't managing. - * (but on a display we are managing at least one screen for) - */ - attrs.override_redirect = True; - attrs.event_mask = valuemask; - - return XCreateWindow (x11_display->xdisplay, - parent, - -100, -100, 1, 1, - 0, - CopyFromParent, - CopyFromParent, - (Visual *)CopyFromParent, - CWOverrideRedirect | CWEventMask, - &attrs); -} - -Cursor -meta_x11_display_create_x_cursor (MetaX11Display *x11_display, - MetaCursor cursor) -{ - return meta_create_x_cursor (x11_display->xdisplay, cursor); -} - -static char * -get_screen_name (Display *xdisplay, - int number) -{ - char *p; - char *dname; - char *scr; - - /* DisplayString gives us a sort of canonical display, - * vs. the user-entered name from XDisplayName() - */ - dname = g_strdup (DisplayString (xdisplay)); - - /* Change display name to specify this screen. - */ - p = strrchr (dname, ':'); - if (p) - { - p = strchr (p, '.'); - if (p) - *p = '\0'; - } - - scr = g_strdup_printf ("%s.%d", dname, number); - - g_free (dname); - - return scr; -} - -void -meta_x11_display_reload_cursor (MetaX11Display *x11_display) -{ - Cursor xcursor; - MetaCursor cursor = x11_display->display->current_cursor; - - /* Set a cursor for X11 applications that don't specify their own */ - xcursor = meta_x11_display_create_x_cursor (x11_display, cursor); - - XDefineCursor (x11_display->xdisplay, x11_display->xroot, xcursor); - XFlush (x11_display->xdisplay); - - if (xcursor) - XFreeCursor (x11_display->xdisplay, xcursor); -} - -static void -set_cursor_theme (Display *xdisplay) -{ - MetaBackend *backend = meta_get_backend (); - MetaSettings *settings = meta_backend_get_settings (backend); - int scale; - - scale = meta_settings_get_ui_scaling_factor (settings); - XcursorSetTheme (xdisplay, meta_prefs_get_cursor_theme ()); - XcursorSetDefaultSize (xdisplay, meta_prefs_get_cursor_size () * scale); -} - -static void -update_cursor_theme (MetaX11Display *x11_display) -{ - MetaBackend *backend = meta_get_backend (); - - set_cursor_theme (x11_display->xdisplay); - meta_x11_display_reload_cursor (x11_display); - - if (META_IS_BACKEND_X11 (backend)) - { - MetaBackendX11 *backend_x11 = META_BACKEND_X11 (backend); - Display *xdisplay = meta_backend_x11_get_xdisplay (backend_x11); - - set_cursor_theme (xdisplay); - meta_backend_x11_reload_cursor (backend_x11); - } -} - -MetaWindow * -meta_x11_display_lookup_x_window (MetaX11Display *x11_display, - Window xwindow) -{ - return g_hash_table_lookup (x11_display->xids, &xwindow); -} - -void -meta_x11_display_register_x_window (MetaX11Display *x11_display, - Window *xwindowp, - MetaWindow *window) -{ - g_return_if_fail (g_hash_table_lookup (x11_display->xids, xwindowp) == NULL); - - g_hash_table_insert (x11_display->xids, xwindowp, window); -} - -void -meta_x11_display_unregister_x_window (MetaX11Display *x11_display, - Window xwindow) -{ - g_return_if_fail (g_hash_table_lookup (x11_display->xids, &xwindow) != NULL); - - g_hash_table_remove (x11_display->xids, &xwindow); -} - - -/* We store sync alarms in the window ID hash table, because they are - * just more types of XIDs in the same global space, but we have - * typesafe functions to register/unregister for readability. - */ - -MetaWindow * -meta_x11_display_lookup_sync_alarm (MetaX11Display *x11_display, - XSyncAlarm alarm) -{ - return g_hash_table_lookup (x11_display->xids, &alarm); -} - -void -meta_x11_display_register_sync_alarm (MetaX11Display *x11_display, - XSyncAlarm *alarmp, - MetaWindow *window) -{ - g_return_if_fail (g_hash_table_lookup (x11_display->xids, alarmp) == NULL); - - g_hash_table_insert (x11_display->xids, alarmp, window); -} - -void -meta_x11_display_unregister_sync_alarm (MetaX11Display *x11_display, - XSyncAlarm alarm) -{ - g_return_if_fail (g_hash_table_lookup (x11_display->xids, &alarm) != NULL); - - g_hash_table_remove (x11_display->xids, &alarm); -} - -void -meta_x11_display_set_alarm_filter (MetaX11Display *x11_display, - MetaAlarmFilter filter, - gpointer data) -{ - g_return_if_fail (filter == NULL || x11_display->alarm_filter == NULL); - - x11_display->alarm_filter = filter; - x11_display->alarm_filter_data = data; -} - -/* The guard window allows us to leave minimized windows mapped so - * that compositor code may provide live previews of them. - * Instead of being unmapped/withdrawn, they get pushed underneath - * the guard window. We also select events on the guard window, which - * should effectively be forwarded to events on the background actor, - * providing that the scene graph is set up correctly. - */ -static Window -create_guard_window (MetaX11Display *x11_display) -{ - XSetWindowAttributes attributes; - Window guard_window; - gulong create_serial; - int display_width, display_height; - - meta_display_get_size (x11_display->display, - &display_width, - &display_height); - - attributes.event_mask = NoEventMask; - attributes.override_redirect = True; - - /* We have to call record_add() after we have the new window ID, - * so save the serial for the CreateWindow request until then */ - create_serial = XNextRequest (x11_display->xdisplay); - guard_window = - XCreateWindow (x11_display->xdisplay, - x11_display->xroot, - 0, /* x */ - 0, /* y */ - display_width, - display_height, - 0, /* border width */ - 0, /* depth */ - InputOnly, /* class */ - CopyFromParent, /* visual */ - CWEventMask | CWOverrideRedirect, - &attributes); - - /* https://bugzilla.gnome.org/show_bug.cgi?id=710346 */ - XStoreName (x11_display->xdisplay, guard_window, "mutter guard window"); - - { - if (!meta_is_wayland_compositor ()) - { - MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ()); - Display *backend_xdisplay = meta_backend_x11_get_xdisplay (backend); - unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 }; - XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits }; - - XISetMask (mask.mask, XI_ButtonPress); - XISetMask (mask.mask, XI_ButtonRelease); - XISetMask (mask.mask, XI_Motion); - - /* Sync on the connection we created the window on to - * make sure it's created before we select on it on the - * backend connection. */ - XSync (x11_display->xdisplay, False); - - XISelectEvents (backend_xdisplay, guard_window, &mask, 1); - } - } - - meta_stack_tracker_record_add (x11_display->display->stack_tracker, - guard_window, - create_serial); - - meta_stack_tracker_lower (x11_display->display->stack_tracker, - guard_window); - - XMapWindow (x11_display->xdisplay, guard_window); - return guard_window; -} - -void -meta_x11_display_create_guard_window (MetaX11Display *x11_display) -{ - if (x11_display->guard_window == None) - x11_display->guard_window = create_guard_window (x11_display); -} - -static void -on_monitors_changed_internal (MetaMonitorManager *monitor_manager, - MetaX11Display *x11_display) -{ - int display_width, display_height; - - meta_monitor_manager_get_screen_size (monitor_manager, - &display_width, - &display_height); - - set_desktop_geometry_hint (x11_display); - - /* Resize the guard window to fill the screen again. */ - if (x11_display->guard_window != None) - { - XWindowChanges changes; - - changes.x = 0; - changes.y = 0; - changes.width = display_width; - changes.height = display_height; - - XConfigureWindow (x11_display->xdisplay, - x11_display->guard_window, - CWX | CWY | CWWidth | CWHeight, - &changes); - } - - x11_display->has_xinerama_indices = FALSE; -} - -void -meta_x11_display_set_cm_selection (MetaX11Display *x11_display) -{ - char selection[32]; - Atom a; - guint32 timestamp; - - timestamp = meta_x11_display_get_current_time_roundtrip (x11_display); - g_snprintf (selection, sizeof (selection), "_NET_WM_CM_S%d", - DefaultScreen (x11_display->xdisplay)); - a = XInternAtom (x11_display->xdisplay, selection, False); - - x11_display->wm_cm_selection_window = take_manager_selection (x11_display, x11_display->xroot, a, timestamp, TRUE); -} - -static Bool -find_timestamp_predicate (Display *xdisplay, - XEvent *ev, - XPointer arg) -{ - MetaX11Display *x11_display = (MetaX11Display *) arg; - - return (ev->type == PropertyNotify && - ev->xproperty.atom == x11_display->atom__MUTTER_TIMESTAMP_PING); -} - -/* Get a timestamp, even if it means a roundtrip */ -guint32 -meta_x11_display_get_current_time_roundtrip (MetaX11Display *x11_display) -{ - guint32 timestamp; - - timestamp = meta_display_get_current_time (x11_display->display); - if (timestamp == META_CURRENT_TIME) - { - XEvent property_event; - - XChangeProperty (x11_display->xdisplay, - x11_display->timestamp_pinging_window, - x11_display->atom__MUTTER_TIMESTAMP_PING, - XA_STRING, 8, PropModeAppend, NULL, 0); - XIfEvent (x11_display->xdisplay, - &property_event, - find_timestamp_predicate, - (XPointer) x11_display); - timestamp = property_event.xproperty.time; - } - - meta_display_sanity_check_timestamps (x11_display->display, timestamp); - - return timestamp; -} - -/** - * meta_x11_display_xwindow_is_a_no_focus_window: - * @x11_display: A #MetaX11Display - * @xwindow: An X11 window - * - * Returns: %TRUE iff window is one of mutter's internal "no focus" windows - * which will have the focus when there is no actual client window focused. - */ -gboolean -meta_x11_display_xwindow_is_a_no_focus_window (MetaX11Display *x11_display, - Window xwindow) -{ - return xwindow == x11_display->no_focus_window; -} - -void -meta_x11_display_increment_event_serial (MetaX11Display *x11_display) - -{ - /* We just make some random X request */ - XDeleteProperty (x11_display->xdisplay, - x11_display->leader_window, - x11_display->atom__MOTIF_WM_HINTS); -} - -static void -meta_x11_display_update_active_window_hint (MetaX11Display *x11_display) -{ - MetaWindow *focus_window; - gulong data[1]; - - if (x11_display->display->closing) - return; /* Leave old value for a replacement */ - - focus_window = meta_x11_display_lookup_x_window (x11_display, - x11_display->focus_xwindow); - - if (focus_window) - data[0] = focus_window->xwindow; - else - data[0] = None; - - meta_x11_error_trap_push (x11_display); - XChangeProperty (x11_display->xdisplay, - x11_display->xroot, - x11_display->atom__NET_ACTIVE_WINDOW, - XA_WINDOW, - 32, PropModeReplace, (guchar*) data, 1); - meta_x11_error_trap_pop (x11_display); -} - -void -meta_x11_display_update_focus_window (MetaX11Display *x11_display, - Window xwindow, - gulong serial, - gboolean focused_by_us) -{ - x11_display->focus_serial = serial; - x11_display->focused_by_us = !!focused_by_us; - - if (x11_display->focus_xwindow == xwindow) - return; - - x11_display->focus_xwindow = xwindow; - meta_x11_display_update_active_window_hint (x11_display); -} - -static void -meta_x11_display_set_input_focus_internal (MetaX11Display *x11_display, - Window xwindow, - uint32_t timestamp) -{ - meta_x11_error_trap_push (x11_display); - - /* In order for mutter to know that the focus request succeeded, we track - * the serial of the "focus request" we made, but if we take the serial - * of the XSetInputFocus request, then there's no way to determine the - * difference between focus events as a result of the SetInputFocus and - * focus events that other clients send around the same time. Ensure that - * we know which is which by making two requests that the server will - * process at the same time. - */ - XGrabServer (x11_display->xdisplay); - - XSetInputFocus (x11_display->xdisplay, - xwindow, - RevertToPointerRoot, - timestamp); - - XChangeProperty (x11_display->xdisplay, - x11_display->timestamp_pinging_window, - x11_display->atom__MUTTER_FOCUS_SET, - XA_STRING, 8, PropModeAppend, NULL, 0); - - XUngrabServer (x11_display->xdisplay); - XFlush (x11_display->xdisplay); - - meta_x11_error_trap_pop (x11_display); -} - -void -meta_x11_display_set_input_focus (MetaX11Display *x11_display, - MetaWindow *window, - gboolean focus_frame, - uint32_t timestamp) -{ - Window xwindow; - gulong serial; - - if (window) - xwindow = focus_frame ? window->frame->xwindow : window->xwindow; - else - xwindow = x11_display->no_focus_window; - - meta_x11_error_trap_push (x11_display); - meta_x11_display_set_input_focus_internal (x11_display, xwindow, timestamp); - serial = XNextRequest (x11_display->xdisplay); - meta_x11_display_update_focus_window (x11_display, xwindow, serial, TRUE); - meta_x11_error_trap_pop (x11_display); -} - -void -meta_x11_display_set_input_focus_xwindow (MetaX11Display *x11_display, - Window window, - guint32 timestamp) -{ - gulong serial; - - if (meta_display_timestamp_too_old (x11_display->display, ×tamp)) - return; - - meta_x11_display_set_input_focus_internal (x11_display, window, timestamp); - serial = XNextRequest (x11_display->xdisplay); - meta_x11_display_update_focus_window (x11_display, window, serial, TRUE); - meta_display_update_focus_window (x11_display->display, NULL); - meta_display_remove_autoraise_callback (x11_display->display); - x11_display->display->last_focus_time = timestamp; -} - -static MetaX11DisplayLogicalMonitorData * -get_x11_display_logical_monitor_data (MetaLogicalMonitor *logical_monitor) -{ - return g_object_get_qdata (G_OBJECT (logical_monitor), - quark_x11_display_logical_monitor_data); -} - -static MetaX11DisplayLogicalMonitorData * -ensure_x11_display_logical_monitor_data (MetaLogicalMonitor *logical_monitor) -{ - MetaX11DisplayLogicalMonitorData *data; - - data = get_x11_display_logical_monitor_data (logical_monitor); - if (data) - return data; - - data = g_new0 (MetaX11DisplayLogicalMonitorData, 1); - g_object_set_qdata_full (G_OBJECT (logical_monitor), - quark_x11_display_logical_monitor_data, - data, - g_free); - - return data; -} - -static void -meta_x11_display_ensure_xinerama_indices (MetaX11Display *x11_display) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - GList *logical_monitors, *l; - XineramaScreenInfo *infos; - int n_infos, j; - - if (x11_display->has_xinerama_indices) - return; - - x11_display->has_xinerama_indices = TRUE; - - if (!XineramaIsActive (x11_display->xdisplay)) - return; - - infos = XineramaQueryScreens (x11_display->xdisplay, - &n_infos); - if (n_infos <= 0 || infos == NULL) - { - meta_XFree (infos); - return; - } - - logical_monitors = - meta_monitor_manager_get_logical_monitors (monitor_manager); - - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - - for (j = 0; j < n_infos; ++j) - { - if (logical_monitor->rect.x == infos[j].x_org && - logical_monitor->rect.y == infos[j].y_org && - logical_monitor->rect.width == infos[j].width && - logical_monitor->rect.height == infos[j].height) - { - MetaX11DisplayLogicalMonitorData *logical_monitor_data; - - logical_monitor_data = - ensure_x11_display_logical_monitor_data (logical_monitor); - logical_monitor_data->xinerama_index = j; - } - } - } - - meta_XFree (infos); -} - -int -meta_x11_display_logical_monitor_to_xinerama_index (MetaX11Display *x11_display, - MetaLogicalMonitor *logical_monitor) -{ - MetaX11DisplayLogicalMonitorData *logical_monitor_data; - - g_return_val_if_fail (logical_monitor, -1); - - meta_x11_display_ensure_xinerama_indices (x11_display); - - logical_monitor_data = get_x11_display_logical_monitor_data (logical_monitor); - - return logical_monitor_data->xinerama_index; -} - -MetaLogicalMonitor * -meta_x11_display_xinerama_index_to_logical_monitor (MetaX11Display *x11_display, - int xinerama_index) -{ - MetaBackend *backend = meta_get_backend (); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - GList *logical_monitors, *l; - - meta_x11_display_ensure_xinerama_indices (x11_display); - - logical_monitors = - meta_monitor_manager_get_logical_monitors (monitor_manager); - - for (l = logical_monitors; l; l = l->next) - { - MetaLogicalMonitor *logical_monitor = l->data; - MetaX11DisplayLogicalMonitorData *logical_monitor_data; - - logical_monitor_data = - ensure_x11_display_logical_monitor_data (logical_monitor); - - if (logical_monitor_data->xinerama_index == xinerama_index) - return logical_monitor; - } - - return NULL; -} - -void -meta_x11_display_update_workspace_names (MetaX11Display *x11_display) -{ - char **names; - int n_names; - int i; - - /* this updates names in prefs when the root window property changes, - * iff the new property contents don't match what's already in prefs - */ - - names = NULL; - n_names = 0; - if (!meta_prop_get_utf8_list (x11_display, - x11_display->xroot, - x11_display->atom__NET_DESKTOP_NAMES, - &names, &n_names)) - { - meta_verbose ("Failed to get workspace names from root window"); - return; - } - - i = 0; - while (i < n_names) - { - meta_topic (META_DEBUG_PREFS, - "Setting workspace %d name to \"%s\" due to _NET_DESKTOP_NAMES change", - i, names[i] ? names[i] : "null"); - meta_prefs_change_workspace_name (i, names[i]); - - ++i; - } - - g_strfreev (names); -} - -#define _NET_WM_ORIENTATION_HORZ 0 -#define _NET_WM_ORIENTATION_VERT 1 - -#define _NET_WM_TOPLEFT 0 -#define _NET_WM_TOPRIGHT 1 -#define _NET_WM_BOTTOMRIGHT 2 -#define _NET_WM_BOTTOMLEFT 3 - -void -meta_x11_display_update_workspace_layout (MetaX11Display *x11_display) -{ - MetaWorkspaceManager *workspace_manager = x11_display->display->workspace_manager; - gboolean vertical_layout = FALSE; - int n_rows = 1; - int n_columns = -1; - MetaDisplayCorner starting_corner = META_DISPLAY_TOPLEFT; - uint32_t *list; - int n_items; - - if (workspace_manager->workspace_layout_overridden) - return; - - list = NULL; - n_items = 0; - - if (meta_prop_get_cardinal_list (x11_display, - x11_display->xroot, - x11_display->atom__NET_DESKTOP_LAYOUT, - &list, &n_items)) - { - if (n_items == 3 || n_items == 4) - { - int cols, rows; - - switch (list[0]) - { - case _NET_WM_ORIENTATION_HORZ: - vertical_layout = FALSE; - break; - case _NET_WM_ORIENTATION_VERT: - vertical_layout = TRUE; - break; - default: - meta_warning ("Someone set a weird orientation in _NET_DESKTOP_LAYOUT"); - break; - } - - cols = list[1]; - rows = list[2]; - - if (rows <= 0 && cols <= 0) - { - meta_warning ("Columns = %d rows = %d in _NET_DESKTOP_LAYOUT makes no sense", rows, cols); - } - else - { - if (rows > 0) - n_rows = rows; - else - n_rows = -1; - - if (cols > 0) - n_columns = cols; - else - n_columns = -1; - } - - if (n_items == 4) - { - switch (list[3]) - { - case _NET_WM_TOPLEFT: - starting_corner = META_DISPLAY_TOPLEFT; - break; - case _NET_WM_TOPRIGHT: - starting_corner = META_DISPLAY_TOPRIGHT; - break; - case _NET_WM_BOTTOMRIGHT: - starting_corner = META_DISPLAY_BOTTOMRIGHT; - break; - case _NET_WM_BOTTOMLEFT: - starting_corner = META_DISPLAY_BOTTOMLEFT; - break; - default: - meta_warning ("Someone set a weird starting corner in _NET_DESKTOP_LAYOUT"); - break; - } - } - } - else - { - meta_warning ("Someone set _NET_DESKTOP_LAYOUT to %d integers instead of 4 " - "(3 is accepted for backwards compat)", n_items); - } - - g_free (list); - - meta_workspace_manager_update_workspace_layout (workspace_manager, - starting_corner, - vertical_layout, - n_rows, - n_columns); - } -} - -static void -prefs_changed_callback (MetaPreference pref, - void *data) -{ - MetaX11Display *x11_display = data; - - if (pref == META_PREF_WORKSPACE_NAMES) - { - set_workspace_names (x11_display); - } -} - -void -meta_x11_display_increment_focus_sentinel (MetaX11Display *x11_display) -{ - unsigned long data[1]; - - data[0] = meta_display_get_current_time (x11_display->display); - - XChangeProperty (x11_display->xdisplay, - x11_display->xroot, - x11_display->atom__MUTTER_SENTINEL, - XA_CARDINAL, - 32, PropModeReplace, (guchar*) data, 1); - - x11_display->sentinel_counter += 1; -} - -void -meta_x11_display_decrement_focus_sentinel (MetaX11Display *x11_display) -{ - x11_display->sentinel_counter -= 1; - - if (x11_display->sentinel_counter < 0) - x11_display->sentinel_counter = 0; -} - -gboolean -meta_x11_display_focus_sentinel_clear (MetaX11Display *x11_display) -{ - return (x11_display->sentinel_counter == 0); -} - -void -meta_x11_display_set_stage_input_region (MetaX11Display *x11_display, - XserverRegion region) -{ - Display *xdisplay = x11_display->xdisplay; - MetaBackend *backend = meta_get_backend (); - ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend)); - Window stage_xwindow; - - g_return_if_fail (!meta_is_wayland_compositor ()); - - stage_xwindow = meta_x11_get_stage_window (stage); - XFixesSetWindowShapeRegion (xdisplay, stage_xwindow, - ShapeInput, 0, 0, region); - - /* - * It's generally a good heuristic that when a crossing event is generated - * because we reshape the overlay, we don't want it to affect - * focus-follows-mouse focus - it's not the user doing something, it's the - * environment changing under the user. - */ - meta_display_add_ignored_crossing_serial (x11_display->display, - XNextRequest (xdisplay)); - XFixesSetWindowShapeRegion (xdisplay, - x11_display->composite_overlay_window, - ShapeInput, 0, 0, region); -} - -void -meta_x11_display_clear_stage_input_region (MetaX11Display *x11_display) -{ - if (x11_display->empty_region == None) - { - x11_display->empty_region = XFixesCreateRegion (x11_display->xdisplay, - NULL, 0); - } - - meta_x11_display_set_stage_input_region (x11_display, - x11_display->empty_region); -} diff --git a/src/x11/meta-x11-errors.c b/src/x11/meta-x11-errors.c deleted file mode 100644 index 506769464..000000000 --- a/src/x11/meta-x11-errors.c +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington, error trapping inspired by GDK - * code copyrighted by the GTK team. - * - * 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 . - */ - -/** - * SECTION:errors - * @title: Errors - * @short_description: Mutter X error handling - */ - -#include "config.h" - -#include "meta/meta-x11-errors.h" - -#include -#include -#include - -#include "x11/meta-x11-display-private.h" - -/* In GTK+-3.0, the error trapping code was significantly rewritten. The new code - * has some neat features (like knowing automatically if a sync is needed or not - * and handling errors asynchronously when the error code isn't needed immediately), - * but it's basically incompatible with the hacks we played with GTK+-2.0 to - * use a custom error handler along with gdk_error_trap_push(). - * - * Since the main point of our custom error trap was to get the error logged - * to the right place, with GTK+-3.0 we simply omit our own error handler and - * use the GTK+ handling straight-up. - * (See https://bugzilla.gnome.org/show_bug.cgi?id=630216 for restoring logging.) - */ - -void -meta_x11_error_trap_push (MetaX11Display *x11_display) -{ - gdk_x11_display_error_trap_push (x11_display->gdk_display); -} - -void -meta_x11_error_trap_pop (MetaX11Display *x11_display) -{ - gdk_x11_display_error_trap_pop_ignored (x11_display->gdk_display); -} - -int -meta_x11_error_trap_pop_with_return (MetaX11Display *x11_display) -{ - return gdk_x11_display_error_trap_pop (x11_display->gdk_display); -} diff --git a/src/x11/meta-x11-selection-input-stream-private.h b/src/x11/meta-x11-selection-input-stream-private.h deleted file mode 100644 index 3fcf9ffd1..000000000 --- a/src/x11/meta-x11-selection-input-stream-private.h +++ /dev/null @@ -1,54 +0,0 @@ -/* GIO - GLib Input, Output and Streaming Library - * - * Copyright (C) 2017 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.1 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 . - * - * Author: Benjamin Otte - * Christian Kellner - */ - -#ifndef META_X11_SELECTION_INPUT_STREAM_H -#define META_X11_SELECTION_INPUT_STREAM_H - -#include - -#include "x11/meta-x11-display-private.h" - -#define META_TYPE_X11_SELECTION_INPUT_STREAM (meta_x11_selection_input_stream_get_type ()) -G_DECLARE_FINAL_TYPE (MetaX11SelectionInputStream, - meta_x11_selection_input_stream, - META, X11_SELECTION_INPUT_STREAM, - GInputStream) - -void meta_x11_selection_input_stream_new_async (MetaX11Display *x11_display, - Window window, - const char *selection, - const char *target, - guint32 timestamp, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -GInputStream * meta_x11_selection_input_stream_new_finish (GAsyncResult *result, - const char **type, - int *format, - GError **error); - -gboolean meta_x11_selection_input_stream_xevent (MetaX11SelectionInputStream *stream, - const XEvent *xevent); - -G_END_DECLS - -#endif /* META_X11_SELECTION_INPUT_STREAM_H */ diff --git a/src/x11/meta-x11-selection-input-stream.c b/src/x11/meta-x11-selection-input-stream.c deleted file mode 100644 index e8d782047..000000000 --- a/src/x11/meta-x11-selection-input-stream.c +++ /dev/null @@ -1,572 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * Copyright (C) 2017 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.1 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 . - * - * Author: Benjamin Otte - * Christian Kellner - */ - -#include "config.h" - -#include "meta-x11-selection-input-stream-private.h" - -#include - -#include "meta/meta-x11-errors.h" -#include "x11/meta-x11-display-private.h" - -typedef struct MetaX11SelectionInputStreamPrivate MetaX11SelectionInputStreamPrivate; - -struct _MetaX11SelectionInputStream -{ - GInputStream parent_instance; -}; - -struct MetaX11SelectionInputStreamPrivate -{ - MetaX11Display *x11_display; - Window window; - GAsyncQueue *chunks; - char *selection; - Atom xselection; - char *target; - Atom xtarget; - char *property; - Atom xproperty; - const char *type; - Atom xtype; - int format; - - GTask *pending_task; - uint8_t *pending_data; - size_t pending_size; - - guint complete : 1; - guint incr : 1; -}; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaX11SelectionInputStream, - meta_x11_selection_input_stream, - G_TYPE_INPUT_STREAM) - -static gboolean -meta_x11_selection_input_stream_has_data (MetaX11SelectionInputStream *stream) -{ - MetaX11SelectionInputStreamPrivate *priv = - meta_x11_selection_input_stream_get_instance_private (stream); - - return g_async_queue_length (priv->chunks) > 0 || priv->complete; -} - -/* NB: blocks when no data is in buffer */ -static size_t -meta_x11_selection_input_stream_fill_buffer (MetaX11SelectionInputStream *stream, - uint8_t *buffer, - size_t count) -{ - MetaX11SelectionInputStreamPrivate *priv = - meta_x11_selection_input_stream_get_instance_private (stream); - GBytes *bytes; - size_t result = 0; - - g_async_queue_lock (priv->chunks); - - for (bytes = g_async_queue_pop_unlocked (priv->chunks); - bytes != NULL && count > 0; - bytes = g_async_queue_try_pop_unlocked (priv->chunks)) - { - size_t size = g_bytes_get_size (bytes); - - if (size == 0) - { - /* EOF marker, put it back */ - g_async_queue_push_front_unlocked (priv->chunks, bytes); - bytes = NULL; - break; - } - else if (size > count) - { - GBytes *subbytes; - if (buffer) - memcpy (buffer, g_bytes_get_data (bytes, NULL), count); - subbytes = g_bytes_new_from_bytes (bytes, count, size - count); - g_async_queue_push_front_unlocked (priv->chunks, subbytes); - size = count; - } - else - { - if (buffer) - memcpy (buffer, g_bytes_get_data (bytes, NULL), size); - } - - g_bytes_unref (bytes); - result += size; - if (buffer) - buffer += size; - count -= size; - } - - if (bytes) - g_async_queue_push_front_unlocked (priv->chunks, bytes); - - g_async_queue_unlock (priv->chunks); - - return result; -} - -static void -meta_x11_selection_input_stream_flush (MetaX11SelectionInputStream *stream) -{ - MetaX11SelectionInputStreamPrivate *priv = - meta_x11_selection_input_stream_get_instance_private (stream); - gssize written; - - if (!meta_x11_selection_input_stream_has_data (stream)) - return; - - if (priv->pending_task == NULL) - return; - - written = meta_x11_selection_input_stream_fill_buffer (stream, - priv->pending_data, - priv->pending_size); - g_task_return_int (priv->pending_task, written); - - g_clear_object (&priv->pending_task); - priv->pending_data = NULL; - priv->pending_size = 0; -} - -static void -meta_x11_selection_input_stream_complete (MetaX11SelectionInputStream *stream) -{ - MetaX11SelectionInputStreamPrivate *priv = - meta_x11_selection_input_stream_get_instance_private (stream); - - if (priv->complete) - return; - - priv->complete = TRUE; - - g_async_queue_push (priv->chunks, g_bytes_new (NULL, 0)); - meta_x11_selection_input_stream_flush (stream); - - priv->x11_display->selection.input_streams = - g_list_remove (priv->x11_display->selection.input_streams, stream); - - g_object_unref (stream); -} - -static gssize -meta_x11_selection_input_stream_read (GInputStream *input_stream, - void *buffer, - size_t count, - GCancellable *cancellable, - GError **error) -{ - MetaX11SelectionInputStream *stream = - META_X11_SELECTION_INPUT_STREAM (input_stream); - - return meta_x11_selection_input_stream_fill_buffer (stream, buffer, count); -} - -static gboolean -meta_x11_selection_input_stream_close (GInputStream *stream, - GCancellable *cancellable, - GError **error) -{ - return TRUE; -} - -static void -meta_x11_selection_input_stream_read_async (GInputStream *input_stream, - void *buffer, - size_t count, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MetaX11SelectionInputStream *stream = - META_X11_SELECTION_INPUT_STREAM (input_stream); - MetaX11SelectionInputStreamPrivate *priv = - meta_x11_selection_input_stream_get_instance_private (stream); - GTask *task; - - task = g_task_new (stream, cancellable, callback, user_data); - g_task_set_source_tag (task, meta_x11_selection_input_stream_read_async); - g_task_set_priority (task, io_priority); - - if (meta_x11_selection_input_stream_has_data (stream)) - { - gssize size; - - size = meta_x11_selection_input_stream_fill_buffer (stream, buffer, count); - g_task_return_int (task, size); - g_object_unref (task); - } - else - { - priv->pending_data = buffer; - priv->pending_size = count; - priv->pending_task = task; - } -} - -static gssize -meta_x11_selection_input_stream_read_finish (GInputStream *stream, - GAsyncResult *result, - GError **error) -{ - g_return_val_if_fail (g_task_is_valid (result, stream), -1); - g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == - meta_x11_selection_input_stream_read_async, -1); - - return g_task_propagate_int (G_TASK (result), error); -} - -static void -meta_x11_selection_input_stream_close_async (GInputStream *stream, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (stream, cancellable, callback, user_data); - g_task_set_source_tag (task, meta_x11_selection_input_stream_close_async); - g_task_return_boolean (task, TRUE); - g_object_unref (task); -} - -static gboolean -meta_x11_selection_input_stream_close_finish (GInputStream *stream, - GAsyncResult *result, - GError **error) -{ - return TRUE; -} - -static void -meta_x11_selection_input_stream_dispose (GObject *object) -{ - MetaX11SelectionInputStream *stream = - META_X11_SELECTION_INPUT_STREAM (object); - MetaX11SelectionInputStreamPrivate *priv = - meta_x11_selection_input_stream_get_instance_private (stream); - - priv->x11_display->selection.input_streams = - g_list_remove (priv->x11_display->selection.input_streams, stream); - - G_OBJECT_CLASS (meta_x11_selection_input_stream_parent_class)->dispose (object); -} - -static void -meta_x11_selection_input_stream_finalize (GObject *object) -{ - MetaX11SelectionInputStream *stream = - META_X11_SELECTION_INPUT_STREAM (object); - MetaX11SelectionInputStreamPrivate *priv = - meta_x11_selection_input_stream_get_instance_private (stream); - - g_async_queue_unref (priv->chunks); - - g_free (priv->selection); - g_free (priv->target); - g_free (priv->property); - - G_OBJECT_CLASS (meta_x11_selection_input_stream_parent_class)->finalize (object); -} - -static void -meta_x11_selection_input_stream_class_init (MetaX11SelectionInputStreamClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GInputStreamClass *istream_class = G_INPUT_STREAM_CLASS (klass); - - object_class->dispose = meta_x11_selection_input_stream_dispose; - object_class->finalize = meta_x11_selection_input_stream_finalize; - - istream_class->read_fn = meta_x11_selection_input_stream_read; - istream_class->close_fn = meta_x11_selection_input_stream_close; - - istream_class->read_async = meta_x11_selection_input_stream_read_async; - istream_class->read_finish = meta_x11_selection_input_stream_read_finish; - istream_class->close_async = meta_x11_selection_input_stream_close_async; - istream_class->close_finish = meta_x11_selection_input_stream_close_finish; -} - -static void -meta_x11_selection_input_stream_init (MetaX11SelectionInputStream *stream) -{ - MetaX11SelectionInputStreamPrivate *priv = - meta_x11_selection_input_stream_get_instance_private (stream); - - priv->chunks = g_async_queue_new_full ((GDestroyNotify) g_bytes_unref); -} - -static void -XFree_without_return_value (gpointer data) -{ - XFree (data); -} - -static GBytes * -get_selection_property (Display *xdisplay, - Window owner, - Atom property, - Atom *ret_type, - gint *ret_format) -{ - gulong nitems; - gulong nbytes; - Atom prop_type; - gint prop_format; - uint8_t *data = NULL; - - if (XGetWindowProperty (xdisplay, owner, property, - 0, 0x1FFFFFFF, False, - AnyPropertyType, &prop_type, &prop_format, - &nitems, &nbytes, &data) != Success) - goto err; - - if (prop_type != None) - { - size_t length; - - switch (prop_format) - { - case 8: - length = nitems; - break; - case 16: - length = sizeof (short) * nitems; - break; - case 32: - length = sizeof (long) * nitems; - break; - default: - g_warning ("Unknown XGetWindowProperty() format %u", prop_format); - goto err; - } - - *ret_type = prop_type; - *ret_format = prop_format; - - return g_bytes_new_with_free_func (data, - length, - XFree_without_return_value, - data); - } - -err: - if (data) - XFree (data); - - *ret_type = None; - *ret_format = 0; - - return NULL; -} - -gboolean -meta_x11_selection_input_stream_xevent (MetaX11SelectionInputStream *stream, - const XEvent *xevent) -{ - MetaX11SelectionInputStreamPrivate *priv = - meta_x11_selection_input_stream_get_instance_private (stream); - Display *xdisplay; - Window xwindow; - GBytes *bytes; - Atom type; - gint format; - - xdisplay = priv->x11_display->xdisplay; - xwindow = priv->window; - - if (xevent->xany.display != xdisplay || - xevent->xany.window != xwindow) - return FALSE; - - switch (xevent->type) - { - case PropertyNotify: - if (!priv->incr || - xevent->xproperty.atom != priv->xproperty || - xevent->xproperty.state != PropertyNewValue) - return FALSE; - - bytes = get_selection_property (xdisplay, xwindow, xevent->xproperty.atom, - &type, &format); - - if (bytes == NULL) - { - g_debug ("INCR request came out empty"); - meta_x11_selection_input_stream_complete (stream); - } - else if (g_bytes_get_size (bytes) == 0 || type == None) - { - g_bytes_unref (bytes); - meta_x11_selection_input_stream_complete (stream); - } - else - { - g_async_queue_push (priv->chunks, bytes); - meta_x11_selection_input_stream_flush (stream); - } - - XDeleteProperty (xdisplay, xwindow, xevent->xproperty.atom); - - return FALSE; - - case SelectionNotify: - { - GTask *task; - - /* selection is not for us */ - if (priv->xselection != xevent->xselection.selection || - priv->xtarget != xevent->xselection.target) - return FALSE; - - /* We already received a selectionNotify before */ - if (priv->pending_task == NULL || - g_task_get_source_tag (priv->pending_task) != meta_x11_selection_input_stream_new_async) - { - g_debug ("Misbehaving client sent a reentrant SelectionNotify"); - return FALSE; - } - - task = g_steal_pointer (&priv->pending_task); - - if (xevent->xselection.property == None) - { - g_task_return_new_error (task, - G_IO_ERROR, - G_IO_ERROR_NOT_FOUND, - _("Format %s not supported"), priv->target); - meta_x11_selection_input_stream_complete (stream); - } - else - { - bytes = get_selection_property (xdisplay, xwindow, - xevent->xselection.property, - &priv->xtype, &priv->format); - priv->type = gdk_x11_get_xatom_name (priv->xtype); - - g_task_return_pointer (task, g_object_ref (stream), g_object_unref); - - if (bytes == NULL) - { - meta_x11_selection_input_stream_complete (stream); - } - else - { - if (priv->xtype == XInternAtom (priv->x11_display->xdisplay, "INCR", False)) - { - /* The remainder of the selection will come through PropertyNotify - events on xwindow */ - priv->incr = TRUE; - meta_x11_selection_input_stream_flush (stream); - } - else - { - g_async_queue_push (priv->chunks, bytes); - - meta_x11_selection_input_stream_complete (stream); - } - } - - XDeleteProperty (xdisplay, xwindow, xevent->xselection.property); - } - - g_object_unref (task); - } - return TRUE; - - default: - return FALSE; - } -} - -void -meta_x11_selection_input_stream_new_async (MetaX11Display *x11_display, - Window window, - const char *selection, - const char *target, - guint32 timestamp, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MetaX11SelectionInputStream *stream; - MetaX11SelectionInputStreamPrivate *priv; - - stream = g_object_new (META_TYPE_X11_SELECTION_INPUT_STREAM, NULL); - priv = meta_x11_selection_input_stream_get_instance_private (stream); - - priv->x11_display = x11_display; - x11_display->selection.input_streams = - g_list_prepend (x11_display->selection.input_streams, stream); - priv->selection = g_strdup (selection); - priv->xselection = XInternAtom (x11_display->xdisplay, priv->selection, False); - priv->target = g_strdup (target); - priv->xtarget = XInternAtom (x11_display->xdisplay, priv->target, False); - priv->property = g_strdup_printf ("META_SELECTION_%p", stream); - priv->xproperty = XInternAtom (x11_display->xdisplay, priv->property, False); - priv->window = window; - - XConvertSelection (x11_display->xdisplay, - priv->xselection, - priv->xtarget, - priv->xproperty, - window, - timestamp); - - priv->pending_task = g_task_new (NULL, cancellable, callback, user_data); - g_task_set_source_tag (priv->pending_task, meta_x11_selection_input_stream_new_async); - g_task_set_priority (priv->pending_task, io_priority); -} - -GInputStream * -meta_x11_selection_input_stream_new_finish (GAsyncResult *result, - const char **type, - int *format, - GError **error) -{ - MetaX11SelectionInputStream *stream; - MetaX11SelectionInputStreamPrivate *priv; - GTask *task; - - g_return_val_if_fail (g_task_is_valid (result, NULL), NULL); - task = G_TASK (result); - g_return_val_if_fail (g_task_get_source_tag (task) == - meta_x11_selection_input_stream_new_async, NULL); - - stream = g_task_propagate_pointer (task, error); - if (!stream) - return NULL; - - priv = meta_x11_selection_input_stream_get_instance_private (stream); - - if (type) - *type = priv->type; - if (format) - *format = priv->format; - - return G_INPUT_STREAM (stream); -} diff --git a/src/x11/meta-x11-selection-output-stream-private.h b/src/x11/meta-x11-selection-output-stream-private.h deleted file mode 100644 index 83390da48..000000000 --- a/src/x11/meta-x11-selection-output-stream-private.h +++ /dev/null @@ -1,47 +0,0 @@ -/* GIO - GLib Output, Output and Streaming Library - * - * Copyright (C) 2017 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.1 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 . - * - * Author: Benjamin Otte - * Christian Kellner - */ - -#ifndef META_X11_SELECTION_OUTPUT_STREAM_H -#define META_X11_SELECTION_OUTPUT_STREAM_H - -#include - -#include "x11/meta-x11-display-private.h" - -#define META_TYPE_X11_SELECTION_OUTPUT_STREAM (meta_x11_selection_output_stream_get_type ()) -G_DECLARE_FINAL_TYPE (MetaX11SelectionOutputStream, - meta_x11_selection_output_stream, - META, X11_SELECTION_OUTPUT_STREAM, - GOutputStream) - -GOutputStream * meta_x11_selection_output_stream_new (MetaX11Display *x11_display, - Window window, - const char *selection, - const char *target, - const char *property, - const char *type, - int format, - gulong timestamp); - -gboolean meta_x11_selection_output_stream_xevent (MetaX11SelectionOutputStream *stream, - const XEvent *xevent); - -#endif /* META_X11_SELECTION_OUTPUT_STREAM_H */ diff --git a/src/x11/meta-x11-selection-output-stream.c b/src/x11/meta-x11-selection-output-stream.c deleted file mode 100644 index 41a691c9a..000000000 --- a/src/x11/meta-x11-selection-output-stream.c +++ /dev/null @@ -1,686 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * Copyright (C) 2017 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.1 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 . - * - * Author: Benjamin Otte - * Christian Kellner - */ - -#include "config.h" - -#include "meta-x11-selection-output-stream-private.h" - -#include "meta/meta-x11-errors.h" -#include "x11/meta-x11-display-private.h" - -typedef struct _MetaX11SelectionOutputStreamPrivate MetaX11SelectionOutputStreamPrivate; - -struct _MetaX11SelectionOutputStream -{ - GOutputStream parent_instance; -}; - -struct _MetaX11SelectionOutputStreamPrivate -{ - MetaX11Display *x11_display; - Window xwindow; - Atom xselection; - Atom xtarget; - Atom xproperty; - Atom xtype; - int format; - gulong timestamp; - - GMutex mutex; - GCond cond; - GByteArray *data; - guint flush_requested : 1; - - GTask *pending_task; - - guint incr : 1; - guint delete_pending : 1; - guint pipe_error : 1; -}; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaX11SelectionOutputStream, - meta_x11_selection_output_stream, - G_TYPE_OUTPUT_STREAM); - -static size_t get_element_size (int format); - -static void -meta_x11_selection_output_stream_notify_selection (MetaX11SelectionOutputStream *stream) -{ - MetaX11SelectionOutputStreamPrivate *priv = - meta_x11_selection_output_stream_get_instance_private (stream); - XSelectionEvent event; - Display *xdisplay; - - event = (XSelectionEvent) { - .type = SelectionNotify, - .time = priv->timestamp, - .requestor = priv->xwindow, - .selection = priv->xselection, - .target = priv->xtarget, - .property = priv->xproperty, - }; - - meta_x11_error_trap_push (priv->x11_display); - - xdisplay = priv->x11_display->xdisplay; - - XSendEvent (xdisplay, - priv->xwindow, False, NoEventMask, - (XEvent *) &event); - XSync (xdisplay, False); - - meta_x11_error_trap_pop (priv->x11_display); -} - -static gboolean -meta_x11_selection_output_stream_can_flush (MetaX11SelectionOutputStream *stream) -{ - MetaX11SelectionOutputStreamPrivate *priv = - meta_x11_selection_output_stream_get_instance_private (stream); - - if (priv->delete_pending) - return FALSE; - if (!g_output_stream_is_closing (G_OUTPUT_STREAM (stream)) && - priv->data->len < get_element_size (priv->format)) - return FALSE; - - return TRUE; -} - -static size_t -get_max_request_size (MetaX11Display *display) -{ - size_t size; - - size = XExtendedMaxRequestSize (display->xdisplay); - if (size <= 0) - size = XMaxRequestSize (display->xdisplay); - - return (size - 100) * 4; -} - -static gboolean -meta_x11_selection_output_stream_needs_flush_unlocked (MetaX11SelectionOutputStream *stream) -{ - MetaX11SelectionOutputStreamPrivate *priv = - meta_x11_selection_output_stream_get_instance_private (stream); - - if (priv->data->len == 0) - { - if (priv->incr) - return g_output_stream_is_closing (G_OUTPUT_STREAM (stream)); - else - return FALSE; - } - - if (g_output_stream_is_closing (G_OUTPUT_STREAM (stream))) - return TRUE; - - if (priv->flush_requested) - return TRUE; - - return priv->data->len >= get_max_request_size (priv->x11_display); -} - -static gboolean -meta_x11_selection_output_stream_needs_flush (MetaX11SelectionOutputStream *stream) -{ - MetaX11SelectionOutputStreamPrivate *priv = - meta_x11_selection_output_stream_get_instance_private (stream); - - gboolean result; - - g_mutex_lock (&priv->mutex); - - result = meta_x11_selection_output_stream_needs_flush_unlocked (stream); - - g_mutex_unlock (&priv->mutex); - - return result; -} - -static size_t -get_element_size (int format) -{ - switch (format) - { - case 8: - return 1; - - case 16: - return sizeof (short); - - case 32: - return sizeof (long); - - default: - g_warning ("Unknown format %u", format); - return 1; - } -} - -static gboolean -meta_x11_selection_output_stream_check_pipe (MetaX11SelectionOutputStream *stream, - GError **error) -{ - MetaX11SelectionOutputStreamPrivate *priv = - meta_x11_selection_output_stream_get_instance_private (stream); - - if (priv->pipe_error) - { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_BROKEN_PIPE, - "Connection with client was broken"); - return FALSE; - } - - return TRUE; -} - -static void -meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *stream) -{ - MetaX11SelectionOutputStreamPrivate *priv = - meta_x11_selection_output_stream_get_instance_private (stream); - Display *xdisplay; - size_t element_size, n_elements, max_size; - gboolean first_chunk = FALSE; - int error_code; - - g_assert (!priv->delete_pending); - - xdisplay = priv->x11_display->xdisplay; - - /* We operate on a foreign window, better guard against catastrophe */ - meta_x11_error_trap_push (priv->x11_display); - - g_mutex_lock (&priv->mutex); - - element_size = get_element_size (priv->format); - n_elements = priv->data->len / element_size; - max_size = get_max_request_size (priv->x11_display); - - if (!priv->incr) - first_chunk = TRUE; - - if (!priv->incr && priv->data->len > max_size) - { - XWindowAttributes attrs; - - priv->incr = TRUE; - XGetWindowAttributes (xdisplay, - priv->xwindow, - &attrs); - if (!(attrs.your_event_mask & PropertyChangeMask)) - { - XSelectInput (xdisplay, priv->xwindow, attrs.your_event_mask | PropertyChangeMask); - } - - XChangeProperty (xdisplay, - priv->xwindow, - priv->xproperty, - XInternAtom (priv->x11_display->xdisplay, "INCR", False), - 32, - PropModeReplace, - (guchar *) &(long) { n_elements }, - 1); - priv->delete_pending = TRUE; - } - else - { - size_t copy_n_elements; - - if (priv->incr && priv->data->len > 0) - priv->delete_pending = TRUE; - - copy_n_elements = MIN (n_elements, max_size / element_size); - - XChangeProperty (xdisplay, - priv->xwindow, - priv->xproperty, - priv->xtype, - priv->format, - PropModeReplace, - priv->data->data, - copy_n_elements); - g_byte_array_remove_range (priv->data, 0, copy_n_elements * element_size); - } - - if (first_chunk) - meta_x11_selection_output_stream_notify_selection (stream); - - g_cond_broadcast (&priv->cond); - g_mutex_unlock (&priv->mutex); - - error_code = meta_x11_error_trap_pop_with_return (priv->x11_display); - - if (error_code != Success) - { - char error_str[100]; - - priv->flush_requested = FALSE; - priv->delete_pending = FALSE; - priv->pipe_error = TRUE; - - if (priv->pending_task) - { - XGetErrorText (xdisplay, error_code, error_str, sizeof (error_str)); - g_task_return_new_error (priv->pending_task, - G_IO_ERROR, - G_IO_ERROR_BROKEN_PIPE, - "Failed to flush selection output stream: %s", - error_str); - g_clear_object (&priv->pending_task); - } - } - else if (priv->pending_task && priv->data->len == 0 && !priv->delete_pending) - { - size_t result; - - priv->flush_requested = FALSE; - result = GPOINTER_TO_SIZE (g_task_get_task_data (priv->pending_task)); - g_task_return_int (priv->pending_task, result); - g_clear_object (&priv->pending_task); - } -} - -static gboolean -meta_x11_selection_output_stream_invoke_flush (gpointer data) -{ - MetaX11SelectionOutputStream *stream = - META_X11_SELECTION_OUTPUT_STREAM (data); - MetaX11SelectionOutputStreamPrivate *priv = - meta_x11_selection_output_stream_get_instance_private (stream); - - if (meta_x11_selection_output_stream_needs_flush (stream) && - meta_x11_selection_output_stream_can_flush (stream)) - meta_x11_selection_output_stream_perform_flush (stream); - - if (priv->delete_pending || priv->data->len > 0) - return G_SOURCE_CONTINUE; - else - return G_SOURCE_REMOVE; -} - -static gssize -meta_x11_selection_output_stream_write (GOutputStream *output_stream, - const void *buffer, - size_t count, - GCancellable *cancellable, - GError **error) -{ - MetaX11SelectionOutputStream *stream = - META_X11_SELECTION_OUTPUT_STREAM (output_stream); - MetaX11SelectionOutputStreamPrivate *priv = - meta_x11_selection_output_stream_get_instance_private (stream); - - if (!meta_x11_selection_output_stream_check_pipe (stream, error)) - return -1; - - g_mutex_lock (&priv->mutex); - g_byte_array_append (priv->data, buffer, count); - g_mutex_unlock (&priv->mutex); - - g_main_context_invoke (NULL, meta_x11_selection_output_stream_invoke_flush, stream); - - g_mutex_lock (&priv->mutex); - if (meta_x11_selection_output_stream_needs_flush_unlocked (stream)) - g_cond_wait (&priv->cond, &priv->mutex); - g_mutex_unlock (&priv->mutex); - - return count; -} - -static void -meta_x11_selection_output_stream_write_async (GOutputStream *output_stream, - const void *buffer, - size_t count, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MetaX11SelectionOutputStream *stream = - META_X11_SELECTION_OUTPUT_STREAM (output_stream); - MetaX11SelectionOutputStreamPrivate *priv = - meta_x11_selection_output_stream_get_instance_private (stream); - GError *error = NULL; - GTask *task; - - task = g_task_new (stream, cancellable, callback, user_data); - g_task_set_source_tag (task, meta_x11_selection_output_stream_write_async); - g_task_set_priority (task, io_priority); - - if (!meta_x11_selection_output_stream_check_pipe (stream, &error)) - { - g_task_return_error (task, error); - return; - } - - g_mutex_lock (&priv->mutex); - g_byte_array_append (priv->data, buffer, count); - g_mutex_unlock (&priv->mutex); - - if (!meta_x11_selection_output_stream_needs_flush (stream)) - { - g_task_return_int (task, count); - g_object_unref (task); - return; - } - else - { - if (meta_x11_selection_output_stream_can_flush (stream)) - meta_x11_selection_output_stream_perform_flush (stream); - - g_task_return_int (task, count); - g_object_unref (task); - return; - } -} - -static gssize -meta_x11_selection_output_stream_write_finish (GOutputStream *stream, - GAsyncResult *result, - GError **error) -{ - g_return_val_if_fail (g_task_is_valid (result, stream), -1); - g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == - meta_x11_selection_output_stream_write_async, -1); - - return g_task_propagate_int (G_TASK (result), error); -} - -static gboolean -meta_x11_selection_output_request_flush (MetaX11SelectionOutputStream *stream) -{ - MetaX11SelectionOutputStreamPrivate *priv = - meta_x11_selection_output_stream_get_instance_private (stream); - gboolean needs_flush; - - g_mutex_lock (&priv->mutex); - - if (priv->data->len > 0) - priv->flush_requested = TRUE; - - needs_flush = meta_x11_selection_output_stream_needs_flush_unlocked (stream); - g_mutex_unlock (&priv->mutex); - - return needs_flush; -} - -static gboolean -meta_x11_selection_output_stream_flush (GOutputStream *output_stream, - GCancellable *cancellable, - GError **error) -{ - MetaX11SelectionOutputStream *stream = - META_X11_SELECTION_OUTPUT_STREAM (output_stream); - MetaX11SelectionOutputStreamPrivate *priv = - meta_x11_selection_output_stream_get_instance_private (stream); - - if (!meta_x11_selection_output_stream_check_pipe (stream, error)) - return FALSE; - if (!meta_x11_selection_output_request_flush (stream)) - return TRUE; - - g_main_context_invoke (NULL, meta_x11_selection_output_stream_invoke_flush, - stream); - - g_mutex_lock (&priv->mutex); - if (meta_x11_selection_output_stream_needs_flush_unlocked (stream)) - g_cond_wait (&priv->cond, &priv->mutex); - g_mutex_unlock (&priv->mutex); - - return TRUE; -} - -static void -meta_x11_selection_output_stream_flush_async (GOutputStream *output_stream, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - MetaX11SelectionOutputStream *stream = - META_X11_SELECTION_OUTPUT_STREAM (output_stream); - MetaX11SelectionOutputStreamPrivate *priv = - meta_x11_selection_output_stream_get_instance_private (stream); - GError *error = NULL; - GTask *task; - - task = g_task_new (stream, cancellable, callback, user_data); - g_task_set_source_tag (task, meta_x11_selection_output_stream_flush_async); - g_task_set_priority (task, io_priority); - - if (!meta_x11_selection_output_stream_check_pipe (stream, &error)) - { - g_task_return_error (task, error); - return; - } - - if (!meta_x11_selection_output_stream_can_flush (stream)) - { - if (meta_x11_selection_output_request_flush (stream)) - { - g_assert (priv->pending_task == NULL); - priv->pending_task = task; - return; - } - else - { - g_task_return_boolean (task, TRUE); - g_object_unref (task); - return; - } - } - - g_assert (priv->pending_task == NULL); - priv->pending_task = task; - meta_x11_selection_output_stream_perform_flush (stream); -} - -static gboolean -meta_x11_selection_output_stream_flush_finish (GOutputStream *stream, - GAsyncResult *result, - GError **error) -{ - g_return_val_if_fail (g_task_is_valid (result, stream), FALSE); - g_return_val_if_fail (g_async_result_is_tagged (result, meta_x11_selection_output_stream_flush_async), FALSE); - - return g_task_propagate_boolean (G_TASK (result), error); -} - -static gboolean -meta_x11_selection_output_stream_invoke_close (gpointer stream) -{ - MetaX11SelectionOutputStreamPrivate *priv = - meta_x11_selection_output_stream_get_instance_private (stream); - - priv->x11_display->selection.output_streams = - g_list_remove (priv->x11_display->selection.output_streams, stream); - - return G_SOURCE_REMOVE; -} - -static gboolean -meta_x11_selection_output_stream_close (GOutputStream *stream, - GCancellable *cancellable, - GError **error) -{ - g_main_context_invoke (NULL, meta_x11_selection_output_stream_invoke_close, stream); - - return TRUE; -} - -static void -meta_x11_selection_output_stream_close_async (GOutputStream *stream, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - - task = g_task_new (stream, cancellable, callback, user_data); - g_task_set_source_tag (task, meta_x11_selection_output_stream_close_async); - g_task_set_priority (task, io_priority); - - meta_x11_selection_output_stream_invoke_close (stream); - g_task_return_boolean (task, TRUE); - - g_object_unref (task); -} - -static gboolean -meta_x11_selection_output_stream_close_finish (GOutputStream *stream, - GAsyncResult *result, - GError **error) -{ - g_return_val_if_fail (g_task_is_valid (result, stream), FALSE); - g_return_val_if_fail (g_async_result_is_tagged (result, meta_x11_selection_output_stream_close_async), FALSE); - - return g_task_propagate_boolean (G_TASK (result), error); -} - -static void -meta_x11_selection_output_stream_dispose (GObject *object) -{ - MetaX11SelectionOutputStream *stream = - META_X11_SELECTION_OUTPUT_STREAM (object); - MetaX11SelectionOutputStreamPrivate *priv = - meta_x11_selection_output_stream_get_instance_private (stream); - - priv->x11_display->selection.output_streams = - g_list_remove (priv->x11_display->selection.output_streams, stream); - - G_OBJECT_CLASS (meta_x11_selection_output_stream_parent_class)->dispose (object); -} - -static void -meta_x11_selection_output_stream_finalize (GObject *object) -{ - MetaX11SelectionOutputStream *stream = - META_X11_SELECTION_OUTPUT_STREAM (object); - MetaX11SelectionOutputStreamPrivate *priv = - meta_x11_selection_output_stream_get_instance_private (stream); - - g_byte_array_unref (priv->data); - g_cond_clear (&priv->cond); - g_mutex_clear (&priv->mutex); - - G_OBJECT_CLASS (meta_x11_selection_output_stream_parent_class)->finalize (object); -} - -static void -meta_x11_selection_output_stream_class_init (MetaX11SelectionOutputStreamClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GOutputStreamClass *output_stream_class = G_OUTPUT_STREAM_CLASS (klass); - - object_class->dispose = meta_x11_selection_output_stream_dispose; - object_class->finalize = meta_x11_selection_output_stream_finalize; - - output_stream_class->write_fn = meta_x11_selection_output_stream_write; - output_stream_class->flush = meta_x11_selection_output_stream_flush; - output_stream_class->close_fn = meta_x11_selection_output_stream_close; - - output_stream_class->write_async = meta_x11_selection_output_stream_write_async; - output_stream_class->write_finish = meta_x11_selection_output_stream_write_finish; - output_stream_class->flush_async = meta_x11_selection_output_stream_flush_async; - output_stream_class->flush_finish = meta_x11_selection_output_stream_flush_finish; - output_stream_class->close_async = meta_x11_selection_output_stream_close_async; - output_stream_class->close_finish = meta_x11_selection_output_stream_close_finish; -} - -static void -meta_x11_selection_output_stream_init (MetaX11SelectionOutputStream *stream) -{ - MetaX11SelectionOutputStreamPrivate *priv = - meta_x11_selection_output_stream_get_instance_private (stream); - - g_mutex_init (&priv->mutex); - g_cond_init (&priv->cond); - priv->data = g_byte_array_new (); -} - -gboolean -meta_x11_selection_output_stream_xevent (MetaX11SelectionOutputStream *stream, - const XEvent *xevent) -{ - MetaX11SelectionOutputStreamPrivate *priv = - meta_x11_selection_output_stream_get_instance_private (stream); - Display *xdisplay = priv->x11_display->xdisplay; - - if (xevent->xany.display != xdisplay || - xevent->xany.window != priv->xwindow) - return FALSE; - - switch (xevent->type) - { - case PropertyNotify: - if (!priv->incr || - xevent->xproperty.atom != priv->xproperty || - xevent->xproperty.state != PropertyDelete) - return FALSE; - - priv->delete_pending = FALSE; - if (meta_x11_selection_output_stream_needs_flush (stream) && - meta_x11_selection_output_stream_can_flush (stream)) - meta_x11_selection_output_stream_perform_flush (stream); - return FALSE; - - default: - return FALSE; - } -} - -GOutputStream * -meta_x11_selection_output_stream_new (MetaX11Display *x11_display, - Window requestor, - const char *selection, - const char *target, - const char *property, - const char *type, - int format, - gulong timestamp) -{ - MetaX11SelectionOutputStream *stream; - MetaX11SelectionOutputStreamPrivate *priv; - - stream = g_object_new (META_TYPE_X11_SELECTION_OUTPUT_STREAM, NULL); - priv = meta_x11_selection_output_stream_get_instance_private (stream); - - x11_display->selection.output_streams = - g_list_prepend (x11_display->selection.output_streams, stream); - - priv->x11_display = x11_display; - priv->xwindow = requestor; - priv->xselection = XInternAtom (x11_display->xdisplay, selection, False); - priv->xtarget = XInternAtom (x11_display->xdisplay, target, False); - priv->xproperty = XInternAtom (x11_display->xdisplay, property, False); - priv->xtype = XInternAtom (x11_display->xdisplay, type, False); - priv->format = format; - priv->timestamp = timestamp; - - return G_OUTPUT_STREAM (stream); -} diff --git a/src/x11/meta-x11-selection-private.h b/src/x11/meta-x11-selection-private.h deleted file mode 100644 index b551ef602..000000000 --- a/src/x11/meta-x11-selection-private.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2018 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: Carlos Garnacho - */ - -#ifndef META_X11_SELECTION_H -#define META_X11_SELECTION_H - -#include "meta/meta-selection.h" -#include "x11/meta-x11-display-private.h" - -gboolean meta_x11_selection_handle_event (MetaX11Display *display, - XEvent *event); - -void meta_x11_selection_init (MetaX11Display *x11_display); -void meta_x11_selection_shutdown (MetaX11Display *x11_display); - -#endif /* META_X11_SELECTION_H */ diff --git a/src/x11/meta-x11-selection.c b/src/x11/meta-x11-selection.c deleted file mode 100644 index e389f22c7..000000000 --- a/src/x11/meta-x11-selection.c +++ /dev/null @@ -1,551 +0,0 @@ -/* - * Copyright (C) 2018 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: Carlos Garnacho - */ - -#include "config.h" - -#include - -#include "core/meta-selection-private.h" -#include "meta/meta-selection-source-memory.h" -#include "x11/meta-selection-source-x11-private.h" -#include "x11/meta-x11-selection-output-stream-private.h" -#include "x11/meta-x11-selection-private.h" - -#define UTF8_STRING_MIMETYPE "text/plain;charset=utf-8" -#define STRING_MIMETYPE "text/plain" - -static gboolean -atom_to_selection_type (Display *xdisplay, - Atom selection, - MetaSelectionType *selection_type) -{ - if (selection == XInternAtom (xdisplay, "PRIMARY", False)) - *selection_type = META_SELECTION_PRIMARY; - else if (selection == XInternAtom (xdisplay, "CLIPBOARD", False)) - *selection_type = META_SELECTION_CLIPBOARD; - else if (selection == XInternAtom (xdisplay, "XdndSelection", False)) - *selection_type = META_SELECTION_DND; - else - return FALSE; - - return TRUE; -} - -static Atom -selection_to_atom (MetaSelectionType type, - Display *xdisplay) -{ - Atom atom; - - switch (type) - { - case META_SELECTION_PRIMARY: - atom = XInternAtom (xdisplay, "PRIMARY", False); - break; - case META_SELECTION_CLIPBOARD: - atom = XInternAtom (xdisplay, "CLIPBOARD", False); - break; - case META_SELECTION_DND: - atom = XInternAtom (xdisplay, "XdndSelection", False); - break; - default: - g_warn_if_reached (); - atom = None; - break; - } - - return atom; -} - -static GBytes * -mimetypes_to_bytes (GList *mimetypes, - Display *xdisplay) -{ - GArray *atoms = g_array_new (FALSE, FALSE, sizeof (Atom)); - GList *l; - char *mimetype; - Atom atom; - gboolean utf8_string_found = FALSE, utf8_string_mimetype_found = FALSE; - gboolean string_found = FALSE, string_mimetype_found = FALSE; - GBytes *bytes; - - for (l = mimetypes; l; l = l->next) - { - mimetype = l->data; - atom = XInternAtom (xdisplay, mimetype, False); - g_array_append_val (atoms, atom); - utf8_string_mimetype_found |= strcmp (mimetype, UTF8_STRING_MIMETYPE) == 0; - utf8_string_found |= strcmp (mimetype, "UTF8_STRING") == 0; - string_mimetype_found |= strcmp (mimetype, STRING_MIMETYPE) == 0; - string_found |= strcmp (mimetype, "STRING") == 0; - } - - /* Some X11 clients can only handle STRING/UTF8_STRING but not the - * corresponding mimetypes. */ - if (utf8_string_mimetype_found && !utf8_string_found) - { - atom = XInternAtom (xdisplay, "UTF8_STRING", False); - g_array_append_val (atoms, atom); - } - - if (string_mimetype_found && !string_found) - { - atom = XInternAtom (xdisplay, "STRING", False); - g_array_append_val (atoms, atom); - } - - atom = XInternAtom (xdisplay, "TARGETS", False); - g_array_append_val (atoms, atom); - - atom = XInternAtom (xdisplay, "TIMESTAMP", False); - g_array_append_val (atoms, atom); - - bytes = g_bytes_new_take (atoms->data, atoms->len * sizeof (Atom)); - g_array_free (atoms, FALSE); - - return bytes; -} - -static void -send_selection_notify (XSelectionRequestEvent *request_event, - gboolean accepted) -{ - Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); - XSelectionEvent event; - - memset(&event, 0, sizeof (XSelectionEvent)); - event.type = SelectionNotify; - event.time = request_event->time; - event.requestor = request_event->requestor; - event.selection = request_event->selection; - event.target = request_event->target; - event.property = accepted ? request_event->property : None; - - XSendEvent (xdisplay, request_event->requestor, - False, NoEventMask, (XEvent *) &event); -} - -static void -write_mimetypes_cb (GOutputStream *stream, - GAsyncResult *res, - gpointer user_data) -{ - GError *error = NULL; - - g_output_stream_write_bytes_finish (stream, res, &error); - g_output_stream_close (stream, NULL, NULL); - g_object_unref (stream); - - if (error) - { - g_warning ("Could not fetch selection mimetypes: %s", error->message); - g_error_free (error); - } -} - -static void -transfer_cb (MetaSelection *selection, - GAsyncResult *res, - GOutputStream *output) -{ - GError *error = NULL; - - if (!meta_selection_transfer_finish (selection, res, &error)) - { - g_warning ("Error writing data to X11 selection: %s", error->message); - g_error_free (error); - } - - g_output_stream_close (output, NULL, NULL); - g_object_unref (output); -} - -static char * -meta_x11_selection_find_target (MetaX11Display *x11_display, - MetaSelection *selection, - MetaSelectionType selection_type, - Atom selection_atom) -{ - GList* mimetypes = NULL; - const gchar *atom_name; - char *retval; - - mimetypes = meta_selection_get_mimetypes (selection, selection_type); - atom_name = gdk_x11_get_xatom_name (selection_atom); - - if (g_list_find_custom (mimetypes, atom_name, (GCompareFunc) g_strcmp0)) - { - retval = g_strdup (atom_name); - } - else if (strcmp (atom_name, "UTF8_STRING") == 0 && - g_list_find_custom (mimetypes, UTF8_STRING_MIMETYPE, - (GCompareFunc) g_strcmp0)) - { - retval = g_strdup (UTF8_STRING_MIMETYPE); - } - else if (strcmp (atom_name, "STRING") == 0 && - g_list_find_custom (mimetypes, STRING_MIMETYPE, - (GCompareFunc) g_strcmp0)) - { - retval = g_strdup (STRING_MIMETYPE); - } - else - { - retval = NULL; - } - - g_list_free_full (mimetypes, g_free); - - return retval; -} - -static gboolean -meta_x11_selection_handle_selection_request (MetaX11Display *x11_display, - XEvent *xevent) -{ - XSelectionRequestEvent *event = (XSelectionRequestEvent *) xevent; - MetaSelectionType selection_type; - MetaSelection *selection; - GOutputStream *output; - GList *mimetypes; - - if (!atom_to_selection_type (x11_display->xdisplay, event->selection, &selection_type)) - return FALSE; - if (x11_display->selection.xwindow != event->owner) - return FALSE; - - selection = meta_display_get_selection (meta_get_display ()); - - if (event->target == gdk_x11_get_xatom_by_name ("TARGETS")) - { - GBytes *bytes; - - mimetypes = meta_selection_get_mimetypes (selection, selection_type); - - if (!mimetypes) - { - send_selection_notify (event, FALSE); - return FALSE; - } - - output = meta_x11_selection_output_stream_new (x11_display, event->requestor, - gdk_x11_get_xatom_name (event->selection), - gdk_x11_get_xatom_name (event->target), - gdk_x11_get_xatom_name (event->property), - "ATOM", 32, event->time); - - bytes = mimetypes_to_bytes (mimetypes, x11_display->xdisplay); - g_list_free_full (mimetypes, g_free); - - g_output_stream_write_bytes_async (output, - bytes, - G_PRIORITY_DEFAULT, - NULL, - (GAsyncReadyCallback) write_mimetypes_cb, - output); - g_bytes_unref (bytes); - return TRUE; - } - else if (event->target == gdk_x11_get_xatom_by_name ("DELETE")) - { - /* DnD only, this is just handled through other means on our non-x11 - * sources, so just go with it. - */ - send_selection_notify (event, TRUE); - } - else - { - g_autofree char *target = NULL; - - target = meta_x11_selection_find_target (x11_display, selection, - selection_type, event->target); - - if (target != NULL) - { - output = meta_x11_selection_output_stream_new (x11_display, - event->requestor, - gdk_x11_get_xatom_name (event->selection), - gdk_x11_get_xatom_name (event->target), - gdk_x11_get_xatom_name (event->property), - gdk_x11_get_xatom_name (event->target), - 8, event->time); - - meta_selection_transfer_async (selection, - selection_type, - target, - -1, - output, - NULL, - (GAsyncReadyCallback) transfer_cb, - output); - return TRUE; - } - else - { - send_selection_notify (event, FALSE); - } - } - - return FALSE; -} - -typedef struct -{ - MetaX11Display *x11_display; - MetaSelection *selection; - MetaSelectionType selection_type; -} SourceNewData; - -static void -source_new_cb (GObject *object, - GAsyncResult *res, - gpointer user_data) -{ - MetaSelectionSource *source; - SourceNewData *data = user_data; - MetaSelection *selection = data->selection; - MetaSelectionType selection_type = data->selection_type; - MetaX11Display *x11_display = data->x11_display; - g_autoptr (GError) error = NULL; - - source = meta_selection_source_x11_new_finish (res, &error); - if (source) - { - g_set_object (&x11_display->selection.owners[selection_type], source); - meta_selection_set_owner (selection, selection_type, source); - g_object_unref (source); - } - else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - { - g_warning ("Could not create selection source for X11: %s", - error->message); - } - - g_free (data); -} - -static gboolean -unset_clipboard_owner (gpointer data) -{ - MetaDisplay *display = meta_get_display (); - MetaSelection *selection = meta_display_get_selection (display); - MetaX11Display *x11_display = meta_display_get_x11_display (display); - - meta_selection_unset_owner (selection, META_SELECTION_CLIPBOARD, - x11_display->selection.owners[META_SELECTION_CLIPBOARD]); - g_clear_object (&x11_display->selection.owners[META_SELECTION_CLIPBOARD]); - - x11_display->selection.timeout_id = 0; - - return G_SOURCE_REMOVE; -} - -static gboolean -meta_x11_selection_handle_xfixes_selection_notify (MetaX11Display *x11_display, - XEvent *xevent) -{ - XFixesSelectionNotifyEvent *event = (XFixesSelectionNotifyEvent *) xevent; - Display *xdisplay = x11_display->xdisplay; - MetaSelectionType selection_type; - MetaSelection *selection; - - if (!atom_to_selection_type (xdisplay, event->selection, &selection_type)) - return FALSE; - - selection = meta_display_get_selection (meta_get_display ()); - - if (selection_type == META_SELECTION_CLIPBOARD) - g_clear_handle_id (&x11_display->selection.timeout_id, g_source_remove); - - if (x11_display->selection.cancellables[selection_type]) - { - g_cancellable_cancel (x11_display->selection.cancellables[selection_type]); - g_clear_object (&x11_display->selection.cancellables[selection_type]); - } - - x11_display->selection.cancellables[selection_type] = g_cancellable_new (); - - if (event->owner == None && x11_display->selection.owners[selection_type]) - { - if (event->subtype == XFixesSetSelectionOwnerNotify) - { - MetaSelectionSource *source; - - /* Replace with an empty owner */ - source = g_object_new (META_TYPE_SELECTION_SOURCE_MEMORY, NULL); - g_set_object (&x11_display->selection.owners[selection_type], source); - meta_selection_set_owner (selection, selection_type, source); - g_object_unref (source); - } - else if (event->subtype == XFixesSelectionWindowDestroyNotify && - selection_type == META_SELECTION_CLIPBOARD) - { - /* Selection window might have gotten destroyed as part of application - * shutdown. Trigger restoring clipboard, but wait a bit, because some - * clients, like wine, destroy the old window immediately before a new - * selection. Restoring the clipboard in this case would overwrite the - * new selection, so this will be cancelled when a new selection - * arrives. */ - x11_display->selection.timeout_id = g_timeout_add (10, - unset_clipboard_owner, - NULL); - } - else - { - /* An X client went away, clear the selection */ - meta_selection_unset_owner (selection, selection_type, - x11_display->selection.owners[selection_type]); - g_clear_object (&x11_display->selection.owners[selection_type]); - } - } - else if (event->owner != None && event->owner != x11_display->selection.xwindow) - { - SourceNewData *data; - - data = g_new (SourceNewData, 1); - data->x11_display = x11_display; - data->selection = selection; - data->selection_type = selection_type; - - meta_selection_source_x11_new_async (x11_display, - event->owner, - event->timestamp, - event->selection, - x11_display->selection.cancellables[selection_type], - source_new_cb, - data); - } - - return TRUE; -} - -gboolean -meta_x11_selection_handle_event (MetaX11Display *x11_display, - XEvent *xevent) -{ - if (xevent->type == SelectionRequest) - return meta_x11_selection_handle_selection_request (x11_display, xevent); - else if (xevent->type - x11_display->xfixes_event_base == XFixesSelectionNotify) - return meta_x11_selection_handle_xfixes_selection_notify (x11_display, xevent); - - return FALSE; -} - -static void -notify_selection_owner (MetaX11Display *x11_display, - MetaSelectionType selection_type, - MetaSelectionSource *new_owner) -{ - Display *xdisplay = x11_display->xdisplay; - - if (new_owner && new_owner != x11_display->selection.owners[selection_type]) - { - if (x11_display->selection.cancellables[selection_type]) - { - g_cancellable_cancel (x11_display->selection.cancellables[selection_type]); - g_clear_object (&x11_display->selection.cancellables[selection_type]); - } - - /* If the owner is non-X11, claim the selection on our selection - * window, so X11 apps can interface with it. - */ - XSetSelectionOwner (xdisplay, - selection_to_atom (selection_type, xdisplay), - x11_display->selection.xwindow, - META_CURRENT_TIME); - } -} - -void -meta_x11_selection_init (MetaX11Display *x11_display) -{ - XSetWindowAttributes attributes = { 0 }; - MetaDisplay *display = meta_get_display (); - MetaSelection *selection; - guint mask, i; - - attributes.event_mask = PropertyChangeMask | SubstructureNotifyMask; - attributes.override_redirect = True; - - x11_display->selection.timeout_id = 0; - x11_display->selection.xwindow = - XCreateWindow (x11_display->xdisplay, - x11_display->xroot, - -1, -1, 1, 1, - 0, /* border width */ - 0, /* depth */ - InputOnly, /* class */ - CopyFromParent, /* visual */ - CWEventMask | CWOverrideRedirect, - &attributes); - - mask = XFixesSetSelectionOwnerNotifyMask | - XFixesSelectionWindowDestroyNotifyMask | - XFixesSelectionClientCloseNotifyMask; - - selection = meta_display_get_selection (display); - - for (i = 0; i < META_N_SELECTION_TYPES; i++) - { - MetaSelectionSource *owner; - - XFixesSelectSelectionInput (x11_display->xdisplay, - x11_display->selection.xwindow, - selection_to_atom (i, x11_display->xdisplay), - mask); - owner = meta_selection_get_current_owner (selection, i); - notify_selection_owner (x11_display, i, owner); - } - - g_signal_connect_swapped (selection, - "owner-changed", - G_CALLBACK (notify_selection_owner), - x11_display); -} - -void -meta_x11_selection_shutdown (MetaX11Display *x11_display) -{ - MetaDisplay *display = meta_get_display (); - guint i; - - g_signal_handlers_disconnect_by_func (meta_display_get_selection (display), - notify_selection_owner, - x11_display); - - for (i = 0; i < META_N_SELECTION_TYPES; i++) - { - g_clear_object (&x11_display->selection.owners[i]); - if (x11_display->selection.cancellables[i]) - { - g_cancellable_cancel (x11_display->selection.cancellables[i]); - g_clear_object (&x11_display->selection.cancellables[i]); - } - } - - if (x11_display->selection.xwindow != None) - { - XDestroyWindow (x11_display->xdisplay, x11_display->selection.xwindow); - x11_display->selection.xwindow = None; - } - - g_clear_handle_id (&x11_display->selection.timeout_id, g_source_remove); -} diff --git a/src/x11/meta-x11-stack-private.h b/src/x11/meta-x11-stack-private.h deleted file mode 100644 index a00b8e743..000000000 --- a/src/x11/meta-x11-stack-private.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * Copyright (C) 2019 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 . - */ - -#ifndef META_X11_STACK_H -#define META_X11_STACK_H - -#include - -#include "meta/types.h" - -#define META_TYPE_X11_STACK (meta_x11_stack_get_type ()) -G_DECLARE_FINAL_TYPE (MetaX11Stack, meta_x11_stack, META, X11_STACK, GObject) - -typedef struct _MetaX11Stack MetaX11Stack; - -MetaX11Stack * meta_x11_stack_new (MetaX11Display *x11_display); - -#endif /* META_X11_STACK_H */ diff --git a/src/x11/meta-x11-stack.c b/src/x11/meta-x11-stack.c deleted file mode 100644 index d41fef78e..000000000 --- a/src/x11/meta-x11-stack.c +++ /dev/null @@ -1,355 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -/* - * Copyright (C) 2019 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 . - */ - -#include "config.h" - -#include - -#include "core/frame.h" -#include "core/stack.h" -#include "core/window-private.h" -#include "x11/meta-x11-display-private.h" -#include "x11/meta-x11-stack-private.h" - -struct _MetaX11Stack -{ - GObject parent; - MetaX11Display *x11_display; - - /* - * A sequence of all the Windows (X handles, not MetaWindows) of the windows - * we manage, sorted in order. Suitable to be passed into _NET_CLIENT_LIST. - */ - GArray *xwindows; - - /* - * MetaWindows waiting to be added to the xwindows list, after - * being added to the MetaStack. - * - * The order of the elements in this list is not important; what is important - * is the stack_position element of each window. - */ - GList *added; - - /* - * Windows (X handles, not MetaWindows) waiting to be removed from the - * xwindows list, after being removed from the MetaStack. - * - * The order of the elements in this list is not important. - */ - GList *removed; -}; - -enum -{ - PROP_DISPLAY = 1, - N_PROPS -}; - -static GParamSpec *pspecs[N_PROPS] = { 0 }; - -G_DEFINE_TYPE (MetaX11Stack, meta_x11_stack, G_TYPE_OBJECT) - -static void -meta_x11_stack_init (MetaX11Stack *x11_stack) -{ - x11_stack->xwindows = g_array_new (FALSE, FALSE, sizeof (Window)); -} - -static void -meta_x11_stack_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - MetaX11Stack *x11_stack = META_X11_STACK (object); - - switch (prop_id) - { - case PROP_DISPLAY: - x11_stack->x11_display = g_value_get_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -meta_x11_stack_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - MetaX11Stack *x11_stack = META_X11_STACK (object); - - switch (prop_id) - { - case PROP_DISPLAY: - g_value_set_object (value, x11_stack->x11_display); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -stack_window_added_cb (MetaStack *stack, - MetaWindow *window, - MetaX11Stack *x11_stack) -{ - if (window->client_type != META_WINDOW_CLIENT_TYPE_X11) - return; - - x11_stack->added = g_list_prepend (x11_stack->added, window); -} - -static void -stack_window_removed_cb (MetaStack *stack, - MetaWindow *window, - MetaX11Stack *x11_stack) -{ - if (window->client_type != META_WINDOW_CLIENT_TYPE_X11) - return; - - x11_stack->added = g_list_remove (x11_stack->added, window); - - x11_stack->removed = g_list_prepend (x11_stack->removed, - GUINT_TO_POINTER (window->xwindow)); - if (window->frame) - { - x11_stack->removed = g_list_prepend (x11_stack->removed, - GUINT_TO_POINTER (window->frame->xwindow)); - } -} - -/** - * stack_do_window_deletions: - * - * Go through "deleted" and take the matching windows - * out of "windows". - */ -static void -x11_stack_do_window_deletions (MetaX11Stack *x11_stack) -{ - GList *tmp; - int i; - - tmp = x11_stack->removed; - while (tmp != NULL) - { - Window xwindow; - xwindow = GPOINTER_TO_UINT (tmp->data); - - /* We go from the end figuring removals are more - * likely to be recent. - */ - i = x11_stack->xwindows->len; - while (i > 0) - { - --i; - - /* there's no guarantee we'll actually find windows to - * remove, e.g. the same xwindow could have been - * added/removed before we ever synced, and we put - * both the window->xwindow and window->frame->xwindow - * in the removal list. - */ - if (xwindow == g_array_index (x11_stack->xwindows, Window, i)) - { - g_array_remove_index (x11_stack->xwindows, i); - goto next; - } - } - - next: - tmp = tmp->next; - } - - g_clear_pointer (&x11_stack->removed, g_list_free); -} - -static void -x11_stack_do_window_additions (MetaX11Stack *x11_stack) -{ - GList *tmp; - gint n_added; - - n_added = g_list_length (x11_stack->added); - if (n_added > 0) - { - meta_topic (META_DEBUG_STACK, - "Adding %d windows to sorted list", - n_added); - - /* stack->added has the most recent additions at the - * front of the list, so we need to reverse it - */ - x11_stack->added = g_list_reverse (x11_stack->added); - - tmp = x11_stack->added; - while (tmp != NULL) - { - MetaWindow *w; - - w = tmp->data; - g_array_append_val (x11_stack->xwindows, w->xwindow); - tmp = tmp->next; - } - } - - g_clear_pointer (&x11_stack->added, g_list_free); -} - -/** - * x11_stack_sync_to_server: - * - * Order the windows on the X server to be the same as in our structure. - * We do this using XRestackWindows if we don't know the previous order, - * or XConfigureWindow on a few particular windows if we do and can figure - * out the minimum set of changes. After that, we set __NET_CLIENT_LIST - * and __NET_CLIENT_LIST_STACKING. - * - * FIXME: Now that we have a good view of the stacking order on the server - * with MetaStackTracker it should be possible to do a simpler and better - * job of computing the minimal set of stacking requests needed. - */ -static void -x11_stack_sync_to_xserver (MetaX11Stack *x11_stack) -{ - MetaX11Display *x11_display = x11_stack->x11_display; - MetaStack *stack = x11_display->display->stack; - GArray *x11_stacked; - GList *tmp; - GList *sorted; - - meta_topic (META_DEBUG_STACK, "Syncing window stack to server"); - - /* Create stacked xwindow arrays, in bottom-to-top order - */ - x11_stacked = g_array_new (FALSE, FALSE, sizeof (Window)); - - sorted = meta_stack_list_windows (stack, NULL); - - for (tmp = sorted; tmp; tmp = tmp->next) - { - MetaWindow *w = tmp->data; - - if (w->client_type == META_WINDOW_CLIENT_TYPE_X11) - g_array_append_val (x11_stacked, w->xwindow); - } - - /* Sync _NET_CLIENT_LIST and _NET_CLIENT_LIST_STACKING */ - - XChangeProperty (x11_stack->x11_display->xdisplay, - x11_stack->x11_display->xroot, - x11_stack->x11_display->atom__NET_CLIENT_LIST, - XA_WINDOW, - 32, PropModeReplace, - (unsigned char *) x11_stack->xwindows->data, - x11_stack->xwindows->len); - XChangeProperty (x11_stack->x11_display->xdisplay, - x11_stack->x11_display->xroot, - x11_stack->x11_display->atom__NET_CLIENT_LIST_STACKING, - XA_WINDOW, - 32, PropModeReplace, - (unsigned char *) x11_stacked->data, - x11_stacked->len); - - g_array_free (x11_stacked, TRUE); - g_list_free (sorted); -} - -static void -stack_changed_cb (MetaX11Stack *x11_stack) -{ - /* Do removals before adds, with paranoid idea that we might re-add - * the same window IDs. - */ - x11_stack_do_window_deletions (x11_stack); - x11_stack_do_window_additions (x11_stack); - x11_stack_sync_to_xserver (x11_stack); -} - -static void -meta_x11_stack_constructed (GObject *object) -{ - MetaX11Stack *x11_stack = META_X11_STACK (object); - MetaX11Display *x11_display = x11_stack->x11_display; - - G_OBJECT_CLASS (meta_x11_stack_parent_class)->constructed (object); - - g_signal_connect (x11_display->display->stack, - "window-added", - G_CALLBACK (stack_window_added_cb), - x11_stack); - g_signal_connect (x11_display->display->stack, - "window-removed", - G_CALLBACK (stack_window_removed_cb), - x11_stack); - g_signal_connect_swapped (x11_display->display->stack, - "changed", - G_CALLBACK (stack_changed_cb), - x11_stack); -} - -static void -meta_x11_stack_finalize (GObject *object) -{ - MetaX11Stack *x11_stack = META_X11_STACK (object); - MetaX11Display *x11_display = x11_stack->x11_display; - - if (x11_display->display && x11_display->display->stack) - { - g_signal_handlers_disconnect_by_data (x11_display->display->stack, - x11_stack); - } - - g_array_free (x11_stack->xwindows, TRUE); - g_list_free (x11_stack->added); - g_list_free (x11_stack->removed); - - G_OBJECT_CLASS (meta_x11_stack_parent_class)->finalize (object); -} - -static void -meta_x11_stack_class_init (MetaX11StackClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->set_property = meta_x11_stack_set_property; - object_class->get_property = meta_x11_stack_get_property; - object_class->constructed = meta_x11_stack_constructed; - object_class->finalize = meta_x11_stack_finalize; - - pspecs[PROP_DISPLAY] = - g_param_spec_object ("display", - "Display", - "Display", - META_TYPE_X11_DISPLAY, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - - g_object_class_install_properties (object_class, N_PROPS, pspecs); -} - -MetaX11Stack * -meta_x11_stack_new (MetaX11Display *x11_display) -{ - return g_object_new (META_TYPE_X11_STACK, - "display", x11_display, - NULL); -} diff --git a/src/x11/meta-x11-window-control.c b/src/x11/meta-x11-window-control.c deleted file mode 100644 index 3af43ce0c..000000000 --- a/src/x11/meta-x11-window-control.c +++ /dev/null @@ -1,265 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter interface used by GTK+ UI to talk to core */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * 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 . - */ - -#include "config.h" - -#include "x11/meta-x11-window-control.h" - -#include "core/frame.h" -#include "core/meta-workspace-manager-private.h" -#include "core/util-private.h" -#include "core/workspace-private.h" -#include "meta/meta-x11-errors.h" -#include "meta/prefs.h" -#include "x11/meta-x11-display-private.h" -#include "x11/window-x11-private.h" -#include "x11/window-x11.h" - -static MetaWindow * -window_from_frame (MetaX11Display *x11_display, - Window frame_xwindow) -{ - MetaWindow *window; - - window = meta_x11_display_lookup_x_window (x11_display, frame_xwindow); - if (!window || !window->frame) - { - meta_bug ("No such frame window 0x%lx!", frame_xwindow); - return NULL; - } - - return window; -} - -void -meta_x11_wm_queue_frame_resize (MetaX11Display *x11_display, - Window frame_xwindow) -{ - MetaWindow *window = window_from_frame (x11_display, frame_xwindow); - - meta_window_queue (window, META_QUEUE_MOVE_RESIZE); - meta_window_frame_size_changed (window); -} - -static gboolean -lower_window_and_transients (MetaWindow *window, - gpointer data) -{ - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - - meta_window_lower (window); - - meta_window_foreach_transient (window, lower_window_and_transients, NULL); - - if (meta_prefs_get_raise_on_click ()) - { - /* Move window to the back of the focusing workspace's MRU list. - * Do extra sanity checks to avoid possible race conditions. - * (Borrowed from window.c.) - */ - if (workspace_manager->active_workspace && - meta_window_located_on_workspace (window, - workspace_manager->active_workspace)) - { - GList* link; - link = g_list_find (workspace_manager->active_workspace->mru_list, - window); - g_assert (link); - - workspace_manager->active_workspace->mru_list = - g_list_remove_link (workspace_manager->active_workspace->mru_list, - link); - g_list_free (link); - - workspace_manager->active_workspace->mru_list = - g_list_append (workspace_manager->active_workspace->mru_list, - window); - } - } - - return FALSE; -} - -void -meta_x11_wm_user_lower_and_unfocus (MetaX11Display *x11_display, - Window frame_xwindow, - uint32_t timestamp) -{ - MetaWindow *window = window_from_frame (x11_display, frame_xwindow); - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - - lower_window_and_transients (window, NULL); - - /* Rather than try to figure that out whether we just lowered - * the focus window, assume that's always the case. (Typically, - * this will be invoked via keyboard action or by a mouse action; - * in either case the window or a modal child will have been focused.) */ - meta_workspace_focus_default_window (workspace_manager->active_workspace, - NULL, - timestamp); -} - -void -meta_x11_wm_toggle_maximize_vertically (MetaX11Display *x11_display, - Window frame_xwindow) -{ - MetaWindow *window = window_from_frame (x11_display, frame_xwindow); - - if (meta_prefs_get_raise_on_click ()) - meta_window_raise (window); - - if (META_WINDOW_MAXIMIZED_VERTICALLY (window)) - meta_window_unmaximize (window, META_MAXIMIZE_VERTICAL); - else - meta_window_maximize (window, META_MAXIMIZE_VERTICAL); -} - -void -meta_x11_wm_toggle_maximize_horizontally (MetaX11Display *x11_display, - Window frame_xwindow) -{ - MetaWindow *window = window_from_frame (x11_display, frame_xwindow); - - if (meta_prefs_get_raise_on_click ()) - meta_window_raise (window); - - if (META_WINDOW_MAXIMIZED_HORIZONTALLY (window)) - meta_window_unmaximize (window, META_MAXIMIZE_HORIZONTAL); - else - meta_window_maximize (window, META_MAXIMIZE_HORIZONTAL); -} - -void -meta_x11_wm_toggle_maximize (MetaX11Display *x11_display, - Window frame_xwindow) -{ - MetaWindow *window = window_from_frame (x11_display, frame_xwindow); - - if (meta_prefs_get_raise_on_click ()) - meta_window_raise (window); - - if (META_WINDOW_MAXIMIZED (window)) - meta_window_unmaximize (window, META_MAXIMIZE_BOTH); - else - meta_window_maximize (window, META_MAXIMIZE_BOTH); -} - -void -meta_x11_wm_show_window_menu (MetaX11Display *x11_display, - Window frame_xwindow, - MetaWindowMenuType menu, - int root_x, - int root_y, - uint32_t timestamp) -{ - MetaWindow *window = window_from_frame (x11_display, frame_xwindow); - - if (meta_prefs_get_raise_on_click ()) - meta_window_raise (window); - meta_window_focus (window, timestamp); - - meta_window_show_menu (window, menu, root_x, root_y); -} - -void -meta_x11_wm_show_window_menu_for_rect (MetaX11Display *x11_display, - Window frame_xwindow, - MetaWindowMenuType menu, - MetaRectangle *rect, - uint32_t timestamp) -{ - MetaWindow *window = window_from_frame (x11_display, frame_xwindow); - - if (meta_prefs_get_raise_on_click ()) - meta_window_raise (window); - meta_window_focus (window, timestamp); - - meta_window_show_menu_for_rect (window, menu, rect); -} - -gboolean -meta_x11_wm_begin_grab_op (MetaX11Display *x11_display, - Window frame_xwindow, - MetaGrabOp op, - gboolean pointer_already_grabbed, - gboolean frame_action, - int button, - gulong modmask, - uint32_t timestamp, - int root_x, - int root_y) -{ - MetaWindow *window = window_from_frame (x11_display, frame_xwindow); - MetaDisplay *display; - - display = meta_x11_display_get_display (x11_display); - - return meta_display_begin_grab_op (display, window, - op, pointer_already_grabbed, - frame_action, - button, modmask, - timestamp, root_x, root_y); -} - -void -meta_x11_wm_end_grab_op (MetaX11Display *x11_display, - uint32_t timestamp) -{ - MetaDisplay *display; - - display = meta_x11_display_get_display (x11_display); - - meta_display_end_grab_op (display, timestamp); -} - -MetaGrabOp -meta_x11_wm_get_grab_op (MetaX11Display *x11_display) -{ - MetaDisplay *display; - - display = meta_x11_display_get_display (x11_display); - - return display->grab_op; -} - -void -meta_x11_wm_grab_buttons (MetaX11Display *x11_display, - Window frame_xwindow) -{ - MetaDisplay *display; - - display = meta_x11_display_get_display (x11_display); - - meta_verbose ("Grabbing buttons on frame 0x%lx", frame_xwindow); - meta_display_grab_window_buttons (display, frame_xwindow); -} - -void -meta_x11_wm_set_screen_cursor (MetaX11Display *x11_display, - Window frame_on_screen, - MetaCursor cursor) -{ - MetaWindow *window = window_from_frame (x11_display, frame_on_screen); - - meta_frame_set_screen_cursor (window->frame, cursor); -} diff --git a/src/x11/meta-x11-window-control.h b/src/x11/meta-x11-window-control.h deleted file mode 100644 index dfb66f262..000000000 --- a/src/x11/meta-x11-window-control.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter interface used by GTK+ UI to talk to core */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2005 Elijah Newren - * - * 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 . - */ - -#ifndef META_X11_WINDOW__CONTROL_H -#define META_X11_WINDOW__CONTROL_H - -#include - -#include "meta/boxes.h" -#include "meta/common.h" -#include "x11/meta-x11-display-private.h" - -void meta_x11_wm_queue_frame_resize (MetaX11Display *x11_display, - Window frame_xwindow); - -void meta_x11_wm_user_lower_and_unfocus (MetaX11Display *x11_display, - Window frame_xwindow, - uint32_t timestamp); - -void meta_x11_wm_toggle_maximize (MetaX11Display *x11_display, - Window frame_xwindow); -void meta_x11_wm_toggle_maximize_horizontally (MetaX11Display *xdisplay, - Window frame_xwindow); -void meta_x11_wm_toggle_maximize_vertically (MetaX11Display *x11_display, - Window frame_xwindow); - -void meta_x11_wm_show_window_menu (MetaX11Display *x11_xdisplay, - Window frame_xwindow, - MetaWindowMenuType menu, - int root_x, - int root_y, - uint32_t timestamp); - -void meta_x11_wm_show_window_menu_for_rect (MetaX11Display *x11_display, - Window frame_xwindow, - MetaWindowMenuType menu, - MetaRectangle *rect, - uint32_t timestamp); - -gboolean meta_x11_wm_begin_grab_op (MetaX11Display *x11_display, - Window frame_xwindow, - MetaGrabOp op, - gboolean pointer_already_grabbed, - gboolean frame_action, - int button, - gulong modmask, - uint32_t timestamp, - int root_x, - int root_y); -void meta_x11_wm_end_grab_op (MetaX11Display *x11_display, - uint32_t timestamp); -MetaGrabOp meta_x11_wm_get_grab_op (MetaX11Display *x11_display); - - -void meta_x11_wm_grab_buttons (MetaX11Display *x11_display, - Window frame_xwindow); - -void meta_x11_wm_set_screen_cursor (MetaX11Display *x11_display, - Window frame_on_screen, - MetaCursor cursor); - -#endif /* META_X11_WINDOW_CONTROL_H */ diff --git a/src/x11/mutter-Xatomtype.h b/src/x11/mutter-Xatomtype.h deleted file mode 100644 index ed3e1f781..000000000 --- a/src/x11/mutter-Xatomtype.h +++ /dev/null @@ -1,136 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/** - * \file mutter-Xatomtype.h Types for communicating with X about properties - * - * This files defines crock C structures for calling XGetWindowProperty and - * XChangeProperty. All fields must be longs as the semantics of property - * routines will handle conversion to and from actual 32 bit objects. If your - * compiler doesn't treat &structoflongs the same as &arrayoflongs[0], you - * will have some work to do. - */ - -/*********************************************************** - -Copyright 1987, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -******************************************************************/ - -#ifndef _XATOMTYPE_H_ -#define _XATOMTYPE_H_ - -#define BOOL int32_t -#define SIGNEDINT int32_t -#define UNSIGNEDINT uint32_t -#define RESOURCEID uint32_t - - -/* this structure may be extended, but do not change the order */ -typedef struct { - UNSIGNEDINT flags; - SIGNEDINT x, y, width, height; /* need to cvt; only for pre-ICCCM */ - SIGNEDINT minWidth, minHeight; /* need to cvt */ - SIGNEDINT maxWidth, maxHeight; /* need to cvt */ - SIGNEDINT widthInc, heightInc; /* need to cvt */ - SIGNEDINT minAspectX, minAspectY; /* need to cvt */ - SIGNEDINT maxAspectX, maxAspectY; /* need to cvt */ - SIGNEDINT baseWidth,baseHeight; /* need to cvt; ICCCM version 1 */ - SIGNEDINT winGravity; /* need to cvt; ICCCM version 1 */ -} xPropSizeHints; -#define OldNumPropSizeElements 15 /* pre-ICCCM */ -#define NumPropSizeElements 18 /* ICCCM version 1 */ - -/* this structure may be extended, but do not change the order */ -/* RGB properties */ -typedef struct { - RESOURCEID colormap; - UNSIGNEDINT red_max; - UNSIGNEDINT red_mult; - UNSIGNEDINT green_max; - UNSIGNEDINT green_mult; - UNSIGNEDINT blue_max; - UNSIGNEDINT blue_mult; - UNSIGNEDINT base_pixel; - RESOURCEID visualid; /* ICCCM version 1 */ - RESOURCEID killid; /* ICCCM version 1 */ -} xPropStandardColormap; -#define OldNumPropStandardColormapElements 8 /* pre-ICCCM */ -#define NumPropStandardColormapElements 10 /* ICCCM version 1 */ - - -/* this structure may be extended, but do not change the order */ -typedef struct { - UNSIGNEDINT flags; - BOOL input; /* need to convert */ - SIGNEDINT initialState; /* need to cvt */ - RESOURCEID iconPixmap; - RESOURCEID iconWindow; - SIGNEDINT iconX; /* need to cvt */ - SIGNEDINT iconY; /* need to cvt */ - RESOURCEID iconMask; - UNSIGNEDINT windowGroup; - } xPropWMHints; -#define NumPropWMHintsElements 9 /* number of elements in this structure */ - -/* this structure defines the icon size hints information */ -typedef struct { - SIGNEDINT minWidth, minHeight; /* need to cvt */ - SIGNEDINT maxWidth, maxHeight; /* need to cvt */ - SIGNEDINT widthInc, heightInc; /* need to cvt */ - } xPropIconSize; -#define NumPropIconSizeElements 6 /* number of elements in this structure */ - -/* this structure defines the window manager state information */ -typedef struct { - SIGNEDINT state; /* need to cvt */ - RESOURCEID iconWindow; -} xPropWMState; -#define NumPropWMStateElements 2 /* number of elements in struct */ - -#undef BOOL -#undef SIGNEDINT -#undef UNSIGNEDINT -#undef RESOURCEID - -#endif /* _XATOMTYPE_H_ */ diff --git a/src/x11/session.c b/src/x11/session.c deleted file mode 100644 index 339a7ae33..000000000 --- a/src/x11/session.c +++ /dev/null @@ -1,1860 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter Session Management */ - -/* - * Copyright (C) 2001 Havoc Pennington (some code in here from - * libgnomeui, (C) Tom Tromey, Carsten Schaar) - * Copyright (C) 2004, 2005 Elijah Newren - * - * 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 . - */ - -#include "config.h" - -#include "x11/session.h" - -#include -#include -#include - -#include "core/util-private.h" -#include "meta/meta-context.h" -#include "x11/meta-x11-display-private.h" - -#ifndef HAVE_SM -void -meta_session_init (MetaContext *context, - const char *client_id, - const char *save_file) -{ - meta_topic (META_DEBUG_SM, "Compiled without session management support"); -} - -const MetaWindowSessionInfo* -meta_window_lookup_saved_state (MetaWindow *window) -{ - return NULL; -} - -void -meta_window_release_saved_state (const MetaWindowSessionInfo *info) -{ - ; -} -#else /* HAVE_SM */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "core/display-private.h" -#include "meta/main.h" -#include "meta/util.h" -#include "meta/workspace.h" - -typedef struct _MetaIceConnection -{ - IceConn ice_connection; - MetaContext *context; -} MetaIceConnection; - -static void ice_io_error_handler (IceConn connection); - -static void new_ice_connection (IceConn connection, IcePointer client_data, - Bool opening, IcePointer *watch_data); - -static void save_state (void); -static char* load_state (const char *previous_save_file); -static void regenerate_save_file (void); -static const char* full_save_file (void); -static void warn_about_lame_clients_and_finish_interact (gboolean shutdown); -static void disconnect (void); - -/* This is called when data is available on an ICE connection. */ -static gboolean -process_ice_messages (GIOChannel *channel, - GIOCondition condition, - gpointer user_data) -{ - MetaIceConnection *ice_connection = user_data; - IceConn connection = ice_connection->ice_connection; - IceProcessMessagesStatus status; - - /* This blocks infinitely sometimes. I don't know what - * to do about it. Checking "condition" just breaks - * session management. - */ - status = IceProcessMessages (connection, NULL, NULL); - - if (status == IceProcessMessagesIOError) - { - /* We were disconnected; close our connection to the - * session manager, this will result in the ICE connection - * being cleaned up, since it is owned by libSM. - */ - disconnect (); - meta_context_terminate (ice_connection->context); - - return FALSE; - } - - return TRUE; -} - -/* This is called when a new ICE connection is made. It arranges for - the ICE connection to be handled via the event loop. */ -static void -new_ice_connection (IceConn connection, IcePointer client_data, Bool opening, - IcePointer *watch_data) -{ - MetaContext *context = client_data; - guint input_id; - - if (opening) - { - MetaIceConnection *ice_connection; - GIOChannel *channel; - - fcntl (IceConnectionNumber (connection), F_SETFD, - fcntl (IceConnectionNumber (connection), F_GETFD, 0) | FD_CLOEXEC); - - ice_connection = g_new0 (MetaIceConnection, 1); - ice_connection->ice_connection = connection; - ice_connection->context = context; - - channel = g_io_channel_unix_new (IceConnectionNumber (connection)); - - input_id = g_io_add_watch_full (channel, - G_PRIORITY_DEFAULT, - G_IO_IN | G_IO_ERR, - process_ice_messages, - ice_connection, - g_free); - - g_io_channel_unref (channel); - - *watch_data = (IcePointer) GUINT_TO_POINTER (input_id); - } - else - { - input_id = GPOINTER_TO_UINT ((gpointer) *watch_data); - - g_clear_handle_id (&input_id, g_source_remove); - } -} - -static IceIOErrorHandler ice_installed_handler; - -/* We call any handler installed before (or after) gnome_ice_init but - avoid calling the default libICE handler which does an exit() */ -static void -ice_io_error_handler (IceConn connection) -{ - if (ice_installed_handler) - (*ice_installed_handler) (connection); -} - -static void -ice_init (void) -{ - static gboolean ice_initted = FALSE; - - if (! ice_initted) - { - IceIOErrorHandler default_handler; - - ice_installed_handler = IceSetIOErrorHandler (NULL); - default_handler = IceSetIOErrorHandler (ice_io_error_handler); - - if (ice_installed_handler == default_handler) - ice_installed_handler = NULL; - - IceAddConnectionWatch (new_ice_connection, NULL); - - ice_initted = TRUE; - } -} - -typedef enum -{ - STATE_DISCONNECTED, - STATE_IDLE, - STATE_SAVING_PHASE_1, - STATE_WAITING_FOR_PHASE_2, - STATE_SAVING_PHASE_2, - STATE_WAITING_FOR_INTERACT, - STATE_DONE_WITH_INTERACT, - STATE_SKIPPING_GLOBAL_SAVE, - STATE_FROZEN, - STATE_REGISTERING -} ClientState; - -static void save_phase_2_callback (SmcConn smc_conn, - SmPointer client_data); -static void interact_callback (SmcConn smc_conn, - SmPointer client_data); -static void shutdown_cancelled_callback (SmcConn smc_conn, - SmPointer client_data); -static void save_complete_callback (SmcConn smc_conn, - SmPointer client_data); -static void die_callback (SmcConn smc_conn, - SmPointer client_data); -static void save_yourself_callback (SmcConn smc_conn, - SmPointer client_data, - int save_style, - Bool shutdown, - int interact_style, - Bool fast); -static void set_clone_restart_commands (void); - -static char *client_id = NULL; -static gpointer session_connection = NULL; -static ClientState current_state = STATE_DISCONNECTED; -static gboolean interaction_allowed = FALSE; - -void -meta_session_init (MetaContext *context, - const char *previous_client_id, - const char *previous_save_file) -{ - /* Some code here from twm */ - char buf[256]; - unsigned long mask; - SmcCallbacks callbacks; - char *saved_client_id; - - if (!previous_client_id) - { - const char *desktop_autostart_id; - - desktop_autostart_id = g_getenv ("DESKTOP_AUTOSTART_ID"); - if (desktop_autostart_id) - previous_client_id = desktop_autostart_id; - } - g_unsetenv ("DESKTOP_AUTOSTART_ID"); - - meta_topic (META_DEBUG_SM, "Initializing session with save file '%s'", - previous_save_file ? previous_save_file : "(none)"); - - if (previous_save_file) - { - saved_client_id = load_state (previous_save_file); - previous_client_id = saved_client_id; - } - else if (previous_client_id) - { - char *save_file = g_strconcat (previous_client_id, ".ms", NULL); - saved_client_id = load_state (save_file); - g_free (save_file); - } - else - { - saved_client_id = NULL; - } - - ice_init (); - - mask = SmcSaveYourselfProcMask | SmcDieProcMask | - SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask; - - callbacks.save_yourself.callback = save_yourself_callback; - callbacks.save_yourself.client_data = context; - - callbacks.die.callback = die_callback; - callbacks.die.client_data = context; - - callbacks.save_complete.callback = save_complete_callback; - callbacks.save_complete.client_data = context; - - callbacks.shutdown_cancelled.callback = shutdown_cancelled_callback; - callbacks.shutdown_cancelled.client_data = context; - - session_connection = - SmcOpenConnection (NULL, /* use SESSION_MANAGER env */ - NULL, /* means use existing ICE connection */ - SmProtoMajor, - SmProtoMinor, - mask, - &callbacks, - (char*) previous_client_id, - &client_id, - 255, buf); - - if (session_connection == NULL) - { - meta_topic (META_DEBUG_SM, - "Failed to a open connection to a session manager, so window positions will not be saved: %s", - buf); - - goto out; - } - else - { - if (client_id == NULL) - meta_bug ("Session manager gave us a NULL client ID?"); - meta_topic (META_DEBUG_SM, "Obtained session ID '%s'", client_id); - } - - if (previous_client_id && strcmp (previous_client_id, client_id) == 0) - current_state = STATE_IDLE; - else - current_state = STATE_REGISTERING; - - { - SmProp prop1, prop2, prop3, prop4, prop5, prop6, *props[6]; - SmPropValue prop1val, prop2val, prop3val, prop4val, prop5val, prop6val; - char pid[32]; - /* Historically, this was SmRestartImmediately, which made sense - * for a stateless window manager, but we don't really control - * what embedders do, and it's all around better if gnome-session - * handles this. - */ - char hint = SmRestartIfRunning; - char priority = 20; /* low to run before other apps */ - const char *prgname; - - prgname = g_get_prgname (); - - prop1.name = (char *)SmProgram; - prop1.type = (char *)SmARRAY8; - prop1.num_vals = 1; - prop1.vals = &prop1val; - prop1val.value = (char *)prgname; - prop1val.length = strlen (prgname); - - /* twm sets getuid() for this, but the SM spec plainly - * says pw_name, twm is on crack - */ - prop2.name = (char *)SmUserID; - prop2.type = (char *)SmARRAY8; - prop2.num_vals = 1; - prop2.vals = &prop2val; - prop2val.value = (char*) g_get_user_name (); - prop2val.length = strlen (prop2val.value); - - prop3.name = (char *)SmRestartStyleHint; - prop3.type = (char *)SmCARD8; - prop3.num_vals = 1; - prop3.vals = &prop3val; - prop3val.value = &hint; - prop3val.length = 1; - - sprintf (pid, "%d", getpid ()); - prop4.name = (char *)SmProcessID; - prop4.type = (char *)SmARRAY8; - prop4.num_vals = 1; - prop4.vals = &prop4val; - prop4val.value = pid; - prop4val.length = strlen (prop4val.value); - - /* Always start in home directory */ - prop5.name = (char *)SmCurrentDirectory; - prop5.type = (char *)SmARRAY8; - prop5.num_vals = 1; - prop5.vals = &prop5val; - prop5val.value = (char*) g_get_home_dir (); - prop5val.length = strlen (prop5val.value); - - prop6.name = (char *)"_GSM_Priority"; - prop6.type = (char *)SmCARD8; - prop6.num_vals = 1; - prop6.vals = &prop6val; - prop6val.value = &priority; - prop6val.length = 1; - - props[0] = &prop1; - props[1] = &prop2; - props[2] = &prop3; - props[3] = &prop4; - props[4] = &prop5; - props[5] = &prop6; - - SmcSetProperties (session_connection, 6, props); - } - - out: - g_free (saved_client_id); -} - -static void -disconnect (void) -{ - SmcCloseConnection (session_connection, 0, NULL); - session_connection = NULL; - current_state = STATE_DISCONNECTED; -} - -static void -save_yourself_possibly_done (gboolean shutdown, - gboolean successful) -{ - meta_topic (META_DEBUG_SM, - "save possibly done shutdown = %d success = %d", - shutdown, successful); - - if (current_state == STATE_SAVING_PHASE_1) - { - Status status; - - status = SmcRequestSaveYourselfPhase2 (session_connection, - save_phase_2_callback, - GINT_TO_POINTER (shutdown)); - - if (status) - current_state = STATE_WAITING_FOR_PHASE_2; - - meta_topic (META_DEBUG_SM, - "Requested phase 2, status = %d", status); - } - - if (current_state == STATE_SAVING_PHASE_2 && - interaction_allowed) - { - Status status; - - status = SmcInteractRequest (session_connection, - /* ignore this feature of the protocol by always - * claiming normal - */ - SmDialogNormal, - interact_callback, - GINT_TO_POINTER (shutdown)); - - if (status) - current_state = STATE_WAITING_FOR_INTERACT; - - meta_topic (META_DEBUG_SM, - "Requested interact, status = %d", status); - } - - if (current_state == STATE_SAVING_PHASE_1 || - current_state == STATE_SAVING_PHASE_2 || - current_state == STATE_DONE_WITH_INTERACT || - current_state == STATE_SKIPPING_GLOBAL_SAVE) - { - meta_topic (META_DEBUG_SM, "Sending SaveYourselfDone"); - - SmcSaveYourselfDone (session_connection, - successful); - - if (shutdown) - current_state = STATE_FROZEN; - else - current_state = STATE_IDLE; - } -} - -static void -save_phase_2_callback (SmcConn smc_conn, SmPointer client_data) -{ - gboolean shutdown; - - meta_topic (META_DEBUG_SM, "Phase 2 save"); - - shutdown = GPOINTER_TO_INT (client_data); - - current_state = STATE_SAVING_PHASE_2; - - save_state (); - - save_yourself_possibly_done (shutdown, TRUE); -} - -static void -save_yourself_callback (SmcConn smc_conn, - SmPointer client_data, - int save_style, - Bool shutdown, - int interact_style, - Bool fast) -{ - gboolean successful; - - meta_topic (META_DEBUG_SM, "SaveYourself received"); - - successful = TRUE; - - /* The first SaveYourself after registering for the first time - * is a special case (SM specs 7.2). - */ - -#if 0 /* I think the GnomeClient rationale for this doesn't apply */ - if (current_state == STATE_REGISTERING) - { - current_state = STATE_IDLE; - /* Double check that this is a section 7.2 SaveYourself: */ - - if (save_style == SmSaveLocal && - interact_style == SmInteractStyleNone && - !shutdown && !fast) - { - /* The protocol requires this even if xsm ignores it. */ - SmcSaveYourselfDone (session_connection, successful); - return; - } - } -#endif - - /* ignore Global style saves - * - * This interpretaion of the Local/Global/Both styles - * was discussed extensively on the xdg-list. See: - * - * https://listman.redhat.com/pipermail/xdg-list/2002-July/000615.html - */ - if (save_style == SmSaveGlobal) - { - current_state = STATE_SKIPPING_GLOBAL_SAVE; - save_yourself_possibly_done (shutdown, successful); - return; - } - - interaction_allowed = interact_style != SmInteractStyleNone; - - current_state = STATE_SAVING_PHASE_1; - - regenerate_save_file (); - - set_clone_restart_commands (); - - save_yourself_possibly_done (shutdown, successful); -} - - -static void -die_callback (SmcConn smc_conn, SmPointer client_data) -{ - MetaContext *context = client_data; - - meta_topic (META_DEBUG_SM, "Disconnecting from session manager"); - - disconnect (); - /* We don't actually exit here - we will simply go away with the X - * server on logout, when we lose the X connection and libx11 kills - * us. It looks like *crap* on logout if the user sees their - * windows lose the decorations, etc. - * - * Anything that wants us to go away outside of session management - * can use kill(). - */ - - /* All of that is true - unless we're a wayland compositor. In which - * case the X server won't go down until we do, so we must die first. - */ - if (meta_is_wayland_compositor ()) - meta_context_terminate (context); -} - -static void -save_complete_callback (SmcConn smc_conn, SmPointer client_data) -{ - /* nothing */ - meta_topic (META_DEBUG_SM, "SaveComplete received"); -} - -static void -shutdown_cancelled_callback (SmcConn smc_conn, SmPointer client_data) -{ - meta_topic (META_DEBUG_SM, "Shutdown cancelled received"); - - if (session_connection != NULL && - (current_state != STATE_IDLE && current_state != STATE_FROZEN)) - { - SmcSaveYourselfDone (session_connection, True); - current_state = STATE_IDLE; - } -} - -static void -interact_callback (SmcConn smc_conn, SmPointer client_data) -{ - /* nothing */ - gboolean shutdown; - - meta_topic (META_DEBUG_SM, "Interaction permission received"); - - shutdown = GPOINTER_TO_INT (client_data); - - current_state = STATE_DONE_WITH_INTERACT; - - warn_about_lame_clients_and_finish_interact (shutdown); -} - -static void -set_clone_restart_commands (void) -{ - char *restartv[10]; - char *clonev[10]; - char *discardv[10]; - int i; - SmProp prop1, prop2, prop3, *props[3]; - const char *prgname; - - prgname = g_get_prgname (); - - /* Restart (use same client ID) */ - - prop1.name = (char *)SmRestartCommand; - prop1.type = (char *)SmLISTofARRAY8; - - g_return_if_fail (client_id); - - i = 0; - restartv[i] = (char *)prgname; - ++i; - restartv[i] = (char *)"--sm-client-id"; - ++i; - restartv[i] = client_id; - ++i; - restartv[i] = NULL; - - prop1.vals = g_new (SmPropValue, i); - i = 0; - while (restartv[i]) - { - prop1.vals[i].value = restartv[i]; - prop1.vals[i].length = strlen (restartv[i]); - ++i; - } - prop1.num_vals = i; - - /* Clone (no client ID) */ - - i = 0; - clonev[i] = (char *)prgname; - ++i; - clonev[i] = NULL; - - prop2.name = (char *)SmCloneCommand; - prop2.type = (char *)SmLISTofARRAY8; - - prop2.vals = g_new (SmPropValue, i); - i = 0; - while (clonev[i]) - { - prop2.vals[i].value = clonev[i]; - prop2.vals[i].length = strlen (clonev[i]); - ++i; - } - prop2.num_vals = i; - - /* Discard */ - - i = 0; - discardv[i] = (char *)"rm"; - ++i; - discardv[i] = (char *)"-f"; - ++i; - discardv[i] = (char*) full_save_file (); - ++i; - discardv[i] = NULL; - - prop3.name = (char *)SmDiscardCommand; - prop3.type = (char *)SmLISTofARRAY8; - - prop3.vals = g_new (SmPropValue, i); - i = 0; - while (discardv[i]) - { - prop3.vals[i].value = discardv[i]; - prop3.vals[i].length = strlen (discardv[i]); - ++i; - } - prop3.num_vals = i; - - - props[0] = &prop1; - props[1] = &prop2; - props[2] = &prop3; - - SmcSetProperties (session_connection, 3, props); - - g_free (prop1.vals); - g_free (prop2.vals); - g_free (prop3.vals); -} - -/* The remaining code in this file actually loads/saves the session, - * while the code above this comment handles chatting with the - * session manager. - */ - -static const char* -window_type_to_string (MetaWindowType type) -{ - switch (type) - { - case META_WINDOW_NORMAL: - return "normal"; - case META_WINDOW_DESKTOP: - return "desktop"; - case META_WINDOW_DOCK: - return "dock"; - case META_WINDOW_DIALOG: - return "dialog"; - case META_WINDOW_MODAL_DIALOG: - return "modal_dialog"; - case META_WINDOW_TOOLBAR: - return "toolbar"; - case META_WINDOW_MENU: - return "menu"; - case META_WINDOW_SPLASHSCREEN: - return "splashscreen"; - case META_WINDOW_UTILITY: - return "utility"; - case META_WINDOW_DROPDOWN_MENU: - return "dropdown_menu"; - case META_WINDOW_POPUP_MENU: - return "popup_menu"; - case META_WINDOW_TOOLTIP: - return "tooltip"; - case META_WINDOW_NOTIFICATION: - return "notification"; - case META_WINDOW_COMBO: - return "combo"; - case META_WINDOW_DND: - return "dnd"; - case META_WINDOW_OVERRIDE_OTHER: - return "override_redirect"; - } - - return ""; -} - -static MetaWindowType -window_type_from_string (const char *str) -{ - if (strcmp (str, "normal") == 0) - return META_WINDOW_NORMAL; - else if (strcmp (str, "desktop") == 0) - return META_WINDOW_DESKTOP; - else if (strcmp (str, "dock") == 0) - return META_WINDOW_DOCK; - else if (strcmp (str, "dialog") == 0) - return META_WINDOW_DIALOG; - else if (strcmp (str, "modal_dialog") == 0) - return META_WINDOW_MODAL_DIALOG; - else if (strcmp (str, "toolbar") == 0) - return META_WINDOW_TOOLBAR; - else if (strcmp (str, "menu") == 0) - return META_WINDOW_MENU; - else if (strcmp (str, "utility") == 0) - return META_WINDOW_UTILITY; - else if (strcmp (str, "splashscreen") == 0) - return META_WINDOW_SPLASHSCREEN; - else - return META_WINDOW_NORMAL; -} - -static int -window_gravity_from_string (const char *str) -{ - if (strcmp (str, "META_GRAVITY_NORTH_WEST") == 0) - return META_GRAVITY_NORTH_WEST; - else if (strcmp (str, "META_GRAVITY_NORTH") == 0) - return META_GRAVITY_NORTH; - else if (strcmp (str, "META_GRAVITY_NORTH_EAST") == 0) - return META_GRAVITY_NORTH_EAST; - else if (strcmp (str, "META_GRAVITY_WEST") == 0) - return META_GRAVITY_WEST; - else if (strcmp (str, "META_GRAVITY_CENTER") == 0) - return META_GRAVITY_CENTER; - else if (strcmp (str, "META_GRAVITY_EAST") == 0) - return META_GRAVITY_EAST; - else if (strcmp (str, "META_GRAVITY_SOUTH_WEST") == 0) - return META_GRAVITY_SOUTH_WEST; - else if (strcmp (str, "META_GRAVITY_SOUTH") == 0) - return META_GRAVITY_SOUTH; - else if (strcmp (str, "META_GRAVITY_SOUTH_EAST") == 0) - return META_GRAVITY_SOUTH_EAST; - else if (strcmp (str, "META_GRAVITY_STATIC") == 0) - return META_GRAVITY_STATIC; - else - return META_GRAVITY_NORTH_WEST; -} - -static char* -encode_text_as_utf8_markup (const char *text) -{ - /* text can be any encoding, and is nul-terminated. - * we pretend it's Latin-1 and encode as UTF-8 - */ - GString *str; - const char *p; - char *escaped; - - str = g_string_new (""); - - p = text; - while (*p) - { - g_string_append_unichar (str, *p); - ++p; - } - - escaped = g_markup_escape_text (str->str, str->len); - g_string_free (str, TRUE); - - return escaped; -} - -static char* -decode_text_from_utf8 (const char *text) -{ - /* Convert back from the encoded (but not escaped) UTF-8 */ - GString *str; - const char *p; - - str = g_string_new (""); - - p = text; - while (*p) - { - /* obviously this barfs if the UTF-8 contains chars > 255 */ - g_string_append_c (str, g_utf8_get_char (p)); - - p = g_utf8_next_char (p); - } - - return g_string_free (str, FALSE); -} - -static void -save_state (void) -{ - char *mutter_dir; - char *session_dir; - FILE *outfile; - GSList *windows; - GSList *tmp; - int stack_position; - - g_assert (client_id); - - outfile = NULL; - - /* - * g_get_user_config_dir() is guaranteed to return an existing directory. - * Eventually, if SM stays with the WM, I'd like to make this - * something like /window_placement in a standard format. - * Future optimisers should note also that by the time we get here - * we probably already have full_save_path figured out and therefore - * can just use the directory name from that. - */ - mutter_dir = g_strconcat (g_get_user_config_dir (), - G_DIR_SEPARATOR_S "mutter", - NULL); - - session_dir = g_strconcat (mutter_dir, - G_DIR_SEPARATOR_S "sessions", - NULL); - - if (mkdir (mutter_dir, 0700) < 0 && - errno != EEXIST) - { - meta_warning ("Could not create directory '%s': %s", - mutter_dir, g_strerror (errno)); - } - - if (mkdir (session_dir, 0700) < 0 && - errno != EEXIST) - { - meta_warning ("Could not create directory '%s': %s", - session_dir, g_strerror (errno)); - } - - meta_topic (META_DEBUG_SM, "Saving session to '%s'", full_save_file ()); - - outfile = fopen (full_save_file (), "w"); - - if (outfile == NULL) - { - meta_warning ("Could not open session file '%s' for writing: %s", - full_save_file (), g_strerror (errno)); - goto out; - } - - /* The file format is: - * - * - * - * - * - * - * - * - * - * Note that attributes on are the match info we use to - * see if the saved state applies to a restored window, and - * child elements are the saved state to be applied. - * - */ - - fprintf (outfile, "\n", - client_id); - - windows = meta_display_list_windows (meta_get_display (), META_LIST_DEFAULT); - stack_position = 0; - - windows = g_slist_sort (windows, meta_display_stack_cmp); - tmp = windows; - stack_position = 0; - - while (tmp != NULL) - { - MetaWindow *window; - - window = tmp->data; - - if (window->sm_client_id) - { - char *sm_client_id; - char *res_class; - char *res_name; - char *role; - char *title; - - /* client id, class, name, role are not expected to be - * in UTF-8 (I think they are in XPCS which is Latin-1? - * in practice they are always ascii though.) - */ - - sm_client_id = encode_text_as_utf8_markup (window->sm_client_id); - res_class = window->res_class ? - encode_text_as_utf8_markup (window->res_class) : NULL; - res_name = window->res_name ? - encode_text_as_utf8_markup (window->res_name) : NULL; - role = window->role ? - encode_text_as_utf8_markup (window->role) : NULL; - if (window->title) - title = g_markup_escape_text (window->title, -1); - else - title = NULL; - - meta_topic (META_DEBUG_SM, "Saving session managed window %s, client ID '%s'", - window->desc, window->sm_client_id); - - fprintf (outfile, - " \n", - sm_client_id, - res_class ? res_class : "", - res_name ? res_name : "", - title ? title : "", - role ? role : "", - window_type_to_string (window->type), - stack_position); - - g_free (sm_client_id); - g_free (res_class); - g_free (res_name); - g_free (role); - g_free (title); - - /* Sticky */ - if (window->on_all_workspaces_requested) - { - fputs (" \n", outfile); - } else { - int n; - if (window->workspace) - n = meta_workspace_index (window->workspace); - else - n = window->initial_workspace; - fprintf (outfile, - " \n", n); - } - - - /* Minimized */ - if (window->minimized) - fputs (" \n", outfile); - - /* Maximized */ - if (META_WINDOW_MAXIMIZED (window)) - { - fprintf (outfile, - " \n", - window->saved_rect.x, - window->saved_rect.y, - window->saved_rect.width, - window->saved_rect.height); - } - - /* Gravity */ - { - int x, y, w, h; - meta_window_get_session_geometry (window, &x, &y, &w, &h); - - fprintf (outfile, - " \n", - x, y, w, h, - meta_gravity_to_string (window->size_hints.win_gravity)); - } - - fputs (" \n", outfile); - } - else - { - meta_topic (META_DEBUG_SM, "Not saving window '%s', not session managed", - window->desc); - } - - tmp = tmp->next; - ++stack_position; - } - - g_slist_free (windows); - - fputs ("\n", outfile); - - out: - if (outfile) - { - /* FIXME need a dialog for this */ - if (ferror (outfile)) - { - meta_warning ("Error writing session file '%s': %s", - full_save_file (), g_strerror (errno)); - } - if (fclose (outfile)) - { - meta_warning ("Error closing session file '%s': %s", - full_save_file (), g_strerror (errno)); - } - } - - g_free (mutter_dir); - g_free (session_dir); -} - -typedef enum -{ - WINDOW_TAG_NONE, - WINDOW_TAG_DESKTOP, - WINDOW_TAG_STICKY, - WINDOW_TAG_MINIMIZED, - WINDOW_TAG_MAXIMIZED, - WINDOW_TAG_GEOMETRY -} WindowTag; - -typedef struct -{ - MetaWindowSessionInfo *info; - char *previous_id; -} ParseData; - -static void session_info_free (MetaWindowSessionInfo *info); -static MetaWindowSessionInfo* session_info_new (void); - -static void start_element_handler (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error); -static void end_element_handler (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error); -static void text_handler (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error); - -static GMarkupParser mutter_session_parser = { - start_element_handler, - end_element_handler, - text_handler, - NULL, - NULL -}; - -static GSList *window_info_list = NULL; - -static char* -load_state (const char *previous_save_file) -{ - GMarkupParseContext *context; - GError *error; - ParseData parse_data; - char *text; - gsize length; - char *session_file; - - session_file = g_strconcat (g_get_user_config_dir (), - G_DIR_SEPARATOR_S "mutter" - G_DIR_SEPARATOR_S "sessions" G_DIR_SEPARATOR_S, - previous_save_file, - NULL); - - error = NULL; - if (!g_file_get_contents (session_file, - &text, - &length, - &error)) - { - char *canonical_session_file = session_file; - - /* Maybe they were doing it the old way, with ~/.mutter */ - session_file = g_strconcat (g_get_home_dir (), - G_DIR_SEPARATOR_S ".mutter" - G_DIR_SEPARATOR_S "sessions" - G_DIR_SEPARATOR_S, - previous_save_file, - NULL); - - if (!g_file_get_contents (session_file, - &text, - &length, - NULL)) - { - /* oh, just give up */ - - g_error_free (error); - g_free (session_file); - g_free (canonical_session_file); - return NULL; - } - - g_free (canonical_session_file); - } - - meta_topic (META_DEBUG_SM, "Parsing saved session file %s", session_file); - g_free (session_file); - session_file = NULL; - - parse_data.info = NULL; - parse_data.previous_id = NULL; - - context = g_markup_parse_context_new (&mutter_session_parser, - 0, &parse_data, NULL); - - error = NULL; - if (!g_markup_parse_context_parse (context, - text, - length, - &error)) - goto error; - - - error = NULL; - if (!g_markup_parse_context_end_parse (context, &error)) - goto error; - - g_markup_parse_context_free (context); - - goto out; - - error: - - meta_warning ("Failed to parse saved session file: %s", - error->message); - g_error_free (error); - - if (parse_data.info) - session_info_free (parse_data.info); - - g_free (parse_data.previous_id); - parse_data.previous_id = NULL; - - out: - - g_free (text); - - return parse_data.previous_id; -} - -/* FIXME this isn't very robust against bogus session files */ -static void -start_element_handler (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error) -{ - ParseData *pd; - - pd = user_data; - - if (strcmp (element_name, "mutter_session") == 0) - { - /* Get previous ID */ - int i; - - i = 0; - while (attribute_names[i]) - { - const char *name; - const char *val; - - name = attribute_names[i]; - val = attribute_values[i]; - - if (pd->previous_id) - { - g_set_error (error, - G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - " attribute seen but we already have the session ID"); - return; - } - - if (strcmp (name, "id") == 0) - { - pd->previous_id = decode_text_from_utf8 (val); - } - else - { - g_set_error (error, - G_MARKUP_ERROR, - G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, - "Unknown attribute %s on <%s> element", - name, "mutter_session"); - return; - } - - ++i; - } - } - else if (strcmp (element_name, "window") == 0) - { - int i; - - if (pd->info) - { - g_set_error (error, - G_MARKUP_ERROR, - G_MARKUP_ERROR_PARSE, - "nested tag"); - return; - } - - pd->info = session_info_new (); - - i = 0; - while (attribute_names[i]) - { - const char *name; - const char *val; - - name = attribute_names[i]; - val = attribute_values[i]; - - if (strcmp (name, "id") == 0) - { - if (*val) - pd->info->id = decode_text_from_utf8 (val); - } - else if (strcmp (name, "class") == 0) - { - if (*val) - pd->info->res_class = decode_text_from_utf8 (val); - } - else if (strcmp (name, "name") == 0) - { - if (*val) - pd->info->res_name = decode_text_from_utf8 (val); - } - else if (strcmp (name, "title") == 0) - { - if (*val) - pd->info->title = g_strdup (val); - } - else if (strcmp (name, "role") == 0) - { - if (*val) - pd->info->role = decode_text_from_utf8 (val); - } - else if (strcmp (name, "type") == 0) - { - if (*val) - pd->info->type = window_type_from_string (val); - } - else if (strcmp (name, "stacking") == 0) - { - if (*val) - { - pd->info->stack_position = atoi (val); - pd->info->stack_position_set = TRUE; - } - } - else - { - g_set_error (error, - G_MARKUP_ERROR, - G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, - "Unknown attribute %s on <%s> element", - name, "window"); - session_info_free (pd->info); - pd->info = NULL; - return; - } - - ++i; - } - } - else if (strcmp (element_name, "workspace") == 0) - { - int i; - - i = 0; - while (attribute_names[i]) - { - const char *name; - - name = attribute_names[i]; - - if (strcmp (name, "index") == 0) - { - pd->info->workspace_indices = - g_slist_prepend (pd->info->workspace_indices, - GINT_TO_POINTER (atoi (attribute_values[i]))); - } - else - { - g_set_error (error, - G_MARKUP_ERROR, - G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, - "Unknown attribute %s on <%s> element", - name, "window"); - session_info_free (pd->info); - pd->info = NULL; - return; - } - - ++i; - } - } - else if (strcmp (element_name, "sticky") == 0) - { - pd->info->on_all_workspaces = TRUE; - pd->info->on_all_workspaces_set = TRUE; - } - else if (strcmp (element_name, "minimized") == 0) - { - pd->info->minimized = TRUE; - pd->info->minimized_set = TRUE; - } - else if (strcmp (element_name, "maximized") == 0) - { - int i; - - i = 0; - pd->info->maximized = TRUE; - pd->info->maximized_set = TRUE; - while (attribute_names[i]) - { - const char *name; - const char *val; - - name = attribute_names[i]; - val = attribute_values[i]; - - if (strcmp (name, "saved_x") == 0) - { - if (*val) - { - pd->info->saved_rect.x = atoi (val); - pd->info->saved_rect_set = TRUE; - } - } - else if (strcmp (name, "saved_y") == 0) - { - if (*val) - { - pd->info->saved_rect.y = atoi (val); - pd->info->saved_rect_set = TRUE; - } - } - else if (strcmp (name, "saved_width") == 0) - { - if (*val) - { - pd->info->saved_rect.width = atoi (val); - pd->info->saved_rect_set = TRUE; - } - } - else if (strcmp (name, "saved_height") == 0) - { - if (*val) - { - pd->info->saved_rect.height = atoi (val); - pd->info->saved_rect_set = TRUE; - } - } - else - { - g_set_error (error, - G_MARKUP_ERROR, - G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, - "Unknown attribute %s on <%s> element", - name, "maximized"); - return; - } - - ++i; - } - - if (pd->info->saved_rect_set) - meta_topic (META_DEBUG_SM, "Saved unmaximized size %d,%d %dx%d ", - pd->info->saved_rect.x, - pd->info->saved_rect.y, - pd->info->saved_rect.width, - pd->info->saved_rect.height); - } - else if (strcmp (element_name, "geometry") == 0) - { - int i; - - pd->info->geometry_set = TRUE; - - i = 0; - while (attribute_names[i]) - { - const char *name; - const char *val; - - name = attribute_names[i]; - val = attribute_values[i]; - - if (strcmp (name, "x") == 0) - { - if (*val) - pd->info->rect.x = atoi (val); - } - else if (strcmp (name, "y") == 0) - { - if (*val) - pd->info->rect.y = atoi (val); - } - else if (strcmp (name, "width") == 0) - { - if (*val) - pd->info->rect.width = atoi (val); - } - else if (strcmp (name, "height") == 0) - { - if (*val) - pd->info->rect.height = atoi (val); - } - else if (strcmp (name, "gravity") == 0) - { - if (*val) - pd->info->gravity = window_gravity_from_string (val); - } - else - { - g_set_error (error, - G_MARKUP_ERROR, - G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, - "Unknown attribute %s on <%s> element", - name, "geometry"); - return; - } - - ++i; - } - - meta_topic (META_DEBUG_SM, "Loaded geometry %d,%d %dx%d gravity %s", - pd->info->rect.x, - pd->info->rect.y, - pd->info->rect.width, - pd->info->rect.height, - meta_gravity_to_string (pd->info->gravity)); - } - else - { - g_set_error (error, - G_MARKUP_ERROR, - G_MARKUP_ERROR_UNKNOWN_ELEMENT, - "Unknown element %s", - element_name); - return; - } -} - -static void -end_element_handler (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error) -{ - ParseData *pd; - - pd = user_data; - - if (strcmp (element_name, "window") == 0) - { - g_assert (pd->info); - - window_info_list = g_slist_prepend (window_info_list, - pd->info); - - meta_topic (META_DEBUG_SM, "Loaded window info from session with class: %s name: %s role: %s", - pd->info->res_class ? pd->info->res_class : "(none)", - pd->info->res_name ? pd->info->res_name : "(none)", - pd->info->role ? pd->info->role : "(none)"); - - pd->info = NULL; - } -} - -static void -text_handler (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error) -{ - /* Right now we don't have any elements where we care about their - * content - */ -} - -static gboolean -both_null_or_matching (const char *a, - const char *b) -{ - if (a == NULL && b == NULL) - return TRUE; - else if (a && b && strcmp (a, b) == 0) - return TRUE; - else - return FALSE; -} - -static GSList* -get_possible_matches (MetaWindow *window) -{ - /* Get all windows with this client ID */ - GSList *retval; - GSList *tmp; - gboolean ignore_client_id; - - retval = NULL; - - ignore_client_id = g_getenv ("MUTTER_DEBUG_SM") != NULL; - - tmp = window_info_list; - while (tmp != NULL) - { - MetaWindowSessionInfo *info; - - info = tmp->data; - - if ((ignore_client_id || - both_null_or_matching (info->id, window->sm_client_id)) && - both_null_or_matching (info->res_class, window->res_class) && - both_null_or_matching (info->res_name, window->res_name) && - both_null_or_matching (info->role, window->role)) - { - meta_topic (META_DEBUG_SM, "Window %s may match saved window with class: %s name: %s role: %s", - window->desc, - info->res_class ? info->res_class : "(none)", - info->res_name ? info->res_name : "(none)", - info->role ? info->role : "(none)"); - - retval = g_slist_prepend (retval, info); - } - else - { - if (meta_is_verbose ()) - { - if (!both_null_or_matching (info->id, window->sm_client_id)) - meta_topic (META_DEBUG_SM, "Window %s has SM client ID %s, saved state has %s, no match", - window->desc, - window->sm_client_id ? window->sm_client_id : "(none)", - info->id ? info->id : "(none)"); - else if (!both_null_or_matching (info->res_class, window->res_class)) - meta_topic (META_DEBUG_SM, "Window %s has class %s doesn't match saved class %s, no match", - window->desc, - window->res_class ? window->res_class : "(none)", - info->res_class ? info->res_class : "(none)"); - - else if (!both_null_or_matching (info->res_name, window->res_name)) - meta_topic (META_DEBUG_SM, "Window %s has name %s doesn't match saved name %s, no match", - window->desc, - window->res_name ? window->res_name : "(none)", - info->res_name ? info->res_name : "(none)"); - else if (!both_null_or_matching (info->role, window->role)) - meta_topic (META_DEBUG_SM, "Window %s has role %s doesn't match saved role %s, no match", - window->desc, - window->role ? window->role : "(none)", - info->role ? info->role : "(none)"); - else - meta_topic (META_DEBUG_SM, "???? should not happen - window %s doesn't match saved state %s for no good reason", - window->desc, info->id); - } - } - - tmp = tmp->next; - } - - return retval; -} - -static const MetaWindowSessionInfo* -find_best_match (GSList *infos, - MetaWindow *window) -{ - GSList *tmp; - const MetaWindowSessionInfo *matching_title; - const MetaWindowSessionInfo *matching_type; - - matching_title = NULL; - matching_type = NULL; - - tmp = infos; - while (tmp != NULL) - { - MetaWindowSessionInfo *info; - - info = tmp->data; - - if (matching_title == NULL && - both_null_or_matching (info->title, window->title)) - matching_title = info; - - if (matching_type == NULL && - info->type == window->type) - matching_type = info; - - tmp = tmp->next; - } - - /* Prefer same title, then same type of window, then - * just pick something. Eventually we could enhance this - * to e.g. break ties by geometry hint similarity, - * or other window features. - */ - - if (matching_title) - return matching_title; - else if (matching_type) - return matching_type; - else - return infos->data; -} - -const MetaWindowSessionInfo* -meta_window_lookup_saved_state (MetaWindow *window) -{ - GSList *possibles; - const MetaWindowSessionInfo *info; - - /* Window is not session managed. - * I haven't yet figured out how to deal with these - * in a way that doesn't cause broken side effects in - * situations other than on session restore. - */ - if (window->sm_client_id == NULL) - { - meta_topic (META_DEBUG_SM, - "Window %s is not session managed, not checking for saved state", - window->desc); - return NULL; - } - - possibles = get_possible_matches (window); - - if (possibles == NULL) - { - meta_topic (META_DEBUG_SM, - "Window %s has no possible matches in the list of saved window states", - window->desc); - return NULL; - } - - info = find_best_match (possibles, window); - - g_slist_free (possibles); - - return info; -} - -void -meta_window_release_saved_state (const MetaWindowSessionInfo *info) -{ - /* We don't want to use the same saved state again for another - * window. - */ - window_info_list = g_slist_remove (window_info_list, info); - - session_info_free ((MetaWindowSessionInfo*) info); -} - -static void -session_info_free (MetaWindowSessionInfo *info) -{ - g_free (info->id); - g_free (info->res_class); - g_free (info->res_name); - g_free (info->title); - g_free (info->role); - - g_slist_free (info->workspace_indices); - - g_free (info); -} - -static MetaWindowSessionInfo* -session_info_new (void) -{ - MetaWindowSessionInfo *info; - - info = g_new0 (MetaWindowSessionInfo, 1); - - info->type = META_WINDOW_NORMAL; - info->gravity = META_GRAVITY_NORTH_WEST; - - return info; -} - -static char* full_save_path = NULL; - -static void -regenerate_save_file (void) -{ - g_free (full_save_path); - - if (client_id) - full_save_path = g_strconcat (g_get_user_config_dir (), - G_DIR_SEPARATOR_S "mutter" - G_DIR_SEPARATOR_S "sessions" G_DIR_SEPARATOR_S, - client_id, - ".ms", - NULL); - else - full_save_path = NULL; -} - -static const char* -full_save_file (void) -{ - return full_save_path; -} - -static int -windows_cmp_by_title (MetaWindow *a, - MetaWindow *b) -{ - return g_utf8_collate (a->title, b->title); -} - -static void -finish_interact (gboolean shutdown) -{ - if (current_state == STATE_DONE_WITH_INTERACT) /* paranoia */ - { - SmcInteractDone (session_connection, False /* don't cancel logout */); - - save_yourself_possibly_done (shutdown, TRUE); - } -} - -static void -dialog_closed (GPid pid, int status, gpointer user_data) -{ - gboolean shutdown = GPOINTER_TO_INT (user_data); - - if (WIFEXITED (status) && WEXITSTATUS (status) == 0) /* pressed "OK" */ - { - finish_interact (shutdown); - } -} - -static void -warn_about_lame_clients_and_finish_interact (gboolean shutdown) -{ - GSList *lame = NULL; - GSList *windows; - GSList *lame_details = NULL; - GSList *tmp; - GSList *columns = NULL; - GPid pid; - - windows = meta_display_list_windows (meta_get_display (), META_LIST_DEFAULT); - tmp = windows; - while (tmp != NULL) - { - MetaWindow *window; - - window = tmp->data; - - /* only complain about normal windows, the others - * are kind of dumb to worry about - */ - if (window->sm_client_id == NULL && - window->type == META_WINDOW_NORMAL) - lame = g_slist_prepend (lame, window); - - tmp = tmp->next; - } - - g_slist_free (windows); - - if (lame == NULL) - { - /* No lame apps. */ - finish_interact (shutdown); - return; - } - - columns = g_slist_prepend (columns, (gpointer)"Window"); - columns = g_slist_prepend (columns, (gpointer)"Class"); - - lame = g_slist_sort (lame, (GCompareFunc) windows_cmp_by_title); - - tmp = lame; - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - - lame_details = g_slist_prepend (lame_details, - w->res_class ? w->res_class : (gpointer)""); - lame_details = g_slist_prepend (lame_details, - w->title); - - tmp = tmp->next; - } - g_slist_free (lame); - - pid = meta_show_dialog("--list", - _("These windows do not support “save current setup” " - "and will have to be restarted manually next time " - "you log in."), - "240", - meta_get_display()->x11_display->screen_name, - NULL, NULL, NULL, - None, - columns, - lame_details); - - g_slist_free (lame_details); - - g_child_watch_add (pid, dialog_closed, GINT_TO_POINTER (shutdown)); -} - -#endif /* HAVE_SM */ diff --git a/src/x11/session.h b/src/x11/session.h deleted file mode 100644 index 8df77efbc..000000000 --- a/src/x11/session.h +++ /dev/null @@ -1,90 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/** - * \file session.h Session management - * - * Maps windows to information about their placing and state on startup. - * This is window matching, which we have a policy of leaving in general - * to programs such as Devil's Pie, but the session manager specification - * requires us to do it here. - */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * 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 . - */ - -#ifndef META_SESSION_H -#define META_SESSION_H - -#include "core/window-private.h" - -typedef struct _MetaWindowSessionInfo MetaWindowSessionInfo; - -struct _MetaWindowSessionInfo -{ - /* Fields we use to match against */ - - char *id; - char *res_class; - char *res_name; - char *title; - char *role; - MetaWindowType type; - - /* Information we restore */ - - GSList *workspace_indices; - - int stack_position; - - /* width/height should be multiplied by resize inc and - * added to base size; position should be interpreted in - * light of gravity. This preserves semantics of the - * window size/pos, even if fonts/themes change, etc. - */ - MetaGravity gravity; - MetaRectangle rect; - MetaRectangle saved_rect; - guint on_all_workspaces : 1; - guint minimized : 1; - guint maximized : 1; - - guint stack_position_set : 1; - guint geometry_set : 1; - guint on_all_workspaces_set : 1; - guint minimized_set : 1; - guint maximized_set : 1; - guint saved_rect_set : 1; -}; - -/* If lookup_saved_state returns something, it should be used, - * and then released when you're done with it. - */ -const MetaWindowSessionInfo* meta_window_lookup_saved_state (MetaWindow *window); -void meta_window_release_saved_state (const MetaWindowSessionInfo *info); - -void meta_session_init (MetaContext *context, - const char *client_id, - const char *save_file); - - -void meta_session_shutdown (void); - -#endif - - - - diff --git a/src/x11/window-props.c b/src/x11/window-props.c deleted file mode 100644 index 1d8cf63a6..000000000 --- a/src/x11/window-props.c +++ /dev/null @@ -1,2012 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * SECTION:window-props - * @short_description: #MetaWindow property handling - * - * A system which can inspect sets of properties of given windows - * and take appropriate action given their values. - * - * Note that all the meta_window_reload_propert* functions require a - * round trip to the server. - * - * The guts of this system are in meta_display_init_window_prop_hooks(). - * Reading this function will give you insight into how this all fits - * together. - */ - -/* - * Copyright (C) 2001, 2002, 2003 Red Hat, Inc. - * Copyright (C) 2004, 2005 Elijah Newren - * Copyright (C) 2009 Thomas Thurman - * - * 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 . - */ - -#define _XOPEN_SOURCE 600 /* for gethostname() */ - -#include "config.h" - -#include "x11/window-props.h" - -#include -#include -#include - -#include "core/frame.h" -#include "core/meta-workspace-manager-private.h" -#include "core/util-private.h" -#include "meta/group.h" -#include "meta/meta-x11-errors.h" -#include "x11/meta-x11-display-private.h" -#include "x11/window-x11-private.h" -#include "x11/window-x11.h" -#include "x11/xprops.h" - -#ifndef HOST_NAME_MAX -/* Solaris headers apparently don't define this so do so manually; #326745 */ -#define HOST_NAME_MAX 255 -#endif - -typedef void (* ReloadValueFunc) (MetaWindow *window, - MetaPropValue *value, - gboolean initial); - -typedef enum -{ - NONE = 0, - LOAD_INIT = (1 << 0), - INCLUDE_OR = (1 << 1), - INIT_ONLY = (1 << 2), - FORCE_INIT = (1 << 3), -} MetaPropHookFlags; - -struct _MetaWindowPropHooks -{ - Atom property; - MetaPropValueType type; - ReloadValueFunc reload_func; - MetaPropHookFlags flags; -}; - -static void init_prop_value (MetaWindow *window, - MetaWindowPropHooks *hooks, - MetaPropValue *value); -static void reload_prop_value (MetaWindow *window, - MetaWindowPropHooks *hooks, - MetaPropValue *value, - gboolean initial); -static MetaWindowPropHooks *find_hooks (MetaX11Display *x11_display, - Atom property); - - -void -meta_window_reload_property_from_xwindow (MetaWindow *window, - Window xwindow, - Atom property, - gboolean initial) -{ - MetaPropValue value = { 0, }; - MetaWindowPropHooks *hooks; - - hooks = find_hooks (window->display->x11_display, property); - if (!hooks) - return; - - if ((hooks->flags & INIT_ONLY) && !initial) - return; - - init_prop_value (window, hooks, &value); - - meta_prop_get_values (window->display->x11_display, xwindow, - &value, 1); - - reload_prop_value (window, hooks, &value, - initial); - - meta_prop_free_values (&value, 1); -} - -static void -meta_window_reload_property (MetaWindow *window, - Atom property, - gboolean initial) -{ - meta_window_reload_property_from_xwindow (window, - window->xwindow, - property, - initial); -} - -void -meta_window_load_initial_properties (MetaWindow *window) -{ - int i, j; - MetaPropValue *values; - int n_properties = 0; - MetaX11Display *x11_display = window->display->x11_display; - - values = g_new0 (MetaPropValue, x11_display->n_prop_hooks); - - j = 0; - for (i = 0; i < x11_display->n_prop_hooks; i++) - { - MetaWindowPropHooks *hooks = &x11_display->prop_hooks_table[i]; - if (hooks->flags & LOAD_INIT) - { - init_prop_value (window, hooks, &values[j]); - ++j; - } - } - n_properties = j; - - meta_prop_get_values (window->display->x11_display, window->xwindow, - values, n_properties); - - j = 0; - for (i = 0; i < x11_display->n_prop_hooks; i++) - { - MetaWindowPropHooks *hooks = &x11_display->prop_hooks_table[i]; - if (hooks->flags & LOAD_INIT) - { - /* If we didn't actually manage to load anything then we don't need - * to call the reload function; this is different from a notification - * where disappearance of a previously present value is significant. - */ - if (values[j].type != META_PROP_VALUE_INVALID || - hooks->flags & FORCE_INIT) - reload_prop_value (window, hooks, &values[j], TRUE); - ++j; - } - } - - meta_prop_free_values (values, n_properties); - - g_free (values); -} - -/* Fill in the MetaPropValue used to get the value of "property" */ -static void -init_prop_value (MetaWindow *window, - MetaWindowPropHooks *hooks, - MetaPropValue *value) -{ - if (!hooks || hooks->type == META_PROP_VALUE_INVALID || - (window->override_redirect && !(hooks->flags & INCLUDE_OR))) - { - value->type = META_PROP_VALUE_INVALID; - value->atom = None; - } - else - { - value->type = hooks->type; - value->atom = hooks->property; - } -} - -static void -reload_prop_value (MetaWindow *window, - MetaWindowPropHooks *hooks, - MetaPropValue *value, - gboolean initial) -{ - if (!(window->override_redirect && !(hooks->flags & INCLUDE_OR))) - (* hooks->reload_func) (window, value, initial); -} - -static void -reload_wm_client_machine (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - g_free (window->wm_client_machine); - window->wm_client_machine = NULL; - - if (value->type != META_PROP_VALUE_INVALID) - window->wm_client_machine = g_strdup (value->v.str); - - meta_verbose ("Window has client machine \"%s\"", - window->wm_client_machine ? window->wm_client_machine : "unset"); - - if (window->wm_client_machine == NULL) - { - window->is_remote = FALSE; - } - else - { - char hostname[HOST_NAME_MAX + 1] = ""; - - gethostname (hostname, HOST_NAME_MAX + 1); - - window->is_remote = g_strcmp0 (window->wm_client_machine, hostname) != 0; - } -} - -static void -complain_about_broken_client (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - meta_warning ("Broken client! Window %s changed client leader window or SM client ID", - window->desc); -} - -static void -reload_net_wm_window_type (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - MetaX11Display *x11_display = window->display->x11_display; - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_private (window_x11); - - if (value->type != META_PROP_VALUE_INVALID) - { - int i; - - for (i = 0; i < value->v.atom_list.n_atoms; i++) - { - Atom atom = value->v.atom_list.atoms[i]; - - /* We break as soon as we find one we recognize, - * supposed to prefer those near the front of the list - */ - if (atom == x11_display->atom__NET_WM_WINDOW_TYPE_DESKTOP || - atom == x11_display->atom__NET_WM_WINDOW_TYPE_DOCK || - atom == x11_display->atom__NET_WM_WINDOW_TYPE_TOOLBAR || - atom == x11_display->atom__NET_WM_WINDOW_TYPE_MENU || - atom == x11_display->atom__NET_WM_WINDOW_TYPE_UTILITY || - atom == x11_display->atom__NET_WM_WINDOW_TYPE_SPLASH || - atom == x11_display->atom__NET_WM_WINDOW_TYPE_DIALOG || - atom == x11_display->atom__NET_WM_WINDOW_TYPE_DROPDOWN_MENU || - atom == x11_display->atom__NET_WM_WINDOW_TYPE_POPUP_MENU || - atom == x11_display->atom__NET_WM_WINDOW_TYPE_TOOLTIP || - atom == x11_display->atom__NET_WM_WINDOW_TYPE_NOTIFICATION || - atom == x11_display->atom__NET_WM_WINDOW_TYPE_COMBO || - atom == x11_display->atom__NET_WM_WINDOW_TYPE_DND || - atom == x11_display->atom__NET_WM_WINDOW_TYPE_NORMAL) - { - priv->type_atom = atom; - break; - } - } - } - - meta_window_x11_recalc_window_type (window); -} - -static void -reload_icon (MetaWindow *window, - Atom atom) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_private (window_x11); - - meta_icon_cache_property_changed (&priv->icon_cache, - window->display->x11_display, - atom); - meta_window_queue(window, META_QUEUE_UPDATE_ICON); -} - -static void -reload_net_wm_icon (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - reload_icon (window, window->display->x11_display->atom__NET_WM_ICON); -} - -static void -reload_kwm_win_icon (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - reload_icon (window, window->display->x11_display->atom__KWM_WIN_ICON); -} - -static void -reload_icon_geometry (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - if (value->type != META_PROP_VALUE_INVALID) - { - if (value->v.cardinal_list.n_cardinals != 4) - { - meta_verbose ("_NET_WM_ICON_GEOMETRY on %s has %d values instead of 4", - window->desc, value->v.cardinal_list.n_cardinals); - } - else - { - MetaRectangle geometry; - - geometry.x = (int)value->v.cardinal_list.cardinals[0]; - geometry.y = (int)value->v.cardinal_list.cardinals[1]; - geometry.width = (int)value->v.cardinal_list.cardinals[2]; - geometry.height = (int)value->v.cardinal_list.cardinals[3]; - - meta_window_set_icon_geometry (window, &geometry); - } - } - else - { - meta_window_set_icon_geometry (window, NULL); - } -} - -static void -meta_window_set_custom_frame_extents (MetaWindow *window, - GtkBorder *extents, - gboolean is_initial) -{ - if (extents) - { - if (window->has_custom_frame_extents && - memcmp (&window->custom_frame_extents, extents, sizeof (GtkBorder)) == 0) - return; - - window->has_custom_frame_extents = TRUE; - window->custom_frame_extents = *extents; - - /* If we're setting the frame extents on map, then this is telling - * us to adjust our understanding of the frame rect to match what - * GTK+ thinks it is. Future changes to the frame extents should - * trigger a resize and send a ConfigureRequest to the application. - */ - if (is_initial) - { - meta_window_client_rect_to_frame_rect (window, &window->rect, &window->rect); - meta_window_client_rect_to_frame_rect (window, &window->unconstrained_rect, &window->unconstrained_rect); - } - } - else - { - if (!window->has_custom_frame_extents) - return; - - window->has_custom_frame_extents = FALSE; - memset (&window->custom_frame_extents, 0, sizeof (window->custom_frame_extents)); - } - - meta_window_queue (window, META_QUEUE_MOVE_RESIZE); -} - -static void -reload_gtk_frame_extents (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - if (value->type != META_PROP_VALUE_INVALID) - { - if (value->v.cardinal_list.n_cardinals != 4) - { - meta_verbose ("_GTK_FRAME_EXTENTS on %s has %d values instead of 4", - window->desc, value->v.cardinal_list.n_cardinals); - } - else - { - GtkBorder extents; - extents.left = (int)value->v.cardinal_list.cardinals[0]; - extents.right = (int)value->v.cardinal_list.cardinals[1]; - extents.top = (int)value->v.cardinal_list.cardinals[2]; - extents.bottom = (int)value->v.cardinal_list.cardinals[3]; - meta_window_set_custom_frame_extents (window, &extents, initial); - } - } - else - { - meta_window_set_custom_frame_extents (window, NULL, initial); - } -} - -static void -reload_struts (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - meta_window_update_struts (window); -} - -static void -reload_wm_window_role (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - g_clear_pointer (&window->role, g_free); - if (value->type != META_PROP_VALUE_INVALID) - window->role = g_strdup (value->v.str); -} - -static void -reload_net_wm_user_time (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - if (value->type != META_PROP_VALUE_INVALID) - { - uint32_t cardinal = value->v.cardinal; - meta_window_set_user_time (window, cardinal); - } -} - -static void -reload_net_wm_user_time_window (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - if (value->type != META_PROP_VALUE_INVALID) - { - MetaWindow *prev_owner; - - /* Unregister old NET_WM_USER_TIME_WINDOW */ - if (window->user_time_window != None) - { - /* See the comment to the meta_display_register_x_window call below. */ - meta_x11_display_unregister_x_window (window->display->x11_display, - window->user_time_window); - /* Don't get events on not-managed windows */ - XSelectInput (window->display->x11_display->xdisplay, - window->user_time_window, - NoEventMask); - } - - /* Ensure the new user time window is not used on another MetaWindow, - * and unset its user time window if that is the case. - */ - prev_owner = meta_x11_display_lookup_x_window (window->display->x11_display, - value->v.xwindow); - if (prev_owner && prev_owner->user_time_window == value->v.xwindow) - { - meta_x11_display_unregister_x_window (window->display->x11_display, - value->v.xwindow); - prev_owner->user_time_window = None; - } - - /* Obtain the new NET_WM_USER_TIME_WINDOW and register it */ - window->user_time_window = value->v.xwindow; - if (window->user_time_window != None) - { - /* Kind of a hack; display.c:event_callback() ignores events - * for unknown windows. We make window->user_time_window - * known by registering it with window (despite the fact - * that window->xwindow is already registered with window). - * This basically means that property notifies to either the - * window->user_time_window or window->xwindow will be - * treated identically and will result in functions for - * window being called to update it. Maybe we should ignore - * any property notifies to window->user_time_window other - * than atom__NET_WM_USER_TIME ones, but I just don't care - * and it's not specified in the spec anyway. - */ - meta_x11_display_register_x_window (window->display->x11_display, - &window->user_time_window, - window); - /* Just listen for property notify events */ - XSelectInput (window->display->x11_display->xdisplay, - window->user_time_window, - PropertyChangeMask); - - /* Manually load the _NET_WM_USER_TIME field from the given window - * at this time as well. If the user_time_window ever broadens in - * scope, we'll probably want to load all relevant properties here. - */ - meta_window_reload_property_from_xwindow ( - window, - window->user_time_window, - window->display->x11_display->atom__NET_WM_USER_TIME, - initial); - } - } -} - -#define MAX_TITLE_LENGTH 512 - -/** - * set_title_text: - * - * Called by set_window_title() to set the value of @target to @title. - * If required and @atom is set, it will update the appropriate property. - * - * Returns: %TRUE if a new title was set. - */ -static gboolean -set_title_text (MetaWindow *window, - gboolean previous_was_modified, - const char *title, - Atom atom, - char **target) -{ - gboolean modified = FALSE; - - if (!target) - return FALSE; - - g_free (*target); - - if (!title) - *target = g_strdup (""); - else if (g_utf8_strlen (title, MAX_TITLE_LENGTH + 1) > MAX_TITLE_LENGTH) - { - *target = meta_g_utf8_strndup (title, MAX_TITLE_LENGTH); - modified = TRUE; - } - /* if WM_CLIENT_MACHINE indicates this machine is on a remote host - * lets place that hostname in the title */ - else if (meta_window_is_remote (window)) - { - *target = g_strdup_printf (_("%s (on %s)"), - title, window->wm_client_machine); - modified = TRUE; - } - else - *target = g_strdup (title); - - if (modified && atom != None) - meta_prop_set_utf8_string_hint (window->display->x11_display, - window->xwindow, - atom, *target); - - /* Bug 330671 -- Don't forget to clear _NET_WM_VISIBLE_(ICON_)NAME */ - if (!modified && previous_was_modified) - { - meta_x11_error_trap_push (window->display->x11_display); - XDeleteProperty (window->display->x11_display->xdisplay, - window->xwindow, - atom); - meta_x11_error_trap_pop (window->display->x11_display); - } - - return modified; -} - -static void -set_window_title (MetaWindow *window, - const char *title) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_private (window_x11); - - char *new_title = NULL; - - gboolean modified = - set_title_text (window, - priv->using_net_wm_visible_name, - title, - window->display->x11_display->atom__NET_WM_VISIBLE_NAME, - &new_title); - priv->using_net_wm_visible_name = modified; - - meta_window_set_title (window, new_title); - - g_free (new_title); -} - -static void -reload_net_wm_name (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_private (window_x11); - - if (value->type != META_PROP_VALUE_INVALID) - { - set_window_title (window, value->v.str); - priv->using_net_wm_name = TRUE; - - meta_verbose ("Using _NET_WM_NAME for new title of %s: \"%s\"", - window->desc, window->title); - } - else - { - set_window_title (window, NULL); - priv->using_net_wm_name = FALSE; - if (!initial) - meta_window_reload_property (window, XA_WM_NAME, FALSE); - } -} - -static void -reload_wm_name (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_private (window_x11); - - if (priv->using_net_wm_name) - { - meta_verbose ("Ignoring WM_NAME \"%s\" as _NET_WM_NAME is set", - value->v.str); - return; - } - - if (value->type != META_PROP_VALUE_INVALID) - { - set_window_title (window, value->v.str); - - meta_verbose ("Using WM_NAME for new title of %s: \"%s\"", - window->desc, window->title); - } - else - { - set_window_title (window, NULL); - } -} - -static void -meta_window_set_opaque_region (MetaWindow *window, - cairo_region_t *region) -{ - if (cairo_region_equal (window->opaque_region, region)) - return; - - g_clear_pointer (&window->opaque_region, cairo_region_destroy); - - if (region != NULL) - window->opaque_region = cairo_region_reference (region); - - meta_compositor_window_shape_changed (window->display->compositor, window); -} - -static void -reload_opaque_region (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - cairo_region_t *opaque_region = NULL; - - if (value->type != META_PROP_VALUE_INVALID) - { - uint32_t *region = value->v.cardinal_list.cardinals; - int nitems = value->v.cardinal_list.n_cardinals; - - cairo_rectangle_int_t *rects; - int i, rect_index, nrects; - - if (nitems % 4 != 0) - { - meta_verbose ("_NET_WM_OPAQUE_REGION does not have a list of 4-tuples."); - goto out; - } - - /* empty region */ - if (nitems == 0) - goto out; - - nrects = nitems / 4; - - rects = g_new (cairo_rectangle_int_t, nrects); - - rect_index = 0; - i = 0; - while (i < nitems) - { - cairo_rectangle_int_t *rect = &rects[rect_index]; - - rect->x = region[i++]; - rect->y = region[i++]; - rect->width = region[i++]; - rect->height = region[i++]; - - rect_index++; - } - - opaque_region = cairo_region_create_rectangles (rects, nrects); - - g_free (rects); - } - - out: - meta_window_set_opaque_region (window, opaque_region); - cairo_region_destroy (opaque_region); -} - -static void -reload_mutter_hints (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - if (value->type != META_PROP_VALUE_INVALID) - { - char *new_hints = value->v.str; - char *old_hints = window->mutter_hints; - gboolean changed = FALSE; - - if (new_hints) - { - if (!old_hints || strcmp (new_hints, old_hints)) - changed = TRUE; - } - else - { - if (old_hints) - changed = TRUE; - } - - if (changed) - { - g_free (old_hints); - - if (new_hints) - window->mutter_hints = g_strdup (new_hints); - else - window->mutter_hints = NULL; - - g_object_notify (G_OBJECT (window), "mutter-hints"); - } - } - else if (window->mutter_hints) - { - g_free (window->mutter_hints); - window->mutter_hints = NULL; - - g_object_notify (G_OBJECT (window), "mutter-hints"); - } -} - -static void -reload_net_wm_state (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - MetaX11Display *x11_display = window->display->x11_display; - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_private (window_x11); - - int i; - - /* We know this is only an initial window creation, - * clients don't change the property. - */ - - if (!initial) { - /* no, they DON'T change the property */ - meta_verbose ("Ignoring _NET_WM_STATE: we should be the one who set " - "the property in the first place"); - return; - } - - window->shaded = FALSE; - window->maximized_horizontally = FALSE; - window->maximized_vertically = FALSE; - window->fullscreen = FALSE; - priv->wm_state_modal = FALSE; - priv->wm_state_skip_taskbar = FALSE; - priv->wm_state_skip_pager = FALSE; - window->wm_state_above = FALSE; - window->wm_state_below = FALSE; - window->wm_state_demands_attention = FALSE; - - if (value->type == META_PROP_VALUE_INVALID) - return; - - i = 0; - while (i < value->v.atom_list.n_atoms) - { - if (value->v.atom_list.atoms[i] == x11_display->atom__NET_WM_STATE_SHADED) - window->shaded = TRUE; - else if (value->v.atom_list.atoms[i] == x11_display->atom__NET_WM_STATE_MAXIMIZED_HORZ) - window->maximize_horizontally_after_placement = TRUE; - else if (value->v.atom_list.atoms[i] == x11_display->atom__NET_WM_STATE_MAXIMIZED_VERT) - window->maximize_vertically_after_placement = TRUE; - else if (value->v.atom_list.atoms[i] == x11_display->atom__NET_WM_STATE_HIDDEN) - window->minimize_after_placement = TRUE; - else if (value->v.atom_list.atoms[i] == x11_display->atom__NET_WM_STATE_MODAL) - priv->wm_state_modal = TRUE; - else if (value->v.atom_list.atoms[i] == x11_display->atom__NET_WM_STATE_SKIP_TASKBAR) - priv->wm_state_skip_taskbar = TRUE; - else if (value->v.atom_list.atoms[i] == x11_display->atom__NET_WM_STATE_SKIP_PAGER) - priv->wm_state_skip_pager = TRUE; - else if (value->v.atom_list.atoms[i] == x11_display->atom__NET_WM_STATE_FULLSCREEN) - { - window->fullscreen = TRUE; - g_object_notify (G_OBJECT (window), "fullscreen"); - } - else if (value->v.atom_list.atoms[i] == x11_display->atom__NET_WM_STATE_ABOVE) - window->wm_state_above = TRUE; - else if (value->v.atom_list.atoms[i] == x11_display->atom__NET_WM_STATE_BELOW) - window->wm_state_below = TRUE; - else if (value->v.atom_list.atoms[i] == x11_display->atom__NET_WM_STATE_DEMANDS_ATTENTION) - window->wm_state_demands_attention = TRUE; - else if (value->v.atom_list.atoms[i] == x11_display->atom__NET_WM_STATE_STICKY) - window->on_all_workspaces_requested = TRUE; - - ++i; - } - - meta_verbose ("Reloaded _NET_WM_STATE for %s", - window->desc); - - meta_window_x11_recalc_window_type (window); - meta_window_recalc_features (window); -} - -static void -reload_mwm_hints (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - MotifWmHints *hints; - gboolean old_decorated = window->decorated; - - window->mwm_decorated = TRUE; - window->mwm_border_only = FALSE; - window->mwm_has_close_func = TRUE; - window->mwm_has_minimize_func = TRUE; - window->mwm_has_maximize_func = TRUE; - window->mwm_has_move_func = TRUE; - window->mwm_has_resize_func = TRUE; - - if (value->type == META_PROP_VALUE_INVALID) - { - meta_verbose ("Window %s has no MWM hints", window->desc); - meta_window_recalc_features (window); - return; - } - - hints = value->v.motif_hints; - - /* We support those MWM hints deemed non-stupid */ - - meta_verbose ("Window %s has MWM hints", - window->desc); - - if (hints->flags & MWM_HINTS_DECORATIONS) - { - meta_verbose ("Window %s sets MWM_HINTS_DECORATIONS 0x%x", - window->desc, hints->decorations); - - if (hints->decorations == 0) - window->mwm_decorated = FALSE; - /* some input methods use this */ - else if (hints->decorations == MWM_DECOR_BORDER) - window->mwm_border_only = TRUE; - } - else - meta_verbose ("Decorations flag unset"); - - if (hints->flags & MWM_HINTS_FUNCTIONS) - { - gboolean toggle_value; - - meta_verbose ("Window %s sets MWM_HINTS_FUNCTIONS 0x%x", - window->desc, hints->functions); - - /* If _ALL is specified, then other flags indicate what to turn off; - * if ALL is not specified, flags are what to turn on. - * at least, I think so - */ - - if ((hints->functions & MWM_FUNC_ALL) == 0) - { - toggle_value = TRUE; - - meta_verbose ("Window %s disables all funcs then reenables some", - window->desc); - window->mwm_has_close_func = FALSE; - window->mwm_has_minimize_func = FALSE; - window->mwm_has_maximize_func = FALSE; - window->mwm_has_move_func = FALSE; - window->mwm_has_resize_func = FALSE; - } - else - { - meta_verbose ("Window %s enables all funcs then disables some", - window->desc); - toggle_value = FALSE; - } - - if ((hints->functions & MWM_FUNC_CLOSE) != 0) - { - meta_verbose ("Window %s toggles close via MWM hints", - window->desc); - window->mwm_has_close_func = toggle_value; - } - if ((hints->functions & MWM_FUNC_MINIMIZE) != 0) - { - meta_verbose ("Window %s toggles minimize via MWM hints", - window->desc); - window->mwm_has_minimize_func = toggle_value; - } - if ((hints->functions & MWM_FUNC_MAXIMIZE) != 0) - { - meta_verbose ("Window %s toggles maximize via MWM hints", - window->desc); - window->mwm_has_maximize_func = toggle_value; - } - if ((hints->functions & MWM_FUNC_MOVE) != 0) - { - meta_verbose ("Window %s toggles move via MWM hints", - window->desc); - window->mwm_has_move_func = toggle_value; - } - if ((hints->functions & MWM_FUNC_RESIZE) != 0) - { - meta_verbose ("Window %s toggles resize via MWM hints", - window->desc); - window->mwm_has_resize_func = toggle_value; - } - } - else - { - meta_verbose ("Functions flag unset"); - } - - meta_window_recalc_features (window); - - /* We do all this anyhow at the end of meta_window_x11_new() */ - if (!window->constructing) - { - if (window->decorated) - meta_window_ensure_frame (window); - else - meta_window_destroy_frame (window); - - meta_window_queue (window, - META_QUEUE_MOVE_RESIZE | - /* because ensure/destroy frame may unmap: */ - META_QUEUE_CALC_SHOWING); - - if (old_decorated != window->decorated) - g_object_notify (G_OBJECT (window), "decorated"); - } -} - -static void -reload_wm_class (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - if (value->type != META_PROP_VALUE_INVALID) - { - g_autofree gchar *res_class = g_convert (value->v.class_hint.res_class, -1, - "UTF-8", "LATIN1", - NULL, NULL, NULL); - g_autofree gchar *res_name = g_convert (value->v.class_hint.res_name, -1, - "UTF-8", "LATIN1", - NULL, NULL, NULL); - meta_window_set_wm_class (window, res_class, res_name); - } - else - { - meta_window_set_wm_class (window, NULL, NULL); - } - - meta_verbose ("Window %s class: '%s' name: '%s'", - window->desc, - window->res_class ? window->res_class : "none", - window->res_name ? window->res_name : "none"); -} - -static void -reload_net_wm_desktop (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - if (value->type != META_PROP_VALUE_INVALID) - { - window->initial_workspace_set = TRUE; - window->initial_workspace = value->v.cardinal; - meta_topic (META_DEBUG_PLACEMENT, - "Read initial workspace prop %d for %s", - window->initial_workspace, window->desc); - } -} - -static void -reload_net_startup_id (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - guint32 timestamp = window->net_wm_user_time; - MetaWorkspace *workspace = NULL; - - g_free (window->startup_id); - - if (value->type != META_PROP_VALUE_INVALID) - window->startup_id = g_strdup (value->v.str); - else - window->startup_id = NULL; - - /* Update timestamp and workspace on a running window */ - if (!window->constructing) - { - window->initial_timestamp_set = 0; - window->initial_workspace_set = 0; - - if (meta_display_apply_startup_properties (window->display, window)) - { - - if (window->initial_timestamp_set) - timestamp = window->initial_timestamp; - if (window->initial_workspace_set) - workspace = meta_workspace_manager_get_workspace_by_index (workspace_manager, - window->initial_workspace); - - meta_window_activate_with_workspace (window, timestamp, workspace); - } - } - - meta_verbose ("New _NET_STARTUP_ID \"%s\" for %s", - window->startup_id ? window->startup_id : "unset", - window->desc); -} - -static void -reload_update_counter (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - if (value->type != META_PROP_VALUE_INVALID) - { - meta_window_x11_destroy_sync_request_alarm (window); - window->sync_request_counter = None; - - if (value->v.xcounter_list.n_counters == 0) - { - meta_warning ("_NET_WM_SYNC_REQUEST_COUNTER is empty"); - return; - } - - if (value->v.xcounter_list.n_counters == 1) - { - window->sync_request_counter = value->v.xcounter_list.counters[0]; - window->extended_sync_request_counter = FALSE; - } - else - { - window->sync_request_counter = value->v.xcounter_list.counters[1]; - window->extended_sync_request_counter = TRUE; - } - meta_verbose ("Window has _NET_WM_SYNC_REQUEST_COUNTER 0x%lx (extended=%s)", - window->sync_request_counter, - window->extended_sync_request_counter ? "true" : "false"); - - if (window->extended_sync_request_counter) - meta_window_x11_create_sync_request_alarm (window); - } -} - -#define FLAG_IS_ON(hints,flag) \ - (((hints)->flags & (flag)) != 0) - -#define FLAG_IS_OFF(hints,flag) \ - (((hints)->flags & (flag)) == 0) - -#define FLAG_TOGGLED_ON(old,new,flag) \ - (FLAG_IS_OFF(old,flag) && \ - FLAG_IS_ON(new,flag)) - -#define FLAG_TOGGLED_OFF(old,new,flag) \ - (FLAG_IS_ON(old,flag) && \ - FLAG_IS_OFF(new,flag)) - -#define FLAG_CHANGED(old,new,flag) \ - (FLAG_TOGGLED_ON(old,new,flag) || FLAG_TOGGLED_OFF(old,new,flag)) - -static void -spew_size_hints_differences (const XSizeHints *old, - const XSizeHints *new) -{ - if (FLAG_CHANGED (old, new, USPosition)) - meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: USPosition now %s", - FLAG_TOGGLED_ON (old, new, USPosition) ? "set" : "unset"); - if (FLAG_CHANGED (old, new, USSize)) - meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: USSize now %s", - FLAG_TOGGLED_ON (old, new, USSize) ? "set" : "unset"); - if (FLAG_CHANGED (old, new, PPosition)) - meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PPosition now %s", - FLAG_TOGGLED_ON (old, new, PPosition) ? "set" : "unset"); - if (FLAG_CHANGED (old, new, PSize)) - meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PSize now %s", - FLAG_TOGGLED_ON (old, new, PSize) ? "set" : "unset"); - if (FLAG_CHANGED (old, new, PMinSize)) - meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PMinSize now %s (%d x %d -> %d x %d)", - FLAG_TOGGLED_ON (old, new, PMinSize) ? "set" : "unset", - old->min_width, old->min_height, - new->min_width, new->min_height); - if (FLAG_CHANGED (old, new, PMaxSize)) - meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PMaxSize now %s (%d x %d -> %d x %d)", - FLAG_TOGGLED_ON (old, new, PMaxSize) ? "set" : "unset", - old->max_width, old->max_height, - new->max_width, new->max_height); - if (FLAG_CHANGED (old, new, PResizeInc)) - meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PResizeInc now %s (width_inc %d -> %d height_inc %d -> %d)", - FLAG_TOGGLED_ON (old, new, PResizeInc) ? "set" : "unset", - old->width_inc, new->width_inc, - old->height_inc, new->height_inc); - if (FLAG_CHANGED (old, new, PAspect)) - meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PAspect now %s (min %d/%d -> %d/%d max %d/%d -> %d/%d)", - FLAG_TOGGLED_ON (old, new, PAspect) ? "set" : "unset", - old->min_aspect.x, old->min_aspect.y, - new->min_aspect.x, new->min_aspect.y, - old->max_aspect.x, old->max_aspect.y, - new->max_aspect.x, new->max_aspect.y); - if (FLAG_CHANGED (old, new, PBaseSize)) - meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PBaseSize now %s (%d x %d -> %d x %d)", - FLAG_TOGGLED_ON (old, new, PBaseSize) ? "set" : "unset", - old->base_width, old->base_height, - new->base_width, new->base_height); - if (FLAG_CHANGED (old, new, PWinGravity)) - meta_topic (META_DEBUG_GEOMETRY, "XSizeHints: PWinGravity now %s (%d -> %d)", - FLAG_TOGGLED_ON (old, new, PWinGravity) ? "set" : "unset", - old->win_gravity, new->win_gravity); -} - -static gboolean -hints_have_changed (const XSizeHints *old, - const XSizeHints *new) -{ - /* 1. Check if the relevant values have changed if the flag is set. */ - - if (FLAG_TOGGLED_ON (old, new, USPosition) || - (FLAG_IS_ON (new, USPosition) && - (old->x != new->x || - old->y != new->y))) - return TRUE; - - if (FLAG_TOGGLED_ON (old, new, USSize) || - (FLAG_IS_ON (new, USSize) && - (old->width != new->width || - old->height != new->height))) - return TRUE; - - if (FLAG_TOGGLED_ON (old, new, PPosition) || - (FLAG_IS_ON (new, PPosition) && - (old->x != new->x || - old->y != new->y))) - return TRUE; - - if (FLAG_TOGGLED_ON (old, new, PSize) || - (FLAG_IS_ON (new, PSize) && - (old->width != new->width || - old->height != new->height))) - return TRUE; - - if (FLAG_TOGGLED_ON (old, new, PMinSize) || - (FLAG_IS_ON (new, PMinSize) && - (old->min_width != new->min_width || - old->min_height != new->min_height))) - return TRUE; - - if (FLAG_TOGGLED_ON (old, new, PMaxSize) || - (FLAG_IS_ON (new, PMaxSize) && - (old->max_width != new->max_width || - old->max_height != new->max_height))) - return TRUE; - - if (FLAG_TOGGLED_ON (old, new, PResizeInc) || - (FLAG_IS_ON (new, PResizeInc) && - (old->width_inc != new->width_inc || - old->height_inc != new->height_inc))) - return TRUE; - - if (FLAG_TOGGLED_ON (old, new, PAspect) || - (FLAG_IS_ON (new, PAspect) && - (old->min_aspect.x != new->min_aspect.x || - old->min_aspect.y != new->min_aspect.y || - old->max_aspect.x != new->max_aspect.x || - old->max_aspect.y != new->max_aspect.y))) - return TRUE; - - if (FLAG_TOGGLED_ON (old, new, PBaseSize) || - (FLAG_IS_ON (new, PBaseSize) && - (old->base_width != new->base_width || - old->base_height != new->base_height))) - return TRUE; - - if (FLAG_TOGGLED_ON (old, new, PWinGravity) || - (FLAG_IS_ON (new, PWinGravity) && - (old->win_gravity != new->win_gravity))) - return TRUE; - - /* 2. Check if the flags have been unset. */ - return FLAG_TOGGLED_OFF (old, new, USPosition) || - FLAG_TOGGLED_OFF (old, new, USSize) || - FLAG_TOGGLED_OFF (old, new, PPosition) || - FLAG_TOGGLED_OFF (old, new, PSize) || - FLAG_TOGGLED_OFF (old, new, PMinSize) || - FLAG_TOGGLED_OFF (old, new, PMaxSize) || - FLAG_TOGGLED_OFF (old, new, PResizeInc) || - FLAG_TOGGLED_OFF (old, new, PAspect) || - FLAG_TOGGLED_OFF (old, new, PBaseSize) || - FLAG_TOGGLED_OFF (old, new, PWinGravity); -} - -void -meta_set_normal_hints (MetaWindow *window, - XSizeHints *hints) -{ - int x, y, w, h; - double minr, maxr; - /* Some convenience vars */ - int minw, minh, maxw, maxh; /* min/max width/height */ - int basew, baseh, winc, hinc; /* base width/height, width/height increment */ - - /* Save the last ConfigureRequest, which we put here. - * Values here set in the hints are supposed to - * be ignored. - */ - x = window->size_hints.x; - y = window->size_hints.y; - w = window->size_hints.width; - h = window->size_hints.height; - - /* as far as I can tell, value->v.size_hints.flags is just to - * check whether we had old-style normal hints without gravity, - * base size as returned by XGetNormalHints(), so we don't - * really use it as we fixup window->size_hints to have those - * fields if they're missing. - */ - - /* - * When the window is first created, NULL hints will - * be passed in which will initialize all of the fields - * as if flags were zero - */ - if (hints) - window->size_hints = *hints; - else - window->size_hints.flags = 0; - - /* Put back saved ConfigureRequest. */ - window->size_hints.x = x; - window->size_hints.y = y; - window->size_hints.width = w; - window->size_hints.height = h; - - /* Get base size hints */ - if (window->size_hints.flags & PBaseSize) - { - meta_topic (META_DEBUG_GEOMETRY, "Window %s sets base size %d x %d", - window->desc, - window->size_hints.base_width, - window->size_hints.base_height); - } - else if (window->size_hints.flags & PMinSize) - { - window->size_hints.base_width = window->size_hints.min_width; - window->size_hints.base_height = window->size_hints.min_height; - } - else - { - window->size_hints.base_width = 0; - window->size_hints.base_height = 0; - } - window->size_hints.flags |= PBaseSize; - - /* Get min size hints */ - if (window->size_hints.flags & PMinSize) - { - meta_topic (META_DEBUG_GEOMETRY, "Window %s sets min size %d x %d", - window->desc, - window->size_hints.min_width, - window->size_hints.min_height); - } - else if (window->size_hints.flags & PBaseSize) - { - window->size_hints.min_width = window->size_hints.base_width; - window->size_hints.min_height = window->size_hints.base_height; - } - else - { - window->size_hints.min_width = 0; - window->size_hints.min_height = 0; - } - window->size_hints.flags |= PMinSize; - - /* Get max size hints */ - if (window->size_hints.flags & PMaxSize) - { - meta_topic (META_DEBUG_GEOMETRY, "Window %s sets max size %d x %d", - window->desc, - window->size_hints.max_width, - window->size_hints.max_height); - } - else - { - window->size_hints.max_width = G_MAXINT; - window->size_hints.max_height = G_MAXINT; - window->size_hints.flags |= PMaxSize; - } - - /* Get resize increment hints */ - if (window->size_hints.flags & PResizeInc) - { - meta_topic (META_DEBUG_GEOMETRY, - "Window %s sets resize width inc: %d height inc: %d", - window->desc, - window->size_hints.width_inc, - window->size_hints.height_inc); - } - else - { - window->size_hints.width_inc = 1; - window->size_hints.height_inc = 1; - window->size_hints.flags |= PResizeInc; - } - - /* Get aspect ratio hints */ - if (window->size_hints.flags & PAspect) - { - meta_topic (META_DEBUG_GEOMETRY, - "Window %s sets min_aspect: %d/%d max_aspect: %d/%d", - window->desc, - window->size_hints.min_aspect.x, - window->size_hints.min_aspect.y, - window->size_hints.max_aspect.x, - window->size_hints.max_aspect.y); - } - else - { - window->size_hints.min_aspect.x = 1; - window->size_hints.min_aspect.y = G_MAXINT; - window->size_hints.max_aspect.x = G_MAXINT; - window->size_hints.max_aspect.y = 1; - window->size_hints.flags |= PAspect; - } - - /* Get gravity hint */ - if (window->size_hints.flags & PWinGravity) - { - meta_topic (META_DEBUG_GEOMETRY, "Window %s sets gravity %d", - window->desc, - window->size_hints.win_gravity); - } - else - { - meta_topic (META_DEBUG_GEOMETRY, - "Window %s doesn't set gravity, using NW", - window->desc); - window->size_hints.win_gravity = META_GRAVITY_NORTH_WEST; - window->size_hints.flags |= PWinGravity; - } - - /*** Lots of sanity checking ***/ - - /* Verify all min & max hints are at least 1 pixel */ - if (window->size_hints.min_width < 1) - { - /* someone is on crack */ - meta_topic (META_DEBUG_GEOMETRY, - "Window %s sets min width to 0, which makes no sense", - window->desc); - window->size_hints.min_width = 1; - } - if (window->size_hints.max_width < 1) - { - /* another cracksmoker */ - meta_topic (META_DEBUG_GEOMETRY, - "Window %s sets max width to 0, which makes no sense", - window->desc); - window->size_hints.max_width = 1; - } - if (window->size_hints.min_height < 1) - { - /* another cracksmoker */ - meta_topic (META_DEBUG_GEOMETRY, - "Window %s sets min height to 0, which makes no sense", - window->desc); - window->size_hints.min_height = 1; - } - if (window->size_hints.max_height < 1) - { - /* another cracksmoker */ - meta_topic (META_DEBUG_GEOMETRY, - "Window %s sets max height to 0, which makes no sense", - window->desc); - window->size_hints.max_height = 1; - } - - /* Verify size increment hints are at least 1 pixel */ - if (window->size_hints.width_inc < 1) - { - /* app authors find so many ways to smoke crack */ - window->size_hints.width_inc = 1; - meta_topic (META_DEBUG_GEOMETRY, "Corrected 0 width_inc to 1"); - } - if (window->size_hints.height_inc < 1) - { - /* another cracksmoker */ - window->size_hints.height_inc = 1; - meta_topic (META_DEBUG_GEOMETRY, "Corrected 0 height_inc to 1"); - } - /* divide by 0 cracksmokers; note that x & y in (min|max)_aspect are - * numerator & denominator - */ - if (window->size_hints.min_aspect.y < 1) - window->size_hints.min_aspect.y = 1; - if (window->size_hints.max_aspect.y < 1) - window->size_hints.max_aspect.y = 1; - - minw = window->size_hints.min_width; minh = window->size_hints.min_height; - maxw = window->size_hints.max_width; maxh = window->size_hints.max_height; - basew = window->size_hints.base_width; baseh = window->size_hints.base_height; - winc = window->size_hints.width_inc; hinc = window->size_hints.height_inc; - - /* Make sure min and max size hints are consistent with the base + increment - * size hints. If they're not, it's not a real big deal, but it means the - * effective min and max size are more restrictive than the application - * specified values. - */ - if ((minw - basew) % winc != 0) - { - /* Take advantage of integer division throwing away the remainder... */ - window->size_hints.min_width = basew + ((minw - basew)/winc + 1)*winc; - - meta_topic (META_DEBUG_GEOMETRY, - "Window %s has width_inc (%d) that does not evenly divide " - "min_width - base_width (%d - %d); thus effective " - "min_width is really %d", - window->desc, - winc, minw, basew, window->size_hints.min_width); - minw = window->size_hints.min_width; - } - if (maxw != G_MAXINT && (maxw - basew) % winc != 0) - { - /* Take advantage of integer division throwing away the remainder... */ - window->size_hints.max_width = basew + ((maxw - basew)/winc)*winc; - - meta_topic (META_DEBUG_GEOMETRY, - "Window %s has width_inc (%d) that does not evenly divide " - "max_width - base_width (%d - %d); thus effective " - "max_width is really %d", - window->desc, - winc, maxw, basew, window->size_hints.max_width); - maxw = window->size_hints.max_width; - } - if ((minh - baseh) % hinc != 0) - { - /* Take advantage of integer division throwing away the remainder... */ - window->size_hints.min_height = baseh + ((minh - baseh)/hinc + 1)*hinc; - - meta_topic (META_DEBUG_GEOMETRY, - "Window %s has height_inc (%d) that does not evenly divide " - "min_height - base_height (%d - %d); thus effective " - "min_height is really %d", - window->desc, - hinc, minh, baseh, window->size_hints.min_height); - minh = window->size_hints.min_height; - } - if (maxh != G_MAXINT && (maxh - baseh) % hinc != 0) - { - /* Take advantage of integer division throwing away the remainder... */ - window->size_hints.max_height = baseh + ((maxh - baseh)/hinc)*hinc; - - meta_topic (META_DEBUG_GEOMETRY, - "Window %s has height_inc (%d) that does not evenly divide " - "max_height - base_height (%d - %d); thus effective " - "max_height is really %d", - window->desc, - hinc, maxh, baseh, window->size_hints.max_height); - maxh = window->size_hints.max_height; - } - - /* make sure maximum size hints are compatible with minimum size hints; min - * size hints take precedence. - */ - if (window->size_hints.max_width < window->size_hints.min_width) - { - /* another cracksmoker */ - meta_topic (META_DEBUG_GEOMETRY, - "Window %s sets max width %d less than min width %d, " - "disabling resize", - window->desc, - window->size_hints.max_width, - window->size_hints.min_width); - maxw = window->size_hints.max_width = window->size_hints.min_width; - } - if (window->size_hints.max_height < window->size_hints.min_height) - { - /* another cracksmoker */ - meta_topic (META_DEBUG_GEOMETRY, - "Window %s sets max height %d less than min height %d, " - "disabling resize", - window->desc, - window->size_hints.max_height, - window->size_hints.min_height); - maxh = window->size_hints.max_height = window->size_hints.min_height; - } - - /* Make sure the aspect ratio hints are sane. */ - minr = window->size_hints.min_aspect.x / - (double)window->size_hints.min_aspect.y; - maxr = window->size_hints.max_aspect.x / - (double)window->size_hints.max_aspect.y; - if (minr > maxr) - { - /* another cracksmoker; not even minimally (self) consistent */ - meta_topic (META_DEBUG_GEOMETRY, - "Window %s sets min aspect ratio larger than max aspect " - "ratio; disabling aspect ratio constraints.", - window->desc); - window->size_hints.min_aspect.x = 1; - window->size_hints.min_aspect.y = G_MAXINT; - window->size_hints.max_aspect.x = G_MAXINT; - window->size_hints.max_aspect.y = 1; - } - else /* check consistency of aspect ratio hints with other hints */ - { - if (minh > 0 && minr > (maxw / (double)minh)) - { - /* another cracksmoker */ - meta_topic (META_DEBUG_GEOMETRY, - "Window %s sets min aspect ratio larger than largest " - "aspect ratio possible given min/max size constraints; " - "disabling min aspect ratio constraint.", - window->desc); - window->size_hints.min_aspect.x = 1; - window->size_hints.min_aspect.y = G_MAXINT; - } - if (maxr < (minw / (double)maxh)) - { - /* another cracksmoker */ - meta_topic (META_DEBUG_GEOMETRY, - "Window %s sets max aspect ratio smaller than smallest " - "aspect ratio possible given min/max size constraints; " - "disabling max aspect ratio constraint.", - window->desc); - window->size_hints.max_aspect.x = G_MAXINT; - window->size_hints.max_aspect.y = 1; - } - /* FIXME: Would be nice to check that aspect ratios are - * consistent with base and size increment constraints. - */ - } -} - -static void -reload_normal_hints (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - if (value->type != META_PROP_VALUE_INVALID) - { - XSizeHints old_hints; - gboolean hints_have_differences; - - meta_topic (META_DEBUG_GEOMETRY, "Updating WM_NORMAL_HINTS for %s", window->desc); - - old_hints = window->size_hints; - - meta_set_normal_hints (window, value->v.size_hints.hints); - - hints_have_differences = hints_have_changed (&old_hints, - &window->size_hints); - if (hints_have_differences) - { - spew_size_hints_differences (&old_hints, &window->size_hints); - meta_window_recalc_features (window); - - if (!initial) - meta_window_queue (window, META_QUEUE_MOVE_RESIZE); - } - } -} - -static void -reload_wm_protocols (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - int i; - - meta_window_x11_set_wm_take_focus (window, FALSE); - meta_window_x11_set_wm_ping (window, FALSE); - meta_window_x11_set_wm_delete_window (window, FALSE); - - if (value->type == META_PROP_VALUE_INVALID) - return; - - i = 0; - while (i < value->v.atom_list.n_atoms) - { - if (value->v.atom_list.atoms[i] == - window->display->x11_display->atom_WM_TAKE_FOCUS) - meta_window_x11_set_wm_take_focus (window, TRUE); - else if (value->v.atom_list.atoms[i] == - window->display->x11_display->atom_WM_DELETE_WINDOW) - meta_window_x11_set_wm_delete_window (window, TRUE); - else if (value->v.atom_list.atoms[i] == - window->display->x11_display->atom__NET_WM_PING) - meta_window_x11_set_wm_ping (window, TRUE); - ++i; - } - - meta_verbose ("New _NET_STARTUP_ID \"%s\" for %s", - window->startup_id ? window->startup_id : "unset", - window->desc); -} - -static void -reload_wm_hints (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_private (window_x11); - Window old_group_leader; - gboolean urgent; - - old_group_leader = window->xgroup_leader; - - /* Fill in defaults */ - window->input = TRUE; - window->initially_iconic = FALSE; - window->xgroup_leader = None; - priv->wm_hints_pixmap = None; - priv->wm_hints_mask = None; - urgent = FALSE; - - if (value->type != META_PROP_VALUE_INVALID) - { - const XWMHints *hints = value->v.wm_hints; - - if (hints->flags & InputHint) - window->input = hints->input; - - if (hints->flags & StateHint) - window->initially_iconic = (hints->initial_state == IconicState); - - if (hints->flags & WindowGroupHint) - window->xgroup_leader = hints->window_group; - - if (hints->flags & IconPixmapHint) - priv->wm_hints_pixmap = hints->icon_pixmap; - - if (hints->flags & IconMaskHint) - priv->wm_hints_mask = hints->icon_mask; - - if (hints->flags & XUrgencyHint) - urgent = TRUE; - - meta_verbose ("Read WM_HINTS input: %d iconic: %d group leader: 0x%lx pixmap: 0x%lx mask: 0x%lx", - window->input, window->initially_iconic, - window->xgroup_leader, - priv->wm_hints_pixmap, - priv->wm_hints_mask); - } - - if (window->xgroup_leader != old_group_leader) - { - meta_verbose ("Window %s changed its group leader to 0x%lx", - window->desc, window->xgroup_leader); - - meta_window_group_leader_changed (window); - } - - meta_window_set_urgent (window, urgent); - - meta_icon_cache_property_changed (&priv->icon_cache, - window->display->x11_display, - XA_WM_HINTS); - - meta_window_queue (window, META_QUEUE_UPDATE_ICON | META_QUEUE_MOVE_RESIZE); -} - -static gboolean -check_xtransient_for_loop (MetaWindow *window, - MetaWindow *parent) -{ - while (parent) - { - if (parent == window) - return TRUE; - - parent = meta_x11_display_lookup_x_window (parent->display->x11_display, - parent->xtransient_for); - } - - return FALSE; -} - -static void -reload_transient_for (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - MetaWindow *parent = NULL; - Window transient_for; - - if (value->type != META_PROP_VALUE_INVALID) - { - transient_for = value->v.xwindow; - - parent = meta_x11_display_lookup_x_window (window->display->x11_display, - transient_for); - if (!parent) - { - meta_warning ("Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.", - transient_for, window->desc); - transient_for = None; - } - else if (parent->override_redirect) - { - const gchar *window_kind = window->override_redirect ? - "override-redirect" : "top-level"; - - if (parent->xtransient_for != None) - { - /* We don't have to go through the parents, as per this code it is - * not possible that a window has the WM_TRANSIENT_FOR set to an - * override-redirect window anyways */ - meta_warning ("WM_TRANSIENT_FOR window %s for %s window %s is an " - "override-redirect window and this is not correct " - "according to the standard, so we'll fallback to " - "the first non-override-redirect window 0x%lx.", - parent->desc, window->desc, window_kind, - parent->xtransient_for); - transient_for = parent->xtransient_for; - parent = - meta_x11_display_lookup_x_window (parent->display->x11_display, - transient_for); - } - else - { - meta_warning ("WM_TRANSIENT_FOR window %s for %s window %s is an " - "override-redirect window and this is not correct " - "according to the standard, so we'll fallback to " - "the root window.", parent->desc, window_kind, - window->desc); - transient_for = parent->display->x11_display->xroot; - parent = NULL; - } - } - - /* Make sure there is not a loop */ - if (check_xtransient_for_loop (window, parent)) - { - meta_warning ("WM_TRANSIENT_FOR window 0x%lx for %s would create a " - "loop.", transient_for, window->desc); - transient_for = None; - } - } - else - transient_for = None; - - if (transient_for == window->xtransient_for) - return; - - window->xtransient_for = transient_for; - - if (window->xtransient_for != None) - meta_verbose ("Window %s transient for 0x%lx", window->desc, window->xtransient_for); - else - meta_verbose ("Window %s is not transient", window->desc); - - if (window->xtransient_for == None || - window->xtransient_for == window->display->x11_display->xroot) - meta_window_set_transient_for (window, NULL); - else - { - meta_window_set_transient_for (window, parent); - } -} - -static void -reload_gtk_theme_variant (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - char *requested_variant = NULL; - char *current_variant = window->gtk_theme_variant; - - if (value->type != META_PROP_VALUE_INVALID) - { - requested_variant = value->v.str; - meta_verbose ("Requested \"%s\" theme variant for window %s.", - requested_variant, window->desc); - } - - if (g_strcmp0 (requested_variant, current_variant) != 0) - { - g_free (current_variant); - - window->gtk_theme_variant = g_strdup (requested_variant); - - if (window->frame) - meta_frame_update_style (window->frame); - } -} - -static void -reload_bypass_compositor (MetaWindow *window, - MetaPropValue *value, - gboolean initial) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_private (window_x11); - MetaBypassCompositorHint requested_value; - MetaBypassCompositorHint current_value; - - if (value->type != META_PROP_VALUE_INVALID) - requested_value = (MetaBypassCompositorHint) value->v.cardinal; - else - requested_value = META_BYPASS_COMPOSITOR_HINT_AUTO; - - current_value = priv->bypass_compositor; - if (requested_value == current_value) - return; - - if (requested_value == META_BYPASS_COMPOSITOR_HINT_ON) - meta_verbose ("Request to bypass compositor for window %s.", window->desc); - else if (requested_value == META_BYPASS_COMPOSITOR_HINT_OFF) - meta_verbose ("Request to don't bypass compositor for window %s.", window->desc); - else if (requested_value != META_BYPASS_COMPOSITOR_HINT_AUTO) - return; - - priv->bypass_compositor = requested_value; -} - -static void -reload_window_opacity (MetaWindow *window, - MetaPropValue *value, - gboolean initial) - -{ - guint8 opacity = 0xFF; - - if (value->type != META_PROP_VALUE_INVALID) - opacity = (guint8)((gfloat)value->v.cardinal * 255.0 / ((gfloat)0xffffffff)); - - meta_window_set_opacity (window, opacity); -} - -#define RELOAD_STRING(var_name, propname) \ - static void \ - reload_ ## var_name (MetaWindow *window, \ - MetaPropValue *value, \ - gboolean initial) \ - { \ - g_free (window->var_name); \ - \ - if (value->type != META_PROP_VALUE_INVALID) \ - window->var_name = g_strdup (value->v.str); \ - else \ - window->var_name = NULL; \ - \ - g_object_notify (G_OBJECT (window), propname); \ - } - -RELOAD_STRING (gtk_unique_bus_name, "gtk-unique-bus-name") -RELOAD_STRING (gtk_application_id, "gtk-application-id") -RELOAD_STRING (gtk_application_object_path, "gtk-application-object-path") -RELOAD_STRING (gtk_window_object_path, "gtk-window-object-path") -RELOAD_STRING (gtk_app_menu_object_path, "gtk-app-menu-object-path") -RELOAD_STRING (gtk_menubar_object_path, "gtk-menubar-object-path") - -#undef RELOAD_STRING - -/** - * meta_x11_display_init_window_prop_hooks: - * @x11_display: The #MetaDX11isplay - * - * Initialises the property hooks system. Each row in the table named "hooks" - * represents an action to take when a property is found on a newly-created - * window, or when a property changes its value. - * - * The first column shows which atom the row concerns. - * The second gives the type of the property data. The property will be - * queried for its new value, unless the type is given as - * META_PROP_VALUE_INVALID, in which case nothing will be queried. - * The third column gives the name of a callback which gets called with the - * new value. (If the new value was not retrieved because the second column - * was META_PROP_VALUE_INVALID, the callback still gets called anyway.) - * This value may be NULL, in which case no callback will be called. - */ -void -meta_x11_display_init_window_prop_hooks (MetaX11Display *x11_display) -{ - /* The ordering here is significant for the properties we load - * initially: they are roughly ordered in the order we want them to - * be gotten. We want to get window name and class first so we can - * use them in error messages and such. However, name is modified - * depending on wm_client_machine, so push it slightly sooner. - * - * For override-redirect windows, we pay attention to: - * - * - properties that identify the window: useful for debugging - * purposes. - * - NET_WM_WINDOW_TYPE: can be used to do appropriate handling - * for different types of override-redirect windows. - */ - MetaWindowPropHooks hooks[] = { - { x11_display->atom_WM_CLIENT_MACHINE, META_PROP_VALUE_STRING, reload_wm_client_machine, LOAD_INIT | INCLUDE_OR }, - { x11_display->atom__NET_WM_NAME, META_PROP_VALUE_UTF8, reload_net_wm_name, LOAD_INIT | INCLUDE_OR }, - { XA_WM_CLASS, META_PROP_VALUE_CLASS_HINT, reload_wm_class, LOAD_INIT | INCLUDE_OR }, - { XA_WM_NAME, META_PROP_VALUE_TEXT_PROPERTY, reload_wm_name, LOAD_INIT | INCLUDE_OR }, - { x11_display->atom__MUTTER_HINTS, META_PROP_VALUE_TEXT_PROPERTY, reload_mutter_hints, LOAD_INIT | INCLUDE_OR }, - { x11_display->atom__NET_WM_OPAQUE_REGION, META_PROP_VALUE_CARDINAL_LIST, reload_opaque_region, LOAD_INIT | INCLUDE_OR }, - { x11_display->atom__NET_WM_DESKTOP, META_PROP_VALUE_CARDINAL, reload_net_wm_desktop, LOAD_INIT | INIT_ONLY }, - { x11_display->atom__NET_STARTUP_ID, META_PROP_VALUE_UTF8, reload_net_startup_id, LOAD_INIT }, - { x11_display->atom__NET_WM_SYNC_REQUEST_COUNTER, META_PROP_VALUE_SYNC_COUNTER_LIST, reload_update_counter, LOAD_INIT | INCLUDE_OR }, - { XA_WM_NORMAL_HINTS, META_PROP_VALUE_SIZE_HINTS, reload_normal_hints, LOAD_INIT }, - { x11_display->atom_WM_PROTOCOLS, META_PROP_VALUE_ATOM_LIST, reload_wm_protocols, LOAD_INIT }, - { XA_WM_HINTS, META_PROP_VALUE_WM_HINTS, reload_wm_hints, LOAD_INIT }, - { x11_display->atom__NET_WM_USER_TIME, META_PROP_VALUE_CARDINAL, reload_net_wm_user_time, LOAD_INIT }, - { x11_display->atom__NET_WM_STATE, META_PROP_VALUE_ATOM_LIST, reload_net_wm_state, LOAD_INIT | INIT_ONLY }, - { x11_display->atom__MOTIF_WM_HINTS, META_PROP_VALUE_MOTIF_HINTS, reload_mwm_hints, LOAD_INIT }, - { XA_WM_TRANSIENT_FOR, META_PROP_VALUE_WINDOW, reload_transient_for, LOAD_INIT | INCLUDE_OR }, - { x11_display->atom__GTK_THEME_VARIANT, META_PROP_VALUE_UTF8, reload_gtk_theme_variant, LOAD_INIT }, - { x11_display->atom__GTK_APPLICATION_ID, META_PROP_VALUE_UTF8, reload_gtk_application_id, LOAD_INIT }, - { x11_display->atom__GTK_UNIQUE_BUS_NAME, META_PROP_VALUE_UTF8, reload_gtk_unique_bus_name, LOAD_INIT }, - { x11_display->atom__GTK_APPLICATION_OBJECT_PATH, META_PROP_VALUE_UTF8, reload_gtk_application_object_path, LOAD_INIT }, - { x11_display->atom__GTK_WINDOW_OBJECT_PATH, META_PROP_VALUE_UTF8, reload_gtk_window_object_path, LOAD_INIT }, - { x11_display->atom__GTK_APP_MENU_OBJECT_PATH, META_PROP_VALUE_UTF8, reload_gtk_app_menu_object_path, LOAD_INIT }, - { x11_display->atom__GTK_MENUBAR_OBJECT_PATH, META_PROP_VALUE_UTF8, reload_gtk_menubar_object_path, LOAD_INIT }, - { x11_display->atom__GTK_FRAME_EXTENTS, META_PROP_VALUE_CARDINAL_LIST,reload_gtk_frame_extents, LOAD_INIT }, - { x11_display->atom__NET_WM_USER_TIME_WINDOW, META_PROP_VALUE_WINDOW, reload_net_wm_user_time_window, LOAD_INIT }, - { x11_display->atom__NET_WM_ICON, META_PROP_VALUE_INVALID, reload_net_wm_icon, NONE }, - { x11_display->atom__KWM_WIN_ICON, META_PROP_VALUE_INVALID, reload_kwm_win_icon, NONE }, - { x11_display->atom__NET_WM_ICON_GEOMETRY, META_PROP_VALUE_CARDINAL_LIST, reload_icon_geometry, LOAD_INIT }, - { x11_display->atom_WM_CLIENT_LEADER, META_PROP_VALUE_INVALID, complain_about_broken_client, NONE }, - { x11_display->atom_SM_CLIENT_ID, META_PROP_VALUE_INVALID, complain_about_broken_client, NONE }, - { x11_display->atom_WM_WINDOW_ROLE, META_PROP_VALUE_STRING, reload_wm_window_role, LOAD_INIT | FORCE_INIT }, - { x11_display->atom__NET_WM_WINDOW_TYPE, META_PROP_VALUE_ATOM_LIST, reload_net_wm_window_type, LOAD_INIT | INCLUDE_OR | FORCE_INIT }, - { x11_display->atom__NET_WM_STRUT, META_PROP_VALUE_INVALID, reload_struts, NONE }, - { x11_display->atom__NET_WM_STRUT_PARTIAL, META_PROP_VALUE_INVALID, reload_struts, NONE }, - { x11_display->atom__NET_WM_BYPASS_COMPOSITOR, META_PROP_VALUE_CARDINAL, reload_bypass_compositor, LOAD_INIT | INCLUDE_OR }, - { x11_display->atom__NET_WM_WINDOW_OPACITY, META_PROP_VALUE_CARDINAL, reload_window_opacity, LOAD_INIT | INCLUDE_OR }, - { 0 }, - }; - MetaWindowPropHooks *table; - MetaWindowPropHooks *cursor; - - table = g_memdup2 (hooks, sizeof (hooks)), - cursor = table; - - g_assert (x11_display->prop_hooks == NULL); - - x11_display->prop_hooks_table = (gpointer) table; - x11_display->prop_hooks = g_hash_table_new (NULL, NULL); - - while (cursor->property) - { - /* Doing initial loading doesn't make sense if we just want notification */ - g_assert (!((cursor->flags & LOAD_INIT) && cursor->type == META_PROP_VALUE_INVALID)); - - /* Forcing initialization doesn't make sense if not loading initially */ - g_assert ((cursor->flags & LOAD_INIT) || !(cursor->flags & FORCE_INIT)); - - /* Atoms are safe to use with GINT_TO_POINTER because it's safe with - * anything 32 bits or less, and atoms are 32 bits with the top three - * bits clear. (Scheifler & Gettys, 2e, p372) - */ - g_hash_table_insert (x11_display->prop_hooks, - GINT_TO_POINTER (cursor->property), - cursor); - cursor++; - } - x11_display->n_prop_hooks = cursor - table; -} - -void -meta_x11_display_free_window_prop_hooks (MetaX11Display *x11_display) -{ - g_hash_table_unref (x11_display->prop_hooks); - x11_display->prop_hooks = NULL; - - g_free (x11_display->prop_hooks_table); - x11_display->prop_hooks_table = NULL; -} - -static MetaWindowPropHooks * -find_hooks (MetaX11Display *x11_display, - Atom property) -{ - return g_hash_table_lookup (x11_display->prop_hooks, - GINT_TO_POINTER (property)); -} diff --git a/src/x11/window-props.h b/src/x11/window-props.h deleted file mode 100644 index 4f37e0c0f..000000000 --- a/src/x11/window-props.h +++ /dev/null @@ -1,95 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/** - * SECTION:window-props - * @short_description: MetaWindow property handling - * - * A system which can inspect sets of properties of given windows - * and take appropriate action given their values. - * - * Note that all the meta_window_reload_propert* functions require a - * round trip to the server. - */ - -/* - * Copyright (C) 2001, 2002 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 . - */ - -#ifndef META_WINDOW_PROPS_H -#define META_WINDOW_PROPS_H - -#include "core/window-private.h" - -/** - * meta_window_reload_property_from_xwindow: - * @window: A window on the same display as the one we're - * investigating (only used to find the display) - * @xwindow: The X handle for the window. - * @property: A single X atom. - * - * Requests the current values of a single property for a given - * window from the server, and deals with it appropriately. - * Does not return it to the caller (it's been dealt with!) - */ -void meta_window_reload_property_from_xwindow (MetaWindow *window, - Window xwindow, - Atom property, - gboolean initial); - -/** - * meta_window_load_initial_properties: - * @window: The window. - * - * Requests the current values for standard properties for a given - * window from the server, and deals with them appropriately. - * Does not return them to the caller (they've been dealt with!) - */ -void meta_window_load_initial_properties (MetaWindow *window); - -/** - * meta_x11_display_init_window_prop_hooks: - * @x11_display: The X11 display. - * - * Initialises the hooks used for the reload_propert* functions - * on a particular display, and stores a pointer to them in the - * x11_display. - */ -void meta_x11_display_init_window_prop_hooks (MetaX11Display *x11_display); - -/** - * meta_x11_display_free_window_prop_hooks: - * @x11_display: The X11 display. - * Frees the hooks used for the reload_propert* functions - * for a particular display. - */ -void meta_x11_display_free_window_prop_hooks (MetaX11Display *x11_display); - -/** - * meta_set_normal_hints: - * @window: The window to set the size hints on. - * @hints: Either some X size hints, or NULL for default. - * - * Sets the size hints for a window. This happens when a - * WM_NORMAL_HINTS property is set on a window, but it is public - * because the size hints are set to defaults when a window is - * created. See - * http://tronche.com/gui/x/icccm/sec-4.html#WM_NORMAL_HINTS - * for the X details. - */ -void meta_set_normal_hints (MetaWindow *window, - XSizeHints *hints); - -#endif /* META_WINDOW_PROPS_H */ diff --git a/src/x11/window-x11-private.h b/src/x11/window-x11-private.h deleted file mode 100644 index e12f83be0..000000000 --- a/src/x11/window-x11-private.h +++ /dev/null @@ -1,89 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington, Anders Carlsson - * Copyright (C) 2002, 2003 Red Hat, Inc. - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * 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 . - */ - -#ifndef META_WINDOW_X11_PRIVATE_H -#define META_WINDOW_X11_PRIVATE_H - -#include "core/window-private.h" -#include "x11/iconcache.h" -#include "x11/window-x11.h" - -G_BEGIN_DECLS - -/* - * Mirrors _NET_WM_BYPASS_COMPOSITOR preference values. - */ -typedef enum _MetaBypassCompositorHint -{ - META_BYPASS_COMPOSITOR_HINT_AUTO = 0, - META_BYPASS_COMPOSITOR_HINT_ON = 1, - META_BYPASS_COMPOSITOR_HINT_OFF = 2, -} MetaBypassCompositorHint; - -typedef struct _MetaWindowX11Private MetaWindowX11Private; - -struct _MetaWindowX11Private -{ - /* TRUE if the client forced these on */ - guint wm_state_skip_taskbar : 1; - guint wm_state_skip_pager : 1; - guint wm_take_focus : 1; - guint wm_ping : 1; - guint wm_delete_window : 1; - - /* Weird "_NET_WM_STATE_MODAL" flag */ - guint wm_state_modal : 1; - - /* Info on which props we got our attributes from */ - guint using_net_wm_name : 1; /* vs. plain wm_name */ - guint using_net_wm_visible_name : 1; /* tracked so we can clear it */ - - Atom type_atom; - - /* Requested geometry */ - int border_width; - - gboolean showing_resize_popup; - - /* These are in server coordinates. If we have a frame, it's - * relative to the frame. */ - MetaRectangle client_rect; - - MetaIconCache icon_cache; - Pixmap wm_hints_pixmap; - Pixmap wm_hints_mask; - - /* Freeze/thaw on resize (for Xwayland) */ - gboolean thaw_after_paint; - - /* Bypass compositor hints */ - MetaBypassCompositorHint bypass_compositor; -}; - -MetaWindowX11Private * meta_window_x11_get_private (MetaWindowX11 *window_x11); - -void meta_window_x11_set_bypass_compositor_hint (MetaWindowX11 *window_x11, - MetaBypassCompositorHint requested_value); - -G_END_DECLS - -#endif diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c deleted file mode 100644 index 204b49e93..000000000 --- a/src/x11/window-x11.c +++ /dev/null @@ -1,4223 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington, Anders Carlsson - * Copyright (C) 2002, 2003 Red Hat, Inc. - * Copyright (C) 2003 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * 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 . - */ - -#include "config.h" - -#include "x11/window-x11.h" -#include "x11/window-x11-private.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "backends/meta-logical-monitor.h" -#include "backends/x11/meta-backend-x11.h" -#include "compositor/meta-window-actor-private.h" -#include "core/boxes-private.h" -#include "core/frame.h" -#include "core/meta-workspace-manager-private.h" -#include "core/window-private.h" -#include "core/workspace-private.h" -#include "meta/common.h" -#include "meta/meta-cursor-tracker.h" -#include "meta/meta-x11-errors.h" -#include "meta/prefs.h" -#include "x11/meta-x11-display-private.h" -#include "x11/session.h" -#include "x11/window-props.h" -#include "x11/xprops.h" - -#define TAKE_FOCUS_FALLBACK_DELAY_MS 150 - -enum _MetaGtkEdgeConstraints -{ - META_GTK_EDGE_CONSTRAINT_TOP_TILED = 1 << 0, - META_GTK_EDGE_CONSTRAINT_TOP_RESIZABLE = 1 << 1, - META_GTK_EDGE_CONSTRAINT_RIGHT_TILED = 1 << 2, - META_GTK_EDGE_CONSTRAINT_RIGHT_RESIZABLE = 1 << 3, - META_GTK_EDGE_CONSTRAINT_BOTTOM_TILED = 1 << 4, - META_GTK_EDGE_CONSTRAINT_BOTTOM_RESIZABLE = 1 << 5, - META_GTK_EDGE_CONSTRAINT_LEFT_TILED = 1 << 6, - META_GTK_EDGE_CONSTRAINT_LEFT_RESIZABLE = 1 << 7 -} MetaGtkEdgeConstraints; - -G_DEFINE_TYPE_WITH_PRIVATE (MetaWindowX11, meta_window_x11, META_TYPE_WINDOW) - -static void -meta_window_x11_maybe_focus_delayed (MetaWindow *window, - GQueue *other_focus_candidates, - guint32 timestamp); - -static void -meta_window_x11_init (MetaWindowX11 *window_x11) -{ -} - -MetaWindowX11Private * -meta_window_x11_get_private (MetaWindowX11 *window_x11) -{ - return meta_window_x11_get_instance_private (window_x11); -} - -static void -send_icccm_message (MetaWindow *window, - Atom atom, - guint32 timestamp) -{ - /* This comment and code are from twm, copyright - * Open Group, Evans & Sutherland, etc. - */ - - /* - * ICCCM Client Messages - Section 4.2.8 of the ICCCM dictates that all - * client messages will have the following form: - * - * event type ClientMessage - * message type _XA_WM_PROTOCOLS - * window tmp->w - * format 32 - * data[0] message atom - * data[1] time stamp - */ - - XClientMessageEvent ev; - MetaX11Display *x11_display = window->display->x11_display; - - ev.type = ClientMessage; - ev.window = window->xwindow; - ev.message_type = x11_display->atom_WM_PROTOCOLS; - ev.format = 32; - ev.data.l[0] = atom; - ev.data.l[1] = timestamp; - - meta_x11_error_trap_push (x11_display); - XSendEvent (x11_display->xdisplay, - window->xwindow, False, 0, (XEvent*) &ev); - meta_x11_error_trap_pop (x11_display); -} - -static Window -read_client_leader (MetaDisplay *display, - Window xwindow) -{ - Window retval = None; - - meta_prop_get_window (display->x11_display, xwindow, - display->x11_display->atom_WM_CLIENT_LEADER, - &retval); - - return retval; -} - -typedef struct -{ - Window leader; -} ClientLeaderData; - -static gboolean -find_client_leader_func (MetaWindow *ancestor, - void *data) -{ - ClientLeaderData *d; - - d = data; - - d->leader = read_client_leader (ancestor->display, - ancestor->xwindow); - - /* keep going if no client leader found */ - return d->leader == None; -} - -static void -update_sm_hints (MetaWindow *window) -{ - Window leader; - - window->xclient_leader = None; - window->sm_client_id = NULL; - - /* If not on the current window, we can get the client - * leader from transient parents. If we find a client - * leader, we read the SM_CLIENT_ID from it. - */ - leader = read_client_leader (window->display, window->xwindow); - if (leader == None) - { - ClientLeaderData d; - d.leader = None; - meta_window_foreach_ancestor (window, find_client_leader_func, - &d); - leader = d.leader; - } - - if (leader != None) - { - window->xclient_leader = leader; - - meta_prop_get_latin1_string (window->display->x11_display, leader, - window->display->x11_display->atom_SM_CLIENT_ID, - &window->sm_client_id); - } - else - { - meta_verbose ("Didn't find a client leader for %s", window->desc); - - if (!meta_prefs_get_disable_workarounds ()) - { - /* Some broken apps (kdelibs fault?) set SM_CLIENT_ID on the app - * instead of the client leader - */ - meta_prop_get_latin1_string (window->display->x11_display, window->xwindow, - window->display->x11_display->atom_SM_CLIENT_ID, - &window->sm_client_id); - - if (window->sm_client_id) - meta_warning ("Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER window as specified in the ICCCM.", - window->desc); - } - } - - meta_verbose ("Window %s client leader: 0x%lx SM_CLIENT_ID: '%s'", - window->desc, window->xclient_leader, - window->sm_client_id ? window->sm_client_id : "none"); -} - -static void -send_configure_notify (MetaWindow *window) -{ - MetaX11Display *x11_display = window->display->x11_display; - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); - XEvent event; - - g_assert (!window->override_redirect); - - /* from twm */ - - event.type = ConfigureNotify; - event.xconfigure.display = x11_display->xdisplay; - event.xconfigure.event = window->xwindow; - event.xconfigure.window = window->xwindow; - event.xconfigure.x = priv->client_rect.x - priv->border_width; - event.xconfigure.y = priv->client_rect.y - priv->border_width; - if (window->frame) - { - if (window->withdrawn) - { - MetaFrameBorders borders; - /* We reparent the client window and put it to the position - * where the visible top-left of the frame window currently is. - */ - - meta_frame_calc_borders (window->frame, &borders); - - event.xconfigure.x = window->frame->rect.x + borders.invisible.left; - event.xconfigure.y = window->frame->rect.y + borders.invisible.top; - } - else - { - /* Need to be in root window coordinates */ - event.xconfigure.x += window->frame->rect.x; - event.xconfigure.y += window->frame->rect.y; - } - } - event.xconfigure.width = priv->client_rect.width; - event.xconfigure.height = priv->client_rect.height; - event.xconfigure.border_width = priv->border_width; /* requested not actual */ - event.xconfigure.above = None; /* FIXME */ - event.xconfigure.override_redirect = False; - - meta_topic (META_DEBUG_GEOMETRY, - "Sending synthetic configure notify to %s with x: %d y: %d w: %d h: %d", - window->desc, - event.xconfigure.x, event.xconfigure.y, - event.xconfigure.width, event.xconfigure.height); - - meta_x11_error_trap_push (x11_display); - XSendEvent (x11_display->xdisplay, - window->xwindow, - False, StructureNotifyMask, &event); - meta_x11_error_trap_pop (x11_display); -} - -static void -adjust_for_gravity (MetaWindow *window, - gboolean coords_assume_border, - MetaGravity gravity, - MetaRectangle *rect) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); - int ref_x, ref_y; - int bw; - int child_x, child_y; - int frame_width, frame_height; - MetaFrameBorders borders; - - /* We're computing position to pass to window_move, which is - * the position of the client window (META_GRAVITY_STATIC basically) - * - * (see WM spec description of gravity computation, but note that - * their formulas assume we're honoring the border width, rather - * than compensating for having turned it off) - */ - - if (gravity == META_GRAVITY_STATIC) - return; - - if (coords_assume_border) - bw = priv->border_width; - else - bw = 0; - - meta_frame_calc_borders (window->frame, &borders); - - child_x = borders.visible.left; - child_y = borders.visible.top; - frame_width = child_x + rect->width + borders.visible.right; - frame_height = child_y + rect->height + borders.visible.bottom; - - /* Calculate the the reference point, which is the corner of the - * outer window specified by the gravity. So, META_GRAVITY_NORTH_EAST - * would have the reference point as the top-right corner of the - * outer window. */ - ref_x = rect->x; - ref_y = rect->y; - - switch (gravity) - { - case META_GRAVITY_NORTH: - case META_GRAVITY_CENTER: - case META_GRAVITY_SOUTH: - ref_x += rect->width / 2 + bw; - break; - case META_GRAVITY_NORTH_EAST: - case META_GRAVITY_EAST: - case META_GRAVITY_SOUTH_EAST: - ref_x += rect->width + bw * 2; - break; - default: - break; - } - - switch (gravity) - { - case META_GRAVITY_WEST: - case META_GRAVITY_CENTER: - case META_GRAVITY_EAST: - ref_y += rect->height / 2 + bw; - break; - case META_GRAVITY_SOUTH_WEST: - case META_GRAVITY_SOUTH: - case META_GRAVITY_SOUTH_EAST: - ref_y += rect->height + bw * 2; - break; - default: - break; - } - - /* Find the top-left corner of the outer window from - * the reference point. */ - - rect->x = ref_x; - rect->y = ref_y; - - switch (gravity) - { - case META_GRAVITY_NORTH: - case META_GRAVITY_CENTER: - case META_GRAVITY_SOUTH: - rect->x -= frame_width / 2; - break; - case META_GRAVITY_NORTH_EAST: - case META_GRAVITY_EAST: - case META_GRAVITY_SOUTH_EAST: - rect->x -= frame_width; - break; - default: - break; - } - - switch (gravity) - { - case META_GRAVITY_WEST: - case META_GRAVITY_CENTER: - case META_GRAVITY_EAST: - rect->y -= frame_height / 2; - break; - case META_GRAVITY_SOUTH_WEST: - case META_GRAVITY_SOUTH: - case META_GRAVITY_SOUTH_EAST: - rect->y -= frame_height; - break; - default: - break; - } - - /* Adjust to get the top-left corner of the inner window. */ - rect->x += child_x; - rect->y += child_y; -} - -static void -meta_window_apply_session_info (MetaWindow *window, - const MetaWindowSessionInfo *info) -{ - if (info->stack_position_set) - { - meta_topic (META_DEBUG_SM, - "Restoring stack position %d for window %s", - info->stack_position, window->desc); - - /* FIXME well, I'm not sure how to do this. */ - } - - if (info->minimized_set) - { - meta_topic (META_DEBUG_SM, - "Restoring minimized state %d for window %s", - info->minimized, window->desc); - - if (info->minimized) - meta_window_minimize (window); - } - - if (info->maximized_set) - { - meta_topic (META_DEBUG_SM, - "Restoring maximized state %d for window %s", - info->maximized, window->desc); - - if (window->has_maximize_func && info->maximized) - { - meta_window_maximize (window, META_MAXIMIZE_BOTH); - - if (info->saved_rect_set) - { - meta_topic (META_DEBUG_SM, - "Restoring saved rect %d,%d %dx%d for window %s", - info->saved_rect.x, - info->saved_rect.y, - info->saved_rect.width, - info->saved_rect.height, - window->desc); - - window->saved_rect.x = info->saved_rect.x; - window->saved_rect.y = info->saved_rect.y; - window->saved_rect.width = info->saved_rect.width; - window->saved_rect.height = info->saved_rect.height; - } - } - } - - if (info->on_all_workspaces_set) - { - window->on_all_workspaces_requested = info->on_all_workspaces; - meta_window_on_all_workspaces_changed (window); - meta_topic (META_DEBUG_SM, - "Restoring sticky state %d for window %s", - window->on_all_workspaces_requested, window->desc); - } - - if (info->workspace_indices) - { - GSList *tmp; - GSList *spaces; - - spaces = NULL; - - tmp = info->workspace_indices; - while (tmp != NULL) - { - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - MetaWorkspace *space; - - space = - meta_workspace_manager_get_workspace_by_index (workspace_manager, - GPOINTER_TO_INT (tmp->data)); - - if (space) - spaces = g_slist_prepend (spaces, space); - - tmp = tmp->next; - } - - if (spaces) - { - /* XXX: What should we do if there's more than one workspace - * listed? We only support one workspace for each window. - * - * For now, just choose the first one. - */ - MetaWorkspace *workspace = spaces->data; - - meta_window_change_workspace (window, workspace); - window->initial_workspace_set = TRUE; - - meta_topic (META_DEBUG_SM, - "Restoring saved window %s to workspace %d", - window->desc, - meta_workspace_index (workspace)); - - g_slist_free (spaces); - } - } - - if (info->geometry_set) - { - MetaRectangle rect; - MetaMoveResizeFlags flags; - MetaGravity gravity; - - window->placed = TRUE; /* don't do placement algorithms later */ - - rect.x = info->rect.x; - rect.y = info->rect.y; - - rect.width = window->size_hints.base_width + info->rect.width * window->size_hints.width_inc; - rect.height = window->size_hints.base_height + info->rect.height * window->size_hints.height_inc; - - /* Force old gravity, ignoring anything now set */ - window->size_hints.win_gravity = info->gravity; - gravity = window->size_hints.win_gravity; - - flags = META_MOVE_RESIZE_MOVE_ACTION | META_MOVE_RESIZE_RESIZE_ACTION; - - adjust_for_gravity (window, FALSE, gravity, &rect); - meta_window_client_rect_to_frame_rect (window, &rect, &rect); - meta_window_move_resize_internal (window, flags, gravity, rect); - } -} - -static void -meta_window_x11_manage (MetaWindow *window) -{ - MetaDisplay *display = window->display; - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); - - meta_icon_cache_init (&priv->icon_cache); - - meta_x11_display_register_x_window (display->x11_display, - &window->xwindow, - window); - - /* assign the window to its group, or create a new group if needed */ - window->group = NULL; - window->xgroup_leader = None; - meta_window_compute_group (window); - - meta_window_load_initial_properties (window); - - if (!window->override_redirect) - update_sm_hints (window); /* must come after transient_for */ - - if (window->decorated) - meta_window_ensure_frame (window); - - /* Now try applying saved stuff from the session */ - { - const MetaWindowSessionInfo *info; - - info = meta_window_lookup_saved_state (window); - - if (info) - { - meta_window_apply_session_info (window, info); - meta_window_release_saved_state (info); - } - } - - /* For override-redirect windows, save the client rect - * directly. window->rect was assigned from the XWindowAttributes - * in the main meta_window_shared_new. - * - * For normal windows, do a full ConfigureRequest based on the - * window hints, as that's what the ICCCM says to do. - */ - priv->client_rect = window->rect; - window->buffer_rect = window->rect; - - if (!window->override_redirect) - { - MetaRectangle rect; - MetaMoveResizeFlags flags; - MetaGravity gravity = window->size_hints.win_gravity; - - rect.x = window->size_hints.x; - rect.y = window->size_hints.y; - rect.width = window->size_hints.width; - rect.height = window->size_hints.height; - - flags = META_MOVE_RESIZE_CONFIGURE_REQUEST | META_MOVE_RESIZE_MOVE_ACTION | META_MOVE_RESIZE_RESIZE_ACTION; - - adjust_for_gravity (window, TRUE, gravity, &rect); - meta_window_client_rect_to_frame_rect (window, &rect, &rect); - meta_window_move_resize_internal (window, flags, gravity, rect); - } - - meta_window_x11_update_shape_region (window); - meta_window_x11_update_input_region (window); -} - -static void -meta_window_x11_unmanage (MetaWindow *window) -{ - MetaX11Display *x11_display = window->display->x11_display; - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); - - meta_x11_error_trap_push (x11_display); - - meta_window_x11_destroy_sync_request_alarm (window); - - if (window->withdrawn) - { - /* We need to clean off the window's state so it - * won't be restored if the app maps it again. - */ - meta_verbose ("Cleaning state from window %s", window->desc); - XDeleteProperty (x11_display->xdisplay, - window->xwindow, - x11_display->atom__NET_WM_DESKTOP); - XDeleteProperty (x11_display->xdisplay, - window->xwindow, - x11_display->atom__NET_WM_STATE); - XDeleteProperty (x11_display->xdisplay, - window->xwindow, - x11_display->atom__NET_WM_FULLSCREEN_MONITORS); - meta_window_x11_set_wm_state (window); - } - else - { - /* We need to put WM_STATE so that others will understand it on - * restart. - */ - if (!window->minimized) - meta_window_x11_set_wm_state (window); - - /* If we're unmanaging a window that is not withdrawn, then - * either (a) mutter is exiting, in which case we need to map - * the window so the next WM will know that it's not Withdrawn, - * or (b) we want to create a new MetaWindow to replace the - * current one, which will happen automatically if we re-map - * the X Window. - */ - XMapWindow (x11_display->xdisplay, - window->xwindow); - } - - meta_x11_display_unregister_x_window (x11_display, window->xwindow); - - /* Put back anything we messed up */ - if (priv->border_width != 0) - XSetWindowBorderWidth (x11_display->xdisplay, - window->xwindow, - priv->border_width); - - /* No save set */ - XRemoveFromSaveSet (x11_display->xdisplay, - window->xwindow); - - /* Even though the window is now unmanaged, we can't unselect events. This - * window might be a window from this process, like a GdkMenu, in - * which case it will have pointer events and so forth selected - * for it by GDK. There's no way to disentangle those events from the events - * we've selected. Even for a window from a different X client, - * GDK could also have selected events for it for IPC purposes, so we - * can't unselect in that case either. - * - * Similarly, we can't unselected for events on window->user_time_window. - * It might be our own GDK focus window, or it might be a window that a - * different client is using for multiple different things: - * _NET_WM_USER_TIME_WINDOW and IPC, perhaps. - */ - - if (window->user_time_window != None) - { - meta_x11_display_unregister_x_window (x11_display, - window->user_time_window); - window->user_time_window = None; - } - - if (META_X11_DISPLAY_HAS_SHAPE (x11_display)) - XShapeSelectInput (x11_display->xdisplay, window->xwindow, NoEventMask); - - meta_window_ungrab_keys (window); - meta_display_ungrab_window_buttons (window->display, window->xwindow); - meta_display_ungrab_focus_window_button (window->display, window); - - meta_x11_error_trap_pop (x11_display); - - if (window->frame) - { - /* The XReparentWindow call in meta_window_destroy_frame() moves the - * window so we need to send a configure notify; see bug 399552. (We - * also do this just in case a window got unmaximized.) - */ - send_configure_notify (window); - - meta_window_destroy_frame (window); - } -} - -void -meta_window_x11_set_wm_ping (MetaWindow *window, - gboolean ping) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = - meta_window_x11_get_instance_private (window_x11); - - priv->wm_ping = ping; -} - -static gboolean -meta_window_x11_can_ping (MetaWindow *window) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = - meta_window_x11_get_instance_private (window_x11); - - return priv->wm_ping; -} - -static void -meta_window_x11_ping (MetaWindow *window, - guint32 serial) -{ - MetaDisplay *display = window->display; - - send_icccm_message (window, display->x11_display->atom__NET_WM_PING, serial); -} - -void -meta_window_x11_set_wm_delete_window (MetaWindow *window, - gboolean delete_window) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = - meta_window_x11_get_instance_private (window_x11); - - priv->wm_delete_window = delete_window; -} - -static void -meta_window_x11_delete (MetaWindow *window, - guint32 timestamp) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = - meta_window_x11_get_instance_private (window_x11); - MetaX11Display *x11_display = window->display->x11_display; - - meta_x11_error_trap_push (x11_display); - if (priv->wm_delete_window) - { - meta_topic (META_DEBUG_WINDOW_OPS, - "Deleting %s with delete_window request", - window->desc); - send_icccm_message (window, x11_display->atom_WM_DELETE_WINDOW, timestamp); - } - else - { - meta_topic (META_DEBUG_WINDOW_OPS, - "Deleting %s with explicit kill", - window->desc); - XKillClient (x11_display->xdisplay, window->xwindow); - } - meta_x11_error_trap_pop (x11_display); -} - -static void -meta_window_x11_kill (MetaWindow *window) -{ - MetaX11Display *x11_display = window->display->x11_display; - - meta_topic (META_DEBUG_WINDOW_OPS, - "Disconnecting %s with XKillClient()", - window->desc); - - meta_x11_error_trap_push (x11_display); - XKillClient (x11_display->xdisplay, window->xwindow); - meta_x11_error_trap_pop (x11_display); -} - -static void -request_take_focus (MetaWindow *window, - guint32 timestamp) -{ - MetaDisplay *display = window->display; - - meta_topic (META_DEBUG_FOCUS, "WM_TAKE_FOCUS(%s, %u)", - window->desc, timestamp); - - send_icccm_message (window, display->x11_display->atom_WM_TAKE_FOCUS, timestamp); -} - -typedef struct -{ - MetaWindow *window; - GQueue *pending_focus_candidates; - guint32 timestamp; - guint timeout_id; - gulong unmanaged_id; - gulong focused_changed_id; -} MetaWindowX11DelayedFocusData; - -static void -disconnect_pending_focus_window_signals (MetaWindow *window, - GQueue *focus_candidates) -{ - g_signal_handlers_disconnect_by_func (window, g_queue_remove, - focus_candidates); -} - -static void -meta_window_x11_delayed_focus_data_free (MetaWindowX11DelayedFocusData *data) -{ - g_clear_signal_handler (&data->unmanaged_id, data->window); - g_clear_signal_handler (&data->focused_changed_id, data->window->display); - - if (data->pending_focus_candidates) - { - g_queue_foreach (data->pending_focus_candidates, - (GFunc) disconnect_pending_focus_window_signals, - data->pending_focus_candidates); - g_queue_free (data->pending_focus_candidates); - } - - g_clear_handle_id (&data->timeout_id, g_source_remove); - g_free (data); -} - -static void -focus_candidates_maybe_take_and_focus_next (GQueue **focus_candidates_ptr, - guint32 timestamp) -{ - MetaWindow *focus_window; - GQueue *focus_candidates; - - g_assert (*focus_candidates_ptr); - - if (g_queue_is_empty (*focus_candidates_ptr)) - return; - - focus_candidates = g_steal_pointer (focus_candidates_ptr); - focus_window = g_queue_pop_head (focus_candidates); - - disconnect_pending_focus_window_signals (focus_window, focus_candidates); - meta_window_x11_maybe_focus_delayed (focus_window, focus_candidates, timestamp); -} - -static void -focus_window_delayed_unmanaged (gpointer user_data) -{ - MetaWindowX11DelayedFocusData *data = user_data; - uint32_t timestamp = data->timestamp; - - focus_candidates_maybe_take_and_focus_next (&data->pending_focus_candidates, - timestamp); - - meta_window_x11_delayed_focus_data_free (data); -} - -static gboolean -focus_window_delayed_timeout (gpointer user_data) -{ - MetaWindowX11DelayedFocusData *data = user_data; - MetaWindow *window = data->window; - guint32 timestamp = data->timestamp; - - focus_candidates_maybe_take_and_focus_next (&data->pending_focus_candidates, - timestamp); - - data->timeout_id = 0; - meta_window_x11_delayed_focus_data_free (data); - - meta_window_focus (window, timestamp); - - return G_SOURCE_REMOVE; -} - -static void -meta_window_x11_maybe_focus_delayed (MetaWindow *window, - GQueue *other_focus_candidates, - guint32 timestamp) -{ - MetaWindowX11DelayedFocusData *data; - - data = g_new0 (MetaWindowX11DelayedFocusData, 1); - data->window = window; - data->timestamp = timestamp; - data->pending_focus_candidates = other_focus_candidates; - - meta_topic (META_DEBUG_FOCUS, - "Requesting delayed focus to %s", window->desc); - - data->unmanaged_id = - g_signal_connect_swapped (window, "unmanaged", - G_CALLBACK (focus_window_delayed_unmanaged), - data); - - data->focused_changed_id = - g_signal_connect_swapped (window->display, "notify::focus-window", - G_CALLBACK (meta_window_x11_delayed_focus_data_free), - data); - - data->timeout_id = g_timeout_add (TAKE_FOCUS_FALLBACK_DELAY_MS, - focus_window_delayed_timeout, data); -} - -static void -maybe_focus_default_window (MetaDisplay *display, - MetaWindow *not_this_one, - guint32 timestamp) -{ - MetaWorkspace *workspace; - MetaStack *stack = display->stack; - g_autoptr (GList) focusable_windows = NULL; - g_autoptr (GQueue) focus_candidates = NULL; - GList *l; - - if (not_this_one && not_this_one->workspace) - workspace = not_this_one->workspace; - else - workspace = display->workspace_manager->active_workspace; - - /* Go through all the focusable windows and try to focus them - * in order, waiting for a delay. The first one that replies to - * the request (in case of take focus windows) changing the display - * focused window, will stop the chained requests. - */ - focusable_windows = - meta_stack_get_default_focus_candidates (stack, workspace); - focus_candidates = g_queue_new (); - - for (l = g_list_last (focusable_windows); l; l = l->prev) - { - MetaWindow *focus_window = l->data; - - if (focus_window == not_this_one) - continue; - - g_queue_push_tail (focus_candidates, focus_window); - g_signal_connect_swapped (focus_window, "unmanaged", - G_CALLBACK (g_queue_remove), - focus_candidates); - - if (!META_IS_WINDOW_X11 (focus_window)) - break; - - if (focus_window->input) - break; - - if (focus_window->shaded && focus_window->frame) - break; - } - - focus_candidates_maybe_take_and_focus_next (&focus_candidates, timestamp); -} - -static void -meta_window_x11_focus (MetaWindow *window, - guint32 timestamp) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = - meta_window_x11_get_instance_private (window_x11); - /* For output-only or shaded windows, focus the frame. - * This seems to result in the client window getting key events - * though, so I don't know if it's icccm-compliant. - * - * Still, we have to do this or keynav breaks for these windows. - */ - if (window->frame && - (window->shaded || !meta_window_is_focusable (window))) - { - meta_topic (META_DEBUG_FOCUS, - "Focusing frame of %s", window->desc); - meta_display_set_input_focus (window->display, - window, - TRUE, - timestamp); - } - else - { - if (window->input) - { - meta_topic (META_DEBUG_FOCUS, - "Setting input focus on %s since input = true", - window->desc); - meta_display_set_input_focus (window->display, - window, - FALSE, - timestamp); - } - - if (priv->wm_take_focus) - { - meta_topic (META_DEBUG_FOCUS, - "Sending WM_TAKE_FOCUS to %s since take_focus = true", - window->desc); - - if (!window->input) - { - /* The "Globally Active Input" window case, where the window - * doesn't want us to call XSetInputFocus on it, but does - * want us to send a WM_TAKE_FOCUS. - * - * Normally, we want to just leave the focus undisturbed until - * the window responds to WM_TAKE_FOCUS, but if we're unmanaging - * the current focus window we *need* to move the focus away, so - * we focus the no focus window before sending WM_TAKE_FOCUS, - * and eventually the default focus window excluding this one, - * if meanwhile we don't get any focus request. - */ - if (window->display->focus_window != NULL && - window->display->focus_window->unmanaging) - { - meta_display_unset_input_focus (window->display, timestamp); - maybe_focus_default_window (window->display, window, - timestamp); - } - } - - request_take_focus (window, timestamp); - } - } -} - -static void -meta_window_get_client_root_coords (MetaWindow *window, - MetaRectangle *rect) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); - - *rect = priv->client_rect; - - if (window->frame) - { - rect->x += window->frame->rect.x; - rect->y += window->frame->rect.y; - } -} - -static void -meta_window_refresh_resize_popup (MetaWindow *window) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); - - if (priv->showing_resize_popup) - { - MetaRectangle rect; - int display_w, display_h; - - meta_window_get_client_root_coords (window, &rect); - - display_w = (rect.width - window->size_hints.base_width); - if (window->size_hints.width_inc > 0) - display_w /= window->size_hints.width_inc; - - display_h = (rect.height - window->size_hints.base_height); - if (window->size_hints.height_inc > 0) - display_h /= window->size_hints.height_inc; - - meta_display_show_resize_popup (window->display, TRUE, &rect, display_w, display_h); - } - else - { - meta_display_show_resize_popup (window->display, FALSE, NULL, 0, 0); - } -} - -static void -meta_window_x11_grab_op_began (MetaWindow *window, - MetaGrabOp op) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); - - if (meta_grab_op_is_resizing (op)) - { - if (window->sync_request_counter != None) - meta_window_x11_create_sync_request_alarm (window); - - if (window->size_hints.width_inc > 2 || window->size_hints.height_inc > 2) - { - priv->showing_resize_popup = TRUE; - meta_window_refresh_resize_popup (window); - } - } - - META_WINDOW_CLASS (meta_window_x11_parent_class)->grab_op_began (window, op); -} - -static void -meta_window_x11_grab_op_ended (MetaWindow *window, - MetaGrabOp op) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); - - if (priv->showing_resize_popup) - { - priv->showing_resize_popup = FALSE; - meta_window_refresh_resize_popup (window); - } - - META_WINDOW_CLASS (meta_window_x11_parent_class)->grab_op_ended (window, op); -} - -static void -update_net_frame_extents (MetaWindow *window) -{ - MetaX11Display *x11_display = window->display->x11_display; - - unsigned long data[4]; - MetaFrameBorders borders; - - meta_frame_calc_borders (window->frame, &borders); - /* Left */ - data[0] = borders.visible.left; - /* Right */ - data[1] = borders.visible.right; - /* Top */ - data[2] = borders.visible.top; - /* Bottom */ - data[3] = borders.visible.bottom; - - meta_topic (META_DEBUG_GEOMETRY, - "Setting _NET_FRAME_EXTENTS on managed window 0x%lx " - "to left = %lu, right = %lu, top = %lu, bottom = %lu", - window->xwindow, data[0], data[1], data[2], data[3]); - - meta_x11_error_trap_push (x11_display); - XChangeProperty (x11_display->xdisplay, window->xwindow, - x11_display->atom__NET_FRAME_EXTENTS, - XA_CARDINAL, - 32, PropModeReplace, (guchar*) data, 4); - meta_x11_error_trap_pop (x11_display); -} - -static gboolean -is_edge_constraint_resizable (MetaEdgeConstraint constraint) -{ - switch (constraint) - { - case META_EDGE_CONSTRAINT_NONE: - case META_EDGE_CONSTRAINT_WINDOW: - return TRUE; - case META_EDGE_CONSTRAINT_MONITOR: - return FALSE; - } - - g_assert_not_reached (); - return FALSE; -} - -static gboolean -is_edge_constraint_tiled (MetaEdgeConstraint constraint) -{ - switch (constraint) - { - case META_EDGE_CONSTRAINT_NONE: - return FALSE; - case META_EDGE_CONSTRAINT_WINDOW: - case META_EDGE_CONSTRAINT_MONITOR: - return TRUE; - } - - g_assert_not_reached (); - return FALSE; -} - -static unsigned long -edge_constraints_to_gtk_edge_constraints (MetaWindow *window) -{ - unsigned long gtk_edge_constraints = 0; - - if (is_edge_constraint_tiled (window->edge_constraints.top)) - gtk_edge_constraints |= META_GTK_EDGE_CONSTRAINT_TOP_TILED; - if (is_edge_constraint_resizable (window->edge_constraints.top)) - gtk_edge_constraints |= META_GTK_EDGE_CONSTRAINT_TOP_RESIZABLE; - - if (is_edge_constraint_tiled (window->edge_constraints.right)) - gtk_edge_constraints |= META_GTK_EDGE_CONSTRAINT_RIGHT_TILED; - if (is_edge_constraint_resizable (window->edge_constraints.right)) - gtk_edge_constraints |= META_GTK_EDGE_CONSTRAINT_RIGHT_RESIZABLE; - - if (is_edge_constraint_tiled (window->edge_constraints.bottom)) - gtk_edge_constraints |= META_GTK_EDGE_CONSTRAINT_BOTTOM_TILED; - if (is_edge_constraint_resizable (window->edge_constraints.bottom)) - gtk_edge_constraints |= META_GTK_EDGE_CONSTRAINT_BOTTOM_RESIZABLE; - - if (is_edge_constraint_tiled (window->edge_constraints.left)) - gtk_edge_constraints |= META_GTK_EDGE_CONSTRAINT_LEFT_TILED; - if (is_edge_constraint_resizable (window->edge_constraints.left)) - gtk_edge_constraints |= META_GTK_EDGE_CONSTRAINT_LEFT_RESIZABLE; - - return gtk_edge_constraints; -} - -static void -update_gtk_edge_constraints (MetaWindow *window) -{ - MetaX11Display *x11_display = window->display->x11_display; - unsigned long data[1]; - - data[0] = edge_constraints_to_gtk_edge_constraints (window); - - meta_verbose ("Setting _GTK_EDGE_CONSTRAINTS to %lu", data[0]); - - meta_x11_error_trap_push (x11_display); - XChangeProperty (x11_display->xdisplay, - window->xwindow, - x11_display->atom__GTK_EDGE_CONSTRAINTS, - XA_CARDINAL, 32, PropModeReplace, - (guchar*) data, 1); - meta_x11_error_trap_pop (x11_display); -} - -static gboolean -sync_request_timeout (gpointer data) -{ - MetaWindow *window = data; - - window->sync_request_timeout_id = 0; - - /* We have now waited for more than a second for the - * application to respond to the sync request - */ - window->disable_sync = TRUE; - - /* Reset the wait serial, so we don't continue freezing - * window updates - */ - window->sync_request_wait_serial = 0; - meta_compositor_sync_updates_frozen (window->display->compositor, window); - - if (window == window->display->grab_window && - meta_grab_op_is_resizing (window->display->grab_op)) - { - meta_window_update_resize (window, - window->display->grab_last_edge_resistance_flags, - window->display->grab_latest_motion_x, - window->display->grab_latest_motion_y, - TRUE); - } - - return FALSE; -} - -static void -send_sync_request (MetaWindow *window) -{ - MetaX11Display *x11_display = window->display->x11_display; - XClientMessageEvent ev; - gint64 wait_serial; - - /* For the old style of _NET_WM_SYNC_REQUEST_COUNTER, we just have to - * increase the value, but for the new "extended" style we need to - * pick an even (unfrozen) value sufficiently ahead of the last serial - * that we received from the client; the same code still works - * for the old style. The increment of 240 is specified by the EWMH - * and is (1 second) * (60fps) * (an increment of 4 per frame). - */ - wait_serial = window->sync_request_serial + 240; - - window->sync_request_wait_serial = wait_serial; - - ev.type = ClientMessage; - ev.window = window->xwindow; - ev.message_type = x11_display->atom_WM_PROTOCOLS; - ev.format = 32; - ev.data.l[0] = x11_display->atom__NET_WM_SYNC_REQUEST; - /* FIXME: meta_display_get_current_time() is bad, but since calls - * come from meta_window_move_resize_internal (which in turn come - * from all over), I'm not sure what we can do to fix it. Do we - * want to use _roundtrip, though? - */ - ev.data.l[1] = meta_display_get_current_time (window->display); - ev.data.l[2] = wait_serial & G_GUINT64_CONSTANT(0xffffffff); - ev.data.l[3] = wait_serial >> 32; - ev.data.l[4] = window->extended_sync_request_counter ? 1 : 0; - - /* We don't need to trap errors here as we are already - * inside an error_trap_push()/pop() pair. - */ - XSendEvent (x11_display->xdisplay, - window->xwindow, False, 0, (XEvent*) &ev); - - /* We give the window 1 sec to respond to _NET_WM_SYNC_REQUEST; - * if this time expires, we consider the window unresponsive - * and resize it unsynchonized. - */ - window->sync_request_timeout_id = g_timeout_add (1000, - sync_request_timeout, - window); - g_source_set_name_by_id (window->sync_request_timeout_id, - "[mutter] sync_request_timeout"); - - meta_compositor_sync_updates_frozen (window->display->compositor, window); -} - -static unsigned long -meta_window_get_net_wm_desktop (MetaWindow *window) -{ - if (window->on_all_workspaces) - return 0xFFFFFFFF; - else - return meta_workspace_index (window->workspace); -} - -static void -meta_window_x11_current_workspace_changed (MetaWindow *window) -{ - MetaX11Display *x11_display = window->display->x11_display; - /* FIXME if on more than one workspace, we claim to be "sticky", - * the WM spec doesn't say what to do here. - */ - unsigned long data[1]; - - if (window->workspace == NULL) - { - /* this happens when unmanaging windows */ - return; - } - - data[0] = meta_window_get_net_wm_desktop (window); - - meta_verbose ("Setting _NET_WM_DESKTOP of %s to %lu", - window->desc, data[0]); - - meta_x11_error_trap_push (x11_display); - XChangeProperty (x11_display->xdisplay, window->xwindow, - x11_display->atom__NET_WM_DESKTOP, - XA_CARDINAL, - 32, PropModeReplace, (guchar*) data, 1); - meta_x11_error_trap_pop (x11_display); -} - -static gboolean -meta_window_x11_can_freeze_commits (MetaWindow *window) -{ - MetaWindowActor *window_actor; - - window_actor = meta_window_actor_from_window (window); - if (window_actor == NULL) - return FALSE; - - return meta_window_actor_can_freeze_commits (window_actor); -} - -static void -meta_window_x11_move_resize_internal (MetaWindow *window, - MetaGravity gravity, - MetaRectangle unconstrained_rect, - MetaRectangle constrained_rect, - MetaRectangle intermediate_rect, - int rel_x, - int rel_y, - MetaMoveResizeFlags flags, - MetaMoveResizeResultFlags *result) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); - MetaFrameBorders borders; - MetaRectangle client_rect; - int size_dx, size_dy; - XWindowChanges values; - unsigned int mask; - gboolean need_configure_notify; - gboolean need_move_client = FALSE; - gboolean need_move_frame = FALSE; - gboolean need_resize_client = FALSE; - gboolean need_resize_frame = FALSE; - gboolean frame_shape_changed = FALSE; - gboolean configure_frame_first; - - gboolean is_configure_request; - - is_configure_request = (flags & META_MOVE_RESIZE_CONFIGURE_REQUEST) != 0; - - meta_frame_calc_borders (window->frame, &borders); - - size_dx = constrained_rect.x - window->rect.width; - size_dy = constrained_rect.y - window->rect.height; - - window->rect = constrained_rect; - - if (window->frame) - { - int new_w, new_h; - int new_x, new_y; - - /* Compute new frame size */ - new_w = window->rect.width + borders.invisible.left + borders.invisible.right; - - if (window->shaded) - new_h = borders.total.top + borders.total.bottom; - else - new_h = window->rect.height + borders.invisible.top + borders.invisible.bottom; - - if (new_w != window->frame->rect.width || - new_h != window->frame->rect.height) - { - need_resize_frame = TRUE; - window->frame->rect.width = new_w; - window->frame->rect.height = new_h; - } - - /* Compute new frame coords */ - new_x = window->rect.x - borders.invisible.left; - new_y = window->rect.y - borders.invisible.top; - - if (new_x != window->frame->rect.x || - new_y != window->frame->rect.y) - { - need_move_frame = TRUE; - window->frame->rect.x = new_x; - window->frame->rect.y = new_y; - } - } - - /* Calculate the new client rect */ - meta_window_frame_rect_to_client_rect (window, &constrained_rect, &client_rect); - - /* The above client_rect is in root window coordinates. The - * values we need to pass to XConfigureWindow are in parent - * coordinates, so if the window is in a frame, we need to - * correct the x/y positions here. */ - if (window->frame) - { - client_rect.x = borders.total.left; - client_rect.y = borders.total.top; - } - - if (client_rect.x != priv->client_rect.x || - client_rect.y != priv->client_rect.y) - { - need_move_client = TRUE; - priv->client_rect.x = client_rect.x; - priv->client_rect.y = client_rect.y; - } - - if (client_rect.width != priv->client_rect.width || - client_rect.height != priv->client_rect.height) - { - need_resize_client = TRUE; - priv->client_rect.width = client_rect.width; - priv->client_rect.height = client_rect.height; - } - - /* If frame extents have changed, fill in other frame fields and - change frame's extents property. */ - if (window->frame && - (window->frame->child_x != borders.total.left || - window->frame->child_y != borders.total.top || - window->frame->right_width != borders.total.right || - window->frame->bottom_height != borders.total.bottom)) - { - window->frame->child_x = borders.total.left; - window->frame->child_y = borders.total.top; - window->frame->right_width = borders.total.right; - window->frame->bottom_height = borders.total.bottom; - - update_net_frame_extents (window); - } - - /* See ICCCM 4.1.5 for when to send ConfigureNotify */ - - need_configure_notify = FALSE; - - /* If this is a configure request and we change nothing, then we - * must send configure notify. - */ - if (is_configure_request && - !(need_move_client || need_move_frame || - need_resize_client || need_resize_frame || - priv->border_width != 0)) - need_configure_notify = TRUE; - - /* We must send configure notify if we move but don't resize, since - * the client window may not get a real event - */ - if ((need_move_client || need_move_frame) && - !(need_resize_client || need_resize_frame)) - need_configure_notify = TRUE; - - /* MapRequest events with a PPosition or UPosition hint with a frame - * are moved by mutter without resizing; send a configure notify - * in such cases. See #322840. (Note that window->constructing is - * only true iff this call is due to a MapRequest, and when - * PPosition/UPosition hints aren't set, mutter seems to send a - * ConfigureNotify anyway due to the above code.) - */ - if (window->constructing && window->frame && - ((window->size_hints.flags & PPosition) || - (window->size_hints.flags & USPosition))) - need_configure_notify = TRUE; - - /* If resizing, freeze commits - This is for Xwayland, and a no-op on Xorg */ - if (need_resize_client || need_resize_frame) - { - if (meta_window_x11_can_freeze_commits (window) && - !meta_window_x11_should_thaw_after_paint (window)) - { - meta_window_x11_set_thaw_after_paint (window, TRUE); - meta_window_x11_freeze_commits (window); - } - } - - /* The rest of this function syncs our new size/pos with X as - * efficiently as possible - */ - - /* For nice effect, when growing the window we want to move/resize - * the frame first, when shrinking the window we want to move/resize - * the client first. If we grow one way and shrink the other, - * see which way we're moving "more" - * - * Mail from Owen subject "Suggestion: Gravity and resizing from the left" - * http://mail.gnome.org/archives/wm-spec-list/1999-November/msg00088.html - * - * An annoying fact you need to know in this code is that META_GRAVITY_STATIC - * does nothing if you _only_ resize or _only_ move the frame; - * it must move _and_ resize, otherwise you get META_GRAVITY_NORTH_WEST - * behavior. The move and resize must actually occur, it is not - * enough to set CWX | CWWidth but pass in the current size/pos. - */ - - /* Normally, we configure the frame first depending on whether - * we grow the frame more than we shrink. The idea is to avoid - * messing up the window contents by having a temporary situation - * where the frame is smaller than the window. However, if we're - * cooperating with the client to create an atomic frame update, - * and the window is redirected, then we should always update - * the frame first, since updating the frame will force a new - * backing pixmap to be allocated, and the old backing pixmap - * will be left undisturbed for us to paint to the screen until - * the client finishes redrawing. - */ - if (window->extended_sync_request_counter) - configure_frame_first = TRUE; - else - configure_frame_first = size_dx + size_dy >= 0; - - if (configure_frame_first && window->frame) - frame_shape_changed = meta_frame_sync_to_window (window->frame, need_resize_frame); - - values.border_width = 0; - values.x = client_rect.x; - values.y = client_rect.y; - values.width = client_rect.width; - values.height = client_rect.height; - - mask = 0; - if (is_configure_request && priv->border_width != 0) - mask |= CWBorderWidth; /* must force to 0 */ - if (need_move_client) - mask |= (CWX | CWY); - if (need_resize_client) - mask |= (CWWidth | CWHeight); - - if (mask != 0) - { - meta_x11_error_trap_push (window->display->x11_display); - - if (window == window->display->grab_window && - meta_grab_op_is_resizing (window->display->grab_op) && - !window->disable_sync && - window->sync_request_counter != None && - window->sync_request_alarm != None && - window->sync_request_timeout_id == 0) - { - send_sync_request (window); - } - - XConfigureWindow (window->display->x11_display->xdisplay, - window->xwindow, - mask, - &values); - - meta_x11_error_trap_pop (window->display->x11_display); - } - - if (!configure_frame_first && window->frame) - frame_shape_changed = meta_frame_sync_to_window (window->frame, need_resize_frame); - - if (window->frame) - window->buffer_rect = window->frame->rect; - else - window->buffer_rect = client_rect; - - if (need_configure_notify) - send_configure_notify (window); - - if (priv->showing_resize_popup) - meta_window_refresh_resize_popup (window); - - if (frame_shape_changed) - *result |= META_MOVE_RESIZE_RESULT_FRAME_SHAPE_CHANGED; - if (need_move_client || need_move_frame) - *result |= META_MOVE_RESIZE_RESULT_MOVED; - if (need_resize_client || need_resize_frame) - *result |= META_MOVE_RESIZE_RESULT_RESIZED; - if (flags & META_MOVE_RESIZE_STATE_CHANGED) - *result |= META_MOVE_RESIZE_RESULT_STATE_CHANGED; - - update_gtk_edge_constraints (window); -} - -static gboolean -meta_window_x11_update_struts (MetaWindow *window) -{ - GSList *old_struts; - GSList *new_struts; - GSList *old_iter, *new_iter; - uint32_t *struts = NULL; - int nitems; - gboolean changed; - - g_return_val_if_fail (!window->override_redirect, FALSE); - - meta_verbose ("Updating struts for %s", window->desc); - - old_struts = window->struts; - new_struts = NULL; - - if (meta_prop_get_cardinal_list (window->display->x11_display, - window->xwindow, - window->display->x11_display->atom__NET_WM_STRUT_PARTIAL, - &struts, &nitems)) - { - if (nitems != 12) - meta_verbose ("_NET_WM_STRUT_PARTIAL on %s has %d values instead " - "of 12", - window->desc, nitems); - else - { - /* Pull out the strut info for each side in the hint */ - int i; - for (i=0; i<4; i++) - { - MetaStrut *temp; - int thickness, strut_begin, strut_end; - - thickness = struts[i]; - if (thickness == 0) - continue; - strut_begin = struts[4+(i*2)]; - strut_end = struts[4+(i*2)+1]; - - temp = g_new0 (MetaStrut, 1); - temp->side = 1 << i; /* See MetaSide def. Matches nicely, eh? */ - meta_display_get_size (window->display, - &temp->rect.width, &temp->rect.height); - switch (temp->side) - { - case META_SIDE_RIGHT: - temp->rect.x = BOX_RIGHT(temp->rect) - thickness; - G_GNUC_FALLTHROUGH; - case META_SIDE_LEFT: - temp->rect.width = thickness; - temp->rect.y = strut_begin; - temp->rect.height = strut_end - strut_begin + 1; - break; - case META_SIDE_BOTTOM: - temp->rect.y = BOX_BOTTOM(temp->rect) - thickness; - G_GNUC_FALLTHROUGH; - case META_SIDE_TOP: - temp->rect.height = thickness; - temp->rect.x = strut_begin; - temp->rect.width = strut_end - strut_begin + 1; - break; - default: - g_assert_not_reached (); - } - - new_struts = g_slist_prepend (new_struts, temp); - } - - meta_verbose ("_NET_WM_STRUT_PARTIAL struts %u %u %u %u for " - "window %s", - struts[0], struts[1], struts[2], struts[3], - window->desc); - } - g_free (struts); - } - else - { - meta_verbose ("No _NET_WM_STRUT property for %s", - window->desc); - } - - if (!new_struts && - meta_prop_get_cardinal_list (window->display->x11_display, - window->xwindow, - window->display->x11_display->atom__NET_WM_STRUT, - &struts, &nitems)) - { - if (nitems != 4) - meta_verbose ("_NET_WM_STRUT on %s has %d values instead of 4", - window->desc, nitems); - else - { - /* Pull out the strut info for each side in the hint */ - int i; - for (i=0; i<4; i++) - { - MetaStrut *temp; - int thickness; - - thickness = struts[i]; - if (thickness == 0) - continue; - - temp = g_new0 (MetaStrut, 1); - temp->side = 1 << i; - meta_display_get_size (window->display, - &temp->rect.width, &temp->rect.height); - switch (temp->side) - { - case META_SIDE_RIGHT: - temp->rect.x = BOX_RIGHT(temp->rect) - thickness; - G_GNUC_FALLTHROUGH; - case META_SIDE_LEFT: - temp->rect.width = thickness; - break; - case META_SIDE_BOTTOM: - temp->rect.y = BOX_BOTTOM(temp->rect) - thickness; - G_GNUC_FALLTHROUGH; - case META_SIDE_TOP: - temp->rect.height = thickness; - break; - default: - g_assert_not_reached (); - } - - new_struts = g_slist_prepend (new_struts, temp); - } - - meta_verbose ("_NET_WM_STRUT struts %u %u %u %u for window %s", - struts[0], struts[1], struts[2], struts[3], - window->desc); - } - g_free (struts); - } - else if (!new_struts) - { - meta_verbose ("No _NET_WM_STRUT property for %s", - window->desc); - } - - /* Determine whether old_struts and new_struts are the same */ - old_iter = old_struts; - new_iter = new_struts; - while (old_iter && new_iter) - { - MetaStrut *old_strut = (MetaStrut*) old_iter->data; - MetaStrut *new_strut = (MetaStrut*) new_iter->data; - - if (old_strut->side != new_strut->side || - !meta_rectangle_equal (&old_strut->rect, &new_strut->rect)) - break; - - old_iter = old_iter->next; - new_iter = new_iter->next; - } - changed = (old_iter != NULL || new_iter != NULL); - - /* Update appropriately */ - g_slist_free_full (old_struts, g_free); - window->struts = new_struts; - return changed; -} - -static void -meta_window_x11_get_default_skip_hints (MetaWindow *window, - gboolean *skip_taskbar_out, - gboolean *skip_pager_out) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); - - *skip_taskbar_out = priv->wm_state_skip_taskbar; - *skip_pager_out = priv->wm_state_skip_pager; -} - -static gboolean -meta_window_x11_update_icon (MetaWindow *window, - cairo_surface_t **icon, - cairo_surface_t **mini_icon) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); - - return meta_read_icons (window->display->x11_display, - window->xwindow, - &priv->icon_cache, - priv->wm_hints_pixmap, - priv->wm_hints_mask, - icon, - META_ICON_WIDTH, META_ICON_HEIGHT, - mini_icon, - META_MINI_ICON_WIDTH, META_MINI_ICON_HEIGHT); -} - -static void -meta_window_x11_update_main_monitor (MetaWindow *window, - MetaWindowUpdateMonitorFlags flags) -{ - window->monitor = meta_window_calculate_main_logical_monitor (window); -} - -static void -meta_window_x11_main_monitor_changed (MetaWindow *window, - const MetaLogicalMonitor *old) -{ -} - -static pid_t -meta_window_x11_get_client_pid (MetaWindow *window) -{ - MetaX11Display *x11_display = window->display->x11_display; - xcb_connection_t *xcb = XGetXCBConnection (x11_display->xdisplay); - xcb_res_client_id_spec_t spec = { 0 }; - xcb_res_query_client_ids_cookie_t cookie; - xcb_res_query_client_ids_reply_t *reply = NULL; - - spec.client = window->xwindow; - spec.mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID; - - cookie = xcb_res_query_client_ids (xcb, 1, &spec); - reply = xcb_res_query_client_ids_reply (xcb, cookie, NULL); - - if (reply == NULL) - return 0; - - uint32_t pid = 0, *value; - xcb_res_client_id_value_iterator_t it; - for (it = xcb_res_query_client_ids_ids_iterator (reply); - it.rem; - xcb_res_client_id_value_next (&it)) - { - spec = it.data->spec; - if (spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID) - { - value = xcb_res_client_id_value_value (it.data); - pid = *value; - break; - } - } - - free (reply); - return (pid_t) pid; -} - -static void -meta_window_x11_force_restore_shortcuts (MetaWindow *window, - ClutterInputDevice *source) -{ - /* - * Not needed on X11 because clients can use a keyboard grab - * to bypass the compositor shortcuts. - */ -} - -static gboolean -meta_window_x11_shortcuts_inhibited (MetaWindow *window, - ClutterInputDevice *source) -{ - /* - * On X11, we don't use a shortcuts inhibitor, clients just grab - * the keyboard. - */ - return FALSE; -} - -void -meta_window_x11_set_wm_take_focus (MetaWindow *window, - gboolean take_focus) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = - meta_window_x11_get_instance_private (window_x11); - - priv->wm_take_focus = take_focus; -} - -static gboolean -meta_window_x11_is_focusable (MetaWindow *window) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = - meta_window_x11_get_instance_private (window_x11); - - return window->input || priv->wm_take_focus; -} - -static gboolean -meta_window_x11_is_stackable (MetaWindow *window) -{ - return !window->override_redirect; -} - -static gboolean -meta_window_x11_are_updates_frozen (MetaWindow *window) -{ - if (window->extended_sync_request_counter && - window->sync_request_serial % 2 == 1) - return TRUE; - - if (window->sync_request_serial < window->sync_request_wait_serial) - return TRUE; - - return FALSE; -} - -/* Get layer ignoring any transient or group relationships */ -static MetaStackLayer -get_standalone_layer (MetaWindow *window) -{ - MetaStackLayer layer; - - switch (window->type) - { - case META_WINDOW_DESKTOP: - layer = META_LAYER_DESKTOP; - break; - - case META_WINDOW_DOCK: - if (window->wm_state_below || - (window->monitor && window->monitor->in_fullscreen)) - layer = META_LAYER_BOTTOM; - else - layer = META_LAYER_DOCK; - break; - - case META_WINDOW_DROPDOWN_MENU: - case META_WINDOW_POPUP_MENU: - case META_WINDOW_TOOLTIP: - case META_WINDOW_NOTIFICATION: - case META_WINDOW_COMBO: - case META_WINDOW_OVERRIDE_OTHER: - layer = META_LAYER_OVERRIDE_REDIRECT; - break; - - default: - layer = meta_window_get_default_layer (window); - break; - } - - return layer; -} - -/* Note that this function can never use window->layer only - * get_standalone_layer, or we'd have issues. - */ -static MetaStackLayer -get_maximum_layer_in_group (MetaWindow *window) -{ - GSList *members; - MetaGroup *group; - GSList *tmp; - MetaStackLayer max; - MetaStackLayer layer; - - max = META_LAYER_DESKTOP; - - group = meta_window_get_group (window); - - if (group != NULL) - members = meta_group_list_windows (group); - else - members = NULL; - - tmp = members; - while (tmp != NULL) - { - MetaWindow *w = tmp->data; - - if (!w->override_redirect) - { - layer = get_standalone_layer (w); - if (layer > max) - max = layer; - } - - tmp = tmp->next; - } - - g_slist_free (members); - - return max; -} - -static MetaStackLayer -meta_window_x11_calculate_layer (MetaWindow *window) -{ - MetaStackLayer layer = get_standalone_layer (window); - - /* We can only do promotion-due-to-group for dialogs and other - * transients, or weird stuff happens like the desktop window and - * nautilus windows getting in the same layer, or all gnome-terminal - * windows getting in fullscreen layer if any terminal is - * fullscreen. - */ - if (layer != META_LAYER_DESKTOP && - meta_window_has_transient_type (window) && - window->transient_for == NULL) - { - /* We only do the group thing if the dialog is NOT transient for - * a particular window. Imagine a group with a normal window, a dock, - * and a dialog transient for the normal window; you don't want the dialog - * above the dock if it wouldn't normally be. - */ - - MetaStackLayer group_max; - - group_max = get_maximum_layer_in_group (window); - - if (group_max > layer) - { - meta_topic (META_DEBUG_STACK, - "Promoting window %s from layer %u to %u due to group membership", - window->desc, layer, group_max); - layer = group_max; - } - } - - meta_topic (META_DEBUG_STACK, - "Window %s on layer %u type = %u has_focus = %d", - window->desc, layer, - window->type, window->has_focus); - return layer; -} - -static void -meta_window_x11_impl_freeze_commits (MetaWindow *window) -{ -} - -static void -meta_window_x11_impl_thaw_commits (MetaWindow *window) -{ -} - -static void -meta_window_x11_map (MetaWindow *window) -{ - MetaX11Display *x11_display = window->display->x11_display; - - meta_x11_error_trap_push (x11_display); - XMapWindow (x11_display->xdisplay, window->xwindow); - meta_x11_error_trap_pop (x11_display); -} - -static void -meta_window_x11_unmap (MetaWindow *window) -{ - MetaX11Display *x11_display = window->display->x11_display; - - meta_x11_error_trap_push (x11_display); - XUnmapWindow (x11_display->xdisplay, window->xwindow); - meta_x11_error_trap_pop (x11_display); - window->unmaps_pending ++; -} - -static gboolean -meta_window_x11_impl_always_update_shape (MetaWindow *window) -{ - return FALSE; -} - -static gboolean -meta_window_x11_is_focus_async (MetaWindow *window) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = - meta_window_x11_get_instance_private (window_x11); - - return !window->input && priv->wm_take_focus; -} - -static void -meta_window_x11_class_init (MetaWindowX11Class *klass) -{ - MetaWindowClass *window_class = META_WINDOW_CLASS (klass); - - window_class->manage = meta_window_x11_manage; - window_class->unmanage = meta_window_x11_unmanage; - window_class->ping = meta_window_x11_ping; - window_class->delete = meta_window_x11_delete; - window_class->kill = meta_window_x11_kill; - window_class->focus = meta_window_x11_focus; - window_class->grab_op_began = meta_window_x11_grab_op_began; - window_class->grab_op_ended = meta_window_x11_grab_op_ended; - window_class->current_workspace_changed = meta_window_x11_current_workspace_changed; - window_class->move_resize_internal = meta_window_x11_move_resize_internal; - window_class->update_struts = meta_window_x11_update_struts; - window_class->get_default_skip_hints = meta_window_x11_get_default_skip_hints; - window_class->update_icon = meta_window_x11_update_icon; - window_class->update_main_monitor = meta_window_x11_update_main_monitor; - window_class->main_monitor_changed = meta_window_x11_main_monitor_changed; - window_class->get_client_pid = meta_window_x11_get_client_pid; - window_class->force_restore_shortcuts = meta_window_x11_force_restore_shortcuts; - window_class->shortcuts_inhibited = meta_window_x11_shortcuts_inhibited; - window_class->is_focusable = meta_window_x11_is_focusable; - window_class->is_stackable = meta_window_x11_is_stackable; - window_class->can_ping = meta_window_x11_can_ping; - window_class->are_updates_frozen = meta_window_x11_are_updates_frozen; - window_class->calculate_layer = meta_window_x11_calculate_layer; - window_class->map = meta_window_x11_map; - window_class->unmap = meta_window_x11_unmap; - window_class->is_focus_async = meta_window_x11_is_focus_async; - - klass->freeze_commits = meta_window_x11_impl_freeze_commits; - klass->thaw_commits = meta_window_x11_impl_thaw_commits; - klass->always_update_shape = meta_window_x11_impl_always_update_shape; -} - -void -meta_window_x11_set_net_wm_state (MetaWindow *window) -{ - MetaX11Display *x11_display = window->display->x11_display; - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); - int i; - unsigned long data[13]; - - i = 0; - if (window->shaded) - { - data[i] = x11_display->atom__NET_WM_STATE_SHADED; - ++i; - } - if (priv->wm_state_modal) - { - data[i] = x11_display->atom__NET_WM_STATE_MODAL; - ++i; - } - if (window->skip_pager) - { - data[i] = x11_display->atom__NET_WM_STATE_SKIP_PAGER; - ++i; - } - if (window->skip_taskbar) - { - data[i] = x11_display->atom__NET_WM_STATE_SKIP_TASKBAR; - ++i; - } - if (window->maximized_horizontally) - { - data[i] = x11_display->atom__NET_WM_STATE_MAXIMIZED_HORZ; - ++i; - } - if (window->maximized_vertically) - { - data[i] = x11_display->atom__NET_WM_STATE_MAXIMIZED_VERT; - ++i; - } - if (window->fullscreen) - { - data[i] = x11_display->atom__NET_WM_STATE_FULLSCREEN; - ++i; - } - if (!meta_window_showing_on_its_workspace (window) || window->shaded) - { - data[i] = x11_display->atom__NET_WM_STATE_HIDDEN; - ++i; - } - if (window->wm_state_above) - { - data[i] = x11_display->atom__NET_WM_STATE_ABOVE; - ++i; - } - if (window->wm_state_below) - { - data[i] = x11_display->atom__NET_WM_STATE_BELOW; - ++i; - } - if (window->wm_state_demands_attention) - { - data[i] = x11_display->atom__NET_WM_STATE_DEMANDS_ATTENTION; - ++i; - } - if (window->on_all_workspaces_requested) - { - data[i] = x11_display->atom__NET_WM_STATE_STICKY; - ++i; - } - if (meta_window_appears_focused (window)) - { - data[i] = x11_display->atom__NET_WM_STATE_FOCUSED; - ++i; - } - - meta_verbose ("Setting _NET_WM_STATE with %d atoms", i); - - meta_x11_error_trap_push (x11_display); - XChangeProperty (x11_display->xdisplay, window->xwindow, - x11_display->atom__NET_WM_STATE, - XA_ATOM, - 32, PropModeReplace, (guchar*) data, i); - meta_x11_error_trap_pop (x11_display); - - if (window->fullscreen) - { - if (meta_window_has_fullscreen_monitors (window)) - { - data[0] = - meta_x11_display_logical_monitor_to_xinerama_index (window->display->x11_display, - window->fullscreen_monitors.top); - data[1] = - meta_x11_display_logical_monitor_to_xinerama_index (window->display->x11_display, - window->fullscreen_monitors.bottom); - data[2] = - meta_x11_display_logical_monitor_to_xinerama_index (window->display->x11_display, - window->fullscreen_monitors.left); - data[3] = - meta_x11_display_logical_monitor_to_xinerama_index (window->display->x11_display, - window->fullscreen_monitors.right); - - meta_verbose ("Setting _NET_WM_FULLSCREEN_MONITORS"); - meta_x11_error_trap_push (x11_display); - XChangeProperty (x11_display->xdisplay, - window->xwindow, - x11_display->atom__NET_WM_FULLSCREEN_MONITORS, - XA_CARDINAL, 32, PropModeReplace, - (guchar*) data, 4); - meta_x11_error_trap_pop (x11_display); - } - else - { - meta_verbose ("Clearing _NET_WM_FULLSCREEN_MONITORS"); - meta_x11_error_trap_push (x11_display); - XDeleteProperty (x11_display->xdisplay, - window->xwindow, - x11_display->atom__NET_WM_FULLSCREEN_MONITORS); - meta_x11_error_trap_pop (x11_display); - } - } - - /* Edge constraints */ - update_gtk_edge_constraints (window); -} - -static cairo_region_t * -region_create_from_x_rectangles (const XRectangle *rects, - int n_rects) -{ - int i; - cairo_rectangle_int_t *cairo_rects = g_newa (cairo_rectangle_int_t, n_rects); - - for (i = 0; i < n_rects; i ++) - { - cairo_rects[i].x = rects[i].x; - cairo_rects[i].y = rects[i].y; - cairo_rects[i].width = rects[i].width; - cairo_rects[i].height = rects[i].height; - } - - return cairo_region_create_rectangles (cairo_rects, n_rects); -} - -static void -meta_window_set_input_region (MetaWindow *window, - cairo_region_t *region) -{ - if (cairo_region_equal (window->input_region, region)) - return; - - g_clear_pointer (&window->input_region, cairo_region_destroy); - - if (region != NULL) - window->input_region = cairo_region_reference (region); - - meta_compositor_window_shape_changed (window->display->compositor, window); -} - -#if 0 -/* Print out a region; useful for debugging */ -static void -print_region (cairo_region_t *region) -{ - int n_rects; - int i; - - n_rects = cairo_region_num_rectangles (region); - g_print ("["); - for (i = 0; i < n_rects; i++) - { - cairo_rectangle_int_t rect; - cairo_region_get_rectangle (region, i, &rect); - g_print ("+%d+%dx%dx%d ", - rect.x, rect.y, rect.width, rect.height); - } - g_print ("]\n"); -} -#endif - -void -meta_window_x11_update_input_region (MetaWindow *window) -{ - MetaX11Display *x11_display = window->display->x11_display; - cairo_region_t *region = NULL; - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); - - /* Decorated windows don't have an input region, because - we don't shape the frame to match the client windows - (so the events are blocked by the frame anyway) - */ - if (window->decorated) - { - if (window->input_region) - meta_window_set_input_region (window, NULL); - return; - } - - if (META_X11_DISPLAY_HAS_SHAPE (x11_display)) - { - /* Translate the set of XShape rectangles that we - * get from the X server to a cairo_region. */ - XRectangle *rects = NULL; - int n_rects = -1, ordering; - - meta_x11_error_trap_push (x11_display); - rects = XShapeGetRectangles (x11_display->xdisplay, - window->xwindow, - ShapeInput, - &n_rects, - &ordering); - meta_x11_error_trap_pop (x11_display); - - /* XXX: The X Shape specification is quite unfortunately specified. - * - * By default, the window has a shape the same as its bounding region, - * which we consider "NULL". - * - * If the window sets an empty region, then we'll get n_rects as 0 - * and rects as NULL, which we need to transform back into an empty - * region. - * - * It would be great to have a less-broken extension for this, but - * hey, it's X11! - */ - - if (n_rects == -1) - { - /* We had an error. */ - region = NULL; - } - else if (n_rects == 0) - { - /* Client set an empty region. */ - region = cairo_region_create (); - } - else if (n_rects == 1 && - (rects[0].x == 0 && - rects[0].y == 0 && - rects[0].width == priv->client_rect.width && - rects[0].height == priv->client_rect.height)) - { - /* This is the bounding region case. Keep the - * region as NULL. */ - region = NULL; - } - else - { - /* Window has a custom shape. */ - region = region_create_from_x_rectangles (rects, n_rects); - } - - meta_XFree (rects); - } - - if (region != NULL) - { - cairo_rectangle_int_t client_area; - - client_area.x = 0; - client_area.y = 0; - client_area.width = priv->client_rect.width; - client_area.height = priv->client_rect.height; - - /* The shape we get back from the client may have coordinates - * outside of the frame. The X SHAPE Extension requires that - * the overall shape the client provides never exceeds the - * "bounding rectangle" of the window -- the shape that the - * window would have gotten if it was unshaped. In our case, - * this is simply the client area. - */ - cairo_region_intersect_rectangle (region, &client_area); - } - - meta_window_set_input_region (window, region); - cairo_region_destroy (region); -} - -static void -meta_window_set_shape_region (MetaWindow *window, - cairo_region_t *region) -{ - if (cairo_region_equal (window->shape_region, region)) - return; - - g_clear_pointer (&window->shape_region, cairo_region_destroy); - - if (region != NULL) - window->shape_region = cairo_region_reference (region); - - meta_compositor_window_shape_changed (window->display->compositor, window); -} - -void -meta_window_x11_update_shape_region (MetaWindow *window) -{ - MetaX11Display *x11_display = window->display->x11_display; - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); - cairo_region_t *region = NULL; - - if (META_X11_DISPLAY_HAS_SHAPE (x11_display)) - { - /* Translate the set of XShape rectangles that we - * get from the X server to a cairo_region. */ - XRectangle *rects = NULL; - int n_rects, ordering; - - int x_bounding, y_bounding, x_clip, y_clip; - unsigned w_bounding, h_bounding, w_clip, h_clip; - int bounding_shaped, clip_shaped; - - meta_x11_error_trap_push (x11_display); - XShapeQueryExtents (x11_display->xdisplay, window->xwindow, - &bounding_shaped, &x_bounding, &y_bounding, - &w_bounding, &h_bounding, - &clip_shaped, &x_clip, &y_clip, - &w_clip, &h_clip); - - if (bounding_shaped) - { - rects = XShapeGetRectangles (x11_display->xdisplay, - window->xwindow, - ShapeBounding, - &n_rects, - &ordering); - } - meta_x11_error_trap_pop (x11_display); - - if (rects) - { - region = region_create_from_x_rectangles (rects, n_rects); - XFree (rects); - } - } - - if (region != NULL) - { - cairo_rectangle_int_t client_area; - - client_area.x = 0; - client_area.y = 0; - client_area.width = priv->client_rect.width; - client_area.height = priv->client_rect.height; - - /* The shape we get back from the client may have coordinates - * outside of the frame. The X SHAPE Extension requires that - * the overall shape the client provides never exceeds the - * "bounding rectangle" of the window -- the shape that the - * window would have gotten if it was unshaped. In our case, - * this is simply the client area. - */ - cairo_region_intersect_rectangle (region, &client_area); - /* Some applications might explicitly set their bounding region - * to the client area. Detect these cases, and throw out the - * bounding region in this case for decorated windows. */ - if (window->decorated && - cairo_region_contains_rectangle (region, &client_area) == CAIRO_REGION_OVERLAP_IN) - g_clear_pointer (®ion, cairo_region_destroy); - } - - meta_window_set_shape_region (window, region); - cairo_region_destroy (region); -} - -/* Generally meta_window_same_application() is a better idea - * of "sameness", since it handles the case where multiple apps - * want to look like the same app or the same app wants to look - * like multiple apps, but in the case of workarounds for legacy - * applications (which likely aren't setting the group properly - * anyways), it may be desirable to check this as well. - */ -static gboolean -meta_window_same_client (MetaWindow *window, - MetaWindow *other_window) -{ - int resource_mask = window->display->x11_display->xdisplay->resource_mask; - - return ((window->xwindow & ~resource_mask) == - (other_window->xwindow & ~resource_mask)); -} - -static void -meta_window_move_resize_request (MetaWindow *window, - guint value_mask, - MetaGravity gravity, - int new_x, - int new_y, - int new_width, - int new_height) -{ - int x, y, width, height; - gboolean allow_position_change; - gboolean in_grab_op; - MetaMoveResizeFlags flags; - MetaRectangle buffer_rect; - - /* We ignore configure requests while the user is moving/resizing - * the window, since these represent the app sucking and fighting - * the user, most likely due to a bug in the app (e.g. pfaedit - * seemed to do this) - * - * Still have to do the ConfigureNotify and all, but pretend the - * app asked for the current size/position instead of the new one. - */ - in_grab_op = (window->display->grab_window == window && - meta_grab_op_is_mouse (window->display->grab_op)); - - /* it's essential to use only the explicitly-set fields, - * and otherwise use our current up-to-date position. - * - * Otherwise you get spurious position changes when the app changes - * size, for example, if window->rect is not in sync with the - * server-side position in effect when the configure request was - * generated. - */ - meta_window_get_gravity_position (window, - gravity, - &x, &y); - - allow_position_change = FALSE; - - if (meta_prefs_get_disable_workarounds ()) - { - if (window->type == META_WINDOW_DIALOG || - window->type == META_WINDOW_MODAL_DIALOG || - window->type == META_WINDOW_SPLASHSCREEN) - ; /* No position change for these */ - else if ((window->size_hints.flags & PPosition) || - /* USPosition is just stale if window is placed; - * no --geometry involved here. - */ - ((window->size_hints.flags & USPosition) && - !window->placed)) - allow_position_change = TRUE; - } - else - { - allow_position_change = TRUE; - } - - if (in_grab_op) - allow_position_change = FALSE; - - if (allow_position_change) - { - if (value_mask & CWX) - x = new_x; - if (value_mask & CWY) - y = new_y; - if (value_mask & (CWX | CWY)) - { - /* Once manually positioned, windows shouldn't be placed - * by the window manager. - */ - window->placed = TRUE; - } - } - else - { - meta_topic (META_DEBUG_GEOMETRY, - "Not allowing position change for window %s PPosition 0x%lx USPosition 0x%lx type %u", - window->desc, window->size_hints.flags & PPosition, - window->size_hints.flags & USPosition, - window->type); - } - - meta_window_get_buffer_rect (window, &buffer_rect); - width = buffer_rect.width; - height = buffer_rect.height; - if (!in_grab_op || !meta_grab_op_is_resizing (window->display->grab_op)) - { - if (value_mask & CWWidth) - width = new_width; - - if (value_mask & CWHeight) - height = new_height; - } - - /* ICCCM 4.1.5 */ - - /* We're ignoring the value_mask here, since sizes - * not in the mask will be the current window geometry. - */ - window->size_hints.x = x; - window->size_hints.y = y; - window->size_hints.width = width; - window->size_hints.height = height; - - /* NOTE: We consider ConfigureRequests to be "user" actions in one - * way, but not in another. Explanation of the two cases are in the - * next two big comments. - */ - - /* The constraints code allows user actions to move windows - * offscreen, etc., and configure request actions would often send - * windows offscreen when users don't want it if not constrained - * (e.g. hitting a dropdown triangle in a fileselector to show more - * options, which makes the window bigger). Thus we do not set - * META_MOVE_RESIZE_USER_ACTION in flags to the - * meta_window_move_resize_internal() call. - */ - flags = META_MOVE_RESIZE_CONFIGURE_REQUEST; - if (value_mask & (CWX | CWY)) - flags |= META_MOVE_RESIZE_MOVE_ACTION; - if (value_mask & (CWWidth | CWHeight)) - flags |= META_MOVE_RESIZE_RESIZE_ACTION; - - if (flags & (META_MOVE_RESIZE_MOVE_ACTION | META_MOVE_RESIZE_RESIZE_ACTION)) - { - MetaRectangle rect; - - rect.x = x; - rect.y = y; - rect.width = width; - rect.height = height; - - if (window->monitor) - { - MetaRectangle monitor_rect; - - meta_display_get_monitor_geometry (window->display, - window->monitor->number, - &monitor_rect); - - /* Workaround braindead legacy apps that don't know how to - * fullscreen themselves properly - don't get fooled by - * windows which hide their titlebar when maximized or which are - * client decorated; that's not the same as fullscreen, even - * if there are no struts making the workarea smaller than - * the monitor. - */ - if (meta_prefs_get_force_fullscreen() && - (window->decorated || !meta_window_is_client_decorated (window)) && - meta_rectangle_equal (&rect, &monitor_rect) && - window->has_fullscreen_func && - !window->fullscreen) - { - /* - meta_topic (META_DEBUG_GEOMETRY, - */ - meta_warning ( - "Treating resize request of legacy application %s as a " - "fullscreen request", - window->desc); - meta_window_make_fullscreen_internal (window); - } - } - - adjust_for_gravity (window, TRUE, gravity, &rect); - meta_window_client_rect_to_frame_rect (window, &rect, &rect); - meta_window_move_resize_internal (window, flags, gravity, rect); - } -} - -static void -restack_window (MetaWindow *window, - MetaWindow *sibling, - int direction) -{ - switch (direction) - { - case Above: - if (sibling) - meta_window_stack_just_above (window, sibling); - else - meta_window_raise (window); - break; - case Below: - if (sibling) - meta_window_stack_just_below (window, sibling); - else - meta_window_lower (window); - break; - case TopIf: - case BottomIf: - case Opposite: - break; - } -} - -gboolean -meta_window_x11_configure_request (MetaWindow *window, - XEvent *event) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); - - /* Note that x, y is the corner of the window border, - * and width, height is the size of the window inside - * its border, but that we always deny border requests - * and give windows a border of 0. But we save the - * requested border here. - */ - if (event->xconfigurerequest.value_mask & CWBorderWidth) - priv->border_width = event->xconfigurerequest.border_width; - - meta_window_move_resize_request(window, - event->xconfigurerequest.value_mask, - window->size_hints.win_gravity, - event->xconfigurerequest.x, - event->xconfigurerequest.y, - event->xconfigurerequest.width, - event->xconfigurerequest.height); - - /* Handle stacking. We only handle raises/lowers, mostly because - * stack.c really can't deal with anything else. I guess we'll fix - * that if a client turns up that really requires it. Only a very - * few clients even require the raise/lower (and in fact all client - * attempts to deal with stacking order are essentially broken, - * since they have no idea what other clients are involved or how - * the stack looks). - * - * I'm pretty sure no interesting client uses TopIf, BottomIf, or - * Opposite anyway. - */ - if (event->xconfigurerequest.value_mask & CWStackMode) - { - MetaWindow *active_window; - active_window = window->display->focus_window; - if (meta_prefs_get_disable_workarounds ()) - { - meta_topic (META_DEBUG_STACK, - "%s sent an xconfigure stacking request; this is " - "broken behavior and the request is being ignored.", - window->desc); - } - else if (active_window && - !meta_window_same_application (window, active_window) && - !meta_window_same_client (window, active_window) && - XSERVER_TIME_IS_BEFORE (window->net_wm_user_time, - active_window->net_wm_user_time)) - { - meta_topic (META_DEBUG_STACK, - "Ignoring xconfigure stacking request from %s (with " - "user_time %u); currently active application is %s (with " - "user_time %u).", - window->desc, - window->net_wm_user_time, - active_window->desc, - active_window->net_wm_user_time); - if (event->xconfigurerequest.detail == Above) - meta_window_set_demands_attention(window); - } - else - { - MetaWindow *sibling = NULL; - /* Handle Above/Below with a sibling set */ - if (event->xconfigurerequest.above != None) - { - MetaDisplay *display; - - display = meta_window_get_display (window); - sibling = meta_x11_display_lookup_x_window (display->x11_display, - event->xconfigurerequest.above); - if (sibling == NULL) - return TRUE; - - meta_topic (META_DEBUG_STACK, - "xconfigure stacking request from window %s sibling %s stackmode %d", - window->desc, sibling->desc, event->xconfigurerequest.detail); - } - restack_window (window, sibling, event->xconfigurerequest.detail); - } - } - - return TRUE; -} - -static gboolean -process_property_notify (MetaWindow *window, - XPropertyEvent *event) -{ - Window xid = window->xwindow; - - if (meta_is_verbose ()) /* avoid looking up the name if we don't have to */ - { - char *property_name = XGetAtomName (window->display->x11_display->xdisplay, - event->atom); - - meta_verbose ("Property notify on %s for %s", - window->desc, property_name); - XFree (property_name); - } - - if (event->atom == window->display->x11_display->atom__NET_WM_USER_TIME && - window->user_time_window) - { - xid = window->user_time_window; - } - - meta_window_reload_property_from_xwindow (window, xid, event->atom, FALSE); - - return TRUE; -} - -gboolean -meta_window_x11_property_notify (MetaWindow *window, - XEvent *event) -{ - return process_property_notify (window, &event->xproperty); -} - -#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0 -#define _NET_WM_MOVERESIZE_SIZE_TOP 1 -#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2 -#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3 -#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4 -#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5 -#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6 -#define _NET_WM_MOVERESIZE_SIZE_LEFT 7 -#define _NET_WM_MOVERESIZE_MOVE 8 -#define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 -#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 -#define _NET_WM_MOVERESIZE_CANCEL 11 - -static int -query_pressed_buttons (MetaWindow *window) -{ - MetaCursorTracker *tracker = meta_cursor_tracker_get_for_display (window->display); - ClutterModifierType mods; - int button = 0; - - meta_cursor_tracker_get_pointer (tracker, NULL, &mods); - - if (mods & CLUTTER_BUTTON1_MASK) - button |= 1 << 1; - if (mods & CLUTTER_BUTTON2_MASK) - button |= 1 << 2; - if (mods & CLUTTER_BUTTON3_MASK) - button |= 1 << 3; - - return button; -} - -static void -handle_net_restack_window (MetaDisplay *display, - XEvent *event) -{ - MetaWindow *window, *sibling = NULL; - - /* Ignore if this does not come from a pager, see the WM spec - */ - if (event->xclient.data.l[0] != 2) - return; - - window = meta_x11_display_lookup_x_window (display->x11_display, - event->xclient.window); - - if (window) - { - if (event->xclient.data.l[1]) - sibling = meta_x11_display_lookup_x_window (display->x11_display, - event->xclient.data.l[1]); - - restack_window (window, sibling, event->xclient.data.l[2]); - } -} - -gboolean -meta_window_x11_client_message (MetaWindow *window, - XEvent *event) -{ - MetaX11Display *x11_display = window->display->x11_display; - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); - MetaDisplay *display; - - display = window->display; - - if (window->override_redirect) - { - /* Don't warn here: we could warn on any of the messages below, - * but we might also receive other client messages that are - * part of protocols we don't know anything about. So, silently - * ignoring is simplest. - */ - return FALSE; - } - - if (event->xclient.message_type == - x11_display->atom__NET_CLOSE_WINDOW) - { - guint32 timestamp; - - if (event->xclient.data.l[0] != 0) - timestamp = event->xclient.data.l[0]; - else - { - meta_warning ("Receiving a NET_CLOSE_WINDOW message for %s without " - "a timestamp! This means some buggy (outdated) " - "application is on the loose!", - window->desc); - timestamp = meta_display_get_current_time (window->display); - } - - meta_window_delete (window, timestamp); - - return TRUE; - } - else if (event->xclient.message_type == - x11_display->atom__NET_WM_DESKTOP) - { - int space; - MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; - MetaWorkspace *workspace; - - space = event->xclient.data.l[0]; - - meta_verbose ("Request to move %s to workspace %d", - window->desc, space); - - workspace = - meta_workspace_manager_get_workspace_by_index (workspace_manager, - space); - - if (workspace) - meta_window_change_workspace (window, workspace); - else if (space == (int) 0xFFFFFFFF) - meta_window_stick (window); - else - meta_verbose ("No such workspace %d for screen", space); - - meta_verbose ("Window %s now on_all_workspaces = %d", - window->desc, window->on_all_workspaces); - - return TRUE; - } - else if (event->xclient.message_type == - x11_display->atom__NET_WM_STATE) - { - gulong action; - Atom first; - Atom second; - - action = event->xclient.data.l[0]; - first = event->xclient.data.l[1]; - second = event->xclient.data.l[2]; - - if (meta_is_verbose ()) - { - char *str1; - char *str2; - - meta_x11_error_trap_push (x11_display); - str1 = XGetAtomName (x11_display->xdisplay, first); - if (meta_x11_error_trap_pop_with_return (x11_display) != Success) - str1 = NULL; - - meta_x11_error_trap_push (x11_display); - str2 = XGetAtomName (x11_display->xdisplay, second); - if (meta_x11_error_trap_pop_with_return (x11_display) != Success) - str2 = NULL; - - meta_verbose ("Request to change _NET_WM_STATE action %lu atom1: %s atom2: %s", - action, - str1 ? str1 : "(unknown)", - str2 ? str2 : "(unknown)"); - - meta_XFree (str1); - meta_XFree (str2); - } - - if (first == x11_display->atom__NET_WM_STATE_SHADED || - second == x11_display->atom__NET_WM_STATE_SHADED) - { - gboolean shade; - guint32 timestamp; - - /* Stupid protocol has no timestamp; of course, shading - * sucks anyway so who really cares that we're forced to do - * a roundtrip here? - */ - timestamp = meta_display_get_current_time_roundtrip (window->display); - - shade = (action == _NET_WM_STATE_ADD || - (action == _NET_WM_STATE_TOGGLE && !window->shaded)); - if (shade && window->has_shade_func) - meta_window_shade (window, timestamp); - else - meta_window_unshade (window, timestamp); - } - - if (first == x11_display->atom__NET_WM_STATE_FULLSCREEN || - second == x11_display->atom__NET_WM_STATE_FULLSCREEN) - { - gboolean make_fullscreen; - - make_fullscreen = (action == _NET_WM_STATE_ADD || - (action == _NET_WM_STATE_TOGGLE && !window->fullscreen)); - if (make_fullscreen && window->has_fullscreen_func) - meta_window_make_fullscreen (window); - else - meta_window_unmake_fullscreen (window); - } - - if (first == x11_display->atom__NET_WM_STATE_MAXIMIZED_HORZ || - second == x11_display->atom__NET_WM_STATE_MAXIMIZED_HORZ || - first == x11_display->atom__NET_WM_STATE_MAXIMIZED_VERT || - second == x11_display->atom__NET_WM_STATE_MAXIMIZED_VERT) - { - gboolean max; - MetaMaximizeFlags directions = 0; - - max = (action == _NET_WM_STATE_ADD || - (action == _NET_WM_STATE_TOGGLE && - !window->maximized_horizontally)); - - if (first == x11_display->atom__NET_WM_STATE_MAXIMIZED_HORZ || - second == x11_display->atom__NET_WM_STATE_MAXIMIZED_HORZ) - directions |= META_MAXIMIZE_HORIZONTAL; - - if (first == x11_display->atom__NET_WM_STATE_MAXIMIZED_VERT || - second == x11_display->atom__NET_WM_STATE_MAXIMIZED_VERT) - directions |= META_MAXIMIZE_VERTICAL; - - if (max && window->has_maximize_func) - { - if (meta_prefs_get_raise_on_click ()) - meta_window_raise (window); - meta_window_maximize (window, directions); - } - else - { - if (meta_prefs_get_raise_on_click ()) - meta_window_raise (window); - meta_window_unmaximize (window, directions); - } - } - - if (first == x11_display->atom__NET_WM_STATE_MODAL || - second == x11_display->atom__NET_WM_STATE_MODAL) - { - priv->wm_state_modal = - (action == _NET_WM_STATE_ADD) || - (action == _NET_WM_STATE_TOGGLE && !priv->wm_state_modal); - - meta_window_x11_recalc_window_type (window); - meta_window_queue(window, META_QUEUE_MOVE_RESIZE); - } - - if (first == x11_display->atom__NET_WM_STATE_SKIP_PAGER || - second == x11_display->atom__NET_WM_STATE_SKIP_PAGER) - { - priv->wm_state_skip_pager = - (action == _NET_WM_STATE_ADD) || - (action == _NET_WM_STATE_TOGGLE && !window->skip_pager); - - meta_window_recalc_features (window); - meta_window_x11_set_net_wm_state (window); - } - - if (first == x11_display->atom__NET_WM_STATE_SKIP_TASKBAR || - second == x11_display->atom__NET_WM_STATE_SKIP_TASKBAR) - { - priv->wm_state_skip_taskbar = - (action == _NET_WM_STATE_ADD) || - (action == _NET_WM_STATE_TOGGLE && !window->skip_taskbar); - - meta_window_recalc_features (window); - meta_window_x11_set_net_wm_state (window); - } - - if (first == x11_display->atom__NET_WM_STATE_ABOVE || - second == x11_display->atom__NET_WM_STATE_ABOVE) - { - if ((action == _NET_WM_STATE_ADD) || - (action == _NET_WM_STATE_TOGGLE && !window->wm_state_demands_attention)) - meta_window_make_above (window); - else - meta_window_unmake_above (window); - } - - if (first == x11_display->atom__NET_WM_STATE_BELOW || - second == x11_display->atom__NET_WM_STATE_BELOW) - { - window->wm_state_below = - (action == _NET_WM_STATE_ADD) || - (action == _NET_WM_STATE_TOGGLE && !window->wm_state_below); - - meta_window_update_layer (window); - meta_window_x11_set_net_wm_state (window); - } - - if (first == x11_display->atom__NET_WM_STATE_DEMANDS_ATTENTION || - second == x11_display->atom__NET_WM_STATE_DEMANDS_ATTENTION) - { - if ((action == _NET_WM_STATE_ADD) || - (action == _NET_WM_STATE_TOGGLE && !window->wm_state_demands_attention)) - meta_window_set_demands_attention (window); - else - meta_window_unset_demands_attention (window); - } - - if (first == x11_display->atom__NET_WM_STATE_STICKY || - second == x11_display->atom__NET_WM_STATE_STICKY) - { - if ((action == _NET_WM_STATE_ADD) || - (action == _NET_WM_STATE_TOGGLE && !window->on_all_workspaces_requested)) - meta_window_stick (window); - else - meta_window_unstick (window); - } - - return TRUE; - } - else if (event->xclient.message_type == - x11_display->atom_WM_CHANGE_STATE) - { - meta_verbose ("WM_CHANGE_STATE client message, state: %ld", - event->xclient.data.l[0]); - if (event->xclient.data.l[0] == IconicState) - meta_window_minimize (window); - - return TRUE; - } - else if (event->xclient.message_type == - x11_display->atom__NET_WM_MOVERESIZE) - { - int x_root; - int y_root; - int action; - MetaGrabOp op; - int button; - guint32 timestamp; - - /* _NET_WM_MOVERESIZE messages are almost certainly going to come from - * clients when users click on the fake "frame" that the client has, - * thus we should also treat such messages as though it were a - * "frame action". - */ - gboolean const frame_action = TRUE; - - x_root = event->xclient.data.l[0]; - y_root = event->xclient.data.l[1]; - action = event->xclient.data.l[2]; - button = event->xclient.data.l[3]; - - /* FIXME: What a braindead protocol; no timestamp?!? */ - timestamp = meta_display_get_current_time_roundtrip (display); - meta_topic (META_DEBUG_WINDOW_OPS, - "Received _NET_WM_MOVERESIZE message on %s, %d,%d action = %d, button %d", - window->desc, - x_root, y_root, action, button); - - op = META_GRAB_OP_NONE; - switch (action) - { - case _NET_WM_MOVERESIZE_SIZE_TOPLEFT: - op = META_GRAB_OP_RESIZING_NW; - break; - case _NET_WM_MOVERESIZE_SIZE_TOP: - op = META_GRAB_OP_RESIZING_N; - break; - case _NET_WM_MOVERESIZE_SIZE_TOPRIGHT: - op = META_GRAB_OP_RESIZING_NE; - break; - case _NET_WM_MOVERESIZE_SIZE_RIGHT: - op = META_GRAB_OP_RESIZING_E; - break; - case _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT: - op = META_GRAB_OP_RESIZING_SE; - break; - case _NET_WM_MOVERESIZE_SIZE_BOTTOM: - op = META_GRAB_OP_RESIZING_S; - break; - case _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT: - op = META_GRAB_OP_RESIZING_SW; - break; - case _NET_WM_MOVERESIZE_SIZE_LEFT: - op = META_GRAB_OP_RESIZING_W; - break; - case _NET_WM_MOVERESIZE_MOVE: - op = META_GRAB_OP_MOVING; - break; - case _NET_WM_MOVERESIZE_SIZE_KEYBOARD: - op = META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN; - break; - case _NET_WM_MOVERESIZE_MOVE_KEYBOARD: - op = META_GRAB_OP_KEYBOARD_MOVING; - break; - case _NET_WM_MOVERESIZE_CANCEL: - /* handled below */ - break; - default: - break; - } - - if (action == _NET_WM_MOVERESIZE_CANCEL) - { - meta_display_end_grab_op (window->display, timestamp); - } - else if (op != META_GRAB_OP_NONE && - ((window->has_move_func && op == META_GRAB_OP_KEYBOARD_MOVING) || - (window->has_resize_func && op == META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN))) - { - meta_window_begin_grab_op (window, op, frame_action, timestamp); - } - else if (op != META_GRAB_OP_NONE && - ((window->has_move_func && op == META_GRAB_OP_MOVING) || - (window->has_resize_func && - (op != META_GRAB_OP_MOVING && - op != META_GRAB_OP_KEYBOARD_MOVING)))) - { - int button_mask; - - meta_topic (META_DEBUG_WINDOW_OPS, - "Beginning move/resize with button = %d", button); - meta_display_begin_grab_op (window->display, - window, - op, - FALSE, - frame_action, - button, 0, - timestamp, - x_root, - y_root); - - button_mask = query_pressed_buttons (window); - - if (button == 0) - { - /* - * the button SHOULD already be included in the message - */ - if ((button_mask & (1 << 1)) != 0) - button = 1; - else if ((button_mask & (1 << 2)) != 0) - button = 2; - else if ((button_mask & (1 << 3)) != 0) - button = 3; - - if (button != 0) - window->display->grab_button = button; - else - meta_display_end_grab_op (window->display, - timestamp); - } - else - { - /* There is a potential race here. If the user presses and - * releases their mouse button very fast, it's possible for - * both the ButtonPress and ButtonRelease to be sent to the - * client before it can get a chance to send _NET_WM_MOVERESIZE - * to us. When that happens, we'll become stuck in a grab - * state, as we haven't received a ButtonRelease to cancel the - * grab. - * - * We can solve this by querying after we take the explicit - * pointer grab -- if the button isn't pressed, we cancel the - * drag immediately. - */ - - if ((button_mask & (1 << button)) == 0) - meta_display_end_grab_op (window->display, timestamp); - } - } - - return TRUE; - } - else if (event->xclient.message_type == - x11_display->atom__NET_MOVERESIZE_WINDOW) - { - MetaGravity gravity; - guint value_mask; - - gravity = (MetaGravity) (event->xclient.data.l[0] & 0xff); - value_mask = (event->xclient.data.l[0] & 0xf00) >> 8; - /* source = (event->xclient.data.l[0] & 0xf000) >> 12; */ - - if (gravity == 0) - gravity = window->size_hints.win_gravity; - - meta_window_move_resize_request(window, - value_mask, - gravity, - event->xclient.data.l[1], /* x */ - event->xclient.data.l[2], /* y */ - event->xclient.data.l[3], /* width */ - event->xclient.data.l[4]); /* height */ - } - else if (event->xclient.message_type == - x11_display->atom__NET_ACTIVE_WINDOW) - { - MetaClientType source_indication; - guint32 timestamp; - - meta_verbose ("_NET_ACTIVE_WINDOW request for window '%s', activating", - window->desc); - - source_indication = event->xclient.data.l[0]; - timestamp = event->xclient.data.l[1]; - - if (source_indication > META_CLIENT_TYPE_MAX_RECOGNIZED) - source_indication = META_CLIENT_TYPE_UNKNOWN; - - if (timestamp == 0) - { - /* Client using older EWMH _NET_ACTIVE_WINDOW without a timestamp */ - meta_warning ("Buggy client sent a _NET_ACTIVE_WINDOW message with a " - "timestamp of 0 for %s", - window->desc); - timestamp = meta_display_get_current_time (display); - } - - meta_window_activate_full (window, timestamp, source_indication, NULL); - return TRUE; - } - else if (event->xclient.message_type == - x11_display->atom__NET_WM_FULLSCREEN_MONITORS) - { - MetaLogicalMonitor *top, *bottom, *left, *right; - - meta_verbose ("_NET_WM_FULLSCREEN_MONITORS request for window '%s'", - window->desc); - - top = - meta_x11_display_xinerama_index_to_logical_monitor (window->display->x11_display, - event->xclient.data.l[0]); - bottom = - meta_x11_display_xinerama_index_to_logical_monitor (window->display->x11_display, - event->xclient.data.l[1]); - left = - meta_x11_display_xinerama_index_to_logical_monitor (window->display->x11_display, - event->xclient.data.l[2]); - right = - meta_x11_display_xinerama_index_to_logical_monitor (window->display->x11_display, - event->xclient.data.l[3]); - /* source_indication = event->xclient.data.l[4]; */ - - meta_window_update_fullscreen_monitors (window, top, bottom, left, right); - } - else if (event->xclient.message_type == - x11_display->atom__GTK_SHOW_WINDOW_MENU) - { - gulong x, y; - - /* l[0] is device_id, which we don't use */ - x = event->xclient.data.l[1]; - y = event->xclient.data.l[2]; - - meta_window_show_menu (window, META_WINDOW_MENU_WM, x, y); - } - else if (event->xclient.message_type == - x11_display->atom__NET_RESTACK_WINDOW) - { - handle_net_restack_window (display, event); - } - - return FALSE; -} - -static void -set_wm_state_on_xwindow (MetaDisplay *display, - Window xwindow, - int state) -{ - unsigned long data[2]; - - /* Mutter doesn't use icon windows, so data[1] should be None - * according to the ICCCM 2.0 Section 4.1.3.1. - */ - data[0] = state; - data[1] = None; - - meta_x11_error_trap_push (display->x11_display); - XChangeProperty (display->x11_display->xdisplay, xwindow, - display->x11_display->atom_WM_STATE, - display->x11_display->atom_WM_STATE, - 32, PropModeReplace, (guchar*) data, 2); - meta_x11_error_trap_pop (display->x11_display); -} - -void -meta_window_x11_set_wm_state (MetaWindow *window) -{ - int state; - - if (window->withdrawn) - state = WithdrawnState; - else if (window->iconic) - state = IconicState; - else - state = NormalState; - - set_wm_state_on_xwindow (window->display, window->xwindow, state); -} - -/* The MUTTER_WM_CLASS_FILTER environment variable is designed for - * performance and regression testing environments where we want to do - * tests with only a limited set of windows and ignore all other windows - * - * When it is set to a comma separated list of WM_CLASS class names, all - * windows not matching the list will be ignored. - * - * Returns TRUE if window has been filtered out and should be ignored. - */ -static gboolean -maybe_filter_xwindow (MetaDisplay *display, - Window xwindow, - gboolean must_be_viewable, - XWindowAttributes *attrs) -{ - static char **filter_wm_classes = NULL; - static gboolean initialized = FALSE; - XClassHint class_hint; - gboolean filtered; - Status success; - int i; - - if (!initialized) - { - const char *filter_string = g_getenv ("MUTTER_WM_CLASS_FILTER"); - if (filter_string) - filter_wm_classes = g_strsplit (filter_string, ",", -1); - initialized = TRUE; - } - - if (!filter_wm_classes || !filter_wm_classes[0]) - return FALSE; - - filtered = TRUE; - - meta_x11_error_trap_push (display->x11_display); - success = XGetClassHint (display->x11_display->xdisplay, - xwindow, &class_hint); - - if (success) - { - for (i = 0; filter_wm_classes[i]; i++) - { - if (strcmp (class_hint.res_class, filter_wm_classes[i]) == 0) - { - filtered = FALSE; - break; - } - } - - XFree (class_hint.res_name); - XFree (class_hint.res_class); - } - - if (filtered) - { - /* We want to try and get the window managed by the next WM that come along, - * so we need to make sure that windows that are requested to be mapped while - * Mutter is running (!must_be_viewable), or windows already viewable at startup - * get a non-withdrawn WM_STATE property. Previously unmapped windows are left - * with whatever WM_STATE property they had. - */ - if (!must_be_viewable || attrs->map_state == IsViewable) - { - uint32_t old_state; - - if (!meta_prop_get_cardinal_with_atom_type (display->x11_display, xwindow, - display->x11_display->atom_WM_STATE, - display->x11_display->atom_WM_STATE, - &old_state)) - old_state = WithdrawnState; - - if (old_state == WithdrawnState) - set_wm_state_on_xwindow (display, xwindow, NormalState); - } - - /* Make sure filtered windows are hidden from view */ - XUnmapWindow (display->x11_display->xdisplay, xwindow); - } - - meta_x11_error_trap_pop (display->x11_display); - - return filtered; -} - -static gboolean -is_our_xwindow (MetaX11Display *x11_display, - Window xwindow, - XWindowAttributes *attrs) -{ - if (xwindow == x11_display->no_focus_window) - return TRUE; - - if (xwindow == x11_display->wm_sn_selection_window) - return TRUE; - - if (xwindow == x11_display->wm_cm_selection_window) - return TRUE; - - if (xwindow == x11_display->guard_window) - return TRUE; - - if (xwindow == x11_display->composite_overlay_window) - return TRUE; - - { - MetaBackend *backend = meta_get_backend (); - - if (META_IS_BACKEND_X11 (backend)) - { - if (xwindow == meta_backend_x11_get_xwindow (META_BACKEND_X11 (backend))) - return TRUE; - } - } - - /* Any windows created via meta_create_offscreen_window */ - if (attrs->override_redirect && attrs->x == -100 && attrs->y == -100 && attrs->width == 1 && attrs->height == 1) - return TRUE; - - return FALSE; -} - -#ifdef WITH_VERBOSE_MODE -static const char* -wm_state_to_string (int state) -{ - switch (state) - { - case NormalState: - return "NormalState"; - case IconicState: - return "IconicState"; - case WithdrawnState: - return "WithdrawnState"; - } - - return "Unknown"; -} -#endif - -MetaWindow * -meta_window_x11_new (MetaDisplay *display, - Window xwindow, - gboolean must_be_viewable, - MetaCompEffect effect) -{ - MetaX11Display *x11_display = display->x11_display; - XWindowAttributes attrs; - gulong existing_wm_state; - MetaWindow *window = NULL; - gulong event_mask; - - meta_verbose ("Attempting to manage 0x%lx", xwindow); - - if (meta_x11_display_xwindow_is_a_no_focus_window (x11_display, xwindow)) - { - meta_verbose ("Not managing no_focus_window 0x%lx", - xwindow); - return NULL; - } - - meta_x11_error_trap_push (x11_display); /* Push a trap over all of window - * creation, to reduce XSync() calls - */ - /* - * This function executes without any server grabs held. This means that - * the window could have already gone away, or could go away at any point, - * so we must be careful with X error handling. - */ - - if (!XGetWindowAttributes (x11_display->xdisplay, xwindow, &attrs)) - { - meta_verbose ("Failed to get attributes for window 0x%lx", - xwindow); - goto error; - } - - if (attrs.root != x11_display->xroot) - { - meta_verbose ("Not on our screen"); - goto error; - } - - if (attrs.class == InputOnly) - { - meta_verbose ("Not managing InputOnly windows"); - goto error; - } - - if (is_our_xwindow (x11_display, xwindow, &attrs)) - { - meta_verbose ("Not managing our own windows"); - goto error; - } - - if (maybe_filter_xwindow (display, xwindow, must_be_viewable, &attrs)) - { - meta_verbose ("Not managing filtered window"); - goto error; - } - - existing_wm_state = WithdrawnState; - if (must_be_viewable && attrs.map_state != IsViewable) - { - /* Only manage if WM_STATE is IconicState or NormalState */ - uint32_t state; - - /* WM_STATE isn't a cardinal, it's type WM_STATE, but is an int */ - if (!(meta_prop_get_cardinal_with_atom_type (x11_display, xwindow, - x11_display->atom_WM_STATE, - x11_display->atom_WM_STATE, - &state) && - (state == IconicState || state == NormalState))) - { - meta_verbose ("Deciding not to manage unmapped or unviewable window 0x%lx", - xwindow); - goto error; - } - - existing_wm_state = state; - meta_verbose ("WM_STATE of %lx = %s", xwindow, - wm_state_to_string (existing_wm_state)); - } - - /* - * XAddToSaveSet can only be called on windows created by a different - * client. with Mutter we want to be able to create manageable windows - * from within the process (such as a dummy desktop window). As we do not - * want this call failing to prevent the window from being managed, we - * call this before creating the return-checked error trap. - */ - XAddToSaveSet (x11_display->xdisplay, xwindow); - - meta_x11_error_trap_push (x11_display); - - event_mask = PropertyChangeMask; - if (attrs.override_redirect) - event_mask |= StructureNotifyMask; - - /* If the window is from this client (a menu, say) we need to augment - * the event mask, not replace it. For windows from other clients, - * attrs.your_event_mask will be empty at this point. - */ - XSelectInput (x11_display->xdisplay, xwindow, attrs.your_event_mask | event_mask); - - { - unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 }; - XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits }; - - XISetMask (mask.mask, XI_Enter); - XISetMask (mask.mask, XI_Leave); - XISetMask (mask.mask, XI_FocusIn); - XISetMask (mask.mask, XI_FocusOut); - - XISelectEvents (x11_display->xdisplay, xwindow, &mask, 1); - } - - if (META_X11_DISPLAY_HAS_SHAPE (x11_display)) - XShapeSelectInput (x11_display->xdisplay, xwindow, ShapeNotifyMask); - - /* Get rid of any borders */ - if (attrs.border_width != 0) - XSetWindowBorderWidth (x11_display->xdisplay, xwindow, 0); - - /* Get rid of weird gravities */ - if (attrs.win_gravity != NorthWestGravity) - { - XSetWindowAttributes set_attrs; - - set_attrs.win_gravity = NorthWestGravity; - - XChangeWindowAttributes (x11_display->xdisplay, - xwindow, - CWWinGravity, - &set_attrs); - } - - if (meta_x11_error_trap_pop_with_return (x11_display) != Success) - { - meta_verbose ("Window 0x%lx disappeared just as we tried to manage it", - xwindow); - goto error; - } - - window = _meta_window_shared_new (display, - META_WINDOW_CLIENT_TYPE_X11, - NULL, - xwindow, - existing_wm_state, - effect, - &attrs); - - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); - - priv->border_width = attrs.border_width; - - meta_window_grab_keys (window); - if (window->type != META_WINDOW_DOCK && !window->override_redirect) - { - meta_display_grab_window_buttons (window->display, window->xwindow); - meta_display_grab_focus_window_button (window->display, window); - } - - meta_x11_error_trap_pop (x11_display); /* pop the XSync()-reducing trap */ - return window; - -error: - meta_x11_error_trap_pop (x11_display); - return NULL; -} - -void -meta_window_x11_recalc_window_type (MetaWindow *window) -{ - MetaX11Display *x11_display = window->display->x11_display; - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); - MetaWindowType type; - - if (priv->type_atom != None) - { - if (priv->type_atom == x11_display->atom__NET_WM_WINDOW_TYPE_DESKTOP) - type = META_WINDOW_DESKTOP; - else if (priv->type_atom == x11_display->atom__NET_WM_WINDOW_TYPE_DOCK) - type = META_WINDOW_DOCK; - else if (priv->type_atom == x11_display->atom__NET_WM_WINDOW_TYPE_TOOLBAR) - type = META_WINDOW_TOOLBAR; - else if (priv->type_atom == x11_display->atom__NET_WM_WINDOW_TYPE_MENU) - type = META_WINDOW_MENU; - else if (priv->type_atom == x11_display->atom__NET_WM_WINDOW_TYPE_UTILITY) - type = META_WINDOW_UTILITY; - else if (priv->type_atom == x11_display->atom__NET_WM_WINDOW_TYPE_SPLASH) - type = META_WINDOW_SPLASHSCREEN; - else if (priv->type_atom == x11_display->atom__NET_WM_WINDOW_TYPE_DIALOG) - type = META_WINDOW_DIALOG; - else if (priv->type_atom == x11_display->atom__NET_WM_WINDOW_TYPE_NORMAL) - type = META_WINDOW_NORMAL; - /* The below are *typically* override-redirect windows, but the spec does - * not disallow using them for managed windows. - */ - else if (priv->type_atom == x11_display->atom__NET_WM_WINDOW_TYPE_DROPDOWN_MENU) - type = META_WINDOW_DROPDOWN_MENU; - else if (priv->type_atom == x11_display->atom__NET_WM_WINDOW_TYPE_POPUP_MENU) - type = META_WINDOW_POPUP_MENU; - else if (priv->type_atom == x11_display->atom__NET_WM_WINDOW_TYPE_TOOLTIP) - type = META_WINDOW_TOOLTIP; - else if (priv->type_atom == x11_display->atom__NET_WM_WINDOW_TYPE_NOTIFICATION) - type = META_WINDOW_NOTIFICATION; - else if (priv->type_atom == x11_display->atom__NET_WM_WINDOW_TYPE_COMBO) - type = META_WINDOW_COMBO; - else if (priv->type_atom == x11_display->atom__NET_WM_WINDOW_TYPE_DND) - type = META_WINDOW_DND; - else - { - char *atom_name; - - /* - * Fallback on a normal type, and print warning. Don't abort. - */ - type = META_WINDOW_NORMAL; - - meta_x11_error_trap_push (x11_display); - atom_name = XGetAtomName (x11_display->xdisplay, - priv->type_atom); - meta_x11_error_trap_pop (x11_display); - - meta_warning ("Unrecognized type atom [%s] set for %s ", - atom_name ? atom_name : "unknown", - window->desc); - - if (atom_name) - XFree (atom_name); - } - } - else if (window->transient_for != NULL) - { - type = META_WINDOW_DIALOG; - } - else - { - type = META_WINDOW_NORMAL; - } - - if (type == META_WINDOW_DIALOG && priv->wm_state_modal) - type = META_WINDOW_MODAL_DIALOG; - - /* We don't want to allow override-redirect windows to have decorated-window - * types since that's just confusing. - */ - if (window->override_redirect) - { - switch (type) - { - /* Decorated types */ - case META_WINDOW_NORMAL: - case META_WINDOW_DIALOG: - case META_WINDOW_MODAL_DIALOG: - case META_WINDOW_MENU: - case META_WINDOW_UTILITY: - type = META_WINDOW_OVERRIDE_OTHER; - break; - /* Undecorated types, normally not override-redirect */ - case META_WINDOW_DESKTOP: - case META_WINDOW_DOCK: - case META_WINDOW_TOOLBAR: - case META_WINDOW_SPLASHSCREEN: - /* Undecorated types, normally override-redirect types */ - case META_WINDOW_DROPDOWN_MENU: - case META_WINDOW_POPUP_MENU: - case META_WINDOW_TOOLTIP: - case META_WINDOW_NOTIFICATION: - case META_WINDOW_COMBO: - case META_WINDOW_DND: - /* To complete enum */ - case META_WINDOW_OVERRIDE_OTHER: - break; - } - } - - meta_verbose ("Calculated type %u for %s, old type %u", - type, window->desc, type); - meta_window_set_type (window, type); -} - -/** - * meta_window_x11_configure_notify: (skip) - * @window: a #MetaWindow - * @event: a #XConfigureEvent - * - * This is used to notify us of an unrequested configuration - * (only applicable to override redirect windows) - */ -void -meta_window_x11_configure_notify (MetaWindow *window, - XConfigureEvent *event) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); - - g_assert (window->override_redirect); - g_assert (window->frame == NULL); - - window->rect.x = event->x; - window->rect.y = event->y; - window->rect.width = event->width; - window->rect.height = event->height; - - priv->client_rect = window->rect; - window->buffer_rect = window->rect; - - meta_window_update_monitor (window, META_WINDOW_UPDATE_MONITOR_FLAGS_NONE); - - /* Whether an override-redirect window is considered fullscreen depends - * on its geometry. - */ - if (window->override_redirect) - meta_display_queue_check_fullscreen (window->display); - - if (!event->override_redirect && !event->send_event) - meta_warning ("Unhandled change of windows override redirect status"); - - meta_compositor_sync_window_geometry (window->display->compositor, window, FALSE); -} - -void -meta_window_x11_set_allowed_actions_hint (MetaWindow *window) -{ - MetaX11Display *x11_display = window->display->x11_display; -#define MAX_N_ACTIONS 12 - unsigned long data[MAX_N_ACTIONS]; - int i; - - i = 0; - if (window->has_move_func) - { - data[i] = x11_display->atom__NET_WM_ACTION_MOVE; - ++i; - } - if (window->has_resize_func) - { - data[i] = x11_display->atom__NET_WM_ACTION_RESIZE; - ++i; - } - if (window->has_fullscreen_func) - { - data[i] = x11_display->atom__NET_WM_ACTION_FULLSCREEN; - ++i; - } - if (window->has_minimize_func) - { - data[i] = x11_display->atom__NET_WM_ACTION_MINIMIZE; - ++i; - } - if (window->has_shade_func) - { - data[i] = x11_display->atom__NET_WM_ACTION_SHADE; - ++i; - } - /* sticky according to EWMH is different from mutter's sticky; - * mutter doesn't support EWMH sticky - */ - if (window->has_maximize_func) - { - data[i] = x11_display->atom__NET_WM_ACTION_MAXIMIZE_HORZ; - ++i; - data[i] = x11_display->atom__NET_WM_ACTION_MAXIMIZE_VERT; - ++i; - } - /* We always allow this */ - data[i] = x11_display->atom__NET_WM_ACTION_CHANGE_DESKTOP; - ++i; - if (window->has_close_func) - { - data[i] = x11_display->atom__NET_WM_ACTION_CLOSE; - ++i; - } - - /* I guess we always allow above/below operations */ - data[i] = x11_display->atom__NET_WM_ACTION_ABOVE; - ++i; - data[i] = x11_display->atom__NET_WM_ACTION_BELOW; - ++i; - - g_assert (i <= MAX_N_ACTIONS); - - meta_verbose ("Setting _NET_WM_ALLOWED_ACTIONS with %d atoms", i); - - meta_x11_error_trap_push (x11_display); - XChangeProperty (x11_display->xdisplay, window->xwindow, - x11_display->atom__NET_WM_ALLOWED_ACTIONS, - XA_ATOM, - 32, PropModeReplace, (guchar*) data, i); - meta_x11_error_trap_pop (x11_display); -#undef MAX_N_ACTIONS -} - -void -meta_window_x11_create_sync_request_alarm (MetaWindow *window) -{ - MetaX11Display *x11_display = window->display->x11_display; - XSyncAlarmAttributes values; - XSyncValue init; - - if (window->sync_request_counter == None || - window->sync_request_alarm != None) - return; - - meta_x11_error_trap_push (x11_display); - - /* In the new (extended style), the counter value is initialized by - * the client before mapping the window. In the old style, we're - * responsible for setting the initial value of the counter. - */ - if (window->extended_sync_request_counter) - { - if (!XSyncQueryCounter(x11_display->xdisplay, - window->sync_request_counter, - &init)) - { - meta_x11_error_trap_pop_with_return (x11_display); - window->sync_request_counter = None; - return; - } - - window->sync_request_serial = - XSyncValueLow32 (init) + ((gint64)XSyncValueHigh32 (init) << 32); - } - else - { - XSyncIntToValue (&init, 0); - XSyncSetCounter (x11_display->xdisplay, - window->sync_request_counter, init); - window->sync_request_serial = 0; - } - - values.trigger.counter = window->sync_request_counter; - values.trigger.test_type = XSyncPositiveComparison; - - /* Initialize to one greater than the current value */ - values.trigger.value_type = XSyncRelative; - XSyncIntToValue (&values.trigger.wait_value, 1); - - /* After triggering, increment test_value by this until - * until the test condition is false */ - XSyncIntToValue (&values.delta, 1); - - /* we want events (on by default anyway) */ - values.events = True; - - window->sync_request_alarm = XSyncCreateAlarm (x11_display->xdisplay, - XSyncCACounter | - XSyncCAValueType | - XSyncCAValue | - XSyncCATestType | - XSyncCADelta | - XSyncCAEvents, - &values); - - if (meta_x11_error_trap_pop_with_return (x11_display) == Success) - meta_x11_display_register_sync_alarm (x11_display, &window->sync_request_alarm, window); - else - { - window->sync_request_alarm = None; - window->sync_request_counter = None; - } -} - -void -meta_window_x11_destroy_sync_request_alarm (MetaWindow *window) -{ - MetaX11Display *x11_display = window->display->x11_display; - - if (window->sync_request_alarm != None) - { - /* Has to be unregistered _before_ clearing the structure field */ - meta_x11_display_unregister_sync_alarm (x11_display, window->sync_request_alarm); - XSyncDestroyAlarm (x11_display->xdisplay, - window->sync_request_alarm); - window->sync_request_alarm = None; - } -} - -void -meta_window_x11_update_sync_request_counter (MetaWindow *window, - gint64 new_counter_value) -{ - gboolean needs_frame_drawn = FALSE; - gboolean no_delay_frame = FALSE; - - if (window->extended_sync_request_counter && new_counter_value % 2 == 0) - { - needs_frame_drawn = TRUE; - no_delay_frame = new_counter_value == window->sync_request_serial + 1; - } - - window->sync_request_serial = new_counter_value; - meta_compositor_sync_updates_frozen (window->display->compositor, window); - - if (new_counter_value >= window->sync_request_wait_serial && - window->sync_request_timeout_id) - { - - if (!window->extended_sync_request_counter || - new_counter_value % 2 == 0) - g_clear_handle_id (&window->sync_request_timeout_id, g_source_remove); - - if (window == window->display->grab_window && - meta_grab_op_is_resizing (window->display->grab_op) && - (!window->extended_sync_request_counter || - new_counter_value % 2 == 0)) - { - meta_topic (META_DEBUG_RESIZING, - "Alarm event received last motion x = %d y = %d", - window->display->grab_latest_motion_x, - window->display->grab_latest_motion_y); - - /* This means we are ready for another configure; - * no pointer round trip here, to keep in sync */ - meta_window_update_resize (window, - window->display->grab_last_edge_resistance_flags, - window->display->grab_latest_motion_x, - window->display->grab_latest_motion_y, - TRUE); - } - } - - /* If sync was previously disabled, turn it back on and hope - * the application has come to its senses (maybe it was just - * busy with a pagefault or a long computation). - */ - window->disable_sync = FALSE; - - if (needs_frame_drawn) - meta_compositor_queue_frame_drawn (window->display->compositor, window, - no_delay_frame); -} - -Window -meta_window_x11_get_toplevel_xwindow (MetaWindow *window) -{ - return window->frame ? window->frame->xwindow : window->xwindow; -} - -void -meta_window_x11_freeze_commits (MetaWindow *window) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - META_WINDOW_X11_GET_CLASS (window_x11)->freeze_commits (window); -} - -void -meta_window_x11_thaw_commits (MetaWindow *window) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - META_WINDOW_X11_GET_CLASS (window_x11)->thaw_commits (window); -} - -void -meta_window_x11_set_thaw_after_paint (MetaWindow *window, - gboolean thaw_after_paint) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); - - priv->thaw_after_paint = thaw_after_paint; -} - -gboolean -meta_window_x11_should_thaw_after_paint (MetaWindow *window) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); - - return priv->thaw_after_paint; -} - -gboolean -meta_window_x11_always_update_shape (MetaWindow *window) -{ - MetaWindowX11 *window_x11 = META_WINDOW_X11 (window); - - return META_WINDOW_X11_GET_CLASS (window_x11)->always_update_shape (window); -} - -void -meta_window_x11_surface_rect_to_frame_rect (MetaWindow *window, - MetaRectangle *surface_rect, - MetaRectangle *frame_rect) - -{ - MetaFrameBorders borders; - - g_return_if_fail (window->frame); - - meta_frame_calc_borders (window->frame, &borders); - - *frame_rect = *surface_rect; - frame_rect->x += borders.invisible.left; - frame_rect->y += borders.invisible.top; - frame_rect->width -= borders.invisible.left + borders.invisible.right; - frame_rect->height -= borders.invisible.top + borders.invisible.bottom; -} - -void -meta_window_x11_surface_rect_to_client_rect (MetaWindow *window, - MetaRectangle *surface_rect, - MetaRectangle *client_rect) -{ - MetaFrameBorders borders; - - meta_frame_calc_borders (window->frame, &borders); - - *client_rect = *surface_rect; - client_rect->x += borders.total.left; - client_rect->y += borders.total.top; - client_rect->width -= borders.total.left + borders.total.right; - client_rect->height -= borders.total.top + borders.total.bottom; -} - -MetaRectangle -meta_window_x11_get_client_rect (MetaWindowX11 *window_x11) -{ - MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); - - return priv->client_rect; -} - -static gboolean -has_requested_bypass_compositor (MetaWindowX11 *window_x11) -{ - MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); - - return priv->bypass_compositor == META_BYPASS_COMPOSITOR_HINT_ON; -} - -static gboolean -has_requested_dont_bypass_compositor (MetaWindowX11 *window_x11) -{ - MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11); - - return priv->bypass_compositor == META_BYPASS_COMPOSITOR_HINT_OFF; -} - -gboolean -meta_window_x11_can_unredirect (MetaWindowX11 *window_x11) -{ - MetaWindow *window = META_WINDOW (window_x11); - - if (has_requested_dont_bypass_compositor (window_x11)) - return FALSE; - - if (window->opacity != 0xFF) - return FALSE; - - if (window->shape_region != NULL) - return FALSE; - - if (!window->monitor) - return FALSE; - - if (window->fullscreen) - return TRUE; - - if (meta_window_is_screen_sized (window)) - return TRUE; - - if (has_requested_bypass_compositor (window_x11)) - return TRUE; - - if (window->override_redirect) - { - MetaRectangle window_rect; - MetaRectangle logical_monitor_layout; - MetaLogicalMonitor *logical_monitor = window->monitor; - - meta_window_get_frame_rect (window, &window_rect); - logical_monitor_layout = - meta_logical_monitor_get_layout (logical_monitor); - - if (meta_rectangle_equal (&window_rect, &logical_monitor_layout)) - return TRUE; - } - - return FALSE; -} diff --git a/src/x11/window-x11.h b/src/x11/window-x11.h deleted file mode 100644 index 5e45adf57..000000000 --- a/src/x11/window-x11.h +++ /dev/null @@ -1,103 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002 Red Hat, Inc. - * Copyright (C) 2003, 2004 Rob Adams - * Copyright (C) 2004-2006 Elijah Newren - * - * 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 . - */ - -#ifndef META_WINDOW_X11_H -#define META_WINDOW_X11_H - -#include - -#include "core/window-private.h" -#include "meta/compositor.h" -#include "meta/window.h" - -G_BEGIN_DECLS - -#define META_TYPE_WINDOW_X11 (meta_window_x11_get_type()) -G_DECLARE_DERIVABLE_TYPE (MetaWindowX11, meta_window_x11, - META, WINDOW_X11, MetaWindow) - -struct _MetaWindowX11Class -{ - MetaWindowClass parent_class; - - void (*freeze_commits) (MetaWindow *window); - void (*thaw_commits) (MetaWindow *window); - gboolean (*always_update_shape) (MetaWindow *window); -}; - -MetaWindow * meta_window_x11_new (MetaDisplay *display, - Window xwindow, - gboolean must_be_viewable, - MetaCompEffect effect); - -void meta_window_x11_set_net_wm_state (MetaWindow *window); -void meta_window_x11_set_wm_state (MetaWindow *window); -void meta_window_x11_set_wm_take_focus (MetaWindow *window, - gboolean take_focus); -void meta_window_x11_set_wm_ping (MetaWindow *window, - gboolean ping); -void meta_window_x11_set_wm_delete_window (MetaWindow *window, - gboolean delete_window); -void meta_window_x11_set_allowed_actions_hint (MetaWindow *window); - -void meta_window_x11_create_sync_request_alarm (MetaWindow *window); -void meta_window_x11_destroy_sync_request_alarm (MetaWindow *window); -void meta_window_x11_update_sync_request_counter (MetaWindow *window, - gint64 new_counter_value); - -void meta_window_x11_update_input_region (MetaWindow *window); -void meta_window_x11_update_shape_region (MetaWindow *window); - -void meta_window_x11_recalc_window_type (MetaWindow *window); - -gboolean meta_window_x11_configure_request (MetaWindow *window, - XEvent *event); -gboolean meta_window_x11_property_notify (MetaWindow *window, - XEvent *event); -gboolean meta_window_x11_client_message (MetaWindow *window, - XEvent *event); - -void meta_window_x11_configure_notify (MetaWindow *window, - XConfigureEvent *event); - -Window meta_window_x11_get_toplevel_xwindow (MetaWindow *window); - -void meta_window_x11_freeze_commits (MetaWindow *window); -void meta_window_x11_thaw_commits (MetaWindow *window); - -void meta_window_x11_set_thaw_after_paint (MetaWindow *window, - gboolean thaw_after_paint); -gboolean meta_window_x11_should_thaw_after_paint (MetaWindow *window); -gboolean meta_window_x11_always_update_shape (MetaWindow *window); - -void meta_window_x11_surface_rect_to_frame_rect (MetaWindow *window, - MetaRectangle *surface_rect, - MetaRectangle *frame_rect); -void meta_window_x11_surface_rect_to_client_rect (MetaWindow *window, - MetaRectangle *surface_rect, - MetaRectangle *client_rect); - -MetaRectangle meta_window_x11_get_client_rect (MetaWindowX11 *window_x11); - -gboolean meta_window_x11_can_unredirect (MetaWindowX11 *window_x11); - -#endif diff --git a/src/x11/xprops.c b/src/x11/xprops.c deleted file mode 100644 index 729d5b684..000000000 --- a/src/x11/xprops.c +++ /dev/null @@ -1,1126 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter X property convenience routines */ - -/* - * Copyright (C) 2001 Havoc Pennington - * Copyright (C) 2002 Red Hat Inc. - * - * Some trivial property-unpacking code from Xlib: - * Copyright 1987, 1988, 1998 The Open Group - * Copyright 1988 by Wyse Technology, Inc., San Jose, Ca, - * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, - * - * 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 . - */ - -/*********************************************************** -Copyright 1988 by Wyse Technology, Inc., San Jose, Ca, -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL AND WYSE DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO -EVENT SHALL DIGITAL OR WYSE BE LIABLE FOR ANY SPECIAL, INDIRECT OR -CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF -USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. - -******************************************************************/ - -/* - -Copyright 1987, 1988, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall -not be used in advertising or otherwise to promote the sale, use or -other dealings in this Software without prior written authorization -from The Open Group. - -*/ - - -#include "config.h" - -#include "x11/xprops.h" - -#include -#include -#include -#include - -#include "core/util-private.h" -#include "core/window-private.h" -#include "meta/meta-x11-errors.h" -#include "ui/ui.h" -#include "x11/meta-x11-display-private.h" -#include "x11/mutter-Xatomtype.h" - -typedef struct -{ - MetaX11Display *x11_display; - Window xwindow; - Atom xatom; - Atom type; - int format; - unsigned long n_items; - unsigned long bytes_after; - unsigned char *prop; -} GetPropertyResults; - -static gboolean -validate_or_free_results (GetPropertyResults *results, - int expected_format, - Atom expected_type, - gboolean must_have_items) -{ - MetaX11Display *x11_display = results->x11_display; - char *type_name; - char *expected_name; - char *prop_name; - const char *title; - const char *res_class; - const char *res_name; - MetaWindow *w; - - if (expected_format == results->format && - expected_type == results->type && - (!must_have_items || results->n_items > 0)) - return TRUE; - - meta_x11_error_trap_push (x11_display); - type_name = XGetAtomName (x11_display->xdisplay, results->type); - expected_name = XGetAtomName (x11_display->xdisplay, expected_type); - prop_name = XGetAtomName (x11_display->xdisplay, results->xatom); - meta_x11_error_trap_pop (x11_display); - - w = meta_x11_display_lookup_x_window (x11_display, results->xwindow); - - if (w != NULL) - { - title = w->title; - res_class = w->res_class; - res_name = w->res_name; - } - else - { - title = NULL; - res_class = NULL; - res_name = NULL; - } - - if (title == NULL) - title = "unknown"; - - if (res_class == NULL) - res_class = "unknown"; - - if (res_name == NULL) - res_name = "unknown"; - - meta_warning ("Window 0x%lx has property %s that was expected to have type %s format %d and actually has type %s format %d n_items %d. This is most likely an application bug, not a window manager bug. The window has title=\"%s\" class=\"%s\" name=\"%s\"", - results->xwindow, - prop_name ? prop_name : "(bad atom)", - expected_name ? expected_name : "(bad atom)", - expected_format, - type_name ? type_name : "(bad atom)", - results->format, (int) results->n_items, - title, res_class, res_name); - - meta_XFree (type_name); - meta_XFree (expected_name); - meta_XFree (prop_name); - - if (results->prop) - { - g_free (results->prop); - results->prop = NULL; - } - - return FALSE; -} - -static xcb_get_property_cookie_t -async_get_property (xcb_connection_t *xcb_conn, Window xwindow, - Atom xatom, Atom required_type) -{ - return xcb_get_property (xcb_conn, False, xwindow, - xatom, required_type, 0, G_MAXUINT32); -} - -static gboolean -async_get_property_finish (xcb_connection_t *xcb_conn, - xcb_get_property_cookie_t cookie, - GetPropertyResults *results) -{ - g_autofree xcb_get_property_reply_t *reply = NULL; - g_autofree xcb_generic_error_t *error = NULL; - int length; - - reply = xcb_get_property_reply (xcb_conn, cookie, &error); - if (error || !reply) - return FALSE; - - results->n_items = reply->value_len; - results->type = reply->type; - results->bytes_after = reply->bytes_after; - results->format = reply->format; - results->prop = NULL; - - if (results->type != None) - { - length = xcb_get_property_value_length (reply); - /* Leave room for a trailing '\0' since xcb doesn't return null-terminated - * strings - */ - results->prop = g_malloc (length + 1); - memcpy (results->prop, xcb_get_property_value (reply), length); - results->prop[length] = '\0'; - } - - return (results->prop != NULL); -} - -static gboolean -get_property (MetaX11Display *x11_display, - Window xwindow, - Atom xatom, - Atom req_type, - GetPropertyResults *results) -{ - xcb_get_property_cookie_t cookie; - xcb_connection_t *xcb_conn = XGetXCBConnection (x11_display->xdisplay); - - results->x11_display = x11_display; - results->xwindow = xwindow; - results->xatom = xatom; - results->prop = NULL; - results->n_items = 0; - results->type = None; - results->bytes_after = 0; - results->format = 0; - - cookie = async_get_property (xcb_conn, xwindow, xatom, req_type); - return async_get_property_finish (xcb_conn, cookie, results); -} - -static gboolean -atom_list_from_results (GetPropertyResults *results, - uint32_t **atoms_p, - int *n_atoms_p) -{ - if (!validate_or_free_results (results, 32, XA_ATOM, FALSE)) - return FALSE; - - *atoms_p = (uint32_t*) results->prop; - *n_atoms_p = results->n_items; - results->prop = NULL; - - return TRUE; -} - -static gboolean -cardinal_list_from_results (GetPropertyResults *results, - uint32_t **cardinals_p, - int *n_cardinals_p) -{ - if (!validate_or_free_results (results, 32, XA_CARDINAL, FALSE)) - return FALSE; - - *cardinals_p = (uint32_t *) results->prop; - *n_cardinals_p = results->n_items; - results->prop = NULL; - - return TRUE; -} - -gboolean -meta_prop_get_cardinal_list (MetaX11Display *x11_display, - Window xwindow, - Atom xatom, - uint32_t **cardinals_p, - int *n_cardinals_p) -{ - GetPropertyResults results; - - *cardinals_p = NULL; - *n_cardinals_p = 0; - - if (!get_property (x11_display, xwindow, xatom, XA_CARDINAL, - &results)) - return FALSE; - - return cardinal_list_from_results (&results, cardinals_p, n_cardinals_p); -} - -static gboolean -motif_hints_from_results (GetPropertyResults *results, - MotifWmHints **hints_p) -{ - *hints_p = NULL; - - if (results->type == None || results->n_items <= 0) - { - g_free (results->prop); - results->prop = NULL; - meta_verbose ("Motif hints had unexpected type or n_items"); - return FALSE; - } - - /* The issue here is that some old crufty code will set a smaller - * MotifWmHints than the one we expect, apparently. I'm not sure of - * the history behind it. See bug #89841 for example. - */ - *hints_p = g_new0 (MotifWmHints, 1); - memcpy(*hints_p, results->prop, MIN (sizeof (MotifWmHints), - results->n_items * sizeof (uint32_t))); - - g_free (results->prop); - results->prop = NULL; - - return TRUE; -} - -gboolean -meta_prop_get_motif_hints (MetaX11Display *x11_display, - Window xwindow, - Atom xatom, - MotifWmHints **hints_p) -{ - GetPropertyResults results; - - *hints_p = NULL; - - if (!get_property (x11_display, xwindow, xatom, AnyPropertyType, - &results)) - return FALSE; - - return motif_hints_from_results (&results, hints_p); -} - -static gboolean -latin1_string_from_results (GetPropertyResults *results, - char **str_p) -{ - *str_p = NULL; - - if (!validate_or_free_results (results, 8, XA_STRING, FALSE)) - return FALSE; - - *str_p = g_strndup ((char *) results->prop, results->n_items); - - g_free (results->prop); - results->prop = NULL; - - return TRUE; -} - -gboolean -meta_prop_get_latin1_string (MetaX11Display *x11_display, - Window xwindow, - Atom xatom, - char **str_p) -{ - GetPropertyResults results; - - *str_p = NULL; - - if (!get_property (x11_display, xwindow, xatom, XA_STRING, - &results)) - return FALSE; - - return latin1_string_from_results (&results, str_p); -} - -static gboolean -utf8_string_from_results (GetPropertyResults *results, - char **str_p) -{ - *str_p = NULL; - - if (!validate_or_free_results (results, 8, - results->x11_display->atom_UTF8_STRING, FALSE)) - return FALSE; - - if (results->n_items > 0 && - !g_utf8_validate ((gchar *)results->prop, results->n_items, NULL)) - { - char *name; - - name = XGetAtomName (results->x11_display->xdisplay, results->xatom); - meta_warning ("Property %s on window 0x%lx contained invalid UTF-8", - name, results->xwindow); - meta_XFree (name); - g_free (results->prop); - results->prop = NULL; - - return FALSE; - } - - *str_p = g_strndup ((char *) results->prop, results->n_items); - - g_free (results->prop); - results->prop = NULL; - - return TRUE; -} - -/* this one freakishly returns g_malloc memory */ -static gboolean -utf8_list_from_results (GetPropertyResults *results, - char ***str_p, - int *n_str_p) -{ - int i; - int n_strings; - char **retval; - const char *p; - - *str_p = NULL; - *n_str_p = 0; - - if (!validate_or_free_results (results, 8, - results->x11_display->atom_UTF8_STRING, FALSE)) - return FALSE; - - /* I'm not sure this is right, but I'm guessing the - * property is nul-separated - */ - i = 0; - n_strings = 0; - while (i < (int) results->n_items) - { - if (results->prop[i] == '\0') - ++n_strings; - ++i; - } - - if (results->prop[results->n_items - 1] != '\0') - ++n_strings; - - /* we're guaranteed that results->prop has a nul on the end - * by XGetWindowProperty - */ - - retval = g_new0 (char*, n_strings + 1); - - p = (char *)results->prop; - i = 0; - while (i < n_strings) - { - if (!g_utf8_validate (p, -1, NULL)) - { - char *name; - - meta_x11_error_trap_push (results->x11_display); - name = XGetAtomName (results->x11_display->xdisplay, results->xatom); - meta_x11_error_trap_pop (results->x11_display); - meta_warning ("Property %s on window 0x%lx contained invalid UTF-8 for item %d in the list", - name, results->xwindow, i); - meta_XFree (name); - g_free (results->prop); - results->prop = NULL; - - g_strfreev (retval); - return FALSE; - } - - retval[i] = g_strdup (p); - - p = p + strlen (p) + 1; - ++i; - } - - *str_p = retval; - *n_str_p = i; - - g_free (results->prop); - results->prop = NULL; - - return TRUE; -} - -/* returns g_malloc not Xmalloc memory */ -gboolean -meta_prop_get_utf8_list (MetaX11Display *x11_display, - Window xwindow, - Atom xatom, - char ***str_p, - int *n_str_p) -{ - GetPropertyResults results; - - *str_p = NULL; - - if (!get_property (x11_display, xwindow, xatom, - x11_display->atom_UTF8_STRING, - &results)) - return FALSE; - - return utf8_list_from_results (&results, str_p, n_str_p); -} - -void -meta_prop_set_utf8_string_hint (MetaX11Display *x11_display, - Window xwindow, - Atom atom, - const char *val) -{ - meta_x11_error_trap_push (x11_display); - XChangeProperty (x11_display->xdisplay, - xwindow, atom, - x11_display->atom_UTF8_STRING, - 8, PropModeReplace, (guchar*) val, strlen (val)); - meta_x11_error_trap_pop (x11_display); -} - -static gboolean -window_from_results (GetPropertyResults *results, - Window *window_p) -{ - if (!validate_or_free_results (results, 32, XA_WINDOW, TRUE)) - return FALSE; - - *window_p = *(uint32_t *) results->prop; - g_free (results->prop); - results->prop = NULL; - - return TRUE; -} - -static gboolean -counter_from_results (GetPropertyResults *results, - XSyncCounter *counter_p) -{ - if (!validate_or_free_results (results, 32, - XA_CARDINAL, - TRUE)) - return FALSE; - - *counter_p = *(uint32_t *) results->prop; - g_free (results->prop); - results->prop = NULL; - - return TRUE; -} - -static gboolean -counter_list_from_results (GetPropertyResults *results, - uint32_t **counters_p, - int *n_counters_p) -{ - if (!validate_or_free_results (results, 32, - XA_CARDINAL, - FALSE)) - return FALSE; - - *counters_p = (uint32_t *) results->prop; - *n_counters_p = results->n_items; - results->prop = NULL; - - return TRUE; -} - -gboolean -meta_prop_get_window (MetaX11Display *x11_display, - Window xwindow, - Atom xatom, - Window *window_p) -{ - GetPropertyResults results; - - *window_p = None; - - if (!get_property (x11_display, xwindow, xatom, XA_WINDOW, - &results)) - return FALSE; - - return window_from_results (&results, window_p); -} - -gboolean -meta_prop_get_cardinal (MetaX11Display *x11_display, - Window xwindow, - Atom xatom, - uint32_t *cardinal_p) -{ - return meta_prop_get_cardinal_with_atom_type (x11_display, xwindow, xatom, - XA_CARDINAL, cardinal_p); -} - -static gboolean -cardinal_with_atom_type_from_results (GetPropertyResults *results, - Atom prop_type, - uint32_t *cardinal_p) -{ - if (!validate_or_free_results (results, 32, prop_type, TRUE)) - return FALSE; - - *cardinal_p = *((uint32_t *) results->prop); - g_free (results->prop); - results->prop = NULL; - - return TRUE; -} - -gboolean -meta_prop_get_cardinal_with_atom_type (MetaX11Display *x11_display, - Window xwindow, - Atom xatom, - Atom prop_type, - uint32_t *cardinal_p) -{ - GetPropertyResults results; - - *cardinal_p = 0; - - if (!get_property (x11_display, xwindow, xatom, prop_type, - &results)) - return FALSE; - - return cardinal_with_atom_type_from_results (&results, prop_type, cardinal_p); -} - -static char * -text_property_to_utf8 (GetPropertyResults *results, - const XTextProperty *prop) -{ - char *ret = NULL; - char **local_list = NULL; - const char *charset = NULL; - int count = 0; - int res; - - res = XmbTextPropertyToTextList (results->x11_display->xdisplay, prop, - &local_list, &count); - if (res == XNoMemory || res == XLocaleNotSupported || res == XConverterNotFound) - goto out; - - if (count == 0) - goto out; - - if (g_get_charset (&charset)) - { - if (!g_utf8_validate (local_list[0], -1, NULL)) - { - char *name; - - meta_x11_error_trap_push (results->x11_display); - name = XGetAtomName (results->x11_display->xdisplay, results->xatom); - meta_x11_error_trap_pop (results->x11_display); - meta_warning ("Property %s on window 0x%lx contained invalid UTF-8", - name, results->xwindow); - meta_XFree (name); - - goto out; - } - ret = g_strdup (local_list[0]); - } - else - { - ret = g_convert (local_list[0], -1, "UTF-8", charset, NULL, NULL, NULL); - } - - out: - XFreeStringList (local_list); - return ret; -} - -static gboolean -text_property_from_results (GetPropertyResults *results, - char **utf8_str_p) -{ - XTextProperty tp; - - *utf8_str_p = NULL; - - tp.value = results->prop; - tp.encoding = results->type; - tp.format = results->format; - tp.nitems = results->n_items; - - *utf8_str_p = text_property_to_utf8 (results, &tp); - - g_clear_pointer (&results->prop, g_free); - - return *utf8_str_p != NULL; -} - -static gboolean -wm_hints_from_results (GetPropertyResults *results, - XWMHints **hints_p) -{ - XWMHints *hints; - xPropWMHints *raw; - - *hints_p = NULL; - - if (!validate_or_free_results (results, 32, XA_WM_HINTS, TRUE)) - return FALSE; - - /* pre-R3 bogusly truncated window_group, don't fail on them */ - if (results->n_items < (NumPropWMHintsElements - 1)) - { - meta_verbose ("WM_HINTS property too short: %d should be %d", - (int) results->n_items, NumPropWMHintsElements - 1); - if (results->prop) - { - g_free (results->prop); - results->prop = NULL; - } - return FALSE; - } - - hints = g_new0 (XWMHints, 1); - - raw = (xPropWMHints*) results->prop; - - hints->flags = raw->flags; - hints->input = (raw->input ? True : False); - hints->initial_state = raw->initialState; - hints->icon_pixmap = raw->iconPixmap; - hints->icon_window = raw->iconWindow; - hints->icon_x = raw->iconX; - hints->icon_y = raw->iconY; - hints->icon_mask = raw->iconMask; - if (results->n_items >= NumPropWMHintsElements) - hints->window_group = raw->windowGroup; - else - hints->window_group = 0; - - if (results->prop) - { - g_free (results->prop); - results->prop = NULL; - } - - *hints_p = hints; - - return TRUE; -} - -static gboolean -class_hint_from_results (GetPropertyResults *results, - XClassHint *class_hint) -{ - int len_name; - - class_hint->res_class = NULL; - class_hint->res_name = NULL; - - if (!validate_or_free_results (results, 8, XA_STRING, FALSE)) - return FALSE; - - class_hint->res_name = g_strdup ((char *) results->prop); - - len_name = strlen (class_hint->res_name); - if (len_name == (int) results->n_items) - class_hint->res_class = g_strdup (""); - else - class_hint->res_class = g_strdup ((char *) results->prop + len_name + 1); - - g_free (results->prop); - results->prop = NULL; - - return TRUE; -} - -static gboolean -size_hints_from_results (GetPropertyResults *results, - XSizeHints **hints_p, - gulong *flags_p) -{ - xPropSizeHints *raw; - XSizeHints *hints; - - *hints_p = NULL; - *flags_p = 0; - - if (!validate_or_free_results (results, 32, XA_WM_SIZE_HINTS, FALSE)) - return FALSE; - - if (results->n_items < OldNumPropSizeElements) - { - g_free (results->prop); - results->prop = NULL; - return FALSE; - } - - raw = (xPropSizeHints*) results->prop; - - hints = g_new0 (XSizeHints, 1); - - hints->flags = raw->flags; - hints->x = raw->x; - hints->y = raw->y; - hints->width = raw->width; - hints->height = raw->height; - hints->min_width = raw->minWidth; - hints->min_height = raw->minHeight; - hints->max_width = raw->maxWidth; - hints->max_height = raw->maxHeight; - hints->width_inc = raw->widthInc; - hints->height_inc = raw->heightInc; - hints->min_aspect.x = raw->minAspectX; - hints->min_aspect.y = raw->minAspectY; - hints->max_aspect.x = raw->maxAspectX; - hints->max_aspect.y = raw->maxAspectY; - - *flags_p = (USPosition | USSize | PAllHints); - if (results->n_items >= NumPropSizeElements) - { - hints->base_width = raw->baseWidth; - hints->base_height = raw->baseHeight; - hints->win_gravity = raw->winGravity; - *flags_p |= (PBaseSize | PWinGravity); - } - - hints->flags &= (*flags_p); /* get rid of unwanted bits */ - - g_free (results->prop); - results->prop = NULL; - - *hints_p = hints; - - return TRUE; -} - -static char* -latin1_to_utf8 (const char *text) -{ - GString *str; - const char *p; - - str = g_string_new (""); - - p = text; - while (*p) - { - g_string_append_unichar (str, *p); - ++p; - } - - return g_string_free (str, FALSE); -} - -void -meta_prop_get_values (MetaX11Display *x11_display, - Window xwindow, - MetaPropValue *values, - int n_values) -{ - int i; - xcb_get_property_cookie_t *tasks; - xcb_connection_t *xcb_conn = XGetXCBConnection (x11_display->xdisplay); - - meta_verbose ("Requesting %d properties of 0x%lx at once", - n_values, xwindow); - - if (n_values == 0) - return; - - tasks = g_new0 (xcb_get_property_cookie_t, n_values); - - /* Start up tasks. The "values" array can have values - * with atom == None, which means to ignore that element. - */ - i = 0; - while (i < n_values) - { - if (values[i].required_type == None) - { - switch (values[i].type) - { - case META_PROP_VALUE_INVALID: - /* This means we don't really want a value, e.g. got - * property notify on an atom we don't care about. - */ - if (values[i].atom != None) - meta_bug ("META_PROP_VALUE_INVALID requested in %s", G_STRFUNC); - break; - case META_PROP_VALUE_UTF8_LIST: - case META_PROP_VALUE_UTF8: - values[i].required_type = x11_display->atom_UTF8_STRING; - break; - case META_PROP_VALUE_STRING: - case META_PROP_VALUE_STRING_AS_UTF8: - values[i].required_type = XA_STRING; - break; - case META_PROP_VALUE_MOTIF_HINTS: - values[i].required_type = AnyPropertyType; - break; - case META_PROP_VALUE_CARDINAL_LIST: - case META_PROP_VALUE_CARDINAL: - values[i].required_type = XA_CARDINAL; - break; - case META_PROP_VALUE_WINDOW: - values[i].required_type = XA_WINDOW; - break; - case META_PROP_VALUE_ATOM_LIST: - values[i].required_type = XA_ATOM; - break; - case META_PROP_VALUE_TEXT_PROPERTY: - values[i].required_type = AnyPropertyType; - break; - case META_PROP_VALUE_WM_HINTS: - values[i].required_type = XA_WM_HINTS; - break; - case META_PROP_VALUE_CLASS_HINT: - values[i].required_type = XA_STRING; - break; - case META_PROP_VALUE_SIZE_HINTS: - values[i].required_type = XA_WM_SIZE_HINTS; - break; - case META_PROP_VALUE_SYNC_COUNTER: - case META_PROP_VALUE_SYNC_COUNTER_LIST: - values[i].required_type = XA_CARDINAL; - break; - } - } - - if (values[i].atom != None) - tasks[i] = async_get_property (xcb_conn, xwindow, values[i].atom, values[i].required_type); - ++i; - } - - /* Get replies for all our tasks */ - meta_topic (META_DEBUG_SYNC, "Syncing to get %d GetProperty replies in %s", - n_values, G_STRFUNC); - XSync (x11_display->xdisplay, False); - - /* Collect results, should arrive in order requested */ - i = 0; - while (i < n_values) - { - GetPropertyResults results; - - /* We're relying on the fact that sequence numbers can never be zero - * in Xorg. This is a bit disgusting... */ - if (tasks[i].sequence == 0) - { - /* Probably values[i].type was None, or ag_task_create() - * returned NULL. - */ - values[i].type = META_PROP_VALUE_INVALID; - goto next; - } - - results.x11_display = x11_display; - results.xwindow = xwindow; - results.xatom = values[i].atom; - results.prop = NULL; - results.n_items = 0; - results.type = None; - results.bytes_after = 0; - results.format = 0; - - if (!async_get_property_finish (xcb_conn, tasks[i], &results)) - { - values[i].type = META_PROP_VALUE_INVALID; - goto next; - } - - switch (values[i].type) - { - case META_PROP_VALUE_INVALID: - g_assert_not_reached (); - break; - case META_PROP_VALUE_UTF8_LIST: - if (!utf8_list_from_results (&results, - &values[i].v.string_list.strings, - &values[i].v.string_list.n_strings)) - values[i].type = META_PROP_VALUE_INVALID; - break; - case META_PROP_VALUE_UTF8: - if (!utf8_string_from_results (&results, - &values[i].v.str)) - values[i].type = META_PROP_VALUE_INVALID; - break; - case META_PROP_VALUE_STRING: - if (!latin1_string_from_results (&results, - &values[i].v.str)) - values[i].type = META_PROP_VALUE_INVALID; - break; - case META_PROP_VALUE_STRING_AS_UTF8: - if (!latin1_string_from_results (&results, - &values[i].v.str)) - values[i].type = META_PROP_VALUE_INVALID; - else - { - char *new_str; - new_str = latin1_to_utf8 (values[i].v.str); - g_free (values[i].v.str); - values[i].v.str = new_str; - } - break; - case META_PROP_VALUE_MOTIF_HINTS: - if (!motif_hints_from_results (&results, - &values[i].v.motif_hints)) - values[i].type = META_PROP_VALUE_INVALID; - break; - case META_PROP_VALUE_CARDINAL_LIST: - if (!cardinal_list_from_results (&results, - &values[i].v.cardinal_list.cardinals, - &values[i].v.cardinal_list.n_cardinals)) - values[i].type = META_PROP_VALUE_INVALID; - break; - case META_PROP_VALUE_CARDINAL: - if (!cardinal_with_atom_type_from_results (&results, - values[i].required_type, - &values[i].v.cardinal)) - values[i].type = META_PROP_VALUE_INVALID; - break; - case META_PROP_VALUE_WINDOW: - if (!window_from_results (&results, - &values[i].v.xwindow)) - values[i].type = META_PROP_VALUE_INVALID; - break; - case META_PROP_VALUE_ATOM_LIST: - if (!atom_list_from_results (&results, - &values[i].v.atom_list.atoms, - &values[i].v.atom_list.n_atoms)) - values[i].type = META_PROP_VALUE_INVALID; - break; - case META_PROP_VALUE_TEXT_PROPERTY: - if (!text_property_from_results (&results, &values[i].v.str)) - values[i].type = META_PROP_VALUE_INVALID; - break; - case META_PROP_VALUE_WM_HINTS: - if (!wm_hints_from_results (&results, &values[i].v.wm_hints)) - values[i].type = META_PROP_VALUE_INVALID; - break; - case META_PROP_VALUE_CLASS_HINT: - if (!class_hint_from_results (&results, &values[i].v.class_hint)) - values[i].type = META_PROP_VALUE_INVALID; - break; - case META_PROP_VALUE_SIZE_HINTS: - if (!size_hints_from_results (&results, - &values[i].v.size_hints.hints, - &values[i].v.size_hints.flags)) - values[i].type = META_PROP_VALUE_INVALID; - break; - case META_PROP_VALUE_SYNC_COUNTER: - if (!counter_from_results (&results, - &values[i].v.xcounter)) - values[i].type = META_PROP_VALUE_INVALID; - break; - case META_PROP_VALUE_SYNC_COUNTER_LIST: - if (!counter_list_from_results (&results, - &values[i].v.xcounter_list.counters, - &values[i].v.xcounter_list.n_counters)) - values[i].type = META_PROP_VALUE_INVALID; - break; - } - - next: - ++i; - } - - g_free (tasks); -} - -static void -free_value (MetaPropValue *value) -{ - switch (value->type) - { - case META_PROP_VALUE_INVALID: - break; - case META_PROP_VALUE_UTF8: - case META_PROP_VALUE_STRING: - g_free (value->v.str); - break; - case META_PROP_VALUE_STRING_AS_UTF8: - g_free (value->v.str); - break; - case META_PROP_VALUE_MOTIF_HINTS: - g_free (value->v.motif_hints); - break; - case META_PROP_VALUE_CARDINAL: - break; - case META_PROP_VALUE_WINDOW: - break; - case META_PROP_VALUE_ATOM_LIST: - g_free (value->v.atom_list.atoms); - break; - case META_PROP_VALUE_TEXT_PROPERTY: - g_free (value->v.str); - break; - case META_PROP_VALUE_WM_HINTS: - g_free (value->v.wm_hints); - break; - case META_PROP_VALUE_CLASS_HINT: - g_free (value->v.class_hint.res_class); - g_free (value->v.class_hint.res_name); - break; - case META_PROP_VALUE_SIZE_HINTS: - g_free (value->v.size_hints.hints); - break; - case META_PROP_VALUE_UTF8_LIST: - g_strfreev (value->v.string_list.strings); - break; - case META_PROP_VALUE_CARDINAL_LIST: - g_free (value->v.cardinal_list.cardinals); - break; - case META_PROP_VALUE_SYNC_COUNTER: - break; - case META_PROP_VALUE_SYNC_COUNTER_LIST: - g_free (value->v.xcounter_list.counters); - break; - } -} - -void -meta_prop_free_values (MetaPropValue *values, - int n_values) -{ - int i; - - i = 0; - while (i < n_values) - { - free_value (&values[i]); - ++i; - } - - /* Zero the whole thing to quickly detect breakage */ - memset (values, '\0', sizeof (MetaPropValue) * n_values); -} diff --git a/src/x11/xprops.h b/src/x11/xprops.h deleted file mode 100644 index b8d723f07..000000000 --- a/src/x11/xprops.h +++ /dev/null @@ -1,196 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ - -/* Mutter X property convenience routines */ - -/* - * Copyright (C) 2001 Havoc Pennington - * - * 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 . - */ - -#ifndef META_XPROPS_H -#define META_XPROPS_H - -#include -#include - -#include "meta/display.h" - -/* Copied from Lesstif by way of GTK. Rudimentary docs can be - * found in some Motif reference guides online. - */ -typedef struct { - uint32_t flags; - uint32_t functions; - uint32_t decorations; - uint32_t input_mode; - uint32_t status; -} MotifWmHints, MwmHints; - -#define MWM_HINTS_FUNCTIONS (1L << 0) -#define MWM_HINTS_DECORATIONS (1L << 1) -#define MWM_HINTS_INPUT_MODE (1L << 2) -#define MWM_HINTS_STATUS (1L << 3) - -#define MWM_FUNC_ALL (1L << 0) -#define MWM_FUNC_RESIZE (1L << 1) -#define MWM_FUNC_MOVE (1L << 2) -#define MWM_FUNC_MINIMIZE (1L << 3) -#define MWM_FUNC_MAXIMIZE (1L << 4) -#define MWM_FUNC_CLOSE (1L << 5) - -#define MWM_DECOR_ALL (1L << 0) -#define MWM_DECOR_BORDER (1L << 1) -#define MWM_DECOR_RESIZEH (1L << 2) -#define MWM_DECOR_TITLE (1L << 3) -#define MWM_DECOR_MENU (1L << 4) -#define MWM_DECOR_MINIMIZE (1L << 5) -#define MWM_DECOR_MAXIMIZE (1L << 6) - -#define MWM_INPUT_MODELESS 0 -#define MWM_INPUT_PRIMARY_APPLICATION_MODAL 1 -#define MWM_INPUT_SYSTEM_MODAL 2 -#define MWM_INPUT_FULL_APPLICATION_MODAL 3 -#define MWM_INPUT_APPLICATION_MODAL MWM_INPUT_PRIMARY_APPLICATION_MODAL - -#define MWM_TEAROFF_WINDOW (1L<<0) - -/* These all return the memory from Xlib, so require an XFree() - * when they return TRUE. They return TRUE on success. - */ -gboolean meta_prop_get_motif_hints (MetaX11Display *x11_display, - Window xwindow, - Atom xatom, - MotifWmHints **hints_p); -gboolean meta_prop_get_cardinal_list (MetaX11Display *x11_display, - Window xwindow, - Atom xatom, - uint32_t **cardinals_p, - int *n_cardinals_p); -gboolean meta_prop_get_latin1_string (MetaX11Display *x11_display, - Window xwindow, - Atom xatom, - char **str_p); -gboolean meta_prop_get_utf8_list (MetaX11Display *x11_display, - Window xwindow, - Atom xatom, - char ***str_p, - int *n_str_p); -void meta_prop_set_utf8_string_hint - (MetaX11Display *x11_display, - Window xwindow, - Atom atom, - const char *val); -gboolean meta_prop_get_window (MetaX11Display *x11_display, - Window xwindow, - Atom xatom, - Window *window_p); -gboolean meta_prop_get_cardinal (MetaX11Display *x11_display, - Window xwindow, - Atom xatom, - uint32_t *cardinal_p); -gboolean meta_prop_get_cardinal_with_atom_type (MetaX11Display *x11_display, - Window xwindow, - Atom xatom, - Atom prop_type, - uint32_t *cardinal_p); - -typedef enum -{ - META_PROP_VALUE_INVALID, - META_PROP_VALUE_UTF8, - META_PROP_VALUE_STRING, - META_PROP_VALUE_STRING_AS_UTF8, - META_PROP_VALUE_MOTIF_HINTS, - META_PROP_VALUE_CARDINAL, - META_PROP_VALUE_WINDOW, - META_PROP_VALUE_CARDINAL_LIST, - META_PROP_VALUE_UTF8_LIST, - META_PROP_VALUE_ATOM_LIST, - META_PROP_VALUE_TEXT_PROPERTY, /* comes back as UTF-8 string */ - META_PROP_VALUE_WM_HINTS, - META_PROP_VALUE_CLASS_HINT, - META_PROP_VALUE_SIZE_HINTS, - META_PROP_VALUE_SYNC_COUNTER, /* comes back as CARDINAL */ - META_PROP_VALUE_SYNC_COUNTER_LIST /* comes back as CARDINAL */ -} MetaPropValueType; - -/* used to request/return/store property values */ -typedef struct -{ - MetaPropValueType type; - Atom atom; - Atom required_type; /* autofilled if None */ - - union - { - char *str; - MotifWmHints *motif_hints; - Window xwindow; - uint32_t cardinal; - XWMHints *wm_hints; - XClassHint class_hint; - XSyncCounter xcounter; - struct - { - uint32_t *counters; - int n_counters; - } xcounter_list; - - struct - { - XSizeHints *hints; - unsigned long flags; - } size_hints; - - struct - { - uint32_t *cardinals; - int n_cardinals; - } cardinal_list; - - struct - { - char **strings; - int n_strings; - } string_list; - - struct - { - uint32_t *atoms; - int n_atoms; - } atom_list; - - } v; - -} MetaPropValue; - -/* Each value has type and atom initialized. If there's an error, - * or property is unset, type comes back as INVALID; - * else type comes back as it originated, and the data - * is filled in. - */ -void meta_prop_get_values (MetaX11Display *x11_display, - Window xwindow, - MetaPropValue *values, - int n_values); - -void meta_prop_free_values (MetaPropValue *values, - int n_values); - -#endif - - - - -- cgit v1.2.1