├── .clang-format ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── common.mk ├── config.mk ├── cursor ├── convert_font.c ├── cursor.pcf └── local.mk ├── example ├── local.mk └── wm.c ├── launch ├── devmajor-linux.c ├── devmajor-netbsd.c ├── devmajor.h ├── launch.c ├── local.mk ├── protocol.c └── protocol.h ├── libswc ├── bindings.c ├── bindings.h ├── compositor.c ├── compositor.h ├── data.c ├── data.h ├── data_device.c ├── data_device.h ├── data_device_manager.c ├── data_device_manager.h ├── dmabuf.c ├── dmabuf.h ├── drm.c ├── drm.h ├── event.h ├── input.c ├── input.h ├── internal.h ├── kde_decoration.c ├── kde_decoration.h ├── keyboard.c ├── keyboard.h ├── launch.c ├── launch.h ├── local.mk ├── mode.c ├── mode.h ├── output.c ├── output.h ├── panel.c ├── panel.h ├── panel_manager.c ├── panel_manager.h ├── plane.c ├── plane.h ├── pointer.c ├── pointer.h ├── primary_plane.c ├── primary_plane.h ├── region.c ├── region.h ├── screen.c ├── screen.h ├── seat-ws.c ├── seat.c ├── seat.h ├── shell.c ├── shell.h ├── shell_surface.c ├── shell_surface.h ├── shm.c ├── shm.h ├── subcompositor.c ├── subcompositor.h ├── subsurface.c ├── subsurface.h ├── surface.c ├── surface.h ├── swc.c ├── swc.h ├── util.c ├── util.h ├── view.c ├── view.h ├── wayland_buffer.c ├── wayland_buffer.h ├── window.c ├── window.h ├── wscons │ ├── atKeynames.h │ └── bsd_KbdMap.h ├── xdg_decoration.c ├── xdg_decoration.h ├── xdg_shell.c ├── xdg_shell.h ├── xserver.c ├── xserver.h ├── xwm.c └── xwm.h ├── protocol ├── local.mk ├── server-decoration.xml ├── swc.xml ├── wayland-drm.xml └── xdg-shell.xml └── swc.pc.in /.clang-format: -------------------------------------------------------------------------------- 1 | # clang-format isn't authoritative for the style decisions in this project, but 2 | # these rules mostly align with the suggested style, and clang-format can be 3 | # used fix any potential style-mistakes. 4 | AllowShortBlocksOnASingleLine: false 5 | AllowShortCaseLabelsOnASingleLine: false 6 | AllowShortFunctionsOnASingleLine: false 7 | AllowShortIfStatementsOnASingleLine: false 8 | AllowShortLoopsOnASingleLine: false 9 | AlwaysBreakAfterDefinitionReturnType: true 10 | BinPackArguments: true 11 | BinPackParameters: true 12 | BreakBeforeBinaryOperators: NonAssignment 13 | BreakBeforeBraces: Linux 14 | ColumnLimit: 0 15 | Cpp11BracedListStyle: false 16 | ForEachMacros: [wl_list_for_each, wl_array_for_each, wl_list_for_each_safe, wl_list_for_each_reverse, wl_resource_for_each] 17 | IndentWidth: 8 18 | MaxEmptyLinesToKeep: 1 19 | PointerAlignment: Right 20 | SpaceAfterCStyleCast: false 21 | TabWidth: 8 22 | UseTab: ForIndentation 23 | ... 24 | # vim: ft=yaml 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.lo 3 | .*.sw* 4 | 5 | protocol/server-decoration-protocol.c 6 | protocol/server-decoration-server-protocol.h 7 | protocol/swc-protocol.c 8 | protocol/swc-server-protocol.h 9 | protocol/wayland-drm-protocol.c 10 | protocol/wayland-drm-server-protocol.h 11 | protocol/xdg-decoration-unstable-v1-protocol.c 12 | protocol/xdg-decoration-unstable-v1-server-protocol.h 13 | protocol/xdg-shell-protocol.c 14 | protocol/xdg-shell-server-protocol.h 15 | protocol/linux-dmabuf-unstable-v1-protocol.c 16 | protocol/linux-dmabuf-unstable-v1-server-protocol.h 17 | 18 | /.deps/ 19 | /swc.pc 20 | /libswc/libswc.a 21 | /libswc/libswc.so* 22 | /launch/swc-launch 23 | /cursor/convert_font 24 | /cursor/cursor_data.h 25 | /example/wm 26 | 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013-2019 Michael Forney 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so, 8 | subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | 20 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # swc: Makefile 2 | 3 | .PHONY: all 4 | all: build 5 | 6 | # Defaults for config.mk 7 | PREFIX ?= /usr/local 8 | BINDIR ?= $(PREFIX)/bin 9 | LIBDIR ?= $(PREFIX)/lib 10 | INCLUDEDIR ?= $(PREFIX)/include 11 | DATADIR ?= $(PREFIX)/share 12 | PKGCONFIGDIR ?= $(LIBDIR)/pkgconfig 13 | 14 | OBJCOPY ?= objcopy 15 | PKG_CONFIG ?= pkg-config 16 | WAYLAND_SCANNER ?= wayland-scanner 17 | 18 | VERSION_MAJOR := 0 19 | VERSION_MINOR := 0 20 | VERSION := $(VERSION_MAJOR).$(VERSION_MINOR) 21 | 22 | TARGETS := swc.pc 23 | SUBDIRS := launch libswc protocol cursor example 24 | CLEAN_FILES := $(TARGETS) 25 | 26 | include config.mk 27 | 28 | # Dependencies 29 | PACKAGES := \ 30 | libdrm \ 31 | pixman-1 \ 32 | wayland-server \ 33 | wayland-protocols \ 34 | wld \ 35 | xkbcommon 36 | 37 | ifeq ($(ENABLE_XWAYLAND),1) 38 | PACKAGES += \ 39 | xcb \ 40 | xcb-composite \ 41 | xcb-ewmh \ 42 | xcb-icccm 43 | endif 44 | 45 | ifneq ($(shell uname),NetBSD) 46 | PACKAGES += libinput 47 | ifeq ($(ENABLE_LIBUDEV),1) 48 | PACKAGES += libudev 49 | endif 50 | endif 51 | 52 | libinput_CONSTRAINTS := --atleast-version=0.4 53 | wayland-server_CONSTRAINTS := --atleast-version=1.6.0 54 | 55 | define check 56 | ifeq ($$(origin $(1)_EXISTS),undefined) 57 | $(1)_EXISTS = $$(shell $$(PKG_CONFIG) --exists $$($(1)_CONSTRAINTS) $(1) && echo yes) 58 | endif 59 | ifneq ($$($(1)_EXISTS),yes) 60 | $$(error Could not find package $(1) $$($(1)_CONSTRAINTS)) 61 | endif 62 | endef 63 | 64 | $(foreach pkg,$(PACKAGES),$(eval $(call check,$(pkg)))) 65 | 66 | FINAL_CFLAGS = $(CFLAGS) -fvisibility=hidden -std=c11 67 | FINAL_CPPFLAGS = $(CPPFLAGS) -D_GNU_SOURCE # Required for mkostemp 68 | 69 | # Warning/error flags 70 | FINAL_CFLAGS += -Werror=implicit-function-declaration -Werror=implicit-int \ 71 | -Werror=pointer-sign -Werror=pointer-arith \ 72 | -Wall -Wno-missing-braces 73 | 74 | ifeq ($(ENABLE_DEBUG),1) 75 | FINAL_CPPFLAGS += -DENABLE_DEBUG=1 76 | FINAL_CFLAGS += -g 77 | endif 78 | 79 | ifeq ($(if $(V),$(V),0),0) 80 | quiet = @echo ' $1 $@'; 81 | endif 82 | 83 | Q_AR = $(call quiet,AR ) 84 | Q_CC = $(call quiet,CC ) 85 | Q_CCLD = $(call quiet,CCLD ) 86 | Q_GEN = $(call quiet,GEN ) 87 | Q_OBJCOPY = $(call quiet,OBJCOPY) 88 | Q_SYM = $(call quiet,SYM ) 89 | 90 | compile = $(Q_CC)$(CC) $(FINAL_CPPFLAGS) $(FINAL_CFLAGS) -I . -c -o $@ $< \ 91 | -MMD -MP -MF .deps/$(basename $<).d -MT $(basename $@).o -MT $(basename $@).lo 92 | link = $(Q_CCLD)$(CC) $(LDFLAGS) -o $@ $^ 93 | pkgconfig = $(foreach pkg,$(1),$(if $($(pkg)_$(3)),$($(pkg)_$(3)), \ 94 | $(shell $(PKG_CONFIG) --$(2) $(pkg)))) 95 | 96 | include $(SUBDIRS:%=%/local.mk) 97 | 98 | $(foreach dir,BIN LIB INCLUDE PKGCONFIG,$(DESTDIR)$($(dir)DIR)) $(DESTDIR)$(DATADIR)/swc: 99 | mkdir -p $@ 100 | 101 | .PHONY: build 102 | build: $(SUBDIRS:%=build-%) $(TARGETS) 103 | 104 | REQUIRES := wayland-server 105 | REQUIRES_PRIVATE := $(filter-out $(REQUIRES),$(libswc_PACKAGES)) 106 | SWC_PC_VARS := VERSION PREFIX LIBDIR INCLUDEDIR DATADIR REQUIRES REQUIRES_PRIVATE 107 | 108 | swc.pc: swc.pc.in 109 | $(Q_GEN)sed $(foreach var,$(SWC_PC_VARS),-e 's:@$(var)@:$($(var)):') $< >$@ 110 | 111 | .PHONY: install-swc.pc 112 | install-swc.pc: swc.pc | $(DESTDIR)$(PKGCONFIGDIR) 113 | install -m 644 $< $(DESTDIR)$(PKGCONFIGDIR) 114 | 115 | .PHONY: install 116 | install: $(SUBDIRS:%=install-%) $(TARGETS:%=install-%) 117 | 118 | .PHONY: clean 119 | clean: 120 | rm -f $(CLEAN_FILES) 121 | 122 | -include .deps/*/*.d 123 | 124 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | swc 2 | === 3 | swc is a small Wayland compositor implemented as a library. 4 | 5 | It has been designed primary with tiling window managers in mind. Additionally, 6 | notable features include: 7 | 8 | * Easy to follow code base 9 | * XWayland support 10 | * Can place borders around windows 11 | 12 | Dependencies 13 | ------------ 14 | * wayland 15 | * wayland-protocols 16 | * libdrm 17 | * libinput (on Linux only; see my 18 | [libinput repository](https://github.com/oasislinux/libinput) if you don't 19 | want the libudev dependency) 20 | * libxkbcommon 21 | * pixman 22 | * [wld](http://github.com/michaelforney/wld) 23 | * linux\[>=3.12\] (for EVIOCREVOKE) or NetBSD\[>=9.0\] 24 | 25 | For input hotplugging on Linux, the following is also required: 26 | * libudev 27 | 28 | For XWayland support, the following are also required: 29 | * libxcb 30 | * xcb-util-wm 31 | 32 | Implementing a window manager using swc 33 | --------------------------------------- 34 | You must implement two callback functions, `new_window` and `new_screen`, which 35 | get called when a new window or screen is created. In `new_window`, you should 36 | allocate your own window window structure, and register a listener for the 37 | window's event signal. More information can be found in `swc.h`. 38 | 39 | ```C 40 | static void new_window(struct swc_window * window) 41 | { 42 | /* TODO: Implement */ 43 | } 44 | 45 | static void new_screen(struct swc_screen * screen) 46 | { 47 | /* TODO: Implement */ 48 | } 49 | ``` 50 | 51 | Create a `struct swc_manager` containing pointers to these functions. 52 | 53 | ```C 54 | static const struct swc_manager manager = { &new_screen, &new_window }; 55 | ``` 56 | 57 | In your startup code, you must create a Wayland display. 58 | 59 | ```C 60 | display = wl_display_create(); 61 | ``` 62 | 63 | Then call `swc_initialize`. 64 | 65 | ```C 66 | swc_initialize(display, NULL, &manager); 67 | ``` 68 | 69 | Finally, run the main event loop. 70 | 71 | ```C 72 | wl_display_run(display); 73 | ``` 74 | 75 | An example window manager that arranges it's windows in a grid can be found in 76 | example/, and can be built with `make example`. 77 | 78 | Why not write a Weston shell plugin? 79 | ------------------------------------ 80 | In my opinion the goals of Weston and swc are rather orthogonal. Weston seeks to 81 | demonstrate many of the features possible with the Wayland protocol, with 82 | various types of backends and shells supported, while swc aims to provide only 83 | what's necessary to get windows displayed on the screen. 84 | 85 | I've seen several people look at Wayland, and ask "How can I implement a tiling 86 | window manager using the Wayland protocol?", only to be turned off by the 87 | response "Write a weston shell plugin". Hopefully it is less intimidating to 88 | implement a window manager using swc. 89 | 90 | How can I try out swc? 91 | ---------------------- 92 | 93 | If you are not interested in developing your own window manager, check out my 94 | swc-based window manager, [velox](http://github.com/michaelforney/velox). 95 | 96 | TODO 97 | ---- 98 | * XWayland copy-paste integration. 99 | * Better multi-screen support, including mirroring and screen arrangement. 100 | * DPMS support. 101 | * Floating window Z-ordering. 102 | * Full-screen composite bypass. 103 | * Atomic modesetting support. 104 | 105 | Contact 106 | ------- 107 | 108 | If you have questions or want to discuss swc feel free to join #swc on 109 | [libera.chat](ircs://irc.libera.chat:6697). 110 | 111 | Related projects 112 | ---------------- 113 | 114 | Since swc's creation, several other projects with similar goals have been 115 | created. 116 | 117 | - [wlc](https://github.com/Cloudef/wlc) and 118 | [orbment](https://github.com/Cloudef/orbment) 119 | - [waysome](https://github.com/waysome/waysome) 120 | - [wlroots](https://github.com/swaywm/wlroots) 121 | -------------------------------------------------------------------------------- /common.mk: -------------------------------------------------------------------------------- 1 | # swc: common.mk 2 | 3 | .PHONY: build-$(dir) 4 | build-$(dir): $($(dir)_TARGETS) 5 | 6 | .PHONY: install-$(dir) 7 | install-$(dir): 8 | 9 | .deps/$(dir): 10 | @mkdir -p "$@" 11 | 12 | $(dir)/%: dir := $(dir) 13 | 14 | $(dir)/%.o: $(dir)/%.c | .deps/$(dir) 15 | $(compile) $($(dir)_CFLAGS) $($(dir)_PACKAGE_CFLAGS) 16 | 17 | $(dir)/%.lo: $(dir)/%.c | .deps/$(dir) 18 | $(compile) -fPIC $($(dir)_CFLAGS) $($(dir)_PACKAGE_CFLAGS) 19 | 20 | ifeq ($(origin $(dir)_PACKAGE_CFLAGS),undefined) 21 | $(dir)_PACKAGE_CFLAGS := $(call pkgconfig,$($(dir)_PACKAGES),cflags,CFLAGS) 22 | endif 23 | ifeq ($(origin $(dir)_PACKAGE_LIBS),undefined) 24 | $(dir)_PACKAGE_LIBS := $(call pkgconfig,$($(dir)_PACKAGES),libs,LIBS) 25 | endif 26 | 27 | CLEAN_FILES += $($(dir)_TARGETS) 28 | 29 | -------------------------------------------------------------------------------- /config.mk: -------------------------------------------------------------------------------- 1 | # swc: config.mk 2 | 3 | # The commented out options are defaults 4 | 5 | # PREFIX = /usr/local 6 | # BINDIR = $(PREFIX)/bin 7 | # LIBDIR = $(PREFIX)/lib 8 | # INCLUDEDIR = $(PREFIX)/include 9 | # DATADIR = $(PREFIX)/share 10 | # PKGCONFIGDIR = $(LIBDIR)/pkgconfig 11 | 12 | # OBJCOPY = objcopy 13 | # PKG_CONFIG = pkg-config 14 | # WAYLAND_SCANNER = wayland-scanner 15 | 16 | ENABLE_DEBUG = 1 17 | ENABLE_STATIC = 1 18 | ENABLE_SHARED = 1 19 | ENABLE_LIBUDEV = 1 20 | ENABLE_XWAYLAND = 1 21 | 22 | -------------------------------------------------------------------------------- /cursor/cursor.pcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michaelforney/swc/19893a5ca3239082b904a04fdb9ac7c3a1fb62e2/cursor/cursor.pcf -------------------------------------------------------------------------------- /cursor/local.mk: -------------------------------------------------------------------------------- 1 | # swc: cursor/local.mk 2 | 3 | dir := cursor 4 | 5 | $(dir)_TARGETS := $(dir)/convert_font $(dir)/cursor_data.h 6 | 7 | $(dir)/convert_font: $(dir)/convert_font.o 8 | $(link) 9 | 10 | $(dir)/cursor_data.h: $(dir)/cursor.pcf $(dir)/convert_font 11 | $(Q_GEN)cursor/convert_font $< $@ 2>/dev/null 12 | 13 | CLEAN_FILES += $(dir)/convert_font.o 14 | 15 | include common.mk 16 | 17 | -------------------------------------------------------------------------------- /example/local.mk: -------------------------------------------------------------------------------- 1 | # swc: example/local.mk 2 | 3 | dir := example 4 | 5 | $(dir)_PACKAGES = wayland-server xkbcommon 6 | $(dir)_CFLAGS = -Ilibswc 7 | 8 | $(dir): $(dir)/wm 9 | 10 | $(dir)/wm: $(dir)/wm.o libswc/libswc.a 11 | $(link) $(example_PACKAGE_LIBS) $(libswc_PACKAGE_LIBS) -lm 12 | 13 | CLEAN_FILES += $(dir)/wm.o $(dir)/wm 14 | 15 | include common.mk 16 | 17 | -------------------------------------------------------------------------------- /launch/devmajor-linux.c: -------------------------------------------------------------------------------- 1 | /* swc: launch/devmajor-linux.c 2 | * 3 | * Copyright (c) 2013, 2014, 2016 Michael Forney 4 | * Copyright (c) 2020 Nia Alarie 5 | * 6 | * Based in part upon weston-launch.c from weston which is: 7 | * 8 | * Copyright © 2012 Benjamin Franzke 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | */ 28 | #include 29 | #include 30 | #include "devmajor.h" 31 | 32 | #ifndef DRM_MAJOR 33 | #define DRM_MAJOR 226 34 | #endif 35 | 36 | bool 37 | device_is_input(dev_t rdev) 38 | { 39 | return major(rdev) == INPUT_MAJOR; 40 | } 41 | 42 | bool 43 | device_is_tty(dev_t rdev) 44 | { 45 | return major(rdev) == TTY_MAJOR; 46 | } 47 | 48 | bool 49 | device_is_drm(dev_t rdev) 50 | { 51 | return major(rdev) == DRM_MAJOR; 52 | } 53 | -------------------------------------------------------------------------------- /launch/devmajor-netbsd.c: -------------------------------------------------------------------------------- 1 | /* swc: launch/devmajor-netbsd.c 2 | * 3 | * Copyright (c) 2020 Nia Alarie 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | #include 24 | #include 25 | #include "devmajor.h" 26 | 27 | bool 28 | device_is_input(dev_t rdev) 29 | { 30 | if (major(rdev) == getdevmajor("wskbd", S_IFCHR)) 31 | return true; 32 | if (major(rdev) == getdevmajor("wsmouse", S_IFCHR)) 33 | return true; 34 | if (major(rdev) == getdevmajor("wsmux", S_IFCHR)) 35 | return true; 36 | return false; 37 | } 38 | 39 | bool 40 | device_is_tty(dev_t rdev) 41 | { 42 | return major(rdev) == getdevmajor("wsdisplay", S_IFCHR); 43 | } 44 | 45 | bool 46 | device_is_drm(dev_t rdev) 47 | { 48 | return major(rdev) == getdevmajor("drm", S_IFCHR); 49 | } 50 | 51 | -------------------------------------------------------------------------------- /launch/devmajor.h: -------------------------------------------------------------------------------- 1 | /* swc: launch/devmajor.h 2 | * 3 | * Copyright (c) 2020 Nia Alarie 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef DEVMAJOR_H 25 | #define DEVMAJOR_H 26 | 27 | #include 28 | #include 29 | 30 | bool device_is_input(dev_t); 31 | 32 | bool device_is_tty(dev_t); 33 | 34 | bool device_is_drm(dev_t); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /launch/local.mk: -------------------------------------------------------------------------------- 1 | # swc: launch/local.mk 2 | 3 | dir := launch 4 | 5 | $(dir)_TARGETS := $(dir)/swc-launch 6 | $(dir)_PACKAGES := libdrm 7 | 8 | ifeq ($(shell uname),NetBSD) 9 | DEVMAJOR_OBJ=devmajor-netbsd.o 10 | else 11 | DEVMAJOR_OBJ=devmajor-linux.o 12 | endif 13 | 14 | $(dir)/swc-launch: $(dir)/$(DEVMAJOR_OBJ) $(dir)/launch.o $(dir)/protocol.o 15 | $(link) $(launch_PACKAGE_LIBS) 16 | 17 | install-$(dir): $(dir)/swc-launch | $(DESTDIR)$(BINDIR) 18 | install -m 4755 launch/swc-launch $(DESTDIR)$(BINDIR) 19 | 20 | CLEAN_FILES += $(dir)/launch.o 21 | CLEAN_FILES += $(dir)/$(DEVMAJOR_OBJ) 22 | 23 | include common.mk 24 | 25 | -------------------------------------------------------------------------------- /launch/protocol.c: -------------------------------------------------------------------------------- 1 | #include "protocol.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | ssize_t 8 | send_fd(int socket, int fd, struct iovec *iov, int iovlen) 9 | { 10 | char control[CMSG_SPACE(sizeof(fd))]; 11 | struct msghdr message = { 12 | .msg_name = NULL, 13 | .msg_namelen = 0, 14 | .msg_iov = iov, 15 | .msg_iovlen = iovlen, 16 | }; 17 | struct cmsghdr *cmsg; 18 | 19 | if (fd != -1) { 20 | message.msg_control = control, 21 | message.msg_controllen = sizeof(control); 22 | 23 | cmsg = CMSG_FIRSTHDR(&message); 24 | cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); 25 | cmsg->cmsg_level = SOL_SOCKET; 26 | cmsg->cmsg_type = SCM_RIGHTS; 27 | 28 | memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd)); 29 | } else { 30 | message.msg_control = NULL; 31 | message.msg_controllen = 0; 32 | } 33 | 34 | return sendmsg(socket, &message, 0); 35 | } 36 | 37 | ssize_t 38 | receive_fd(int socket, int *fd, struct iovec *iov, int iovlen) 39 | { 40 | ssize_t size; 41 | char control[CMSG_SPACE(sizeof(*fd))]; 42 | struct msghdr message = { 43 | .msg_name = NULL, 44 | .msg_namelen = 0, 45 | .msg_iov = iov, 46 | .msg_iovlen = iovlen, 47 | }; 48 | struct cmsghdr *cmsg; 49 | 50 | if (fd) { 51 | *fd = -1; 52 | message.msg_control = &control; 53 | message.msg_controllen = sizeof(control); 54 | } 55 | 56 | size = recvmsg(socket, &message, MSG_CMSG_CLOEXEC); 57 | if (size < 0) 58 | return -1; 59 | 60 | cmsg = CMSG_FIRSTHDR(&message); 61 | if (fd && cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(*fd)) && cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) 62 | memcpy(fd, CMSG_DATA(cmsg), sizeof(*fd)); 63 | 64 | return size; 65 | } 66 | -------------------------------------------------------------------------------- /launch/protocol.h: -------------------------------------------------------------------------------- 1 | /* swc: launch/protocol.h 2 | * 3 | * Copyright (c) 2013, 2014 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_LAUNCH_PROTOCOL_H 25 | #define SWC_LAUNCH_PROTOCOL_H 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #define SWC_LAUNCH_SOCKET_ENV "SWC_LAUNCH_SOCKET" 32 | 33 | struct iovec; 34 | 35 | struct swc_launch_request { 36 | enum { 37 | SWC_LAUNCH_REQUEST_OPEN_DEVICE, 38 | SWC_LAUNCH_REQUEST_ACTIVATE_VT, 39 | } type; 40 | 41 | uint32_t serial; 42 | 43 | union { 44 | struct /* OPEN_DEVICE */ { 45 | int flags; 46 | }; 47 | struct /* ACTIVATE_VT */ { 48 | unsigned vt; 49 | }; 50 | }; 51 | }; 52 | 53 | struct swc_launch_event { 54 | enum { 55 | SWC_LAUNCH_EVENT_RESPONSE, 56 | SWC_LAUNCH_EVENT_ACTIVATE, 57 | SWC_LAUNCH_EVENT_DEACTIVATE, 58 | } type; 59 | 60 | union { 61 | struct /* RESPONSE */ { 62 | uint32_t serial; 63 | bool success; 64 | }; 65 | }; 66 | }; 67 | 68 | ssize_t send_fd(int socket, int fd, struct iovec *iov, int iovlen); 69 | ssize_t receive_fd(int socket, int *fd, struct iovec *iov, int iovlen); 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /libswc/bindings.c: -------------------------------------------------------------------------------- 1 | /* swc: swc/bindings.c 2 | * 3 | * Copyright (c) 2013 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #include "swc.h" 25 | #include "bindings.h" 26 | #include "internal.h" 27 | #include "keyboard.h" 28 | #include "pointer.h" 29 | #include "seat.h" 30 | #include "util.h" 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | struct binding { 37 | uint32_t value; 38 | uint32_t modifiers; 39 | swc_binding_handler handler; 40 | void *data; 41 | }; 42 | 43 | static bool handle_key(struct keyboard *keyboard, uint32_t time, struct key *key, uint32_t state); 44 | 45 | static struct keyboard_handler key_binding_handler = { 46 | .key = handle_key, 47 | }; 48 | 49 | static bool handle_button(struct pointer_handler *handler, uint32_t time, struct button *button, uint32_t state); 50 | 51 | static struct pointer_handler button_binding_handler = { 52 | .button = handle_button, 53 | }; 54 | 55 | static struct wl_array key_bindings, button_bindings; 56 | 57 | const struct swc_bindings swc_bindings = { 58 | .keyboard_handler = &key_binding_handler, 59 | .pointer_handler = &button_binding_handler, 60 | }; 61 | 62 | static struct binding * 63 | find_binding(struct wl_array *bindings, uint32_t modifiers, uint32_t value) 64 | { 65 | struct binding *binding; 66 | 67 | wl_array_for_each (binding, bindings) { 68 | if (binding->value == value && (binding->modifiers == modifiers || binding->modifiers == SWC_MOD_ANY)) 69 | return binding; 70 | } 71 | 72 | return NULL; 73 | } 74 | 75 | static struct binding * 76 | find_key_binding(uint32_t modifiers, uint32_t key) 77 | { 78 | struct binding *binding; 79 | struct xkb *xkb = &swc.seat->keyboard->xkb; 80 | xkb_keysym_t keysym; 81 | 82 | /* First try the keysym the keymap generates in it's current state. */ 83 | keysym = xkb_state_key_get_one_sym(xkb->state, XKB_KEY(key)); 84 | binding = find_binding(&key_bindings, modifiers, keysym); 85 | 86 | if (binding) 87 | return binding; 88 | 89 | xkb_layout_index_t layout; 90 | const xkb_keysym_t *keysyms; 91 | 92 | /* Then try the keysym associated with shift-level 0 for the key. */ 93 | layout = xkb_state_key_get_layout(xkb->state, XKB_KEY(key)); 94 | xkb_keymap_key_get_syms_by_level(xkb->keymap.map, XKB_KEY(key), layout, 0, &keysyms); 95 | 96 | if (!keysyms) 97 | return NULL; 98 | 99 | binding = find_binding(&key_bindings, modifiers, keysyms[0]); 100 | 101 | return binding; 102 | } 103 | 104 | static struct binding * 105 | find_button_binding(uint32_t modifiers, uint32_t value) 106 | { 107 | return find_binding(&button_bindings, modifiers, value); 108 | } 109 | 110 | static bool 111 | handle_binding(uint32_t time, struct press *press, uint32_t state, struct binding *(*find_binding)(uint32_t, uint32_t)) 112 | { 113 | struct binding *binding; 114 | 115 | if (state) { 116 | binding = find_binding(swc.seat->keyboard->modifiers, press->value); 117 | 118 | if (!binding) 119 | return false; 120 | 121 | press->data = binding; 122 | } else { 123 | binding = press->data; 124 | } 125 | 126 | binding->handler(binding->data, time, binding->value, state); 127 | 128 | return true; 129 | } 130 | 131 | bool 132 | handle_key(struct keyboard *keyboard, uint32_t time, struct key *key, uint32_t state) 133 | { 134 | return handle_binding(time, &key->press, state, &find_key_binding); 135 | } 136 | 137 | bool 138 | handle_button(struct pointer_handler *handler, uint32_t time, struct button *button, uint32_t state) 139 | { 140 | return handle_binding(time, &button->press, state, &find_button_binding); 141 | } 142 | 143 | bool 144 | bindings_initialize(void) 145 | { 146 | wl_array_init(&key_bindings); 147 | wl_array_init(&button_bindings); 148 | 149 | return true; 150 | } 151 | 152 | void 153 | bindings_finalize(void) 154 | { 155 | wl_array_release(&key_bindings); 156 | wl_array_release(&button_bindings); 157 | } 158 | 159 | EXPORT int 160 | swc_add_binding(enum swc_binding_type type, uint32_t modifiers, uint32_t value, swc_binding_handler handler, void *data) 161 | { 162 | struct binding *binding; 163 | struct wl_array *bindings; 164 | 165 | switch (type) { 166 | case SWC_BINDING_KEY: 167 | bindings = &key_bindings; 168 | break; 169 | case SWC_BINDING_BUTTON: 170 | bindings = &button_bindings; 171 | break; 172 | default: 173 | return -EINVAL; 174 | } 175 | 176 | if (!(binding = wl_array_add(bindings, sizeof(*binding)))) 177 | return -ENOMEM; 178 | 179 | binding->value = value; 180 | binding->modifiers = modifiers; 181 | binding->handler = handler; 182 | binding->data = data; 183 | 184 | return 0; 185 | } 186 | -------------------------------------------------------------------------------- /libswc/bindings.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/bindings.h 2 | * 3 | * Copyright (c) 2013 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_BINDINGS_H 25 | #define SWC_BINDINGS_H 26 | 27 | #include 28 | 29 | struct swc_bindings { 30 | struct keyboard_handler *keyboard_handler; 31 | struct pointer_handler *pointer_handler; 32 | }; 33 | 34 | bool bindings_initialize(void); 35 | void bindings_finalize(void); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /libswc/compositor.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/compositor.h 2 | * 3 | * Copyright (c) 2013, 2014 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_COMPOSITOR_H 25 | #define SWC_COMPOSITOR_H 26 | 27 | #include "view.h" 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | struct swc_compositor { 34 | struct pointer_handler *const pointer_handler; 35 | struct { 36 | /** 37 | * Emitted when a new surface is created. 38 | * 39 | * The data argument of the signal refers to the surface that has been 40 | * created. 41 | */ 42 | struct wl_signal new_surface; 43 | } signal; 44 | }; 45 | 46 | bool compositor_initialize(void); 47 | void compositor_finalize(void); 48 | 49 | struct compositor_view { 50 | struct view base; 51 | struct surface *surface; 52 | struct wld_buffer *buffer; 53 | struct window *window; 54 | struct compositor_view *parent; 55 | 56 | /* Whether or not the view is visible (mapped). */ 57 | bool visible; 58 | 59 | /* The box that the surface covers (including it's border). */ 60 | pixman_box32_t extents; 61 | 62 | /* The region that is covered by opaque regions of surfaces above this 63 | * surface. */ 64 | pixman_region32_t clip; 65 | 66 | struct { 67 | uint32_t width; 68 | uint32_t color; 69 | bool damaged; 70 | } border; 71 | 72 | struct wl_list link; 73 | struct wl_signal destroy_signal; 74 | }; 75 | 76 | struct compositor_view *compositor_create_view(struct surface *surface); 77 | 78 | void compositor_view_destroy(struct compositor_view *view); 79 | 80 | /** 81 | * Returns view as a compositor_view, or NULL if view is not a compositor_view. 82 | */ 83 | struct compositor_view *compositor_view(struct view *view); 84 | 85 | void compositor_view_set_parent(struct compositor_view *view, struct compositor_view *parent); 86 | 87 | void compositor_view_show(struct compositor_view *view); 88 | void compositor_view_hide(struct compositor_view *view); 89 | 90 | void compositor_view_set_border_color(struct compositor_view *view, uint32_t color); 91 | void compositor_view_set_border_width(struct compositor_view *view, uint32_t width); 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /libswc/data.c: -------------------------------------------------------------------------------- 1 | /* swc: data.c 2 | * 3 | * Copyright (c) 2013-2020 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #include "data.h" 25 | #include "util.h" 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | struct data { 33 | struct wl_array mime_types; 34 | struct wl_resource *source; 35 | struct wl_list offers; 36 | }; 37 | 38 | static void 39 | offer_accept(struct wl_client *client, struct wl_resource *offer, uint32_t serial, const char *mime_type) 40 | { 41 | struct data *data = wl_resource_get_user_data(offer); 42 | 43 | /* Protect against expired data_offers being used. */ 44 | if (!data) 45 | return; 46 | 47 | wl_data_source_send_target(data->source, mime_type); 48 | } 49 | 50 | static void 51 | offer_receive(struct wl_client *client, struct wl_resource *offer, const char *mime_type, int fd) 52 | { 53 | struct data *data = wl_resource_get_user_data(offer); 54 | 55 | /* Protect against expired data_offers being used. */ 56 | if (!data) 57 | return; 58 | 59 | wl_data_source_send_send(data->source, mime_type, fd); 60 | close(fd); 61 | } 62 | 63 | static const struct wl_data_offer_interface data_offer_impl = { 64 | .accept = offer_accept, 65 | .receive = offer_receive, 66 | .destroy = destroy_resource, 67 | }; 68 | 69 | static void 70 | source_offer(struct wl_client *client, struct wl_resource *source, const char *mime_type) 71 | { 72 | struct data *data = wl_resource_get_user_data(source); 73 | char *s, **dst; 74 | 75 | s = strdup(mime_type); 76 | if (!s) 77 | goto error0; 78 | dst = wl_array_add(&data->mime_types, sizeof(*dst)); 79 | if (!dst) 80 | goto error1; 81 | *dst = s; 82 | return; 83 | 84 | error1: 85 | free(s); 86 | error0: 87 | wl_resource_post_no_memory(source); 88 | } 89 | 90 | static const struct wl_data_source_interface data_source_impl = { 91 | .offer = source_offer, 92 | .destroy = destroy_resource, 93 | }; 94 | 95 | static void 96 | data_destroy(struct wl_resource *source) 97 | { 98 | struct data *data = wl_resource_get_user_data(source); 99 | struct wl_resource *offer; 100 | char **mime_type; 101 | 102 | wl_array_for_each (mime_type, &data->mime_types) 103 | free(*mime_type); 104 | wl_array_release(&data->mime_types); 105 | 106 | /* After this data_source is destroyed, each of the data_offer objects 107 | * associated with the data_source has a pointer to a free'd struct. We can't 108 | * destroy the resources because this results in a segfault on the client when 109 | * it correctly tries to call data_source.destroy. However, a misbehaving 110 | * client could still attempt to call accept or receive on the data_offer, 111 | * which would crash the server. 112 | * 113 | * So, we clear the user data on each of the offers to protect us. */ 114 | wl_resource_for_each (offer, &data->offers) { 115 | wl_resource_set_user_data(offer, NULL); 116 | wl_resource_set_destructor(offer, NULL); 117 | } 118 | 119 | free(data); 120 | } 121 | 122 | struct wl_resource * 123 | data_source_new(struct wl_client *client, uint32_t version, uint32_t id) 124 | { 125 | struct data *data; 126 | 127 | data = malloc(sizeof(*data)); 128 | if (!data) 129 | goto error0; 130 | wl_array_init(&data->mime_types); 131 | wl_list_init(&data->offers); 132 | 133 | data->source = wl_resource_create(client, &wl_data_source_interface, version, id); 134 | if (!data->source) 135 | goto error1; 136 | wl_resource_set_implementation(data->source, &data_source_impl, data, &data_destroy); 137 | 138 | return data->source; 139 | 140 | error1: 141 | free(data); 142 | error0: 143 | return NULL; 144 | } 145 | 146 | struct wl_resource * 147 | data_offer_new(struct wl_client *client, struct wl_resource *source, uint32_t version) 148 | { 149 | struct data *data = wl_resource_get_user_data(source); 150 | struct wl_resource *offer; 151 | 152 | offer = wl_resource_create(client, &wl_data_offer_interface, version, 0); 153 | if (!offer) 154 | return NULL; 155 | wl_resource_set_implementation(offer, &data_offer_impl, data, &remove_resource); 156 | wl_list_insert(&data->offers, wl_resource_get_link(offer)); 157 | 158 | return offer; 159 | } 160 | 161 | void 162 | data_send_mime_types(struct wl_resource *source, struct wl_resource *offer) 163 | { 164 | struct data *data = wl_resource_get_user_data(source); 165 | char **mime_type; 166 | 167 | wl_array_for_each (mime_type, &data->mime_types) 168 | wl_data_offer_send_offer(offer, *mime_type); 169 | } 170 | -------------------------------------------------------------------------------- /libswc/data.h: -------------------------------------------------------------------------------- 1 | /* swc: data.h 2 | * 3 | * Copyright (c) 2013 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_DATA_H 25 | #define SWC_DATA_H 26 | 27 | #include 28 | 29 | struct wl_client; 30 | 31 | struct wl_resource *data_source_new(struct wl_client *client, uint32_t version, uint32_t id); 32 | struct wl_resource *data_offer_new(struct wl_client *client, struct wl_resource *source, uint32_t version); 33 | void data_send_mime_types(struct wl_resource *source, struct wl_resource *offer); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /libswc/data_device.c: -------------------------------------------------------------------------------- 1 | /* swc: data_device.c 2 | * 3 | * Copyright (c) 2013-2020 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #include "data_device.h" 25 | #include "data.h" 26 | #include "event.h" 27 | #include "util.h" 28 | 29 | static void 30 | start_drag(struct wl_client *client, struct wl_resource *resource, 31 | struct wl_resource *source_resource, struct wl_resource *origin_resource, 32 | struct wl_resource *icon_resource, uint32_t serial) 33 | { 34 | /* XXX: Implement */ 35 | } 36 | 37 | static void 38 | set_selection(struct wl_client *client, struct wl_resource *resource, struct wl_resource *data_source, uint32_t serial) 39 | { 40 | struct data_device *data_device = wl_resource_get_user_data(resource); 41 | 42 | /* Check if this data source is already the current selection. */ 43 | if (data_source == data_device->selection) 44 | return; 45 | 46 | if (data_device->selection) { 47 | wl_data_source_send_cancelled(data_device->selection); 48 | wl_list_remove(&data_device->selection_destroy_listener.link); 49 | } 50 | 51 | data_device->selection = data_source; 52 | 53 | if (data_source) 54 | wl_resource_add_destroy_listener(data_source, &data_device->selection_destroy_listener); 55 | 56 | send_event(&data_device->event_signal, DATA_DEVICE_EVENT_SELECTION_CHANGED, NULL); 57 | } 58 | 59 | static const struct wl_data_device_interface data_device_impl = { 60 | .start_drag = start_drag, 61 | .set_selection = set_selection, 62 | .release = destroy_resource, 63 | }; 64 | 65 | static void 66 | handle_selection_destroy(struct wl_listener *listener, void *data) 67 | { 68 | struct data_device *data_device = wl_container_of(listener, data_device, selection_destroy_listener); 69 | 70 | data_device->selection = NULL; 71 | send_event(&data_device->event_signal, DATA_DEVICE_EVENT_SELECTION_CHANGED, NULL); 72 | } 73 | 74 | struct data_device * 75 | data_device_create(void) 76 | { 77 | struct data_device *data_device; 78 | 79 | data_device = malloc(sizeof(*data_device)); 80 | if (!data_device) 81 | return NULL; 82 | data_device->selection = NULL; 83 | data_device->selection_destroy_listener.notify = &handle_selection_destroy; 84 | wl_signal_init(&data_device->event_signal); 85 | wl_list_init(&data_device->resources); 86 | 87 | return data_device; 88 | } 89 | 90 | void 91 | data_device_destroy(struct data_device *data_device) 92 | { 93 | struct wl_resource *resource, *tmp; 94 | 95 | wl_list_for_each_safe (resource, tmp, &data_device->resources, link) 96 | wl_resource_destroy(resource); 97 | free(data_device); 98 | } 99 | 100 | struct wl_resource * 101 | data_device_bind(struct data_device *data_device, struct wl_client *client, uint32_t version, uint32_t id) 102 | { 103 | struct wl_resource *resource; 104 | 105 | resource = wl_resource_create(client, &wl_data_device_interface, version, id); 106 | if (!resource) 107 | return NULL; 108 | wl_resource_set_implementation(resource, &data_device_impl, data_device, &remove_resource); 109 | wl_list_insert(&data_device->resources, &resource->link); 110 | 111 | return resource; 112 | } 113 | 114 | static struct wl_resource * 115 | new_offer(struct wl_resource *resource, struct wl_client *client, struct wl_resource *source) 116 | { 117 | struct wl_resource *offer; 118 | 119 | offer = data_offer_new(client, source, wl_resource_get_version(resource)); 120 | if (!offer) 121 | return NULL; 122 | wl_data_device_send_data_offer(resource, offer); 123 | data_send_mime_types(source, offer); 124 | 125 | return offer; 126 | } 127 | 128 | void 129 | data_device_offer_selection(struct data_device *data_device, struct wl_client *client) 130 | { 131 | struct wl_resource *resource; 132 | struct wl_resource *offer = NULL; 133 | 134 | /* Look for the client's data_device resource. */ 135 | resource = wl_resource_find_for_client(&data_device->resources, client); 136 | 137 | /* If the client does not have a data device, there is nothing to do. */ 138 | if (!resource) 139 | return; 140 | 141 | /* If we have a selection, create a new offer for the client. */ 142 | if (data_device->selection) 143 | offer = new_offer(resource, client, data_device->selection); 144 | 145 | wl_data_device_send_selection(resource, offer); 146 | } 147 | -------------------------------------------------------------------------------- /libswc/data_device.h: -------------------------------------------------------------------------------- 1 | /* swc: data_device.h 2 | * 3 | * Copyright (c) 2013-2020 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_DATA_DEVICE_H 25 | #define SWC_DATA_DEVICE_H 26 | 27 | #include 28 | #include 29 | 30 | enum { 31 | DATA_DEVICE_EVENT_SELECTION_CHANGED 32 | }; 33 | 34 | struct data_device { 35 | /* The data source corresponding to the current selection. */ 36 | struct wl_resource *selection; 37 | struct wl_listener selection_destroy_listener; 38 | 39 | struct wl_signal event_signal; 40 | struct wl_list resources; 41 | }; 42 | 43 | struct data_device *data_device_create(void); 44 | void data_device_destroy(struct data_device *data_device); 45 | struct wl_resource *data_device_bind(struct data_device *data_device, struct wl_client *client, uint32_t version, uint32_t id); 46 | void data_device_offer_selection(struct data_device *data_device, struct wl_client *client); 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /libswc/data_device_manager.c: -------------------------------------------------------------------------------- 1 | /* swc: data_device_manager.c 2 | * 3 | * Copyright (c) 2013-2020 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #include "data_device_manager.h" 25 | #include "data.h" 26 | #include "data_device.h" 27 | #include "internal.h" 28 | #include "seat.h" 29 | 30 | static void 31 | create_data_source(struct wl_client *client, struct wl_resource *resource, uint32_t id) 32 | { 33 | if (!data_source_new(client, wl_resource_get_version(resource), id)) 34 | wl_resource_post_no_memory(resource); 35 | } 36 | 37 | static void 38 | get_data_device(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *seat_resource) 39 | { 40 | struct swc_seat *seat = wl_resource_get_user_data(seat_resource); 41 | 42 | if (!data_device_bind(seat->data_device, client, wl_resource_get_version(resource), id)) 43 | wl_resource_post_no_memory(resource); 44 | } 45 | 46 | static const struct wl_data_device_manager_interface data_device_manager_impl = { 47 | .create_data_source = create_data_source, 48 | .get_data_device = get_data_device, 49 | }; 50 | 51 | static void 52 | bind_data_device_manager(struct wl_client *client, void *data, uint32_t version, uint32_t id) 53 | { 54 | struct wl_resource *resource; 55 | 56 | resource = wl_resource_create(client, &wl_data_device_manager_interface, version, id); 57 | if (!resource) { 58 | wl_client_post_no_memory(client); 59 | return; 60 | } 61 | wl_resource_set_implementation(resource, &data_device_manager_impl, NULL, NULL); 62 | } 63 | 64 | struct wl_global * 65 | data_device_manager_create(struct wl_display *display) 66 | { 67 | return wl_global_create(display, &wl_data_device_manager_interface, 2, NULL, &bind_data_device_manager); 68 | } 69 | -------------------------------------------------------------------------------- /libswc/data_device_manager.h: -------------------------------------------------------------------------------- 1 | /* swc: data_device_manager.h 2 | * 3 | * Copyright (c) 2013-2019 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_DATA_DEVICE_MANAGER_H 25 | #define SWC_DATA_DEVICE_MANAGER_H 26 | 27 | struct wl_display; 28 | 29 | struct wl_global *data_device_manager_create(struct wl_display *display); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /libswc/dmabuf.c: -------------------------------------------------------------------------------- 1 | /* swc: dmabuf.c 2 | * 3 | * Copyright (c) 2019 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #include "dmabuf.h" 25 | #include "drm.h" 26 | #include "internal.h" 27 | #include "util.h" 28 | #include "wayland_buffer.h" 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include "linux-dmabuf-unstable-v1-server-protocol.h" 37 | 38 | struct params { 39 | struct wl_resource *resource; 40 | int fd[4]; 41 | uint32_t offset[4]; 42 | uint32_t stride[4]; 43 | uint64_t modifier[4]; 44 | bool created; 45 | }; 46 | 47 | static void 48 | add(struct wl_client *client, struct wl_resource *resource, int32_t fd, uint32_t i, uint32_t offset, uint32_t stride, uint32_t modifier_hi, uint32_t modifier_lo) 49 | { 50 | struct params *params = wl_resource_get_user_data(resource); 51 | 52 | if (params->created) { 53 | wl_resource_post_error(resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED, "buffer already created"); 54 | return; 55 | } 56 | if (i > ARRAY_LENGTH(params->fd)) { 57 | wl_resource_post_error(resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_IDX, "plane index too large"); 58 | return; 59 | } 60 | if (params->fd[i] != -1) { 61 | wl_resource_post_error(resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_SET, "buffer plane already set"); 62 | return; 63 | } 64 | params->fd[i] = fd; 65 | params->offset[i] = offset; 66 | params->stride[i] = stride; 67 | params->modifier[i] = (uint64_t)modifier_hi << 32 | modifier_lo; 68 | } 69 | 70 | static void 71 | create_immed(struct wl_client *client, struct wl_resource *resource, uint32_t id, 72 | int32_t width, int32_t height, uint32_t format, uint32_t flags) 73 | { 74 | struct params *params = wl_resource_get_user_data(resource); 75 | struct wld_buffer *buffer; 76 | struct wl_resource *buffer_resource; 77 | union wld_object object; 78 | int num_planes, i; 79 | 80 | if (params->created) { 81 | wl_resource_post_error(resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED, "buffer already created"); 82 | return; 83 | } 84 | params->created = true; 85 | switch (format) { 86 | case DRM_FORMAT_XRGB8888: 87 | case DRM_FORMAT_ARGB8888: 88 | num_planes = 1; 89 | break; 90 | default: 91 | wl_resource_post_error(resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_FORMAT, "unsupported format %#" PRIx32, format); 92 | return; 93 | } 94 | for (i = 0; i < num_planes; ++i) { 95 | if (params->fd[i] == -1) 96 | wl_resource_post_error(resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, "missing plane %d", i); 97 | } 98 | for (; i < ARRAY_LENGTH(params->fd); ++i) { 99 | if (params->fd[i] != -1) 100 | wl_resource_post_error(resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, "too many planes"); 101 | } 102 | object.i = params->fd[0]; 103 | buffer = wld_import_buffer(swc.drm->context, WLD_DRM_OBJECT_PRIME_FD, object, width, height, format, params->stride[0]); 104 | for (i = 0; i < num_planes; ++i) { 105 | close(params->fd[i]); 106 | params->fd[i] = -1; 107 | } 108 | if (!buffer) 109 | zwp_linux_buffer_params_v1_send_failed(resource); 110 | 111 | buffer_resource = wayland_buffer_create_resource(client, 1, id, buffer); 112 | if (!buffer_resource) { 113 | if (buffer) 114 | wld_buffer_unreference(buffer); 115 | wl_resource_post_no_memory(resource); 116 | return; 117 | } 118 | if (id == 0 && buffer) 119 | zwp_linux_buffer_params_v1_send_created(resource, buffer_resource); 120 | } 121 | 122 | static void 123 | create(struct wl_client *client, struct wl_resource *resource, 124 | int32_t width, int32_t height, uint32_t format, uint32_t flags) 125 | { 126 | create_immed(client, resource, 0, width, height, format, flags); 127 | } 128 | 129 | static const struct zwp_linux_buffer_params_v1_interface params_impl = { 130 | .destroy = destroy_resource, 131 | .add = add, 132 | .create = create, 133 | .create_immed = create_immed, 134 | }; 135 | 136 | static void 137 | params_destroy(struct wl_resource *resource) 138 | { 139 | struct params *params = wl_resource_get_user_data(resource); 140 | int i; 141 | 142 | for (i = 0; i < ARRAY_LENGTH(params->fd); ++i) 143 | close(params->fd[i]); 144 | } 145 | 146 | static void 147 | create_params(struct wl_client *client, struct wl_resource *resource, uint32_t id) 148 | { 149 | struct params *params; 150 | int i; 151 | 152 | params = malloc(sizeof(*params)); 153 | if (!params) 154 | goto error0; 155 | params->created = false; 156 | params->resource = wl_resource_create(client, &zwp_linux_buffer_params_v1_interface, wl_resource_get_version(resource), id); 157 | if (!params->resource) 158 | goto error1; 159 | for (i = 0; i < ARRAY_LENGTH(params->fd); ++i) 160 | params->fd[i] = -1; 161 | wl_resource_set_implementation(params->resource, ¶ms_impl, params, params_destroy); 162 | return; 163 | 164 | error1: 165 | free(params); 166 | error0: 167 | wl_resource_post_no_memory(resource); 168 | } 169 | 170 | static const struct zwp_linux_dmabuf_v1_interface dmabuf_impl = { 171 | .destroy = destroy_resource, 172 | .create_params = create_params, 173 | }; 174 | 175 | static void 176 | bind_dmabuf(struct wl_client *client, void *data, uint32_t version, uint32_t id) 177 | { 178 | static const uint32_t formats[] = { 179 | DRM_FORMAT_XRGB8888, 180 | DRM_FORMAT_ARGB8888, 181 | }; 182 | uint64_t modifier = DRM_FORMAT_MOD_INVALID; 183 | struct wl_resource *resource; 184 | size_t i; 185 | 186 | resource = wl_resource_create(client, &zwp_linux_dmabuf_v1_interface, version, id); 187 | if (!resource) { 188 | wl_client_post_no_memory(client); 189 | return; 190 | } 191 | wl_resource_set_implementation(resource, &dmabuf_impl, NULL, NULL); 192 | for (i = 0; i < ARRAY_LENGTH(formats); ++i) { 193 | if (version >= 3) { 194 | /* TODO: need a way to query DRM modifiers of wld */ 195 | zwp_linux_dmabuf_v1_send_modifier(resource, formats[i], modifier >> 32, modifier & 0xffffffff); 196 | } else { 197 | zwp_linux_dmabuf_v1_send_format(resource, formats[i]); 198 | } 199 | } 200 | } 201 | 202 | struct wl_global * 203 | swc_dmabuf_create(struct wl_display *display) 204 | { 205 | return wl_global_create(display, &zwp_linux_dmabuf_v1_interface, 3, NULL, &bind_dmabuf); 206 | } 207 | -------------------------------------------------------------------------------- /libswc/dmabuf.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/dmabuf.h 2 | * 3 | * Copyright (c) 2019 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_DMABUF_H 25 | #define SWC_DMABUF_H 26 | 27 | struct wl_display; 28 | 29 | struct wl_global *swc_dmabuf_create(struct wl_display *display); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /libswc/drm.h: -------------------------------------------------------------------------------- 1 | #ifndef SWC_DRM_H 2 | #define SWC_DRM_H 3 | 4 | #include 5 | #include 6 | 7 | struct wl_list; 8 | struct wld_buffer; 9 | 10 | struct drm_handler { 11 | void (*page_flip)(struct drm_handler *handler, uint32_t time); 12 | }; 13 | 14 | struct swc_drm { 15 | int fd; 16 | uint32_t cursor_w, cursor_h; 17 | struct wld_context *context; 18 | struct wld_renderer *renderer; 19 | }; 20 | 21 | bool drm_initialize(void); 22 | void drm_finalize(void); 23 | 24 | bool drm_create_screens(struct wl_list *screens); 25 | uint32_t drm_get_framebuffer(struct wld_buffer *buffer); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /libswc/event.h: -------------------------------------------------------------------------------- 1 | #ifndef SWC_EVENT_H 2 | #define SWC_EVENT_H 3 | 4 | #include 5 | #include 6 | 7 | /** 8 | * An event is the data passed to the listeners of the event_signals of various 9 | * objects. 10 | */ 11 | struct event { 12 | /** 13 | * The type of event that was sent. 14 | * 15 | * The meaning of this field depends on the type of object containing the 16 | * event_signal that passed this event. 17 | */ 18 | uint32_t type; 19 | 20 | /** 21 | * Data specific to the event type. 22 | * 23 | * Unless explicitly stated in the description of the event type, this value 24 | * is undefined. 25 | */ 26 | void *data; 27 | }; 28 | 29 | static inline void 30 | send_event(struct wl_signal *signal, uint32_t type, void *event_data) 31 | { 32 | struct event event = { .type = type, .data = event_data }; 33 | wl_signal_emit(signal, &event); 34 | } 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /libswc/input.c: -------------------------------------------------------------------------------- 1 | /* swc: input.c 2 | * 3 | * Copyright (c) 2013, 2014 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #include "input.h" 25 | #include "compositor.h" 26 | #include "event.h" 27 | #include "surface.h" 28 | #include "util.h" 29 | 30 | static void 31 | focus(struct input_focus *input_focus, struct compositor_view *view) 32 | { 33 | struct wl_client *client = NULL; 34 | struct wl_resource *resource, *tmp; 35 | 36 | if (view) { 37 | client = wl_resource_get_client(view->surface->resource); 38 | wl_resource_for_each_safe (resource, tmp, &input_focus->inactive) { 39 | if (wl_resource_get_client(resource) == client) { 40 | wl_list_remove(wl_resource_get_link(resource)); 41 | wl_list_insert(&input_focus->active, wl_resource_get_link(resource)); 42 | } 43 | } 44 | wl_signal_add(&view->destroy_signal, &input_focus->view_destroy_listener); 45 | } 46 | 47 | input_focus->client = client; 48 | input_focus->view = view; 49 | input_focus->handler->enter(input_focus->handler, &input_focus->active, view); 50 | } 51 | 52 | static void 53 | unfocus(struct input_focus *input_focus) 54 | { 55 | if (input_focus->view) 56 | wl_list_remove(&input_focus->view_destroy_listener.link); 57 | input_focus->handler->leave(input_focus->handler, &input_focus->active, input_focus->view); 58 | wl_list_insert_list(&input_focus->inactive, &input_focus->active); 59 | wl_list_init(&input_focus->active); 60 | } 61 | 62 | static void 63 | handle_focus_view_destroy(struct wl_listener *listener, void *data) 64 | { 65 | struct input_focus *input_focus = wl_container_of(listener, input_focus, view_destroy_listener); 66 | 67 | /* XXX: Should this call unfocus? */ 68 | wl_list_insert_list(&input_focus->inactive, &input_focus->active); 69 | wl_list_init(&input_focus->active); 70 | input_focus->client = NULL; 71 | input_focus->view = NULL; 72 | } 73 | 74 | bool 75 | input_focus_initialize(struct input_focus *input_focus, struct input_focus_handler *handler) 76 | { 77 | input_focus->client = NULL; 78 | input_focus->view = NULL; 79 | input_focus->view_destroy_listener.notify = &handle_focus_view_destroy; 80 | input_focus->handler = handler; 81 | 82 | wl_list_init(&input_focus->active); 83 | wl_list_init(&input_focus->inactive); 84 | wl_signal_init(&input_focus->event_signal); 85 | 86 | return true; 87 | } 88 | 89 | void 90 | input_focus_finalize(struct input_focus *input_focus) 91 | { 92 | /* XXX: Destroy resources? */ 93 | } 94 | 95 | void 96 | input_focus_add_resource(struct input_focus *input_focus, struct wl_resource *resource) 97 | { 98 | struct wl_list resources, *target = &input_focus->inactive; 99 | 100 | wl_list_init(&resources); 101 | wl_list_insert(&resources, wl_resource_get_link(resource)); 102 | 103 | /* If this new input resource corresponds to the focused client, send an enter event. */ 104 | if (wl_resource_get_client(resource) == input_focus->client) { 105 | input_focus->handler->enter(input_focus->handler, &resources, input_focus->view); 106 | target = &input_focus->active; 107 | } 108 | 109 | wl_list_insert_list(target, &resources); 110 | } 111 | 112 | void 113 | input_focus_remove_resource(struct input_focus *input_focus, struct wl_resource *resource) 114 | { 115 | wl_list_remove(wl_resource_get_link(resource)); 116 | } 117 | 118 | void 119 | input_focus_set(struct input_focus *input_focus, struct compositor_view *view) 120 | { 121 | struct input_focus_event_data data; 122 | 123 | if (view == input_focus->view) 124 | return; 125 | 126 | data.old = input_focus->view; 127 | data.new = view; 128 | 129 | unfocus(input_focus); 130 | focus(input_focus, view); 131 | 132 | send_event(&input_focus->event_signal, INPUT_FOCUS_EVENT_CHANGED, &data); 133 | } 134 | -------------------------------------------------------------------------------- /libswc/input.h: -------------------------------------------------------------------------------- 1 | /* swc: input.h 2 | * 3 | * Copyright (c) 2013, 2014 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_INPUT_H 25 | #define SWC_INPUT_H 26 | 27 | #include 28 | #include 29 | 30 | /* Focus {{{ */ 31 | 32 | enum { 33 | INPUT_FOCUS_EVENT_CHANGED 34 | }; 35 | 36 | struct input_focus_event_data { 37 | struct compositor_view *old, *new; 38 | }; 39 | 40 | struct input_focus_handler { 41 | void (*enter)(struct input_focus_handler *handler, struct wl_list *resources, struct compositor_view *view); 42 | void (*leave)(struct input_focus_handler *handler, struct wl_list *resources, struct compositor_view *view); 43 | }; 44 | 45 | struct input_focus { 46 | struct wl_client *client; 47 | struct compositor_view *view; 48 | struct wl_listener view_destroy_listener; 49 | 50 | struct input_focus_handler *handler; 51 | struct wl_list active, inactive; 52 | 53 | struct wl_signal event_signal; 54 | }; 55 | 56 | bool input_focus_initialize(struct input_focus *input_focus, struct input_focus_handler *input_handler); 57 | void input_focus_finalize(struct input_focus *input_focus); 58 | void input_focus_add_resource(struct input_focus *input_focus, struct wl_resource *resource); 59 | void input_focus_remove_resource(struct input_focus *input_focus, struct wl_resource *resource); 60 | void input_focus_set(struct input_focus *input_focus, struct compositor_view *view); 61 | 62 | /* }}} */ 63 | 64 | /* Key/button handling {{{ */ 65 | 66 | struct press { 67 | uint32_t value; 68 | uint32_t serial; 69 | void *data; 70 | }; 71 | 72 | /* }}} */ 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /libswc/internal.h: -------------------------------------------------------------------------------- 1 | /* swc: swc/internal.h 2 | * 3 | * Copyright (c) 2013-2019 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_INTERNAL_H 25 | #define SWC_INTERNAL_H 26 | 27 | #include 28 | #include 29 | 30 | enum { 31 | SWC_EVENT_ACTIVATED, 32 | SWC_EVENT_DEACTIVATED, 33 | }; 34 | 35 | struct swc { 36 | struct wl_display *display; 37 | struct wl_event_loop *event_loop; 38 | const struct swc_manager *manager; 39 | struct wl_signal event_signal; 40 | bool active; 41 | 42 | struct swc_seat *seat; 43 | const struct swc_bindings *const bindings; 44 | struct wl_list screens; 45 | struct swc_compositor *const compositor; 46 | struct swc_shm *shm; 47 | struct swc_drm *const drm; 48 | struct wl_global *data_device_manager; 49 | struct wl_global *kde_decoration_manager; 50 | struct wl_global *panel_manager; 51 | struct wl_global *shell; 52 | struct wl_global *subcompositor; 53 | struct wl_global *xdg_decoration_manager; 54 | struct wl_global *xdg_shell; 55 | 56 | #ifdef ENABLE_XWAYLAND 57 | const struct swc_xserver *const xserver; 58 | #endif 59 | }; 60 | 61 | extern struct swc swc; 62 | 63 | void swc_activate(void); 64 | void swc_deactivate(void); 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /libswc/kde_decoration.c: -------------------------------------------------------------------------------- 1 | /* swc: libswc/kde_decoration.c 2 | * 3 | * Copyright (c) 2020 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #include "kde_decoration.h" 25 | #include "util.h" 26 | 27 | #include 28 | #include "server-decoration-server-protocol.h" 29 | 30 | static void 31 | request_mode(struct wl_client *client, struct wl_resource *resource, uint32_t mode) 32 | { 33 | /* Server is required to send back the mode requested by 34 | * the client, we just don't plan to do anything with it. */ 35 | org_kde_kwin_server_decoration_send_mode(resource, mode); 36 | } 37 | 38 | static const struct org_kde_kwin_server_decoration_interface decoration_impl = { 39 | .release = destroy_resource, 40 | .request_mode = request_mode, 41 | }; 42 | 43 | static void 44 | create(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *toplevel_resource) 45 | { 46 | struct wl_resource *decoration; 47 | 48 | decoration = wl_resource_create(client, &org_kde_kwin_server_decoration_interface, wl_resource_get_version(resource), id); 49 | if (!decoration) { 50 | wl_resource_post_no_memory(resource); 51 | return; 52 | } 53 | wl_resource_set_implementation(decoration, &decoration_impl, NULL, NULL); 54 | org_kde_kwin_server_decoration_send_mode(decoration, ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_SERVER); 55 | } 56 | 57 | static const struct org_kde_kwin_server_decoration_manager_interface decoration_manager_impl = { 58 | .create = create, 59 | }; 60 | 61 | static void 62 | bind_decoration_manager(struct wl_client *client, void *data, uint32_t version, uint32_t id) 63 | { 64 | struct wl_resource *resource; 65 | 66 | resource = wl_resource_create(client, &org_kde_kwin_server_decoration_manager_interface, version, id); 67 | if (!resource) { 68 | wl_client_post_no_memory(client); 69 | return; 70 | } 71 | wl_resource_set_implementation(resource, &decoration_manager_impl, NULL, NULL); 72 | org_kde_kwin_server_decoration_manager_send_default_mode(resource, ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_SERVER); 73 | } 74 | 75 | struct wl_global * 76 | kde_decoration_manager_create(struct wl_display *display) 77 | { 78 | return wl_global_create(display, &org_kde_kwin_server_decoration_manager_interface, 1, NULL, &bind_decoration_manager); 79 | } 80 | -------------------------------------------------------------------------------- /libswc/kde_decoration.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/kde_decoration.h 2 | * 3 | * Copyright (c) 2020 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_KDE_DECORATION_H 25 | #define SWC_KDE_DECORATION_H 26 | 27 | struct wl_display; 28 | 29 | struct wl_global *kde_decoration_manager_create(struct wl_display *display); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /libswc/keyboard.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/keyboard.h 2 | * 3 | * Copyright (c) 2013, 2014 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_KEYBOARD_H 25 | #define SWC_KEYBOARD_H 26 | 27 | #include "input.h" 28 | 29 | #include 30 | #include 31 | 32 | /* Keycodes are offset by 8 in XKB. */ 33 | #define XKB_KEY(key) ((key) + 8) 34 | 35 | struct keyboard; 36 | struct wl_client; 37 | 38 | struct key { 39 | struct press press; 40 | struct keyboard_handler *handler; 41 | }; 42 | 43 | struct keyboard_modifier_state { 44 | uint32_t depressed; 45 | uint32_t latched; 46 | uint32_t locked; 47 | uint32_t group; 48 | }; 49 | 50 | struct keyboard_handler { 51 | bool (*key)(struct keyboard *keyboard, uint32_t time, struct key *key, uint32_t state); 52 | bool (*modifiers)(struct keyboard *keyboard, const struct keyboard_modifier_state *state); 53 | 54 | struct wl_list link; 55 | }; 56 | 57 | struct xkb { 58 | struct xkb_context *context; 59 | struct xkb_state *state; 60 | 61 | struct { 62 | struct xkb_keymap *map; 63 | int fd; 64 | uint32_t size; 65 | char *area; 66 | } keymap; 67 | 68 | struct { 69 | uint32_t ctrl, alt, super, shift; 70 | } indices; 71 | }; 72 | 73 | struct keyboard { 74 | struct input_focus focus; 75 | struct input_focus_handler focus_handler; 76 | struct xkb xkb; 77 | 78 | struct wl_array keys; 79 | struct wl_list handlers; 80 | struct keyboard_handler client_handler; 81 | struct wl_array client_keys; 82 | 83 | struct keyboard_modifier_state modifier_state; 84 | uint32_t modifiers; 85 | }; 86 | 87 | struct keyboard *keyboard_create(struct xkb_rule_names *names); 88 | void keyboard_destroy(struct keyboard *keyboard); 89 | bool keyboard_reset(struct keyboard *keyboard); 90 | void keyboard_set_focus(struct keyboard *keyboard, struct compositor_view *view); 91 | struct wl_resource *keyboard_bind(struct keyboard *keyboard, struct wl_client *client, uint32_t version, uint32_t id); 92 | void keyboard_handle_key(struct keyboard *keyboard, uint32_t time, uint32_t key, uint32_t state); 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /libswc/launch.c: -------------------------------------------------------------------------------- 1 | /* swc: libswc/launch.c 2 | * 3 | * Copyright (c) 2013, 2014 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #include "launch.h" 25 | #include "event.h" 26 | #include "internal.h" 27 | #include "launch/protocol.h" 28 | #include "util.h" 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | static struct { 36 | int socket; 37 | struct wl_event_source *source; 38 | uint32_t next_serial; 39 | } launch; 40 | 41 | static bool 42 | handle_event(struct swc_launch_event *event) 43 | { 44 | switch (event->type) { 45 | case SWC_LAUNCH_EVENT_ACTIVATE: 46 | swc_activate(); 47 | break; 48 | case SWC_LAUNCH_EVENT_DEACTIVATE: 49 | swc_deactivate(); 50 | break; 51 | default: 52 | return false; 53 | } 54 | 55 | return true; 56 | } 57 | 58 | static int 59 | handle_data(int fd, uint32_t mask, void *data) 60 | { 61 | struct swc_launch_event event; 62 | struct iovec iov[1] = { 63 | {.iov_base = &event, .iov_len = sizeof(event)}, 64 | }; 65 | 66 | if (receive_fd(fd, NULL, iov, 1) != -1) 67 | handle_event(&event); 68 | return 1; 69 | } 70 | 71 | bool 72 | launch_initialize(void) 73 | { 74 | char *socket_string, *end; 75 | 76 | if (!(socket_string = getenv(SWC_LAUNCH_SOCKET_ENV))) 77 | return false; 78 | 79 | launch.socket = strtol(socket_string, &end, 10); 80 | if (*end != '\0') 81 | return false; 82 | 83 | unsetenv(SWC_LAUNCH_SOCKET_ENV); 84 | if (fcntl(launch.socket, F_SETFD, FD_CLOEXEC) < 0) 85 | return false; 86 | 87 | launch.source = wl_event_loop_add_fd(swc.event_loop, launch.socket, WL_EVENT_READABLE, &handle_data, NULL); 88 | if (!launch.source) 89 | return false; 90 | 91 | return true; 92 | } 93 | 94 | void 95 | launch_finalize(void) 96 | { 97 | wl_event_source_remove(launch.source); 98 | close(launch.socket); 99 | } 100 | 101 | static bool 102 | send_request(struct swc_launch_request *request, const void *data, size_t size, struct swc_launch_event *event, int out_fd, int *in_fd) 103 | { 104 | struct iovec request_iov[2] = { 105 | {.iov_base = request, .iov_len = sizeof(*request)}, 106 | {.iov_base = (void *)data, .iov_len = size}, 107 | }; 108 | struct iovec response_iov[1] = { 109 | {.iov_base = event, .iov_len = sizeof(*event)}, 110 | }; 111 | 112 | request->serial = ++launch.next_serial; 113 | 114 | if (send_fd(launch.socket, out_fd, request_iov, 1 + (size > 0)) == -1) 115 | return false; 116 | 117 | while (receive_fd(launch.socket, in_fd, response_iov, 1) != -1) { 118 | if (event->type == SWC_LAUNCH_EVENT_RESPONSE && event->serial == request->serial) 119 | return true; 120 | handle_event(event); 121 | } 122 | 123 | return false; 124 | } 125 | 126 | int 127 | launch_open_device(const char *path, int flags) 128 | { 129 | struct swc_launch_request request; 130 | struct swc_launch_event response; 131 | int fd; 132 | 133 | request.type = SWC_LAUNCH_REQUEST_OPEN_DEVICE; 134 | request.flags = flags; 135 | 136 | if (!send_request(&request, path, strlen(path) + 1, &response, -1, &fd)) 137 | return -1; 138 | 139 | return fd; 140 | } 141 | 142 | bool 143 | launch_activate_vt(unsigned vt) 144 | { 145 | struct swc_launch_request request; 146 | struct swc_launch_event response; 147 | 148 | request.type = SWC_LAUNCH_REQUEST_ACTIVATE_VT; 149 | request.vt = vt; 150 | 151 | if (!send_request(&request, NULL, 0, &response, -1, NULL)) 152 | return false; 153 | 154 | return response.success; 155 | } 156 | -------------------------------------------------------------------------------- /libswc/launch.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/launch.h 2 | * 3 | * Copyright (c) 2013, 2014 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_LAUNCH_H 25 | #define SWC_LAUNCH_H 26 | 27 | #include 28 | 29 | bool launch_initialize(void); 30 | void launch_finalize(void); 31 | int launch_open_device(const char *path, int flags); 32 | bool launch_activate_vt(unsigned vt); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /libswc/local.mk: -------------------------------------------------------------------------------- 1 | # swc: libswc/local.mk 2 | 3 | dir := libswc 4 | 5 | LIBSWC_LINK := libswc.so 6 | LIBSWC_SO := $(LIBSWC_LINK).$(VERSION_MAJOR) 7 | LIBSWC_LIB := $(LIBSWC_SO).$(VERSION_MINOR) 8 | 9 | ifneq ($(ENABLE_STATIC), 0) 10 | $(dir)_TARGETS += $(dir)/libswc.a 11 | endif 12 | 13 | ifneq ($(ENABLE_SHARED), 0) 14 | $(dir)_TARGETS += \ 15 | $(dir)/$(LIBSWC_LIB) \ 16 | $(dir)/$(LIBSWC_SO) \ 17 | $(dir)/$(LIBSWC_LINK) 18 | endif 19 | 20 | $(dir)_PACKAGES := libdrm pixman-1 wayland-server wld xkbcommon 21 | $(dir)_CFLAGS += -Iprotocol 22 | 23 | SWC_SOURCES = \ 24 | launch/protocol.c \ 25 | libswc/bindings.c \ 26 | libswc/compositor.c \ 27 | libswc/data.c \ 28 | libswc/data_device.c \ 29 | libswc/data_device_manager.c \ 30 | libswc/dmabuf.c \ 31 | libswc/drm.c \ 32 | libswc/input.c \ 33 | libswc/kde_decoration.c \ 34 | libswc/keyboard.c \ 35 | libswc/launch.c \ 36 | libswc/mode.c \ 37 | libswc/output.c \ 38 | libswc/panel.c \ 39 | libswc/panel_manager.c \ 40 | libswc/plane.c \ 41 | libswc/pointer.c \ 42 | libswc/primary_plane.c \ 43 | libswc/region.c \ 44 | libswc/screen.c \ 45 | libswc/shell.c \ 46 | libswc/shell_surface.c \ 47 | libswc/shm.c \ 48 | libswc/subcompositor.c \ 49 | libswc/subsurface.c \ 50 | libswc/surface.c \ 51 | libswc/swc.c \ 52 | libswc/util.c \ 53 | libswc/view.c \ 54 | libswc/wayland_buffer.c \ 55 | libswc/window.c \ 56 | libswc/xdg_decoration.c \ 57 | libswc/xdg_shell.c \ 58 | protocol/linux-dmabuf-unstable-v1-protocol.c \ 59 | protocol/server-decoration-protocol.c \ 60 | protocol/swc-protocol.c \ 61 | protocol/wayland-drm-protocol.c \ 62 | protocol/xdg-decoration-unstable-v1-protocol.c \ 63 | protocol/xdg-shell-protocol.c 64 | 65 | ifeq ($(shell uname),NetBSD) 66 | SWC_SOURCES += libswc/seat-ws.c 67 | else 68 | SWC_SOURCES += libswc/seat.c 69 | $(dir)_PACKAGES += libinput 70 | ifeq ($(ENABLE_LIBUDEV),1) 71 | $(dir)_CFLAGS += -DENABLE_LIBUDEV 72 | $(dir)_PACKAGES += libudev 73 | endif 74 | endif 75 | 76 | ifeq ($(ENABLE_XWAYLAND),1) 77 | $(dir)_CFLAGS += -DENABLE_XWAYLAND 78 | $(dir)_PACKAGES += xcb xcb-composite xcb-ewmh xcb-icccm 79 | 80 | SWC_SOURCES += \ 81 | libswc/xserver.c \ 82 | libswc/xwm.c 83 | endif 84 | 85 | SWC_STATIC_OBJECTS = $(SWC_SOURCES:%.c=%.o) 86 | SWC_SHARED_OBJECTS = $(SWC_SOURCES:%.c=%.lo) 87 | 88 | # Explicitly state dependencies on generated files 89 | objects = $(foreach obj,$(1),$(dir)/$(obj).o $(dir)/$(obj).lo) 90 | $(call objects,compositor panel_manager panel screen): protocol/swc-server-protocol.h 91 | $(call objects,dmabuf): protocol/linux-dmabuf-unstable-v1-server-protocol.h 92 | $(call objects,drm drm_buffer): protocol/wayland-drm-server-protocol.h 93 | $(call objects,kde_decoration): protocol/server-decoration-server-protocol.h 94 | $(call objects,xdg_decoration): protocol/xdg-decoration-unstable-v1-server-protocol.h 95 | $(call objects,xdg_shell): protocol/xdg-shell-server-protocol.h 96 | $(call objects,pointer): cursor/cursor_data.h 97 | 98 | $(dir)/libswc-internal.o: $(SWC_STATIC_OBJECTS) 99 | $(link) -nostdlib -r 100 | 101 | $(dir)/libswc.o: $(dir)/libswc-internal.o 102 | $(Q_OBJCOPY)$(OBJCOPY) --localize-hidden $< $@ 103 | 104 | $(dir)/libswc.a: $(dir)/libswc.o 105 | $(Q_AR)$(AR) cru $@ $^ 106 | 107 | $(dir)/$(LIBSWC_LIB): $(SWC_SHARED_OBJECTS) 108 | $(link) -shared -Wl,-soname,$(LIBSWC_SO) -Wl,-no-undefined $(libswc_PACKAGE_LIBS) 109 | 110 | $(dir)/$(LIBSWC_SO): $(dir)/$(LIBSWC_LIB) 111 | $(Q_SYM)ln -sf $(notdir $<) $@ 112 | 113 | $(dir)/$(LIBSWC_LINK): $(dir)/$(LIBSWC_SO) 114 | $(Q_SYM)ln -sf $(notdir $<) $@ 115 | 116 | .PHONY: install-libswc.a 117 | install-libswc.a: $(dir)/libswc.a | $(DESTDIR)$(LIBDIR) 118 | install -m 644 $< $(DESTDIR)$(LIBDIR) 119 | 120 | .PHONY: install-$(LIBSWC_LIB) 121 | install-$(LIBSWC_LIB): $(dir)/$(LIBSWC_LIB) | $(DESTDIR)$(LIBDIR) 122 | install -m 755 $< $(DESTDIR)$(LIBDIR) 123 | 124 | .PHONY: install-$(LIBSWC_SO) install-$(LIBSWC_LINK) 125 | install-$(LIBSWC_SO) install-$(LIBSWC_LINK): install-$(LIBSWC_LIB) 126 | ln -sf $(LIBSWC_LIB) $(DESTDIR)$(LIBDIR)/${@:install-%=%} 127 | 128 | install-$(dir): $($(dir)_TARGETS:$(dir)/%=install-%) | $(DESTDIR)$(INCLUDEDIR) 129 | install -m 644 libswc/swc.h $(DESTDIR)$(INCLUDEDIR) 130 | 131 | CLEAN_FILES += $(SWC_SHARED_OBJECTS) $(SWC_STATIC_OBJECTS) 132 | 133 | include common.mk 134 | -------------------------------------------------------------------------------- /libswc/mode.c: -------------------------------------------------------------------------------- 1 | /* swc: libswc/mode.c 2 | * 3 | * Copyright (c) 2013 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #include "mode.h" 25 | 26 | bool 27 | mode_initialize(struct mode *mode, drmModeModeInfo *mode_info) 28 | { 29 | mode->width = mode_info->hdisplay; 30 | mode->height = mode_info->vdisplay; 31 | mode->refresh = mode_info->vrefresh * 1000; 32 | mode->preferred = mode_info->type & DRM_MODE_TYPE_PREFERRED; 33 | mode->info = *mode_info; 34 | return true; 35 | } 36 | 37 | bool 38 | mode_equal(const struct mode *mode1, const struct mode *mode2) 39 | { 40 | return mode1->width == mode2->width 41 | && mode1->height == mode2->height 42 | && mode1->refresh == mode2->refresh; 43 | } 44 | -------------------------------------------------------------------------------- /libswc/mode.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/mode.h 2 | * 3 | * Copyright (c) 2013 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_MODE_H 25 | #define SWC_MODE_H 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | struct mode { 33 | uint16_t width, height; 34 | uint32_t refresh; 35 | 36 | bool preferred; 37 | 38 | drmModeModeInfo info; 39 | }; 40 | 41 | bool mode_initialize(struct mode *mode, drmModeModeInfo *mode_info); 42 | bool mode_equal(const struct mode *mode1, const struct mode *mode2); 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /libswc/output.c: -------------------------------------------------------------------------------- 1 | #include "output.h" 2 | #include "drm.h" 3 | #include "internal.h" 4 | #include "mode.h" 5 | #include "screen.h" 6 | #include "util.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | static const struct wl_output_interface output_impl = { 15 | .release = destroy_resource, 16 | }; 17 | 18 | static void 19 | bind_output(struct wl_client *client, void *data, uint32_t version, uint32_t id) 20 | { 21 | struct output *output = data; 22 | struct screen *screen = output->screen; 23 | struct mode *mode; 24 | struct wl_resource *resource; 25 | uint32_t flags; 26 | 27 | resource = wl_resource_create(client, &wl_output_interface, version, id); 28 | 29 | if (!resource) { 30 | wl_client_post_no_memory(client); 31 | return; 32 | } 33 | 34 | wl_resource_set_implementation(resource, &output_impl, output, &remove_resource); 35 | wl_list_insert(&output->resources, wl_resource_get_link(resource)); 36 | 37 | wl_output_send_geometry(resource, screen->base.geometry.x, screen->base.geometry.y, 38 | output->physical_width, output->physical_height, 39 | 0, "unknown", "unknown", WL_OUTPUT_TRANSFORM_NORMAL); 40 | 41 | wl_array_for_each (mode, &output->modes) { 42 | flags = 0; 43 | if (mode->preferred) 44 | flags |= WL_OUTPUT_MODE_PREFERRED; 45 | if (mode_equal(&screen->planes.primary.mode, mode)) 46 | flags |= WL_OUTPUT_MODE_CURRENT; 47 | 48 | wl_output_send_mode(resource, flags, mode->width, mode->height, mode->refresh); 49 | } 50 | 51 | if (version >= 2) 52 | wl_output_send_done(resource); 53 | } 54 | 55 | struct output * 56 | output_new(drmModeConnectorPtr connector) 57 | { 58 | struct output *output; 59 | struct mode *modes; 60 | uint32_t i; 61 | 62 | if (!(output = malloc(sizeof(*output)))) { 63 | ERROR("Failed to allocated output\n"); 64 | goto error0; 65 | } 66 | 67 | output->global = wl_global_create(swc.display, &wl_output_interface, 3, output, &bind_output); 68 | 69 | if (!output->global) { 70 | ERROR("Failed to create output global\n"); 71 | goto error1; 72 | } 73 | 74 | output->physical_width = connector->mmWidth; 75 | output->physical_height = connector->mmHeight; 76 | output->preferred_mode = NULL; 77 | 78 | wl_list_init(&output->resources); 79 | wl_array_init(&output->modes); 80 | pixman_region32_init(&output->current_damage); 81 | pixman_region32_init(&output->previous_damage); 82 | 83 | output->connector = connector->connector_id; 84 | 85 | if (connector->count_modes == 0) 86 | goto error2; 87 | 88 | modes = wl_array_add(&output->modes, connector->count_modes * sizeof(*modes)); 89 | if (!modes) 90 | goto error2; 91 | 92 | for (i = 0; i < connector->count_modes; ++i) { 93 | mode_initialize(&modes[i], &connector->modes[i]); 94 | 95 | if (modes[i].preferred) 96 | output->preferred_mode = &modes[i]; 97 | } 98 | 99 | if (!output->preferred_mode) 100 | output->preferred_mode = &modes[0]; 101 | 102 | return output; 103 | 104 | error2: 105 | wl_global_destroy(output->global); 106 | error1: 107 | free(output); 108 | error0: 109 | return NULL; 110 | } 111 | 112 | void 113 | output_destroy(struct output *output) 114 | { 115 | wl_array_release(&output->modes); 116 | wl_global_destroy(output->global); 117 | free(output); 118 | } 119 | -------------------------------------------------------------------------------- /libswc/output.h: -------------------------------------------------------------------------------- 1 | #ifndef SWC_OUTPUT_H 2 | #define SWC_OUTPUT_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | struct wl_display; 10 | 11 | struct output { 12 | struct screen *screen; 13 | 14 | /* The physical dimensions (in mm) of this output */ 15 | uint32_t physical_width, physical_height; 16 | 17 | struct wl_array modes; 18 | struct mode *preferred_mode; 19 | 20 | pixman_region32_t current_damage, previous_damage; 21 | 22 | /* The DRM connector corresponding to this output */ 23 | uint32_t connector; 24 | 25 | struct wl_global *global; 26 | struct wl_list resources; 27 | struct wl_list link; 28 | }; 29 | 30 | struct output *output_new(drmModeConnector *connector); 31 | void output_destroy(struct output *output); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /libswc/panel.c: -------------------------------------------------------------------------------- 1 | /* swc: libswc/panel.c 2 | * 3 | * Copyright (c) 2013, 2014 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #include "panel.h" 25 | #include "compositor.h" 26 | #include "internal.h" 27 | #include "keyboard.h" 28 | #include "output.h" 29 | #include "screen.h" 30 | #include "seat.h" 31 | #include "surface.h" 32 | #include "util.h" 33 | #include "view.h" 34 | 35 | #include 36 | #include 37 | #include "swc-server-protocol.h" 38 | 39 | struct panel { 40 | struct wl_resource *resource; 41 | 42 | struct wl_listener surface_destroy_listener; 43 | struct compositor_view *view; 44 | struct view_handler view_handler; 45 | struct screen *screen; 46 | struct screen_modifier modifier; 47 | uint32_t edge; 48 | uint32_t offset, strut_size; 49 | bool docked; 50 | }; 51 | 52 | static void 53 | update_position(struct panel *panel) 54 | { 55 | int32_t x, y; 56 | struct swc_rectangle *screen = &panel->screen->base.geometry, *view = &panel->view->base.geometry; 57 | 58 | switch (panel->edge) { 59 | case SWC_PANEL_EDGE_TOP: 60 | x = screen->x + panel->offset; 61 | y = screen->y; 62 | break; 63 | case SWC_PANEL_EDGE_BOTTOM: 64 | x = screen->x + panel->offset; 65 | y = screen->y + screen->height - view->height; 66 | break; 67 | case SWC_PANEL_EDGE_LEFT: 68 | x = screen->x; 69 | y = screen->y + screen->height - view->height - panel->offset; 70 | break; 71 | case SWC_PANEL_EDGE_RIGHT: 72 | x = screen->x + screen->width - view->width; 73 | y = screen->y + panel->offset; 74 | break; 75 | default: 76 | return; 77 | } 78 | 79 | view_move(&panel->view->base, x, y); 80 | } 81 | 82 | static void 83 | dock(struct wl_client *client, struct wl_resource *resource, uint32_t edge, struct wl_resource *screen_resource, uint32_t focus) 84 | { 85 | struct panel *panel = wl_resource_get_user_data(resource); 86 | struct screen *screen; 87 | uint32_t length; 88 | 89 | if (screen_resource) 90 | screen = wl_resource_get_user_data(screen_resource); 91 | else 92 | screen = wl_container_of(swc.screens.next, screen, link); 93 | 94 | switch (edge) { 95 | case SWC_PANEL_EDGE_TOP: 96 | case SWC_PANEL_EDGE_BOTTOM: 97 | length = screen->base.geometry.width; 98 | break; 99 | case SWC_PANEL_EDGE_LEFT: 100 | case SWC_PANEL_EDGE_RIGHT: 101 | length = screen->base.geometry.height; 102 | break; 103 | default: 104 | return; 105 | } 106 | 107 | if (panel->screen && screen != panel->screen) { 108 | wl_list_remove(&panel->modifier.link); 109 | screen_update_usable_geometry(panel->screen); 110 | } 111 | 112 | panel->screen = screen; 113 | panel->edge = edge; 114 | panel->docked = true; 115 | 116 | update_position(panel); 117 | compositor_view_show(panel->view); 118 | wl_list_insert(&screen->modifiers, &panel->modifier.link); 119 | 120 | if (focus) 121 | keyboard_set_focus(swc.seat->keyboard, panel->view); 122 | 123 | swc_panel_send_docked(resource, length); 124 | } 125 | 126 | static void 127 | set_offset(struct wl_client *client, struct wl_resource *resource, uint32_t offset) 128 | { 129 | struct panel *panel = wl_resource_get_user_data(resource); 130 | 131 | panel->offset = offset; 132 | if (panel->docked) 133 | update_position(panel); 134 | } 135 | 136 | static void 137 | set_strut(struct wl_client *client, struct wl_resource *resource, uint32_t size, uint32_t begin, uint32_t end) 138 | { 139 | struct panel *panel = wl_resource_get_user_data(resource); 140 | 141 | panel->strut_size = size; 142 | if (panel->docked) 143 | screen_update_usable_geometry(panel->screen); 144 | } 145 | 146 | static const struct swc_panel_interface panel_impl = { 147 | .dock = dock, 148 | .set_offset = set_offset, 149 | .set_strut = set_strut, 150 | }; 151 | 152 | static void 153 | handle_resize(struct view_handler *handler, uint32_t old_width, uint32_t old_height) 154 | { 155 | struct panel *panel = wl_container_of(handler, panel, view_handler); 156 | update_position(panel); 157 | } 158 | 159 | static const struct view_handler_impl view_handler_impl = { 160 | .resize = handle_resize, 161 | }; 162 | 163 | static void 164 | modify(struct screen_modifier *modifier, const struct swc_rectangle *geom, pixman_region32_t *usable) 165 | { 166 | struct panel *panel = wl_container_of(modifier, panel, modifier); 167 | pixman_box32_t box = { 168 | .x1 = geom->x, 169 | .y1 = geom->y, 170 | .x2 = geom->x + geom->width, 171 | .y2 = geom->y + geom->height 172 | }; 173 | 174 | assert(panel->docked); 175 | 176 | DEBUG("Original geometry { x1: %d, y1: %d, x2: %d, y2: %d }\n", 177 | box.x1, box.y1, box.x2, box.y2); 178 | 179 | switch (panel->edge) { 180 | case SWC_PANEL_EDGE_TOP: 181 | box.y1 = MAX(box.y1, geom->y + panel->strut_size); 182 | break; 183 | case SWC_PANEL_EDGE_BOTTOM: 184 | box.y2 = MIN(box.y2, geom->y + geom->height - panel->strut_size); 185 | break; 186 | case SWC_PANEL_EDGE_LEFT: 187 | box.x1 = MAX(box.x1, geom->x + panel->strut_size); 188 | break; 189 | case SWC_PANEL_EDGE_RIGHT: 190 | box.x2 = MIN(box.x2, geom->x + geom->width - panel->strut_size); 191 | break; 192 | } 193 | 194 | DEBUG("Usable region { x1: %d, y1: %d, x2: %d, y2: %d }\n", 195 | box.x1, box.y1, box.x2, box.y2); 196 | 197 | pixman_region32_reset(usable, &box); 198 | } 199 | 200 | static void 201 | destroy_panel(struct wl_resource *resource) 202 | { 203 | struct panel *panel = wl_resource_get_user_data(resource); 204 | 205 | if (panel->docked) { 206 | wl_list_remove(&panel->modifier.link); 207 | screen_update_usable_geometry(panel->screen); 208 | } 209 | 210 | compositor_view_destroy(panel->view); 211 | free(panel); 212 | } 213 | 214 | static void 215 | handle_surface_destroy(struct wl_listener *listener, void *data) 216 | { 217 | struct panel *panel = wl_container_of(listener, panel, surface_destroy_listener); 218 | wl_resource_destroy(panel->resource); 219 | } 220 | 221 | struct panel * 222 | panel_new(struct wl_client *client, uint32_t version, uint32_t id, struct surface *surface) 223 | { 224 | struct panel *panel; 225 | 226 | panel = malloc(sizeof(*panel)); 227 | 228 | if (!panel) 229 | goto error0; 230 | 231 | panel->resource = wl_resource_create(client, &swc_panel_interface, version, id); 232 | 233 | if (!panel->resource) 234 | goto error1; 235 | 236 | if (!(panel->view = compositor_create_view(surface))) 237 | goto error2; 238 | 239 | wl_resource_set_implementation(panel->resource, &panel_impl, panel, &destroy_panel); 240 | panel->surface_destroy_listener.notify = &handle_surface_destroy; 241 | panel->view_handler.impl = &view_handler_impl; 242 | panel->modifier.modify = &modify; 243 | panel->screen = NULL; 244 | panel->offset = 0; 245 | panel->strut_size = 0; 246 | panel->docked = false; 247 | wl_list_insert(&panel->view->base.handlers, &panel->view_handler.link); 248 | wl_resource_add_destroy_listener(surface->resource, &panel->surface_destroy_listener); 249 | 250 | return panel; 251 | 252 | error2: 253 | wl_resource_destroy(panel->resource); 254 | error1: 255 | free(panel); 256 | error0: 257 | return NULL; 258 | } 259 | -------------------------------------------------------------------------------- /libswc/panel.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/panel.h 2 | * 3 | * Copyright (c) 2013, 2014 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_PANEL_H 25 | #define SWC_PANEL_H 26 | 27 | #include 28 | 29 | struct surface; 30 | struct wl_client; 31 | 32 | struct panel *panel_new(struct wl_client *client, uint32_t version, uint32_t id, struct surface *surface); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /libswc/panel_manager.c: -------------------------------------------------------------------------------- 1 | /* swc: libswc/panel_manager.c 2 | * 3 | * Copyright (c) 2013-2020 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #include "panel_manager.h" 25 | #include "internal.h" 26 | #include "panel.h" 27 | 28 | #include 29 | #include "swc-server-protocol.h" 30 | 31 | static void 32 | create_panel(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource) 33 | { 34 | struct surface *surface = wl_resource_get_user_data(surface_resource); 35 | 36 | if (!panel_new(client, wl_resource_get_version(resource), id, surface)) 37 | wl_client_post_no_memory(client); 38 | } 39 | 40 | static const struct swc_panel_manager_interface panel_manager_impl = { 41 | .create_panel = create_panel, 42 | }; 43 | 44 | static void 45 | bind_panel_manager(struct wl_client *client, void *data, uint32_t version, uint32_t id) 46 | { 47 | struct wl_resource *resource; 48 | 49 | resource = wl_resource_create(client, &swc_panel_manager_interface, version, id); 50 | if (!resource) { 51 | wl_client_post_no_memory(client); 52 | return; 53 | } 54 | wl_resource_set_implementation(resource, &panel_manager_impl, NULL, NULL); 55 | } 56 | 57 | struct wl_global * 58 | panel_manager_create(struct wl_display *display) 59 | { 60 | return wl_global_create(display, &swc_panel_manager_interface, 1, NULL, &bind_panel_manager); 61 | } 62 | -------------------------------------------------------------------------------- /libswc/panel_manager.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/panel_manager.h 2 | * 3 | * Copyright (c) 2013-2019 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_PANEL_MANAGER_H 25 | #define SWC_PANEL_MANAGER_H 26 | 27 | struct wl_display; 28 | 29 | struct wl_global *panel_manager_create(struct wl_display *display); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /libswc/plane.c: -------------------------------------------------------------------------------- 1 | /* swc: libswc/plane.c 2 | * 3 | * Copyright (c) 2019 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #include "plane.h" 25 | #include "event.h" 26 | #include "drm.h" 27 | #include "internal.h" 28 | #include "screen.h" 29 | #include "util.h" 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | enum plane_property { 38 | PLANE_TYPE, 39 | PLANE_IN_FENCE_FD, 40 | PLANE_CRTC_ID, 41 | PLANE_CRTC_X, 42 | PLANE_CRTC_Y, 43 | PLANE_CRTC_W, 44 | PLANE_CRTC_H, 45 | PLANE_SRC_X, 46 | PLANE_SRC_Y, 47 | PLANE_SRC_W, 48 | PLANE_SRC_H, 49 | }; 50 | 51 | static bool 52 | update(struct view *view) 53 | { 54 | struct plane *plane = wl_container_of(view, plane, view); 55 | uint32_t x, y, w, h; 56 | 57 | if (!plane->screen) 58 | return false; 59 | x = view->geometry.x - plane->screen->base.geometry.x; 60 | y = view->geometry.y - plane->screen->base.geometry.y; 61 | w = view->geometry.width; 62 | h = view->geometry.height; 63 | if (swc.active && drmModeSetPlane(swc.drm->fd, plane->id, plane->screen->crtc, plane->fb, 0, x, y, w, h, 0, 0, w << 16, h << 16) < 0) { 64 | ERROR("Could not set cursor: %s\n", strerror(errno)); 65 | return false; 66 | } 67 | 68 | return true; 69 | } 70 | 71 | static int 72 | attach(struct view *view, struct wld_buffer *buffer) 73 | { 74 | struct plane *plane = wl_container_of(view, plane, view); 75 | 76 | plane->fb = drm_get_framebuffer(buffer); 77 | view_set_size_from_buffer(view, buffer); 78 | return 0; 79 | } 80 | 81 | static bool 82 | move(struct view *view, int32_t x, int32_t y) 83 | { 84 | view_set_position(view, x, y); 85 | return true; 86 | } 87 | 88 | static const struct view_impl view_impl = { 89 | .update = update, 90 | .attach = attach, 91 | .move = move, 92 | }; 93 | 94 | static enum plane_property 95 | find_prop(const char *name) 96 | { 97 | static const char property_names[][16] = { 98 | [PLANE_TYPE] = "type", 99 | [PLANE_IN_FENCE_FD] = "IN_FENCE_FD", 100 | [PLANE_CRTC_ID] = "CRTC_ID", 101 | [PLANE_CRTC_X] = "CRTC_X", 102 | [PLANE_CRTC_Y] = "CRTC_Y", 103 | [PLANE_CRTC_W] = "CRTC_W", 104 | [PLANE_CRTC_H] = "CRTC_H", 105 | [PLANE_SRC_X] = "SRC_X", 106 | [PLANE_SRC_Y] = "SRC_Y", 107 | [PLANE_SRC_W] = "SRC_W", 108 | [PLANE_SRC_H] = "SRC_H", 109 | }; 110 | size_t i; 111 | 112 | for (i = 0; i < ARRAY_LENGTH(property_names); ++i) { 113 | if (strcmp(name, property_names[i]) == 0) 114 | return i; 115 | } 116 | return -1; 117 | } 118 | 119 | static void 120 | handle_swc_event(struct wl_listener *listener, void *data) 121 | { 122 | struct event *event = data; 123 | struct plane *plane = wl_container_of(listener, plane, swc_listener); 124 | 125 | switch (event->type) { 126 | case SWC_EVENT_ACTIVATED: 127 | update(&plane->view); 128 | break; 129 | } 130 | } 131 | 132 | struct plane * 133 | plane_new(uint32_t id) 134 | { 135 | struct plane *plane; 136 | uint32_t i; 137 | drmModeObjectProperties *props; 138 | drmModePropertyRes *prop; 139 | drmModePlane *drm_plane; 140 | 141 | plane = malloc(sizeof(*plane)); 142 | if (!plane) 143 | goto error0; 144 | drm_plane = drmModeGetPlane(swc.drm->fd, id); 145 | if (!drm_plane) 146 | goto error1; 147 | plane->id = id; 148 | plane->fb = 0; 149 | plane->screen = NULL; 150 | plane->possible_crtcs = drm_plane->possible_crtcs; 151 | drmModeFreePlane(drm_plane); 152 | plane->type = -1; 153 | props = drmModeObjectGetProperties(swc.drm->fd, id, DRM_MODE_OBJECT_PLANE); 154 | for (i = 0; i < props->count_props; ++i, drmModeFreeProperty(prop)) { 155 | prop = drmModeGetProperty(swc.drm->fd, props->props[i]); 156 | if (prop && find_prop(prop->name) == PLANE_TYPE) 157 | plane->type = props->prop_values[i]; 158 | } 159 | plane->swc_listener.notify = &handle_swc_event; 160 | wl_signal_add(&swc.event_signal, &plane->swc_listener); 161 | view_initialize(&plane->view, &view_impl); 162 | return plane; 163 | 164 | error1: 165 | free(plane); 166 | error0: 167 | return NULL; 168 | } 169 | 170 | void 171 | plane_destroy(struct plane *plane) 172 | { 173 | free(plane); 174 | } 175 | -------------------------------------------------------------------------------- /libswc/plane.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/plane.h 2 | * 3 | * Copyright (c) 2019 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_PLANE_H 25 | #define SWC_PLANE_H 26 | 27 | #include "plane.h" 28 | #include "view.h" 29 | 30 | #include 31 | 32 | struct plane { 33 | struct view view; 34 | struct screen *screen; 35 | uint32_t id, fb; 36 | int type; 37 | uint32_t possible_crtcs; 38 | struct wl_listener swc_listener; 39 | struct wl_list link; 40 | }; 41 | 42 | struct plane *plane_new(uint32_t id); 43 | void plane_destroy(struct plane *plane); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /libswc/pointer.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/pointer.h 2 | * 3 | * Copyright (c) 2013, 2014 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_POINTER_H 25 | #define SWC_POINTER_H 26 | 27 | #include "input.h" 28 | #include "view.h" 29 | 30 | #include 31 | #include 32 | 33 | struct button { 34 | struct press press; 35 | struct pointer_handler *handler; 36 | }; 37 | 38 | struct pointer_handler { 39 | bool (*motion)(struct pointer_handler *handler, uint32_t time, wl_fixed_t x, wl_fixed_t y); 40 | bool (*button)(struct pointer_handler *handler, uint32_t time, struct button *button, uint32_t state); 41 | bool (*axis)(struct pointer_handler *handler, uint32_t time, enum wl_pointer_axis axis, enum wl_pointer_axis_source source, wl_fixed_t value, int value120); 42 | void (*frame)(struct pointer_handler *handler); 43 | 44 | int pending; 45 | struct wl_list link; 46 | }; 47 | 48 | struct pointer { 49 | struct input_focus focus; 50 | struct input_focus_handler focus_handler; 51 | 52 | struct { 53 | struct view view; 54 | struct surface *surface; 55 | struct wl_listener destroy_listener; 56 | struct wld_buffer *buffer; 57 | 58 | /* Used for cursors set with pointer_set_cursor */ 59 | struct wld_buffer *internal_buffer; 60 | 61 | struct { 62 | int32_t x, y; 63 | } hotspot; 64 | } cursor; 65 | 66 | struct wl_array buttons; 67 | struct wl_list handlers; 68 | struct pointer_handler client_handler; 69 | enum wl_pointer_axis_source client_axis_source; 70 | 71 | wl_fixed_t x, y; 72 | pixman_region32_t region; 73 | }; 74 | 75 | bool pointer_initialize(struct pointer *pointer); 76 | void pointer_finalize(struct pointer *pointer); 77 | void pointer_set_focus(struct pointer *pointer, struct compositor_view *view); 78 | void pointer_set_region(struct pointer *pointer, pixman_region32_t *region); 79 | void pointer_set_cursor(struct pointer *pointer, uint32_t id); 80 | 81 | struct button *pointer_get_button(struct pointer *pointer, uint32_t serial); 82 | 83 | struct wl_resource *pointer_bind(struct pointer *pointer, struct wl_client *client, uint32_t version, uint32_t id); 84 | void pointer_handle_button(struct pointer *pointer, uint32_t time, uint32_t button, uint32_t state); 85 | void pointer_handle_axis(struct pointer *pointer, uint32_t time, enum wl_pointer_axis axis, enum wl_pointer_axis_source source, wl_fixed_t value, int value120); 86 | void pointer_handle_relative_motion(struct pointer *pointer, uint32_t time, wl_fixed_t dx, wl_fixed_t dy); 87 | void pointer_handle_absolute_motion(struct pointer *pointer, uint32_t time, wl_fixed_t x, wl_fixed_t y); 88 | void pointer_handle_frame(struct pointer *pointer); 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /libswc/primary_plane.c: -------------------------------------------------------------------------------- 1 | /* swc: primary_plane.c 2 | * 3 | * Copyright (c) 2013, 2014, 2016 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #include "primary_plane.h" 25 | #include "drm.h" 26 | #include "event.h" 27 | #include "internal.h" 28 | #include "launch.h" 29 | #include "util.h" 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | static bool 38 | update(struct view *view) 39 | { 40 | return true; 41 | } 42 | 43 | static void 44 | send_frame(void *data) 45 | { 46 | struct primary_plane *plane = data; 47 | 48 | view_frame(&plane->view, get_time()); 49 | } 50 | 51 | static int 52 | attach(struct view *view, struct wld_buffer *buffer) 53 | { 54 | struct primary_plane *plane = wl_container_of(view, plane, view); 55 | uint32_t fb; 56 | int ret; 57 | 58 | fb = drm_get_framebuffer(buffer); 59 | if (plane->need_modeset) { 60 | ret = drmModeSetCrtc(swc.drm->fd, plane->crtc, fb, 0, 0, plane->connectors.data, plane->connectors.size / 4, &plane->mode.info); 61 | 62 | if (ret == 0) { 63 | wl_event_loop_add_idle(swc.event_loop, &send_frame, plane); 64 | plane->need_modeset = false; 65 | } else { 66 | ERROR("Could not set CRTC to next framebuffer: %s\n", strerror(-ret)); 67 | return ret; 68 | } 69 | } else { 70 | ret = drmModePageFlip(swc.drm->fd, plane->crtc, fb, DRM_MODE_PAGE_FLIP_EVENT, &plane->drm_handler); 71 | 72 | if (ret < 0) { 73 | ERROR("Page flip failed: %s\n", strerror(errno)); 74 | return ret; 75 | } 76 | } 77 | 78 | return 0; 79 | } 80 | 81 | static bool 82 | move(struct view *view, int32_t x, int32_t y) 83 | { 84 | view_set_position(view, x, y); 85 | return true; 86 | } 87 | 88 | static const struct view_impl view_impl = { 89 | .update = update, 90 | .attach = attach, 91 | .move = move, 92 | }; 93 | 94 | static void 95 | handle_page_flip(struct drm_handler *handler, uint32_t time) 96 | { 97 | struct primary_plane *plane = wl_container_of(handler, plane, drm_handler); 98 | view_frame(&plane->view, time); 99 | } 100 | 101 | static void 102 | handle_swc_event(struct wl_listener *listener, void *data) 103 | { 104 | struct event *event = data; 105 | struct primary_plane *plane = wl_container_of(listener, plane, swc_listener); 106 | 107 | switch (event->type) { 108 | case SWC_EVENT_ACTIVATED: 109 | plane->need_modeset = true; 110 | break; 111 | } 112 | } 113 | 114 | bool 115 | primary_plane_initialize(struct primary_plane *plane, uint32_t crtc, struct mode *mode, uint32_t *connectors, uint32_t num_connectors) 116 | { 117 | uint32_t *plane_connectors; 118 | 119 | if (!(plane->original_crtc_state = drmModeGetCrtc(swc.drm->fd, crtc))) { 120 | ERROR("Failed to get CRTC state for CRTC %u: %s\n", crtc, strerror(errno)); 121 | goto error0; 122 | } 123 | 124 | wl_array_init(&plane->connectors); 125 | plane_connectors = wl_array_add(&plane->connectors, num_connectors * sizeof(connectors[0])); 126 | 127 | if (!plane_connectors) { 128 | ERROR("Failed to allocate connector array\n"); 129 | goto error1; 130 | } 131 | 132 | memcpy(plane_connectors, connectors, num_connectors * sizeof(connectors[0])); 133 | plane->crtc = crtc; 134 | plane->need_modeset = true; 135 | view_initialize(&plane->view, &view_impl); 136 | plane->view.geometry.width = mode->width; 137 | plane->view.geometry.height = mode->height; 138 | plane->drm_handler.page_flip = &handle_page_flip; 139 | plane->swc_listener.notify = &handle_swc_event; 140 | plane->mode = *mode; 141 | wl_signal_add(&swc.event_signal, &plane->swc_listener); 142 | 143 | return true; 144 | 145 | error1: 146 | drmModeFreeCrtc(plane->original_crtc_state); 147 | error0: 148 | return false; 149 | } 150 | 151 | void 152 | primary_plane_finalize(struct primary_plane *plane) 153 | { 154 | wl_array_release(&plane->connectors); 155 | drmModeCrtcPtr crtc = plane->original_crtc_state; 156 | drmModeSetCrtc(swc.drm->fd, crtc->crtc_id, crtc->buffer_id, crtc->x, crtc->y, NULL, 0, &crtc->mode); 157 | drmModeFreeCrtc(crtc); 158 | } 159 | -------------------------------------------------------------------------------- /libswc/primary_plane.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/primary_plane.h 2 | * 3 | * Copyright (c) 2013, 2016 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_PRIMARY_PLANE_H 25 | #define SWC_PRIMARY_PLANE_H 26 | 27 | #include "drm.h" 28 | #include "mode.h" 29 | #include "view.h" 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | struct primary_plane { 36 | uint32_t crtc; 37 | drmModeCrtcPtr original_crtc_state; 38 | struct mode mode; 39 | struct view view; 40 | struct wl_array connectors; 41 | bool need_modeset; 42 | struct drm_handler drm_handler; 43 | struct wl_listener swc_listener; 44 | }; 45 | 46 | bool primary_plane_initialize(struct primary_plane *plane, uint32_t crtc, struct mode *mode, uint32_t *connectors, uint32_t num_connectors); 47 | void primary_plane_finalize(struct primary_plane *plane); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /libswc/region.c: -------------------------------------------------------------------------------- 1 | #include "region.h" 2 | #include "util.h" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | static void 9 | add(struct wl_client *client, struct wl_resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) 10 | { 11 | pixman_region32_t *region = wl_resource_get_user_data(resource); 12 | 13 | pixman_region32_union_rect(region, region, x, y, width, height); 14 | } 15 | 16 | static void 17 | subtract(struct wl_client *client, struct wl_resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) 18 | { 19 | pixman_region32_t *region = wl_resource_get_user_data(resource); 20 | pixman_region32_t operand; 21 | 22 | pixman_region32_init_rect(&operand, x, y, width, height); 23 | pixman_region32_subtract(region, region, &operand); 24 | } 25 | 26 | static const struct wl_region_interface region_impl = { 27 | .destroy = destroy_resource, 28 | .add = add, 29 | .subtract = subtract, 30 | }; 31 | 32 | static void 33 | region_destroy(struct wl_resource *resource) 34 | { 35 | pixman_region32_t *region = wl_resource_get_user_data(resource); 36 | 37 | pixman_region32_fini(region); 38 | free(region); 39 | } 40 | 41 | struct wl_resource * 42 | region_new(struct wl_client *client, uint32_t version, uint32_t id) 43 | { 44 | pixman_region32_t *region; 45 | struct wl_resource *resource; 46 | 47 | region = malloc(sizeof(*region)); 48 | if (!region) 49 | goto error0; 50 | 51 | resource = wl_resource_create(client, &wl_region_interface, version, id); 52 | if (!resource) 53 | goto error1; 54 | wl_resource_set_implementation(resource, ®ion_impl, region, ®ion_destroy); 55 | 56 | pixman_region32_init(region); 57 | 58 | return resource; 59 | 60 | error1: 61 | free(region); 62 | error0: 63 | return NULL; 64 | } 65 | -------------------------------------------------------------------------------- /libswc/region.h: -------------------------------------------------------------------------------- 1 | #ifndef SWC_REGION_H 2 | #define SWC_REGION_H 3 | 4 | #include 5 | 6 | struct wl_client; 7 | 8 | struct wl_resource *region_new(struct wl_client *client, uint32_t version, uint32_t id); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /libswc/screen.c: -------------------------------------------------------------------------------- 1 | /* swc: libswc/screen.c 2 | * 3 | * Copyright (c) 2013, 2014 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #include "screen.h" 25 | #include "drm.h" 26 | #include "event.h" 27 | #include "internal.h" 28 | #include "mode.h" 29 | #include "output.h" 30 | #include "plane.h" 31 | #include "pointer.h" 32 | #include "util.h" 33 | 34 | #include 35 | #include "swc-server-protocol.h" 36 | 37 | #define INTERNAL(s) ((struct screen *)(s)) 38 | 39 | static struct screen *active_screen; 40 | static const struct swc_screen_handler null_handler; 41 | 42 | static bool handle_motion(struct pointer_handler *handler, uint32_t time, wl_fixed_t x, wl_fixed_t y); 43 | 44 | struct pointer_handler screens_pointer_handler = { 45 | .motion = handle_motion, 46 | }; 47 | 48 | EXPORT void 49 | swc_screen_set_handler(struct swc_screen *base, const struct swc_screen_handler *handler, void *data) 50 | { 51 | struct screen *screen = INTERNAL(base); 52 | 53 | screen->handler = handler; 54 | screen->handler_data = data; 55 | } 56 | 57 | bool 58 | screens_initialize(void) 59 | { 60 | wl_list_init(&swc.screens); 61 | 62 | if (!drm_create_screens(&swc.screens)) 63 | return false; 64 | 65 | if (wl_list_empty(&swc.screens)) 66 | return false; 67 | 68 | return true; 69 | } 70 | 71 | void 72 | screens_finalize(void) 73 | { 74 | struct screen *screen, *tmp; 75 | 76 | wl_list_for_each_safe (screen, tmp, &swc.screens, link) 77 | screen_destroy(screen); 78 | } 79 | 80 | static void 81 | bind_screen(struct wl_client *client, void *data, uint32_t version, uint32_t id) 82 | { 83 | struct screen *screen = data; 84 | struct wl_resource *resource; 85 | 86 | resource = wl_resource_create(client, &swc_screen_interface, version, id); 87 | 88 | if (!resource) { 89 | wl_client_post_no_memory(client); 90 | return; 91 | } 92 | 93 | wl_resource_set_implementation(resource, NULL, screen, &remove_resource); 94 | wl_list_insert(&screen->resources, wl_resource_get_link(resource)); 95 | } 96 | 97 | struct screen * 98 | screen_new(uint32_t crtc, struct output *output, struct plane *cursor_plane) 99 | { 100 | struct screen *screen; 101 | int32_t x = 0; 102 | 103 | /* Simple heuristic for initial screen positioning. */ 104 | wl_list_for_each (screen, &swc.screens, link) 105 | x = MAX(x, screen->base.geometry.x + screen->base.geometry.width); 106 | 107 | if (!(screen = malloc(sizeof(*screen)))) 108 | goto error0; 109 | 110 | screen->global = wl_global_create(swc.display, &swc_screen_interface, 1, screen, &bind_screen); 111 | 112 | if (!screen->global) { 113 | ERROR("Failed to create screen global\n"); 114 | goto error1; 115 | } 116 | 117 | screen->crtc = crtc; 118 | 119 | if (!primary_plane_initialize(&screen->planes.primary, crtc, output->preferred_mode, &output->connector, 1)) { 120 | ERROR("Failed to initialize primary plane\n"); 121 | goto error2; 122 | } 123 | 124 | cursor_plane->screen = screen; 125 | screen->planes.cursor = cursor_plane; 126 | 127 | screen->handler = &null_handler; 128 | wl_signal_init(&screen->destroy_signal); 129 | wl_list_init(&screen->resources); 130 | wl_list_init(&screen->outputs); 131 | wl_list_insert(&screen->outputs, &output->link); 132 | wl_list_init(&screen->modifiers); 133 | 134 | view_move(&screen->planes.primary.view, x, 0); 135 | screen->base.geometry = screen->planes.primary.view.geometry; 136 | screen->base.usable_geometry = screen->base.geometry; 137 | 138 | swc.manager->new_screen(&screen->base); 139 | 140 | return screen; 141 | 142 | error2: 143 | wl_global_destroy(screen->global); 144 | error1: 145 | free(screen); 146 | error0: 147 | return NULL; 148 | } 149 | 150 | void 151 | screen_destroy(struct screen *screen) 152 | { 153 | struct output *output, *next; 154 | 155 | if (active_screen == screen) 156 | active_screen = NULL; 157 | if (screen->handler->destroy) 158 | screen->handler->destroy(screen->handler_data); 159 | wl_signal_emit(&screen->destroy_signal, NULL); 160 | wl_list_for_each_safe (output, next, &screen->outputs, link) 161 | output_destroy(output); 162 | primary_plane_finalize(&screen->planes.primary); 163 | plane_destroy(screen->planes.cursor); 164 | free(screen); 165 | } 166 | 167 | void 168 | screen_update_usable_geometry(struct screen *screen) 169 | { 170 | pixman_region32_t total_usable, usable; 171 | pixman_box32_t *extents; 172 | struct screen_modifier *modifier; 173 | struct swc_rectangle *geom = &screen->base.geometry; 174 | 175 | DEBUG("Updating usable geometry\n"); 176 | 177 | pixman_region32_init_rect(&total_usable, geom->x, geom->y, geom->width, geom->height); 178 | pixman_region32_init(&usable); 179 | 180 | wl_list_for_each (modifier, &screen->modifiers, link) { 181 | modifier->modify(modifier, geom, &usable); 182 | pixman_region32_intersect(&total_usable, &total_usable, &usable); 183 | } 184 | 185 | extents = pixman_region32_extents(&total_usable); 186 | 187 | if (extents->x1 != screen->base.usable_geometry.x 188 | || extents->y1 != screen->base.usable_geometry.y 189 | || (extents->x2 - extents->x1) != screen->base.usable_geometry.width 190 | || (extents->y2 - extents->y1) != screen->base.usable_geometry.height) 191 | { 192 | screen->base.usable_geometry.x = extents->x1; 193 | screen->base.usable_geometry.y = extents->y1; 194 | screen->base.usable_geometry.width = extents->x2 - extents->x1; 195 | screen->base.usable_geometry.height = extents->y2 - extents->y1; 196 | 197 | if (screen->handler->usable_geometry_changed) 198 | screen->handler->usable_geometry_changed(screen->handler_data); 199 | } 200 | } 201 | 202 | bool 203 | handle_motion(struct pointer_handler *handler, uint32_t time, wl_fixed_t fx, wl_fixed_t fy) 204 | { 205 | struct screen *screen; 206 | int32_t x = wl_fixed_to_int(fx), y = wl_fixed_to_int(fy); 207 | 208 | wl_list_for_each (screen, &swc.screens, link) { 209 | if (rectangle_contains_point(&screen->base.geometry, x, y)) { 210 | if (screen != active_screen) { 211 | active_screen = screen; 212 | 213 | if (screen->handler->entered) 214 | screen->handler->entered(screen->handler_data); 215 | } 216 | break; 217 | } 218 | } 219 | 220 | return false; 221 | } 222 | -------------------------------------------------------------------------------- /libswc/screen.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/screen.h 2 | * 3 | * Copyright (c) 2013, 2014 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_SCREEN_H 25 | #define SWC_SCREEN_H 26 | 27 | #include "swc.h" 28 | #include "primary_plane.h" 29 | 30 | #include 31 | 32 | struct output; 33 | struct pixman_region32; 34 | 35 | struct screen_modifier { 36 | /** 37 | * Takes the screen geometry and sets 'usable' to the usable region of the 38 | * screen. 'usable' is an already initialized pixman region. 39 | */ 40 | void (*modify)(struct screen_modifier *modifier, const struct swc_rectangle *geometry, struct pixman_region32 *usable); 41 | 42 | struct wl_list link; 43 | }; 44 | 45 | struct screen { 46 | struct swc_screen base; 47 | const struct swc_screen_handler *handler; 48 | void *handler_data; 49 | 50 | struct wl_signal destroy_signal; 51 | uint8_t id; 52 | uint32_t crtc; 53 | 54 | struct { 55 | struct primary_plane primary; 56 | struct plane *cursor; 57 | } planes; 58 | 59 | struct wl_global *global; 60 | struct wl_list resources; 61 | 62 | struct wl_list outputs; 63 | struct wl_list modifiers; 64 | struct wl_list link; 65 | }; 66 | 67 | bool screens_initialize(void); 68 | void screens_finalize(void); 69 | 70 | struct screen *screen_new(uint32_t crtc, struct output *output, struct plane *cursor_plane); 71 | void screen_destroy(struct screen *screen); 72 | 73 | static inline uint32_t 74 | screen_mask(struct screen *screen) 75 | { 76 | return 1 << screen->id; 77 | } 78 | 79 | void screen_update_usable_geometry(struct screen *screen); 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /libswc/seat.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/seat.h 2 | * 3 | * Copyright (c) 2013-2019 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_SEAT_H 25 | #define SWC_SEAT_H 26 | 27 | struct wl_display; 28 | 29 | struct swc_seat { 30 | struct pointer *pointer; 31 | struct keyboard *keyboard; 32 | struct data_device *data_device; 33 | }; 34 | 35 | struct swc_seat *seat_create(struct wl_display *display, const char *name); 36 | void seat_destroy(struct swc_seat *seat); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /libswc/shell.c: -------------------------------------------------------------------------------- 1 | /* swc: libswc/shell.c 2 | * 3 | * Copyright (c) 2013-2020 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #include "shell.h" 25 | #include "internal.h" 26 | #include "shell_surface.h" 27 | 28 | #include 29 | 30 | static void 31 | get_shell_surface(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource) 32 | { 33 | struct surface *surface = wl_resource_get_user_data(surface_resource); 34 | struct shell_surface *shell_surface; 35 | 36 | shell_surface = shell_surface_new(client, wl_resource_get_version(resource), id, surface); 37 | 38 | if (!shell_surface) 39 | wl_resource_post_no_memory(resource); 40 | } 41 | 42 | static const struct wl_shell_interface shell_implementation = { 43 | .get_shell_surface = get_shell_surface, 44 | }; 45 | 46 | static void 47 | bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id) 48 | { 49 | struct wl_resource *resource; 50 | 51 | resource = wl_resource_create(client, &wl_shell_interface, version, id); 52 | if (!resource) { 53 | wl_client_post_no_memory(client); 54 | return; 55 | } 56 | wl_resource_set_implementation(resource, &shell_implementation, NULL, NULL); 57 | } 58 | 59 | struct wl_global * 60 | shell_create(struct wl_display *display) 61 | { 62 | return wl_global_create(display, &wl_shell_interface, 1, NULL, &bind_shell); 63 | } 64 | -------------------------------------------------------------------------------- /libswc/shell.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/shell.h 2 | * 3 | * Copyright (c) 2013-2019 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_SHELL_H 25 | #define SWC_SHELL_H 26 | 27 | struct wl_display; 28 | 29 | struct wl_global *shell_create(struct wl_display *display); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /libswc/shell_surface.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/shell_surface.h 2 | * 3 | * Copyright (c) 2013, 2014 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_SHELL_SURFACE_H 25 | #define SWC_SHELL_SURFACE_H 26 | 27 | #include 28 | 29 | struct surface; 30 | struct wl_client; 31 | 32 | struct shell_surface *shell_surface_new(struct wl_client *client, uint32_t version, uint32_t id, struct surface *surface); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /libswc/shm.c: -------------------------------------------------------------------------------- 1 | /* swc: libswc/shm.c 2 | * 3 | * Copyright (c) 2013-2020 Michael Forney 4 | * 5 | * Based in part upon wayland-shm.c from wayland, which is: 6 | * 7 | * Copyright © 2008 Kristian Høgsberg 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a copy 10 | * of this software and associated documentation files (the "Software"), to deal 11 | * in the Software without restriction, including without limitation the rights 12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in 17 | * all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | * SOFTWARE. 26 | */ 27 | 28 | #include "shm.h" 29 | #include "internal.h" 30 | #include "util.h" 31 | #include "wayland_buffer.h" 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | struct pool { 42 | struct wl_resource *resource; 43 | struct swc_shm *shm; 44 | void *data; 45 | uint32_t size; 46 | unsigned references; 47 | }; 48 | 49 | struct pool_reference { 50 | struct wld_destructor destructor; 51 | struct pool *pool; 52 | }; 53 | 54 | static void * 55 | swc_mremap(void *oldp, size_t oldsize, size_t newsize) 56 | { 57 | #ifdef __NetBSD__ 58 | return mremap(oldp, oldsize, NULL, newsize, 0); 59 | #else /* Linux-style mremap */ 60 | return mremap(oldp, oldsize, newsize, MREMAP_MAYMOVE); 61 | #endif 62 | } 63 | 64 | static void 65 | unref_pool(struct pool *pool) 66 | { 67 | if (--pool->references > 0) 68 | return; 69 | 70 | munmap(pool->data, pool->size); 71 | free(pool); 72 | } 73 | 74 | static void 75 | destroy_pool_resource(struct wl_resource *resource) 76 | { 77 | struct pool *pool = wl_resource_get_user_data(resource); 78 | unref_pool(pool); 79 | } 80 | 81 | static void 82 | handle_buffer_destroy(struct wld_destructor *destructor) 83 | { 84 | struct pool_reference *reference = wl_container_of(destructor, reference, destructor); 85 | unref_pool(reference->pool); 86 | } 87 | 88 | static inline uint32_t 89 | format_shm_to_wld(uint32_t format) 90 | { 91 | switch (format) { 92 | case WL_SHM_FORMAT_ARGB8888: 93 | return WLD_FORMAT_ARGB8888; 94 | case WL_SHM_FORMAT_XRGB8888: 95 | return WLD_FORMAT_XRGB8888; 96 | default: 97 | return format; 98 | } 99 | } 100 | 101 | static void 102 | create_buffer(struct wl_client *client, struct wl_resource *resource, 103 | uint32_t id, int32_t offset, int32_t width, int32_t height, int32_t stride, uint32_t format) 104 | { 105 | struct pool *pool = wl_resource_get_user_data(resource); 106 | struct pool_reference *reference; 107 | struct wld_buffer *buffer; 108 | struct wl_resource *buffer_resource; 109 | union wld_object object; 110 | 111 | if (offset > pool->size || offset < 0) { 112 | wl_resource_post_error(resource, WL_SHM_ERROR_INVALID_STRIDE, "offset is too big or negative"); 113 | return; 114 | } 115 | 116 | object.ptr = (void *)((uintptr_t)pool->data + offset); 117 | buffer = wld_import_buffer(pool->shm->context, WLD_OBJECT_DATA, object, width, height, format_shm_to_wld(format), stride); 118 | 119 | if (!buffer) 120 | goto error0; 121 | 122 | buffer_resource = wayland_buffer_create_resource(client, wl_resource_get_version(resource), id, buffer); 123 | 124 | if (!buffer_resource) 125 | goto error1; 126 | 127 | if (!(reference = malloc(sizeof(*reference)))) 128 | goto error2; 129 | 130 | reference->pool = pool; 131 | reference->destructor.destroy = &handle_buffer_destroy; 132 | wld_buffer_add_destructor(buffer, &reference->destructor); 133 | ++pool->references; 134 | 135 | return; 136 | 137 | error2: 138 | wl_resource_destroy(buffer_resource); 139 | error1: 140 | wld_buffer_unreference(buffer); 141 | error0: 142 | wl_resource_post_no_memory(resource); 143 | } 144 | 145 | static void 146 | resize(struct wl_client *client, struct wl_resource *resource, int32_t size) 147 | { 148 | struct pool *pool = wl_resource_get_user_data(resource); 149 | void *data; 150 | 151 | data = swc_mremap(pool->data, pool->size, size); 152 | if (data == MAP_FAILED) { 153 | wl_resource_post_error(resource, WL_SHM_ERROR_INVALID_FD, "mremap failed: %s", strerror(errno)); 154 | return; 155 | } 156 | pool->data = data; 157 | pool->size = size; 158 | } 159 | 160 | static const struct wl_shm_pool_interface shm_pool_impl = { 161 | .create_buffer = create_buffer, 162 | .destroy = destroy_resource, 163 | .resize = resize, 164 | }; 165 | 166 | static void 167 | create_pool(struct wl_client *client, struct wl_resource *resource, uint32_t id, int32_t fd, int32_t size) 168 | { 169 | struct swc_shm *shm = wl_resource_get_user_data(resource); 170 | struct pool *pool; 171 | 172 | pool = malloc(sizeof(*pool)); 173 | if (!pool) { 174 | wl_resource_post_no_memory(resource); 175 | goto error0; 176 | } 177 | pool->shm = shm; 178 | pool->resource = wl_resource_create(client, &wl_shm_pool_interface, wl_resource_get_version(resource), id); 179 | if (!pool->resource) { 180 | wl_resource_post_no_memory(resource); 181 | goto error1; 182 | } 183 | wl_resource_set_implementation(pool->resource, &shm_pool_impl, pool, &destroy_pool_resource); 184 | pool->data = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); 185 | if (pool->data == MAP_FAILED) { 186 | wl_resource_post_error(resource, WL_SHM_ERROR_INVALID_FD, "mmap failed: %s", strerror(errno)); 187 | goto error2; 188 | } 189 | close(fd); 190 | pool->size = size; 191 | pool->references = 1; 192 | return; 193 | 194 | error2: 195 | wl_resource_destroy(pool->resource); 196 | error1: 197 | free(pool); 198 | error0: 199 | close(fd); 200 | } 201 | 202 | static const struct wl_shm_interface shm_impl = { 203 | .create_pool = &create_pool 204 | }; 205 | 206 | static void 207 | bind_shm(struct wl_client *client, void *data, uint32_t version, uint32_t id) 208 | { 209 | struct swc_shm *shm = data; 210 | struct wl_resource *resource; 211 | 212 | resource = wl_resource_create(client, &wl_shm_interface, version, id); 213 | if (!resource) { 214 | wl_client_post_no_memory(client); 215 | return; 216 | } 217 | wl_resource_set_implementation(resource, &shm_impl, shm, NULL); 218 | 219 | wl_shm_send_format(resource, WL_SHM_FORMAT_XRGB8888); 220 | wl_shm_send_format(resource, WL_SHM_FORMAT_ARGB8888); 221 | } 222 | 223 | struct swc_shm * 224 | shm_create(struct wl_display *display) 225 | { 226 | struct swc_shm *shm; 227 | 228 | shm = malloc(sizeof(*shm)); 229 | if (!shm) 230 | goto error0; 231 | shm->context = wld_pixman_create_context(); 232 | if (!shm->context) 233 | goto error1; 234 | shm->renderer = wld_create_renderer(shm->context); 235 | if (!shm->renderer) 236 | goto error2; 237 | shm->global = wl_global_create(display, &wl_shm_interface, 1, shm, &bind_shm); 238 | if (!shm->global) 239 | goto error3; 240 | 241 | return shm; 242 | 243 | error3: 244 | wld_destroy_renderer(shm->renderer); 245 | error2: 246 | wld_destroy_context(shm->context); 247 | error1: 248 | free(shm); 249 | error0: 250 | return NULL; 251 | } 252 | 253 | void 254 | shm_destroy(struct swc_shm *shm) 255 | { 256 | wl_global_destroy(shm->global); 257 | wld_destroy_renderer(shm->renderer); 258 | wld_destroy_context(shm->context); 259 | free(shm); 260 | } 261 | -------------------------------------------------------------------------------- /libswc/shm.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/shm.h 2 | * 3 | * Copyright (c) 2013-2019 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_SHM_H 25 | #define SWC_SHM_H 26 | 27 | struct wl_display; 28 | 29 | struct swc_shm { 30 | struct wl_global *global; 31 | struct wld_context *context; 32 | struct wld_renderer *renderer; 33 | }; 34 | 35 | struct swc_shm *shm_create(struct wl_display *display); 36 | void shm_destroy(struct swc_shm *shm); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /libswc/subcompositor.c: -------------------------------------------------------------------------------- 1 | /* swc: libswc/subcompositor.c 2 | * 3 | * Copyright (c) 2015-2020 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #include "swc.h" 25 | #include "internal.h" 26 | #include "subcompositor.h" 27 | #include "subsurface.h" 28 | #include "util.h" 29 | 30 | static void 31 | get_subsurface(struct wl_client *client, struct wl_resource *resource, 32 | uint32_t id, struct wl_resource *surface_resource, struct wl_resource *parent_resource) 33 | { 34 | struct subsurface *subsurface; 35 | 36 | subsurface = subsurface_new(client, wl_resource_get_version(resource), id); 37 | 38 | if (!subsurface) { 39 | wl_resource_post_no_memory(resource); 40 | return; 41 | } 42 | } 43 | 44 | static const struct wl_subcompositor_interface subcompositor_impl = { 45 | .destroy = destroy_resource, 46 | .get_subsurface = get_subsurface, 47 | }; 48 | 49 | static void 50 | bind_subcompositor(struct wl_client *client, void *data, uint32_t version, uint32_t id) 51 | { 52 | struct wl_resource *resource; 53 | 54 | resource = wl_resource_create(client, &wl_subcompositor_interface, version, id); 55 | if (!resource) { 56 | wl_client_post_no_memory(client); 57 | return; 58 | } 59 | wl_resource_set_implementation(resource, &subcompositor_impl, NULL, NULL); 60 | } 61 | 62 | struct wl_global * 63 | subcompositor_create(struct wl_display *display) 64 | { 65 | return wl_global_create(display, &wl_subcompositor_interface, 1, NULL, &bind_subcompositor); 66 | } 67 | -------------------------------------------------------------------------------- /libswc/subcompositor.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/subcompositor.h 2 | * 3 | * Copyright (c) 2015-2020 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_SUBCOMPOSITOR_H 25 | #define SWC_SUBCOMPOSITOR_H 26 | 27 | struct wl_display; 28 | 29 | struct wl_global *subcompositor_create(struct wl_display *display); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /libswc/subsurface.c: -------------------------------------------------------------------------------- 1 | /* swc: libswc/subsurface.c 2 | * 3 | * Copyright (c) 2015-2019 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #include "subsurface.h" 25 | #include "util.h" 26 | 27 | #include 28 | #include 29 | 30 | static void 31 | set_position(struct wl_client *client, struct wl_resource *resource, int32_t x, int32_t y) 32 | { 33 | /* TODO: Implement. */ 34 | } 35 | 36 | static void 37 | place_above(struct wl_client *client, struct wl_resource *resource, struct wl_resource *sibling_resource) 38 | { 39 | /* TODO: Implement. */ 40 | } 41 | 42 | static void 43 | place_below(struct wl_client *client, struct wl_resource *resource, struct wl_resource *sibling_resource) 44 | { 45 | /* TODO: Implement. */ 46 | } 47 | 48 | static void 49 | set_sync(struct wl_client *client, struct wl_resource *resource) 50 | { 51 | /* TODO: Implement. */ 52 | } 53 | 54 | static void 55 | set_desync(struct wl_client *client, struct wl_resource *resource) 56 | { 57 | /* TODO: Implement. */ 58 | } 59 | 60 | static const struct wl_subsurface_interface subsurface_impl = { 61 | .destroy = destroy_resource, 62 | .set_position = set_position, 63 | .place_above = place_above, 64 | .place_below = place_below, 65 | .set_sync = set_sync, 66 | .set_desync = set_desync, 67 | }; 68 | 69 | static void 70 | subsurface_destroy(struct wl_resource *resource) 71 | { 72 | struct subsurface *subsurface = wl_resource_get_user_data(resource); 73 | free(subsurface); 74 | } 75 | 76 | struct subsurface * 77 | subsurface_new(struct wl_client *client, uint32_t version, uint32_t id) 78 | { 79 | struct subsurface *subsurface; 80 | 81 | if (!(subsurface = malloc(sizeof(*subsurface)))) 82 | goto error0; 83 | 84 | subsurface->resource = wl_resource_create(client, &wl_subsurface_interface, version, id); 85 | 86 | if (!subsurface->resource) 87 | goto error1; 88 | 89 | wl_resource_set_implementation(subsurface->resource, &subsurface_impl, subsurface, &subsurface_destroy); 90 | 91 | return subsurface; 92 | 93 | error1: 94 | free(subsurface); 95 | error0: 96 | return NULL; 97 | } 98 | -------------------------------------------------------------------------------- /libswc/subsurface.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/subsurface.h 2 | * 3 | * Copyright (c) 2015 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_SUBSURFACE_H 25 | #define SWC_SUBSURFACE_H 26 | 27 | #include 28 | 29 | struct wl_client; 30 | 31 | struct subsurface { 32 | struct wl_resource *resource; 33 | }; 34 | 35 | struct subsurface *subsurface_new(struct wl_client *client, uint32_t version, uint32_t id); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /libswc/surface.h: -------------------------------------------------------------------------------- 1 | /* swc: surface.h 2 | * 3 | * Copyright (c) 2013 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_SURFACE_H 25 | #define SWC_SURFACE_H 26 | 27 | #include "view.h" 28 | 29 | #include 30 | #include 31 | 32 | enum { 33 | SURFACE_COMMIT_ATTACH = (1 << 0), 34 | SURFACE_COMMIT_DAMAGE = (1 << 1), 35 | SURFACE_COMMIT_OPAQUE = (1 << 2), 36 | SURFACE_COMMIT_INPUT = (1 << 3), 37 | SURFACE_COMMIT_FRAME = (1 << 4) 38 | }; 39 | 40 | struct surface_state { 41 | struct wld_buffer *buffer; 42 | struct wl_resource *buffer_resource; 43 | struct wl_listener buffer_destroy_listener; 44 | 45 | /* The region that needs to be repainted. */ 46 | pixman_region32_t damage; 47 | 48 | /* The region that is opaque. */ 49 | pixman_region32_t opaque; 50 | 51 | /* The region that accepts input. */ 52 | pixman_region32_t input; 53 | 54 | struct wl_list frame_callbacks; 55 | }; 56 | 57 | struct surface { 58 | struct wl_resource *resource; 59 | 60 | struct surface_state state; 61 | 62 | struct { 63 | struct surface_state state; 64 | uint32_t commit; 65 | int32_t x, y; 66 | } pending; 67 | 68 | struct view *view; 69 | struct view_handler view_handler; 70 | }; 71 | 72 | struct surface *surface_new(struct wl_client *client, uint32_t version, uint32_t id); 73 | void surface_set_view(struct surface *surface, struct view *view); 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /libswc/swc.c: -------------------------------------------------------------------------------- 1 | /* swc: libswc/swc.c 2 | * 3 | * Copyright (c) 2013-2020 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #include "swc.h" 25 | #include "bindings.h" 26 | #include "compositor.h" 27 | #include "data_device_manager.h" 28 | #include "drm.h" 29 | #include "event.h" 30 | #include "internal.h" 31 | #include "launch.h" 32 | #include "kde_decoration.h" 33 | #include "keyboard.h" 34 | #include "panel_manager.h" 35 | #include "pointer.h" 36 | #include "screen.h" 37 | #include "seat.h" 38 | #include "shell.h" 39 | #include "shm.h" 40 | #include "subcompositor.h" 41 | #include "util.h" 42 | #include "window.h" 43 | #include "xdg_decoration.h" 44 | #include "xdg_shell.h" 45 | #ifdef ENABLE_XWAYLAND 46 | # include "xserver.h" 47 | #endif 48 | 49 | extern struct swc_launch swc_launch; 50 | extern const struct swc_bindings swc_bindings; 51 | extern struct swc_compositor swc_compositor; 52 | extern struct swc_drm swc_drm; 53 | #ifdef ENABLE_XWAYLAND 54 | extern struct swc_xserver swc_xserver; 55 | #endif 56 | 57 | extern struct pointer_handler screens_pointer_handler; 58 | 59 | struct swc swc = { 60 | .bindings = &swc_bindings, 61 | .compositor = &swc_compositor, 62 | .drm = &swc_drm, 63 | #ifdef ENABLE_XWAYLAND 64 | .xserver = &swc_xserver, 65 | #endif 66 | }; 67 | 68 | static void 69 | setup_compositor(void) 70 | { 71 | pixman_region32_t pointer_region; 72 | struct screen *screen; 73 | struct swc_rectangle *geom; 74 | 75 | wl_list_insert(&swc.seat->keyboard->handlers, &swc.bindings->keyboard_handler->link); 76 | wl_list_insert(&swc.seat->pointer->handlers, &swc.bindings->pointer_handler->link); 77 | wl_list_insert(&swc.seat->pointer->handlers, &swc.compositor->pointer_handler->link); 78 | wl_list_insert(&swc.seat->pointer->handlers, &screens_pointer_handler.link); 79 | wl_signal_add(&swc.seat->pointer->focus.event_signal, &window_enter_listener); 80 | 81 | /* Calculate pointer region */ 82 | pixman_region32_init(&pointer_region); 83 | 84 | wl_list_for_each (screen, &swc.screens, link) { 85 | geom = &screen->base.geometry; 86 | pixman_region32_union_rect(&pointer_region, &pointer_region, geom->x, geom->y, geom->width, geom->height); 87 | } 88 | 89 | pointer_set_region(swc.seat->pointer, &pointer_region); 90 | pixman_region32_fini(&pointer_region); 91 | } 92 | 93 | void 94 | swc_activate(void) 95 | { 96 | swc.active = true; 97 | send_event(&swc.event_signal, SWC_EVENT_ACTIVATED, NULL); 98 | if (swc.manager->activate) 99 | swc.manager->activate(); 100 | } 101 | 102 | void 103 | swc_deactivate(void) 104 | { 105 | swc.active = false; 106 | send_event(&swc.event_signal, SWC_EVENT_DEACTIVATED, NULL); 107 | if (swc.manager->deactivate) 108 | swc.manager->deactivate(); 109 | } 110 | 111 | EXPORT bool 112 | swc_initialize(struct wl_display *display, struct wl_event_loop *event_loop, const struct swc_manager *manager) 113 | { 114 | swc.display = display; 115 | swc.event_loop = event_loop ? event_loop : wl_display_get_event_loop(display); 116 | swc.manager = manager; 117 | const char *default_seat = "seat0"; 118 | wl_signal_init(&swc.event_signal); 119 | 120 | if (!launch_initialize()) { 121 | ERROR("Could not connect to swc-launch\n"); 122 | goto error0; 123 | } 124 | 125 | if (!drm_initialize()) { 126 | ERROR("Could not initialize DRM\n"); 127 | goto error1; 128 | } 129 | 130 | swc.shm = shm_create(display); 131 | if (!swc.shm) { 132 | ERROR("Could not initialize SHM\n"); 133 | goto error2; 134 | } 135 | 136 | if (!bindings_initialize()) { 137 | ERROR("Could not initialize bindings\n"); 138 | goto error3; 139 | } 140 | 141 | swc.subcompositor = subcompositor_create(display); 142 | if (!swc.subcompositor) { 143 | ERROR("Could not initialize subcompositor\n"); 144 | goto error4; 145 | } 146 | 147 | if (!screens_initialize()) { 148 | ERROR("Could not initialize screens\n"); 149 | goto error5; 150 | } 151 | 152 | if (!compositor_initialize()) { 153 | ERROR("Could not initialize compositor\n"); 154 | goto error6; 155 | } 156 | 157 | swc.data_device_manager = data_device_manager_create(display); 158 | if (!swc.data_device_manager) { 159 | ERROR("Could not initialize data device manager\n"); 160 | goto error7; 161 | } 162 | 163 | swc.seat = seat_create(display, default_seat); 164 | if (!swc.seat) { 165 | ERROR("Could not initialize seat\n"); 166 | goto error8; 167 | } 168 | 169 | swc.shell = shell_create(display); 170 | if (!swc.shell) { 171 | ERROR("Could not initialize shell\n"); 172 | goto error9; 173 | } 174 | 175 | swc.xdg_shell = xdg_shell_create(display); 176 | if (!swc.xdg_shell) { 177 | ERROR("Could not initialize XDG shell\n"); 178 | goto error10; 179 | } 180 | 181 | swc.xdg_decoration_manager = xdg_decoration_manager_create(display); 182 | if (!swc.xdg_decoration_manager) { 183 | ERROR("Could not initialize XDG decoration manager\n"); 184 | goto error11; 185 | } 186 | 187 | swc.kde_decoration_manager = kde_decoration_manager_create(display); 188 | if (!swc.kde_decoration_manager) { 189 | ERROR("Could not initialize KDE decoration manager\n"); 190 | goto error12; 191 | } 192 | 193 | swc.panel_manager = panel_manager_create(display); 194 | if (!swc.panel_manager) { 195 | ERROR("Could not initialize panel manager\n"); 196 | goto error13; 197 | } 198 | 199 | #ifdef ENABLE_XWAYLAND 200 | if (!xserver_initialize()) { 201 | ERROR("Could not initialize xwayland\n"); 202 | goto error14; 203 | } 204 | #endif 205 | 206 | setup_compositor(); 207 | 208 | return true; 209 | 210 | #ifdef ENABLE_XWAYLAND 211 | error14: 212 | wl_global_destroy(swc.panel_manager); 213 | #endif 214 | error13: 215 | wl_global_destroy(swc.kde_decoration_manager); 216 | error12: 217 | wl_global_destroy(swc.xdg_decoration_manager); 218 | error11: 219 | wl_global_destroy(swc.xdg_shell); 220 | error10: 221 | wl_global_destroy(swc.shell); 222 | error9: 223 | seat_destroy(swc.seat); 224 | error8: 225 | wl_global_destroy(swc.data_device_manager); 226 | error7: 227 | wl_global_destroy(swc.subcompositor); 228 | error6: 229 | compositor_finalize(); 230 | error5: 231 | screens_finalize(); 232 | error4: 233 | bindings_finalize(); 234 | error3: 235 | shm_destroy(swc.shm); 236 | error2: 237 | drm_finalize(); 238 | error1: 239 | launch_finalize(); 240 | error0: 241 | return false; 242 | } 243 | 244 | EXPORT void 245 | swc_finalize(void) 246 | { 247 | #ifdef ENABLE_XWAYLAND 248 | xserver_finalize(); 249 | #endif 250 | wl_global_destroy(swc.panel_manager); 251 | wl_global_destroy(swc.xdg_decoration_manager); 252 | wl_global_destroy(swc.xdg_shell); 253 | wl_global_destroy(swc.shell); 254 | seat_destroy(swc.seat); 255 | wl_global_destroy(swc.data_device_manager); 256 | compositor_finalize(); 257 | screens_finalize(); 258 | bindings_finalize(); 259 | shm_destroy(swc.shm); 260 | drm_finalize(); 261 | launch_finalize(); 262 | } 263 | -------------------------------------------------------------------------------- /libswc/util.c: -------------------------------------------------------------------------------- 1 | /* swc: libswc/util.c 2 | * 3 | * Copyright (c) 2013, 2014 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #include "util.h" 25 | 26 | #include 27 | 28 | pixman_box32_t infinite_extents = { 29 | .x1 = INT32_MIN, .y1 = INT32_MIN, 30 | .x2 = INT32_MAX, .y2 = INT32_MAX, 31 | }; 32 | 33 | void 34 | remove_resource(struct wl_resource *resource) 35 | { 36 | wl_list_remove(wl_resource_get_link(resource)); 37 | } 38 | 39 | void 40 | destroy_resource(struct wl_client *client, struct wl_resource *resource) 41 | { 42 | wl_resource_destroy(resource); 43 | } 44 | -------------------------------------------------------------------------------- /libswc/util.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/util.c 2 | * 3 | * Copyright (c) 2013, 2014 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_UTIL_H 25 | #define SWC_UTIL_H 26 | 27 | #include "swc.h" 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #define EXPORT __attribute__((visibility("default"))) 38 | 39 | #if ENABLE_DEBUG 40 | #define MESSAGE_SOURCE \ 41 | fprintf(stderr, "[swc:%s:%d] ", __FILE__, __LINE__); 42 | #else 43 | #define MESSAGE_SOURCE 44 | #endif 45 | 46 | #define MESSAGE(type, format, ...) \ 47 | do { \ 48 | MESSAGE_SOURCE \ 49 | fprintf(stderr, type ": " format, ##__VA_ARGS__); \ 50 | } while (false) 51 | 52 | #define WARNING(format, ...) MESSAGE("WARNING", format, ##__VA_ARGS__) 53 | #define ERROR(format, ...) MESSAGE("ERROR", format, ##__VA_ARGS__) 54 | 55 | #if ENABLE_DEBUG 56 | #define DEBUG(format, ...) MESSAGE("DEBUG", format, ##__VA_ARGS__) 57 | #else 58 | #define DEBUG(format, ...) 59 | #endif 60 | 61 | #define ARRAY_LENGTH(array) (sizeof(array) / sizeof(array)[0]) 62 | 63 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) 64 | #define MAX(a, b) ((a) > (b) ? (a) : (b)) 65 | 66 | struct wl_resource; 67 | struct wl_client; 68 | 69 | void remove_resource(struct wl_resource *resource); 70 | void destroy_resource(struct wl_client *client, struct wl_resource *resource); 71 | 72 | static inline uint32_t 73 | get_time(void) 74 | { 75 | struct timeval timeval; 76 | 77 | gettimeofday(&timeval, NULL); 78 | return timeval.tv_sec * 1000 + timeval.tv_usec / 1000; 79 | } 80 | 81 | extern pixman_box32_t infinite_extents; 82 | 83 | static inline bool 84 | rectangle_contains_point(const struct swc_rectangle *rectangle, int32_t x, int32_t y) 85 | { 86 | return x > rectangle->x && x < rectangle->x + rectangle->width 87 | && y > rectangle->y && y < rectangle->y + rectangle->height; 88 | } 89 | 90 | static inline bool 91 | rectangle_overlap(const struct swc_rectangle *r1, const struct swc_rectangle *r2) 92 | { 93 | return (MAX(r1->x + r1->width, r2->x + r2->width) - MIN(r1->x, r2->x) 94 | < r1->width + r2->width) 95 | && (MAX(r1->y + r1->height, r2->y + r2->height) - MIN(r1->y, r2->y) 96 | < r1->height + r2->height); 97 | } 98 | 99 | static inline void 100 | array_remove(struct wl_array *array, void *item, size_t size) 101 | { 102 | size_t bytes = array->size - ((intptr_t)item + size - (intptr_t)array->data); 103 | if (bytes > 0) 104 | memmove(item, (void *)((intptr_t)item + size), bytes); 105 | array->size -= size; 106 | } 107 | 108 | #endif 109 | -------------------------------------------------------------------------------- /libswc/view.c: -------------------------------------------------------------------------------- 1 | /* swc: libswc/view.c 2 | * 3 | * Copyright (c) 2013 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #include "view.h" 25 | #include "event.h" 26 | #include "internal.h" 27 | #include "screen.h" 28 | #include "util.h" 29 | 30 | #include 31 | 32 | #define HANDLE(view, handler, method, ...) \ 33 | do { \ 34 | wl_list_for_each (handler, &view->handlers, link) { \ 35 | if (handler->impl->method) \ 36 | handler->impl->method(handler, ##__VA_ARGS__); \ 37 | } \ 38 | } while (0) 39 | 40 | void 41 | view_initialize(struct view *view, const struct view_impl *impl) 42 | { 43 | view->impl = impl; 44 | view->geometry.x = 0; 45 | view->geometry.y = 0; 46 | view->geometry.width = 0; 47 | view->geometry.height = 0; 48 | view->buffer = NULL; 49 | view->screens = 0; 50 | wl_list_init(&view->handlers); 51 | } 52 | 53 | void 54 | view_finalize(struct view *view) 55 | { 56 | if (view->buffer) 57 | wld_buffer_unreference(view->buffer); 58 | } 59 | 60 | int 61 | view_attach(struct view *view, struct wld_buffer *buffer) 62 | { 63 | int ret; 64 | struct view_handler *handler; 65 | 66 | if ((ret = view->impl->attach(view, buffer)) < 0) 67 | return ret; 68 | 69 | if (view->buffer) 70 | wld_buffer_unreference(view->buffer); 71 | 72 | if (buffer) 73 | wld_buffer_reference(buffer); 74 | 75 | view->buffer = buffer; 76 | HANDLE(view, handler, attach); 77 | 78 | return 0; 79 | } 80 | 81 | bool 82 | view_update(struct view *view) 83 | { 84 | return view->impl->update(view); 85 | } 86 | 87 | bool 88 | view_move(struct view *view, int32_t x, int32_t y) 89 | { 90 | return view->impl->move(view, x, y); 91 | } 92 | 93 | bool 94 | view_set_position(struct view *view, int32_t x, int32_t y) 95 | { 96 | struct view_handler *handler; 97 | 98 | if (x == view->geometry.x && y == view->geometry.y) 99 | return false; 100 | 101 | view->geometry.x = x; 102 | view->geometry.y = y; 103 | HANDLE(view, handler, move); 104 | 105 | return true; 106 | } 107 | 108 | bool 109 | view_set_size(struct view *view, uint32_t width, uint32_t height) 110 | { 111 | struct view_handler *handler; 112 | 113 | if (view->geometry.width == width && view->geometry.height == height) 114 | return false; 115 | 116 | uint32_t old_width = view->geometry.width, old_height = view->geometry.height; 117 | 118 | view->geometry.width = width; 119 | view->geometry.height = height; 120 | HANDLE(view, handler, resize, old_width, old_height); 121 | 122 | return true; 123 | } 124 | 125 | bool 126 | view_set_size_from_buffer(struct view *view, struct wld_buffer *buffer) 127 | { 128 | return view_set_size(view, buffer ? buffer->width : 0, buffer ? buffer->height : 0); 129 | } 130 | 131 | void 132 | view_set_screens(struct view *view, uint32_t screens) 133 | { 134 | if (view->screens == screens) 135 | return; 136 | 137 | uint32_t entered = screens & ~view->screens, left = view->screens & ~screens; 138 | struct view_handler *handler; 139 | 140 | view->screens = screens; 141 | HANDLE(view, handler, screens, entered, left); 142 | } 143 | 144 | void 145 | view_update_screens(struct view *view) 146 | { 147 | uint32_t screens = 0; 148 | struct screen *screen; 149 | 150 | wl_list_for_each (screen, &swc.screens, link) { 151 | if (rectangle_overlap(&screen->base.geometry, &view->geometry)) 152 | screens |= screen_mask(screen); 153 | } 154 | 155 | view_set_screens(view, screens); 156 | } 157 | 158 | void 159 | view_frame(struct view *view, uint32_t time) 160 | { 161 | struct view_handler *handler; 162 | HANDLE(view, handler, frame, time); 163 | } 164 | -------------------------------------------------------------------------------- /libswc/view.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/view.h 2 | * 3 | * Copyright (c) 2013 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_VIEW_H 25 | #define SWC_VIEW_H 26 | 27 | #include "swc.h" 28 | 29 | #include 30 | 31 | /** 32 | * A view represents a component that can display buffers to the user. 33 | * 34 | * For example, each output contains a view residing in its framebuffer plane 35 | * that is used to scan out buffers. Additionally, the compositor creates views 36 | * dynamically for each surface it displays, compositing them into a single 37 | * buffer, which it can then attach to the previously mentioned view. 38 | * 39 | * This abstraction allows various components of swc to connect in a general 40 | * way, allowing operations like setting the output view of a surface directly 41 | * to an output's framebuffer plane, bypassing the compositor. 42 | */ 43 | struct view { 44 | const struct view_impl *impl; 45 | struct wl_list handlers; 46 | 47 | struct swc_rectangle geometry; 48 | uint32_t screens; 49 | 50 | struct wld_buffer *buffer; 51 | }; 52 | 53 | struct view_handler { 54 | const struct view_handler_impl *impl; 55 | struct wl_list link; 56 | }; 57 | 58 | /** 59 | * Every view must have an implementation containing these functions. 60 | * 61 | * For descriptions, see the corresponding view_* function. 62 | */ 63 | struct view_impl { 64 | bool (*update)(struct view *view); 65 | int (*attach)(struct view *view, struct wld_buffer *buffer); 66 | bool (*move)(struct view *view, int32_t x, int32_t y); 67 | }; 68 | 69 | struct view_handler_impl { 70 | /* Called when the view has displayed the next frame. */ 71 | void (*frame)(struct view_handler *handler, uint32_t time); 72 | /* Called when a new buffer is attached to the view. */ 73 | void (*attach)(struct view_handler *handler); 74 | /* Called after the view's position changes. */ 75 | void (*move)(struct view_handler *handler); 76 | /* Called after the view's size changes. */ 77 | void (*resize)(struct view_handler *handler, uint32_t old_width, uint32_t old_height); 78 | /* Called when the set of screens the view is visible on changes. */ 79 | void (*screens)(struct view_handler *handler, uint32_t left, uint32_t entered); 80 | }; 81 | 82 | /** 83 | * Attach a new buffer to the view. 84 | * 85 | * If buffer is NULL, the previous buffer is removed from the view. 86 | * 87 | * @return 0 on success, negative error code otherwise. 88 | */ 89 | int view_attach(struct view *view, struct wld_buffer *buffer); 90 | 91 | /** 92 | * Display a new frame consisting of the currently attached buffer. 93 | * 94 | * @return Whether or not the update succeeds. 95 | */ 96 | bool view_update(struct view *view); 97 | 98 | /** 99 | * Move the view to the specified coordinates, if supported. 100 | * 101 | * @return Whether or not the move succeeds. 102 | */ 103 | bool view_move(struct view *view, int32_t x, int32_t y); 104 | 105 | /**** For internal view use only ****/ 106 | 107 | /** 108 | * Initialize a new view with the specified implementation. 109 | */ 110 | void view_initialize(struct view *view, const struct view_impl *impl); 111 | 112 | /** 113 | * Release any resources associated with this view. 114 | */ 115 | void view_finalize(struct view *view); 116 | 117 | bool view_set_position(struct view *view, int32_t x, int32_t y); 118 | bool view_set_size(struct view *view, uint32_t width, uint32_t height); 119 | bool view_set_size_from_buffer(struct view *view, struct wld_buffer *bufer); 120 | void view_set_screens(struct view *view, uint32_t screens); 121 | void view_update_screens(struct view *view); 122 | 123 | /** 124 | * Send a new frame event through the view's event signal. 125 | * 126 | * This should be called by the view itself when the next frame is visible to 127 | * the user. If time information is not available, get_time() can be passed 128 | * instead. 129 | */ 130 | void view_frame(struct view *view, uint32_t time); 131 | 132 | #endif 133 | -------------------------------------------------------------------------------- /libswc/wayland_buffer.c: -------------------------------------------------------------------------------- 1 | /* swc: libswc/wayland_buffer.c 2 | * 3 | * Copyright (c) 2013 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #include "wayland_buffer.h" 25 | #include "internal.h" 26 | #include "shm.h" 27 | #include "util.h" 28 | 29 | #include 30 | #include 31 | 32 | static const struct wl_buffer_interface buffer_impl = { 33 | .destroy = destroy_resource, 34 | }; 35 | 36 | struct wld_buffer * 37 | wayland_buffer_get(struct wl_resource *resource) 38 | { 39 | if (wl_resource_instance_of(resource, &wl_buffer_interface, &buffer_impl)) 40 | return wl_resource_get_user_data(resource); 41 | 42 | return NULL; 43 | } 44 | 45 | static void 46 | destroy_buffer(struct wl_resource *resource) 47 | { 48 | struct wld_buffer *buffer = wl_resource_get_user_data(resource); 49 | wld_buffer_unreference(buffer); 50 | } 51 | 52 | struct wl_resource * 53 | wayland_buffer_create_resource(struct wl_client *client, uint32_t version, uint32_t id, struct wld_buffer *buffer) 54 | { 55 | struct wl_resource *resource; 56 | 57 | resource = wl_resource_create(client, &wl_buffer_interface, version, id); 58 | if (resource) 59 | wl_resource_set_implementation(resource, &buffer_impl, buffer, &destroy_buffer); 60 | return resource; 61 | } 62 | -------------------------------------------------------------------------------- /libswc/wayland_buffer.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/wayland_buffer.h 2 | * 3 | * Copyright (c) 2013 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_WAYLAND_BUFFER_H 25 | #define SWC_WAYLAND_BUFFER_H 26 | 27 | #include 28 | 29 | struct wl_client; 30 | struct wl_resource; 31 | 32 | struct wld_buffer *wayland_buffer_get(struct wl_resource *resource); 33 | struct wl_resource *wayland_buffer_create_resource(struct wl_client *client, uint32_t version, uint32_t id, struct wld_buffer *buffer); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /libswc/window.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/window.h 2 | * 3 | * Copyright (c) 2013 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_WINDOW_H 25 | #define SWC_WINDOW_H 26 | 27 | #include "swc.h" 28 | #include "pointer.h" 29 | 30 | #include 31 | #include 32 | 33 | struct window_pointer_interaction { 34 | bool active; 35 | uint32_t serial; 36 | struct pointer_handler handler, *original_handler; 37 | }; 38 | 39 | enum window_mode { 40 | WINDOW_MODE_STACKED, 41 | WINDOW_MODE_TILED, 42 | WINDOW_MODE_FULLSCREEN, 43 | }; 44 | 45 | struct window { 46 | struct swc_window base; 47 | const struct window_impl *impl; 48 | const struct swc_window_handler *handler; 49 | void *handler_data; 50 | 51 | struct compositor_view *view; 52 | struct view_handler view_handler; 53 | bool managed; 54 | unsigned mode; 55 | 56 | struct { 57 | struct window_pointer_interaction interaction; 58 | struct { 59 | int32_t x, y; 60 | } offset; 61 | 62 | bool pending; 63 | int32_t x, y; 64 | } move; 65 | 66 | struct { 67 | struct window_pointer_interaction interaction; 68 | struct { 69 | int32_t x, y; 70 | } offset; 71 | uint32_t edges; 72 | } resize; 73 | 74 | struct { 75 | bool pending, acknowledged; 76 | uint32_t width, height; 77 | } configure; 78 | }; 79 | 80 | struct window_impl { 81 | void (*move)(struct window *window, int32_t x, int32_t y); 82 | void (*configure)(struct window *window, uint32_t width, uint32_t height); 83 | void (*focus)(struct window *window); 84 | void (*unfocus)(struct window *window); 85 | void (*close)(struct window *window); 86 | void (*set_mode)(struct window *window, enum window_mode mode); 87 | }; 88 | 89 | extern struct wl_listener window_enter_listener; 90 | 91 | bool window_initialize(struct window *window, const struct window_impl *impl, struct surface *surface); 92 | void window_finalize(struct window *window); 93 | void window_manage(struct window *window); 94 | void window_unmanage(struct window *window); 95 | void window_set_title(struct window *window, const char *title, size_t length); 96 | void window_set_app_id(struct window *window, const char *app_id); 97 | void window_set_parent(struct window *window, struct window *parent); 98 | void window_begin_move(struct window *window, struct button *button); 99 | void window_begin_resize(struct window *window, uint32_t edges, struct button *button); 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /libswc/xdg_decoration.c: -------------------------------------------------------------------------------- 1 | /* swc: libswc/xdg_decoration.c 2 | * 3 | * Copyright (c) 2020 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #include "xdg_decoration.h" 25 | #include "util.h" 26 | 27 | #include 28 | #include "xdg-decoration-unstable-v1-server-protocol.h" 29 | 30 | struct xdg_toplevel_decoration { 31 | struct wl_resource *resource; 32 | struct wl_listener toplevel_destroy_listener; 33 | }; 34 | 35 | static void 36 | set_mode(struct wl_client *client, struct wl_resource *resource, uint32_t mode) 37 | { 38 | } 39 | 40 | static void 41 | unset_mode(struct wl_client *client, struct wl_resource *resource) 42 | { 43 | } 44 | 45 | static const struct zxdg_toplevel_decoration_v1_interface decoration_impl = { 46 | .destroy = destroy_resource, 47 | .set_mode = set_mode, 48 | .unset_mode = unset_mode, 49 | }; 50 | 51 | static void 52 | handle_toplevel_destroy(struct wl_listener *listener, void *data) 53 | { 54 | struct xdg_toplevel_decoration *decoration = wl_container_of(listener, decoration, toplevel_destroy_listener); 55 | 56 | wl_resource_destroy(decoration->resource); 57 | } 58 | 59 | static void 60 | decoration_destroy(struct wl_resource *resource) 61 | { 62 | struct xdg_toplevel_decoration *decoration = wl_resource_get_user_data(resource); 63 | 64 | wl_list_remove(&decoration->toplevel_destroy_listener.link); 65 | free(decoration); 66 | } 67 | 68 | static void 69 | get_toplevel_decoration(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *toplevel_resource) 70 | { 71 | struct xdg_toplevel_decoration *decoration; 72 | 73 | decoration = malloc(sizeof(*decoration)); 74 | if (!decoration) 75 | goto error0; 76 | decoration->resource = wl_resource_create(client, &zxdg_toplevel_decoration_v1_interface, wl_resource_get_version(resource), id); 77 | if (!decoration->resource) 78 | goto error1; 79 | decoration->toplevel_destroy_listener.notify = &handle_toplevel_destroy; 80 | wl_resource_add_destroy_listener(toplevel_resource, &decoration->toplevel_destroy_listener); 81 | wl_resource_set_implementation(decoration->resource, &decoration_impl, decoration, decoration_destroy); 82 | zxdg_toplevel_decoration_v1_send_configure(decoration->resource, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); 83 | return; 84 | 85 | error1: 86 | free(decoration); 87 | error0: 88 | wl_resource_post_no_memory(resource); 89 | } 90 | 91 | static const struct zxdg_decoration_manager_v1_interface decoration_manager_impl = { 92 | .destroy = destroy_resource, 93 | .get_toplevel_decoration = get_toplevel_decoration, 94 | }; 95 | 96 | static void 97 | bind_decoration_manager(struct wl_client *client, void *data, uint32_t version, uint32_t id) 98 | { 99 | struct wl_resource *resource; 100 | 101 | resource = wl_resource_create(client, &zxdg_decoration_manager_v1_interface, version, id); 102 | if (!resource) { 103 | wl_client_post_no_memory(client); 104 | return; 105 | } 106 | wl_resource_set_implementation(resource, &decoration_manager_impl, NULL, NULL); 107 | } 108 | 109 | struct wl_global * 110 | xdg_decoration_manager_create(struct wl_display *display) 111 | { 112 | return wl_global_create(display, &zxdg_decoration_manager_v1_interface, 1, NULL, &bind_decoration_manager); 113 | } 114 | -------------------------------------------------------------------------------- /libswc/xdg_decoration.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/xdg_decoration.h 2 | * 3 | * Copyright (c) 2020 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_XDG_DECORATION_H 25 | #define SWC_XDG_DECORATION_H 26 | 27 | struct wl_display; 28 | 29 | struct wl_global *xdg_decoration_manager_create(struct wl_display *display); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /libswc/xdg_shell.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/xdg_shell.h 2 | * 3 | * Copyright (c) 2018-2019 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_XDG_SHELL_H 25 | #define SWC_XDG_SHELL_H 26 | 27 | struct wl_display; 28 | 29 | struct wl_global *xdg_shell_create(struct wl_display *display); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /libswc/xserver.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/xserver.h 2 | * 3 | * Copyright (c) 2013, 2014 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_XSERVER_H 25 | #define SWC_XSERVER_H 26 | 27 | #include 28 | 29 | struct swc_xserver { 30 | struct wl_client *client; 31 | }; 32 | 33 | bool xserver_initialize(void); 34 | void xserver_finalize(void); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /libswc/xwm.h: -------------------------------------------------------------------------------- 1 | /* swc: libswc/xwm.h 2 | * 3 | * Copyright (c) 2013 Michael Forney 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | * SOFTWARE. 22 | */ 23 | 24 | #ifndef SWC_XWM_H 25 | #define SWC_XWM_H 26 | 27 | #include 28 | 29 | bool xwm_initialize(int fd); 30 | void xwm_finalize(void); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /protocol/local.mk: -------------------------------------------------------------------------------- 1 | # swc: protocol/local.mk 2 | 3 | dir := protocol 4 | wayland_protocols := $(call pkgconfig,wayland-protocols,variable=pkgdatadir,DATADIR) 5 | 6 | PROTOCOL_EXTENSIONS = \ 7 | $(dir)/server-decoration.xml\ 8 | $(dir)/swc.xml \ 9 | $(dir)/wayland-drm.xml \ 10 | $(wayland_protocols)/stable/xdg-shell/xdg-shell.xml \ 11 | $(wayland_protocols)/unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml \ 12 | $(wayland_protocols)/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml 13 | 14 | $(dir)_PACKAGES := wayland-server 15 | 16 | define protocol_rules 17 | 18 | $(dir)/$$(basename $$(notdir $(1)))-protocol.c: $(1) 19 | $$(Q_GEN)$$(WAYLAND_SCANNER) code <$$< >$$@ 20 | $(dir)/$$(basename $$(notdir $(1)))-server-protocol.h: $(1) 21 | $$(Q_GEN)$$(WAYLAND_SCANNER) server-header <$$< >$$@ 22 | 23 | CLEAN_FILES += $(foreach type,protocol.c server-protocol.h, \ 24 | $(dir)/$$(basename $$(notdir $(1)))-$(type)) 25 | 26 | endef 27 | 28 | $(eval $(foreach extension,$(PROTOCOL_EXTENSIONS),$(call protocol_rules,$(extension)))) 29 | 30 | install-$(dir): | $(DESTDIR)$(DATADIR)/swc 31 | install -m 644 protocol/swc.xml $(DESTDIR)$(DATADIR)/swc 32 | 33 | include common.mk 34 | 35 | -------------------------------------------------------------------------------- /protocol/server-decoration.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | . 18 | ]]> 19 | 20 | 21 | This interface allows to coordinate whether the server should create 22 | a server-side window decoration around a wl_surface representing a 23 | shell surface (wl_shell_surface or similar). By announcing support 24 | for this interface the server indicates that it supports server 25 | side decorations. 26 | 27 | Use in conjunction with zxdg_decoration_manager_v1 is undefined. 28 | 29 | 30 | 31 | When a client creates a server-side decoration object it indicates 32 | that it supports the protocol. The client is supposed to tell the 33 | server whether it wants server-side decorations or will provide 34 | client-side decorations. 35 | 36 | If the client does not create a server-side decoration object for 37 | a surface the server interprets this as lack of support for this 38 | protocol and considers it as client-side decorated. Nevertheless a 39 | client-side decorated surface should use this protocol to indicate 40 | to the server that it does not want a server-side deco. 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | This event is emitted directly after binding the interface. It contains 54 | the default mode for the decoration. When a new server decoration object 55 | is created this new object will be in the default mode until the first 56 | request_mode is requested. 57 | 58 | The server may change the default mode at any time. 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | This event is emitted directly after the decoration is created and 80 | represents the base decoration policy by the server. E.g. a server 81 | which wants all surfaces to be client-side decorated will send Client, 82 | a server which wants server-side decoration will send Server. 83 | 84 | The client can request a different mode through the decoration request. 85 | The server will acknowledge this by another event with the same mode. So 86 | even if a server prefers server-side decoration it's possible to force a 87 | client-side decoration. 88 | 89 | The server may emit this event at any time. In this case the client can 90 | again request a different mode. It's the responsibility of the server to 91 | prevent a feedback loop. 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /protocol/swc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Copyright (c) 2013, 2014 Michael Forney 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | 24 | 25 | 26 | 27 | A screen represents an area in which windows may be placed. It 28 | corresponds to one or monitors displaying the same content (in 29 | mirror mode). 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /swc.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@PREFIX@ 2 | exec_prefix=${prefix} 3 | libdir=@LIBDIR@ 4 | includedir=@INCLUDEDIR@ 5 | datadir=@DATADIR@/swc 6 | 7 | Name: swc 8 | Description: A library for making a simple Wayland compositor 9 | Version: @VERSION@ 10 | Cflags: -I${includedir} 11 | Libs: -L${libdir} -lswc 12 | 13 | Requires: @REQUIRES@ 14 | Requires.private: @REQUIRES_PRIVATE@ 15 | --------------------------------------------------------------------------------