├── .gitignore ├── LICENSE.md ├── Makefile ├── README.md ├── flake.lock ├── flake.nix └── src └── activate_linux.c /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright © `<2022>` `` 5 | 6 | Permission is hereby granted, free of charge, to any person 7 | obtaining a copy of this software and associated documentation 8 | files (the “Software”), to deal in the Software without 9 | restriction, including without limitation the rights to use, 10 | copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the 12 | Software is furnished to do so, subject to the following 13 | conditions: 14 | 15 | The above copyright notice and this permission notice shall be 16 | included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | RM = rm 3 | BINARY = activate-linux 4 | CFLAGS = $(shell pkg-config --cflags --libs gtk+-3.0 gtk-layer-shell-0) 5 | 6 | activate-linux: 7 | mkdir -p bin 8 | $(CC) src/activate_linux.c -o bin/$(BINARY) $(CFLAGS) 9 | 10 | .PHONY: clean 11 | clean: 12 | $(RM) -rf bin/ 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # activate-linux for Wayland 2 | 3 | The "Activate Windows" watermark ported to Linux with Gtk Layer Shell 4 | 5 | # Linux 6 | 7 | ## Dependencies 8 | 9 | This project depends on: 10 | 11 | - `gtk-3.0` (on some distros also `libgtk-3-dev`) 12 | - `gtk-layer-shell` and any [supported wayland compositor](https://github.com/wmww/gtk-layer-shell#supported-desktops) 13 | 14 | ## Building 15 | 16 | ``` 17 | make 18 | ``` 19 | 20 | ## Installing 21 | 22 | ### Arch Linux 23 | 24 | This project is in the AUR under [activate-linux-wayland-git](https://aur.archlinux.org/packages/activate-linux-wayland-git) 25 | 26 | Install it using your favorite AUR helper. 27 | 28 | ### NixOS 29 | 30 | #### NixOS installation with Flakes 31 | 32 | Just import flake and use `defaultPackage`. 33 | 34 | ```nix 35 | { 36 | ........ 37 | inputs.activate-linux = { 38 | url = "github:Kljunas2/activate-linux"; 39 | inputs.nixpkgs.follows = "nixpkgs"; # not mandatory but recommended 40 | }; 41 | ........ 42 | 43 | outputs = { self, nixpkgs, activate-linux }: { 44 | ........ 45 | modules = [ 46 | ({ self, ... }: { 47 | environment.systemPackages = with pkgs; [ 48 | ........ 49 | activate-linux.defaultPackage.xf86_64-linux 50 | ........ 51 | ]; 52 | }) 53 | ]; 54 | }; 55 | }; 56 | } 57 | ``` 58 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "nixpkgs": { 4 | "locked": { 5 | "lastModified": 1652875358, 6 | "narHash": "sha256-mIUPX/wMS6ASa1AshLPOvKj8HvjwK4rnlLiaJBUOhRc=", 7 | "owner": "NixOS", 8 | "repo": "nixpkgs", 9 | "rev": "51c998bdd9f0d6e809cf31acb95cccb627075004", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "NixOS", 14 | "repo": "nixpkgs", 15 | "type": "github" 16 | } 17 | }, 18 | "root": { 19 | "inputs": { 20 | "nixpkgs": "nixpkgs", 21 | "utils": "utils" 22 | } 23 | }, 24 | "utils": { 25 | "locked": { 26 | "lastModified": 1652776076, 27 | "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", 28 | "owner": "numtide", 29 | "repo": "flake-utils", 30 | "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", 31 | "type": "github" 32 | }, 33 | "original": { 34 | "owner": "numtide", 35 | "repo": "flake-utils", 36 | "type": "github" 37 | } 38 | } 39 | }, 40 | "root": "root", 41 | "version": 7 42 | } 43 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "Activate Linux watermark for wayland"; 3 | 4 | inputs.utils.url = "github:numtide/flake-utils"; 5 | inputs.nixpkgs.url = "github:NixOS/nixpkgs"; 6 | 7 | outputs = { self, nixpkgs, utils }: 8 | utils.lib.eachSystem [ "x86_64-linux" "aarch64-linux" ] (system: 9 | let pkgs = nixpkgs.legacyPackages.${system}; 10 | in { 11 | packages.activate-linux = pkgs.stdenv.mkDerivation { 12 | pname = "activate-linux"; 13 | version = "0.0.1"; 14 | src = ./.; 15 | nativeBuildInputs = with pkgs; [ pkg-config ]; 16 | buildInputs = with pkgs; [ gtk3 gtk-layer-shell ]; 17 | installPhase = '' 18 | mkdir -p $out/bin 19 | cp bin/activate-linux $out/bin/activate-linux 20 | ''; 21 | }; 22 | 23 | defaultPackage = self.packages.${system}.activate-linux; 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /src/activate_linux.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | struct config { 6 | char *title; 7 | char *subtitle; 8 | }; 9 | 10 | void draw_window(GdkMonitor *monitor, char *text, GtkApplication *app) 11 | { 12 | GtkWindow *gtk_window = GTK_WINDOW(gtk_application_window_new(app)); 13 | 14 | gtk_layer_init_for_window(gtk_window); 15 | 16 | gtk_layer_set_layer(gtk_window, GTK_LAYER_SHELL_LAYER_OVERLAY); 17 | 18 | // gtk layer shell options 19 | gtk_layer_set_margin(gtk_window, GTK_LAYER_SHELL_EDGE_RIGHT, 40); 20 | gtk_layer_set_margin(gtk_window, GTK_LAYER_SHELL_EDGE_BOTTOM, 40); 21 | static const gboolean anchors[] = {FALSE, TRUE, FALSE, TRUE}; 22 | for (int i = 0; i < GTK_LAYER_SHELL_EDGE_ENTRY_NUMBER; i++) { 23 | gtk_layer_set_anchor(gtk_window, i, anchors[i]); 24 | } 25 | 26 | gtk_layer_set_monitor(gtk_window, monitor); 27 | 28 | // set window background to transparent 29 | GtkCssProvider *css_provider = gtk_css_provider_new(); 30 | char *css = "window {background-color: transparent;}"; 31 | gtk_css_provider_load_from_data(css_provider, css, strlen(css), NULL); 32 | GtkStyleContext *context = 33 | gtk_widget_get_style_context(GTK_WIDGET(gtk_window)); 34 | gtk_style_context_add_provider(context, GTK_STYLE_PROVIDER(css_provider), 35 | GTK_STYLE_PROVIDER_PRIORITY_USER); 36 | 37 | // render label 38 | GtkWidget *label = gtk_label_new(""); 39 | gtk_label_set_markup(GTK_LABEL(label), text); 40 | gtk_container_add(GTK_CONTAINER(gtk_window), label); 41 | gtk_container_set_border_width(GTK_CONTAINER(gtk_window), 12); 42 | gtk_widget_show_all(GTK_WIDGET(gtk_window)); 43 | cairo_rectangle_int_t *rectangle = malloc(sizeof(cairo_rectangle_int_t)); 44 | memset(rectangle, 0, sizeof(cairo_rectangle_int_t)); 45 | cairo_region_t *region = cairo_region_create_rectangle(rectangle); 46 | gtk_widget_input_shape_combine_region(GTK_WIDGET(gtk_window), region); 47 | free(rectangle); 48 | cairo_region_destroy(region); 49 | } 50 | 51 | static void activate(GtkApplication *app, void *data) 52 | { 53 | struct config *conf = (struct config *)data; 54 | 55 | int title_len = strlen(conf->title); 56 | int subtitle_len = strlen(conf->subtitle); 57 | int len = 100 + title_len + subtitle_len; 58 | char text[len]; 59 | 60 | snprintf(text, len, 61 | "%s\n" 62 | "%s", 63 | conf->title, conf->subtitle); 64 | 65 | GdkDisplay *display = gdk_display_get_default(); 66 | for (int i = 0; i < gdk_display_get_n_monitors(display); i++) { 67 | GdkMonitor *monitor = gdk_display_get_monitor(display, i); 68 | draw_window(monitor, text, app); 69 | } 70 | } 71 | 72 | int main(int argc, char **argv) 73 | { 74 | if (!gtk_layer_is_supported()) { 75 | printf("Your compositor may not support gtk-layer-shell.\n"); 76 | } 77 | 78 | struct config conf; 79 | conf.title = argc > 1 ? argv[1] : "Activate Linux"; 80 | conf.subtitle = argc > 2 ? argv[2] : "Go to Settings to activate Linux."; 81 | GtkApplication *app = gtk_application_new(NULL, G_APPLICATION_DEFAULT_FLAGS); 82 | g_signal_connect(app, "activate", G_CALLBACK(activate), (void *)&conf); 83 | int status = g_application_run(G_APPLICATION(app), 0, NULL); 84 | g_object_unref(app); 85 | return status; 86 | } 87 | --------------------------------------------------------------------------------